diff --git a/Makefile b/Makefile index 51c2b18..7da7958 100644 --- a/Makefile +++ b/Makefile @@ -31,4 +31,10 @@ install-hooks: ## Point git at the tracked .githooks/ (auto-rebuilds dist on com git config core.hooksPath .githooks @echo "core.hooksPath -> .githooks" -.PHONY: help web-build web-dev web-check format format-check build techdata dev install-hooks +gc: ## Repack git history (committed dist/repo-intel deltas down to ~nothing) + @before=$$(git count-objects -vH | awk '/size-pack:/{print $$2 $$3}'); \ + git gc --quiet; \ + after=$$(git count-objects -vH | awk '/size-pack:/{print $$2 $$3}'); \ + echo "pack: $$before -> $$after" + +.PHONY: help web-build web-dev web-check format format-check build techdata dev install-hooks gc diff --git a/README.md b/README.md index d4b1ca1..bfca069 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,18 @@ Pushing a `vX.Y.Z` tag by hand still works as a fallback and runs the same `Release` workflow — but it skips the pre-tag build gate, so prefer _Cut release_. +**Syncing tags locally.** Because `Release` _force-moves_ the floating `vX` +major tag onto each new release commit, a plain `git fetch --tags` refuses to +update it (`! [rejected] vX -> vX (would clobber existing tag)`). Pull the +realigned tags with: + +```sh +git fetch --tags --force --prune origin +``` + +The `vX.Y.Z` tags are immutable and always fetch cleanly; only the floating +`vX` tag needs `--force`. + ### Detection data (`techdata.json`) Language detection (extension/filename → language, colors, vendored-path noise diff --git a/dist/repo-intel b/dist/repo-intel index 017aa30..0193cce 100755 --- a/dist/repo-intel +++ b/dist/repo-intel @@ -83,7 +83,7 @@ from collections import defaultdict from datetime import datetime, timedelta, timezone from pathlib import Path -TEMPLATE = '\n\n \n \n \n Repo Intel\n \n \n \n \n \n \n
\n \n\n' +TEMPLATE = '\n\n \n \n \n \n \n Repo Intel\n \n \n \n \n \n \n
\n \n\n' PLACEHOLDER = "/*__DATA_INJECTION__*/" NOREPLY_RE = re.compile(r"(?:\d+\+)?(.+)@users\.noreply\.github\.com") ORIGIN_RE = re.compile( @@ -325,7 +325,7 @@ def iso_week_label(dt): # build.py inlines the JSON here; when unbuilt we read the sibling file. Used # only on the local + bare-clone paths — the GraphQL remote path lacks per-file # data, so these maps go unused there. -TECHDATA = '{\n "_source": {\n "languages": "https://raw.githubusercontent.com/github-linguist/linguist/master/lib/linguist/languages.yml",\n "vendor": "https://raw.githubusercontent.com/github-linguist/linguist/master/lib/linguist/vendor.yml"\n },\n "fw_deps": {\n "Go": {\n "github.com/gin-gonic/gin": "Gin",\n "github.com/go-chi/chi": "chi",\n "github.com/gofiber/fiber": "Fiber",\n "github.com/gorilla/mux": "Gorilla",\n "github.com/labstack/echo": "Echo",\n "github.com/spf13/cobra": "Cobra",\n "google.golang.org/grpc": "gRPC",\n "gorm.io/gorm": "GORM"\n },\n "PHP": {\n "cakephp/cakephp": "CakePHP",\n "laravel/framework": "Laravel",\n "slim/slim": "Slim",\n "symfony/framework-bundle": "Symfony",\n "symfony/symfony": "Symfony",\n "yiisoft/yii2": "Yii"\n },\n "Python": {\n "aiohttp": "aiohttp",\n "celery": "Celery",\n "click": "Click",\n "django": "Django",\n "djangorestframework": "Django REST",\n "fastapi": "FastAPI",\n "flask": "Flask",\n "httpx": "HTTPX",\n "keras": "Keras",\n "matplotlib": "Matplotlib",\n "numpy": "NumPy",\n "pandas": "pandas",\n "pydantic": "Pydantic",\n "pyramid": "Pyramid",\n "pytest": "pytest",\n "requests": "Requests",\n "sanic": "Sanic",\n "scikit-learn": "scikit-learn",\n "scipy": "SciPy",\n "scrapy": "Scrapy",\n "sqlalchemy": "SQLAlchemy",\n "starlette": "Starlette",\n "tensorflow": "TensorFlow",\n "torch": "PyTorch",\n "tornado": "Tornado",\n "transformers": "Transformers",\n "typer": "Typer"\n },\n "Ruby": {\n "devise": "Devise",\n "hanami": "Hanami",\n "puma": "Puma",\n "rails": "Rails",\n "rspec": "RSpec",\n "sidekiq": "Sidekiq",\n "sinatra": "Sinatra"\n },\n "Rust": {\n "actix-web": "Actix Web",\n "axum": "Axum",\n "bevy": "Bevy",\n "clap": "clap",\n "diesel": "Diesel",\n "rocket": "Rocket",\n "serde": "Serde",\n "tauri": "Tauri",\n "tokio": "Tokio",\n "tonic": "Tonic",\n "warp": "warp"\n },\n "npm": {\n "@angular/core": "Angular",\n "@apollo/client": "Apollo",\n "@babel/core": "Babel",\n "@biomejs/biome": "Biome",\n "@chakra-ui/react": "Chakra UI",\n "@hapi/hapi": "hapi",\n "@ionic/core": "Ionic",\n "@mui/material": "MUI",\n "@nestjs/core": "NestJS",\n "@nx/workspace": "Nx",\n "@playwright/test": "Playwright",\n "@prisma/client": "Prisma",\n "@reduxjs/toolkit": "Redux",\n "@remix-run/react": "Remix",\n "@storybook/angular": "Storybook",\n "@storybook/html": "Storybook",\n "@storybook/preact": "Storybook",\n "@storybook/react": "Storybook",\n "@storybook/svelte": "Storybook",\n "@storybook/vue3": "Storybook",\n "@storybook/web-components": "Storybook",\n "@sveltejs/kit": "SvelteKit",\n "@swc/core": "SWC",\n "@testing-library/dom": "Testing Library",\n "@testing-library/react": "Testing Library",\n "@testing-library/vue": "Testing Library",\n "@trpc/client": "tRPC",\n "@trpc/server": "tRPC",\n "astro": "Astro",\n "bootstrap": "Bootstrap",\n "chart.js": "Chart.js",\n "cypress": "Cypress",\n "d3": "D3",\n "drizzle-orm": "Drizzle",\n "electron": "Electron",\n "esbuild": "esbuild",\n "eslint": "ESLint",\n "expo": "Expo",\n "express": "Express",\n "fastify": "Fastify",\n "gatsby": "Gatsby",\n "graphql": "GraphQL",\n "jest": "Jest",\n "koa": "Koa",\n "mocha": "Mocha",\n "mongoose": "Mongoose",\n "next": "Next.js",\n "nuxt": "Nuxt",\n "nx": "Nx",\n "parcel": "Parcel",\n "playwright": "Playwright",\n "preact": "Preact",\n "prettier": "Prettier",\n "prisma": "Prisma",\n "puppeteer": "Puppeteer",\n "react": "React",\n "react-dom": "React",\n "react-native": "React Native",\n "redux": "Redux",\n "rollup": "Rollup",\n "sequelize": "Sequelize",\n "solid-js": "SolidJS",\n "storybook": "Storybook",\n "styled-components": "styled-components",\n "svelte": "Svelte",\n "tailwindcss": "Tailwind CSS",\n "testcafe": "TestCafe",\n "three": "three.js",\n "turbo": "Turborepo",\n "typeorm": "TypeORM",\n "vite": "Vite",\n "vitest": "Vitest",\n "vue": "Vue",\n "webpack": "webpack",\n "zustand": "Zustand"\n }\n },\n "fw_sentinels_js": [\n [\n "next.config.js",\n "Next.js"\n ],\n [\n "next.config.ts",\n "Next.js"\n ],\n [\n "next.config.mjs",\n "Next.js"\n ],\n [\n "nuxt.config.js",\n "Nuxt"\n ],\n [\n "nuxt.config.ts",\n "Nuxt"\n ],\n [\n "svelte.config.js",\n "Svelte"\n ],\n [\n "astro.config.mjs",\n "Astro"\n ],\n [\n "vue.config.js",\n "Vue"\n ],\n [\n "gatsby-config.js",\n "Gatsby"\n ],\n [\n "angular.json",\n "Angular"\n ]\n ],\n "fw_sentinels_other": [\n [\n "manage.py",\n "Django",\n "Python"\n ],\n [\n "artisan",\n "Laravel",\n "PHP"\n ],\n [\n "config/application.rb",\n "Rails",\n "Ruby"\n ],\n [\n "Dockerfile",\n "Docker",\n "Tools"\n ],\n [\n "docker-compose.yml",\n "Docker Compose",\n "Tools"\n ],\n [\n "docker-compose.yaml",\n "Docker Compose",\n "Tools"\n ],\n [\n "compose.yml",\n "Docker Compose",\n "Tools"\n ],\n [\n "compose.yaml",\n "Docker Compose",\n "Tools"\n ],\n [\n "Makefile",\n "Make",\n "Tools"\n ],\n [\n "GNUmakefile",\n "Make",\n "Tools"\n ],\n [\n "pnpm-lock.yaml",\n "pnpm",\n "Tools"\n ],\n [\n "yarn.lock",\n "Yarn",\n "Tools"\n ],\n [\n "bun.lockb",\n "Bun",\n "Tools"\n ],\n [\n "bun.lock",\n "Bun",\n "Tools"\n ],\n [\n ".gitlab-ci.yml",\n "GitLab CI",\n "Tools"\n ],\n [\n "vercel.json",\n "Vercel",\n "Tools"\n ],\n [\n "netlify.toml",\n "Netlify",\n "Tools"\n ],\n [\n ".github/workflows/",\n "GitHub Actions",\n "Tools"\n ]\n ],\n "lang": {\n "color": {\n "1C Enterprise": "#814CCC",\n "2-Dimensional Array": "#38761D",\n "4D": "#004289",\n "ABAP": "#E8274B",\n "ABAP CDS": "#555e25",\n "AGS Script": "#B9D9FF",\n "AIDL": "#34EB6B",\n "AL": "#3AA2B5",\n "ALGOL": "#D1E0DB",\n "AMPL": "#E6EFBB",\n "ANTLR": "#9DC3FF",\n "API Blueprint": "#2ACCA8",\n "APL": "#5A8164",\n "ASP.NET": "#9400ff",\n "ATS": "#1ac620",\n "ActionScript": "#882B0F",\n "Ada": "#02f88c",\n "Adblock Filter List": "#800000",\n "Adobe Font Metrics": "#fa0f00",\n "Agda": "#315665",\n "Aiken": "#640ff8",\n "Alloy": "#64C800",\n "Alpine Abuild": "#0D597F",\n "Altium Designer": "#A89663",\n "AngelScript": "#C7D7DC",\n "Answer Set Programming": "#A9CC29",\n "Ant Build System": "#A9157E",\n "Antlers": "#ff269e",\n "ApacheConf": "#d12127",\n "Apex": "#1797c0",\n "Apollo Guidance Computer": "#0B3D91",\n "AppleScript": "#101F1F",\n "Arc": "#aa2afe",\n "AsciiDoc": "#73a0c5",\n "AspectJ": "#a957b0",\n "Assembly": "#6E4C13",\n "Astro": "#ff5a03",\n "Asymptote": "#ff0000",\n "Augeas": "#9CC134",\n "AutoHotkey": "#6594b9",\n "AutoIt": "#1C3552",\n "Avro IDL": "#0040FF",\n "Awk": "#c30e9b",\n "B (Formal Method)": "#8aa8c5",\n "B4X": "#00e4ff",\n "BASIC": "#ff0000",\n "BQN": "#2b7067",\n "Ballerina": "#FF5000",\n "Batchfile": "#C1F12E",\n "Beef": "#a52f4e",\n "Berry": "#15A13C",\n "BibTeX": "#778899",\n "Bicep": "#519aba",\n "Bikeshed": "#5562ac",\n "Bison": "#6A463F",\n "BitBake": "#00bce4",\n "Blade": "#f7523f",\n "BlitzBasic": "#00FFAE",\n "BlitzMax": "#cd6400",\n "Bluespec": "#12223c",\n "Bluespec BH": "#12223c",\n "Boo": "#d4bec1",\n "Boogie": "#c80fa0",\n "Brainfuck": "#2F2530",\n "BrighterScript": "#66AABB",\n "Brightscript": "#662D91",\n "Browserslist": "#ffd539",\n "Bru": "#F4AA41",\n "BuildStream": "#006bff",\n "C": "#555555",\n "C#": "#178600",\n "C++": "#f34b7d",\n "C3": "#2563eb",\n "CAP CDS": "#0092d1",\n "CLIPS": "#00A300",\n "CMake": "#DA3434",\n "COLLADA": "#F1A42B",\n "CQL": "#006091",\n "CSON": "#244776",\n "CSS": "#663399",\n "CSV": "#237346",\n "CUE": "#5886E1",\n "CWeb": "#00007a",\n "Cabal Config": "#483465",\n "Caddyfile": "#22b638",\n "Cadence": "#00ef8b",\n "Cairo": "#ff4a48",\n "Cairo Zero": "#ff4a48",\n "CameLIGO": "#3be133",\n "Cangjie": "#00868B",\n "Cap\'n Proto": "#c42727",\n "Carbon": "#222222",\n "Ceylon": "#dfa535",\n "Chapel": "#8dc63f",\n "ChucK": "#3f8000",\n "Circom": "#707575",\n "Cirru": "#ccccff",\n "Clarion": "#db901e",\n "Clarity": "#5546ff",\n "Classic ASP": "#6a40fd",\n "Clean": "#3F85AF",\n "Click": "#E4E6F3",\n "Clojure": "#db5855",\n "Closure Templates": "#0d948f",\n "Cloud Firestore Security Rules": "#FFA000",\n "Clue": "#0009b5",\n "CodeQL": "#140f46",\n "CoffeeScript": "#244776",\n "ColdFusion": "#ed2cd6",\n "ColdFusion CFC": "#ed2cd6",\n "Common Lisp": "#3fb68b",\n "Common Workflow Language": "#B5314C",\n "Component Pascal": "#B0CE4E",\n "Cooklang": "#E15A29",\n "Crystal": "#000100",\n "Csound": "#1a1a1a",\n "Csound Document": "#1a1a1a",\n "Csound Score": "#1a1a1a",\n "Cuda": "#3A4E3A",\n "Curry": "#531242",\n "Cylc": "#00b3fd",\n "Cypher": "#34c0eb",\n "Cython": "#fedf5b",\n "D": "#ba595e",\n "D2": "#526ee8",\n "DM": "#447265",\n "Dafny": "#FFEC25",\n "Darcs Patch": "#8eff23",\n "Dart": "#00B4AB",\n "Daslang": "#d3d3d3",\n "DataWeave": "#003a52",\n "Debian Package Control File": "#D70751",\n "DenizenScript": "#FBEE96",\n "Dhall": "#dfafff",\n "DirectX 3D File": "#aace60",\n "Dockerfile": "#384d54",\n "Dogescript": "#cca760",\n "Dotenv": "#e5d559",\n "Dune": "#89421e",\n "Dylan": "#6c616e",\n "E": "#ccce35",\n "ECL": "#8a1267",\n "ECLiPSe": "#001d9d",\n "EJS": "#a91e50",\n "EQ": "#a78649",\n "Earthly": "#2af0ff",\n "Easybuild": "#069406",\n "Ecere Projects": "#913960",\n "Ecmarkup": "#eb8131",\n "Edge": "#0dffe0",\n "EdgeQL": "#31A7FF",\n "EditorConfig": "#fff1f2",\n "Eiffel": "#4d6977",\n "Elixir": "#6e4a7e",\n "Elm": "#60B5CC",\n "Elvish": "#55BB55",\n "Elvish Transcript": "#55BB55",\n "Emacs Lisp": "#c065db",\n "EmberScript": "#FFF4F3",\n "Erlang": "#B83998",\n "Euphoria": "#FF790B",\n "F#": "#b845fc",\n "F*": "#572e30",\n "FIGlet Font": "#FFDDBB",\n "FIRRTL": "#2f632f",\n "FLUX": "#88ccff",\n "Factor": "#636746",\n "Fancy": "#7b9db4",\n "Fantom": "#14253c",\n "Faust": "#c37240",\n "Fennel": "#fff3d7",\n "Filebench WML": "#F6B900",\n "FlatBuffers": "#ed284a",\n "Flix": "#d44a45",\n "Fluent": "#ffcc33",\n "Forth": "#341708",\n "Fortran": "#4d41b1",\n "Fortran Free Form": "#4d41b1",\n "FreeBASIC": "#141AC9",\n "FreeMarker": "#0050b2",\n "Frege": "#00cafe",\n "Futhark": "#5f021f",\n "G-code": "#D08CF2",\n "GAML": "#FFC766",\n "GAMS": "#f49a22",\n "GAP": "#0000cc",\n "GCC Machine Description": "#FFCFAB",\n "GDScript": "#355570",\n "GDShader": "#478CBF",\n "GEDCOM": "#003058",\n "GLSL": "#5686a5",\n "GSC": "#FF6800",\n "Game Maker Language": "#71b417",\n "Gemfile.lock": "#701516",\n "Gemini": "#ff6900",\n "Genero 4gl": "#63408e",\n "Genero per": "#d8df39",\n "Genie": "#fb855d",\n "Genshi": "#951531",\n "Gentoo Ebuild": "#9400ff",\n "Gentoo Eclass": "#9400ff",\n "Gerber Image": "#d20b00",\n "Gherkin": "#5B2063",\n "Git Attributes": "#F44D27",\n "Git Commit": "#F44D27",\n "Git Config": "#F44D27",\n "Git Revision List": "#F44D27",\n "Gleam": "#ffaff3",\n "Glimmer JS": "#F5835F",\n "Glimmer TS": "#3178c6",\n "Glyph": "#c1ac7f",\n "Gnuplot": "#f0a9f0",\n "Go": "#00ADD8",\n "Go Checksums": "#00ADD8",\n "Go Module": "#00ADD8",\n "Go Template": "#00ADD8",\n "Go Workspace": "#00ADD8",\n "Godot Resource": "#355570",\n "Golo": "#88562A",\n "Gosu": "#82937f",\n "Grace": "#615f8b",\n "Gradle": "#02303a",\n "Gradle Kotlin DSL": "#02303a",\n "Grammatical Framework": "#ff0000",\n "GraphQL": "#e10098",\n "Graphviz (DOT)": "#2596be",\n "Groovy": "#4298b8",\n "Groovy Server Pages": "#4298b8",\n "HAProxy": "#106da9",\n "HCL": "#844FBA",\n "HIP": "#4F3A4F",\n "HLSL": "#aace60",\n "HOCON": "#9ff8ee",\n "HTML": "#e34c26",\n "HTML+ECR": "#2e1052",\n "HTML+EEX": "#6e4a7e",\n "HTML+ERB": "#701516",\n "HTML+PHP": "#4f5d95",\n "HTML+Razor": "#512be4",\n "HTTP": "#005C9C",\n "HXML": "#f68712",\n "Hack": "#878787",\n "Haml": "#ece2a9",\n "Handlebars": "#f7931e",\n "Harbour": "#0e60e3",\n "Hare": "#9d7424",\n "Haskell": "#5e5086",\n "Haxe": "#df7900",\n "HiveQL": "#dce200",\n "HolyC": "#ffefaf",\n "Hosts File": "#308888",\n "Hurl": "#FF0288",\n "Hy": "#7790B2",\n "IDL": "#a3522f",\n "IGOR Pro": "#0000cc",\n "IL Assembly": "#512BD4",\n "INI": "#d1dbe0",\n "ISPC": "#2D68B1",\n "Idris": "#b30000",\n "Ignore List": "#000000",\n "ImageJ Macro": "#99AAFF",\n "Imba": "#16cec6",\n "Inno Setup": "#264b99",\n "Io": "#a9188d",\n "Ioke": "#078193",\n "Isabelle": "#FEFE00",\n "Isabelle ROOT": "#FEFE00",\n "J": "#9EEDFF",\n "JAR Manifest": "#b07219",\n "JCL": "#d90e09",\n "JFlex": "#DBCA00",\n "JSON": "#292929",\n "JSON with Comments": "#292929",\n "JSON5": "#267CB9",\n "JSONLD": "#0c479c",\n "JSONiq": "#40d47e",\n "Jac": "#FC792D",\n "Jai": "#ab8b4b",\n "Janet": "#0886a5",\n "Jasmin": "#d03600",\n "Java": "#b07219",\n "Java Properties": "#2A6277",\n "Java Server Pages": "#2A6277",\n "Java Template Engine": "#2A6277",\n "JavaScript": "#f1e05a",\n "JavaScript+ERB": "#f1e05a",\n "Jest Snapshot": "#15c213",\n "JetBrains MPS": "#21D789",\n "Jinja": "#a52a22",\n "Jison": "#56b3cb",\n "Jison Lex": "#56b3cb",\n "Jolie": "#843179",\n "Jsonnet": "#0064bd",\n "Julia": "#a270ba",\n "Julia REPL": "#a270ba",\n "Jupyter Notebook": "#DA5B0B",\n "Just": "#384d54",\n "KCL": "#7ABABF",\n "KDL": "#ffb3b3",\n "KFramework": "#4195c5",\n "KRL": "#28430A",\n "Kaitai Struct": "#773b37",\n "KakouneScript": "#6f8042",\n "KerboScript": "#41adf0",\n "KiCad Layout": "#2f4aab",\n "KiCad Legacy Layout": "#2f4aab",\n "KiCad Schematic": "#2f4aab",\n "KoLmafia ASH": "#B9D9B9",\n "Koka": "#215166",\n "Kotlin": "#A97BFF",\n "LFE": "#4C3023",\n "LLVM": "#185619",\n "LOLCODE": "#cc9900",\n "LSL": "#3d9970",\n "LabVIEW": "#fede06",\n "Lambdapi": "#8027a3",\n "Langium": "#2c8c87",\n "Lark": "#2980B9",\n "Lasso": "#999999",\n "Latte": "#f2a542",\n "Leo": "#C4FFC2",\n "Less": "#1d365d",\n "Lex": "#DBCA00",\n "LigoLANG": "#0e74ff",\n "LilyPond": "#9ccc7c",\n "Liquid": "#67b8de",\n "Liquidsoap": "#990066",\n "Literate Agda": "#315665",\n "Literate CoffeeScript": "#244776",\n "Literate Haskell": "#5e5086",\n "LiveCode Script": "#0c5ba5",\n "LiveScript": "#499886",\n "Logtalk": "#295b9a",\n "LookML": "#652B81",\n "Lua": "#000080",\n "Luau": "#00A2FF",\n "M3U": "#179C7D",\n "MATLAB": "#e16737",\n "MAXScript": "#00a6a6",\n "MDX": "#fcb32c",\n "MLIR": "#5EC8DB",\n "MQL4": "#62A8D6",\n "MQL5": "#4A76B8",\n "MTML": "#b7e1f4",\n "Macaulay2": "#d8ffff",\n "Makefile": "#427819",\n "Mako": "#7e858d",\n "Markdown": "#083fa1",\n "Marko": "#42bff2",\n "Mask": "#f97732",\n "Mathematical Programming System": "#0530ad",\n "Max": "#c4a79c",\n "MeTTa": "#6a5acd",\n "Mercury": "#ff2b2b",\n "Mermaid": "#ff3670",\n "Meson": "#007800",\n "Metal": "#8f14e9",\n "MiniYAML": "#ff1111",\n "MiniZinc": "#06a9e6",\n "Mint": "#02b046",\n "Mirah": "#c7a938",\n "Modelica": "#de1d31",\n "Modula-2": "#10253f",\n "Modula-3": "#223388",\n "Mojo": "#ff4c1f",\n "Monkey C": "#8D6747",\n "MoonBit": "#b92381",\n "MoonScript": "#ff4585",\n "Motoko": "#fbb03b",\n "Motorola 68K Assembly": "#005daa",\n "Move": "#4a137a",\n "Mustache": "#724b3b",\n "NCL": "#28431f",\n "NMODL": "#00356B",\n "NPM Config": "#cb3837",\n "NWScript": "#111522",\n "Nasal": "#1d2c4e",\n "Nearley": "#990000",\n "Nemerle": "#3d3c6e",\n "NetLinx": "#0aa0ff",\n "NetLinx+ERB": "#747faa",\n "NetLogo": "#ff6375",\n "NewLisp": "#87AED7",\n "Nextflow": "#3ac486",\n "Nginx": "#009639",\n "Nickel": "#E0C3FC",\n "Nim": "#ffc200",\n "Nit": "#009917",\n "Nix": "#7e7eff",\n "Noir": "#2f1f49",\n "Nu": "#c9df40",\n "NumPy": "#9C8AF9",\n "Nunjucks": "#3d8137",\n "Nushell": "#4E9906",\n "OASv2-json": "#85ea2d",\n "OASv2-yaml": "#85ea2d",\n "OASv3-json": "#85ea2d",\n "OASv3-yaml": "#85ea2d",\n "OCaml": "#ef7a08",\n "OMNeT++ MSG": "#a0e0a0",\n "OMNeT++ NED": "#08607c",\n "ObjectScript": "#424893",\n "Objective-C": "#438eff",\n "Objective-C++": "#6866fb",\n "Objective-J": "#ff0c5a",\n "Odin": "#60AFFE",\n "Omgrofl": "#cabbff",\n "Opal": "#f7ede0",\n "Open Policy Agent": "#7d9199",\n "OpenAPI Specification v2": "#85ea2d",\n "OpenAPI Specification v3": "#85ea2d",\n "OpenCL": "#ed2e2d",\n "OpenEdge ABL": "#5ce600",\n "OpenQASM": "#AA70FF",\n "OpenSCAD": "#e5cd45",\n "Option List": "#476732",\n "Org": "#77aa99",\n "OverpassQL": "#cce2aa",\n "Oxygene": "#cdd0e3",\n "Oz": "#fab738",\n "P4": "#7055b5",\n "PDDL": "#0d00ff",\n "PEG.js": "#234d6b",\n "PHP": "#4F5D95",\n "PLSQL": "#dad8d8",\n "PLpgSQL": "#336790",\n "POV-Ray SDL": "#6bac65",\n "Pact": "#F7A8B8",\n "Pan": "#cc0000",\n "Papyrus": "#6600cc",\n "Parrot": "#f3ca0a",\n "Pascal": "#E3F171",\n "Pawn": "#dbb284",\n "Pep8": "#C76F5B",\n "Perl": "#0298c3",\n "PicoLisp": "#6067af",\n "PigLatin": "#fcd7de",\n "Pike": "#005390",\n "Pip Requirements": "#FFD343",\n "Pkl": "#6b9543",\n "PlantUML": "#fbbd16",\n "PogoScript": "#d80074",\n "Polar": "#ae81ff",\n "Portugol": "#f8bd00",\n "PostCSS": "#dc3a0c",\n "PostScript": "#da291c",\n "PowerBuilder": "#8f0f8d",\n "PowerShell": "#012456",\n "Praat": "#c8506d",\n "Prisma": "#0c344b",\n "Processing": "#0096D8",\n "Procfile": "#3B2F63",\n "Prolog": "#74283c",\n "Promela": "#de0000",\n "Propeller Spin": "#7fa2a7",\n "Pug": "#a86454",\n "Puppet": "#302B6D",\n "PureBasic": "#5a6986",\n "PureScript": "#1D222D",\n "Pyret": "#ee1e10",\n "Python": "#3572A5",\n "Python console": "#3572A5",\n "Python traceback": "#3572A5",\n "Q#": "#fed659",\n "QML": "#44a51c",\n "Qt Script": "#00b841",\n "Quake": "#882233",\n "QuakeC": "#975777",\n "QuickBASIC": "#008080",\n "Quint": "#9d6ce5",\n "R": "#198CE7",\n "RAML": "#77d9fb",\n "RAScript": "#2C97FA",\n "RBS": "#701516",\n "RDoc": "#701516",\n "REXX": "#d90e09",\n "RMarkdown": "#198ce7",\n "RON": "#a62c00",\n "ROS Interface": "#22314e",\n "RPGLE": "#2BDE21",\n "RUNOFF": "#665a4e",\n "Racket": "#3c5caa",\n "Ragel": "#9d5200",\n "Raku": "#0000fb",\n "Rascal": "#fffaa0",\n "ReScript": "#ed5051",\n "Reason": "#ff5847",\n "ReasonLIGO": "#ff5847",\n "Rebol": "#358a5b",\n "Record Jar": "#0673ba",\n "Red": "#f50000",\n "Regular Expression": "#009a00",\n "Ren\'Py": "#ff7f7f",\n "Rez": "#FFDAB3",\n "Ring": "#2D54CB",\n "Riot": "#A71E49",\n "RobotFramework": "#00c0b5",\n "Roc": "#7c38f5",\n "Rocq Prover": "#d0b68c",\n "Roff": "#ecdebe",\n "Roff Manpage": "#ecdebe",\n "Rouge": "#cc0088",\n "RouterOS Script": "#DE3941",\n "Ruby": "#701516",\n "Rust": "#dea584",\n "SAS": "#B34936",\n "SCSS": "#c6538c",\n "SPARQL": "#0C4597",\n "SQF": "#3F3F3F",\n "SQL": "#e38c00",\n "SQLPL": "#e38c00",\n "SRecode Template": "#348a34",\n "STL": "#373b5e",\n "SVG": "#ff9900",\n "Sail": "#259dd5",\n "SaltStack": "#646464",\n "Sass": "#a53b70",\n "Scala": "#c22d40",\n "Scaml": "#bd181a",\n "Scenic": "#fdc700",\n "Scheme": "#1e4aec",\n "Scilab": "#ca0f21",\n "Self": "#0579aa",\n "ShaderLab": "#222c37",\n "Shell": "#89e051",\n "ShellCheck Config": "#cecfcb",\n "Shen": "#120F14",\n "Simple File Verification": "#C9BFED",\n "Singularity": "#64E6AD",\n "Slang": "#1fbec9",\n "Slash": "#007eff",\n "Slice": "#003fa2",\n "Slim": "#2b2b2b",\n "Slint": "#2379F4",\n "SmPL": "#c94949",\n "Smalltalk": "#596706",\n "Smarty": "#f0c040",\n "Smithy": "#c44536",\n "Snakemake": "#419179",\n "Solidity": "#AA6746",\n "SourcePawn": "#f69e1d",\n "SpiceDB Schema": "#a5318a",\n "Squirrel": "#800000",\n "Stan": "#b2011d",\n "Standard ML": "#dc566d",\n "Starlark": "#76d275",\n "Stata": "#1a5f91",\n "StringTemplate": "#3fb34f",\n "Stylus": "#ff6347",\n "SubRip Text": "#9e0101",\n "SugarSS": "#2fcc9f",\n "SuperCollider": "#46390b",\n "SurrealQL": "#ff00a0",\n "Survex data": "#ffcc99",\n "Svelte": "#ff3e00",\n "Sway": "#00F58C",\n "Sweave": "#198ce7",\n "Swift": "#F05138",\n "SystemVerilog": "#DAE1C2",\n "TI Program": "#A0AA87",\n "TL-Verilog": "#C40023",\n "TLA": "#4b0079",\n "TMDL": "#f0c913",\n "TOML": "#9c4221",\n "TSQL": "#e38c00",\n "TSV": "#237346",\n "TSX": "#3178c6",\n "TXL": "#0178b8",\n "Tact": "#48b5ff",\n "Talon": "#333333",\n "Tcl": "#e4cc98",\n "TeX": "#3D6117",\n "Teal": "#00B1BC",\n "Terra": "#00004c",\n "Terraform Template": "#7b42bb",\n "TextGrid": "#c8506d",\n "TextMate Properties": "#df66e4",\n "Textile": "#ffe7ac",\n "Thrift": "#D12127",\n "Toit": "#c2c9fb",\n "Tools": "#a371f7",\n "Tor Config": "#59316b",\n "Tree-sitter Query": "#8ea64c",\n "Turing": "#cf142b",\n "Twig": "#c1d026",\n "TypeScript": "#3178c6",\n "TypeSpec": "#4A3665",\n "Typst": "#239dad",\n "Unified Parallel C": "#4e3617",\n "Unity3D Asset": "#222c37",\n "Uno": "#9933cc",\n "UnrealScript": "#a54c4d",\n "Untyped Plutus Core": "#36adbd",\n "UrWeb": "#ccccee",\n "V": "#4f87c4",\n "VBA": "#867db1",\n "VBScript": "#15dcdc",\n "VCL": "#148AA8",\n "VHDL": "#adb2cb",\n "Vala": "#a56de2",\n "Valve Data Format": "#f26025",\n "Velocity Template Language": "#507cff",\n "Vento": "#ff0080",\n "Verilog": "#b2b7f8",\n "Vim Help File": "#199f4b",\n "Vim Script": "#199f4b",\n "Vim Snippet": "#199f4b",\n "Visual Basic .NET": "#945db7",\n "Visual Basic 6.0": "#2c6353",\n "Volt": "#1F1F1F",\n "Vue": "#41b883",\n "Vyper": "#9F4CF2",\n "WDL": "#42f1f4",\n "WGSL": "#1a5e9a",\n "Web Ontology Language": "#5b70bd",\n "WebAssembly": "#04133b",\n "WebAssembly Interface Type": "#6250e7",\n "Whiley": "#d5c397",\n "Wikitext": "#fc5757",\n "Windows Registry Entries": "#52d5ff",\n "Witcher Script": "#ff0000",\n "Wolfram Language": "#dd1100",\n "Wollok": "#a23738",\n "World of Warcraft Addon Data": "#f7e43f",\n "Wren": "#383838",\n "X10": "#4B6BEF",\n "XC": "#99DA07",\n "XML": "#0060ac",\n "XML Property List": "#0060ac",\n "XQuery": "#5232e7",\n "XSLT": "#EB8CEB",\n "Xmake": "#22a079",\n "Xojo": "#81bd41",\n "Xonsh": "#285EEF",\n "Xtend": "#24255d",\n "YAML": "#cb171e",\n "YARA": "#220000",\n "YASnippet": "#32AB90",\n "Yacc": "#4B6C4B",\n "Yul": "#794932",\n "ZAP": "#0d665e",\n "ZIL": "#dc75e5",\n "ZenScript": "#00BCD1",\n "Zephir": "#118f9e",\n "Zig": "#ec915c",\n "Zimpl": "#d67711",\n "Zmodel": "#ff7100",\n "crontab": "#ead7ac",\n "eC": "#913960",\n "fish": "#4aae47",\n "hoon": "#00b171",\n "iCalendar": "#ec564c",\n "jq": "#c7254e",\n "kvlang": "#1da6e0",\n "mIRC Script": "#3d57c3",\n "mcfunction": "#E22837",\n "mdsvex": "#5f9ea0",\n "mupad": "#244963",\n "nanorc": "#2d004d",\n "nesC": "#94B0C7",\n "ooc": "#b0b77e",\n "q": "#0040cd",\n "reStructuredText": "#141414",\n "sed": "#64b970",\n "templ": "#66D0DD",\n "vCard": "#ee2647",\n "wisp": "#7582D1",\n "xBase": "#403a40"\n },\n "ext": {\n "1": "Roff",\n "1in": "Roff",\n "1m": "Roff",\n "1x": "Roff",\n "2": "Roff",\n "2da": "2-Dimensional Array",\n "3": "Roff",\n "3in": "Roff",\n "3m": "Roff",\n "3p": "Roff",\n "3pm": "Roff",\n "3qt": "Roff",\n "3x": "Roff",\n "4": "Roff",\n "4dform": "JSON",\n "4dm": "4D",\n "4dproject": "JSON",\n "4gl": "Genero 4gl",\n "4th": "Forth",\n "5": "Roff",\n "6": "Roff",\n "6pl": "Raku",\n "6pm": "Raku",\n "7": "Roff",\n "8": "Roff",\n "8xp": "TI Program",\n "8xp.txt": "TI Program",\n "9": "Roff",\n "_coffee": "CoffeeScript",\n "_js": "JavaScript",\n "_ls": "LiveScript",\n "a51": "Assembly",\n "abap": "ABAP",\n "action": "ROS Interface",\n "ada": "Ada",\n "adb": "Ada",\n "adml": "XML",\n "admx": "XML",\n "ado": "Stata",\n "adoc": "AsciiDoc",\n "adp": "Tcl",\n "ads": "Ada",\n "afm": "Adobe Font Metrics",\n "agc": "Assembly",\n "agda": "Agda",\n "ahk": "AutoHotkey",\n "ahkl": "AutoHotkey",\n "aidl": "AIDL",\n "aj": "AspectJ",\n "ak": "Aiken",\n "al": "AL",\n "alg": "ALGOL",\n "als": "Alloy",\n "ampl": "AMPL",\n "angelscript": "AngelScript",\n "anim": "Unity3D Asset",\n "ant": "XML",\n "antlers.html": "Antlers",\n "antlers.php": "Antlers",\n "antlers.xml": "Antlers",\n "apacheconf": "ApacheConf",\n "apex": "Apex",\n "apib": "API Blueprint",\n "apl": "APL",\n "app": "Erlang",\n "app.src": "Erlang",\n "applescript": "AppleScript",\n "arc": "Arc",\n "arr": "Pyret",\n "as": "ActionScript",\n "asax": "ASP.NET",\n "asc": "AGS Script",\n "asciidoc": "AsciiDoc",\n "ascx": "ASP.NET",\n "asd": "Common Lisp",\n "asddls": "ABAP CDS",\n "ash": "KoLmafia ASH",\n "ashx": "ASP.NET",\n "asm": "Assembly",\n "asmx": "ASP.NET",\n "asp": "Classic ASP",\n "aspx": "ASP.NET",\n "asset": "Unity3D Asset",\n "astro": "Astro",\n "asy": "Asymptote",\n "au3": "AutoIt",\n "aug": "Augeas",\n "auk": "Awk",\n "aux": "TeX",\n "avdl": "Avro IDL",\n "avsc": "JSON",\n "aw": "PHP",\n "awk": "Awk",\n "axaml": "XML",\n "axd": "ASP.NET",\n "axi": "NetLinx",\n "axi.erb": "NetLinx+ERB",\n "axml": "XML",\n "axs": "NetLinx",\n "axs.erb": "NetLinx+ERB",\n "b": "Brainfuck",\n "bal": "Ballerina",\n "bas": "B4X",\n "bash": "Shell",\n "bat": "Batchfile",\n "bats": "Shell",\n "bb": "BitBake",\n "bbappend": "BitBake",\n "bbclass": "BitBake",\n "bbx": "TeX",\n "bdy": "PLSQL",\n "be": "Berry",\n "bf": "Beef",\n "bi": "FreeBASIC",\n "bib": "TeX",\n "bibtex": "TeX",\n "bicep": "Bicep",\n "bicepparam": "Bicep",\n "bison": "Yacc",\n "blade": "Blade",\n "blade.php": "Blade",\n "bmx": "BlitzMax",\n "bones": "JavaScript",\n "boo": "Boo",\n "boot": "Clojure",\n "bpl": "Boogie",\n "bqn": "BQN",\n "brd": "KiCad Legacy Layout",\n "brs": "Brightscript",\n "bru": "Bru",\n "bs": "Bluespec",\n "bsl": "1C Enterprise",\n "bst": "BuildStream",\n "bsv": "Bluespec",\n "builder": "Ruby",\n "builds": "XML",\n "bzl": "Starlark",\n "c": "C",\n "c++": "C++",\n "c3": "C3",\n "cabal": "Cabal Config",\n "caddyfile": "Caddyfile",\n "cairo": "Cairo",\n "cake": "C#",\n "capnp": "Cap\'n Proto",\n "carbon": "Carbon",\n "cats": "C",\n "cbx": "TeX",\n "cc": "C++",\n "ccproj": "XML",\n "ccxml": "XML",\n "cdc": "Cadence",\n "cdf": "Wolfram Language",\n "cds": "CAP CDS",\n "ceylon": "Ceylon",\n "cfc": "ColdFusion",\n "cfg": "HAProxy",\n "cfm": "ColdFusion",\n "cfml": "ColdFusion",\n "cgi": "Perl",\n "cginc": "HLSL",\n "ch": "xBase",\n "chpl": "Chapel",\n "circom": "Circom",\n "cirru": "Cirru",\n "cj": "Cangjie",\n "cjs": "JavaScript",\n "cjsx": "CoffeeScript",\n "ck": "ChucK",\n "cl": "C",\n "cl2": "Clojure",\n "clar": "Clarity",\n "click": "Click",\n "clixml": "XML",\n "clj": "Clojure",\n "cljc": "Clojure",\n "cljs": "Clojure",\n "cljs.hl": "Clojure",\n "cljscm": "Clojure",\n "cljx": "Clojure",\n "clp": "CLIPS",\n "cls": "Apex",\n "clue": "Clue",\n "clw": "Clarion",\n "cmake": "CMake",\n "cmake.in": "CMake",\n "cmd": "Batchfile",\n "cmp": "Gerber Image",\n "cnc": "G-code",\n "cnf": "INI",\n "cocci": "SmPL",\n "code-snippets": "JSON",\n "code-workspace": "JSON",\n "coffee": "CoffeeScript",\n "coffee.md": "CoffeeScript",\n "command": "Shell",\n "containerfile": "Dockerfile",\n "cook": "Cooklang",\n "coq": "Rocq Prover",\n "cp": "Component Pascal",\n "cpp": "C++",\n "cppm": "C++",\n "cproject": "XML",\n "cps": "Component Pascal",\n "cql": "CQL",\n "cr": "Crystal",\n "cs": "C#",\n "cs.pp": "C#",\n "csc": "GSC",\n "cscfg": "XML",\n "csd": "Csound Document",\n "csdef": "XML",\n "cshtml": "HTML",\n "csl": "XML",\n "cson": "CSON",\n "csproj": "XML",\n "css": "CSS",\n "csv": "CSV",\n "csx": "C#",\n "ct": "XML",\n "ctl": "Visual Basic 6.0",\n "ctp": "PHP",\n "cts": "TypeScript",\n "cu": "Cuda",\n "cue": "CUE",\n "cuh": "Cuda",\n "curry": "Curry",\n "cwl": "Common Workflow Language",\n "cxx": "C++",\n "cylc": "INI",\n "cyp": "Cypher",\n "cypher": "Cypher",\n "d": "D",\n "d2": "D2",\n "dae": "COLLADA",\n "darcspatch": "Darcs Patch",\n "dart": "Dart",\n "das": "Daslang",\n "dats": "ATS",\n "db2": "SQLPL",\n "dcl": "Clean",\n "ddl": "PLSQL",\n "decls": "BlitzBasic",\n "depproj": "XML",\n "dfm": "Pascal",\n "dfy": "Dafny",\n "dhall": "Dhall",\n "di": "D",\n "dita": "XML",\n "ditamap": "XML",\n "ditaval": "XML",\n "djs": "Dogescript",\n "dll.config": "XML",\n "dlm": "IDL",\n "dm": "DM",\n "do": "Stata",\n "dockerfile": "Dockerfile",\n "dof": "INI",\n "doh": "Stata",\n "dot": "Graphviz (DOT)",\n "dotsettings": "XML",\n "dpatch": "Darcs Patch",\n "dpr": "Pascal",\n "druby": "Mirah",\n "dsc": "DenizenScript",\n "dsp": "Faust",\n "dsr": "Visual Basic 6.0",\n "dtx": "TeX",\n "duby": "Mirah",\n "dwl": "DataWeave",\n "dyalog": "APL",\n "dyl": "Dylan",\n "dylan": "Dylan",\n "e": "E",\n "eb": "Python",\n "ebuild": "Shell",\n "ec": "eC",\n "ecl": "ECL",\n "eclass": "Shell",\n "eclxml": "ECL",\n "ecr": "HTML",\n "ect": "EJS",\n "edge": "Edge",\n "edgeql": "EdgeQL",\n "editorconfig": "INI",\n "eh": "eC",\n "ejs": "EJS",\n "ejs.t": "EJS",\n "el": "Emacs Lisp",\n "eliom": "OCaml",\n "eliomi": "OCaml",\n "elm": "Elm",\n "elv": "Elvish",\n "em": "EmberScript",\n "emacs": "Emacs Lisp",\n "emacs.desktop": "Emacs Lisp",\n "emberscript": "EmberScript",\n "env": "Dotenv",\n "epj": "JavaScript",\n "eps": "PostScript",\n "epsi": "PostScript",\n "eq": "EQ",\n "erb": "HTML",\n "erb.deface": "HTML",\n "erl": "Erlang",\n "es": "Erlang",\n "es6": "JavaScript",\n "escript": "Erlang",\n "esdl": "EdgeQL",\n "ex": "Elixir",\n "exs": "Elixir",\n "eye": "Ruby",\n "f": "Fortran",\n "f03": "Fortran",\n "f08": "Fortran",\n "f77": "Fortran",\n "f90": "Fortran",\n "f95": "Fortran",\n "factor": "Factor",\n "fan": "Fantom",\n "fancypack": "Fancy",\n "fbs": "FlatBuffers",\n "fcgi": "Lua",\n "feature": "Gherkin",\n "filters": "XML",\n "fir": "FIRRTL",\n "fish": "Shell",\n "flex": "Lex",\n "flf": "FIGlet Font",\n "flix": "Flix",\n "flux": "FLUX",\n "fnc": "PLSQL",\n "fnl": "Fennel",\n "for": "Fortran",\n "forth": "Forth",\n "fp": "GLSL",\n "fpp": "Fortran",\n "fr": "Frege",\n "frag": "GLSL",\n "frg": "GLSL",\n "frm": "VBA",\n "frt": "Forth",\n "fs": "F#",\n "fsh": "GLSL",\n "fshader": "GLSL",\n "fsi": "F#",\n "fsproj": "XML",\n "fst": "F*",\n "fsti": "F*",\n "fsx": "F#",\n "fth": "Forth",\n "ftl": "Fluent",\n "ftlh": "FreeMarker",\n "fun": "Standard ML",\n "fut": "Futhark",\n "fx": "FLUX",\n "fxh": "HLSL",\n "fxml": "XML",\n "fy": "Fancy",\n "g": "G-code",\n "g4": "ANTLR",\n "gaml": "GAML",\n "gap": "GAP",\n "gawk": "Awk",\n "gbl": "Gerber Image",\n "gbo": "Gerber Image",\n "gbp": "Gerber Image",\n "gbr": "Gerber Image",\n "gbs": "Gerber Image",\n "gco": "G-code",\n "gcode": "G-code",\n "gd": "GDScript",\n "gdnlib": "Godot Resource",\n "gdns": "Godot Resource",\n "gdshader": "GDShader",\n "gdshaderinc": "GDShader",\n "ged": "GEDCOM",\n "gemspec": "Ruby",\n "geo": "GLSL",\n "geojson": "JSON",\n "geom": "GLSL",\n "gf": "Grammatical Framework",\n "gi": "GAP",\n "gitconfig": "INI",\n "gitignore": "Ignore List",\n "gjs": "JavaScript",\n "gko": "Gerber Image",\n "glade": "XML",\n "gleam": "Gleam",\n "glf": "Glyph",\n "glsl": "GLSL",\n "glslf": "GLSL",\n "glslv": "GLSL",\n "gltf": "JSON",\n "gmi": "Gemini",\n "gml": "Game Maker Language",\n "gms": "GAMS",\n "gmx": "XML",\n "gnu": "Gnuplot",\n "gnuplot": "Gnuplot",\n "go": "Go",\n "god": "Ruby",\n "gohtml": "Go Template",\n "golo": "Golo",\n "gotmpl": "Go Template",\n "gp": "Gnuplot",\n "gpb": "Gerber Image",\n "gpt": "Gerber Image",\n "gpx": "XML",\n "gql": "GraphQL",\n "grace": "Grace",\n "gradle": "Gradle",\n "gradle.kts": "Gradle",\n "graphql": "GraphQL",\n "graphqls": "GraphQL",\n "groovy": "Groovy",\n "grt": "Groovy",\n "grxml": "XML",\n "gs": "Genie",\n "gsc": "GSC",\n "gsh": "GSC",\n "gshader": "GLSL",\n "gsp": "Groovy",\n "gst": "Gosu",\n "gsx": "Gosu",\n "gtl": "Gerber Image",\n "gto": "Gerber Image",\n "gtp": "Gerber Image",\n "gtpl": "Groovy",\n "gts": "TypeScript",\n "gv": "Graphviz (DOT)",\n "gvy": "Groovy",\n "gyp": "Python",\n "gypi": "Python",\n "h": "C",\n "h++": "C++",\n "h.in": "C",\n "ha": "Hare",\n "hack": "Hack",\n "haml": "Haml",\n "haml.deface": "Haml",\n "handlebars": "Handlebars",\n "har": "JSON",\n "hats": "ATS",\n "hb": "Harbour",\n "hbs": "Handlebars",\n "hc": "HolyC",\n "hcl": "HCL",\n "heex": "HTML",\n "hh": "C++",\n "hhi": "Hack",\n "hic": "Clojure",\n "hip": "HIP",\n "hlsl": "HLSL",\n "hlsli": "HLSL",\n "hocon": "HOCON",\n "hoon": "hoon",\n "hpp": "C++",\n "hqf": "SQF",\n "hql": "HiveQL",\n "hrl": "Erlang",\n "hs": "Haskell",\n "hs-boot": "Haskell",\n "hsc": "Haskell",\n "hta": "HTML",\n "htm": "HTML",\n "html": "HTML",\n "html.eex": "HTML",\n "html.hl": "HTML",\n "html.tmpl": "Go Template",\n "http": "HTTP",\n "hurl": "Hurl",\n "hx": "Haxe",\n "hxml": "HXML",\n "hxsl": "Haxe",\n "hxx": "C++",\n "hy": "Hy",\n "hzp": "XML",\n "i": "Assembly",\n "i3": "Modula-3",\n "ical": "iCalendar",\n "ice": "Slice",\n "iced": "CoffeeScript",\n "icl": "Clean",\n "icls": "XML",\n "ics": "iCalendar",\n "idc": "C",\n "idr": "Idris",\n "ig": "Modula-3",\n "ihlp": "Stata",\n "ijm": "ImageJ Macro",\n "ijs": "J",\n "ik": "Ioke",\n "il": "IL Assembly",\n "ily": "LilyPond",\n "imba": "Imba",\n "iml": "XML",\n "inc": "Assembly",\n "ini": "INI",\n "inl": "C++",\n "ino": "C++",\n "ins": "TeX",\n "intr": "Dylan",\n "io": "Io",\n "iol": "Jolie",\n "ipf": "IGOR Pro",\n "ipp": "C++",\n "ipynb": "Jupyter Notebook",\n "isl": "Inno Setup",\n "ispc": "ISPC",\n "iss": "Inno Setup",\n "iuml": "PlantUML",\n "ivy": "XML",\n "ixx": "C++",\n "j": "Jasmin",\n "j2": "Jinja",\n "jac": "Jac",\n "jade": "Pug",\n "jai": "Jai",\n "jake": "JavaScript",\n "janet": "Janet",\n "jav": "Java",\n "java": "Java",\n "javascript": "JavaScript",\n "jbuilder": "Ruby",\n "jcl": "JCL",\n "jelly": "XML",\n "jflex": "Lex",\n "jinja": "Jinja",\n "jinja2": "Jinja",\n "jison": "Yacc",\n "jisonlex": "Lex",\n "jl": "Julia",\n "jq": "JSONiq",\n "js": "JavaScript",\n "js.erb": "JavaScript",\n "jsb": "JavaScript",\n "jscad": "JavaScript",\n "jsfl": "JavaScript",\n "jsh": "Java",\n "jslib": "JavaScript",\n "jsm": "JavaScript",\n "json": "JSON",\n "json-tmlanguage": "JSON",\n "json.example": "JSON",\n "json5": "JSON5",\n "jsonc": "JSON",\n "jsonl": "JSON",\n "jsonld": "JSONLD",\n "jsonnet": "Jsonnet",\n "jsp": "Java",\n "jspre": "JavaScript",\n "jsproj": "XML",\n "jss": "JavaScript",\n "jst": "EJS",\n "jsx": "JavaScript",\n "jte": "Java",\n "just": "Just",\n "k": "KCL",\n "kak": "KakouneScript",\n "kdl": "KDL",\n "kicad_mod": "KiCad Layout",\n "kicad_pcb": "KiCad Layout",\n "kicad_sch": "KiCad Schematic",\n "kicad_sym": "KiCad Schematic",\n "kicad_wks": "KiCad Layout",\n "kid": "Genshi",\n "kk": "Koka",\n "kml": "XML",\n "kojo": "Scala",\n "krl": "KRL",\n "ks": "KerboScript",\n "ksh": "Shell",\n "ksy": "Kaitai Struct",\n "kt": "Kotlin",\n "ktm": "Kotlin",\n "kts": "Kotlin",\n "kv": "kvlang",\n "l": "Common Lisp",\n "lagda": "Agda",\n "langium": "Langium",\n "lark": "Lark",\n "las": "Lasso",\n "lasso": "Lasso",\n "lasso8": "Lasso",\n "lasso9": "Lasso",\n "latte": "Latte",\n "launch": "XML",\n "lbx": "TeX",\n "leex": "HTML",\n "lektorproject": "INI",\n "leo": "Leo",\n "less": "Less",\n "lex": "Lex",\n "lfe": "LFE",\n "lgt": "Logtalk",\n "lhs": "Haskell",\n "libsonnet": "Jsonnet",\n "lid": "Dylan",\n "lidr": "Idris",\n "ligo": "LigoLANG",\n "linq": "C#",\n "liq": "Liquidsoap",\n "liquid": "Liquid",\n "lisp": "Common Lisp",\n "litcoffee": "CoffeeScript",\n "livecodescript": "LiveCode Script",\n "livemd": "Markdown",\n "lkml": "LookML",\n "ll": "LLVM",\n "lmi": "Python",\n "logtalk": "Logtalk",\n "lol": "LOLCODE",\n "lookml": "LookML",\n "lp": "Answer Set Programming",\n "lpr": "Pascal",\n "ls": "LiveScript",\n "lsl": "LSL",\n "lslp": "LSL",\n "lsp": "Common Lisp",\n "ltx": "TeX",\n "lua": "Lua",\n "luau": "Luau",\n "lvclass": "LabVIEW",\n "lvlib": "LabVIEW",\n "lvproj": "LabVIEW",\n "ly": "LilyPond",\n "m": "Objective-C",\n "m2": "Macaulay2",\n "m3": "Modula-3",\n "m3u": "M3U",\n "m3u8": "M3U",\n "ma": "Wolfram Language",\n "mak": "Makefile",\n "make": "Makefile",\n "makefile": "Makefile",\n "mako": "Mako",\n "man": "Roff",\n "mao": "Mako",\n "markdown": "Markdown",\n "marko": "Marko",\n "mask": "Mask",\n "mat": "Unity3D Asset",\n "mata": "Stata",\n "matah": "Stata",\n "mathematica": "Wolfram Language",\n "matlab": "MATLAB",\n "mawk": "Awk",\n "maxhelp": "Max",\n "maxpat": "Max",\n "maxproj": "Max",\n "mbt": "MoonBit",\n "mc": "Monkey C",\n "mcfunction": "mcfunction",\n "mch": "B (Formal Method)",\n "mcmeta": "JSON",\n "mcr": "MAXScript",\n "md": "Markdown",\n "mdoc": "Roff",\n "mdown": "Markdown",\n "mdpolicy": "XML",\n "mdwn": "Markdown",\n "mdx": "MDX",\n "me": "Roff",\n "mediawiki": "Wikitext",\n "mermaid": "Mermaid",\n "meta": "Unity3D Asset",\n "metal": "Metal",\n "metta": "MeTTa",\n "mg": "Modula-3",\n "mint": "Mint",\n "mir": "YAML",\n "mirah": "Mirah",\n "mjml": "XML",\n "mjs": "JavaScript",\n "mk": "Makefile",\n "mkd": "Markdown",\n "mkdn": "Markdown",\n "mkdown": "Markdown",\n "mkfile": "Makefile",\n "mkii": "TeX",\n "mkiv": "TeX",\n "mkvi": "TeX",\n "ml": "OCaml",\n "ml4": "OCaml",\n "mli": "OCaml",\n "mligo": "LigoLANG",\n "mlir": "MLIR",\n "mll": "OCaml",\n "mly": "OCaml",\n "mm": "Objective-C++",\n "mmd": "Mermaid",\n "mo": "Modelica",\n "mod": "Modula-2",\n "mojo": "Mojo",\n "moo": "Mercury",\n "moon": "MoonScript",\n "move": "Move",\n "mpl": "JetBrains MPS",\n "mps": "JetBrains MPS",\n "mq4": "MQL4",\n "mq5": "MQL5",\n "mqh": "MQL4",\n "mrc": "mIRC Script",\n "ms": "MAXScript",\n "msd": "JetBrains MPS",\n "msg": "OMNeT++ MSG",\n "mspec": "Ruby",\n "mt": "Wolfram Language",\n "mtml": "MTML",\n "mts": "TypeScript",\n "mu": "mupad",\n "mud": "ZIL",\n "mustache": "Mustache",\n "mxml": "XML",\n "mxt": "Max",\n "mysql": "SQL",\n "mzn": "MiniZinc",\n "n": "Nemerle",\n "nanorc": "INI",\n "nas": "Nasal",\n "nasm": "Assembly",\n "natvis": "XML",\n "nawk": "Awk",\n "nb": "Wolfram Language",\n "nbp": "Wolfram Language",\n "nc": "nesC",\n "ncl": "NCL",\n "ndproj": "XML",\n "ne": "Nearley",\n "nearley": "Nearley",\n "ned": "OMNeT++ NED",\n "nf": "Nextflow",\n "nginx": "Nginx",\n "nginxconf": "Nginx",\n "nim": "Nim",\n "nim.cfg": "Nim",\n "nimble": "Nim",\n "nimrod": "Nim",\n "nims": "Nim",\n "nit": "Nit",\n "nix": "Nix",\n "njk": "Nunjucks",\n "njs": "JavaScript",\n "nl": "NewLisp",\n "nlogo": "NetLogo",\n "nomad": "HCL",\n "nproj": "XML",\n "nqp": "Raku",\n "nr": "Noir",\n "nse": "Lua",\n "nss": "NWScript",\n "nu": "Nu",\n "numpy": "Python",\n "numpyw": "Python",\n "numsc": "Python",\n "nuspec": "XML",\n "nut": "Squirrel",\n "ny": "Common Lisp",\n "odd": "XML",\n "odin": "Odin",\n "ol": "Jolie",\n "omgrofl": "Omgrofl",\n "ooc": "ooc",\n "opal": "Opal",\n "opencl": "C",\n "orc": "Csound",\n "org": "Org",\n "os": "1C Enterprise",\n "osm": "XML",\n "outjob": "Altium Designer",\n "overpassql": "OverpassQL",\n "owl": "Web Ontology Language",\n "oxygene": "Oxygene",\n "oz": "Oz",\n "p": "OpenEdge ABL",\n "p4": "P4",\n "p6": "Raku",\n "p6l": "Raku",\n "p6m": "Raku",\n "p8": "Lua",\n "pac": "JavaScript",\n "pact": "Pact",\n "pan": "Pan",\n "parrot": "Parrot",\n "pas": "Pascal",\n "pascal": "Pascal",\n "pat": "Max",\n "pb": "PureBasic",\n "pbi": "PureBasic",\n "pbt": "PowerBuilder",\n "pcbdoc": "Altium Designer",\n "pck": "PLSQL",\n "pcss": "CSS",\n "pd_lua": "Lua",\n "pddl": "PDDL",\n "pde": "Processing",\n "peggy": "PEG.js",\n "pegjs": "PEG.js",\n "pep": "Pep8",\n "per": "Genero per",\n "perl": "Perl",\n "pfa": "PostScript",\n "pgsql": "PLpgSQL",\n "ph": "Perl",\n "php": "PHP",\n "php3": "PHP",\n "php4": "PHP",\n "php5": "PHP",\n "phps": "PHP",\n "phpt": "PHP",\n "phtml": "HTML",\n "pig": "PigLatin",\n "pike": "Pike",\n "pkb": "PLSQL",\n "pkgproj": "XML",\n "pkl": "Pkl",\n "pks": "PLSQL",\n "pl": "Perl",\n "pl6": "Raku",\n "plantuml": "PlantUML",\n "plb": "PLSQL",\n "plist": "XML",\n "plot": "Gnuplot",\n "pls": "PLSQL",\n "plsql": "PLSQL",\n "plt": "Gnuplot",\n "pluginspec": "Ruby",\n "plx": "Perl",\n "pm": "Perl",\n "pm6": "Raku",\n "pml": "Promela",\n "pmod": "Pike",\n "podsl": "Common Lisp",\n "podspec": "Ruby",\n "pogo": "PogoScript",\n "polar": "Polar",\n "por": "Portugol",\n "postcss": "CSS",\n "pov": "POV-Ray SDL",\n "pp": "Puppet",\n "pprx": "REXX",\n "praat": "Praat",\n "prawn": "Ruby",\n "prc": "PLSQL",\n "prefab": "Unity3D Asset",\n "prefs": "INI",\n "prg": "xBase",\n "prisma": "Prisma",\n "prjpcb": "Altium Designer",\n "pro": "Prolog",\n "proj": "XML",\n "prolog": "Prolog",\n "properties": "Java Properties",\n "props": "XML",\n "prw": "xBase",\n "ps": "PostScript",\n "ps1": "PowerShell",\n "ps1xml": "XML",\n "psc": "Papyrus",\n "psc1": "XML",\n "psd1": "PowerShell",\n "psgi": "Perl",\n "psm1": "PowerShell",\n "pt": "XML",\n "pubxml": "XML",\n "pug": "Pug",\n "puml": "PlantUML",\n "purs": "PureScript",\n "pwn": "Pawn",\n "pxd": "Cython",\n "pxi": "Cython",\n "py": "Python",\n "py3": "Python",\n "pyde": "Python",\n "pyi": "Python",\n "pyp": "Python",\n "pyt": "Python",\n "pytb": "Python",\n "pyw": "Python",\n "pyx": "Cython",\n "q": "HiveQL",\n "qasm": "OpenQASM",\n "qbs": "QML",\n "qc": "QuakeC",\n "qhelp": "XML",\n "ql": "CodeQL",\n "qll": "CodeQL",\n "qmd": "RMarkdown",\n "qml": "QML",\n "qnt": "Quint",\n "qs": "Q#",\n "r": "R",\n "r2": "Rebol",\n "r3": "Rebol",\n "rabl": "Ruby",\n "rake": "Ruby",\n "raku": "Raku",\n "rakumod": "Raku",\n "raml": "RAML",\n "rascript": "RAScript",\n "razor": "HTML",\n "rb": "Ruby",\n "rbi": "Ruby",\n "rbs": "Ruby",\n "rbuild": "Ruby",\n "rbw": "Ruby",\n "rbx": "Ruby",\n "rbxs": "Lua",\n "rchit": "GLSL",\n "rd": "R",\n "rdf": "XML",\n "rdoc": "RDoc",\n "re": "Reason",\n "reb": "Rebol",\n "rebol": "Rebol",\n "red": "Red",\n "reds": "Red",\n "reek": "YAML",\n "reg": "Windows Registry Entries",\n "regex": "Regular Expression",\n "regexp": "Regular Expression",\n "rego": "Open Policy Agent",\n "rei": "Reason",\n "religo": "LigoLANG",\n "res": "ReScript",\n "resi": "ReScript",\n "resource": "RobotFramework",\n "rest": "reStructuredText",\n "rest.txt": "reStructuredText",\n "resx": "XML",\n "rex": "REXX",\n "rexx": "REXX",\n "rg": "Rouge",\n "rhtml": "HTML",\n "ring": "Ring",\n "riot": "Riot",\n "rkt": "Racket",\n "rktd": "Racket",\n "rktl": "Racket",\n "rl": "Ragel",\n "rmd": "RMarkdown",\n "rmiss": "GLSL",\n "rnh": "RUNOFF",\n "rno": "RUNOFF",\n "rnw": "Sweave",\n "robot": "RobotFramework",\n "roc": "Roc",\n "rockspec": "Lua",\n "roff": "Roff",\n "ron": "RON",\n "ronn": "Markdown",\n "rpgle": "RPGLE",\n "rpy": "Ren\'Py",\n "rq": "SPARQL",\n "rs": "Rust",\n "rs.in": "Rust",\n "rsc": "Rascal",\n "rss": "XML",\n "rst": "reStructuredText",\n "rst.txt": "reStructuredText",\n "rsx": "R",\n "ru": "Ruby",\n "ruby": "Ruby",\n "rviz": "YAML",\n "s": "Assembly",\n "sail": "Sail",\n "sarif": "JSON",\n "sas": "SAS",\n "sass": "Sass",\n "sats": "ATS",\n "sbatch": "Shell",\n "sbt": "Scala",\n "sc": "SuperCollider",\n "scad": "OpenSCAD",\n "scala": "Scala",\n "scaml": "Scaml",\n "scd": "SuperCollider",\n "sce": "Scilab",\n "scenic": "Scenic",\n "sch": "Scheme",\n "schdoc": "Altium Designer",\n "sci": "Scilab",\n "scm": "Scheme",\n "sco": "Csound Score",\n "scpt": "AppleScript",\n "scrbl": "Racket",\n "scss": "SCSS",\n "scxml": "XML",\n "sdc": "Tcl",\n "sed": "sed",\n "self": "Self",\n "sexp": "Common Lisp",\n "sfproj": "XML",\n "sfv": "Simple File Verification",\n "sh": "Shell",\n "sh.in": "Shell",\n "shader": "ShaderLab",\n "shen": "Shen",\n "shproj": "XML",\n "sig": "Standard ML",\n "sj": "Objective-J",\n "sjs": "JavaScript",\n "sl": "Slash",\n "slang": "Slang",\n "sld": "Scheme",\n "slim": "Slim",\n "slint": "Slint",\n "slnx": "XML",\n "sls": "SaltStack",\n "slurm": "Shell",\n "sma": "Pawn",\n "smithy": "Smithy",\n "smk": "Python",\n "sml": "Standard ML",\n "snakefile": "Python",\n "snap": "Jest Snapshot",\n "snip": "Vim Snippet",\n "snippet": "Vim Snippet",\n "snippets": "Vim Snippet",\n "sol": "Solidity",\n "soy": "Closure Templates",\n "sp": "SourcePawn",\n "sparql": "SPARQL",\n "spc": "PLSQL",\n "spec": "Python",\n "spin": "Propeller Spin",\n "sps": "Scheme",\n "sqf": "SQF",\n "sql": "SQL",\n "sqlrpgle": "RPGLE",\n "sra": "PowerBuilder",\n "srdf": "XML",\n "srt": "SRecode Template",\n "sru": "PowerBuilder",\n "srv": "ROS Interface",\n "srw": "PowerBuilder",\n "ss": "Scheme",\n "ssjs": "JavaScript",\n "sss": "SugarSS",\n "st": "Smalltalk",\n "stan": "Stan",\n "star": "Starlark",\n "sthlp": "Stata",\n "stl": "STL",\n "story": "Gherkin",\n "storyboard": "XML",\n "sttheme": "XML",\n "sty": "TeX",\n "styl": "Stylus",\n "sublime-build": "JSON",\n "sublime-color-scheme": "JSON",\n "sublime-commands": "JSON",\n "sublime-completions": "JSON",\n "sublime-keymap": "JSON",\n "sublime-macro": "JSON",\n "sublime-menu": "JSON",\n "sublime-mousemap": "JSON",\n "sublime-project": "JSON",\n "sublime-settings": "JSON",\n "sublime-snippet": "XML",\n "sublime-syntax": "YAML",\n "sublime-theme": "JSON",\n "sublime-workspace": "JSON",\n "sublime_metrics": "JSON",\n "sublime_session": "JSON",\n "surql": "SurrealQL",\n "sv": "SystemVerilog",\n "svelte": "Svelte",\n "svg": "SVG",\n "svh": "SystemVerilog",\n "svx": "mdsvex",\n "sw": "Sway",\n "swift": "Swift",\n "syntax": "YAML",\n "t": "Perl",\n "tab": "SQL",\n "tac": "Python",\n "tact": "Tact",\n "tag": "Java",\n "talon": "Talon",\n "targets": "XML",\n "tcc": "C++",\n "tcl": "Tcl",\n "tcl.in": "Tcl",\n "templ": "templ",\n "tesc": "GLSL",\n "tese": "GLSL",\n "tex": "TeX",\n "textgrid": "TextGrid",\n "textile": "Textile",\n "tf": "HCL",\n "tfstate": "JSON",\n "tfstate.backup": "JSON",\n "tftpl": "HCL",\n "tfvars": "HCL",\n "thor": "Ruby",\n "thrift": "Thrift",\n "thy": "Isabelle",\n "tl": "Teal",\n "tla": "TLA",\n "tlv": "TL-Verilog",\n "tm": "Tcl",\n "tmac": "Roff",\n "tmcommand": "XML",\n "tmdl": "TMDL",\n "tml": "XML",\n "tmlanguage": "XML",\n "tmpl": "Go Template",\n "tmpreferences": "XML",\n "tmsnippet": "XML",\n "tmtheme": "XML",\n "tmux": "Shell",\n "toc": "TeX",\n "tofu": "HCL",\n "toit": "Toit",\n "toml": "TOML",\n "toml.example": "TOML",\n "tool": "Shell",\n "topojson": "JSON",\n "tpb": "PLSQL",\n "tpl": "Smarty",\n "tpp": "C++",\n "tps": "PLSQL",\n "tres": "Godot Resource",\n "trg": "PLSQL",\n "trigger": "Apex",\n "ts": "TypeScript",\n "tscn": "Godot Resource",\n "tsconfig.json": "JSON",\n "tsp": "TypeSpec",\n "tst": "GAP",\n "tsv": "TSV",\n "tsx": "TypeScript",\n "tu": "Turing",\n "twig": "Twig",\n "txl": "TXL",\n "txx": "C++",\n "typ": "Typst",\n "uc": "UnrealScript",\n "udf": "SQL",\n "udo": "Csound",\n "ui": "XML",\n "unity": "Unity3D Asset",\n "uno": "Uno",\n "upc": "C",\n "uplc": "Untyped Plutus Core",\n "ur": "UrWeb",\n "urdf": "XML",\n "url": "INI",\n "urs": "UrWeb",\n "ux": "XML",\n "v": "Verilog",\n "vala": "Vala",\n "vapi": "Vala",\n "vark": "Gosu",\n "vb": "Visual Basic .NET",\n "vba": "VBA",\n "vbhtml": "Visual Basic .NET",\n "vbproj": "XML",\n "vbs": "VBScript",\n "vcf": "vCard",\n "vcl": "VCL",\n "vcxproj": "XML",\n "vdf": "Valve Data Format",\n "veo": "Verilog",\n "vert": "GLSL",\n "vh": "SystemVerilog",\n "vhd": "VHDL",\n "vhdl": "VHDL",\n "vhf": "VHDL",\n "vhi": "VHDL",\n "vho": "VHDL",\n "vhost": "ApacheConf",\n "vhs": "VHDL",\n "vht": "VHDL",\n "vhw": "VHDL",\n "vim": "Vim Script",\n "vimrc": "Vim Script",\n "viw": "SQL",\n "vmb": "Vim Script",\n "volt": "Volt",\n "vrx": "GLSL",\n "vs": "GLSL",\n "vsh": "GLSL",\n "vshader": "GLSL",\n "vsixmanifest": "XML",\n "vssettings": "XML",\n "vstemplate": "XML",\n "vtl": "Velocity Template Language",\n "vto": "Vento",\n "vue": "Vue",\n "vw": "PLSQL",\n "vxml": "XML",\n "vy": "Vyper",\n "w": "CWeb",\n "wast": "WebAssembly",\n "wat": "WebAssembly",\n "watchr": "Ruby",\n "wdl": "WDL",\n "webapp": "JSON",\n "webmanifest": "JSON",\n "wgsl": "WGSL",\n "whiley": "Whiley",\n "wiki": "Wikitext",\n "wikitext": "Wikitext",\n "wisp": "wisp",\n "wit": "WebAssembly Interface Type",\n "wixproj": "XML",\n "wl": "Wolfram Language",\n "wlk": "Wollok",\n "wls": "Wolfram Language",\n "wlt": "Wolfram Language",\n "wlua": "Lua",\n "workbook": "Markdown",\n "workflow": "HCL",\n "wren": "Wren",\n "ws": "Witcher Script",\n "wsdl": "XML",\n "wsf": "XML",\n "wsgi": "Python",\n "wxi": "XML",\n "wxl": "XML",\n "wxs": "XML",\n "x": "DirectX 3D File",\n "x10": "X10",\n "x3d": "XML",\n "x68": "Assembly",\n "xacro": "XML",\n "xaml": "XML",\n "xc": "XC",\n "xdc": "Tcl",\n "xht": "HTML",\n "xhtml": "HTML",\n "xib": "XML",\n "xlf": "XML",\n "xliff": "XML",\n "xmi": "XML",\n "xml": "XML",\n "xml.dist": "XML",\n "xmp": "XML",\n "xojo_code": "Xojo",\n "xojo_menu": "Xojo",\n "xojo_report": "Xojo",\n "xojo_script": "Xojo",\n "xojo_toolbar": "Xojo",\n "xojo_window": "Xojo",\n "xproj": "XML",\n "xpy": "Python",\n "xq": "XQuery",\n "xql": "XQuery",\n "xqm": "XQuery",\n "xquery": "XQuery",\n "xqy": "XQuery",\n "xrl": "Erlang",\n "xsd": "XML",\n "xsh": "Xonsh",\n "xsjs": "JavaScript",\n "xsjslib": "JavaScript",\n "xsl": "XSLT",\n "xslt": "XSLT",\n "xspec": "XML",\n "xtend": "Xtend",\n "xul": "XML",\n "xzap": "ZAP",\n "y": "Yacc",\n "yacc": "Yacc",\n "yaml": "MiniYAML",\n "yaml-tmlanguage": "YAML",\n "yaml.sed": "YAML",\n "yap": "Prolog",\n "yar": "YARA",\n "yara": "YARA",\n "yasnippet": "YASnippet",\n "yml": "YAML",\n "yml.mysql": "YAML",\n "yrl": "Erlang",\n "yul": "Yul",\n "yy": "Yacc",\n "yyp": "JSON",\n "zap": "ZAP",\n "zcml": "XML",\n "zed": "SpiceDB Schema",\n "zep": "Zephir",\n "zig": "Zig",\n "zig.zon": "Zig",\n "zil": "ZIL",\n "zimpl": "Zimpl",\n "zmodel": "Zmodel",\n "zmpl": "Zimpl",\n "zpl": "Zimpl",\n "zs": "ZenScript",\n "zsh": "Shell",\n "zsh-theme": "Shell"\n },\n "filename": {\n ".abbrev_defs": "Emacs Lisp",\n ".ackrc": "Option List",\n ".all-contributorsrc": "JSON",\n ".arcconfig": "JSON",\n ".atomignore": "Ignore List",\n ".auto-changelog": "JSON",\n ".babelignore": "Ignore List",\n ".babelrc": "JSON",\n ".bash_aliases": "Shell",\n ".bash_functions": "Shell",\n ".bash_history": "Shell",\n ".bash_logout": "Shell",\n ".bash_profile": "Shell",\n ".bashrc": "Shell",\n ".browserslistrc": "Browserslist",\n ".buckconfig": "INI",\n ".bzrignore": "Ignore List",\n ".c8rc": "JSON",\n ".clang-format": "YAML",\n ".clang-tidy": "YAML",\n ".clangd": "YAML",\n ".classpath": "XML",\n ".coffeelintignore": "Ignore List",\n ".coveragerc": "INI",\n ".cproject": "XML",\n ".cshrc": "Shell",\n ".cvsignore": "Ignore List",\n ".devcontainer.json": "JSON",\n ".dockerignore": "Ignore List",\n ".easignore": "Ignore List",\n ".editorconfig": "INI",\n ".eleventyignore": "Ignore List",\n ".emacs": "Emacs Lisp",\n ".emacs.desktop": "Emacs Lisp",\n ".env": "Dotenv",\n ".env.ci": "Dotenv",\n ".env.dev": "Dotenv",\n ".env.development": "Dotenv",\n ".env.development.local": "Dotenv",\n ".env.example": "Dotenv",\n ".env.local": "Dotenv",\n ".env.prod": "Dotenv",\n ".env.production": "Dotenv",\n ".env.sample": "Dotenv",\n ".env.staging": "Dotenv",\n ".env.template": "Dotenv",\n ".env.test": "Dotenv",\n ".env.testing": "Dotenv",\n ".envrc": "Shell",\n ".eslintignore": "Ignore List",\n ".eslintrc.json": "JSON",\n ".exrc": "Vim Script",\n ".factor-boot-rc": "Factor",\n ".factor-rc": "Factor",\n ".flake8": "INI",\n ".flaskenv": "Shell",\n ".gclient": "Python",\n ".gemrc": "YAML",\n ".git-blame-ignore-revs": "Git Revision List",\n ".gitattributes": "Git Attributes",\n ".gitconfig": "INI",\n ".gitignore": "Ignore List",\n ".gitmodules": "INI",\n ".gnus": "Emacs Lisp",\n ".gvimrc": "Vim Script",\n ".htaccess": "ApacheConf",\n ".htmlhintrc": "JSON",\n ".ignore": "Ignore List",\n ".imgbotconfig": "JSON",\n ".irbrc": "Ruby",\n ".jscsrc": "JSON",\n ".jshintrc": "JSON",\n ".jslintrc": "JSON",\n ".justfile": "Just",\n ".kshrc": "Shell",\n ".latexmkrc": "Perl",\n ".login": "Shell",\n ".luacheckrc": "Lua",\n ".markdownlintignore": "Ignore List",\n ".nanorc": "INI",\n ".nodemonignore": "Ignore List",\n ".npmignore": "Ignore List",\n ".npmrc": "INI",\n ".nvimrc": "Vim Script",\n ".nycrc": "JSON",\n ".oxlintrc.json": "JSON",\n ".php": "PHP",\n ".php_cs": "PHP",\n ".php_cs.dist": "PHP",\n ".prettierignore": "Ignore List",\n ".profile": "Shell",\n ".project": "XML",\n ".pryrc": "Ruby",\n ".pylintrc": "INI",\n ".rprofile": "R",\n ".rspec": "Option List",\n ".scalafix.conf": "HOCON",\n ".scalafmt.conf": "HOCON",\n ".shellcheckrc": "ShellCheck Config",\n ".simplecov": "Ruby",\n ".spacemacs": "Emacs Lisp",\n ".stylelintignore": "Ignore List",\n ".swcrc": "JSON",\n ".tern-config": "JSON",\n ".tern-project": "JSON",\n ".tm_properties": "TextMate Properties",\n ".tmux.conf": "Shell",\n ".vercelignore": "Ignore List",\n ".vimrc": "Vim Script",\n ".viper": "Emacs Lisp",\n ".vscodeignore": "Ignore List",\n ".watchmanconfig": "JSON",\n ".xinitrc": "Shell",\n ".xsession": "Shell",\n ".yardopts": "Option List",\n ".zlogin": "Shell",\n ".zlogout": "Shell",\n ".zprofile": "Shell",\n ".zshenv": "Shell",\n ".zshrc": "Shell",\n "9fs": "Shell",\n "_emacs": "Emacs Lisp",\n "_helpers.tpl": "Go Template",\n "_vimrc": "Vim Script",\n "abbrev_defs": "Emacs Lisp",\n "ack": "Perl",\n "ackrc": "Option List",\n "ant.xml": "Ant Build System",\n "apache2.conf": "ApacheConf",\n "api-extractor.json": "JSON",\n "apkbuild": "Shell",\n "app.config": "XML",\n "appraisals": "Ruby",\n "bash_aliases": "Shell",\n "bash_logout": "Shell",\n "bash_profile": "Shell",\n "bashrc": "Shell",\n "berksfile": "Ruby",\n "brewfile": "Ruby",\n "browserslist": "Browserslist",\n "bsdmakefile": "Makefile",\n "buck": "Starlark",\n "build": "Starlark",\n "build.bazel": "Starlark",\n "build.xml": "Ant Build System",\n "buildfile": "Ruby",\n "buildozer.spec": "INI",\n "bun.lock": "JSON",\n "cabal.config": "Cabal Config",\n "cabal.project": "Cabal Config",\n "caddyfile": "Caddyfile",\n "cakefile": "CoffeeScript",\n "capfile": "Ruby",\n "cargo.lock": "TOML",\n "cargo.toml.orig": "TOML",\n "cask": "Emacs Lisp",\n "citation.cff": "YAML",\n "cmakelists.txt": "CMake",\n "commit_editmsg": "Git Commit",\n "composer.lock": "JSON",\n "containerfile": "Dockerfile",\n "contents.lr": "Markdown",\n "cpanfile": "Perl",\n "crontab": "crontab",\n "cshrc": "Shell",\n "dangerfile": "Ruby",\n "deliverfile": "Ruby",\n "deno.lock": "JSON",\n "deps": "Python",\n "dev-requirements.txt": "Pip Requirements",\n "devcontainer.json": "JSON",\n "dockerfile": "Dockerfile",\n "dune-project": "Dune",\n "earthfile": "Earthly",\n "eask": "Emacs Lisp",\n "emakefile": "Erlang",\n "eqnrc": "Roff",\n "expr-dist": "R",\n "fakefile": "Fancy",\n "fastfile": "Ruby",\n "firestore.rules": "Cloud Firestore Security Rules",\n "flake.lock": "JSON",\n "fp-lib-table": "KiCad Layout",\n "gemfile": "Ruby",\n "gemfile.lock": "Gemfile.lock",\n "gitignore-global": "Ignore List",\n "gitignore_global": "Ignore List",\n "glide.lock": "YAML",\n "gnumakefile": "Makefile",\n "go.mod": "Go Module",\n "go.sum": "Go Checksums",\n "go.work": "Go Workspace",\n "go.work.sum": "Go Checksums",\n "gopkg.lock": "TOML",\n "gradlew": "Shell",\n "gradlew.bat": "Batchfile",\n "guardfile": "Ruby",\n "gvimrc": "Vim Script",\n "haproxy.cfg": "HAProxy",\n "hosts": "Hosts File",\n "hosts.txt": "Hosts File",\n "httpd.conf": "ApacheConf",\n "installscript.qs": "Qt Script",\n "jakefile": "JavaScript",\n "jarfile": "Ruby",\n "jenkinsfile": "Groovy",\n "jsconfig.json": "JSON",\n "justfile": "Just",\n "kakrc": "KakouneScript",\n "kbuild": "Makefile",\n "kcl.mod": "KCL",\n "kcl.mod.lock": "KCL",\n "kshrc": "Shell",\n "language-configuration.json": "JSON",\n "language-subtag-registry.txt": "Record Jar",\n "latexmkrc": "Perl",\n "lexer.x": "Lex",\n "login": "Shell",\n "m3makefile": "Quake",\n "m3overrides": "Quake",\n "makefile": "Makefile",\n "makefile.am": "Makefile",\n "makefile.boot": "Makefile",\n "makefile.frag": "Makefile",\n "makefile.in": "Makefile",\n "makefile.inc": "Makefile",\n "makefile.pl": "Perl",\n "makefile.sco": "Makefile",\n "makefile.wat": "Makefile",\n "man": "Shell",\n "manifest.mf": "JAR Manifest",\n "mavenfile": "Ruby",\n "mcmod.info": "JSON",\n "meson.build": "Meson",\n "meson_options.txt": "Meson",\n "mise.local.lock": "TOML",\n "mise.lock": "TOML",\n "mix.lock": "Elixir",\n "mkfile": "Makefile",\n "mmn": "Roff",\n "mmt": "Roff",\n "mocha.opts": "Option List",\n "module.bazel": "Starlark",\n "module.bazel.lock": "JSON",\n "modulefile": "Puppet",\n "mvnw": "Shell",\n "mvnw.cmd": "Batchfile",\n "nanorc": "INI",\n "nextflow.config": "Nextflow",\n "nginx.conf": "Nginx",\n "nim.cfg": "Nim",\n "notebook": "Jupyter Notebook",\n "nuget.config": "XML",\n "nukefile": "Nu",\n "nvimrc": "Vim Script",\n "owh": "Tcl",\n "package.resolved": "JSON",\n "packages.config": "XML",\n "pdm.lock": "TOML",\n "phakefile": "PHP",\n "pipfile": "TOML",\n "pipfile.lock": "JSON",\n "pixi.lock": "YAML",\n "pkgbuild": "Shell",\n "podfile": "Ruby",\n "poetry.lock": "TOML",\n "procfile": "Procfile",\n "profile": "Shell",\n "project.ede": "Emacs Lisp",\n "project.godot": "Godot Resource",\n "puppetfile": "Ruby",\n "pylintrc": "INI",\n "rakefile": "Ruby",\n "rebar.config": "Erlang",\n "rebar.config.lock": "Erlang",\n "rebar.lock": "Erlang",\n "requirements-dev.txt": "Pip Requirements",\n "requirements.lock.txt": "Pip Requirements",\n "requirements.txt": "Pip Requirements",\n "rexfile": "Perl",\n "riemann.config": "Clojure",\n "root": "Isabelle",\n "sconscript": "Python",\n "sconstruct": "Python",\n "settings.stylecop": "XML",\n "singularity": "Singularity",\n "slakefile": "LiveScript",\n "snakefile": "Python",\n "snapfile": "Ruby",\n "starfield": "Tcl",\n "steepfile": "Ruby",\n "suite.rc": "INI",\n "thorfile": "Ruby",\n "tiltfile": "Starlark",\n "tmux.conf": "Shell",\n "toolchain_installscript.qs": "Qt Script",\n "torrc": "Tor Config",\n "troffrc": "Roff",\n "troffrc-end": "Roff",\n "tsconfig.json": "JSON",\n "tslint.json": "JSON",\n "uv.lock": "TOML",\n "vagrantfile": "Ruby",\n "vimrc": "Vim Script",\n "vlcrc": "INI",\n "web.config": "XML",\n "web.debug.config": "XML",\n "web.release.config": "XML",\n "workspace": "Starlark",\n "workspace.bazel": "Starlark",\n "workspace.bzlmod": "Starlark",\n "wscript": "Python",\n "xinitrc": "Shell",\n "xmake.lua": "Xmake",\n "xsession": "Shell",\n "yarn.lock": "YAML",\n "zlogin": "Shell",\n "zlogout": "Shell",\n "zprofile": "Shell",\n "zshenv": "Shell",\n "zshrc": "Shell"\n }\n },\n "vendor": [\n "(^|/)cache/",\n "^[Dd]ependencies/",\n "(^|/)dist/",\n "^deps/",\n "(^|/)configure$",\n "(^|/)config\\\\.guess$",\n "(^|/)config\\\\.sub$",\n "(^|/)aclocal\\\\.m4",\n "(^|/)libtool\\\\.m4",\n "(^|/)ltoptions\\\\.m4",\n "(^|/)ltsugar\\\\.m4",\n "(^|/)ltversion\\\\.m4",\n "(^|/)lt~obsolete\\\\.m4",\n "(^|/)dotnet-install\\\\.(ps1|sh)$",\n "(^|/)cpplint\\\\.py",\n "(^|/)node_modules/",\n "(^|/)\\\\.yarn/releases/",\n "(^|/)\\\\.yarn/plugins/",\n "(^|/)\\\\.yarn/sdks/",\n "(^|/)\\\\.yarn/versions/",\n "(^|/)\\\\.yarn/unplugged/",\n "(^|/)_esy$",\n "(^|/)bower_components/",\n "^rebar$",\n "(^|/)erlang\\\\.mk",\n "(^|/)Godeps/_workspace/",\n "(^|/)testdata/",\n "(^|/)\\\\.indent\\\\.pro",\n "(\\\\.|-)min\\\\.(js|css)$",\n "([^\\\\s]*)import\\\\.(css|less|scss|styl)$",\n "(^|/)bootstrap([^/.]*)(\\\\..*)?\\\\.(js|css|less|scss|styl)$",\n "(^|/)custom\\\\.bootstrap([^\\\\s]*)(js|css|less|scss|styl)$",\n "(^|/)font-?awesome\\\\.(css|less|scss|styl)$",\n "(^|/)font-?awesome/.*\\\\.(css|less|scss|styl)$",\n "(^|/)foundation\\\\.(css|less|scss|styl)$",\n "(^|/)normalize\\\\.(css|less|scss|styl)$",\n "(^|/)skeleton\\\\.(css|less|scss|styl)$",\n "(^|/)[Bb]ourbon/.*\\\\.(css|less|scss|styl)$",\n "(^|/)animate\\\\.(css|less|scss|styl)$",\n "(^|/)materialize\\\\.(css|less|scss|styl|js)$",\n "(^|/)select2/.*\\\\.(css|scss|js)$",\n "(^|/)bulma\\\\.(css|sass|scss)$",\n "(3rd|[Tt]hird)[-_]?[Pp]arty/",\n "(^|/)vendors?/",\n "(^|/)[Ee]xtern(als?)?/",\n "(^|/)[Vv]+endor/",\n "^debian/",\n "(^|/)run\\\\.n$",\n "(^|/)bootstrap-datepicker/",\n "(^|/)jquery([^.]*)\\\\.js$",\n "(^|/)jquery\\\\-\\\\d\\\\.\\\\d+(\\\\.\\\\d+)?\\\\.js$",\n "(^|/)jquery\\\\-ui(\\\\-\\\\d\\\\.\\\\d+(\\\\.\\\\d+)?)?(\\\\.\\\\w+)?\\\\.(js|css)$",\n "(^|/)jquery\\\\.(ui|effects)\\\\.([^.]*)\\\\.(js|css)$",\n "(^|/)jquery\\\\.fn\\\\.gantt\\\\.js",\n "(^|/)jquery\\\\.fancybox\\\\.(js|css)",\n "(^|/)fuelux\\\\.js",\n "(^|/)jquery\\\\.fileupload(-\\\\w+)?\\\\.js$",\n "(^|/)jquery\\\\.dataTables\\\\.js",\n "(^|/)bootbox\\\\.js",\n "(^|/)pdf\\\\.worker\\\\.js",\n "(^|/)slick\\\\.\\\\w+.js$",\n "(^|/)Leaflet\\\\.Coordinates-\\\\d+\\\\.\\\\d+\\\\.\\\\d+\\\\.src\\\\.js$",\n "(^|/)leaflet\\\\.draw-src\\\\.js",\n "(^|/)leaflet\\\\.draw\\\\.css",\n "(^|/)Control\\\\.FullScreen\\\\.css",\n "(^|/)Control\\\\.FullScreen\\\\.js",\n "(^|/)leaflet\\\\.spin\\\\.js",\n "(^|/)wicket-leaflet\\\\.js",\n "(^|/)\\\\.sublime-project",\n "(^|/)\\\\.sublime-workspace",\n "(^|/)\\\\.vscode/",\n "(^|/)prototype(.*)\\\\.js$",\n "(^|/)effects\\\\.js$",\n "(^|/)controls\\\\.js$",\n "(^|/)dragdrop\\\\.js$",\n "(.*?)\\\\.d\\\\.ts$",\n "(^|/)mootools([^.]*)\\\\d+\\\\.\\\\d+.\\\\d+([^.]*)\\\\.js$",\n "(^|/)dojo\\\\.js$",\n "(^|/)MochiKit\\\\.js$",\n "(^|/)yahoo-([^.]*)\\\\.js$",\n "(^|/)yui([^.]*)\\\\.js$",\n "(^|/)ckeditor\\\\.js$",\n "(^|/)tiny_mce([^.]*)\\\\.js$",\n "(^|/)tiny_mce/(langs|plugins|themes|utils)",\n "(^|/)ace-builds/",\n "(^|/)fontello(.*?)\\\\.css$",\n "(^|/)MathJax/",\n "(^|/)Chart\\\\.js$",\n "(^|/)[Cc]ode[Mm]irror/(\\\\d+\\\\.\\\\d+/)?(lib|mode|theme|addon|keymap|demo)",\n "(^|/)shBrush([^.]*)\\\\.js$",\n "(^|/)shCore\\\\.js$",\n "(^|/)shLegacy\\\\.js$",\n "(^|/)angular([^.]*)\\\\.js$",\n "(^|\\\\/)d3(\\\\.v\\\\d+)?([^.]*)\\\\.js$",\n "(^|/)react(-[^.]*)?\\\\.js$",\n "(^|/)flow-typed/.*\\\\.js$",\n "(^|/)modernizr\\\\-\\\\d\\\\.\\\\d+(\\\\.\\\\d+)?\\\\.js$",\n "(^|/)modernizr\\\\.custom\\\\.\\\\d+\\\\.js$",\n "(^|/)knockout-(\\\\d+\\\\.){3}(debug\\\\.)?js$",\n "(^|/)docs?/_?(build|themes?|templates?|static)/",\n "(^|/)admin_media/",\n "(^|/)env/",\n "(^|/)fabfile\\\\.py$",\n "(^|/)waf$",\n "(^|/)\\\\.osx$",\n "\\\\.xctemplate/",\n "\\\\.imageset/",\n "(^|/)Carthage/",\n "(^|/)Sparkle/",\n "(^|/)Crashlytics\\\\.framework/",\n "(^|/)Fabric\\\\.framework/",\n "(^|/)BuddyBuildSDK\\\\.framework/",\n "(^|/)Realm\\\\.framework",\n "(^|/)RealmSwift\\\\.framework",\n "(^|/)\\\\.gitattributes$",\n "(^|/)\\\\.gitignore$",\n "(^|/)\\\\.gitmodules$",\n "(^|/)gradlew$",\n "(^|/)gradlew\\\\.bat$",\n "(^|/)gradle/wrapper/",\n "(^|/)mvnw$",\n "(^|/)mvnw\\\\.cmd$",\n "(^|/)\\\\.mvn/wrapper/",\n "-vsdoc\\\\.js$",\n "\\\\.intellisense\\\\.js$",\n "(^|/)jquery([^.]*)\\\\.validate(\\\\.unobtrusive)?\\\\.js$",\n "(^|/)jquery([^.]*)\\\\.unobtrusive\\\\-ajax\\\\.js$",\n "(^|/)[Mm]icrosoft([Mm]vc)?([Aa]jax|[Vv]alidation)(\\\\.debug)?\\\\.js$",\n "(^|/)[Pp]ackages\\\\/.+\\\\.\\\\d+\\\\/",\n "(^|/)extjs/.*?\\\\.js$",\n "(^|/)extjs/.*?\\\\.xml$",\n "(^|/)extjs/.*?\\\\.txt$",\n "(^|/)extjs/.*?\\\\.html$",\n "(^|/)extjs/.*?\\\\.properties$",\n "(^|/)extjs/\\\\.sencha/",\n "(^|/)extjs/docs/",\n "(^|/)extjs/builds/",\n "(^|/)extjs/cmd/",\n "(^|/)extjs/examples/",\n "(^|/)extjs/locale/",\n "(^|/)extjs/packages/",\n "(^|/)extjs/plugins/",\n "(^|/)extjs/resources/",\n "(^|/)extjs/src/",\n "(^|/)extjs/welcome/",\n "(^|/)html5shiv\\\\.js$",\n "(^|/)[Tt]ests?/fixtures/",\n "(^|/)[Ss]pecs?/fixtures/",\n "(^|/)cordova([^.]*)\\\\.js$",\n "(^|/)cordova\\\\-\\\\d\\\\.\\\\d(\\\\.\\\\d)?\\\\.js$",\n "(^|/)foundation(\\\\..*)?\\\\.js$",\n "(^|/)Vagrantfile$",\n "(^|/)\\\\.[Dd][Ss]_[Ss]tore$",\n "(^|/)inst/extdata/",\n "(^|/)octicons\\\\.css",\n "(^|/)sprockets-octicons\\\\.scss",\n "(^|/)activator$",\n "(^|/)activator\\\\.bat$",\n "(^|/)proguard\\\\.pro$",\n "(^|/)proguard-rules\\\\.pro$",\n "(^|/)puphpet/",\n "(^|/)\\\\.google_apis/",\n "(^|/)Jenkinsfile$",\n "(^|/)\\\\.gitpod\\\\.Dockerfile$",\n "(^|/)\\\\.github/",\n "(^|/)\\\\.obsidian/",\n "(^|/)\\\\.teamcity/",\n "(^|/)xvba_modules/"\n ]\n}' +TECHDATA = '{\n "_source": {\n "languages": "https://raw.githubusercontent.com/github-linguist/linguist/master/lib/linguist/languages.yml",\n "vendor": "https://raw.githubusercontent.com/github-linguist/linguist/master/lib/linguist/vendor.yml"\n },\n "fw_deps": {\n "Go": {\n "github.com/gin-gonic/gin": "Gin",\n "github.com/go-chi/chi": "chi",\n "github.com/gofiber/fiber": "Fiber",\n "github.com/gorilla/mux": "Gorilla",\n "github.com/labstack/echo": "Echo",\n "github.com/spf13/cobra": "Cobra",\n "google.golang.org/grpc": "gRPC",\n "gorm.io/gorm": "GORM"\n },\n "PHP": {\n "cakephp/cakephp": "CakePHP",\n "laravel/framework": "Laravel",\n "slim/slim": "Slim",\n "symfony/framework-bundle": "Symfony",\n "symfony/symfony": "Symfony",\n "yiisoft/yii2": "Yii"\n },\n "Python": {\n "aiohttp": "aiohttp",\n "celery": "Celery",\n "click": "Click",\n "django": "Django",\n "djangorestframework": "Django REST",\n "fastapi": "FastAPI",\n "flask": "Flask",\n "httpx": "HTTPX",\n "keras": "Keras",\n "matplotlib": "Matplotlib",\n "numpy": "NumPy",\n "pandas": "pandas",\n "pydantic": "Pydantic",\n "pyramid": "Pyramid",\n "pytest": "pytest",\n "requests": "Requests",\n "sanic": "Sanic",\n "scikit-learn": "scikit-learn",\n "scipy": "SciPy",\n "scrapy": "Scrapy",\n "sqlalchemy": "SQLAlchemy",\n "starlette": "Starlette",\n "tensorflow": "TensorFlow",\n "torch": "PyTorch",\n "tornado": "Tornado",\n "transformers": "Transformers",\n "typer": "Typer"\n },\n "Ruby": {\n "devise": "Devise",\n "hanami": "Hanami",\n "puma": "Puma",\n "rails": "Rails",\n "rspec": "RSpec",\n "sidekiq": "Sidekiq",\n "sinatra": "Sinatra"\n },\n "Rust": {\n "actix-web": "Actix Web",\n "axum": "Axum",\n "bevy": "Bevy",\n "clap": "clap",\n "diesel": "Diesel",\n "rocket": "Rocket",\n "serde": "Serde",\n "tauri": "Tauri",\n "tokio": "Tokio",\n "tonic": "Tonic",\n "warp": "warp"\n },\n "npm": {\n "@angular/core": "Angular",\n "@apollo/client": "Apollo",\n "@babel/core": "Babel",\n "@biomejs/biome": "Biome",\n "@chakra-ui/react": "Chakra UI",\n "@hapi/hapi": "hapi",\n "@ionic/core": "Ionic",\n "@mui/material": "MUI",\n "@nestjs/core": "NestJS",\n "@nx/workspace": "Nx",\n "@playwright/test": "Playwright",\n "@prisma/client": "Prisma",\n "@reduxjs/toolkit": "Redux",\n "@remix-run/react": "Remix",\n "@storybook/angular": "Storybook",\n "@storybook/html": "Storybook",\n "@storybook/preact": "Storybook",\n "@storybook/react": "Storybook",\n "@storybook/svelte": "Storybook",\n "@storybook/vue3": "Storybook",\n "@storybook/web-components": "Storybook",\n "@sveltejs/kit": "SvelteKit",\n "@swc/core": "SWC",\n "@testing-library/dom": "Testing Library",\n "@testing-library/react": "Testing Library",\n "@testing-library/vue": "Testing Library",\n "@trpc/client": "tRPC",\n "@trpc/server": "tRPC",\n "astro": "Astro",\n "bootstrap": "Bootstrap",\n "chart.js": "Chart.js",\n "cypress": "Cypress",\n "d3": "D3",\n "drizzle-orm": "Drizzle",\n "electron": "Electron",\n "esbuild": "esbuild",\n "eslint": "ESLint",\n "expo": "Expo",\n "express": "Express",\n "fastify": "Fastify",\n "gatsby": "Gatsby",\n "graphql": "GraphQL",\n "jest": "Jest",\n "koa": "Koa",\n "mocha": "Mocha",\n "mongoose": "Mongoose",\n "next": "Next.js",\n "nuxt": "Nuxt",\n "nx": "Nx",\n "parcel": "Parcel",\n "playwright": "Playwright",\n "preact": "Preact",\n "prettier": "Prettier",\n "prisma": "Prisma",\n "puppeteer": "Puppeteer",\n "react": "React",\n "react-dom": "React",\n "react-native": "React Native",\n "redux": "Redux",\n "rollup": "Rollup",\n "sequelize": "Sequelize",\n "solid-js": "SolidJS",\n "storybook": "Storybook",\n "styled-components": "styled-components",\n "svelte": "Svelte",\n "tailwindcss": "Tailwind CSS",\n "testcafe": "TestCafe",\n "three": "three.js",\n "turbo": "Turborepo",\n "typeorm": "TypeORM",\n "vite": "Vite",\n "vitest": "Vitest",\n "vue": "Vue",\n "webpack": "webpack",\n "zustand": "Zustand"\n }\n },\n "fw_sentinels_js": [\n [\n "next.config.js",\n "Next.js"\n ],\n [\n "next.config.ts",\n "Next.js"\n ],\n [\n "next.config.mjs",\n "Next.js"\n ],\n [\n "nuxt.config.js",\n "Nuxt"\n ],\n [\n "nuxt.config.ts",\n "Nuxt"\n ],\n [\n "svelte.config.js",\n "Svelte"\n ],\n [\n "astro.config.mjs",\n "Astro"\n ],\n [\n "vue.config.js",\n "Vue"\n ],\n [\n "gatsby-config.js",\n "Gatsby"\n ],\n [\n "angular.json",\n "Angular"\n ]\n ],\n "fw_sentinels_other": [\n [\n "manage.py",\n "Django",\n "Python"\n ],\n [\n "artisan",\n "Laravel",\n "PHP"\n ],\n [\n "config/application.rb",\n "Rails",\n "Ruby"\n ],\n [\n "Dockerfile",\n "Docker",\n "Tools"\n ],\n [\n "docker-compose.yml",\n "Docker Compose",\n "Tools"\n ],\n [\n "docker-compose.yaml",\n "Docker Compose",\n "Tools"\n ],\n [\n "compose.yml",\n "Docker Compose",\n "Tools"\n ],\n [\n "compose.yaml",\n "Docker Compose",\n "Tools"\n ],\n [\n "Makefile",\n "Make",\n "Tools"\n ],\n [\n "GNUmakefile",\n "Make",\n "Tools"\n ],\n [\n "pnpm-lock.yaml",\n "pnpm",\n "Tools"\n ],\n [\n "yarn.lock",\n "Yarn",\n "Tools"\n ],\n [\n "bun.lockb",\n "Bun",\n "Tools"\n ],\n [\n "bun.lock",\n "Bun",\n "Tools"\n ],\n [\n ".gitlab-ci.yml",\n "GitLab CI",\n "Tools"\n ],\n [\n "vercel.json",\n "Vercel",\n "Tools"\n ],\n [\n "netlify.toml",\n "Netlify",\n "Tools"\n ],\n [\n ".github/workflows/",\n "GitHub Actions",\n "Tools"\n ]\n ],\n "lang": {\n "color": {\n "1C Enterprise": "#814CCC",\n "2-Dimensional Array": "#38761D",\n "4D": "#004289",\n "ABAP": "#E8274B",\n "ABAP CDS": "#555e25",\n "AGS Script": "#B9D9FF",\n "AIDL": "#34EB6B",\n "AL": "#3AA2B5",\n "ALGOL": "#D1E0DB",\n "AMPL": "#E6EFBB",\n "ANTLR": "#9DC3FF",\n "API Blueprint": "#2ACCA8",\n "APL": "#5A8164",\n "ASP.NET": "#9400ff",\n "ATS": "#1ac620",\n "ActionScript": "#882B0F",\n "Ada": "#02f88c",\n "Adblock Filter List": "#800000",\n "Adobe Font Metrics": "#fa0f00",\n "Agda": "#315665",\n "Aiken": "#640ff8",\n "Alloy": "#64C800",\n "Alpine Abuild": "#0D597F",\n "Altium Designer": "#A89663",\n "AngelScript": "#C7D7DC",\n "Answer Set Programming": "#A9CC29",\n "Ant Build System": "#A9157E",\n "Antlers": "#ff269e",\n "ApacheConf": "#d12127",\n "Apex": "#1797c0",\n "Apollo Guidance Computer": "#0B3D91",\n "AppleScript": "#101F1F",\n "Arc": "#aa2afe",\n "AsciiDoc": "#73a0c5",\n "AspectJ": "#a957b0",\n "Assembly": "#6E4C13",\n "Astro": "#ff5a03",\n "Asymptote": "#ff0000",\n "Augeas": "#9CC134",\n "AutoHotkey": "#6594b9",\n "AutoIt": "#1C3552",\n "Avro IDL": "#0040FF",\n "Awk": "#c30e9b",\n "B (Formal Method)": "#8aa8c5",\n "B4X": "#00e4ff",\n "BASIC": "#ff0000",\n "BQN": "#2b7067",\n "Ballerina": "#FF5000",\n "Batchfile": "#C1F12E",\n "Beef": "#a52f4e",\n "Berry": "#15A13C",\n "BibTeX": "#778899",\n "Bicep": "#519aba",\n "Bikeshed": "#5562ac",\n "Bison": "#6A463F",\n "BitBake": "#00bce4",\n "Blade": "#f7523f",\n "BlitzBasic": "#00FFAE",\n "BlitzMax": "#cd6400",\n "Bluespec": "#12223c",\n "Bluespec BH": "#12223c",\n "Boo": "#d4bec1",\n "Boogie": "#c80fa0",\n "Brainfuck": "#2F2530",\n "BrighterScript": "#66AABB",\n "Brightscript": "#662D91",\n "Browserslist": "#ffd539",\n "Bru": "#F4AA41",\n "BuildStream": "#006bff",\n "C": "#555555",\n "C#": "#178600",\n "C++": "#f34b7d",\n "C3": "#2563eb",\n "CAP CDS": "#0092d1",\n "CLIPS": "#00A300",\n "CMake": "#DA3434",\n "COLLADA": "#F1A42B",\n "CQL": "#006091",\n "CSON": "#244776",\n "CSS": "#663399",\n "CSV": "#237346",\n "CUE": "#5886E1",\n "CWeb": "#00007a",\n "Cabal Config": "#483465",\n "Caddyfile": "#22b638",\n "Cadence": "#00ef8b",\n "Cairo": "#ff4a48",\n "Cairo Zero": "#ff4a48",\n "CameLIGO": "#3be133",\n "Cangjie": "#00868B",\n "Cap\'n Proto": "#c42727",\n "Carbon": "#222222",\n "Ceylon": "#dfa535",\n "Chapel": "#8dc63f",\n "ChucK": "#3f8000",\n "Circom": "#707575",\n "Cirru": "#ccccff",\n "Clarion": "#db901e",\n "Clarity": "#5546ff",\n "Classic ASP": "#6a40fd",\n "Clean": "#3F85AF",\n "Click": "#E4E6F3",\n "Clojure": "#db5855",\n "Closure Templates": "#0d948f",\n "Cloud Firestore Security Rules": "#FFA000",\n "Clue": "#0009b5",\n "CodeQL": "#140f46",\n "CoffeeScript": "#244776",\n "ColdFusion": "#ed2cd6",\n "ColdFusion CFC": "#ed2cd6",\n "Common Lisp": "#3fb68b",\n "Common Workflow Language": "#B5314C",\n "Component Pascal": "#B0CE4E",\n "Cooklang": "#E15A29",\n "Crystal": "#000100",\n "Csound": "#1a1a1a",\n "Csound Document": "#1a1a1a",\n "Csound Score": "#1a1a1a",\n "Cuda": "#3A4E3A",\n "Curry": "#531242",\n "Cylc": "#00b3fd",\n "Cypher": "#34c0eb",\n "Cython": "#fedf5b",\n "D": "#ba595e",\n "D2": "#526ee8",\n "DM": "#447265",\n "Dafny": "#FFEC25",\n "Darcs Patch": "#8eff23",\n "Dart": "#00B4AB",\n "Daslang": "#d3d3d3",\n "DataWeave": "#003a52",\n "Debian Package Control File": "#D70751",\n "DenizenScript": "#FBEE96",\n "Dhall": "#dfafff",\n "DirectX 3D File": "#aace60",\n "Dockerfile": "#384d54",\n "Dogescript": "#cca760",\n "Dotenv": "#e5d559",\n "Dune": "#89421e",\n "Dylan": "#6c616e",\n "E": "#ccce35",\n "ECL": "#8a1267",\n "ECLiPSe": "#001d9d",\n "EJS": "#a91e50",\n "EQ": "#a78649",\n "Earthly": "#2af0ff",\n "Easybuild": "#069406",\n "Ecere Projects": "#913960",\n "Ecmarkup": "#eb8131",\n "Edge": "#0dffe0",\n "EdgeQL": "#31A7FF",\n "EditorConfig": "#fff1f2",\n "Eiffel": "#4d6977",\n "Elixir": "#6e4a7e",\n "Elm": "#60B5CC",\n "Elvish": "#55BB55",\n "Elvish Transcript": "#55BB55",\n "Emacs Lisp": "#c065db",\n "EmberScript": "#FFF4F3",\n "Erlang": "#B83998",\n "Euphoria": "#FF790B",\n "F#": "#b845fc",\n "F*": "#572e30",\n "FIGlet Font": "#FFDDBB",\n "FIRRTL": "#2f632f",\n "FLUX": "#88ccff",\n "Factor": "#636746",\n "Fancy": "#7b9db4",\n "Fantom": "#14253c",\n "Faust": "#c37240",\n "Fennel": "#fff3d7",\n "Filebench WML": "#F6B900",\n "FlatBuffers": "#ed284a",\n "Flix": "#d44a45",\n "Fluent": "#ffcc33",\n "Forth": "#341708",\n "Fortran": "#4d41b1",\n "Fortran Free Form": "#4d41b1",\n "FreeBASIC": "#141AC9",\n "FreeMarker": "#0050b2",\n "Frege": "#00cafe",\n "Futhark": "#5f021f",\n "G-code": "#D08CF2",\n "GAML": "#FFC766",\n "GAMS": "#f49a22",\n "GAP": "#0000cc",\n "GCC Machine Description": "#FFCFAB",\n "GDScript": "#355570",\n "GDShader": "#478CBF",\n "GEDCOM": "#003058",\n "GLSL": "#5686a5",\n "GSC": "#FF6800",\n "Game Maker Language": "#71b417",\n "Gemfile.lock": "#701516",\n "Gemini": "#ff6900",\n "Genero 4gl": "#63408e",\n "Genero per": "#d8df39",\n "Genie": "#fb855d",\n "Genshi": "#951531",\n "Gentoo Ebuild": "#9400ff",\n "Gentoo Eclass": "#9400ff",\n "Gerber Image": "#d20b00",\n "Gettext Catalog": "#9e6a03",\n "Gherkin": "#5B2063",\n "Git Attributes": "#F44D27",\n "Git Commit": "#F44D27",\n "Git Config": "#F44D27",\n "Git Revision List": "#F44D27",\n "Gleam": "#ffaff3",\n "Glimmer JS": "#F5835F",\n "Glimmer TS": "#3178c6",\n "Glyph": "#c1ac7f",\n "Gnuplot": "#f0a9f0",\n "Go": "#00ADD8",\n "Go Checksums": "#00ADD8",\n "Go Module": "#00ADD8",\n "Go Template": "#00ADD8",\n "Go Workspace": "#00ADD8",\n "Godot Resource": "#355570",\n "Golo": "#88562A",\n "Gosu": "#82937f",\n "Grace": "#615f8b",\n "Gradle": "#02303a",\n "Gradle Kotlin DSL": "#02303a",\n "Grammatical Framework": "#ff0000",\n "GraphQL": "#e10098",\n "Graphviz (DOT)": "#2596be",\n "Groovy": "#4298b8",\n "Groovy Server Pages": "#4298b8",\n "HAProxy": "#106da9",\n "HCL": "#844FBA",\n "HIP": "#4F3A4F",\n "HLSL": "#aace60",\n "HOCON": "#9ff8ee",\n "HTML": "#e34c26",\n "HTML+ECR": "#2e1052",\n "HTML+EEX": "#6e4a7e",\n "HTML+ERB": "#701516",\n "HTML+PHP": "#4f5d95",\n "HTML+Razor": "#512be4",\n "HTTP": "#005C9C",\n "HXML": "#f68712",\n "Hack": "#878787",\n "Haml": "#ece2a9",\n "Handlebars": "#f7931e",\n "Harbour": "#0e60e3",\n "Hare": "#9d7424",\n "Haskell": "#5e5086",\n "Haxe": "#df7900",\n "HiveQL": "#dce200",\n "HolyC": "#ffefaf",\n "Hosts File": "#308888",\n "Hurl": "#FF0288",\n "Hy": "#7790B2",\n "IDL": "#a3522f",\n "IGOR Pro": "#0000cc",\n "IL Assembly": "#512BD4",\n "INI": "#d1dbe0",\n "ISPC": "#2D68B1",\n "Idris": "#b30000",\n "Ignore List": "#000000",\n "ImageJ Macro": "#99AAFF",\n "Imba": "#16cec6",\n "Inno Setup": "#264b99",\n "Io": "#a9188d",\n "Ioke": "#078193",\n "Isabelle": "#FEFE00",\n "Isabelle ROOT": "#FEFE00",\n "J": "#9EEDFF",\n "JAR Manifest": "#b07219",\n "JCL": "#d90e09",\n "JFlex": "#DBCA00",\n "JSON": "#292929",\n "JSON with Comments": "#292929",\n "JSON5": "#267CB9",\n "JSONLD": "#0c479c",\n "JSONiq": "#40d47e",\n "Jac": "#FC792D",\n "Jai": "#ab8b4b",\n "Janet": "#0886a5",\n "Jasmin": "#d03600",\n "Java": "#b07219",\n "Java Properties": "#2A6277",\n "Java Server Pages": "#2A6277",\n "Java Template Engine": "#2A6277",\n "JavaScript": "#f1e05a",\n "JavaScript+ERB": "#f1e05a",\n "Jest Snapshot": "#15c213",\n "JetBrains MPS": "#21D789",\n "Jinja": "#a52a22",\n "Jison": "#56b3cb",\n "Jison Lex": "#56b3cb",\n "Jolie": "#843179",\n "Jsonnet": "#0064bd",\n "Julia": "#a270ba",\n "Julia REPL": "#a270ba",\n "Jupyter Notebook": "#DA5B0B",\n "Just": "#384d54",\n "KCL": "#7ABABF",\n "KDL": "#ffb3b3",\n "KFramework": "#4195c5",\n "KRL": "#28430A",\n "Kaitai Struct": "#773b37",\n "KakouneScript": "#6f8042",\n "KerboScript": "#41adf0",\n "KiCad Layout": "#2f4aab",\n "KiCad Legacy Layout": "#2f4aab",\n "KiCad Schematic": "#2f4aab",\n "KoLmafia ASH": "#B9D9B9",\n "Koka": "#215166",\n "Kotlin": "#A97BFF",\n "LFE": "#4C3023",\n "LLVM": "#185619",\n "LOLCODE": "#cc9900",\n "LSL": "#3d9970",\n "LabVIEW": "#fede06",\n "Lambdapi": "#8027a3",\n "Langium": "#2c8c87",\n "Lark": "#2980B9",\n "Lasso": "#999999",\n "Latte": "#f2a542",\n "Leo": "#C4FFC2",\n "Less": "#1d365d",\n "Lex": "#DBCA00",\n "LigoLANG": "#0e74ff",\n "LilyPond": "#9ccc7c",\n "Liquid": "#67b8de",\n "Liquidsoap": "#990066",\n "Literate Agda": "#315665",\n "Literate CoffeeScript": "#244776",\n "Literate Haskell": "#5e5086",\n "LiveCode Script": "#0c5ba5",\n "LiveScript": "#499886",\n "Logtalk": "#295b9a",\n "LookML": "#652B81",\n "Lua": "#000080",\n "Luau": "#00A2FF",\n "M3U": "#179C7D",\n "MATLAB": "#e16737",\n "MAXScript": "#00a6a6",\n "MDX": "#fcb32c",\n "MLIR": "#5EC8DB",\n "MQL4": "#62A8D6",\n "MQL5": "#4A76B8",\n "MTML": "#b7e1f4",\n "Macaulay2": "#d8ffff",\n "Makefile": "#427819",\n "Mako": "#7e858d",\n "Markdown": "#083fa1",\n "Marko": "#42bff2",\n "Mask": "#f97732",\n "Mathematical Programming System": "#0530ad",\n "Max": "#c4a79c",\n "MeTTa": "#6a5acd",\n "Mercury": "#ff2b2b",\n "Mermaid": "#ff3670",\n "Meson": "#007800",\n "Metal": "#8f14e9",\n "MiniYAML": "#ff1111",\n "MiniZinc": "#06a9e6",\n "Mint": "#02b046",\n "Mirah": "#c7a938",\n "Modelica": "#de1d31",\n "Modula-2": "#10253f",\n "Modula-3": "#223388",\n "Mojo": "#ff4c1f",\n "Monkey C": "#8D6747",\n "MoonBit": "#b92381",\n "MoonScript": "#ff4585",\n "Motoko": "#fbb03b",\n "Motorola 68K Assembly": "#005daa",\n "Move": "#4a137a",\n "Mustache": "#724b3b",\n "NCL": "#28431f",\n "NMODL": "#00356B",\n "NPM Config": "#cb3837",\n "NWScript": "#111522",\n "Nasal": "#1d2c4e",\n "Nearley": "#990000",\n "Nemerle": "#3d3c6e",\n "NetLinx": "#0aa0ff",\n "NetLinx+ERB": "#747faa",\n "NetLogo": "#ff6375",\n "NewLisp": "#87AED7",\n "Nextflow": "#3ac486",\n "Nginx": "#009639",\n "Nickel": "#E0C3FC",\n "Nim": "#ffc200",\n "Nit": "#009917",\n "Nix": "#7e7eff",\n "Noir": "#2f1f49",\n "Nu": "#c9df40",\n "NumPy": "#9C8AF9",\n "Nunjucks": "#3d8137",\n "Nushell": "#4E9906",\n "OASv2-json": "#85ea2d",\n "OASv2-yaml": "#85ea2d",\n "OASv3-json": "#85ea2d",\n "OASv3-yaml": "#85ea2d",\n "OCaml": "#ef7a08",\n "OMNeT++ MSG": "#a0e0a0",\n "OMNeT++ NED": "#08607c",\n "ObjectScript": "#424893",\n "Objective-C": "#438eff",\n "Objective-C++": "#6866fb",\n "Objective-J": "#ff0c5a",\n "Odin": "#60AFFE",\n "Omgrofl": "#cabbff",\n "Opal": "#f7ede0",\n "Open Policy Agent": "#7d9199",\n "OpenAPI Specification v2": "#85ea2d",\n "OpenAPI Specification v3": "#85ea2d",\n "OpenCL": "#ed2e2d",\n "OpenEdge ABL": "#5ce600",\n "OpenQASM": "#AA70FF",\n "OpenSCAD": "#e5cd45",\n "Option List": "#476732",\n "Org": "#77aa99",\n "OverpassQL": "#cce2aa",\n "Oxygene": "#cdd0e3",\n "Oz": "#fab738",\n "P4": "#7055b5",\n "PDDL": "#0d00ff",\n "PEG.js": "#234d6b",\n "PHP": "#4F5D95",\n "PLSQL": "#dad8d8",\n "PLpgSQL": "#336790",\n "POV-Ray SDL": "#6bac65",\n "Pact": "#F7A8B8",\n "Pan": "#cc0000",\n "Papyrus": "#6600cc",\n "Parrot": "#f3ca0a",\n "Pascal": "#E3F171",\n "Pawn": "#dbb284",\n "Pep8": "#C76F5B",\n "Perl": "#0298c3",\n "PicoLisp": "#6067af",\n "PigLatin": "#fcd7de",\n "Pike": "#005390",\n "Pip Requirements": "#FFD343",\n "Pkl": "#6b9543",\n "PlantUML": "#fbbd16",\n "PogoScript": "#d80074",\n "Polar": "#ae81ff",\n "Portugol": "#f8bd00",\n "PostCSS": "#dc3a0c",\n "PostScript": "#da291c",\n "PowerBuilder": "#8f0f8d",\n "PowerShell": "#012456",\n "Praat": "#c8506d",\n "Prisma": "#0c344b",\n "Processing": "#0096D8",\n "Procfile": "#3B2F63",\n "Prolog": "#74283c",\n "Promela": "#de0000",\n "Propeller Spin": "#7fa2a7",\n "Pug": "#a86454",\n "Puppet": "#302B6D",\n "PureBasic": "#5a6986",\n "PureScript": "#1D222D",\n "Pyret": "#ee1e10",\n "Python": "#3572A5",\n "Python console": "#3572A5",\n "Python traceback": "#3572A5",\n "Q#": "#fed659",\n "QML": "#44a51c",\n "Qt Script": "#00b841",\n "Quake": "#882233",\n "QuakeC": "#975777",\n "QuickBASIC": "#008080",\n "Quint": "#9d6ce5",\n "R": "#198CE7",\n "RAML": "#77d9fb",\n "RAScript": "#2C97FA",\n "RBS": "#701516",\n "RDoc": "#701516",\n "REXX": "#d90e09",\n "RMarkdown": "#198ce7",\n "RON": "#a62c00",\n "ROS Interface": "#22314e",\n "RPGLE": "#2BDE21",\n "RUNOFF": "#665a4e",\n "Racket": "#3c5caa",\n "Ragel": "#9d5200",\n "Raku": "#0000fb",\n "Rascal": "#fffaa0",\n "ReScript": "#ed5051",\n "Reason": "#ff5847",\n "ReasonLIGO": "#ff5847",\n "Rebol": "#358a5b",\n "Record Jar": "#0673ba",\n "Red": "#f50000",\n "Regular Expression": "#009a00",\n "Ren\'Py": "#ff7f7f",\n "Rez": "#FFDAB3",\n "Ring": "#2D54CB",\n "Riot": "#A71E49",\n "RobotFramework": "#00c0b5",\n "Roc": "#7c38f5",\n "Rocq Prover": "#d0b68c",\n "Roff": "#ecdebe",\n "Roff Manpage": "#ecdebe",\n "Rouge": "#cc0088",\n "RouterOS Script": "#DE3941",\n "Ruby": "#701516",\n "Rust": "#dea584",\n "SAS": "#B34936",\n "SCSS": "#c6538c",\n "SPARQL": "#0C4597",\n "SQF": "#3F3F3F",\n "SQL": "#e38c00",\n "SQLPL": "#e38c00",\n "SRecode Template": "#348a34",\n "STL": "#373b5e",\n "SVG": "#ff9900",\n "Sail": "#259dd5",\n "SaltStack": "#646464",\n "Sass": "#a53b70",\n "Scala": "#c22d40",\n "Scaml": "#bd181a",\n "Scenic": "#fdc700",\n "Scheme": "#1e4aec",\n "Scilab": "#ca0f21",\n "Self": "#0579aa",\n "ShaderLab": "#222c37",\n "Shell": "#89e051",\n "ShellCheck Config": "#cecfcb",\n "Shen": "#120F14",\n "Simple File Verification": "#C9BFED",\n "Singularity": "#64E6AD",\n "Slang": "#1fbec9",\n "Slash": "#007eff",\n "Slice": "#003fa2",\n "Slim": "#2b2b2b",\n "Slint": "#2379F4",\n "SmPL": "#c94949",\n "Smalltalk": "#596706",\n "Smarty": "#f0c040",\n "Smithy": "#c44536",\n "Snakemake": "#419179",\n "Solidity": "#AA6746",\n "SourcePawn": "#f69e1d",\n "SpiceDB Schema": "#a5318a",\n "Squirrel": "#800000",\n "Stan": "#b2011d",\n "Standard ML": "#dc566d",\n "Starlark": "#76d275",\n "Stata": "#1a5f91",\n "StringTemplate": "#3fb34f",\n "Stylus": "#ff6347",\n "SubRip Text": "#9e0101",\n "SugarSS": "#2fcc9f",\n "SuperCollider": "#46390b",\n "SurrealQL": "#ff00a0",\n "Survex data": "#ffcc99",\n "Svelte": "#ff3e00",\n "Sway": "#00F58C",\n "Sweave": "#198ce7",\n "Swift": "#F05138",\n "SystemVerilog": "#DAE1C2",\n "TI Program": "#A0AA87",\n "TL-Verilog": "#C40023",\n "TLA": "#4b0079",\n "TMDL": "#f0c913",\n "TOML": "#9c4221",\n "TSQL": "#e38c00",\n "TSV": "#237346",\n "TSX": "#3178c6",\n "TXL": "#0178b8",\n "Tact": "#48b5ff",\n "Talon": "#333333",\n "Tcl": "#e4cc98",\n "TeX": "#3D6117",\n "Teal": "#00B1BC",\n "Terra": "#00004c",\n "Terraform Template": "#7b42bb",\n "TextGrid": "#c8506d",\n "TextMate Properties": "#df66e4",\n "Textile": "#ffe7ac",\n "Thrift": "#D12127",\n "Toit": "#c2c9fb",\n "Tools": "#a371f7",\n "Tor Config": "#59316b",\n "Tree-sitter Query": "#8ea64c",\n "Turing": "#cf142b",\n "Twig": "#c1d026",\n "TypeScript": "#3178c6",\n "TypeSpec": "#4A3665",\n "Typst": "#239dad",\n "Unified Parallel C": "#4e3617",\n "Unity3D Asset": "#222c37",\n "Uno": "#9933cc",\n "UnrealScript": "#a54c4d",\n "Untyped Plutus Core": "#36adbd",\n "UrWeb": "#ccccee",\n "V": "#4f87c4",\n "VBA": "#867db1",\n "VBScript": "#15dcdc",\n "VCL": "#148AA8",\n "VHDL": "#adb2cb",\n "Vala": "#a56de2",\n "Valve Data Format": "#f26025",\n "Velocity Template Language": "#507cff",\n "Vento": "#ff0080",\n "Verilog": "#b2b7f8",\n "Vim Help File": "#199f4b",\n "Vim Script": "#199f4b",\n "Vim Snippet": "#199f4b",\n "Visual Basic .NET": "#945db7",\n "Visual Basic 6.0": "#2c6353",\n "Volt": "#1F1F1F",\n "Vue": "#41b883",\n "Vyper": "#9F4CF2",\n "WDL": "#42f1f4",\n "WGSL": "#1a5e9a",\n "Web Ontology Language": "#5b70bd",\n "WebAssembly": "#04133b",\n "WebAssembly Interface Type": "#6250e7",\n "Whiley": "#d5c397",\n "Wikitext": "#fc5757",\n "Windows Registry Entries": "#52d5ff",\n "Witcher Script": "#ff0000",\n "Wolfram Language": "#dd1100",\n "Wollok": "#a23738",\n "World of Warcraft Addon Data": "#f7e43f",\n "Wren": "#383838",\n "X10": "#4B6BEF",\n "XC": "#99DA07",\n "XML": "#0060ac",\n "XML Property List": "#0060ac",\n "XQuery": "#5232e7",\n "XSLT": "#EB8CEB",\n "Xmake": "#22a079",\n "Xojo": "#81bd41",\n "Xonsh": "#285EEF",\n "Xtend": "#24255d",\n "YAML": "#cb171e",\n "YARA": "#220000",\n "YASnippet": "#32AB90",\n "Yacc": "#4B6C4B",\n "Yul": "#794932",\n "ZAP": "#0d665e",\n "ZIL": "#dc75e5",\n "ZenScript": "#00BCD1",\n "Zephir": "#118f9e",\n "Zig": "#ec915c",\n "Zimpl": "#d67711",\n "Zmodel": "#ff7100",\n "crontab": "#ead7ac",\n "eC": "#913960",\n "fish": "#4aae47",\n "hoon": "#00b171",\n "iCalendar": "#ec564c",\n "jq": "#c7254e",\n "kvlang": "#1da6e0",\n "mIRC Script": "#3d57c3",\n "mcfunction": "#E22837",\n "mdsvex": "#5f9ea0",\n "mupad": "#244963",\n "nanorc": "#2d004d",\n "nesC": "#94B0C7",\n "ooc": "#b0b77e",\n "q": "#0040cd",\n "reStructuredText": "#141414",\n "sed": "#64b970",\n "templ": "#66D0DD",\n "vCard": "#ee2647",\n "wisp": "#7582D1",\n "xBase": "#403a40"\n },\n "ext": {\n "1": "Roff",\n "1in": "Roff",\n "1m": "Roff",\n "1x": "Roff",\n "2": "Roff",\n "2da": "2-Dimensional Array",\n "3": "Roff",\n "3in": "Roff",\n "3m": "Roff",\n "3p": "Roff",\n "3pm": "Roff",\n "3qt": "Roff",\n "3x": "Roff",\n "4": "Roff",\n "4dform": "JSON",\n "4dm": "4D",\n "4dproject": "JSON",\n "4gl": "Genero 4gl",\n "4th": "Forth",\n "5": "Roff",\n "6": "Roff",\n "6pl": "Raku",\n "6pm": "Raku",\n "7": "Roff",\n "8": "Roff",\n "8xp": "TI Program",\n "8xp.txt": "TI Program",\n "9": "Roff",\n "_coffee": "CoffeeScript",\n "_js": "JavaScript",\n "_ls": "LiveScript",\n "a51": "Assembly",\n "abap": "ABAP",\n "action": "ROS Interface",\n "ada": "Ada",\n "adb": "Ada",\n "adml": "XML",\n "admx": "XML",\n "ado": "Stata",\n "adoc": "AsciiDoc",\n "adp": "Tcl",\n "ads": "Ada",\n "afm": "Adobe Font Metrics",\n "agc": "Assembly",\n "agda": "Agda",\n "ahk": "AutoHotkey",\n "ahkl": "AutoHotkey",\n "aidl": "AIDL",\n "aj": "AspectJ",\n "ak": "Aiken",\n "al": "AL",\n "alg": "ALGOL",\n "als": "Alloy",\n "ampl": "AMPL",\n "angelscript": "AngelScript",\n "anim": "Unity3D Asset",\n "ant": "XML",\n "antlers.html": "Antlers",\n "antlers.php": "Antlers",\n "antlers.xml": "Antlers",\n "apacheconf": "ApacheConf",\n "apex": "Apex",\n "apib": "API Blueprint",\n "apl": "APL",\n "app": "Erlang",\n "app.src": "Erlang",\n "applescript": "AppleScript",\n "arc": "Arc",\n "arr": "Pyret",\n "as": "ActionScript",\n "asax": "ASP.NET",\n "asc": "AGS Script",\n "asciidoc": "AsciiDoc",\n "ascx": "ASP.NET",\n "asd": "Common Lisp",\n "asddls": "ABAP CDS",\n "ash": "KoLmafia ASH",\n "ashx": "ASP.NET",\n "asm": "Assembly",\n "asmx": "ASP.NET",\n "asp": "Classic ASP",\n "aspx": "ASP.NET",\n "asset": "Unity3D Asset",\n "astro": "Astro",\n "asy": "Asymptote",\n "au3": "AutoIt",\n "aug": "Augeas",\n "auk": "Awk",\n "aux": "TeX",\n "avdl": "Avro IDL",\n "avsc": "JSON",\n "aw": "PHP",\n "awk": "Awk",\n "axaml": "XML",\n "axd": "ASP.NET",\n "axi": "NetLinx",\n "axi.erb": "NetLinx+ERB",\n "axml": "XML",\n "axs": "NetLinx",\n "axs.erb": "NetLinx+ERB",\n "b": "Brainfuck",\n "bal": "Ballerina",\n "bas": "B4X",\n "bash": "Shell",\n "bat": "Batchfile",\n "bats": "Shell",\n "bb": "BitBake",\n "bbappend": "BitBake",\n "bbclass": "BitBake",\n "bbx": "TeX",\n "bdy": "PLSQL",\n "be": "Berry",\n "bf": "Beef",\n "bi": "FreeBASIC",\n "bib": "TeX",\n "bibtex": "TeX",\n "bicep": "Bicep",\n "bicepparam": "Bicep",\n "bison": "Yacc",\n "blade": "Blade",\n "blade.php": "Blade",\n "bmx": "BlitzMax",\n "bones": "JavaScript",\n "boo": "Boo",\n "boot": "Clojure",\n "bpl": "Boogie",\n "bqn": "BQN",\n "brd": "KiCad Legacy Layout",\n "brs": "Brightscript",\n "bru": "Bru",\n "bs": "Bluespec",\n "bsl": "1C Enterprise",\n "bst": "BuildStream",\n "bsv": "Bluespec",\n "builder": "Ruby",\n "builds": "XML",\n "bzl": "Starlark",\n "c": "C",\n "c++": "C++",\n "c3": "C3",\n "cabal": "Cabal Config",\n "caddyfile": "Caddyfile",\n "cairo": "Cairo",\n "cake": "C#",\n "capnp": "Cap\'n Proto",\n "carbon": "Carbon",\n "cats": "C",\n "cbx": "TeX",\n "cc": "C++",\n "ccproj": "XML",\n "ccxml": "XML",\n "cdc": "Cadence",\n "cdf": "Wolfram Language",\n "cds": "CAP CDS",\n "ceylon": "Ceylon",\n "cfc": "ColdFusion",\n "cfg": "HAProxy",\n "cfm": "ColdFusion",\n "cfml": "ColdFusion",\n "cgi": "Perl",\n "cginc": "HLSL",\n "ch": "xBase",\n "chpl": "Chapel",\n "circom": "Circom",\n "cirru": "Cirru",\n "cj": "Cangjie",\n "cjs": "JavaScript",\n "cjsx": "CoffeeScript",\n "ck": "ChucK",\n "cl": "C",\n "cl2": "Clojure",\n "clar": "Clarity",\n "click": "Click",\n "clixml": "XML",\n "clj": "Clojure",\n "cljc": "Clojure",\n "cljs": "Clojure",\n "cljs.hl": "Clojure",\n "cljscm": "Clojure",\n "cljx": "Clojure",\n "clp": "CLIPS",\n "cls": "Apex",\n "clue": "Clue",\n "clw": "Clarion",\n "cmake": "CMake",\n "cmake.in": "CMake",\n "cmd": "Batchfile",\n "cmp": "Gerber Image",\n "cnc": "G-code",\n "cnf": "INI",\n "cocci": "SmPL",\n "code-snippets": "JSON",\n "code-workspace": "JSON",\n "coffee": "CoffeeScript",\n "coffee.md": "CoffeeScript",\n "command": "Shell",\n "containerfile": "Dockerfile",\n "cook": "Cooklang",\n "coq": "Rocq Prover",\n "cp": "Component Pascal",\n "cpp": "C++",\n "cppm": "C++",\n "cproject": "XML",\n "cps": "Component Pascal",\n "cql": "CQL",\n "cr": "Crystal",\n "cs": "C#",\n "cs.pp": "C#",\n "csc": "GSC",\n "cscfg": "XML",\n "csd": "Csound Document",\n "csdef": "XML",\n "cshtml": "HTML",\n "csl": "XML",\n "cson": "CSON",\n "csproj": "XML",\n "css": "CSS",\n "csv": "CSV",\n "csx": "C#",\n "ct": "XML",\n "ctl": "Visual Basic 6.0",\n "ctp": "PHP",\n "cts": "TypeScript",\n "cu": "Cuda",\n "cue": "CUE",\n "cuh": "Cuda",\n "curry": "Curry",\n "cwl": "Common Workflow Language",\n "cxx": "C++",\n "cylc": "INI",\n "cyp": "Cypher",\n "cypher": "Cypher",\n "d": "D",\n "d2": "D2",\n "dae": "COLLADA",\n "darcspatch": "Darcs Patch",\n "dart": "Dart",\n "das": "Daslang",\n "dats": "ATS",\n "db2": "SQLPL",\n "dcl": "Clean",\n "ddl": "PLSQL",\n "decls": "BlitzBasic",\n "depproj": "XML",\n "dfm": "Pascal",\n "dfy": "Dafny",\n "dhall": "Dhall",\n "di": "D",\n "dita": "XML",\n "ditamap": "XML",\n "ditaval": "XML",\n "djs": "Dogescript",\n "dll.config": "XML",\n "dlm": "IDL",\n "dm": "DM",\n "do": "Stata",\n "dockerfile": "Dockerfile",\n "dof": "INI",\n "doh": "Stata",\n "dot": "Graphviz (DOT)",\n "dotsettings": "XML",\n "dpatch": "Darcs Patch",\n "dpr": "Pascal",\n "druby": "Mirah",\n "dsc": "DenizenScript",\n "dsp": "Faust",\n "dsr": "Visual Basic 6.0",\n "dtx": "TeX",\n "duby": "Mirah",\n "dwl": "DataWeave",\n "dyalog": "APL",\n "dyl": "Dylan",\n "dylan": "Dylan",\n "e": "E",\n "eb": "Python",\n "ebuild": "Shell",\n "ec": "eC",\n "ecl": "ECL",\n "eclass": "Shell",\n "eclxml": "ECL",\n "ecr": "HTML",\n "ect": "EJS",\n "edge": "Edge",\n "edgeql": "EdgeQL",\n "editorconfig": "INI",\n "eh": "eC",\n "ejs": "EJS",\n "ejs.t": "EJS",\n "el": "Emacs Lisp",\n "eliom": "OCaml",\n "eliomi": "OCaml",\n "elm": "Elm",\n "elv": "Elvish",\n "em": "EmberScript",\n "emacs": "Emacs Lisp",\n "emacs.desktop": "Emacs Lisp",\n "emberscript": "EmberScript",\n "env": "Dotenv",\n "epj": "JavaScript",\n "eps": "PostScript",\n "epsi": "PostScript",\n "eq": "EQ",\n "erb": "HTML",\n "erb.deface": "HTML",\n "erl": "Erlang",\n "es": "Erlang",\n "es6": "JavaScript",\n "escript": "Erlang",\n "esdl": "EdgeQL",\n "ex": "Elixir",\n "exs": "Elixir",\n "eye": "Ruby",\n "f": "Fortran",\n "f03": "Fortran",\n "f08": "Fortran",\n "f77": "Fortran",\n "f90": "Fortran",\n "f95": "Fortran",\n "factor": "Factor",\n "fan": "Fantom",\n "fancypack": "Fancy",\n "fbs": "FlatBuffers",\n "fcgi": "Lua",\n "feature": "Gherkin",\n "filters": "XML",\n "fir": "FIRRTL",\n "fish": "Shell",\n "flex": "Lex",\n "flf": "FIGlet Font",\n "flix": "Flix",\n "flux": "FLUX",\n "fnc": "PLSQL",\n "fnl": "Fennel",\n "for": "Fortran",\n "forth": "Forth",\n "fp": "GLSL",\n "fpp": "Fortran",\n "fr": "Frege",\n "frag": "GLSL",\n "frg": "GLSL",\n "frm": "VBA",\n "frt": "Forth",\n "fs": "F#",\n "fsh": "GLSL",\n "fshader": "GLSL",\n "fsi": "F#",\n "fsproj": "XML",\n "fst": "F*",\n "fsti": "F*",\n "fsx": "F#",\n "fth": "Forth",\n "ftl": "Fluent",\n "ftlh": "FreeMarker",\n "fun": "Standard ML",\n "fut": "Futhark",\n "fx": "FLUX",\n "fxh": "HLSL",\n "fxml": "XML",\n "fy": "Fancy",\n "g": "G-code",\n "g4": "ANTLR",\n "gaml": "GAML",\n "gap": "GAP",\n "gawk": "Awk",\n "gbl": "Gerber Image",\n "gbo": "Gerber Image",\n "gbp": "Gerber Image",\n "gbr": "Gerber Image",\n "gbs": "Gerber Image",\n "gco": "G-code",\n "gcode": "G-code",\n "gd": "GDScript",\n "gdnlib": "Godot Resource",\n "gdns": "Godot Resource",\n "gdshader": "GDShader",\n "gdshaderinc": "GDShader",\n "ged": "GEDCOM",\n "gemspec": "Ruby",\n "geo": "GLSL",\n "geojson": "JSON",\n "geom": "GLSL",\n "gf": "Grammatical Framework",\n "gi": "GAP",\n "gitconfig": "INI",\n "gitignore": "Ignore List",\n "gjs": "JavaScript",\n "gko": "Gerber Image",\n "glade": "XML",\n "gleam": "Gleam",\n "glf": "Glyph",\n "glsl": "GLSL",\n "glslf": "GLSL",\n "glslv": "GLSL",\n "gltf": "JSON",\n "gmi": "Gemini",\n "gml": "Game Maker Language",\n "gms": "GAMS",\n "gmx": "XML",\n "gnu": "Gnuplot",\n "gnuplot": "Gnuplot",\n "go": "Go",\n "god": "Ruby",\n "gohtml": "Go Template",\n "golo": "Golo",\n "gotmpl": "Go Template",\n "gp": "Gnuplot",\n "gpb": "Gerber Image",\n "gpt": "Gerber Image",\n "gpx": "XML",\n "gql": "GraphQL",\n "grace": "Grace",\n "gradle": "Gradle",\n "gradle.kts": "Gradle",\n "graphql": "GraphQL",\n "graphqls": "GraphQL",\n "groovy": "Groovy",\n "grt": "Groovy",\n "grxml": "XML",\n "gs": "Genie",\n "gsc": "GSC",\n "gsh": "GSC",\n "gshader": "GLSL",\n "gsp": "Groovy",\n "gst": "Gosu",\n "gsx": "Gosu",\n "gtl": "Gerber Image",\n "gto": "Gerber Image",\n "gtp": "Gerber Image",\n "gtpl": "Groovy",\n "gts": "TypeScript",\n "gv": "Graphviz (DOT)",\n "gvy": "Groovy",\n "gyp": "Python",\n "gypi": "Python",\n "h": "C",\n "h++": "C++",\n "h.in": "C",\n "ha": "Hare",\n "hack": "Hack",\n "haml": "Haml",\n "haml.deface": "Haml",\n "handlebars": "Handlebars",\n "har": "JSON",\n "hats": "ATS",\n "hb": "Harbour",\n "hbs": "Handlebars",\n "hc": "HolyC",\n "hcl": "HCL",\n "heex": "HTML",\n "hh": "C++",\n "hhi": "Hack",\n "hic": "Clojure",\n "hip": "HIP",\n "hlsl": "HLSL",\n "hlsli": "HLSL",\n "hocon": "HOCON",\n "hoon": "hoon",\n "hpp": "C++",\n "hqf": "SQF",\n "hql": "HiveQL",\n "hrl": "Erlang",\n "hs": "Haskell",\n "hs-boot": "Haskell",\n "hsc": "Haskell",\n "hta": "HTML",\n "htm": "HTML",\n "html": "HTML",\n "html.eex": "HTML",\n "html.hl": "HTML",\n "html.tmpl": "Go Template",\n "http": "HTTP",\n "hurl": "Hurl",\n "hx": "Haxe",\n "hxml": "HXML",\n "hxsl": "Haxe",\n "hxx": "C++",\n "hy": "Hy",\n "hzp": "XML",\n "i": "Assembly",\n "i3": "Modula-3",\n "ical": "iCalendar",\n "ice": "Slice",\n "iced": "CoffeeScript",\n "icl": "Clean",\n "icls": "XML",\n "ics": "iCalendar",\n "idc": "C",\n "idr": "Idris",\n "ig": "Modula-3",\n "ihlp": "Stata",\n "ijm": "ImageJ Macro",\n "ijs": "J",\n "ik": "Ioke",\n "il": "IL Assembly",\n "ily": "LilyPond",\n "imba": "Imba",\n "iml": "XML",\n "inc": "Assembly",\n "ini": "INI",\n "inl": "C++",\n "ino": "C++",\n "ins": "TeX",\n "intr": "Dylan",\n "io": "Io",\n "iol": "Jolie",\n "ipf": "IGOR Pro",\n "ipp": "C++",\n "ipynb": "Jupyter Notebook",\n "isl": "Inno Setup",\n "ispc": "ISPC",\n "iss": "Inno Setup",\n "iuml": "PlantUML",\n "ivy": "XML",\n "ixx": "C++",\n "j": "Jasmin",\n "j2": "Jinja",\n "jac": "Jac",\n "jade": "Pug",\n "jai": "Jai",\n "jake": "JavaScript",\n "janet": "Janet",\n "jav": "Java",\n "java": "Java",\n "javascript": "JavaScript",\n "jbuilder": "Ruby",\n "jcl": "JCL",\n "jelly": "XML",\n "jflex": "Lex",\n "jinja": "Jinja",\n "jinja2": "Jinja",\n "jison": "Yacc",\n "jisonlex": "Lex",\n "jl": "Julia",\n "jq": "JSONiq",\n "js": "JavaScript",\n "js.erb": "JavaScript",\n "jsb": "JavaScript",\n "jscad": "JavaScript",\n "jsfl": "JavaScript",\n "jsh": "Java",\n "jslib": "JavaScript",\n "jsm": "JavaScript",\n "json": "JSON",\n "json-tmlanguage": "JSON",\n "json.example": "JSON",\n "json5": "JSON5",\n "jsonc": "JSON",\n "jsonl": "JSON",\n "jsonld": "JSONLD",\n "jsonnet": "Jsonnet",\n "jsp": "Java",\n "jspre": "JavaScript",\n "jsproj": "XML",\n "jss": "JavaScript",\n "jst": "EJS",\n "jsx": "JavaScript",\n "jte": "Java",\n "just": "Just",\n "k": "KCL",\n "kak": "KakouneScript",\n "kdl": "KDL",\n "kicad_mod": "KiCad Layout",\n "kicad_pcb": "KiCad Layout",\n "kicad_sch": "KiCad Schematic",\n "kicad_sym": "KiCad Schematic",\n "kicad_wks": "KiCad Layout",\n "kid": "Genshi",\n "kk": "Koka",\n "kml": "XML",\n "kojo": "Scala",\n "krl": "KRL",\n "ks": "KerboScript",\n "ksh": "Shell",\n "ksy": "Kaitai Struct",\n "kt": "Kotlin",\n "ktm": "Kotlin",\n "kts": "Kotlin",\n "kv": "kvlang",\n "l": "Common Lisp",\n "lagda": "Agda",\n "langium": "Langium",\n "lark": "Lark",\n "las": "Lasso",\n "lasso": "Lasso",\n "lasso8": "Lasso",\n "lasso9": "Lasso",\n "latte": "Latte",\n "launch": "XML",\n "lbx": "TeX",\n "leex": "HTML",\n "lektorproject": "INI",\n "leo": "Leo",\n "less": "Less",\n "lex": "Lex",\n "lfe": "LFE",\n "lgt": "Logtalk",\n "lhs": "Haskell",\n "libsonnet": "Jsonnet",\n "lid": "Dylan",\n "lidr": "Idris",\n "ligo": "LigoLANG",\n "linq": "C#",\n "liq": "Liquidsoap",\n "liquid": "Liquid",\n "lisp": "Common Lisp",\n "litcoffee": "CoffeeScript",\n "livecodescript": "LiveCode Script",\n "livemd": "Markdown",\n "lkml": "LookML",\n "ll": "LLVM",\n "lmi": "Python",\n "logtalk": "Logtalk",\n "lol": "LOLCODE",\n "lookml": "LookML",\n "lp": "Answer Set Programming",\n "lpr": "Pascal",\n "ls": "LiveScript",\n "lsl": "LSL",\n "lslp": "LSL",\n "lsp": "Common Lisp",\n "ltx": "TeX",\n "lua": "Lua",\n "luau": "Luau",\n "lvclass": "LabVIEW",\n "lvlib": "LabVIEW",\n "lvproj": "LabVIEW",\n "ly": "LilyPond",\n "m": "Objective-C",\n "m2": "Macaulay2",\n "m3": "Modula-3",\n "m3u": "M3U",\n "m3u8": "M3U",\n "ma": "Wolfram Language",\n "mak": "Makefile",\n "make": "Makefile",\n "makefile": "Makefile",\n "mako": "Mako",\n "man": "Roff",\n "mao": "Mako",\n "markdown": "Markdown",\n "marko": "Marko",\n "mask": "Mask",\n "mat": "Unity3D Asset",\n "mata": "Stata",\n "matah": "Stata",\n "mathematica": "Wolfram Language",\n "matlab": "MATLAB",\n "mawk": "Awk",\n "maxhelp": "Max",\n "maxpat": "Max",\n "maxproj": "Max",\n "mbt": "MoonBit",\n "mc": "Monkey C",\n "mcfunction": "mcfunction",\n "mch": "B (Formal Method)",\n "mcmeta": "JSON",\n "mcr": "MAXScript",\n "md": "Markdown",\n "mdoc": "Roff",\n "mdown": "Markdown",\n "mdpolicy": "XML",\n "mdwn": "Markdown",\n "mdx": "MDX",\n "me": "Roff",\n "mediawiki": "Wikitext",\n "mermaid": "Mermaid",\n "meta": "Unity3D Asset",\n "metal": "Metal",\n "metta": "MeTTa",\n "mg": "Modula-3",\n "mint": "Mint",\n "mir": "YAML",\n "mirah": "Mirah",\n "mjml": "XML",\n "mjs": "JavaScript",\n "mk": "Makefile",\n "mkd": "Markdown",\n "mkdn": "Markdown",\n "mkdown": "Markdown",\n "mkfile": "Makefile",\n "mkii": "TeX",\n "mkiv": "TeX",\n "mkvi": "TeX",\n "ml": "OCaml",\n "ml4": "OCaml",\n "mli": "OCaml",\n "mligo": "LigoLANG",\n "mlir": "MLIR",\n "mll": "OCaml",\n "mly": "OCaml",\n "mm": "Objective-C++",\n "mmd": "Mermaid",\n "mo": "Modelica",\n "mod": "Modula-2",\n "mojo": "Mojo",\n "moo": "Mercury",\n "moon": "MoonScript",\n "move": "Move",\n "mpl": "JetBrains MPS",\n "mps": "JetBrains MPS",\n "mq4": "MQL4",\n "mq5": "MQL5",\n "mqh": "MQL4",\n "mrc": "mIRC Script",\n "ms": "MAXScript",\n "msd": "JetBrains MPS",\n "msg": "OMNeT++ MSG",\n "mspec": "Ruby",\n "mt": "Wolfram Language",\n "mtml": "MTML",\n "mts": "TypeScript",\n "mu": "mupad",\n "mud": "ZIL",\n "mustache": "Mustache",\n "mxml": "XML",\n "mxt": "Max",\n "mysql": "SQL",\n "mzn": "MiniZinc",\n "n": "Nemerle",\n "nanorc": "INI",\n "nas": "Nasal",\n "nasm": "Assembly",\n "natvis": "XML",\n "nawk": "Awk",\n "nb": "Wolfram Language",\n "nbp": "Wolfram Language",\n "nc": "nesC",\n "ncl": "NCL",\n "ndproj": "XML",\n "ne": "Nearley",\n "nearley": "Nearley",\n "ned": "OMNeT++ NED",\n "nf": "Nextflow",\n "nginx": "Nginx",\n "nginxconf": "Nginx",\n "nim": "Nim",\n "nim.cfg": "Nim",\n "nimble": "Nim",\n "nimrod": "Nim",\n "nims": "Nim",\n "nit": "Nit",\n "nix": "Nix",\n "njk": "Nunjucks",\n "njs": "JavaScript",\n "nl": "NewLisp",\n "nlogo": "NetLogo",\n "nomad": "HCL",\n "nproj": "XML",\n "nqp": "Raku",\n "nr": "Noir",\n "nse": "Lua",\n "nss": "NWScript",\n "nu": "Nu",\n "numpy": "Python",\n "numpyw": "Python",\n "numsc": "Python",\n "nuspec": "XML",\n "nut": "Squirrel",\n "ny": "Common Lisp",\n "odd": "XML",\n "odin": "Odin",\n "ol": "Jolie",\n "omgrofl": "Omgrofl",\n "ooc": "ooc",\n "opal": "Opal",\n "opencl": "C",\n "orc": "Csound",\n "org": "Org",\n "os": "1C Enterprise",\n "osm": "XML",\n "outjob": "Altium Designer",\n "overpassql": "OverpassQL",\n "owl": "Web Ontology Language",\n "oxygene": "Oxygene",\n "oz": "Oz",\n "p": "OpenEdge ABL",\n "p4": "P4",\n "p6": "Raku",\n "p6l": "Raku",\n "p6m": "Raku",\n "p8": "Lua",\n "pac": "JavaScript",\n "pact": "Pact",\n "pan": "Pan",\n "parrot": "Parrot",\n "pas": "Pascal",\n "pascal": "Pascal",\n "pat": "Max",\n "pb": "PureBasic",\n "pbi": "PureBasic",\n "pbt": "PowerBuilder",\n "pcbdoc": "Altium Designer",\n "pck": "PLSQL",\n "pcss": "CSS",\n "pd_lua": "Lua",\n "pddl": "PDDL",\n "pde": "Processing",\n "peggy": "PEG.js",\n "pegjs": "PEG.js",\n "pep": "Pep8",\n "per": "Genero per",\n "perl": "Perl",\n "pfa": "PostScript",\n "pgsql": "PLpgSQL",\n "ph": "Perl",\n "php": "PHP",\n "php3": "PHP",\n "php4": "PHP",\n "php5": "PHP",\n "phps": "PHP",\n "phpt": "PHP",\n "phtml": "HTML",\n "pig": "PigLatin",\n "pike": "Pike",\n "pkb": "PLSQL",\n "pkgproj": "XML",\n "pkl": "Pkl",\n "pks": "PLSQL",\n "pl": "Perl",\n "pl6": "Raku",\n "plantuml": "PlantUML",\n "plb": "PLSQL",\n "plist": "XML",\n "plot": "Gnuplot",\n "pls": "PLSQL",\n "plsql": "PLSQL",\n "plt": "Gnuplot",\n "pluginspec": "Ruby",\n "plx": "Perl",\n "pm": "Perl",\n "pm6": "Raku",\n "pml": "Promela",\n "pmod": "Pike",\n "po": "Gettext Catalog",\n "podsl": "Common Lisp",\n "podspec": "Ruby",\n "pogo": "PogoScript",\n "polar": "Polar",\n "por": "Portugol",\n "postcss": "CSS",\n "pot": "Gettext Catalog",\n "pov": "POV-Ray SDL",\n "pp": "Puppet",\n "pprx": "REXX",\n "praat": "Praat",\n "prawn": "Ruby",\n "prc": "PLSQL",\n "prefab": "Unity3D Asset",\n "prefs": "INI",\n "prg": "xBase",\n "prisma": "Prisma",\n "prjpcb": "Altium Designer",\n "pro": "Prolog",\n "proj": "XML",\n "prolog": "Prolog",\n "properties": "Java Properties",\n "props": "XML",\n "prw": "xBase",\n "ps": "PostScript",\n "ps1": "PowerShell",\n "ps1xml": "XML",\n "psc": "Papyrus",\n "psc1": "XML",\n "psd1": "PowerShell",\n "psgi": "Perl",\n "psm1": "PowerShell",\n "pt": "XML",\n "pubxml": "XML",\n "pug": "Pug",\n "puml": "PlantUML",\n "purs": "PureScript",\n "pwn": "Pawn",\n "pxd": "Cython",\n "pxi": "Cython",\n "py": "Python",\n "py3": "Python",\n "pyde": "Python",\n "pyi": "Python",\n "pyp": "Python",\n "pyt": "Python",\n "pytb": "Python",\n "pyw": "Python",\n "pyx": "Cython",\n "q": "HiveQL",\n "qasm": "OpenQASM",\n "qbs": "QML",\n "qc": "QuakeC",\n "qhelp": "XML",\n "ql": "CodeQL",\n "qll": "CodeQL",\n "qmd": "RMarkdown",\n "qml": "QML",\n "qnt": "Quint",\n "qs": "Q#",\n "r": "R",\n "r2": "Rebol",\n "r3": "Rebol",\n "rabl": "Ruby",\n "rake": "Ruby",\n "raku": "Raku",\n "rakumod": "Raku",\n "raml": "RAML",\n "rascript": "RAScript",\n "razor": "HTML",\n "rb": "Ruby",\n "rbi": "Ruby",\n "rbs": "Ruby",\n "rbuild": "Ruby",\n "rbw": "Ruby",\n "rbx": "Ruby",\n "rbxs": "Lua",\n "rchit": "GLSL",\n "rd": "R",\n "rdf": "XML",\n "rdoc": "RDoc",\n "re": "Reason",\n "reb": "Rebol",\n "rebol": "Rebol",\n "red": "Red",\n "reds": "Red",\n "reek": "YAML",\n "reg": "Windows Registry Entries",\n "regex": "Regular Expression",\n "regexp": "Regular Expression",\n "rego": "Open Policy Agent",\n "rei": "Reason",\n "religo": "LigoLANG",\n "res": "ReScript",\n "resi": "ReScript",\n "resource": "RobotFramework",\n "rest": "reStructuredText",\n "rest.txt": "reStructuredText",\n "resx": "XML",\n "rex": "REXX",\n "rexx": "REXX",\n "rg": "Rouge",\n "rhtml": "HTML",\n "ring": "Ring",\n "riot": "Riot",\n "rkt": "Racket",\n "rktd": "Racket",\n "rktl": "Racket",\n "rl": "Ragel",\n "rmd": "RMarkdown",\n "rmiss": "GLSL",\n "rnh": "RUNOFF",\n "rno": "RUNOFF",\n "rnw": "Sweave",\n "robot": "RobotFramework",\n "roc": "Roc",\n "rockspec": "Lua",\n "roff": "Roff",\n "ron": "RON",\n "ronn": "Markdown",\n "rpgle": "RPGLE",\n "rpy": "Ren\'Py",\n "rq": "SPARQL",\n "rs": "Rust",\n "rs.in": "Rust",\n "rsc": "Rascal",\n "rss": "XML",\n "rst": "reStructuredText",\n "rst.txt": "reStructuredText",\n "rsx": "R",\n "ru": "Ruby",\n "ruby": "Ruby",\n "rviz": "YAML",\n "s": "Assembly",\n "sail": "Sail",\n "sarif": "JSON",\n "sas": "SAS",\n "sass": "Sass",\n "sats": "ATS",\n "sbatch": "Shell",\n "sbt": "Scala",\n "sc": "SuperCollider",\n "scad": "OpenSCAD",\n "scala": "Scala",\n "scaml": "Scaml",\n "scd": "SuperCollider",\n "sce": "Scilab",\n "scenic": "Scenic",\n "sch": "Scheme",\n "schdoc": "Altium Designer",\n "sci": "Scilab",\n "scm": "Scheme",\n "sco": "Csound Score",\n "scpt": "AppleScript",\n "scrbl": "Racket",\n "scss": "SCSS",\n "scxml": "XML",\n "sdc": "Tcl",\n "sed": "sed",\n "self": "Self",\n "sexp": "Common Lisp",\n "sfproj": "XML",\n "sfv": "Simple File Verification",\n "sh": "Shell",\n "sh.in": "Shell",\n "shader": "ShaderLab",\n "shen": "Shen",\n "shproj": "XML",\n "sig": "Standard ML",\n "sj": "Objective-J",\n "sjs": "JavaScript",\n "sl": "Slash",\n "slang": "Slang",\n "sld": "Scheme",\n "slim": "Slim",\n "slint": "Slint",\n "slnx": "XML",\n "sls": "SaltStack",\n "slurm": "Shell",\n "sma": "Pawn",\n "smithy": "Smithy",\n "smk": "Python",\n "sml": "Standard ML",\n "snakefile": "Python",\n "snap": "Jest Snapshot",\n "snip": "Vim Snippet",\n "snippet": "Vim Snippet",\n "snippets": "Vim Snippet",\n "sol": "Solidity",\n "soy": "Closure Templates",\n "sp": "SourcePawn",\n "sparql": "SPARQL",\n "spc": "PLSQL",\n "spec": "Python",\n "spin": "Propeller Spin",\n "sps": "Scheme",\n "sqf": "SQF",\n "sql": "SQL",\n "sqlrpgle": "RPGLE",\n "sra": "PowerBuilder",\n "srdf": "XML",\n "srt": "SRecode Template",\n "sru": "PowerBuilder",\n "srv": "ROS Interface",\n "srw": "PowerBuilder",\n "ss": "Scheme",\n "ssjs": "JavaScript",\n "sss": "SugarSS",\n "st": "Smalltalk",\n "stan": "Stan",\n "star": "Starlark",\n "sthlp": "Stata",\n "stl": "STL",\n "story": "Gherkin",\n "storyboard": "XML",\n "sttheme": "XML",\n "sty": "TeX",\n "styl": "Stylus",\n "sublime-build": "JSON",\n "sublime-color-scheme": "JSON",\n "sublime-commands": "JSON",\n "sublime-completions": "JSON",\n "sublime-keymap": "JSON",\n "sublime-macro": "JSON",\n "sublime-menu": "JSON",\n "sublime-mousemap": "JSON",\n "sublime-project": "JSON",\n "sublime-settings": "JSON",\n "sublime-snippet": "XML",\n "sublime-syntax": "YAML",\n "sublime-theme": "JSON",\n "sublime-workspace": "JSON",\n "sublime_metrics": "JSON",\n "sublime_session": "JSON",\n "surql": "SurrealQL",\n "sv": "SystemVerilog",\n "svelte": "Svelte",\n "svg": "SVG",\n "svh": "SystemVerilog",\n "svx": "mdsvex",\n "sw": "Sway",\n "swift": "Swift",\n "syntax": "YAML",\n "t": "Perl",\n "tab": "SQL",\n "tac": "Python",\n "tact": "Tact",\n "tag": "Java",\n "talon": "Talon",\n "targets": "XML",\n "tcc": "C++",\n "tcl": "Tcl",\n "tcl.in": "Tcl",\n "templ": "templ",\n "tesc": "GLSL",\n "tese": "GLSL",\n "tex": "TeX",\n "textgrid": "TextGrid",\n "textile": "Textile",\n "tf": "HCL",\n "tfstate": "JSON",\n "tfstate.backup": "JSON",\n "tftpl": "HCL",\n "tfvars": "HCL",\n "thor": "Ruby",\n "thrift": "Thrift",\n "thy": "Isabelle",\n "tl": "Teal",\n "tla": "TLA",\n "tlv": "TL-Verilog",\n "tm": "Tcl",\n "tmac": "Roff",\n "tmcommand": "XML",\n "tmdl": "TMDL",\n "tml": "XML",\n "tmlanguage": "XML",\n "tmpl": "Go Template",\n "tmpreferences": "XML",\n "tmsnippet": "XML",\n "tmtheme": "XML",\n "tmux": "Shell",\n "toc": "TeX",\n "tofu": "HCL",\n "toit": "Toit",\n "toml": "TOML",\n "toml.example": "TOML",\n "tool": "Shell",\n "topojson": "JSON",\n "tpb": "PLSQL",\n "tpl": "Smarty",\n "tpp": "C++",\n "tps": "PLSQL",\n "tres": "Godot Resource",\n "trg": "PLSQL",\n "trigger": "Apex",\n "ts": "TypeScript",\n "tscn": "Godot Resource",\n "tsconfig.json": "JSON",\n "tsp": "TypeSpec",\n "tst": "GAP",\n "tsv": "TSV",\n "tsx": "TypeScript",\n "tu": "Turing",\n "twig": "Twig",\n "txl": "TXL",\n "txx": "C++",\n "typ": "Typst",\n "uc": "UnrealScript",\n "udf": "SQL",\n "udo": "Csound",\n "ui": "XML",\n "unity": "Unity3D Asset",\n "uno": "Uno",\n "upc": "C",\n "uplc": "Untyped Plutus Core",\n "ur": "UrWeb",\n "urdf": "XML",\n "url": "INI",\n "urs": "UrWeb",\n "ux": "XML",\n "v": "Verilog",\n "vala": "Vala",\n "vapi": "Vala",\n "vark": "Gosu",\n "vb": "Visual Basic .NET",\n "vba": "VBA",\n "vbhtml": "Visual Basic .NET",\n "vbproj": "XML",\n "vbs": "VBScript",\n "vcf": "vCard",\n "vcl": "VCL",\n "vcxproj": "XML",\n "vdf": "Valve Data Format",\n "veo": "Verilog",\n "vert": "GLSL",\n "vh": "SystemVerilog",\n "vhd": "VHDL",\n "vhdl": "VHDL",\n "vhf": "VHDL",\n "vhi": "VHDL",\n "vho": "VHDL",\n "vhost": "ApacheConf",\n "vhs": "VHDL",\n "vht": "VHDL",\n "vhw": "VHDL",\n "vim": "Vim Script",\n "vimrc": "Vim Script",\n "viw": "SQL",\n "vmb": "Vim Script",\n "volt": "Volt",\n "vrx": "GLSL",\n "vs": "GLSL",\n "vsh": "GLSL",\n "vshader": "GLSL",\n "vsixmanifest": "XML",\n "vssettings": "XML",\n "vstemplate": "XML",\n "vtl": "Velocity Template Language",\n "vto": "Vento",\n "vue": "Vue",\n "vw": "PLSQL",\n "vxml": "XML",\n "vy": "Vyper",\n "w": "CWeb",\n "wast": "WebAssembly",\n "wat": "WebAssembly",\n "watchr": "Ruby",\n "wdl": "WDL",\n "webapp": "JSON",\n "webmanifest": "JSON",\n "wgsl": "WGSL",\n "whiley": "Whiley",\n "wiki": "Wikitext",\n "wikitext": "Wikitext",\n "wisp": "wisp",\n "wit": "WebAssembly Interface Type",\n "wixproj": "XML",\n "wl": "Wolfram Language",\n "wlk": "Wollok",\n "wls": "Wolfram Language",\n "wlt": "Wolfram Language",\n "wlua": "Lua",\n "workbook": "Markdown",\n "workflow": "HCL",\n "wren": "Wren",\n "ws": "Witcher Script",\n "wsdl": "XML",\n "wsf": "XML",\n "wsgi": "Python",\n "wxi": "XML",\n "wxl": "XML",\n "wxs": "XML",\n "x": "DirectX 3D File",\n "x10": "X10",\n "x3d": "XML",\n "x68": "Assembly",\n "xacro": "XML",\n "xaml": "XML",\n "xc": "XC",\n "xdc": "Tcl",\n "xht": "HTML",\n "xhtml": "HTML",\n "xib": "XML",\n "xlf": "XML",\n "xliff": "XML",\n "xmi": "XML",\n "xml": "XML",\n "xml.dist": "XML",\n "xmp": "XML",\n "xojo_code": "Xojo",\n "xojo_menu": "Xojo",\n "xojo_report": "Xojo",\n "xojo_script": "Xojo",\n "xojo_toolbar": "Xojo",\n "xojo_window": "Xojo",\n "xproj": "XML",\n "xpy": "Python",\n "xq": "XQuery",\n "xql": "XQuery",\n "xqm": "XQuery",\n "xquery": "XQuery",\n "xqy": "XQuery",\n "xrl": "Erlang",\n "xsd": "XML",\n "xsh": "Xonsh",\n "xsjs": "JavaScript",\n "xsjslib": "JavaScript",\n "xsl": "XSLT",\n "xslt": "XSLT",\n "xspec": "XML",\n "xtend": "Xtend",\n "xul": "XML",\n "xzap": "ZAP",\n "y": "Yacc",\n "yacc": "Yacc",\n "yaml": "MiniYAML",\n "yaml-tmlanguage": "YAML",\n "yaml.sed": "YAML",\n "yap": "Prolog",\n "yar": "YARA",\n "yara": "YARA",\n "yasnippet": "YASnippet",\n "yml": "YAML",\n "yml.mysql": "YAML",\n "yrl": "Erlang",\n "yul": "Yul",\n "yy": "Yacc",\n "yyp": "JSON",\n "zap": "ZAP",\n "zcml": "XML",\n "zed": "SpiceDB Schema",\n "zep": "Zephir",\n "zig": "Zig",\n "zig.zon": "Zig",\n "zil": "ZIL",\n "zimpl": "Zimpl",\n "zmodel": "Zmodel",\n "zmpl": "Zimpl",\n "zpl": "Zimpl",\n "zs": "ZenScript",\n "zsh": "Shell",\n "zsh-theme": "Shell"\n },\n "filename": {\n ".abbrev_defs": "Emacs Lisp",\n ".ackrc": "Option List",\n ".all-contributorsrc": "JSON",\n ".arcconfig": "JSON",\n ".atomignore": "Ignore List",\n ".auto-changelog": "JSON",\n ".babelignore": "Ignore List",\n ".babelrc": "JSON",\n ".bash_aliases": "Shell",\n ".bash_functions": "Shell",\n ".bash_history": "Shell",\n ".bash_logout": "Shell",\n ".bash_profile": "Shell",\n ".bashrc": "Shell",\n ".browserslistrc": "Browserslist",\n ".buckconfig": "INI",\n ".bzrignore": "Ignore List",\n ".c8rc": "JSON",\n ".clang-format": "YAML",\n ".clang-tidy": "YAML",\n ".clangd": "YAML",\n ".classpath": "XML",\n ".coffeelintignore": "Ignore List",\n ".coveragerc": "INI",\n ".cproject": "XML",\n ".cshrc": "Shell",\n ".cvsignore": "Ignore List",\n ".devcontainer.json": "JSON",\n ".dockerignore": "Ignore List",\n ".easignore": "Ignore List",\n ".editorconfig": "INI",\n ".eleventyignore": "Ignore List",\n ".emacs": "Emacs Lisp",\n ".emacs.desktop": "Emacs Lisp",\n ".env": "Dotenv",\n ".env.ci": "Dotenv",\n ".env.dev": "Dotenv",\n ".env.development": "Dotenv",\n ".env.development.local": "Dotenv",\n ".env.example": "Dotenv",\n ".env.local": "Dotenv",\n ".env.prod": "Dotenv",\n ".env.production": "Dotenv",\n ".env.sample": "Dotenv",\n ".env.staging": "Dotenv",\n ".env.template": "Dotenv",\n ".env.test": "Dotenv",\n ".env.testing": "Dotenv",\n ".envrc": "Shell",\n ".eslintignore": "Ignore List",\n ".eslintrc.json": "JSON",\n ".exrc": "Vim Script",\n ".factor-boot-rc": "Factor",\n ".factor-rc": "Factor",\n ".flake8": "INI",\n ".flaskenv": "Shell",\n ".gclient": "Python",\n ".gemrc": "YAML",\n ".git-blame-ignore-revs": "Git Revision List",\n ".gitattributes": "Git Attributes",\n ".gitconfig": "INI",\n ".gitignore": "Ignore List",\n ".gitmodules": "INI",\n ".gnus": "Emacs Lisp",\n ".gvimrc": "Vim Script",\n ".htaccess": "ApacheConf",\n ".htmlhintrc": "JSON",\n ".ignore": "Ignore List",\n ".imgbotconfig": "JSON",\n ".irbrc": "Ruby",\n ".jscsrc": "JSON",\n ".jshintrc": "JSON",\n ".jslintrc": "JSON",\n ".justfile": "Just",\n ".kshrc": "Shell",\n ".latexmkrc": "Perl",\n ".login": "Shell",\n ".luacheckrc": "Lua",\n ".markdownlintignore": "Ignore List",\n ".nanorc": "INI",\n ".nodemonignore": "Ignore List",\n ".npmignore": "Ignore List",\n ".npmrc": "INI",\n ".nvimrc": "Vim Script",\n ".nycrc": "JSON",\n ".oxlintrc.json": "JSON",\n ".php": "PHP",\n ".php_cs": "PHP",\n ".php_cs.dist": "PHP",\n ".prettierignore": "Ignore List",\n ".profile": "Shell",\n ".project": "XML",\n ".pryrc": "Ruby",\n ".pylintrc": "INI",\n ".rprofile": "R",\n ".rspec": "Option List",\n ".scalafix.conf": "HOCON",\n ".scalafmt.conf": "HOCON",\n ".shellcheckrc": "ShellCheck Config",\n ".simplecov": "Ruby",\n ".spacemacs": "Emacs Lisp",\n ".stylelintignore": "Ignore List",\n ".swcrc": "JSON",\n ".tern-config": "JSON",\n ".tern-project": "JSON",\n ".tm_properties": "TextMate Properties",\n ".tmux.conf": "Shell",\n ".vercelignore": "Ignore List",\n ".vimrc": "Vim Script",\n ".viper": "Emacs Lisp",\n ".vscodeignore": "Ignore List",\n ".watchmanconfig": "JSON",\n ".xinitrc": "Shell",\n ".xsession": "Shell",\n ".yardopts": "Option List",\n ".zlogin": "Shell",\n ".zlogout": "Shell",\n ".zprofile": "Shell",\n ".zshenv": "Shell",\n ".zshrc": "Shell",\n "9fs": "Shell",\n "_emacs": "Emacs Lisp",\n "_helpers.tpl": "Go Template",\n "_vimrc": "Vim Script",\n "abbrev_defs": "Emacs Lisp",\n "ack": "Perl",\n "ackrc": "Option List",\n "ant.xml": "Ant Build System",\n "apache2.conf": "ApacheConf",\n "api-extractor.json": "JSON",\n "apkbuild": "Shell",\n "app.config": "XML",\n "appraisals": "Ruby",\n "bash_aliases": "Shell",\n "bash_logout": "Shell",\n "bash_profile": "Shell",\n "bashrc": "Shell",\n "berksfile": "Ruby",\n "brewfile": "Ruby",\n "browserslist": "Browserslist",\n "bsdmakefile": "Makefile",\n "buck": "Starlark",\n "build": "Starlark",\n "build.bazel": "Starlark",\n "build.xml": "Ant Build System",\n "buildfile": "Ruby",\n "buildozer.spec": "INI",\n "bun.lock": "JSON",\n "cabal.config": "Cabal Config",\n "cabal.project": "Cabal Config",\n "caddyfile": "Caddyfile",\n "cakefile": "CoffeeScript",\n "capfile": "Ruby",\n "cargo.lock": "TOML",\n "cargo.toml.orig": "TOML",\n "cask": "Emacs Lisp",\n "citation.cff": "YAML",\n "cmakelists.txt": "CMake",\n "commit_editmsg": "Git Commit",\n "composer.lock": "JSON",\n "containerfile": "Dockerfile",\n "contents.lr": "Markdown",\n "cpanfile": "Perl",\n "crontab": "crontab",\n "cshrc": "Shell",\n "dangerfile": "Ruby",\n "deliverfile": "Ruby",\n "deno.lock": "JSON",\n "deps": "Python",\n "dev-requirements.txt": "Pip Requirements",\n "devcontainer.json": "JSON",\n "dockerfile": "Dockerfile",\n "dune-project": "Dune",\n "earthfile": "Earthly",\n "eask": "Emacs Lisp",\n "emakefile": "Erlang",\n "eqnrc": "Roff",\n "expr-dist": "R",\n "fakefile": "Fancy",\n "fastfile": "Ruby",\n "firestore.rules": "Cloud Firestore Security Rules",\n "flake.lock": "JSON",\n "fp-lib-table": "KiCad Layout",\n "gemfile": "Ruby",\n "gemfile.lock": "Gemfile.lock",\n "gitignore-global": "Ignore List",\n "gitignore_global": "Ignore List",\n "glide.lock": "YAML",\n "gnumakefile": "Makefile",\n "go.mod": "Go Module",\n "go.sum": "Go Checksums",\n "go.work": "Go Workspace",\n "go.work.sum": "Go Checksums",\n "gopkg.lock": "TOML",\n "gradlew": "Shell",\n "gradlew.bat": "Batchfile",\n "guardfile": "Ruby",\n "gvimrc": "Vim Script",\n "haproxy.cfg": "HAProxy",\n "hosts": "Hosts File",\n "hosts.txt": "Hosts File",\n "httpd.conf": "ApacheConf",\n "installscript.qs": "Qt Script",\n "jakefile": "JavaScript",\n "jarfile": "Ruby",\n "jenkinsfile": "Groovy",\n "jsconfig.json": "JSON",\n "justfile": "Just",\n "kakrc": "KakouneScript",\n "kbuild": "Makefile",\n "kcl.mod": "KCL",\n "kcl.mod.lock": "KCL",\n "kshrc": "Shell",\n "language-configuration.json": "JSON",\n "language-subtag-registry.txt": "Record Jar",\n "latexmkrc": "Perl",\n "lexer.x": "Lex",\n "login": "Shell",\n "m3makefile": "Quake",\n "m3overrides": "Quake",\n "makefile": "Makefile",\n "makefile.am": "Makefile",\n "makefile.boot": "Makefile",\n "makefile.frag": "Makefile",\n "makefile.in": "Makefile",\n "makefile.inc": "Makefile",\n "makefile.pl": "Perl",\n "makefile.sco": "Makefile",\n "makefile.wat": "Makefile",\n "man": "Shell",\n "manifest.mf": "JAR Manifest",\n "mavenfile": "Ruby",\n "mcmod.info": "JSON",\n "meson.build": "Meson",\n "meson_options.txt": "Meson",\n "mise.local.lock": "TOML",\n "mise.lock": "TOML",\n "mix.lock": "Elixir",\n "mkfile": "Makefile",\n "mmn": "Roff",\n "mmt": "Roff",\n "mocha.opts": "Option List",\n "module.bazel": "Starlark",\n "module.bazel.lock": "JSON",\n "modulefile": "Puppet",\n "mvnw": "Shell",\n "mvnw.cmd": "Batchfile",\n "nanorc": "INI",\n "nextflow.config": "Nextflow",\n "nginx.conf": "Nginx",\n "nim.cfg": "Nim",\n "notebook": "Jupyter Notebook",\n "nuget.config": "XML",\n "nukefile": "Nu",\n "nvimrc": "Vim Script",\n "owh": "Tcl",\n "package.resolved": "JSON",\n "packages.config": "XML",\n "pdm.lock": "TOML",\n "phakefile": "PHP",\n "pipfile": "TOML",\n "pipfile.lock": "JSON",\n "pixi.lock": "YAML",\n "pkgbuild": "Shell",\n "podfile": "Ruby",\n "poetry.lock": "TOML",\n "procfile": "Procfile",\n "profile": "Shell",\n "project.ede": "Emacs Lisp",\n "project.godot": "Godot Resource",\n "puppetfile": "Ruby",\n "pylintrc": "INI",\n "rakefile": "Ruby",\n "rebar.config": "Erlang",\n "rebar.config.lock": "Erlang",\n "rebar.lock": "Erlang",\n "requirements-dev.txt": "Pip Requirements",\n "requirements.lock.txt": "Pip Requirements",\n "requirements.txt": "Pip Requirements",\n "rexfile": "Perl",\n "riemann.config": "Clojure",\n "root": "Isabelle",\n "sconscript": "Python",\n "sconstruct": "Python",\n "settings.stylecop": "XML",\n "singularity": "Singularity",\n "slakefile": "LiveScript",\n "snakefile": "Python",\n "snapfile": "Ruby",\n "starfield": "Tcl",\n "steepfile": "Ruby",\n "suite.rc": "INI",\n "thorfile": "Ruby",\n "tiltfile": "Starlark",\n "tmux.conf": "Shell",\n "toolchain_installscript.qs": "Qt Script",\n "torrc": "Tor Config",\n "troffrc": "Roff",\n "troffrc-end": "Roff",\n "tsconfig.json": "JSON",\n "tslint.json": "JSON",\n "uv.lock": "TOML",\n "vagrantfile": "Ruby",\n "vimrc": "Vim Script",\n "vlcrc": "INI",\n "web.config": "XML",\n "web.debug.config": "XML",\n "web.release.config": "XML",\n "workspace": "Starlark",\n "workspace.bazel": "Starlark",\n "workspace.bzlmod": "Starlark",\n "wscript": "Python",\n "xinitrc": "Shell",\n "xmake.lua": "Xmake",\n "xsession": "Shell",\n "yarn.lock": "YAML",\n "zlogin": "Shell",\n "zlogout": "Shell",\n "zprofile": "Shell",\n "zshenv": "Shell",\n "zshrc": "Shell"\n }\n },\n "vendor": [\n "(^|/)cache/",\n "^[Dd]ependencies/",\n "(^|/)dist/",\n "^deps/",\n "(^|/)configure$",\n "(^|/)config\\\\.guess$",\n "(^|/)config\\\\.sub$",\n "(^|/)aclocal\\\\.m4",\n "(^|/)libtool\\\\.m4",\n "(^|/)ltoptions\\\\.m4",\n "(^|/)ltsugar\\\\.m4",\n "(^|/)ltversion\\\\.m4",\n "(^|/)lt~obsolete\\\\.m4",\n "(^|/)dotnet-install\\\\.(ps1|sh)$",\n "(^|/)cpplint\\\\.py",\n "(^|/)node_modules/",\n "(^|/)\\\\.yarn/releases/",\n "(^|/)\\\\.yarn/plugins/",\n "(^|/)\\\\.yarn/sdks/",\n "(^|/)\\\\.yarn/versions/",\n "(^|/)\\\\.yarn/unplugged/",\n "(^|/)_esy$",\n "(^|/)bower_components/",\n "^rebar$",\n "(^|/)erlang\\\\.mk",\n "(^|/)Godeps/_workspace/",\n "(^|/)testdata/",\n "(^|/)\\\\.indent\\\\.pro",\n "(\\\\.|-)min\\\\.(js|css)$",\n "([^\\\\s]*)import\\\\.(css|less|scss|styl)$",\n "(^|/)bootstrap([^/.]*)(\\\\..*)?\\\\.(js|css|less|scss|styl)$",\n "(^|/)custom\\\\.bootstrap([^\\\\s]*)(js|css|less|scss|styl)$",\n "(^|/)font-?awesome\\\\.(css|less|scss|styl)$",\n "(^|/)font-?awesome/.*\\\\.(css|less|scss|styl)$",\n "(^|/)foundation\\\\.(css|less|scss|styl)$",\n "(^|/)normalize\\\\.(css|less|scss|styl)$",\n "(^|/)skeleton\\\\.(css|less|scss|styl)$",\n "(^|/)[Bb]ourbon/.*\\\\.(css|less|scss|styl)$",\n "(^|/)animate\\\\.(css|less|scss|styl)$",\n "(^|/)materialize\\\\.(css|less|scss|styl|js)$",\n "(^|/)select2/.*\\\\.(css|scss|js)$",\n "(^|/)bulma\\\\.(css|sass|scss)$",\n "(3rd|[Tt]hird)[-_]?[Pp]arty/",\n "(^|/)vendors?/",\n "(^|/)[Ee]xtern(als?)?/",\n "(^|/)[Vv]+endor/",\n "^debian/",\n "(^|/)run\\\\.n$",\n "(^|/)bootstrap-datepicker/",\n "(^|/)jquery([^.]*)\\\\.js$",\n "(^|/)jquery\\\\-\\\\d\\\\.\\\\d+(\\\\.\\\\d+)?\\\\.js$",\n "(^|/)jquery\\\\-ui(\\\\-\\\\d\\\\.\\\\d+(\\\\.\\\\d+)?)?(\\\\.\\\\w+)?\\\\.(js|css)$",\n "(^|/)jquery\\\\.(ui|effects)\\\\.([^.]*)\\\\.(js|css)$",\n "(^|/)jquery\\\\.fn\\\\.gantt\\\\.js",\n "(^|/)jquery\\\\.fancybox\\\\.(js|css)",\n "(^|/)fuelux\\\\.js",\n "(^|/)jquery\\\\.fileupload(-\\\\w+)?\\\\.js$",\n "(^|/)jquery\\\\.dataTables\\\\.js",\n "(^|/)bootbox\\\\.js",\n "(^|/)pdf\\\\.worker\\\\.js",\n "(^|/)slick\\\\.\\\\w+.js$",\n "(^|/)Leaflet\\\\.Coordinates-\\\\d+\\\\.\\\\d+\\\\.\\\\d+\\\\.src\\\\.js$",\n "(^|/)leaflet\\\\.draw-src\\\\.js",\n "(^|/)leaflet\\\\.draw\\\\.css",\n "(^|/)Control\\\\.FullScreen\\\\.css",\n "(^|/)Control\\\\.FullScreen\\\\.js",\n "(^|/)leaflet\\\\.spin\\\\.js",\n "(^|/)wicket-leaflet\\\\.js",\n "(^|/)\\\\.sublime-project",\n "(^|/)\\\\.sublime-workspace",\n "(^|/)\\\\.vscode/",\n "(^|/)prototype(.*)\\\\.js$",\n "(^|/)effects\\\\.js$",\n "(^|/)controls\\\\.js$",\n "(^|/)dragdrop\\\\.js$",\n "(.*?)\\\\.d\\\\.ts$",\n "(^|/)mootools([^.]*)\\\\d+\\\\.\\\\d+.\\\\d+([^.]*)\\\\.js$",\n "(^|/)dojo\\\\.js$",\n "(^|/)MochiKit\\\\.js$",\n "(^|/)yahoo-([^.]*)\\\\.js$",\n "(^|/)yui([^.]*)\\\\.js$",\n "(^|/)ckeditor\\\\.js$",\n "(^|/)tiny_mce([^.]*)\\\\.js$",\n "(^|/)tiny_mce/(langs|plugins|themes|utils)",\n "(^|/)ace-builds/",\n "(^|/)fontello(.*?)\\\\.css$",\n "(^|/)MathJax/",\n "(^|/)Chart\\\\.js$",\n "(^|/)[Cc]ode[Mm]irror/(\\\\d+\\\\.\\\\d+/)?(lib|mode|theme|addon|keymap|demo)",\n "(^|/)shBrush([^.]*)\\\\.js$",\n "(^|/)shCore\\\\.js$",\n "(^|/)shLegacy\\\\.js$",\n "(^|/)angular([^.]*)\\\\.js$",\n "(^|\\\\/)d3(\\\\.v\\\\d+)?([^.]*)\\\\.js$",\n "(^|/)react(-[^.]*)?\\\\.js$",\n "(^|/)flow-typed/.*\\\\.js$",\n "(^|/)modernizr\\\\-\\\\d\\\\.\\\\d+(\\\\.\\\\d+)?\\\\.js$",\n "(^|/)modernizr\\\\.custom\\\\.\\\\d+\\\\.js$",\n "(^|/)knockout-(\\\\d+\\\\.){3}(debug\\\\.)?js$",\n "(^|/)docs?/_?(build|themes?|templates?|static)/",\n "(^|/)admin_media/",\n "(^|/)env/",\n "(^|/)fabfile\\\\.py$",\n "(^|/)waf$",\n "(^|/)\\\\.osx$",\n "\\\\.xctemplate/",\n "\\\\.imageset/",\n "(^|/)Carthage/",\n "(^|/)Sparkle/",\n "(^|/)Crashlytics\\\\.framework/",\n "(^|/)Fabric\\\\.framework/",\n "(^|/)BuddyBuildSDK\\\\.framework/",\n "(^|/)Realm\\\\.framework",\n "(^|/)RealmSwift\\\\.framework",\n "(^|/)\\\\.gitattributes$",\n "(^|/)\\\\.gitignore$",\n "(^|/)\\\\.gitmodules$",\n "(^|/)gradlew$",\n "(^|/)gradlew\\\\.bat$",\n "(^|/)gradle/wrapper/",\n "(^|/)mvnw$",\n "(^|/)mvnw\\\\.cmd$",\n "(^|/)\\\\.mvn/wrapper/",\n "-vsdoc\\\\.js$",\n "\\\\.intellisense\\\\.js$",\n "(^|/)jquery([^.]*)\\\\.validate(\\\\.unobtrusive)?\\\\.js$",\n "(^|/)jquery([^.]*)\\\\.unobtrusive\\\\-ajax\\\\.js$",\n "(^|/)[Mm]icrosoft([Mm]vc)?([Aa]jax|[Vv]alidation)(\\\\.debug)?\\\\.js$",\n "(^|/)[Pp]ackages\\\\/.+\\\\.\\\\d+\\\\/",\n "(^|/)extjs/.*?\\\\.js$",\n "(^|/)extjs/.*?\\\\.xml$",\n "(^|/)extjs/.*?\\\\.txt$",\n "(^|/)extjs/.*?\\\\.html$",\n "(^|/)extjs/.*?\\\\.properties$",\n "(^|/)extjs/\\\\.sencha/",\n "(^|/)extjs/docs/",\n "(^|/)extjs/builds/",\n "(^|/)extjs/cmd/",\n "(^|/)extjs/examples/",\n "(^|/)extjs/locale/",\n "(^|/)extjs/packages/",\n "(^|/)extjs/plugins/",\n "(^|/)extjs/resources/",\n "(^|/)extjs/src/",\n "(^|/)extjs/welcome/",\n "(^|/)html5shiv\\\\.js$",\n "(^|/)[Tt]ests?/fixtures/",\n "(^|/)[Ss]pecs?/fixtures/",\n "(^|/)cordova([^.]*)\\\\.js$",\n "(^|/)cordova\\\\-\\\\d\\\\.\\\\d(\\\\.\\\\d)?\\\\.js$",\n "(^|/)foundation(\\\\..*)?\\\\.js$",\n "(^|/)Vagrantfile$",\n "(^|/)\\\\.[Dd][Ss]_[Ss]tore$",\n "(^|/)inst/extdata/",\n "(^|/)octicons\\\\.css",\n "(^|/)sprockets-octicons\\\\.scss",\n "(^|/)activator$",\n "(^|/)activator\\\\.bat$",\n "(^|/)proguard\\\\.pro$",\n "(^|/)proguard-rules\\\\.pro$",\n "(^|/)puphpet/",\n "(^|/)\\\\.google_apis/",\n "(^|/)Jenkinsfile$",\n "(^|/)\\\\.gitpod\\\\.Dockerfile$",\n "(^|/)\\\\.github/",\n "(^|/)\\\\.obsidian/",\n "(^|/)\\\\.teamcity/",\n "(^|/)xvba_modules/"\n ]\n}' OTHER_LANG = "Other" OTHER_COLOR = "#8b949e" @@ -460,7 +460,7 @@ def classify_path(field, present=None, shebang=None): return OTHER_LANG -def top_languages(langs, limit=6): +def top_languages(langs, limit=10): """Build a sorted language-bar list from {name: [added, deleted, files]}. Ranks by lines touched (added + deleted); languages past `limit` collapse @@ -1017,6 +1017,15 @@ def collect_local(cwd=None, suppress_current_user=False): "frameworks": detect_frameworks(present, cwd=cwd), "file_count": len(present), "branch_count": count_branches(cwd=cwd), + # Whole-repo merge count for the header's "(N merges)" note. The stats + # pipeline runs --no-merges, so the headline total is rebuilt as + # no-merge commits + this. It can't be filtered (merges aren't in + # commits_meta to recount), so main() drops it under any --since/--until/ + # --commits filter rather than inflate the now-filtered headline. + "merge_count": int(git("rev-list", "--merges", "--count", "HEAD", cwd=cwd).strip() or 0), + # HEAD's commit date (includes merges) for the header's "updated N ago". + # Whole-repo like the counts above; the browser renders it relative to now. + "last_commit_iso": git("log", "-1", "--format=%cI", cwd=cwd).strip(), "largest_files": head_file_sizes(cwd=cwd), "disk_by_path": history_disk_by_path(cwd=cwd), } @@ -1122,6 +1131,33 @@ query($owner: String!, $repo: String!) { return total if isinstance(total, int) else None +def fetch_repo_social(github_base, token): + """Stars / watchers / forks for a github.com repo via REST; None otherwise + (non-GitHub origin, offline, private repo without a token, etc.).""" + m = ORIGIN_RE.match(github_base or "") + host = (m.group("https_host") or m.group("ssh_host")) if m else "" + if not m or not (host == "github.com" or host.endswith(".github.com")): + return None + url = f"https://api.github.com/repos/{m.group('owner')}/{m.group('repo')}" + headers = {"Accept": "application/vnd.github+json", "User-Agent": "repo-intel"} + if token: + headers["Authorization"] = f"Bearer {token}" + try: + with urllib.request.urlopen( + urllib.request.Request(url, headers=headers), timeout=5 + ) as resp: + body = json.loads(resp.read().decode()) + except (urllib.error.URLError, TimeoutError, ValueError): + return None + return { + "stars": body.get("stargazers_count"), + # REST quirk: "Watchers" in GitHub's UI is subscribers_count; + # watchers_count is a legacy alias of the star count. + "watchers": body.get("subscribers_count"), + "forks": body.get("forks_count"), + } + + def get_github_token(): try: token = subprocess.check_output( @@ -1196,7 +1232,10 @@ def fetch_user_profiles(logins, token): unique = [] seen = set() for login in logins: - if login and login not in seen: + # Bot accounts (e.g. "github-actions[bot]") are GraphQL Bot nodes, not + # User nodes — user(login:) can never resolve them, so querying just + # yields a NOT_FOUND error. Skip them rather than emit a noisy warning. + if login and login not in seen and not login.endswith("[bot]"): seen.add(login) unique.append(login) if not unique: @@ -1219,8 +1258,12 @@ def fetch_user_profiles(logins, token): except urllib.error.URLError as exc: print(f" warning: profile fetch failed: {exc}", file=sys.stderr) return {} - if "errors" in body: - print(f" warning: profile fetch errors: {body['errors']}", file=sys.stderr) + # NOT_FOUND just means a login no longer resolves (deleted/renamed account); + # the per-alias `if not node: continue` below already skips those. Only warn + # about other errors (auth, rate limits) that signal a real fetch problem. + real_errors = [e for e in body.get("errors", []) if e.get("type") != "NOT_FOUND"] + if real_errors: + print(f" warning: profile fetch errors: {real_errors}", file=sys.stderr) data = body.get("data") or {} out = {} for i, login in enumerate(unique): @@ -1778,6 +1821,12 @@ def build_data( # Total branch count: a snapshot stat like file_count. None on paths that # can't determine it. branch_count = (extras or {}).get("branch_count") + merge_count = (extras or {}).get("merge_count") or 0 + # HEAD commit date for "updated N ago"; fall back to the newest commit we + # have (the remote GraphQL path supplies no extras). + last_commit_iso = (extras or {}).get("last_commit_iso") or max( + (m.get("iso") or "" for m in commits_meta.values()), default="" + ) # File-size sunbursts: blob sizes at HEAD and accumulated on-disk size per # path across history. None on the remote GraphQL path (no tree fetched). largest_files = (extras or {}).get("largest_files") @@ -1920,8 +1969,15 @@ def build_data( "largestFiles": largest_files, "diskByPath": disk_by_path, "dateRange": date_range, + "lastCommit": last_commit_iso, + "generatedAt": datetime.now(timezone.utc).isoformat(), "totals": { + # Authored (no-merge) commits — equals the sum of contributors' + # commits, so it's the denominator for every share/percentage. + # Merges are tracked separately; the GitHub-comparable headline + # (commits + merges) is composed at display time. "commits": total_commits, + "merges": merge_count, "added": total_added, "deleted": total_deleted, "contributors": total_contributors, @@ -2073,15 +2129,20 @@ def render_markdown(data): out.append(f"# repo-intel — {f'[{name}]({base})' if base else name}") out.append("") n_contrib = t["contributors"] + # Headline commit count matches GitHub (authored + merges); the per-author + # stats below use the merge-free t["commits"]. + merges = t.get("merges") or 0 + commits_all = t["commits"] + merges + merge_note = f" ({merges:,} merge{'' if merges == 1 else 's'})" if merges else "" out.append( - f"_{t['commits']:,} commits · {dr['start'] or '?'} — {dr['end'] or '?'} · " + f"_{commits_all:,} commits · {dr['start'] or '?'} — {dr['end'] or '?'} · " f"{n_contrib:,} contributor{'' if n_contrib == 1 else 's'}_" ) out.append("") out.append("## Totals") out.append("") - out.append(f"- Commits: {t['commits']:,}") + out.append(f"- Commits: {commits_all:,}{merge_note}") out.append(f"- Lines: +{t['added']:,} / -{t['deleted']:,}") out.append(f"- Contributors: {t['contributors']:,}") out.append(f"- Default branch: `{data['defaultBranch']}`") @@ -2251,6 +2312,13 @@ def main(): ) if not commits_meta: sys.exit("error: no commits match the given filters") + # The merge tally is whole-history (collected before filtering, and + # merges aren't in commits_meta to recount), so adding it to the now + # date/subset-filtered authored total would inflate the "N commits" + # headline. Drop it under any filter — the headline then reads as just + # the commits in range. + if extras: + extras.pop("merge_count", None) tags = filter_tags_to_range(tags, commits_meta) @@ -2271,6 +2339,10 @@ def main(): enrich_contributor_profiles(data["contributors"], commits_meta, github_base, token=token) + social = fetch_repo_social(github_base, token or get_github_token()) + if social: + data.update(social) + multi = len(formats) > 1 builders = { "html": lambda: render_html(data), @@ -2287,7 +2359,7 @@ def main(): print(f"Wrote {out_path}") print( - f" {data['totals']['commits']} commits · " + f" {data['totals']['commits'] + (data['totals'].get('merges') or 0)} commits · " f"{data['dateRange']['start']} — {data['dateRange']['end']} · " f"{data['totals']['contributors']} contributor" f"{'' if data['totals']['contributors'] == 1 else 's'}" diff --git a/gen_techdata.py b/gen_techdata.py index 439bd28..f9f8bee 100644 --- a/gen_techdata.py +++ b/gen_techdata.py @@ -41,6 +41,12 @@ "r": "R", "pl": "Perl", "t": "Perl", "l": "Common Lisp", "v": "Verilog", "f": "Fortran", "for": "Fortran", "cls": "Apex", "pro": "Prolog", "ts": "TypeScript", "rs": "Rust", "cs": "C#", "sql": "SQL", + # Linguist's "Gettext Catalog" (.po/.pot) is type:prose and ships no color, + # so it'd be dropped and translation catalogs would vanish into "Other". + # Re-pin them under Linguist's own name with the gold GitHub falls back to + # for colorless languages (Primer --bgColor-attention-emphasis; see + # SYNTHETIC_COLORS). + "po": "Gettext Catalog", "pot": "Gettext Catalog", } # Generic extensions whose canonical Linguist owner is the colorless "Text" @@ -141,7 +147,7 @@ # Colors for synthetic framework groups Linguist doesn't define a language for. # Purple keeps "Tools" distinct from the grey "Other" bucket on the same page. -SYNTHETIC_COLORS = {"Tools": "#a371f7"} +SYNTHETIC_COLORS = {"Tools": "#a371f7", "Gettext Catalog": "#9e6a03"} # Backend / non-JS sentinel files: basename (or sub-path) → (framework, language). # The "Tools" bucket surfaces build/devops tooling that's present as a config @@ -254,12 +260,13 @@ def build_language_tables(langs): ext_meta[key] = (rank, primary) for fn in info.get("filenames", []): filename_lang.setdefault(fn.lower(), eff) + name_color.update(SYNTHETIC_COLORS) # synthetic buckets Linguist doesn't color; + # merged before EXT_OVERRIDE so its guard sees them for ext, lang in EXT_OVERRIDE.items(): if lang in name_color: ext_lang[ext] = lang for ext in EXT_EXCLUDE: ext_lang.pop(ext, None) - name_color.update(SYNTHETIC_COLORS) # synthetic buckets Linguist doesn't color return name_color, ext_lang, filename_lang diff --git a/repo-intel.py b/repo-intel.py index 7a50568..c615e3e 100755 --- a/repo-intel.py +++ b/repo-intel.py @@ -460,7 +460,7 @@ def classify_path(field, present=None, shebang=None): return OTHER_LANG -def top_languages(langs, limit=6): +def top_languages(langs, limit=10): """Build a sorted language-bar list from {name: [added, deleted, files]}. Ranks by lines touched (added + deleted); languages past `limit` collapse @@ -1017,6 +1017,15 @@ def collect_local(cwd=None, suppress_current_user=False): "frameworks": detect_frameworks(present, cwd=cwd), "file_count": len(present), "branch_count": count_branches(cwd=cwd), + # Whole-repo merge count for the header's "(N merges)" note. The stats + # pipeline runs --no-merges, so the headline total is rebuilt as + # no-merge commits + this. It can't be filtered (merges aren't in + # commits_meta to recount), so main() drops it under any --since/--until/ + # --commits filter rather than inflate the now-filtered headline. + "merge_count": int(git("rev-list", "--merges", "--count", "HEAD", cwd=cwd).strip() or 0), + # HEAD's commit date (includes merges) for the header's "updated N ago". + # Whole-repo like the counts above; the browser renders it relative to now. + "last_commit_iso": git("log", "-1", "--format=%cI", cwd=cwd).strip(), "largest_files": head_file_sizes(cwd=cwd), "disk_by_path": history_disk_by_path(cwd=cwd), } @@ -1122,6 +1131,33 @@ def probe_remote_total(owner, repo, token): return total if isinstance(total, int) else None +def fetch_repo_social(github_base, token): + """Stars / watchers / forks for a github.com repo via REST; None otherwise + (non-GitHub origin, offline, private repo without a token, etc.).""" + m = ORIGIN_RE.match(github_base or "") + host = (m.group("https_host") or m.group("ssh_host")) if m else "" + if not m or not (host == "github.com" or host.endswith(".github.com")): + return None + url = f"https://api.github.com/repos/{m.group('owner')}/{m.group('repo')}" + headers = {"Accept": "application/vnd.github+json", "User-Agent": "repo-intel"} + if token: + headers["Authorization"] = f"Bearer {token}" + try: + with urllib.request.urlopen( + urllib.request.Request(url, headers=headers), timeout=5 + ) as resp: + body = json.loads(resp.read().decode()) + except (urllib.error.URLError, TimeoutError, ValueError): + return None + return { + "stars": body.get("stargazers_count"), + # REST quirk: "Watchers" in GitHub's UI is subscribers_count; + # watchers_count is a legacy alias of the star count. + "watchers": body.get("subscribers_count"), + "forks": body.get("forks_count"), + } + + def get_github_token(): try: token = subprocess.check_output( @@ -1196,7 +1232,10 @@ def fetch_user_profiles(logins, token): unique = [] seen = set() for login in logins: - if login and login not in seen: + # Bot accounts (e.g. "github-actions[bot]") are GraphQL Bot nodes, not + # User nodes — user(login:) can never resolve them, so querying just + # yields a NOT_FOUND error. Skip them rather than emit a noisy warning. + if login and login not in seen and not login.endswith("[bot]"): seen.add(login) unique.append(login) if not unique: @@ -1219,8 +1258,12 @@ def fetch_user_profiles(logins, token): except urllib.error.URLError as exc: print(f" warning: profile fetch failed: {exc}", file=sys.stderr) return {} - if "errors" in body: - print(f" warning: profile fetch errors: {body['errors']}", file=sys.stderr) + # NOT_FOUND just means a login no longer resolves (deleted/renamed account); + # the per-alias `if not node: continue` below already skips those. Only warn + # about other errors (auth, rate limits) that signal a real fetch problem. + real_errors = [e for e in body.get("errors", []) if e.get("type") != "NOT_FOUND"] + if real_errors: + print(f" warning: profile fetch errors: {real_errors}", file=sys.stderr) data = body.get("data") or {} out = {} for i, login in enumerate(unique): @@ -1778,6 +1821,12 @@ def build_data( # Total branch count: a snapshot stat like file_count. None on paths that # can't determine it. branch_count = (extras or {}).get("branch_count") + merge_count = (extras or {}).get("merge_count") or 0 + # HEAD commit date for "updated N ago"; fall back to the newest commit we + # have (the remote GraphQL path supplies no extras). + last_commit_iso = (extras or {}).get("last_commit_iso") or max( + (m.get("iso") or "" for m in commits_meta.values()), default="" + ) # File-size sunbursts: blob sizes at HEAD and accumulated on-disk size per # path across history. None on the remote GraphQL path (no tree fetched). largest_files = (extras or {}).get("largest_files") @@ -1920,8 +1969,15 @@ def build_data( "largestFiles": largest_files, "diskByPath": disk_by_path, "dateRange": date_range, + "lastCommit": last_commit_iso, + "generatedAt": datetime.now(timezone.utc).isoformat(), "totals": { + # Authored (no-merge) commits — equals the sum of contributors' + # commits, so it's the denominator for every share/percentage. + # Merges are tracked separately; the GitHub-comparable headline + # (commits + merges) is composed at display time. "commits": total_commits, + "merges": merge_count, "added": total_added, "deleted": total_deleted, "contributors": total_contributors, @@ -2073,15 +2129,20 @@ def render_markdown(data): out.append(f"# repo-intel — {f'[{name}]({base})' if base else name}") out.append("") n_contrib = t["contributors"] + # Headline commit count matches GitHub (authored + merges); the per-author + # stats below use the merge-free t["commits"]. + merges = t.get("merges") or 0 + commits_all = t["commits"] + merges + merge_note = f" ({merges:,} merge{'' if merges == 1 else 's'})" if merges else "" out.append( - f"_{t['commits']:,} commits · {dr['start'] or '?'} — {dr['end'] or '?'} · " + f"_{commits_all:,} commits · {dr['start'] or '?'} — {dr['end'] or '?'} · " f"{n_contrib:,} contributor{'' if n_contrib == 1 else 's'}_" ) out.append("") out.append("## Totals") out.append("") - out.append(f"- Commits: {t['commits']:,}") + out.append(f"- Commits: {commits_all:,}{merge_note}") out.append(f"- Lines: +{t['added']:,} / -{t['deleted']:,}") out.append(f"- Contributors: {t['contributors']:,}") out.append(f"- Default branch: `{data['defaultBranch']}`") @@ -2251,6 +2312,13 @@ def main(): ) if not commits_meta: sys.exit("error: no commits match the given filters") + # The merge tally is whole-history (collected before filtering, and + # merges aren't in commits_meta to recount), so adding it to the now + # date/subset-filtered authored total would inflate the "N commits" + # headline. Drop it under any filter — the headline then reads as just + # the commits in range. + if extras: + extras.pop("merge_count", None) tags = filter_tags_to_range(tags, commits_meta) @@ -2271,6 +2339,10 @@ def main(): enrich_contributor_profiles(data["contributors"], commits_meta, github_base, token=token) + social = fetch_repo_social(github_base, token or get_github_token()) + if social: + data.update(social) + multi = len(formats) > 1 builders = { "html": lambda: render_html(data), @@ -2287,7 +2359,7 @@ def main(): print(f"Wrote {out_path}") print( - f" {data['totals']['commits']} commits · " + f" {data['totals']['commits'] + (data['totals'].get('merges') or 0)} commits · " f"{data['dateRange']['start']} — {data['dateRange']['end']} · " f"{data['totals']['contributors']} contributor" f"{'' if data['totals']['contributors'] == 1 else 's'}" diff --git a/techdata.json b/techdata.json index 5eba008..7f93f63 100644 --- a/techdata.json +++ b/techdata.json @@ -489,6 +489,7 @@ "Gentoo Ebuild": "#9400ff", "Gentoo Eclass": "#9400ff", "Gerber Image": "#d20b00", + "Gettext Catalog": "#9e6a03", "Gherkin": "#5B2063", "Git Attributes": "#F44D27", "Git Commit": "#F44D27", @@ -1790,12 +1791,14 @@ "pm6": "Raku", "pml": "Promela", "pmod": "Pike", + "po": "Gettext Catalog", "podsl": "Common Lisp", "podspec": "Ruby", "pogo": "PogoScript", "polar": "Polar", "por": "Portugol", "postcss": "CSS", + "pot": "Gettext Catalog", "pov": "POV-Ray SDL", "pp": "Puppet", "pprx": "REXX", diff --git a/web/index.html b/web/index.html index e3c386f..2488128 100644 --- a/web/index.html +++ b/web/index.html @@ -3,6 +3,10 @@ + + Repo Intel diff --git a/web/src/App.svelte b/web/src/App.svelte index 71881f4..be594ad 100644 --- a/web/src/App.svelte +++ b/web/src/App.svelte @@ -11,7 +11,8 @@ createTimelineTooltip, buildPunchPoints, } from "$lib/popovers"; - import { fmtTimelineDuration } from "$lib/format"; + import { authorUrl, fmtTimelineDuration, relativeTime, fmtDateTime } from "$lib/format"; + import { setAuthorTotalCommits } from "$lib/popover-store.svelte"; import { registerEchartsTheme } from "$lib/theme"; import { buildTimeline } from "$lib/timeline"; import { dragScroll, scrollSpy } from "$lib/actions"; @@ -41,6 +42,10 @@ timelineDur ? `Commit timeline: ${timelineDur}` : "Commit timeline", ); + // "Last commit N ago" shown in the Contributions header. + const lastCommitAgo = $derived(relativeTime(data.lastCommit)); + const lastCommitFull = $derived(fmtDateTime(data.lastCommit)); + // The author popover (shared by the table and the timeline lane labels) and the // commit-bucket popover (opened by the punch-card cells) write the shared // popover store rendered by / . Created in @@ -61,6 +66,7 @@ // The timeline is still rendered imperatively into the container elements below // (it's a hand-drawn canvas); wire it once the static layout is mounted. onMount(() => { + setAuthorTotalCommits(data.totals.commits); authorPopover = createAuthorPopover(data.contributors); commitPopover = createCommitPopover(data); buildTimeline(data, authorPopover, createTimelineTooltip()); @@ -89,7 +95,16 @@
-

Contributions

+
+

Contributions

+ {#if lastCommitAgo} + Last commit + {/if} +
(heatmapMode = mode)} />
@@ -119,14 +134,16 @@

Overall

- +

Commit frequency over time

{#each data.contributors as c, i (c.email)} {#each data.contributors as c, i (c.email)} => + new Map(contributors.map((c) => [c.email, c.name] as const)); + +// Email → original contributor index, so a chart that filters/re-sorts a local +// copy (the churn bars) can still resolve the right person's colour and popover. +export const buildEmailToOrig = (contributors: Contributor[]): Map => + new Map(contributors.map((c, i) => [c.email, i] as const)); + +export const buildContribLegend = (contributors: Contributor[]): LegendItem[] => + contributors.map((c, i) => ({ key: c.email, name: c.name, color: clr(i), idx: i })); + +// Contributors with their original index, minus bots. A `[bot]` login (the ones +// repo-intel.py skips for profiles — Renovate, CI accounts) churns nothing like a +// human and only flattens everyone else's scale, so the churn and commit-style +// charts drop them. `origIdx` is preserved so each row still resolves the right +// identity colour (clr) and author popover after the chart re-sorts its own copy. +export const humanContribRows = ( + contributors: Contributor[], +): { c: Contributor; origIdx: number }[] => + contributors.map((c, origIdx) => ({ c, origIdx })).filter((r) => !r.c.login.endsWith("[bot]")); + +// Half-transparent dark inner border on the treemap tiles, so each grey/brand +// tile reads against the gap around it (shared by the languages and files +// treemaps). +export const tileInnerBorder = "rgba(0, 0, 0, 0.6)"; diff --git a/web/src/lib/chart-legend.svelte.ts b/web/src/lib/chart-legend.svelte.ts new file mode 100644 index 0000000..b1c7379 --- /dev/null +++ b/web/src/lib/chart-legend.svelte.ts @@ -0,0 +1,36 @@ +// Shared legend-selection state for the cards whose HTML ChartLegend drives an +// ECharts hidden legend (weekly-commits line, commit-share pie). The chart owns +// the source of truth for what's hidden; this factory mirrors its `selected` +// map back into $state so the legend can dim rows and reveal Reset, and wraps +// the legend chart-actions the legend's callbacks dispatch. Lives in a .svelte.ts +// module so it can hold $state (the popover-store.svelte.ts convention). +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { EChartsType } from "echarts/core"; + +export function createLegendSelection() { + // Keyed by series/slice name (the contributor's email, or "Others"); a missing + // key means selected. Only onReady writes it, from the chart's own event. + let sel = $state>({}); + let chart: EChartsType | undefined; + return { + get selected(): Record { + return sel; + }, + onReady(c: EChartsType): void { + chart = c; + c.on("legendselectchanged", (p: any) => (sel = { ...p.selected })); + }, + toggle(key: string): void { + chart?.dispatchAction({ type: "legendToggleSelect", name: key }); + }, + reset(): void { + chart?.dispatchAction({ type: "legendAllSelect" }); + sel = {}; + }, + // Pie only: hovering a legend row emphasises the matching slice by name (the + // legend's toggle key). Harmless on cards that never wire onEmphasize. + highlight(key: string, on: boolean): void { + chart?.dispatchAction({ type: on ? "highlight" : "downplay", name: key }); + }, + }; +} diff --git a/web/src/lib/components/AuthorPopover.svelte b/web/src/lib/components/AuthorPopover.svelte index e482ea9..4e1bc5e 100644 --- a/web/src/lib/components/AuthorPopover.svelte +++ b/web/src/lib/components/AuthorPopover.svelte @@ -4,10 +4,10 @@ // positioning are handled by the portal/position actions, so this component // only builds the (auto-escaped) markup. Svelte port of createAuthorPopover's // innerHTML in lib/popovers.ts. - import { authorState } from "$lib/popover-store.svelte"; + import { authorState, authorMeta } from "$lib/popover-store.svelte"; import { portal, position } from "$lib/actions"; import { clr } from "$lib/theme"; - import { fmt } from "$lib/format"; + import { fmt, pct } from "$lib/format"; import LangBar from "./LangBar.svelte"; const ICON_LOC = @@ -23,6 +23,12 @@ const handle = $derived(c?.login ? "@" + c.login : ""); const initial = $derived((c?.name || "?").trim().charAt(0).toUpperCase()); const net = $derived(c ? c.added - c.deleted : 0); + // Share of all commits in the repo (treemap header used to carry this; it now + // lives here so the header strip stays a clean, untruncated name). Hidden until + // the total is set, and on the off chance the total is zero. + const commitShare = $derived( + c && authorMeta.totalCommits ? pct(c.commits, authorMeta.totalCommits) : null, + ); const counts = $derived( c @@ -99,7 +105,7 @@ {/if}
-
{fmt(c.commits)} commits · {c.activeDays} active day{c.activeDays === 1 ? "" : "s"}
+
{fmt(c.commits)} commits{#if commitShare}{" "}({commitShare}){/if} · {c.activeDays} active day{c.activeDays === 1 ? "" : "s"}
+{fmt(c.added)} -{fmt(c.deleted)} (net {#if net > 0}+{fmt(net)}{:else if net < 0}{fmt(net)}{:else}{fmt(net)}{/if})
{c.first} — {c.last}
@@ -232,6 +238,9 @@ .del { color: var(--color-deleted); } + .lp-share { + color: var(--text-muted); + } } .lp-period { color: var(--text-muted); diff --git a/web/src/lib/components/ChartLegend.svelte b/web/src/lib/components/ChartLegend.svelte new file mode 100644 index 0000000..344159e --- /dev/null +++ b/web/src/lib/components/ChartLegend.svelte @@ -0,0 +1,166 @@ + + +
+ {#each items as item (item.key)} + + {/each} +
+ + + diff --git a/web/src/lib/components/ChurnCard.svelte b/web/src/lib/components/ChurnCard.svelte new file mode 100644 index 0000000..52ba447 --- /dev/null +++ b/web/src/lib/components/ChurnCard.svelte @@ -0,0 +1,192 @@ + + +
+
+ Lines added vs + deleted +
+
+
+ + diff --git a/web/src/lib/components/CommitShareCard.svelte b/web/src/lib/components/CommitShareCard.svelte new file mode 100644 index 0000000..f889b7b --- /dev/null +++ b/web/src/lib/components/CommitShareCard.svelte @@ -0,0 +1,127 @@ + + +
+
Commit share
+
+
+ +
+
+ + diff --git a/web/src/lib/components/CommitStyleCard.svelte b/web/src/lib/components/CommitStyleCard.svelte new file mode 100644 index 0000000..6b259a6 --- /dev/null +++ b/web/src/lib/components/CommitStyleCard.svelte @@ -0,0 +1,117 @@ + + +
+
Commit style
+
+
diff --git a/web/src/lib/components/ContributorCard.svelte b/web/src/lib/components/ContributorCard.svelte index 4457fba..da2c81e 100644 --- a/web/src/lib/components/ContributorCard.svelte +++ b/web/src/lib/components/ContributorCard.svelte @@ -3,19 +3,34 @@ // weekly-commits sparkline mounted via the `echart` action. Svelte port of the // contributor-cards block from lib/charts.ts. import type { Contributor } from "$types"; + import type { AuthorPopover } from "$lib/popovers"; import type { EChartsCoreOption } from "echarts/core"; import { echart } from "$lib/actions"; import { clr, textMuted } from "$lib/theme"; import { fmt, weekLabel } from "$lib/format"; let { + authorPopover, contributor, + url, index, weeks, weekly, - }: { contributor: Contributor; index: number; weeks: string[]; weekly: number[] } = $props(); + }: { + authorPopover: AuthorPopover | undefined; + contributor: Contributor; + // Author-commits URL, or "#" for a local-only repo (no GitHub base) — in + // which case the name renders as a non-navigating label (see the markup). + url: string; + index: number; + weeks: string[]; + weekly: number[]; + } = $props(); const color = $derived(clr(index)); + // "#" means a local-only repo (no GitHub base): render a non-navigating label, + // dropping target/rel along with the href so they aren't left dangling. + const href = $derived(url === "#" ? undefined : url); const option: EChartsCoreOption = $derived.by(() => { const labels = weeks.map(weekLabel); @@ -50,7 +65,17 @@
#{index + 1}
-
{contributor.name}
+ + authorPopover?.show(index, e.currentTarget)} + onmouseleave={() => authorPopover?.hide()}>{contributor.name}
{fmt(contributor.commits)} commits {fmt(contributor.added)} ++ @@ -68,9 +93,20 @@ min-width: 0; .name { + display: inline-block; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + vertical-align: bottom; font-weight: 600; font-size: 0.75rem; margin-bottom: 2px; + text-decoration: none; + + &:hover { + text-decoration: underline; + } } .meta { font-size: 0.62rem; diff --git a/web/src/lib/components/Header.svelte b/web/src/lib/components/Header.svelte index fed1dcf..d88fbed 100644 --- a/web/src/lib/components/Header.svelte +++ b/web/src/lib/components/Header.svelte @@ -5,7 +5,7 @@ // set as a side effect. import type { RepoData } from "$types"; import { colorAdded, colorDeleted } from "$lib/theme"; - import { fmt, fmtSize } from "$lib/format"; + import { fmt, fmtSize, relativeTime, fmtDateTime } from "$lib/format"; let { data }: { data: RepoData } = $props(); @@ -20,27 +20,132 @@ const sizeStr = $derived(fmtSize(data.repoSizeKb)); const fileCount = $derived(data.fileCount); const branchCount = $derived(data.branchCount); + // GitHub base URL without a trailing slash; the deep links and social links hang off it. + const base = $derived(data.githubBaseUrl ? data.githubBaseUrl.replace(/\/$/, "") : null); + const contributorsUrl = $derived(base ? `${base}/graphs/contributors` : null); + const branchesUrl = $derived(base ? `${base}/branches` : null); + const commitsUrl = $derived(base ? `${base}/commits` : null); + const mergeCount = $derived(totals.merges ?? 0); + const generatedAgo = $derived(relativeTime(data.generatedAt)); + const generatedFull = $derived(fmtDateTime(data.generatedAt)); + + // Subtitle stat labels, extracted so the link/plain-text branches below don't + // each repeat the text. branchLabel is only rendered when branchCount != null. + const commitsLabel = $derived(`${fmt(totals.commits + mergeCount)} commits`); + const contribLabel = $derived(`${fmt(contribCount)} contributor${contribCount === 1 ? "" : "s"}`); + const branchLabel = $derived( + branchCount != null ? `${fmt(branchCount)} branch${branchCount === 1 ? "" : "es"}` : "", + ); + + // GitHub social counts (top-right line); present only for reachable GitHub repos. + const stars = $derived(data.stars ?? null); + const watchers = $derived(data.watchers ?? null); + const forks = $derived(data.forks ?? null); + const hasSocial = $derived(stars != null || watchers != null || forks != null); + const plural = (n: number, w: string) => `${fmt(n)} ${w}${n === 1 ? "" : "s"}`; $effect(() => { document.title = titleText ? `${titleText} · Repo Intel` : "Repo Intel"; }); -

- {#if data.githubBaseUrl} - {titleText} - {:else}{titleText}{/if} -

+
+

+ {#if data.githubBaseUrl} + {titleText} + {:else}{titleText}{/if} +

+ {#if hasSocial || generatedAgo} +
+ {#if hasSocial} + + {/if} + {#if generatedAgo} +
+ Generated +
+ {/if} +
+ {/if} +
+ + +{#snippet stat(url: string | null, label: string)}{#if url}{label}{:else}{label}{/if}{/snippet} +

- {data.dateRange.start} — {data.dateRange.end} · {fmt(totals.commits)} commits · + {data.dateRange.start} — {data.dateRange.end} · {@render stat( + commitsUrl, + commitsLabel, + )}{#if mergeCount > 0}{" "}({fmt(mergeCount)} merge{mergeCount === 1 ? "" : "s"}){/if} · +{fmt(totals.added)} -{fmt(totals.deleted)} (net {#if net > 0}+{fmt(net)}{:else if net < 0}{fmt(net)}{:else}{fmt(net)}{/if}) · {fmt(contribCount)} contributor{contribCount === 1 - ? "" - : "s"}{#if branchCount != null}{" "}· {fmt(branchCount)} branch{branchCount === 1 - ? "" - : "es"}{/if}{#if fileCount != null}{" "}· {fmt(fileCount)} files{/if}{#if sizeStr}{" "}· {sizeStr}{/if} + >{:else}{fmt(net)}{/if}) · {@render stat( + contributorsUrl, + contribLabel, + )}{#if branchCount != null}{" "}· {@render stat( + branchesUrl, + branchLabel, + )}{/if}{#if fileCount != null}{" "}· {fmt(fileCount)} files{/if}{#if sizeStr}{" "}· {sizeStr}{/if}

+ + diff --git a/web/src/lib/components/LanguagesCard.svelte b/web/src/lib/components/LanguagesCard.svelte new file mode 100644 index 0000000..0ddfc37 --- /dev/null +++ b/web/src/lib/components/LanguagesCard.svelte @@ -0,0 +1,197 @@ + + +{#if hasLangData} +
+
Languages by contributor
+
+
+{/if} diff --git a/web/src/lib/components/LargestFilesCard.svelte b/web/src/lib/components/LargestFilesCard.svelte new file mode 100644 index 0000000..ba519a8 --- /dev/null +++ b/web/src/lib/components/LargestFilesCard.svelte @@ -0,0 +1,402 @@ + + +{#if hasFiles && filesOption} +
+
+ Largest files {activeFilesTab === "head" ? "in HEAD" : "in Git history"} +
+
+ {#if hasHeadFiles} + + {/if} + {#if hasHistFiles} + + {/if} +
+
+ {#if filesPath.length > 1} + + {/if} +
+{/if} + + diff --git a/web/src/lib/components/OverallCharts.svelte b/web/src/lib/components/OverallCharts.svelte index 5fa3137..27d3a46 100644 --- a/web/src/lib/components/OverallCharts.svelte +++ b/web/src/lib/components/OverallCharts.svelte @@ -1,754 +1,28 @@
-
-
Weekly commits (stacked)
-
- -
-
-
Commit share
-
- -
-
-
Lines added vs deleted
-
-
-
-
Net lines per commit
-
-
- {#if hasLangData} -
-
Languages by contributor
-
-
- {/if} - {#if hasFiles && filesOption} -
-
Largest files
-
- {#if hasHeadFiles} - - {/if} - {#if hasHistFiles} - - {/if} -
-
- {#if filesPath.length > 1} - - {/if} -
- {/if} + + + + + +
- - diff --git a/web/src/lib/components/PatternCard.svelte b/web/src/lib/components/PatternCard.svelte index 0dab0c0..39af4e0 100644 --- a/web/src/lib/components/PatternCard.svelte +++ b/web/src/lib/components/PatternCard.svelte @@ -7,19 +7,25 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import type { Contributor } from "$types"; import type { EChartsType, EChartsCoreOption } from "echarts/core"; - import type { CommitPopover } from "$lib/popovers"; + import type { AuthorPopover, CommitPopover } from "$lib/popovers"; import type { PunchPoint } from "$lib/popovers"; import { echart } from "$lib/actions"; import { clr, accentWeekend } from "$lib/theme"; let { + authorPopover, contributor, + url, index, points, commitPopover, linksEnabled, }: { + authorPopover: AuthorPopover | undefined; contributor: Contributor; + // Author-commits URL, or "#" for a local-only repo (no GitHub base) — in + // which case the name renders as a non-navigating label (see the markup). + url: string; index: number; points: PunchPoint[]; commitPopover: CommitPopover | undefined; @@ -27,6 +33,9 @@ } = $props(); const color = $derived(clr(index)); + // "#" means a local-only repo (no GitHub base): render a non-navigating label, + // dropping target/rel along with the href so they aren't left dangling. + const href = $derived(url === "#" ? undefined : url); const HOURS = Array.from({ length: 24 }, (_, i) => `${i}:00`); const DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; @@ -73,7 +82,10 @@ inverse: true, axisTick: { show: false }, axisLabel: { fontSize: 9 }, - splitLine: { show: true, lineStyle: { color: "rgba(255,255,255,0.06)" } }, + // Faint, uniform row separators. Kept low because the weekend tint + // amplifies the Sat/Sun line that sits inside it — at higher opacity it + // became the chart's boldest rule, which read as a misplaced divider. + splitLine: { show: true, lineStyle: { color: "rgba(255,255,255,0.035)" } }, // Tint the Sat/Sun rows to match the weekend shading in the contributor // heatmap and timeline. Under `inverse: true`, ECharts shifts the // splitArea colour array by one band (verified in-browser): color[i] @@ -130,7 +142,20 @@ @@ -139,6 +164,16 @@ position: relative; padding: 14px; } + /* Re-enable pointer events for just the name (the title strip disables them so + chart hover/clicks pass through), and strip the default anchor styling. */ + .title-link { + pointer-events: auto; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } .ec { width: 100%; height: 280px; diff --git a/web/src/lib/components/TechGrid.svelte b/web/src/lib/components/TechGrid.svelte index 7e98fe1..efb1950 100644 --- a/web/src/lib/components/TechGrid.svelte +++ b/web/src/lib/components/TechGrid.svelte @@ -54,11 +54,12 @@ .tech-grid { display: grid; grid-template-columns: 1fr 1fr; - gap: 16px; + gap: 48px; align-items: start; @media (max-width: 900px) { grid-template-columns: 1fr; + gap: 16px; } } .tech-bar-label { diff --git a/web/src/lib/components/TimelineTooltip.svelte b/web/src/lib/components/TimelineTooltip.svelte index dd5c2bb..6e7661e 100644 --- a/web/src/lib/components/TimelineTooltip.svelte +++ b/web/src/lib/components/TimelineTooltip.svelte @@ -51,14 +51,17 @@ }); // --- tag tip --- - const tag = $derived(tip.kind === "tag" ? tip.tag : null); - const tagDT = $derived(tag ? dateTime(String(tag.date ?? "")) : ["", ""]); - const tagOid = $derived((tag?.oid ?? "").slice(0, 7)); - // Show the message only when it adds something beyond the tag name. - const tagMsg = $derived.by(() => { - const msg = (tag?.message ?? "").trim(); - return msg && msg !== (tag?.name ?? "").trim() ? msg : ""; - }); + // One or more tags sharing the hovered commit; they share date + oid, so the + // meta line is taken from the first. + const tags = $derived(tip.kind === "tag" ? tip.tags : []); + const tag0 = $derived(tags[0] ?? null); + const tagDT = $derived(tag0 ? dateTime(String(tag0.date ?? "")) : ["", ""]); + const tagOid = $derived((tag0?.oid ?? "").slice(0, 7)); + // A tag's message, only when it adds something beyond the tag name. + const tagMsg = (t: { name?: string; message?: string }): string => { + const msg = (t.message ?? "").trim(); + return msg && msg !== (t.name ?? "").trim() ? msg : ""; + }; // Place at the cursor: 12px to the right, flipped left near the right edge, // vertically centred, clamped to the viewport with an 8px margin. @@ -122,15 +125,26 @@ {#if ftypes.more > 0}+{ftypes.more}{/if}
{/if} - {:else if tag} + {:else if tag0}
- TAG{tag.name || ""} + {tags.length > 1 ? "TAGS" : "TAG"}{#if tags.length === 1}{tag0.name || ""}{/if}
- {#if tagMsg}
{tagMsg}
{/if} + {#if tags.length === 1} + {#if tagMsg(tag0)}
{tagMsg(tag0)}
{/if} + {:else} +
+ {#each tags as t (t.name)} +
+ {t.name || ""} + {tagMsg(t)} +
+ {/each} +
+ {/if} -
{tagDT[0] || tag.date || ""}{tagDT[1] ? " " + tagDT[1] : ""}{#if tagOid}{" · "}{tagOid}{/if}
+
{tagDT[0] || tag0.date || ""}{tagDT[1] ? " " + tagDT[1] : ""}{#if tagOid}{" · "}{tagOid}{/if}
{/if}
@@ -233,6 +247,32 @@ font-weight: 600; color: var(--text-primary); } + /* Tag rows as a 2-column table: names share a column so messages line up; + a hairline rule separates each row (mirrors .tt-bundle-item). */ + .tt-tag-group { + display: grid; + grid-template-columns: max-content 1fr; + margin: 4px 0; + } + .tt-tag-row { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; + gap: 0 12px; + padding-top: 5px; + margin-top: 5px; + border-top: 1px solid var(--border-default); + + &:first-child { + padding-top: 0; + margin-top: 0; + border-top: none; + } + } + .tt-tag-msg { + color: var(--text-muted); + overflow-wrap: anywhere; + } .tt-tag-icon { display: inline-block; width: 8px; diff --git a/web/src/lib/components/WeeklyCommitsCard.svelte b/web/src/lib/components/WeeklyCommitsCard.svelte new file mode 100644 index 0000000..c55a958 --- /dev/null +++ b/web/src/lib/components/WeeklyCommitsCard.svelte @@ -0,0 +1,85 @@ + + +
+
Weekly commits (stacked)
+
+ +
diff --git a/web/src/lib/format.ts b/web/src/lib/format.ts index 2d84cf1..205cb07 100644 --- a/web/src/lib/format.ts +++ b/web/src/lib/format.ts @@ -33,6 +33,34 @@ export function fmtBytes(bytes: number): string { return `${s} ${units[i]}`; } +// "12 minutes ago" / "2 days ago" / "1 year ago", relative to `now` (the +// browser's clock at render time, so a stale report reads as old). Returns "" +// for an unparseable timestamp. +export function relativeTime(iso: string | null | undefined, now: Date = new Date()): string { + if (!iso) return ""; + const t = new Date(iso).getTime(); + if (Number.isNaN(t)) return ""; + const secs = Math.max(0, Math.round((now.getTime() - t) / 1000)); + const ago = (n: number, w: string) => `${n} ${w}${n === 1 ? "" : "s"} ago`; + if (secs < 60) return "just now"; + const mins = Math.floor(secs / 60); + if (mins < 60) return ago(mins, "minute"); + const hours = Math.floor(mins / 60); + if (hours < 24) return ago(hours, "hour"); + const days = Math.floor(hours / 24); + if (days < 7) return ago(days, "day"); + if (days < 30) return ago(Math.floor(days / 7), "week"); + if (days < 365) return ago(Math.floor(days / 30), "month"); + return ago(Math.floor(days / 365), "year"); +} + +// Full timestamp for the hover title behind a relative time. "" when unparseable. +export function fmtDateTime(iso: string | null | undefined): string { + if (!iso) return ""; + const d = new Date(iso); + return Number.isNaN(d.getTime()) ? "" : d.toLocaleString(); +} + export const weekLabel = (w: string): string => { const [y, wn] = w.split("-W").map(Number); const jan4 = new Date(y, 0, 4); @@ -97,10 +125,23 @@ export function authorUrl(D: RepoData, c: Contributor): string { return `${D.githubBaseUrl}/commits/${encodeBranch(D.defaultBranch)}?author=${encodeURIComponent(c.email)}`; } -// GitHub code-search URL for a language within a repo, or '' when there's no -// GitHub base (local-only repo) or the bucket isn't a real language ("Other"). +// Synthetic buckets (see SYNTHETIC_COLORS in gen_techdata.py) aren't real GitHub +// languages, so `language:` can't resolve them. Map the ones with a clean extension +// set to a `path:` glob (grouped so the repo: scope covers every clause); the rest +// (e.g. "Tools" — a grab-bag of Dockerfiles/Makefiles/lockfiles) have no tidy query. +const SYNTHETIC_PATH_QUERY: Record = { + "Gettext Catalog": "(path:*.po OR path:*.pot)", +}; +const UNLINKED_BUCKETS = new Set(["Other", "Tools"]); + +// GitHub code-search URL for a language within a repo, or '' when there's no GitHub +// base (local-only repo) or the bucket has no resolvable query. export function langSearchUrl(base: string | null | undefined, name: string): string { const m = /^(https?:\/\/[^/]+)\/(.+?)\/?$/.exec(base || ""); - if (!m || name === "Other") return ""; - return `${m[1]}/search?q=${encodeURIComponent(`repo:${m[2]} language:${name}`)}&type=code`; + if (!m || UNLINKED_BUCKETS.has(name)) return ""; + const [, origin, repo] = m; + // Multi-word names must be quoted, or GitHub reads only the first word as the + // language (e.g. `language:Common Lisp` → `language:Common` + loose "Lisp"). + const query = SYNTHETIC_PATH_QUERY[name] ?? `language:${/\s/.test(name) ? `"${name}"` : name}`; + return `${origin}/search?q=${encodeURIComponent(`repo:${repo} ${query}`)}&type=code`; } diff --git a/web/src/lib/popover-store.svelte.ts b/web/src/lib/popover-store.svelte.ts index c583ca8..a20d8ff 100644 --- a/web/src/lib/popover-store.svelte.ts +++ b/web/src/lib/popover-store.svelte.ts @@ -24,6 +24,16 @@ export interface CommitPopoverState { export const authorState: AuthorPopoverState = $state({ c: null, idx: 0, anchor: null }); +// Repo-wide commit total, set once at startup so the popover can show each +// contributor's share of all commits. Kept here (not on each setAuthor call) +// because every consumer — table, timeline, churn axis, treemap — would +// otherwise have to thread the same total through. +export const authorMeta = $state({ totalCommits: 0 }); + +export function setAuthorTotalCommits(total: number): void { + authorMeta.totalCommits = total; +} + export const commitState: CommitPopoverState = $state({ c: null, colorIdx: 0, @@ -77,8 +87,8 @@ export interface TimelineTipState { c: TimelineBundle | null; author: Contributor | null; color: string; - // tag - tag: Tag | null; + // tag — one or more tags sharing the hovered commit (same dot) + tags: Tag[]; // cursor (viewport coords) x: number; y: number; @@ -89,7 +99,7 @@ export const timelineTipState: TimelineTipState = $state({ c: null, author: null, color: "", - tag: null, + tags: [], x: 0, y: 0, }); @@ -114,10 +124,20 @@ export function setCommitTip( timelineTipState.y = y; } -export function setTagTip(tag: Tag, x: number, y: number): void { - if (timelineTipState.kind !== "tag" || timelineTipState.tag?.oid !== tag.oid) { +export function setTagTip(tags: Tag[], x: number, y: number): void { + // Tags in a group share a dot, keyed by `oid || date` (timeline.ts's + // tagGroupKey) — lightweight tags carry no oid, so fall back to date or the + // stale tooltip would stick across date-keyed groups. First key + count + // identify the group. + const prevKey = timelineTipState.tags[0]?.oid || timelineTipState.tags[0]?.date; + const nextKey = tags[0]?.oid || tags[0]?.date; + if ( + timelineTipState.kind !== "tag" || + prevKey !== nextKey || + timelineTipState.tags.length !== tags.length + ) { timelineTipState.kind = "tag"; - timelineTipState.tag = tag; + timelineTipState.tags = tags; } timelineTipState.x = x; timelineTipState.y = y; diff --git a/web/src/lib/popovers.ts b/web/src/lib/popovers.ts index 7912bd5..ec7028d 100644 --- a/web/src/lib/popovers.ts +++ b/web/src/lib/popovers.ts @@ -110,7 +110,7 @@ export function createCommitPopover(D: RepoData): CommitPopover { // rebuilding when the hovered item is unchanged), hide on leave/drag/zoom. export interface TimelineTooltip { showCommit(c: TimelineBundle, author: Contributor, color: string, x: number, y: number): void; - showTag(tag: Tag, x: number, y: number): void; + showTag(tags: Tag[], x: number, y: number): void; hide(): void; } diff --git a/web/src/lib/timeline.ts b/web/src/lib/timeline.ts index a17b5df..7ddc268 100644 --- a/web/src/lib/timeline.ts +++ b/web/src/lib/timeline.ts @@ -2,7 +2,7 @@ // inertia, wheel/pinch zoom, a draggable histogram minimap, tag markers, and a // rich hover tooltip. Ported ~verbatim from template.html (imperative canvas / // pointer-event code that is wrapped, not rewritten). -import type { Commit, RepoData } from "$types"; +import type { Commit, RepoData, Tag } from "$types"; import { clr, gridLine, selectionFill, selectionStroke, accentWeekend } from "./theme"; import { authorUrl, escapeHtml } from "./format"; import type { AuthorPopover, TimelineTooltip } from "./popovers"; @@ -73,6 +73,16 @@ export function buildTimeline( return isNaN(+dt) ? 0 : +dt - +start; }); const hasTags = tags.length > 0; + // Tags on the same commit (shared oid) land on one dot; group them so the + // hover tip lists all of them rather than just whichever drew on top. + const tagGroupKey = (t: Tag) => String(t.oid || t.date || ""); + const tagGroups = new Map(); + for (const t of tags) { + const k = tagGroupKey(t); + const g = tagGroups.get(k); + if (g) g.push(t); + else tagGroups.set(k, [t]); + } const tagHeight = hasTags ? 16 : 0; const tagDotRadius = 3.5; const tagHitPad = 4; @@ -1163,7 +1173,7 @@ export function buildTimeline( } if (hit != null) { tagCanvas!.style.cursor = "pointer"; - tooltip.showTag(tags[hit], e.clientX, e.clientY); + tooltip.showTag(tagGroups.get(tagGroupKey(tags[hit])) ?? [tags[hit]], e.clientX, e.clientY); } else { tagCanvas!.style.cursor = ""; tooltip.hide(); diff --git a/web/src/styles/app.css b/web/src/styles/app.css index 81a8f77..a237937 100644 --- a/web/src/styles/app.css +++ b/web/src/styles/app.css @@ -193,6 +193,24 @@ h3 { gap: 16px; } +/* Shared chart-card layout primitives (used by every OverallCharts card). The + card must be position: relative so the .chart-title overlay and the legend's + Reset button anchor to it. The .ec containers size their ECharts canvas; the + taller .ec-tree is for the treemaps. */ +.chart-card { + position: relative; +} +.ec { + width: 100%; + height: 260px; +} +.ec-tree { + height: 320px; +} +.span-2 { + grid-column: 1 / -1; +} + .grid-5 { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); @@ -297,9 +315,26 @@ table { } } +.contributions-title { + display: flex; + align-items: baseline; + gap: 12px; + flex-wrap: wrap; + + .last-commit { + color: var(--text-muted); + font-size: 0.8rem; + + time { + cursor: help; + } + } +} + /* .contributor-card lives in ContributorCard.svelte; - .pattern-card in PatternCard.svelte; .chart-resettable / .chart-reset-btn in - OverallCharts.svelte. */ + .pattern-card in PatternCard.svelte; .chart-reset-btn / the legend rows in + ChartLegend.svelte. The OverallCharts cards live in their own *Card.svelte + files and share the .chart-card / .ec / .ec-tree / .span-2 primitives above. */ /* === Horizontal scroll rows (dragScroll action; runtime-toggled classes) === */ .scroll-row { diff --git a/web/src/types.ts b/web/src/types.ts index b332ed3..411e916 100644 --- a/web/src/types.ts +++ b/web/src/types.ts @@ -44,6 +44,8 @@ export interface Contributor { export interface Totals { commits: number; + /** Merge commits, additive to `commits` (not included in it); absent on the remote GraphQL path. */ + merges?: number; added: number; deleted: number; contributors: number; @@ -99,6 +101,14 @@ export interface RepoData { largestFiles: FileSizes | null; diskByPath: FileSizes | null; dateRange: DateRange; + /** ISO timestamp of the latest commit (HEAD), for the "updated N ago" note. */ + lastCommit?: string; + /** ISO timestamp of when this report was generated. */ + generatedAt?: string; + /** GitHub social counts; absent for non-GitHub or unreachable repos. */ + stars?: number | null; + watchers?: number | null; + forks?: number | null; totals: Totals; contributors: Contributor[]; weeks: string[]; diff --git a/web/vite.config.ts b/web/vite.config.ts index 77fee35..97ae077 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -23,6 +23,37 @@ function injectionMarker(): Plugin { }; } +// vite-plugin-singlefile inlines JS and CSS but never image assets, so the +// favicon would ship as a sibling hashed PNG the dashboard can't reach — the +// generated file is opened over file:// from /tmp, with no network guarantee. +// Fold the favicon into the single file as a base64 data URI: read its bytes +// straight from the bundle (no fs), rewrite the href, and drop the now- +// orphaned asset. enforce:"post" so it runs after singlefile's own output. +function inlineFavicon(): Plugin { + return { + name: "repo-intel:inline-favicon", + enforce: "post", + generateBundle(_options, bundle) { + const fav = Object.values(bundle).find( + (c) => c.type === "asset" && /favicon.*\.png$/.test(c.fileName), + ); + const html = Object.values(bundle).find( + (c) => c.type === "asset" && c.fileName.endsWith(".html"), + ); + if (fav?.type !== "asset" || html?.type !== "asset" || typeof html.source !== "string") { + return; + } + const bytes = + typeof fav.source === "string" ? new TextEncoder().encode(fav.source) : fav.source; + let binary = ""; + for (const b of bytes) binary += String.fromCharCode(b); + const dataUri = `data:image/png;base64,${btoa(binary)}`; + html.source = html.source.replace(new RegExp(`\\.?/${fav.fileName}`), dataUri); + delete bundle[fav.fileName]; + }, + }; +} + // Path aliases (mirrored in tsconfig.json's paths) for nicer imports: // $types → src/types.ts // $lib/* → src/lib/* @@ -37,7 +68,7 @@ const abs = (p: string) => { }; export default defineConfig({ - plugins: [svelte(), viteSingleFile(), injectionMarker()], + plugins: [svelte(), viteSingleFile(), injectionMarker(), inlineFavicon()], resolve: { alias: { $components: abs("./src/lib/components"),