From 7ffa6470a0d1ebfa42c290ed98e9d8eaeb78e1b7 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 12:34:19 +0100 Subject: [PATCH 01/18] Enrich the header with links, merge count, timestamps, and social counts - Link the commits/contributors/branches counts to their GitHub pages (text-colour, underlined, no underline on hover). - Headline now matches GitHub's commit count: show authored + merge commits as "N commits (M merges)". totals.commits stays the merge-free authored count (= sum of contributors' commits, the share denominator); merges live in a sibling totals.merges composed in only at display time. - Add "Generated N ago" (header, right) and "Last commit N ago" (Contributions section), both relative with the full timestamp on hover. - Add GitHub stars/watchers/forks via REST (github.com only, 5s timeout, degrades to absent for non-GitHub or unreachable repos). --- dist/repo-intel | 65 +++++++++++++- repo-intel.py | 63 ++++++++++++- web/src/App.svelte | 17 +++- web/src/lib/components/Header.svelte | 129 ++++++++++++++++++++++++--- web/src/lib/format.ts | 28 ++++++ web/src/styles/app.css | 16 ++++ web/src/types.ts | 10 +++ 7 files changed, 307 insertions(+), 21 deletions(-) diff --git a/dist/repo-intel b/dist/repo-intel index 017aa30..b994ad7 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 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( @@ -1017,6 +1017,14 @@ 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. Like branch_count/file_count, it is not + # filter-aware: under --since/--until it stays whole-history. + "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 +1130,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( @@ -1778,6 +1813,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 +1961,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 +2121,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']}`") @@ -2271,6 +2324,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 +2344,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/repo-intel.py b/repo-intel.py index 7a50568..d856e1f 100755 --- a/repo-intel.py +++ b/repo-intel.py @@ -1017,6 +1017,14 @@ 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. Like branch_count/file_count, it is not + # filter-aware: under --since/--until it stays whole-history. + "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 +1130,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( @@ -1778,6 +1813,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 +1961,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 +2121,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']}`") @@ -2271,6 +2324,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 +2344,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/web/src/App.svelte b/web/src/App.svelte index 71881f4..a818d8e 100644 --- a/web/src/App.svelte +++ b/web/src/App.svelte @@ -11,7 +11,7 @@ createTimelineTooltip, buildPunchPoints, } from "$lib/popovers"; - import { fmtTimelineDuration } from "$lib/format"; + import { fmtTimelineDuration, relativeTime, fmtDateTime } from "$lib/format"; import { registerEchartsTheme } from "$lib/theme"; import { buildTimeline } from "$lib/timeline"; import { dragScroll, scrollSpy } from "$lib/actions"; @@ -41,6 +41,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 @@ -89,7 +93,16 @@
-

Contributions

+
+

Contributions

+ {#if lastCommitAgo} + Last commit + {/if} +
(heatmapMode = mode)} />
diff --git a/web/src/lib/components/Header.svelte b/web/src/lib/components/Header.svelte index fed1dcf..42fa236 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} +

- {data.dateRange.start} — {data.dateRange.end} · {fmt(totals.commits)} commits · + {data.dateRange.start} — {data.dateRange.end} · {#if commitsUrl}{commitsLabel}{:else}{commitsLabel}{/if}{#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}) · {#if contributorsUrl}{contribLabel}{:else}{contribLabel}{/if}{#if branchCount != null}{" "}· {#if branchesUrl}{branchLabel}{:else}{branchLabel}{/if}{/if}{#if fileCount != null}{" "}· {fmt(fileCount)} files{/if}{#if sizeStr}{" "}· + {sizeStr}{/if}

+ + diff --git a/web/src/lib/format.ts b/web/src/lib/format.ts index 2d84cf1..b236955 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); diff --git a/web/src/styles/app.css b/web/src/styles/app.css index 81a8f77..fc0187d 100644 --- a/web/src/styles/app.css +++ b/web/src/styles/app.css @@ -297,6 +297,22 @@ 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. */ 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[]; From f48ed2fbd5e92295e85f2ee00867ca5ce5aeb5d8 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 12:34:43 +0100 Subject: [PATCH 02/18] Group co-located tags in the timeline hover tooltip Tags on the same commit (shared oid) draw on one dot, so only the topmost was discoverable. The tag tip now lists every tag at that commit as a two-column table (names aligned, hairline row separators), with the shared date and oid below. --- web/src/lib/components/TimelineTooltip.svelte | 68 +++++++++++++++---- web/src/lib/popover-store.svelte.ts | 17 +++-- web/src/lib/popovers.ts | 2 +- web/src/lib/timeline.ts | 14 +++- 4 files changed, 78 insertions(+), 23 deletions(-) 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/popover-store.svelte.ts b/web/src/lib/popover-store.svelte.ts index c583ca8..88ad7f1 100644 --- a/web/src/lib/popover-store.svelte.ts +++ b/web/src/lib/popover-store.svelte.ts @@ -77,8 +77,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 +89,7 @@ export const timelineTipState: TimelineTipState = $state({ c: null, author: null, color: "", - tag: null, + tags: [], x: 0, y: 0, }); @@ -114,10 +114,15 @@ 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 commit (oid), so the first oid + count identify it. + if ( + timelineTipState.kind !== "tag" || + timelineTipState.tags[0]?.oid !== tags[0]?.oid || + 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(); From ac1d33a70c4424bf52bdcd744fea1b5e25d8110b Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 12:34:58 +0100 Subject: [PATCH 03/18] Dim punch-card row separators so the weekend tint stays calm The Sat/Sun grid line sits inside the weekend tint band, which amplified it into the chart's boldest rule. Lower the uniform splitLine opacity so it reads as a normal subdivision again. Tints unchanged. --- web/src/lib/components/PatternCard.svelte | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web/src/lib/components/PatternCard.svelte b/web/src/lib/components/PatternCard.svelte index 0dab0c0..725df5d 100644 --- a/web/src/lib/components/PatternCard.svelte +++ b/web/src/lib/components/PatternCard.svelte @@ -73,7 +73,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] From 8407e8295167355f88d29d6d30b870eff02427f5 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 12:35:07 +0100 Subject: [PATCH 04/18] Widen the technologies grid column gap --- web/src/lib/components/TechGrid.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 { From 74d41d580926f1920501283bd6297b235a7d2acc Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 12:44:39 +0100 Subject: [PATCH 05/18] Document tag-sync caveat and add a git gc make target --- Makefile | 8 +++++++- README.md | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) 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 From 6675844e511022f846c176d4362fe6a4e5d57e40 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 13:36:31 +0100 Subject: [PATCH 06/18] Replace ECharts legends with HTML legends carrying author popovers The weekly-commits and commit-share charts aggregate contributors by email, so one person committing under several addresses shows up as several rows sharing a display name. ECharts keys legend selection by series name, collapsing those into one toggle. Name the series/slices by email instead, hide ECharts' own legend, and render HTML legends that toggle selection and carry the same author popover the timeline lanes use. Add matching name links + popovers to the contributor and pattern cards, with aria-pressed on the legend toggles and non-navigating labels on local-only repos. --- dist/repo-intel | 2 +- web/src/App.svelte | 8 +- web/src/lib/components/ContributorCard.svelte | 37 ++- web/src/lib/components/OverallCharts.svelte | 235 ++++++++++++++---- web/src/lib/components/PatternCard.svelte | 33 ++- 5 files changed, 266 insertions(+), 49 deletions(-) diff --git a/dist/repo-intel b/dist/repo-intel index b994ad7..9cf6f50 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 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( diff --git a/web/src/App.svelte b/web/src/App.svelte index a818d8e..92aa95a 100644 --- a/web/src/App.svelte +++ b/web/src/App.svelte @@ -11,7 +11,7 @@ createTimelineTooltip, buildPunchPoints, } from "$lib/popovers"; - import { fmtTimelineDuration, relativeTime, fmtDateTime } from "$lib/format"; + import { authorUrl, fmtTimelineDuration, relativeTime, fmtDateTime } from "$lib/format"; import { registerEchartsTheme } from "$lib/theme"; import { buildTimeline } from "$lib/timeline"; import { dragScroll, scrollSpy } from "$lib/actions"; @@ -132,14 +132,16 @@

Overall

- +

Commit frequency over time

{#each data.contributors as c, i (c.email)} {#each data.contributors as c, i (c.email)}
#{index + 1}
-
{contributor.name}
+ + authorPopover?.show(index, e.currentTarget)} + onmouseleave={() => authorPopover?.hide()}>{contributor.name}
{fmt(contributor.commits)} commits {fmt(contributor.added)} ++ @@ -68,9 +90,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/OverallCharts.svelte b/web/src/lib/components/OverallCharts.svelte index 5fa3137..cd42803 100644 --- a/web/src/lib/components/OverallCharts.svelte +++ b/web/src/lib/components/OverallCharts.svelte @@ -7,6 +7,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { echart } from "$lib/actions"; import { fmtBytes, weekLabel } from "$lib/format"; + import type { AuthorPopover } from "$lib/popovers"; import { bgCard, bgPrimary, @@ -20,7 +21,41 @@ import type { FileSizes, RepoData } from "$types"; import type { EChartsCoreOption, EChartsType } from "echarts/core"; - let { data }: { data: RepoData } = $props(); + let { data, authorPopover }: { data: RepoData; authorPopover: AuthorPopover | undefined } = + $props(); + + // Contributors are aggregated by email, so one person who committed under + // several addresses (old work emails, a noreply alias) shows up as several + // rows that all share one display name. ECharts keys legend selection by the + // series/slice name, so identical names would collapse into a single legend + // entry and toggle together. We therefore name every series/slice by its + // (unique) email under the hood, hide ECharts' own legend, and render our own + // HTML legend below — plain names, one entry per identity, each with the same + // author popover the timeline lanes use, so duplicate names are told apart on + // hover rather than by cluttering the label. `nameByEmail` maps the email back + // to a display name for tooltips. + const nameByEmail = $derived(new Map(data.contributors.map((c) => [c.email, c.name] as const))); + const dispName = (email: string): string => nameByEmail.get(email) ?? email; + + // Legend rows for the weekly-commits line and the commit-share pie. The pie + // gains a non-author "Others" row when the top-N don't cover every commit + // (see the pie option); it toggles like the rest but has no popover. + type LegendItem = { key: string; name: string; color: string; idx: number }; + const contribLegend = $derived( + data.contributors.map((c, i) => ({ key: c.email, name: c.name, color: clr(i), idx: i })), + ); + // Commits not covered by the top-N contributors → the pie's "Others" slice. + // Single source of truth so the slice and its legend row can't drift apart. + const othersCommits = $derived( + data.totals.commits - data.contributors.reduce((acc, c) => acc + c.commits, 0), + ); + // The pie's legend mirrors its slices: the contributors plus the "Others" + // remainder (idx -1 → no popover) when the top-N don't cover every commit. + const pieLegend = $derived( + othersCommits > 0 + ? [...contribLegend, { key: "Others", name: "Others", color: borderDefault, idx: -1 }] + : contribLegend, + ); // Hide the languages treemap entirely when no contributor has a language mix, // rather than rendering an empty chart. @@ -215,29 +250,49 @@ // languages treemap, which shares this border). const tileInnerBorder = "rgba(0, 0, 0, 0.6)"; - // The Reset button shows (via .has-hidden on the card) once the legend has - // hidden at least one series, and re-selects everything when clicked. - let timelineHasHidden = $state(false); - let pieHasHidden = $state(false); + // Our HTML legends drive ECharts' (hidden) legend selection by dispatching + // legendToggleSelect/legendAllSelect. The chart still owns the source of truth + // for what's hidden — we mirror its `selected` map back into Svelte state so a + // legend row dims when its series is off, and the Reset button shows once + // anything is hidden. Keyed by the series name (the contributor's email, or + // "Others" on the pie). A missing key means selected (the initial state). + let timelineSel = $state>({}); + let pieSel = $state>({}); let timelineChart: EChartsType | undefined; let pieChart: EChartsType | undefined; - const someHidden = (p: any): boolean => Object.values(p.selected).some((v) => v === false); + const isHidden = (sel: Record, key: string): boolean => sel[key] === false; + const anyHidden = (sel: Record): boolean => + Object.values(sel).some((v) => v === false); + const timelineHasHidden = $derived(anyHidden(timelineSel)); + const pieHasHidden = $derived(anyHidden(pieSel)); + function onTimelineReady(c: EChartsType): void { timelineChart = c; - c.on("legendselectchanged", (p: any) => (timelineHasHidden = someHidden(p))); + c.on("legendselectchanged", (p: any) => (timelineSel = { ...p.selected })); } function onPieReady(c: EChartsType): void { pieChart = c; - c.on("legendselectchanged", (p: any) => (pieHasHidden = someHidden(p))); + c.on("legendselectchanged", (p: any) => (pieSel = { ...p.selected })); + } + function toggleTimeline(key: string): void { + timelineChart?.dispatchAction({ type: "legendToggleSelect", name: key }); + } + function togglePie(key: string): void { + pieChart?.dispatchAction({ type: "legendToggleSelect", name: key }); } function resetTimeline(): void { timelineChart?.dispatchAction({ type: "legendAllSelect" }); - timelineHasHidden = false; + timelineSel = {}; } function resetPie(): void { pieChart?.dispatchAction({ type: "legendAllSelect" }); - pieHasHidden = false; + pieSel = {}; + } + // Author popover on legend hover, mirroring the timeline lane labels. The + // "Others" pie row has idx < 0 (no contributor), so it gets no popover. + function legendEnter(e: MouseEvent, idx: number): void { + if (idx >= 0) authorPopover?.show(idx, e.currentTarget as Element); } // ECharts' treemap view forces a pointer cursor on every node (and on the root @@ -328,20 +383,27 @@ // All five chart options, derived from data (data is set once at mount, but // $derived keeps the reads reactive and avoids capturing only the initial value). const opts = $derived.by(() => { - const { contributors, totals, weeks, weeklyData } = data; - // Top-N commit subtotal, so the pie's "Others" slice is the remainder. - const subC = contributors.reduce((acc, c) => acc + c.commits, 0); + const { contributors, weeks, weeklyData } = data; const timeline: EChartsCoreOption = { - tooltip: { trigger: "axis" }, - legend: { - top: 42, - type: "scroll", - itemWidth: 10, - itemHeight: 10, - textStyle: { fontSize: 10 }, + // Series are named by email (unique), so map back to the display name and + // drop zero-commit weeks to keep the stacked tooltip readable. + tooltip: { + trigger: "axis", + formatter: (ps: any) => { + const arr = Array.isArray(ps) ? ps : [ps]; + const head = arr[0]?.axisValueLabel ?? ""; + const rows = arr + .filter((p: any) => p.value) + .map((p: any) => `${p.marker}${dispName(p.seriesName)}: ${p.value}`) + .join("
"); + return rows ? (head ? `${head}
${rows}` : rows) : head; + }, }, - grid: { left: 36, right: 14, top: 76, bottom: 34 }, + // ECharts' own legend is hidden; the HTML legend below drives selection. + legend: { show: false }, + // No built-in legend to clear up top now — just the floating title strip. + grid: { left: 36, right: 14, top: 38, bottom: 34 }, xAxis: { type: "category", boundaryGap: false, @@ -350,7 +412,7 @@ }, yAxis: { type: "value", min: 0 }, series: contributors.map((c, i) => ({ - name: c.name, + name: c.email, type: "line", stack: "total", smooth: true, @@ -367,38 +429,30 @@ }; const pie: EChartsCoreOption = { - tooltip: { trigger: "item", formatter: "{b}: {c} ({d}%)" }, - legend: { - type: "scroll", - orient: "vertical", - right: 8, - top: "middle", - itemWidth: 10, - itemHeight: 10, - textStyle: { fontSize: 11 }, + // Slices are named by email (unique); map back for the tooltip. "Others" + // isn't an email, so dispName falls through to it unchanged. + tooltip: { + trigger: "item", + formatter: (p: any) => `${dispName(p.name)}: ${p.value} (${p.percent}%)`, }, + // ECharts' own legend is hidden; the HTML legend beside it drives selection. + legend: { show: false }, series: [ { type: "pie", cursor: "default", radius: ["50%", "72%"], - center: ["42%", "56%"], + center: ["50%", "50%"], data: [ ...contributors.map((c, i) => ({ - name: c.name, + name: c.email, value: c.commits, itemStyle: { color: clr(i) }, })), // Only show "Others" when the top-N contributors don't cover every // commit; otherwise it's a 0-value slice cluttering the legend. - ...(totals.commits - subC > 0 - ? [ - { - name: "Others", - value: totals.commits - subC, - itemStyle: { color: borderDefault }, - }, - ] + ...(othersCommits > 0 + ? [{ name: "Others", value: othersCommits, itemStyle: { color: borderDefault } }] : []), ], itemStyle: { borderColor: bgCard, borderWidth: 2 }, @@ -559,15 +613,46 @@ const filesOption = $derived(activeFilesTab === "head" ? opts.headFiles : opts.histFiles); + +{#snippet legendItem(item: LegendItem, hidden: boolean, toggle: (key: string) => void)} + +{/snippet} +
Weekly commits (stacked)
+
+ {#each contribLegend as item (item.key)} + {@render legendItem(item, isHidden(timelineSel, item.key), toggleTimeline)} + {/each} +
Commit share
-
+
+
+
+ {#each pieLegend as item (item.key)} + {@render legendItem(item, isHidden(pieSel, item.key), togglePie)} + {/each} +
+
@@ -641,6 +726,72 @@ .span-2 { grid-column: 1 / -1; } + + /* The commit-share donut and its legend sit side by side; the donut takes the + remaining width while the legend column scrolls if there are many people. */ + .pie-body { + display: flex; + align-items: center; + gap: 4px; + } + .ec-pie { + flex: 1 1 0; + min-width: 0; + width: auto; + } + .chart-legend-col { + display: flex; + flex-direction: column; + justify-content: center; + flex-shrink: 0; + max-width: 45%; + max-height: 240px; + overflow-y: auto; + } + /* The weekly-commits legend wraps as a centered row beneath the chart. */ + .chart-legend-row { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 2px 4px; + margin-top: 6px; + } + /* One legend entry: swatch + plain name. Mirrors the timeline lane labels — + hover opens the author popover, click toggles the series (dimmed when off). */ + .legend-item { + display: inline-flex; + align-items: center; + gap: 5px; + max-width: 100%; + padding: 2px 5px; + border: 0; + border-radius: 4px; + background: transparent; + color: var(--text-muted); + font-family: inherit; + font-size: 0.72rem; + line-height: 1.3; + cursor: pointer; + + &:hover { + color: var(--text-primary); + background: var(--bg-badge); + } + &.hidden { + opacity: 0.4; + } + } + .legend-dot { + flex-shrink: 0; + width: 9px; + height: 9px; + border-radius: 50%; + } + .legend-name { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } /* The files treemap hugs the top edge, so the default translucent + blurred title strip would smear the tiles beneath it. Give this card's header a flat opaque fill (no gradient fade, no backdrop blur) for a clean divide. */ diff --git a/web/src/lib/components/PatternCard.svelte b/web/src/lib/components/PatternCard.svelte index 725df5d..8b58116 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; @@ -133,7 +139,20 @@ @@ -142,6 +161,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; From 74e4714f9187f6dbfd2c5fa65c1823771028a3d3 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 13:54:16 +0100 Subject: [PATCH 07/18] Render commit share as a labelled pie and skip bot profile lookups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the commit-share donut to a larger solid pie with outside name + share labels. minShowLabelAngle drops the label (and its leader line) for sectors under ~4% of the circle; being angle-based, labels reappear as the legend hides bigger slices and the survivors widen. Hovering a legend row now highlights its slice, scaling it out a touch. Also skip bot accounts (logins ending in [bot]) in the GraphQL profile fetch — they're Bot nodes, not User nodes, so user(login:) only ever returns NOT_FOUND. Benign NOT_FOUND errors are no longer warned about. --- dist/repo-intel | 15 +++- repo-intel.py | 13 +++- web/src/lib/components/OverallCharts.svelte | 83 +++++++++++++++------ 3 files changed, 82 insertions(+), 29 deletions(-) diff --git a/dist/repo-intel b/dist/repo-intel index 9cf6f50..73e8ed9 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 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( @@ -1231,7 +1231,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: @@ -1254,8 +1257,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): diff --git a/repo-intel.py b/repo-intel.py index d856e1f..6104ebc 100755 --- a/repo-intel.py +++ b/repo-intel.py @@ -1231,7 +1231,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: @@ -1254,8 +1257,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): diff --git a/web/src/lib/components/OverallCharts.svelte b/web/src/lib/components/OverallCharts.svelte index cd42803..4a39258 100644 --- a/web/src/lib/components/OverallCharts.svelte +++ b/web/src/lib/components/OverallCharts.svelte @@ -17,6 +17,7 @@ colorDeleted, contrastText, textMuted, + textPrimary, } from "$lib/theme"; import type { FileSizes, RepoData } from "$types"; import type { EChartsCoreOption, EChartsType } from "echarts/core"; @@ -294,6 +295,12 @@ function legendEnter(e: MouseEvent, idx: number): void { if (idx >= 0) authorPopover?.show(idx, e.currentTarget as Element); } + // Hovering a pie legend row emphasises the matching slice (keyed by email, or + // "Others"), so it scales out per the series' emphasis config; leaving downplays + // it. Highlight is addressed by slice name, the same key the legend toggles use. + function pieHighlight(key: string, on: boolean): void { + pieChart?.dispatchAction({ type: on ? "highlight" : "downplay", name: key }); + } // ECharts' treemap view forces a pointer cursor on every node (and on the root // background) and ignores series.cursor, so override it to the default after @@ -428,6 +435,19 @@ })), }; + const pieSlices = [ + ...contributors.map((c, i) => ({ + name: c.email, + value: c.commits, + itemStyle: { color: clr(i) }, + })), + // Only show "Others" when the top-N contributors don't cover every commit; + // otherwise it's a 0-value slice cluttering the legend. + ...(othersCommits > 0 + ? [{ name: "Others", value: othersCommits, itemStyle: { color: borderDefault } }] + : []), + ]; + const pie: EChartsCoreOption = { // Slices are named by email (unique); map back for the tooltip. "Others" // isn't an email, so dispName falls through to it unchanged. @@ -441,24 +461,31 @@ { type: "pie", cursor: "default", - radius: ["50%", "72%"], - center: ["50%", "50%"], - data: [ - ...contributors.map((c, i) => ({ - name: c.email, - value: c.commits, - itemStyle: { color: clr(i) }, - })), - // Only show "Others" when the top-N contributors don't cover every - // commit; otherwise it's a 0-value slice cluttering the legend. - ...(othersCommits > 0 - ? [{ name: "Others", value: othersCommits, itemStyle: { color: borderDefault } }] - : []), - ], + radius: "72%", + center: ["50%", "52%"], + data: pieSlices, itemStyle: { borderColor: bgCard, borderWidth: 2 }, - label: { show: false }, - labelLine: { show: false }, - emphasis: { scale: false }, + // Outside labels carry the name + share. The long tail of tiny slices + // would only collide into an unreadable fan, so minShowLabelAngle drops + // the label (and its leader line) for any sector narrower than ~4% of + // the circle. It's angle-based, so when the legend hides the big slices + // the survivors widen past the threshold and their labels reappear — + // unlike a static per-slice flag. hideOverlap prunes any that still + // touch. Every identity is always present in the legend regardless. + minShowLabelAngle: 14, + label: { + show: true, + formatter: (p: any) => `{n|${dispName(p.name)}}\n{p|${p.percent}%}`, + rich: { + n: { color: textPrimary, fontSize: 12, lineHeight: 16 }, + p: { color: textMuted, fontSize: 11, lineHeight: 14 }, + }, + }, + labelLine: { length: 10, length2: 12 }, + labelLayout: { hideOverlap: true }, + // Hovering a legend row highlights the matching slice (see pieHighlight), + // which scales it out a touch; scaleSize is the radial nudge in px. + emphasis: { scale: true, scaleSize: 8 }, }, ], }; @@ -617,14 +644,25 @@ opens the same author popover the timeline lanes use (so people committing under several emails are told apart on hover, not in the label); click toggles the matching series via ECharts' hidden legend. --> -{#snippet legendItem(item: LegendItem, hidden: boolean, toggle: (key: string) => void)} +{#snippet legendItem( + item: LegendItem, + hidden: boolean, + toggle: (key: string) => void, + emphasize?: (key: string, on: boolean) => void, +)}
@@ -727,7 +765,7 @@ grid-column: 1 / -1; } - /* The commit-share donut and its legend sit side by side; the donut takes the + /* The commit-share pie and its legend sit side by side; the pie takes the remaining width while the legend column scrolls if there are many people. */ .pie-body { display: flex; @@ -738,6 +776,7 @@ flex: 1 1 0; min-width: 0; width: auto; + height: 320px; } .chart-legend-col { display: flex; From 66c9eb2c208236e77aa9a55e95098c345c998f34 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 14:25:08 +0100 Subject: [PATCH 08/18] Recast the churn chart as diverging bars with author labels Replace the grouped added/deleted bars with horizontal diverging bars (deleted left of zero, added right), sorted by total churn and filtered of [bot] accounts so the human contributors keep the scale. The y-axis labels carry the identity dot, name, and author popover used elsewhere, and click through to the contributor's commits. The legend moves into the title as colour squares, and the value labels drop their stroke. --- dist/repo-intel | 2 +- web/src/lib/components/OverallCharts.svelte | 153 ++++++++++++++++++-- 2 files changed, 142 insertions(+), 13 deletions(-) diff --git a/dist/repo-intel b/dist/repo-intel index 73e8ed9..1653b09 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 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( diff --git a/web/src/lib/components/OverallCharts.svelte b/web/src/lib/components/OverallCharts.svelte index 4a39258..8aa4685 100644 --- a/web/src/lib/components/OverallCharts.svelte +++ b/web/src/lib/components/OverallCharts.svelte @@ -6,7 +6,7 @@ // through the `echart` action (div + setOption + auto-resize + dispose). /* eslint-disable @typescript-eslint/no-explicit-any */ import { echart } from "$lib/actions"; - import { fmtBytes, weekLabel } from "$lib/format"; + import { authorUrl, fmtBytes, weekLabel } from "$lib/format"; import type { AuthorPopover } from "$lib/popovers"; import { bgCard, @@ -37,6 +37,10 @@ // to a display name for tooltips. const nameByEmail = $derived(new Map(data.contributors.map((c) => [c.email, c.name] as const))); const dispName = (email: string): string => nameByEmail.get(email) ?? email; + // Email → original contributor index, so the churn chart's axis-label hover can + // resolve the right person (and their clr() colour / popover) even after that + // chart filters bots and re-sorts its own local copy. + const emailToOrig = $derived(new Map(data.contributors.map((c, i) => [c.email, i] as const))); // Legend rows for the weekly-commits line and the commit-share pie. The pie // gains a non-author "Others" row when the top-N don't cover every commit @@ -276,6 +280,48 @@ pieChart = c; c.on("legendselectchanged", (p: any) => (pieSel = { ...p.selected })); } + // The churn chart's y-axis labels carry the same author popover as the timeline + // lanes. ECharts axis labels are canvas, not DOM, so triggerEvent surfaces one + // mouseover/mouseout per label with the category value (the unique email); we + // anchor the popover to the cursor via a synthetic rect, which is all + // authorPopover.show reads off the element. + function onChurnReady(c: EChartsType): void { + c.on("mouseover", (p: any) => { + if (p.componentType !== "yAxis" || p.targetType !== "axisLabel") return; + const idx = emailToOrig.get(p.value); + if (idx == null) return; + // Anchor at the cursor when the native event rode along; otherwise fall + // back to the label's row centre via the chart geometry (as PatternCard + // does for its punch-card cells), so the popover lands regardless. + let x: number, y: number; + const ev = p.event?.event as MouseEvent | undefined; + if (ev) { + x = ev.clientX; + y = ev.clientY; + } else { + const py = c.convertToPixel({ yAxisIndex: 0 }, p.value) as number; + if (py == null || Number.isNaN(py)) return; + const dom = c.getDom().getBoundingClientRect(); + x = dom.left + 24; + y = dom.top + py; + } + const rect = { left: x, right: x, top: y, bottom: y, width: 0, height: 0, x, y } as DOMRect; + authorPopover?.show(idx, { getBoundingClientRect: () => rect } as Element); + }); + c.on("mouseout", (p: any) => { + if (p.componentType === "yAxis" && p.targetType === "axisLabel") authorPopover?.hide(); + }); + // triggerEvent gives the labels a pointer cursor, so make them behave like the + // timeline lane labels: click opens the contributor's commits. Local-only repos + // have no GitHub base (authorUrl → "#"), so there's nothing to open. + c.on("click", (p: any) => { + if (p.componentType !== "yAxis" || p.targetType !== "axisLabel") return; + const idx = emailToOrig.get(p.value); + if (idx == null) return; + const url = authorUrl(data, data.contributors[idx]); + if (url !== "#") window.open(url, "_blank", "noopener"); + }); + } function toggleTimeline(key: string): void { timelineChart?.dispatchAction({ type: "legendToggleSelect", name: key }); } @@ -490,30 +536,95 @@ ], }; + // Diverging horizontal bars: deleted extends left of the zero axis, added + // right, so each person's net balance reads as whichever side is longer. + // Bots (the `[bot]` logins repo-intel.py skips for profiles) are dropped — + // a Renovate/CI account churning tens of thousands of lines is noise here + // and only flattens the human contributors' scale. Sorted by total churn + // (added + deleted) so the busiest sit at the top (yAxis is inverted, since + // ECharts otherwise draws the first category at the bottom). Local copy: the + // shared `contributors` is index-keyed for the line/pie colours, so sorting + // or filtering it in place would corrupt them. Linear scale with per-bar + // labels keeps even a one-pixel bar legible despite the heavy skew. + // Rows carry their original contributor index so the axis label can show the + // person's identity colour (clr) and dot, matching every other chart, and the + // hover popover can resolve the right person. Categories are keyed by email + // (unique) — two people sharing a display name would otherwise collapse into + // one band. + const addDelRows = contributors + .map((c, origIdx) => ({ c, origIdx })) + .filter((r) => !r.c.login.endsWith("[bot]")) + .sort((a, b) => b.c.added + b.c.deleted - (a.c.added + a.c.deleted)); + const abs = (v: number) => Math.abs(v).toLocaleString(); + // One rich-text style per row for its identity-coloured dot; the name shares a + // single muted style. Keyed by row position (d0, d1, …), which is what the + // axisLabel formatter receives as its index. + const dotRich = Object.fromEntries( + addDelRows.map((r, i) => [`d${i}`, { color: clr(r.origIdx), fontSize: 12 }]), + ); const addDel: EChartsCoreOption = { - tooltip: { trigger: "axis" }, - legend: { top: 42, itemWidth: 10, itemHeight: 10 }, - grid: { left: 56, right: 14, top: 76, bottom: 40 }, - xAxis: { + tooltip: { + trigger: "axis", + axisPointer: { type: "shadow" }, + formatter: (ps: any) => { + const arr = Array.isArray(ps) ? ps : [ps]; + const rows = arr + .map((p: any) => `${p.marker}${p.seriesName}: ${abs(p.value)}`) + .join("
"); + return `${dispName(arr[0]?.axisValue ?? "")}
${rows}`; + }, + }, + grid: { left: 120, right: 56, top: 16, bottom: 24 }, + // Deleted lives on the negative side, so strip the minus sign from ticks. + xAxis: { type: "value", axisLabel: { formatter: (v: number) => abs(v) } }, + yAxis: { type: "category", - data: contributors.map((c) => c.name), - axisLabel: { rotate: 35, fontSize: 10 }, + inverse: true, + triggerEvent: true, + data: addDelRows.map((r) => r.c.email), + axisLabel: { + margin: 10, + formatter: (email: string, i: number) => + `{d${i}|●}{n|${nameByEmail.get(email) ?? email}}`, + rich: { + ...dotRich, + n: { color: textMuted, fontSize: 10, padding: [0, 0, 0, 5] }, + }, + }, }, - yAxis: { type: "value", min: 0 }, series: [ { name: "Added", type: "bar", + stack: "churn", cursor: "default", - data: contributors.map((c) => c.added), + data: addDelRows.map((r) => r.c.added), itemStyle: { color: colorAdded }, + label: { + show: true, + position: "right", + fontSize: 9, + color: textMuted, + textBorderWidth: 0, + formatter: (p: any) => (p.value ? abs(p.value) : ""), + }, }, { name: "Deleted", type: "bar", + stack: "churn", cursor: "default", - data: contributors.map((c) => c.deleted), + // Negated so the bar grows left from zero; tooltip/label/ticks re-abs. + data: addDelRows.map((r) => -r.c.deleted), itemStyle: { color: colorDeleted }, + label: { + show: true, + position: "left", + fontSize: 9, + color: textMuted, + textBorderWidth: 0, + formatter: (p: any) => (p.value ? abs(p.value) : ""), + }, }, ], }; @@ -694,8 +805,11 @@
-
Lines added vs deleted
-
+
+ Lines added vs + deleted +
+
Net lines per commit
@@ -761,6 +875,21 @@ .ec-tree { height: 320px; } + /* Horizontal diverging bars need a row of vertical space each; give the churn + chart a little more height than the default so ~10 contributors stay legible. */ + .ec-churn { + height: 300px; + } + /* Small colour keys inline in the churn title, standing in for a legend: green + for added, red for deleted, beside the words they label. */ + .title-sq { + display: inline-block; + width: 9px; + height: 9px; + margin: 0 5px 0 9px; + border-radius: 2px; + vertical-align: middle; + } .span-2 { grid-column: 1 / -1; } From 419ac6be011f9cacd9ebda95e9df16463610171b Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 14:45:15 +0100 Subject: [PATCH 09/18] Recast net-lines-per-commit as a commit-style scatter and balance the churn axis --- dist/repo-intel | 2 +- web/src/lib/components/OverallCharts.svelte | 131 +++++++++++++++++--- 2 files changed, 113 insertions(+), 20 deletions(-) diff --git a/dist/repo-intel b/dist/repo-intel index 1653b09..30b8489 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 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( diff --git a/web/src/lib/components/OverallCharts.svelte b/web/src/lib/components/OverallCharts.svelte index 8aa4685..9e0a475 100644 --- a/web/src/lib/components/OverallCharts.svelte +++ b/web/src/lib/components/OverallCharts.svelte @@ -1,6 +1,6 @@ \n \n \n \n \n
\n \n\n' +TEMPLATE = '\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( diff --git a/web/src/App.svelte b/web/src/App.svelte index 92aa95a..be594ad 100644 --- a/web/src/App.svelte +++ b/web/src/App.svelte @@ -12,6 +12,7 @@ buildPunchPoints, } from "$lib/popovers"; 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"; @@ -65,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()); 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/OverallCharts.svelte b/web/src/lib/components/OverallCharts.svelte index 9e0a475..b83070e 100644 --- a/web/src/lib/components/OverallCharts.svelte +++ b/web/src/lib/components/OverallCharts.svelte @@ -362,6 +362,46 @@ }; chart.on("finished", useDefaultCursor); useDefaultCursor(); + + // Hovering a contributor's name strip opens the same author popover the + // timeline lanes and churn axis use. Only the contributor containers carry an + // `idx` (the language tiles don't), so hovering a leaf tile hides it. We anchor + // a zero-size rect at the cursor, exactly as onChurnReady does for its + // canvas-rendered axis labels. + // + // The header strip is several zrender elements (the container rect + its text + // label), so a naive re-anchor on every `mouseover` makes the popover jump as + // the cursor crosses element boundaries within one strip. We therefore key on + // the contributor `idx` and only (re)anchor when it actually changes — moving + // around inside one section is a no-op, which keeps the popover still. + let shownIdx = -1; + chart.on("mouseover", (p: any) => { + const idx = p.data?.idx; + if (idx == null) { + // A language tile, the gap, or the root — i.e. we've left the name region. + if (shownIdx !== -1) { + authorPopover?.hide(); + shownIdx = -1; + } + return; + } + if (idx === shownIdx) return; + const ev = p.event?.event as MouseEvent | undefined; + if (!ev) return; + shownIdx = idx; + const x = ev.clientX; + const y = ev.clientY; + const rect = { left: x, right: x, top: y, bottom: y, width: 0, height: 0, x, y } as DOMRect; + authorPopover?.show(idx, { getBoundingClientRect: () => rect } as Element); + }); + // Leaving the chart entirely (between cards, off the canvas) closes the popover; + // mouseout per-element would fire mid-strip and re-trigger the jump above. + chart.getZr().on("globalout", () => { + if (shownIdx !== -1) { + authorPopover?.hide(); + shownIdx = -1; + } + }); } // Files treemaps drill by re-rooting (dispatchAction treemapRootToNode), which @@ -807,6 +847,10 @@ const langs = [...c.languages].sort((a, b) => b.pct - a.pct); return { name: c.name, + // `idx` lets the hover handler (onTreemapReady) resolve this person for + // the author popover — which carries their commit share, so the header + // strip stays a plain (often-truncated-prone) name. + idx: i, // Container fill = contributor colour (shows in the language gaps); // matching border frames the whole section. itemStyle: { color: base, borderColor: base, borderWidth: 3 }, diff --git a/web/src/lib/popover-store.svelte.ts b/web/src/lib/popover-store.svelte.ts index 88ad7f1..210a711 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, From 6b4a687b4df94e0c139b1c219efd48d8e6704c7c Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 15:07:01 +0100 Subject: [PATCH 11/18] Label the largest-files title with its active scope --- dist/repo-intel | 2 +- web/src/lib/components/OverallCharts.svelte | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dist/repo-intel b/dist/repo-intel index bf2f825..e9492a4 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 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( diff --git a/web/src/lib/components/OverallCharts.svelte b/web/src/lib/components/OverallCharts.svelte index b83070e..1143920 100644 --- a/web/src/lib/components/OverallCharts.svelte +++ b/web/src/lib/components/OverallCharts.svelte @@ -960,7 +960,9 @@ {/if} {#if hasFiles && filesOption}
-
Largest files
+
+ Largest files {activeFilesTab === "head" ? "in HEAD" : "in Git history"} +
{#if hasHeadFiles}
{/if}
+ + +{#snippet stat(url: string | null, label: string)}{#if url}{label}{:else}{label}{/if}{/snippet} +

- {data.dateRange.start} — {data.dateRange.end} · {#if commitsUrl}{commitsLabel}{:else}{commitsLabel}{/if}{#if mergeCount > 0}{" "}({fmt(mergeCount)} merge{mergeCount === 1 - ? "" - : "s"}){/if} · + {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}) · {#if contributorsUrl}{contribLabel}{:else}{contribLabel}{/if}{#if branchCount != null}{" "}· {#if branchesUrl}{branchLabel}{:else}{branchLabel}{/if}{/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}

\n \n \n
\n \n\n' +TEMPLATE = '\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": "#2aa198",\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" diff --git a/web/src/lib/chart-helpers.ts b/web/src/lib/chart-helpers.ts new file mode 100644 index 0000000..d919626 --- /dev/null +++ b/web/src/lib/chart-helpers.ts @@ -0,0 +1,34 @@ +// Shared scaffolding for the repo-wide OverallCharts cards. Contributors are +// aggregated by email, so one person who committed under several addresses (old +// work emails, a noreply alias) shows up as several rows that all share one +// display name. ECharts keys legend selection by the series/slice name, so +// identical names would collapse into a single legend entry and toggle together. +// Every card therefore names its series/slice by the (unique) email under the +// hood, hides ECharts' own legend, and renders the HTML legend (ChartLegend) +// below — plain names, one entry per identity. These helpers map email ↔ name ↔ +// original contributor index so the cards can share that mapping. +import { clr } from "$lib/theme"; +import type { Contributor } from "$types"; + +// Legend rows for the weekly-commits line and the commit-share pie. `idx` is the +// original contributor index (so clr() and the author popover line up); the pie +// gains a non-author "Others" row (idx -1 → no popover) when the top-N don't +// cover every commit. +export type LegendItem = { key: string; name: string; color: string; idx: number }; + +// Email → display name, for tooltips that key series by the unique email. +export const buildNameByEmail = (contributors: Contributor[]): Map => + 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 })); + +// 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/components/ChartLegend.svelte b/web/src/lib/components/ChartLegend.svelte new file mode 100644 index 0000000..c90edb0 --- /dev/null +++ b/web/src/lib/components/ChartLegend.svelte @@ -0,0 +1,156 @@ + + +
+ {#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..0af700e --- /dev/null +++ b/web/src/lib/components/ChurnCard.svelte @@ -0,0 +1,198 @@ + + +
+
+ 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..3bdf473 --- /dev/null +++ b/web/src/lib/components/CommitShareCard.svelte @@ -0,0 +1,144 @@ + + +
+
Commit share
+
+
+ +
+
+ + diff --git a/web/src/lib/components/CommitStyleCard.svelte b/web/src/lib/components/CommitStyleCard.svelte new file mode 100644 index 0000000..a6b525e --- /dev/null +++ b/web/src/lib/components/CommitStyleCard.svelte @@ -0,0 +1,118 @@ + + +
+
Commit style
+
+
diff --git a/web/src/lib/components/LanguagesCard.svelte b/web/src/lib/components/LanguagesCard.svelte new file mode 100644 index 0000000..86d790b --- /dev/null +++ b/web/src/lib/components/LanguagesCard.svelte @@ -0,0 +1,167 @@ + + +{#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 c8477f0..27d3a46 100644 --- a/web/src/lib/components/OverallCharts.svelte +++ b/web/src/lib/components/OverallCharts.svelte @@ -1,1212 +1,28 @@ - -{#snippet legendItem( - item: LegendItem, - hidden: boolean, - toggle: (key: string) => void, - emphasize?: (key: string, on: boolean) => void, -)} - -{/snippet} -
-
-
Weekly commits (stacked)
-
-
- {#each contribLegend as item (item.key)} - {@render legendItem(item, isHidden(timelineSel, item.key), toggleTimeline)} - {/each} -
- -
-
-
Commit share
-
-
-
- {#each pieLegend as item (item.key)} - {@render legendItem(item, isHidden(pieSel, item.key), togglePie, pieHighlight)} - {/each} -
-
- -
-
-
- Lines added vs - deleted -
-
-
-
-
Commit style
-
-
- {#if hasLangData} -
-
Languages by contributor
-
-
- {/if} - {#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/WeeklyCommitsCard.svelte b/web/src/lib/components/WeeklyCommitsCard.svelte new file mode 100644 index 0000000..1391653 --- /dev/null +++ b/web/src/lib/components/WeeklyCommitsCard.svelte @@ -0,0 +1,97 @@ + + +
+
Weekly commits (stacked)
+
+ +
diff --git a/web/src/styles/app.css b/web/src/styles/app.css index fc0187d..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)); @@ -314,8 +332,9 @@ table { } /* .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 { From d8344de00ddc9ff9721ea03a96b277db2aa3d9f5 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 16:08:56 +0100 Subject: [PATCH 14/18] Classify .po as Gettext Catalog and link the language treemap to GitHub - Classify .po/.pot as "Gettext Catalog" (gold #9e6a03, GitHub's attention fallback for colorless Linguist languages) instead of letting translation catalogs vanish into "Other". Pinned via gen_techdata.py's EXT_OVERRIDE + SYNTHETIC_COLORS (merge reordered before the override guard) so a `make techdata` regen reproduces it rather than dropping it. - Fix langSearchUrl: emit a path-glob query for buckets GitHub can't resolve by language (Gettext Catalog -> path:*.po OR path:*.pot), suppress the unresolvable Tools link, and quote multi-word language names so `language:"Common Lisp"` parses. - Link "Languages by contributor" treemap cells. GitHub code search has no author filter, so the two dimensions split across the cell: the header strip opens the author's commit log, each language tile opens a repo-wide code search for that language. - Raise the language limit 6 -> 10 before collapsing into "Other". --- dist/repo-intel | 6 +-- gen_techdata.py | 11 +++++- repo-intel.py | 2 +- techdata.json | 3 ++ web/src/lib/components/LanguagesCard.svelte | 44 +++++++++++++++++---- web/src/lib/format.ts | 21 ++++++++-- 6 files changed, 70 insertions(+), 17 deletions(-) diff --git a/dist/repo-intel b/dist/repo-intel index f29f6e4..40a93a2 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 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 "Gettext Catalog": "#2aa198",\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}' +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 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 4d6472d..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 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/src/lib/components/LanguagesCard.svelte b/web/src/lib/components/LanguagesCard.svelte index 86d790b..0ddfc37 100644 --- a/web/src/lib/components/LanguagesCard.svelte +++ b/web/src/lib/components/LanguagesCard.svelte @@ -7,6 +7,7 @@ // lanes and churn axis use. /* eslint-disable @typescript-eslint/no-explicit-any */ import { echart } from "$lib/actions"; + import { authorUrl, langSearchUrl } from "$lib/format"; import type { AuthorPopover } from "$lib/popovers"; import { tileInnerBorder } from "$lib/chart-helpers"; import { bgCard, clr, contrastText } from "$lib/theme"; @@ -27,13 +28,34 @@ // list; guard the private access so a future ECharts bump degrades to a stray // pointer cursor instead of throwing and breaking the treemap mount. function onReady(chart: EChartsType): void { - const useDefaultCursor = (): void => { - const list = (chart.getZr() as any)?.storage?.getDisplayList?.(); - if (!list) return; - for (const el of list) el.cursor = "default"; - }; - chart.on("finished", useDefaultCursor); - useDefaultCursor(); + if (data.githubBaseUrl) { + // Links active. GitHub code search has no author filter, so a cell can't link + // to (author × language); we split the two dimensions across the cell instead: + // the header strip → this author's commit log, each language tile → a repo-wide + // search for that language. Contributor containers fall back to zrender's pointer + // (they're all clickable); language tiles set their own cursor per-node below + // (pointer when the search resolves, default for the inert Other/Tools tiles). + // Open the clicked node's url. + chart.on("click", (p: any) => { + const url = p?.data?.url; + if (url && url !== "#") window.open(url, "_blank", "noopener,noreferrer"); + }); + } else { + // Local-only repo (no GitHub base): nothing is clickable, but ECharts' treemap + // forces a pointer cursor on every node (and the root background) and ignores + // series.cursor, so override it to the default after each render — `finished` + // fires on the initial draw and on every redraw/resize. zrender exposes no public + // per-node cursor API, so we reach into the display list; guard the private access + // so a future ECharts bump degrades to a stray pointer cursor instead of throwing + // and breaking the treemap mount. + const useDefaultCursor = (): void => { + const list = (chart.getZr() as any)?.storage?.getDisplayList?.(); + if (!list) return; + for (const el of list) el.cursor = "default"; + }; + chart.on("finished", useDefaultCursor); + useDefaultCursor(); + } // Only the contributor containers carry an `idx` (the language tiles don't), // so hovering a leaf tile hides the popover. We anchor a zero-size rect at the @@ -135,6 +157,9 @@ // popover — which carries their commit share, so the header strip // stays a plain (often-truncation-prone) name. idx: i, + // Header strip → this author's commit log ("#" when local-only, which + // the click handler ignores). + url: authorUrl(data, c), // Container fill = contributor colour (shows in the language gaps); // matching border frames the whole section. itemStyle: { color: base, borderColor: base, borderWidth: 3 }, @@ -145,9 +170,14 @@ upperLabel: { color: contrastText(base) }, children: langs.map((l) => { const color = l.color || base; + // Tile → repo-wide code search for the language ("" for buckets GitHub + // can't resolve — Other/Tools — which then stay inert / default-cursor). + const url = langSearchUrl(data.githubBaseUrl, l.name); return { name: l.name, value: l.pct, + url, + cursor: url ? "pointer" : "default", itemStyle: { color, borderColor: tileInnerBorder, borderWidth: 1 }, label: { color: contrastText(color) }, }; diff --git a/web/src/lib/format.ts b/web/src/lib/format.ts index b236955..205cb07 100644 --- a/web/src/lib/format.ts +++ b/web/src/lib/format.ts @@ -125,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`; } From a2a1db86945062d3627512c5255479419c507a87 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 16:14:54 +0100 Subject: [PATCH 15/18] Extract shared legend-selection state into a factory WeeklyCommitsCard and CommitShareCard each carried an identical copy of the hidden-legend plumbing (sel state, chart ref, onReady/toggle/reset, plus highlight on the pie). Pull it into createLegendSelection() in a new chart-legend.svelte.ts module (the popover-store.svelte.ts -module convention), exposing selected via a getter so callers stay reactive. --- dist/repo-intel | 2 +- web/src/lib/chart-legend.svelte.ts | 36 +++++++++++++++++++ web/src/lib/components/CommitShareCard.svelte | 35 +++++------------- .../lib/components/WeeklyCommitsCard.svelte | 30 +++++----------- 4 files changed, 55 insertions(+), 48 deletions(-) create mode 100644 web/src/lib/chart-legend.svelte.ts diff --git a/dist/repo-intel b/dist/repo-intel index 40a93a2..d6042a0 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 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( 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/CommitShareCard.svelte b/web/src/lib/components/CommitShareCard.svelte index 3bdf473..f889b7b 100644 --- a/web/src/lib/components/CommitShareCard.svelte +++ b/web/src/lib/components/CommitShareCard.svelte @@ -8,9 +8,10 @@ import { escapeHtml } from "$lib/format"; import type { AuthorPopover } from "$lib/popovers"; import { buildContribLegend, buildNameByEmail, type LegendItem } from "$lib/chart-helpers"; + import { createLegendSelection } from "$lib/chart-legend.svelte"; import { bgCard, borderDefault, clr, textMuted, textPrimary } from "$lib/theme"; import type { RepoData } from "$types"; - import type { EChartsCoreOption, EChartsType } from "echarts/core"; + import type { EChartsCoreOption } from "echarts/core"; import ChartLegend from "$components/ChartLegend.svelte"; let { data, authorPopover }: { data: RepoData; authorPopover: AuthorPopover | undefined } = @@ -33,26 +34,8 @@ : contribLegend, ); - let sel = $state>({}); - let chart: EChartsType | undefined; - - function onReady(c: EChartsType): void { - chart = c; - c.on("legendselectchanged", (p: any) => (sel = { ...p.selected })); - } - function toggle(key: string): void { - chart?.dispatchAction({ type: "legendToggleSelect", name: key }); - } - function reset(): void { - chart?.dispatchAction({ type: "legendAllSelect" }); - sel = {}; - } - // Hovering a legend row emphasises the matching slice (keyed by email, or - // "Others"), so it scales out per the series' emphasis config; leaving - // downplays it. Highlight is addressed by slice name, the legend's toggle key. - function highlight(key: string, on: boolean): void { - chart?.dispatchAction({ type: on ? "highlight" : "downplay", name: key }); - } + // Legend selection + slice highlight on row hover (the pie wires onEmphasize). + const legend = createLegendSelection(); const option = $derived.by(() => { const pieSlices = [ @@ -114,14 +97,14 @@
Commit share
-
+
diff --git a/web/src/lib/components/WeeklyCommitsCard.svelte b/web/src/lib/components/WeeklyCommitsCard.svelte index 1391653..c55a958 100644 --- a/web/src/lib/components/WeeklyCommitsCard.svelte +++ b/web/src/lib/components/WeeklyCommitsCard.svelte @@ -8,9 +8,10 @@ import { escapeHtml, weekLabel } from "$lib/format"; import type { AuthorPopover } from "$lib/popovers"; import { buildContribLegend, buildNameByEmail } from "$lib/chart-helpers"; + import { createLegendSelection } from "$lib/chart-legend.svelte"; import { clr } from "$lib/theme"; import type { RepoData } from "$types"; - import type { EChartsCoreOption, EChartsType } from "echarts/core"; + import type { EChartsCoreOption } from "echarts/core"; import ChartLegend from "$components/ChartLegend.svelte"; let { data, authorPopover }: { data: RepoData; authorPopover: AuthorPopover | undefined } = @@ -20,22 +21,9 @@ const dispName = (email: string): string => nameByEmail.get(email) ?? email; const contribLegend = $derived(buildContribLegend(data.contributors)); - // The chart owns the source of truth for what's hidden; we mirror its - // `selected` map back here so the legend can dim rows and reveal Reset. - let sel = $state>({}); - let chart: EChartsType | undefined; - - function onReady(c: EChartsType): void { - chart = c; - c.on("legendselectchanged", (p: any) => (sel = { ...p.selected })); - } - function toggle(key: string): void { - chart?.dispatchAction({ type: "legendToggleSelect", name: key }); - } - function reset(): void { - chart?.dispatchAction({ type: "legendAllSelect" }); - sel = {}; - } + // Legend selection: the chart owns what's hidden, this mirrors it back so the + // legend can dim rows and reveal Reset. + const legend = createLegendSelection(); const option = $derived.by(() => { const { contributors, weeks, weeklyData } = data; @@ -85,13 +73,13 @@
Weekly commits (stacked)
-
+
From 098c22bb6a4ec227174740a2e05d507fe1d0f440 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 16:15:42 +0100 Subject: [PATCH 16/18] Centralize the bot-filter rule into humanContribRows ChurnCard and CommitStyleCard both open-coded the non-bot contributor filter (map to {c, origIdx}, drop logins ending in [bot]). Pull it into humanContribRows() in chart-helpers.ts so the bot-detection rule lives in one place and the two charts can't drift on what counts as a bot. --- web/src/lib/chart-helpers.ts | 10 +++++++ web/src/lib/components/ChurnCard.svelte | 26 +++++++------------ web/src/lib/components/CommitStyleCard.svelte | 13 +++++----- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/web/src/lib/chart-helpers.ts b/web/src/lib/chart-helpers.ts index d919626..a09b881 100644 --- a/web/src/lib/chart-helpers.ts +++ b/web/src/lib/chart-helpers.ts @@ -28,6 +28,16 @@ export const buildEmailToOrig = (contributors: Contributor[]): Map 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). diff --git a/web/src/lib/components/ChurnCard.svelte b/web/src/lib/components/ChurnCard.svelte index 0af700e..52ba447 100644 --- a/web/src/lib/components/ChurnCard.svelte +++ b/web/src/lib/components/ChurnCard.svelte @@ -7,7 +7,7 @@ import { echart } from "$lib/actions"; import { authorUrl, escapeHtml } from "$lib/format"; import type { AuthorPopover } from "$lib/popovers"; - import { buildEmailToOrig, buildNameByEmail } from "$lib/chart-helpers"; + import { buildEmailToOrig, buildNameByEmail, humanContribRows } from "$lib/chart-helpers"; import { clr, colorAdded, colorDeleted, textMuted } from "$lib/theme"; import type { RepoData } from "$types"; import type { EChartsCoreOption, EChartsType } from "echarts/core"; @@ -66,21 +66,15 @@ } const option = $derived.by(() => { - const { contributors } = data; - // Bots (the `[bot]` logins repo-intel.py skips for profiles) are dropped — a - // Renovate/CI account churning tens of thousands of lines is noise here and - // only flattens the human contributors' scale. Sorted by total churn (added + - // deleted) so the busiest sit at the top (yAxis is inverted, since ECharts - // otherwise draws the first category at the bottom). Local copy: the shared - // `contributors` is index-keyed for the line/pie colours, so sorting or - // filtering it in place would corrupt them. Rows carry their original index so - // the axis label can show the person's identity colour (clr) and dot, and the - // hover popover can resolve the right person. Categories are keyed by email - // (unique) — two people sharing a display name would otherwise collapse. - const addDelRows = contributors - .map((c, origIdx) => ({ c, origIdx })) - .filter((r) => !r.c.login.endsWith("[bot]")) - .sort((a, b) => b.c.added + b.c.deleted - (a.c.added + a.c.deleted)); + // Bots dropped (see humanContribRows), sorted by total churn (added + + // deleted) so the busiest sit at the top — the yAxis is inverted, since + // ECharts otherwise draws the first category at the bottom. Categories are + // keyed by the (unique) email — two people sharing a display name would + // otherwise collapse — and each row keeps its original index for the axis + // label's identity colour/dot and the hover popover. + const addDelRows = humanContribRows(data.contributors).sort( + (a, b) => b.c.added + b.c.deleted - (a.c.added + a.c.deleted), + ); const abs = (v: number) => Math.abs(v).toLocaleString(); // Force a symmetric x-axis sized to the single largest bar (added or deleted), // with ~8% headroom rounded to hundreds. Left to its own devices ECharts scales diff --git a/web/src/lib/components/CommitStyleCard.svelte b/web/src/lib/components/CommitStyleCard.svelte index a6b525e..6b259a6 100644 --- a/web/src/lib/components/CommitStyleCard.svelte +++ b/web/src/lib/components/CommitStyleCard.svelte @@ -10,6 +10,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { echart } from "$lib/actions"; import { escapeHtml } from "$lib/format"; + import { humanContribRows } from "$lib/chart-helpers"; import { borderDefault, clr, textMuted, textPrimary } from "$lib/theme"; import type { RepoData } from "$types"; import type { EChartsCoreOption } from "echarts/core"; @@ -17,10 +18,8 @@ let { data }: { data: RepoData } = $props(); const option = $derived.by(() => { - const { contributors } = data; - // Bots are dropped (a Renovate/CI account commits nothing like a human and - // only stretches the axes). Both axes are log: commit counts and sizes span - // orders of magnitude, so a linear scale would crush everyone into one corner. + // Both axes are log: commit counts and sizes span orders of magnitude, so a + // linear scale would crush everyone into one corner. // Per-commit churn comes from data.commits (keyed by author email c.e), which // holds every commit by the displayed contributors. const median = (xs: number[]): number => { @@ -35,9 +34,9 @@ if (arr) arr.push(k.a + k.l); else churnByEmail.set(k.e, [k.a + k.l]); } - const styleRows = contributors - .map((c, origIdx) => ({ c, origIdx })) - .filter((r) => !r.c.login.endsWith("[bot]")); + // Bots dropped — a Renovate/CI account commits nothing like a human and only + // stretches the axes (see humanContribRows). + const styleRows = humanContribRows(data.contributors); const styleMax = Math.max(1, ...styleRows.map((r) => r.c.added + r.c.deleted)); // The busiest contributor sits hard against the right edge; flip just their // label to the left so the longest name can't clip off the plot. From 74c9142ad57fae035e7e5de56dca2f7ed8a29eff Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 16:36:40 +0100 Subject: [PATCH 17/18] Inline the favicon as a base64 data URI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generated dashboard is a single HTML file opened over file:// from /tmp, so a sibling or remote favicon never loads. vite-plugin-singlefile only inlines JS/CSS, and public/ files are copied verbatim — so the icon shipped as an unreachable ./favicon.png link. Move the favicon out of public/ into src/assets so Vite tracks it as a build asset, and add an inlineFavicon() plugin that reads its bytes from the bundle and rewrites the href to a data: URI (no node:fs, like the existing abs() helper). One self-contained file, no emitted sibling. --- dist/repo-intel | 2 +- web/index.html | 4 ++++ web/src/assets/favicon.png | Bin 0 -> 10794 bytes web/vite.config.ts | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 web/src/assets/favicon.png diff --git a/dist/repo-intel b/dist/repo-intel index d6042a0..87a9209 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( 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/assets/favicon.png b/web/src/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..51707cd765beea0e7162d725d6203fc7f5193ec5 GIT binary patch literal 10794 zcmV+_D%I7AP)SU_>)f)8f%EFatbvOvq88TiIfO z*Ui55+xPd~s{H@|T5jF@Uhi}_1z&&Py|-@Ns{iu)FI9D)!ppGi+GTrME!LSFo9Xbi zP#93w4p^nS6l}MJ?W5lYuuw`_(7(`@PGig{jMKTjbkB&f<_VSQy~Z?tndh}V+qbJx zyv&Ni%b+m9vl(oK#(CCYE0J>xQ5Bkdm-bK>KdmD>tnyXDZ~lh+#QJnDci+2}#_n9< zmTV4#F9(L4GzKuy^)xOaN?k;~*s2}jxIc#eRgtI=MkqePB5%VrmUrdHpdCNBE)iJn zp-NKMGGBZ<#xaTilV{`^2C4c@*)(oBS7(1!jW_}2xHDka4R$Ls zTuCF}%EulaB9WtntHr$v(4kTyrsuKP1|ZRzw2rMXg*k4L`o=Rr`QOBly>$K4zx{Ug zeH_Pf+!#QFA0PtUKp&BKYYRf9gblqYX+%;lg(NId2S^OBD#KPvbRlwj%`-rS^8u0| za3uGcjIWy;7c%|%%ic_$)o~~q$Dw@Z276_0aGxQmXTq001jfd?de(oVa%_{fYy|(x zJ!zeA*_NsnOs_o4Rvw}(DmSL>sY|snLpS|{y%NWvyrdei>#KHPp@v=5=$4eVy6{Y* z`xqtM_ae|am0<0Sr%oUxg%~8q&V4HGPbDAz8a(C)C}RmvHNqy>gBDPH;g9L*8TQ&- zZ+j`V;U&|6zy6xNd_m(rBJh?d?eG$B+_8M4(1cVoj7>b9a1QQ-NhCYHZvBZ^7mLq} z`^gtPGfikD)vWL_#l2CRq^|RLXXebnyqUXiKF_bfOH^JG4fv}+vpcDuS47NKWuvOA z7_N$+&`TI&75#sw0qK4I8CCCSk<=%4#;UUS6Y82IP_sI*8Cf*MbZq2!asg;1zEU_>;^nZejB(AU|(N6xLw4bgm9yZhRG`?h_0{raO0;*J`EzD;;P zHBE-rB!)KhEA|f&3W9n^1DF~;UreaWMI~_I@3E$6*Q8Jblni+Fe91^B(3sW>?aDK3 zVXH|Gup4RZV#c3;YeBez@F0YZ^L;wEp$zk+2 z*9J^Jf7j76;fNV<0}+2-<1QlfKpa>q=_nJ!CWA65BW#5^RjKvI24&(b^&D>}3&z^Q z)vXe@dM;{#7mR>;!(+giugLK)&aM}pn=kzH=g*Jhg?WQaaZ(Bc85Zu^c@#`IA_frg zd+6bJQD+CjAWb?TRj9TQ!W8F91g?4;70FAbJN`(Sfr8K}6Jk56Xm61=p&)elZIZq* zq4$pfZ+K;ncWkaX?<^sH(8OI&?8nNMTJ(_U?g68S2}46YID&Gd8W4#ei5hU(R0wMl zVk03~isMKKno582jr1`ApMerwRJA7Uhq5TSy0N}O8OpdW-S_-3@V3njyyeVH>T9)_ zVD}GC;)$6C>U2>jaR@zZAX~_G;RwoMGvLqv#O@>lY$*}NN43Gv4@@!XU=v0yB5o2F zAYoui&?+OU*OtP4psXqJIMKMskc3$;5b-ZOH^yGgY-OOR5Xui63FelF?5_o?l?WGp17+wz zS%VhUuP_PK^Gy8xG%>L)$C(?lMVOxw>wYp0k4?{`xu(jId>T_gU2*-;6PM#K$|2)` zul|u8AP(P4pC0ndRjD^9X02izkoxrgJH!Do*wV@65EJ-(wDLhw+IFaywvqN>(Q)eE z`}2|372lt7Rv4eOxcJ=$YgQ}`J6sHLMN=pK;Ag+a3^mwMuc1aJpssm*8co_gUenFB zn#>WAC8?kN$@Q!E;vnUa8bGO#J4qsY2xgQCFk#AY6VIUnBS6{9soD!vpaA8%DTLW2 z@W1e7lXii{(3NU{Dt<3CD8d~x_~=E}5#KCLe4zso|KZ_rJUlUtmP`v_g4}4>BqwD9 z4EAWu{|ydB--BJe{%ZR<>eD(IkM)RQ%Y-ZCX_A~zj0e(lDIpX5wFwhbkEH6wlo)Im z!%&Gil{%4mUI^yqi2<_)mwXWD?RImT`T*1jF75w%X})JrTpe(oruWiXXH|h*mX#wsMSwP=QgZit(nLunR;D zo{j=a+E>yJ6u)O?IKx21{}9mLrVohukw|py!Tn=+h;kAgwG6T#0}63QGui-EPSi?_ zp#S3y&kPM5umx*D>@D z73P=f`#v&}rzy42*=F!tA5v(l9h&$-`oH?n5Y~3K`%DlKUt7odFn?{myqeV8qqCV@_t7^C2 z@Wjy8CEH)}sTN<9+iV=GD&aN~Xfar9R885(4mKererb-NqAk_WQt)L;+&~<1=z}9s zae4oK;5BFEc+Z7})E~+PG`^wh9vs5@u6AiH^MrShr9X$mVZhGM z+DnNJ12Rr4Oeh)LDDf#FeOF30A|Ysin4G+hnJHjmjJ*%~9(Lbz)Bavmv?H}0CXUxl zA@ZS07?K8jDBrjLMT-lz8NBVS*&!jPL>#JkKSgK19GyaUQ(a&{M`-bsPgGIGfXqg3 z$SNHwocFCKo;a`ijM}1yX84$8qe~y+a+s(p!foRQ9=_u_ICZr_-#vjEWbkI`)7(rs z_2mZ3PXqc_YSijRq-btN;kjoFo_tJ^an$Hu?hINWlrY2l*d=!|5ZlKONb*1OP3Pw+ zk3Tm-Y`()B(e_=^oy0>5$6thNq=4}4G&^Of`Qk1+Ff z&(qK1)4zBaXD{zZM{^4@ni;FhSV@4$5O5}xX`(Zi6UyMOaXlU;%TY!@GFjPYExWFn z&Mx@y>Q@YgXVfa(_?SqwQyOKITh=EFE5i&D3WMmqu>xxeVn!+cYi*;6;d3oEpG#7| zf*PUw=jP}$3-KOAf^^w`c^tGv2Q6)*Es!qrM|f;%DC{@}`b33mc#1&&aFqgwaZiT6RRtWO@`;`CeOaL3YJw(F-u+&hNO|RvK~A;YvG+-Q?*2#d z>fUaej_i~HaQ0IcQqZ^jW-o{sA?XKiZP`d?nYgLsFe%F(lhXi)mUL~bc_!bm-A`ji z4KVX~zl_{iHmDPz05-mN&dNHRx|k7Pe>D17tj}g&#f0V=zj>P|dWG`N%0iM=cLmPQNjof;l-^Qpn3?sw=Au1LE!D|MB z<~rErjoS8gUPlJ+X`rb^+*hBDMa1XQJZeJl!wG_b zLKC*UiQLm3gWG;UhI~QOvn+c0EZ+4#;PkVOP3l7l>E>(qJcuUpc=&f`TPrMS0;ij! zgeT((#L^xj;<~6bSEAy5*1=b1SxECvq51cP0p#6Wlwys8DrqoogAn4=$(*34jas_WxOC67e`0^ZT z;K}g`{MF;n;Iys|bho#8Z%uijQZe-${E^f#(5WHt{Rt+*_ss>hPP|oSa2}oezW3AI za>5kivyJ%KOA{ScWoQC9Zm>&P2uaZy<6Dkl9XpEz3Lc*fS76jrVwDC*ZGZ93Kx zaz_8S0@^DqOYT!BKJlSc=_o^m3UwQ`$H*di0_=z?nY%3&)NB~=gHWvx`NzK zVu0LX0+)QTE)HPAHx^J#s8EF_ifqRx6u$T8gungPT~F^-<)9TfCLSEO5)AMEd2|T( zjnANo2G`Tph8FT9wDx{K920`~7Sa)+1f!XXp!NSM4=oWJC;x$>{p7oPw>o{xF6Y}+?2@r>4Hl6%PZ9r-Z_Ah4o%EIF2#)OTka^t&+gZvqY?^gC;jSY73-tE>Gfys^|uJSJmx8X%cY`u@ld|1UaeiqWNx9YfZxT#f~bgeBt{ z46L^SDiG6aKss?0co5+RF6SRN5C*Y#=WUQ>6D~+jgJTV);|{-)gB9dG{G0mn4*JSo zO~qdd+QD-JwI+=(?|{rKL7!L+2)KXUJwM0p$r@RAy^lYMtM7Xdr+0Pv-Sk?df5XZZ)UO4ZUW`c8` zXktD2Pzrb;3fXvX*z+Rk~#Kk|n6K5{(CzsPblqJ58a{m3~`51EBLOv%DwQx7B z_j(d9McdN2-Bf`}>5h_WBy@6SH=(e>UY@((7jPX3o>yS~00)K5z`8(cq;j>0Br zZvY*UZ5f6vl1ZXCa=~18TQb9C`zSWXFHsQAMlVPCwjB1^6ml%e-_>G~*aKTI zN8D9nLN7(j|MZ~7x4xQ7^6sT%g5-IKQvde5e~W*dp2Z4YR^t1?*uSulW78>X$Og4D94$@t z!mwJuiaAPe&;S(&5+O!~{67E`5LHY|+VT`-ge4oA3e}hp%1~UWjTzk++Ny(f;0myss?BQfEdUuhgO6PWlM$zDkY_iGRB#pykryiziDin~*% z>zhtpOjc}opA;6BcOV?kDVL=lfd8meOT-R{BPVA9;NP+lQ5%I74)uTAG-{tpJlAD~E zoW|*E*HFTcmr824(oGfcz~7mtzVdJsy_6k`>dDxTaySjNoVuxuSEFBM-|;idAg|_6N5zC0@GZL@nw; zL8oA-9Y37g;u3Tof|LYkQX^ApcX%F4!(h3|mOinn8J^&a-e8q71#TH%$da;m)X@#h&eiZge&1kvIzOOYU^kNq(4dZQ`_r58 z(`QC-`m!Fue1RRA&vm&S#`}TQ%hB21;uxmNSg#Y}h4rh-CeX5kkFSsn67W-&*3+p- zJERMFBMH1>;BapPB6IvgskyKS} zumQgzUI_0fNoL}z(3sDmvJ@_y1r9J1mLR5tjVmHb?xsqNG>Z0ALNp|KBP8$@X2q2B z_NIicuF&{yq%W5l_1a_$Lm&BJfkkmi^<2q*piKONiv<&8?||2Ylrg<4H2z{|9e4cg ztXyY;efB$d_X zENpyk={rb9xSrQQ-0tXH*$->=M_4 ztwM66i5)Jxv+2EQV;GlHyv+DLfZ7Q}S z-j#Sg%CC$dLA(h`DQN(g9skMRY55K3h^;20BDI;v1?Z3Rji z6bxNfgQ#5}%_BcGydSsiz8zEKK6ZCfT4A9htem}DQCfEsrmZlKR3Pwq?t*@^Q z=e%hXCdQ{_l|wCP8kC1JcU()?{p-Sy5B+ht?_AUfPa@@Re^_9E>M8?>!8<(01q%{f233{v((gsAEW?yK#C3S)bdUjVujRP&fqU`o zpZpC)t*z+cRlt0a;HKV9SKrEJ=fE`TXx$en-$Y4kG1*kLpv5 zj}o6YqzgDIT|0oL#AFkFcQrG1T0Hdh6EuVM2%4K(iQYM;r=BH@ZIT63{1)5rCR?+A z9(X;~+0qM3zco#Jj*m{`^}n$J%lbP=QyTItze`b`qg8;KV$L@#H!M~{dw8OAS*oF- zUa)bxkY0I4Lcdz(*FRXP$8G^Pv-hIq8#YvFy=bSrf8OWm-mS@rFs)W%SZWW%NQcln z(TWIJN#p7LZB0N+&0^^J=dt^#AZn$X`bOt5epCfK0sWyG;P zGgz3kX!?yl%s(@WQ`h!k^{G9W8k_O<0g0Pv;}l~_Vv{B3QGj3>tJ> z&p(SvauYjRo6$=Fm1HnI$Ar^5qcq6^np^us))wYRp=5T;%}`67t|sW`=P>ioB=Wa6 z(A?34#>{+y#i2Lpylx^jr5sPv&p`YnIQ91yzqM~RXh_T{c{G6kD_f0uy#og*`al;b zJ+YVCx)v1|H2(IKwV{>hX%quVwWO1GQmO_XC8)XMfd}!cr=BKBZKA2ccA|F{qgj{W zD!$pf$s3LdO|8A;t`gppWVjh7y3Xs3Hnk&P*N)q-{}txP=Fr*QBCE<`oS}=s>Lm6k z5!D$@f2@jusKP+U`Y6U8_be;KEKtHozWn*^tJm+v0m=a(D3l%l+1@Mf3)LmN8hcer zBv#;vUo6Wnvly9~!80TK@$3XiFcGhXm&qZ#&c(=k7(~0}?I-Mn8iXB%hF?@+eI0_J zg~k}>XGX|A5F9lcFvQrVH}}CzQ1DPQ7<+CCZ++iJoU*AGqc2X$8w@kwuQ&Qe3Symn)aZm4Gt9cKZO{8m@(YzY&8@Al;zHyn(Xy|bmuc{Aea7s;$JDdA?5xa&m#;^4x?otEIJ zR_~&?qJ{hzxDB2zt13VM1q5fVTIuzaovCzmdJHLPln(&^Oo0Y6)&F5tJ zC3CVCQal$GiR;cAr>E9Lo;o%K1~_w?9q;^Cuf+7+0&>cVvZjQ%pr(VT<1?VDh=iTqRlFc4LGo6B!bDilxPn=9 z`P%I(PCKkWb8^@W;PQpvw|6ZVvvq+aeU9*Vo<1`R4I!f2Q|n}ziRK+insDI=H21GI zbFP69+IoqNdj_q~{25tN7&cN^<=S^EE0}2%3#_XN-g8`Fn{wxJ@O_Hy1YEoP-U?#I zEV;Ki3CV@;IUTL!f=y4)g;YU&=Yunxszprc*1A7$s{GWb_J1uzCCgB~ znNsonkDMx}|G2KZ-vvq});hCp`3Rj|*W_~dR@&zJ)+4l4Vcno)Ar(&-llN4!Ep0XY z@P`kW=boJ~y*;fY6gGX`oPR!wPmy#nR)w``aDIbg*>Fd03!Mq8_<7CeW7)Lch9f9P zqyb#6_{7WrO>W%Df55@G)s{-S;Zp_N)7-yd&r2~S5M?pG_US;b%|Ky;cN1o8jDJI^ z3&xzx6Q)}%}B^qD0mKc#9lDk^M5>tq zR#P01v5}#vea95VUXW78>6?6nDZ(83ZOLO%{5pc1?AUwGdnJ0hTQN#$Yv&PJp1E|f zrNe!f%Xh>UuSgi6+_;;%$PB`A`M_oaDUX9AV>b>Ag_MPxRyYWS@2wT$^}EUx{?s*NZ254ok~Q=gi? zoE(BHY1F;Oztr9_K-?SgA52*7E-%D%_z&y%?Kd%TsXNUqa!waG@H1J?e?DHhzwJow zEZG3DjwIQJ4Kf90+#VlG9Kh}pohP=F&annq`SbHu`&X4{fk@|LW=vRXXXo6zcFsTN zG`*_7!|orOQhvVJXt$?E>yTNqW`yRPcYJi!p@Xc$DK8lVxLomxk%30mbSDjconfMQ zACF%{NEog?#huhUlR*+rzgv|MN8D)sX2a@ND+rOrGj$Nf8UW>tFkj7YDSTrFg2IA@Ni`IG*rI*vZKWN zrOHdnfKWd5J5yJZ7F_AYQ=kd*SVl;g&LP(Jyo@%IzZevwAKK_pLH zl-&6gE&z7;3~!W~n3>m;%t*-QC0H@!I2(`r z%m+CJzz$N+cHH>BcMjqNloQ5)P(Jm$6I+R_mr`!vW8uw3LMR^{i18HcXJ85uucVpT zH}a9N6(WmQRBt#Y))?fBTL&c`k#(9TuBS_1utxc`5vQi9POkjB{zqwMSM%&t;&V@;@7i#=reYV@nR#KJs`r?9RtM0rAXKcBsqgC zF@O$6xX6;aTwe^{ybX}}V308A7H!N;H*Vi{)WOuTl#|AQv@kO$v%S@r>>||7W@5t@ z(E)ZnL-MT@2Ur(1GXpYbY$XNl4R18M0&hN&7Ej0QrtiC{{kv;fK6tW-o|cyd1FA(B z0&F2Sbu$rpovo<>!si~c4D0e*qlf=8k oR?Y1}y>0J}+h2Fm30^J#46Bi*&B`8)fdBvi07*qoM6N<$g7$I-v;Y7A literal 0 HcmV?d00001 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"), From 09e3bdebc7405cf74f987f3c16ef877725db0889 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 23 May 2026 19:24:33 +0100 Subject: [PATCH 18/18] Fix Reset button a11y and stale date-keyed tag tooltips - ChartLegend: hide Reset from tab order/AT and make it click-inert when no series is hidden (was opacity-only, still focusable/clickable). - setTagTip: key group identity on oid || date so lightweight tags (no oid) don't collide and stick a stale tooltip across date groups. --- dist/repo-intel | 2 +- web/src/lib/components/ChartLegend.svelte | 12 +++++++++++- web/src/lib/popover-store.svelte.ts | 9 +++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/dist/repo-intel b/dist/repo-intel index 87a9209..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 \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( diff --git a/web/src/lib/components/ChartLegend.svelte b/web/src/lib/components/ChartLegend.svelte index c90edb0..344159e 100644 --- a/web/src/lib/components/ChartLegend.svelte +++ b/web/src/lib/components/ChartLegend.svelte @@ -69,7 +69,13 @@ {/each}
- +