@urmzd/github-insights 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +5 -1
- package/CHANGELOG.md +40 -0
- package/README.md +0 -2
- package/assets/insights/index.svg +14 -0
- package/assets/insights/metrics-calendar.svg +14 -0
- package/{metrics → assets/insights}/metrics-complexity.svg +1 -1
- package/{metrics → assets/insights}/metrics-contributions.svg +1 -1
- package/assets/insights/metrics-expertise.svg +14 -0
- package/assets/insights/metrics-languages.svg +14 -0
- package/{metrics → assets/insights}/metrics-pulse.svg +1 -1
- package/examples/classic/README.md +2 -2
- package/examples/classic/index.svg +2 -2
- package/examples/classic/metrics-calendar.svg +1 -1
- package/examples/classic/metrics-complexity.svg +1 -1
- package/examples/classic/metrics-contributions.svg +1 -1
- package/examples/classic/metrics-expertise.svg +2 -2
- package/examples/classic/metrics-languages.svg +1 -1
- package/examples/classic/metrics-pulse.svg +1 -1
- package/examples/ecosystem/README.md +23 -24
- package/examples/ecosystem/index.svg +2 -2
- package/examples/ecosystem/metrics-calendar.svg +1 -1
- package/examples/ecosystem/metrics-complexity.svg +1 -1
- package/examples/ecosystem/metrics-contributions.svg +1 -1
- package/examples/ecosystem/metrics-expertise.svg +2 -2
- package/examples/ecosystem/metrics-languages.svg +1 -1
- package/examples/ecosystem/metrics-pulse.svg +1 -1
- package/examples/minimal/README.md +2 -2
- package/examples/minimal/index.svg +2 -2
- package/examples/minimal/metrics-calendar.svg +1 -1
- package/examples/minimal/metrics-complexity.svg +1 -1
- package/examples/minimal/metrics-contributions.svg +1 -1
- package/examples/minimal/metrics-expertise.svg +2 -2
- package/examples/minimal/metrics-languages.svg +1 -1
- package/examples/minimal/metrics-pulse.svg +1 -1
- package/examples/modern/README.md +36 -38
- package/examples/modern/index.svg +2 -2
- package/examples/modern/metrics-calendar.svg +1 -1
- package/examples/modern/metrics-complexity.svg +1 -1
- package/examples/modern/metrics-contributions.svg +1 -1
- package/examples/modern/metrics-expertise.svg +2 -2
- package/examples/modern/metrics-languages.svg +1 -1
- package/examples/modern/metrics-pulse.svg +1 -1
- package/package.json +5 -5
- package/src/api.ts +1 -1
- package/src/config.ts +6 -12
- package/src/index.ts +6 -0
- package/src/metrics.ts +16 -2
- package/src/readme.test.ts +31 -25
- package/src/templates.test.ts +110 -13
- package/src/templates.ts +38 -11
- package/src/types.ts +3 -0
- package/metrics/index.svg +0 -14
- package/metrics/metrics-calendar.svg +0 -14
- package/metrics/metrics-expertise.svg +0 -14
- package/metrics/metrics-languages.svg +0 -14
- /package/{metrics → assets/insights}/metrics-domains.svg +0 -0
- /package/{metrics → assets/insights}/metrics-tech-stack.svg +0 -0
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
.t-card-detail { font-size: 11px; fill: #8b949e; }
|
|
12
12
|
.t-pill { font-size: 11px; font-weight: 600; }
|
|
13
13
|
.t-bullet { font-size: 12px; fill: #c9d1d9; }
|
|
14
|
-
</style></defs><rect width="808" height="390" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">SIGNATURE PROJECTS</text><text x="24" y="56" class="t t-sub">Top projects by technical complexity</text><rect x="24" y="66" width="760" height="52" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="66" width="4" height="52" rx="2" fill="#58a6ff"/><text x="40" y="84" class="t t-card-title">resume-generator</text><text x="768" y="84" class="t t-value" text-anchor="end">★ 10</text><text x="40" y="100" class="t t-card-detail">A data-driven CLI tool that converts YAML/JSON/TOML resume data into polished PDFs, DOCX,…</text><rect x="24" y="128" width="760" height="52" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="128" width="4" height="52" rx="2" fill="#3fb950"/><text x="40" y="146" class="t t-card-title">
|
|
14
|
+
</style></defs><rect width="808" height="390" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">SIGNATURE PROJECTS</text><text x="24" y="56" class="t t-sub">Top projects by technical complexity</text><rect x="24" y="66" width="760" height="52" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="66" width="4" height="52" rx="2" fill="#58a6ff"/><text x="40" y="84" class="t t-card-title">resume-generator</text><text x="768" y="84" class="t t-value" text-anchor="end">★ 10</text><text x="40" y="100" class="t t-card-detail">A data-driven CLI tool that converts YAML/JSON/TOML resume data into polished PDFs, DOCX,…</text><rect x="24" y="128" width="760" height="52" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="128" width="4" height="52" rx="2" fill="#3fb950"/><text x="40" y="146" class="t t-card-title">linear-gp</text><text x="768" y="146" class="t t-value" text-anchor="end">★ 2</text><text x="40" y="162" class="t t-card-detail">A production-grade Rust framework for Linear Genetic Programming research, featuring modu…</text><rect x="24" y="190" width="760" height="52" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="190" width="4" height="52" rx="2" fill="#d29922"/><text x="40" y="208" class="t t-card-title">zigbee-rest</text><text x="768" y="208" class="t t-value" text-anchor="end">★ 0</text><text x="40" y="224" class="t t-card-detail">Local-first, privacy-focused smart home control system. Manage Zigbee devices through a R…</text><rect x="24" y="252" width="760" height="52" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="252" width="4" height="52" rx="2" fill="#f85149"/><text x="40" y="270" class="t t-card-title">urmzd.com</text><text x="768" y="270" class="t t-value" text-anchor="end">★ 0</text><text x="40" y="286" class="t t-card-detail">Personal website and blog built with Astro, TypeScript, and MDX—featuring fast static sit…</text><rect x="24" y="314" width="760" height="52" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="314" width="4" height="52" rx="2" fill="#bc8cff"/><text x="40" y="332" class="t t-card-title">resume-generator-app</text><text x="768" y="332" class="t t-value" text-anchor="end">★ 0</text><text x="40" y="348" class="t t-card-detail">A native desktop app for building polished resumes with live PDF preview, template galler…</text></svg>
|
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
.t-card-detail { font-size: 11px; fill: #8b949e; }
|
|
12
12
|
.t-pill { font-size: 11px; font-weight: 600; }
|
|
13
13
|
.t-bullet { font-size: 12px; fill: #c9d1d9; }
|
|
14
|
-
</style></defs><rect width="808" height="186" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">OPEN SOURCE CONTRIBUTIONS</text><text x="24" y="56" class="t t-sub">External repositories contributed to (all time)</text><rect x="24" y="66" width="760" height="44" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="66" width="4" height="44" rx="2" fill="#58a6ff"/><text x="40" y="84" class="t t-card-title">MathisWellmann/gym-rs</text><text x="40" y="100" class="t t-card-detail">★
|
|
14
|
+
</style></defs><rect width="808" height="186" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">OPEN SOURCE CONTRIBUTIONS</text><text x="24" y="56" class="t t-sub">External repositories contributed to (all time)</text><rect x="24" y="66" width="760" height="44" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="66" width="4" height="44" rx="2" fill="#58a6ff"/><text x="40" y="84" class="t t-card-title">MathisWellmann/gym-rs</text><text x="40" y="100" class="t t-card-detail">★ 127 · Rust</text><rect x="24" y="118" width="760" height="44" rx="6" fill="#161b22" stroke="#30363d" stroke-width="1"/><rect x="24" y="118" width="4" height="44" rx="2" fill="#3fb950"/><text x="40" y="136" class="t t-card-title">getzep/graphiti</text><text x="40" y="152" class="t t-card-detail">★ 23,825 · Python</text></svg>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="808" height="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="808" height="550" viewBox="0 0 808 550"><defs><style>
|
|
2
2
|
.t { font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif; }
|
|
3
3
|
.t-h { font-size: 13px; fill: #c9d1d9; letter-spacing: 1.5px; font-weight: 600; }
|
|
4
4
|
.t-sub { font-size: 11px; fill: #6e7681; }
|
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
.t-card-detail { font-size: 11px; fill: #8b949e; }
|
|
12
12
|
.t-pill { font-size: 11px; font-weight: 600; }
|
|
13
13
|
.t-bullet { font-size: 12px; fill: #c9d1d9; }
|
|
14
|
-
</style></defs><rect width="808" height="
|
|
14
|
+
</style></defs><rect width="808" height="550" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">EXPERTISE</text><text x="24" y="56" class="t t-sub">Curated from dependencies, topics, and languages via AI analysis</text><text x="24" y="80" class="t t-subhdr">AI & MACHINE LEARNING</text><rect x="24" y="92" width="700" height="18" rx="4" fill="#58a6ff" fill-opacity="0.15"/><rect x="24" y="92" width="630" height="18" rx="4" fill="#58a6ff" fill-opacity="0.85"/><text x="734" y="105" class="t t-value">90%</text><text x="24" y="126" class="t t-card-detail">PyTorch · PyTorch Lightning · Rust (Linear Genetic Programm… · Retrieval-Augmented Generatio… · Knowledge Graphs</text><text x="24" y="142" class="t t-card-detail">(SurrealDB) · Q-Learning</text><text x="24" y="170" class="t t-subhdr">WEB DEVELOPMENT & STATIC SITES</text><rect x="24" y="182" width="700" height="18" rx="4" fill="#3fb950" fill-opacity="0.15"/><rect x="24" y="182" width="595" height="18" rx="4" fill="#3fb950" fill-opacity="0.85"/><text x="734" y="195" class="t t-value">85%</text><text x="24" y="216" class="t t-card-detail">Astro · React · TypeScript · Tailwind CSS · MDX</text><text x="24" y="244" class="t t-subhdr">BACKEND & APIS</text><rect x="24" y="256" width="700" height="18" rx="4" fill="#d29922" fill-opacity="0.15"/><rect x="24" y="256" width="560" height="18" rx="4" fill="#d29922" fill-opacity="0.85"/><text x="734" y="269" class="t t-value">80%</text><text x="24" y="290" class="t t-card-detail">Go · FastAPI · OpenAPI · SurrealDB · Graph-enhanced Retrieval</text><text x="24" y="318" class="t t-subhdr">DEVOPS & AUTOMATION</text><rect x="24" y="330" width="700" height="18" rx="4" fill="#f85149" fill-opacity="0.15"/><rect x="24" y="330" width="525" height="18" rx="4" fill="#f85149" fill-opacity="0.85"/><text x="734" y="343" class="t t-value">75%</text><text x="24" y="364" class="t t-card-detail">GitHub Actions · CI/CD · Chezmoi · Nix · Docker</text><text x="24" y="392" class="t t-subhdr">DESKTOP & CLI APPLICATIONS</text><rect x="24" y="404" width="700" height="18" rx="4" fill="#bc8cff" fill-opacity="0.15"/><rect x="24" y="404" width="489.99999999999994" height="18" rx="4" fill="#bc8cff" fill-opacity="0.85"/><text x="734" y="417" class="t t-value">70%</text><text x="24" y="438" class="t t-card-detail">Rust · Go · JavaFX · Wails · Textual</text><text x="24" y="466" class="t t-subhdr">DOCUMENTATION & PUBLISHING</text><rect x="24" y="478" width="700" height="18" rx="4" fill="#39d2c0" fill-opacity="0.15"/><rect x="24" y="478" width="420" height="18" rx="4" fill="#39d2c0" fill-opacity="0.85"/><text x="734" y="491" class="t t-value">60%</text><text x="24" y="512" class="t t-card-detail">TeX/LaTeX · Pandoc · Markdown · PDF Generation</text></svg>
|
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
.t-card-detail { font-size: 11px; fill: #8b949e; }
|
|
12
12
|
.t-pill { font-size: 11px; font-weight: 600; }
|
|
13
13
|
.t-bullet { font-size: 12px; fill: #c9d1d9; }
|
|
14
|
-
</style></defs><rect width="808" height="350" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">LANGUAGES</text><text x="24" y="56" class="t t-sub">By bytes of code across all public repos</text><circle cx="114" cy="156" r="70" fill="none" stroke="#00ADD8" stroke-width="28" stroke-dasharray="
|
|
14
|
+
</style></defs><rect width="808" height="350" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">LANGUAGES</text><text x="24" y="56" class="t t-sub">By bytes of code across all public repos</text><circle cx="114" cy="156" r="70" fill="none" stroke="#00ADD8" stroke-width="28" stroke-dasharray="120.51149419170444 319.31147731086656" stroke-dashoffset="0" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#3178c6" stroke-width="28" stroke-dasharray="110.8353888186479 328.9875826839231" stroke-dashoffset="-120.51149419170444" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#dea584" stroke-width="28" stroke-dasharray="108.63627396113505 331.186697541436" stroke-dashoffset="-231.34688301035234" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#3D6117" stroke-width="28" stroke-dasharray="19.792033717615695 420.0309377849553" stroke-dashoffset="-339.9831569714874" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#89e051" stroke-width="28" stroke-dasharray="15.833626974092558 423.98934452847845" stroke-dashoffset="-359.7751906891031" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#3572A5" stroke-width="28" stroke-dasharray="13.634512116579701 426.18845938599134" stroke-dashoffset="-375.6088176631957" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#a52a22" stroke-width="28" stroke-dasharray="7.916813487046279 431.90615801552474" stroke-dashoffset="-389.24332977977537" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#b07219" stroke-width="28" stroke-dasharray="6.597344572538565 433.22562693003243" stroke-dashoffset="-397.16014326682165" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#663399" stroke-width="28" stroke-dasharray="5.717698629533424 434.1052728730376" stroke-dashoffset="-403.75748783936024" transform="rotate(-90 114 156)" opacity="0.85"/><circle cx="114" cy="156" r="70" fill="none" stroke="#000080" stroke-width="28" stroke-dasharray="5.717698629533424 434.1052728730376" stroke-dashoffset="-409.47518646889364" transform="rotate(-90 114 156)" opacity="0.85"/><text x="114" y="161" class="t" fill="#c9d1d9" font-size="14" font-weight="700" text-anchor="middle">10</text><text x="114" y="176" class="t" fill="#6e7681" font-size="10" text-anchor="middle">languages</text><rect x="244" y="76" width="12" height="12" rx="2" fill="#00ADD8" opacity="0.85"/><text x="264" y="86" class="t t-label">Go</text><text x="444" y="86" class="t t-value" text-anchor="end">27.4%</text><rect x="244" y="100" width="12" height="12" rx="2" fill="#3178c6" opacity="0.85"/><text x="264" y="110" class="t t-label">TypeScript</text><text x="444" y="110" class="t t-value" text-anchor="end">25.2%</text><rect x="244" y="124" width="12" height="12" rx="2" fill="#dea584" opacity="0.85"/><text x="264" y="134" class="t t-label">Rust</text><text x="444" y="134" class="t t-value" text-anchor="end">24.7%</text><rect x="244" y="148" width="12" height="12" rx="2" fill="#3D6117" opacity="0.85"/><text x="264" y="158" class="t t-label">TeX</text><text x="444" y="158" class="t t-value" text-anchor="end">4.5%</text><rect x="244" y="172" width="12" height="12" rx="2" fill="#89e051" opacity="0.85"/><text x="264" y="182" class="t t-label">Shell</text><text x="444" y="182" class="t t-value" text-anchor="end">3.6%</text><rect x="244" y="196" width="12" height="12" rx="2" fill="#3572A5" opacity="0.85"/><text x="264" y="206" class="t t-label">Python</text><text x="444" y="206" class="t t-value" text-anchor="end">3.1%</text><rect x="244" y="220" width="12" height="12" rx="2" fill="#a52a22" opacity="0.85"/><text x="264" y="230" class="t t-label">Jinja</text><text x="444" y="230" class="t t-value" text-anchor="end">1.8%</text><rect x="244" y="244" width="12" height="12" rx="2" fill="#b07219" opacity="0.85"/><text x="264" y="254" class="t t-label">Java</text><text x="444" y="254" class="t t-value" text-anchor="end">1.5%</text><rect x="244" y="268" width="12" height="12" rx="2" fill="#663399" opacity="0.85"/><text x="264" y="278" class="t t-label">CSS</text><text x="444" y="278" class="t t-value" text-anchor="end">1.3%</text><rect x="244" y="292" width="12" height="12" rx="2" fill="#000080" opacity="0.85"/><text x="264" y="302" class="t t-label">Lua</text><text x="444" y="302" class="t t-value" text-anchor="end">1.3%</text></svg>
|
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
.t-card-detail { font-size: 11px; fill: #8b949e; }
|
|
12
12
|
.t-pill { font-size: 11px; font-weight: 600; }
|
|
13
13
|
.t-bullet { font-size: 12px; fill: #c9d1d9; }
|
|
14
|
-
</style></defs><rect width="808" height="162" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">AT A GLANCE</text><text x="24" y="56" class="t t-sub">Contribution activity over the past year</text><rect x="24" y="66" width="140" height="72" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/><circle cx="38" cy="82" r="4" fill="#58a6ff"/><text x="48" y="86" class="t t-stat-label">COMMITS</text><text x="94" y="118" fill="#58a6ff" class="t t-stat-value" text-anchor="middle">1,
|
|
14
|
+
</style></defs><rect width="808" height="162" rx="12" fill="#0d1117"/><text x="24" y="40" class="t t-h">AT A GLANCE</text><text x="24" y="56" class="t t-sub">Contribution activity over the past year</text><rect x="24" y="66" width="140" height="72" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/><circle cx="38" cy="82" r="4" fill="#58a6ff"/><text x="48" y="86" class="t t-stat-label">COMMITS</text><text x="94" y="118" fill="#58a6ff" class="t t-stat-value" text-anchor="middle">1,117</text><rect x="179" y="66" width="140" height="72" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/><circle cx="193" cy="82" r="4" fill="#3fb950"/><text x="203" y="86" class="t t-stat-label">PRS</text><text x="249" y="118" fill="#3fb950" class="t t-stat-value" text-anchor="middle">3</text><rect x="334" y="66" width="140" height="72" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/><circle cx="348" cy="82" r="4" fill="#d29922"/><text x="358" y="86" class="t t-stat-label">REVIEWS</text><text x="404" y="118" fill="#d29922" class="t t-stat-value" text-anchor="middle">5</text><rect x="489" y="66" width="140" height="72" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/><circle cx="503" cy="82" r="4" fill="#bc8cff"/><text x="513" y="86" class="t t-stat-label">REPOS</text><text x="559" y="118" fill="#bc8cff" class="t t-stat-value" text-anchor="middle">26</text></svg>
|
package/package.json
CHANGED
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
},
|
|
17
17
|
"license": "Apache-2.0",
|
|
18
18
|
"name": "@urmzd/github-insights",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/urmzd/github-insights.git"
|
|
22
|
+
},
|
|
19
23
|
"scripts": {
|
|
20
24
|
"build": "ncc build src/index.ts -o dist --source-map --license licenses.txt",
|
|
21
25
|
"ci": "npm run fmt && npm run lint && npm run typecheck && npm run test && npm run build",
|
|
@@ -26,10 +30,6 @@
|
|
|
26
30
|
"test": "vitest run",
|
|
27
31
|
"typecheck": "tsc --noEmit"
|
|
28
32
|
},
|
|
29
|
-
"repository": {
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "https://github.com/urmzd/github-insights.git"
|
|
32
|
-
},
|
|
33
33
|
"type": "module",
|
|
34
|
-
"version": "2.
|
|
34
|
+
"version": "2.1.0"
|
|
35
35
|
}
|
package/src/api.ts
CHANGED
|
@@ -86,7 +86,7 @@ export const fetchAllRepoData = async (
|
|
|
86
86
|
{ username },
|
|
87
87
|
);
|
|
88
88
|
|
|
89
|
-
return data.user.repositories.nodes.filter((r) => !r.
|
|
89
|
+
return data.user.repositories.nodes.filter((r) => !r.isFork);
|
|
90
90
|
};
|
|
91
91
|
|
|
92
92
|
export const fetchManifestsForRepos = async (
|
package/src/config.ts
CHANGED
|
@@ -17,10 +17,7 @@ function extractConfig(parsed: Record<string, unknown>): UserConfig {
|
|
|
17
17
|
if (typeof parsed.name === "string" && parsed.name.trim()) {
|
|
18
18
|
config.name = parsed.name.trim();
|
|
19
19
|
}
|
|
20
|
-
if (
|
|
21
|
-
typeof parsed.pronunciation === "string" &&
|
|
22
|
-
parsed.pronunciation.trim()
|
|
23
|
-
) {
|
|
20
|
+
if (typeof parsed.pronunciation === "string" && parsed.pronunciation.trim()) {
|
|
24
21
|
config.pronunciation = parsed.pronunciation.trim();
|
|
25
22
|
}
|
|
26
23
|
if (typeof parsed.bio === "string" && parsed.bio.trim()) {
|
|
@@ -51,11 +48,14 @@ function extractConfig(parsed: Record<string, unknown>): UserConfig {
|
|
|
51
48
|
return config;
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
export function parseUserConfig(
|
|
51
|
+
export function parseUserConfig(
|
|
52
|
+
raw: string,
|
|
53
|
+
format: "yaml" | "toml" = "yaml",
|
|
54
|
+
): UserConfig {
|
|
55
55
|
const parsed =
|
|
56
56
|
format === "toml"
|
|
57
57
|
? toml.parse(raw)
|
|
58
|
-
: (yaml.parse(raw) as Record<string, unknown>) ?? {};
|
|
58
|
+
: ((yaml.parse(raw) as Record<string, unknown>) ?? {});
|
|
59
59
|
return extractConfig(parsed);
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -93,11 +93,5 @@ function resolveConfigPath(): { path: string; format: "yaml" | "toml" } {
|
|
|
93
93
|
if (existsSync("github-insights.yaml")) {
|
|
94
94
|
return { path: "github-insights.yaml", format: "yaml" };
|
|
95
95
|
}
|
|
96
|
-
if (existsSync(".github-metrics.toml")) {
|
|
97
|
-
console.warn(
|
|
98
|
-
'Warning: ".github-metrics.toml" is deprecated. Please rename it to "github-insights.yml".',
|
|
99
|
-
);
|
|
100
|
-
return { path: ".github-metrics.toml", format: "toml" };
|
|
101
|
-
}
|
|
102
96
|
return { path: "github-insights.yml", format: "yaml" };
|
|
103
97
|
}
|
package/src/index.ts
CHANGED
|
@@ -142,6 +142,7 @@ async function run(): Promise<void> {
|
|
|
142
142
|
active: activeProjects,
|
|
143
143
|
maintained: maintainedProjects,
|
|
144
144
|
inactive: inactiveProjects,
|
|
145
|
+
archived: archivedProjects,
|
|
145
146
|
} = splitProjectsByRecency(repos, contributionData, aiClassifications);
|
|
146
147
|
|
|
147
148
|
const sectionDefs = buildSections({
|
|
@@ -227,6 +228,7 @@ async function run(): Promise<void> {
|
|
|
227
228
|
...activeProjects,
|
|
228
229
|
...maintainedProjects,
|
|
229
230
|
...inactiveProjects,
|
|
231
|
+
...archivedProjects,
|
|
230
232
|
];
|
|
231
233
|
const categorizedProjects: Record<string, typeof allProjectItems> = {};
|
|
232
234
|
for (const project of allProjectItems) {
|
|
@@ -245,12 +247,14 @@ async function run(): Promise<void> {
|
|
|
245
247
|
title: userConfig.title,
|
|
246
248
|
bio: userConfig.bio,
|
|
247
249
|
preamble,
|
|
250
|
+
templateName,
|
|
248
251
|
svgs,
|
|
249
252
|
sectionSvgs,
|
|
250
253
|
profile: userProfile,
|
|
251
254
|
activeProjects,
|
|
252
255
|
maintainedProjects,
|
|
253
256
|
inactiveProjects,
|
|
257
|
+
archivedProjects,
|
|
254
258
|
allProjects: complexProjects,
|
|
255
259
|
categorizedProjects,
|
|
256
260
|
languages,
|
|
@@ -308,12 +312,14 @@ async function run(): Promise<void> {
|
|
|
308
312
|
title: userConfig.title,
|
|
309
313
|
bio: userConfig.bio,
|
|
310
314
|
preamble,
|
|
315
|
+
templateName: tplName,
|
|
311
316
|
svgs: previewSvgs,
|
|
312
317
|
sectionSvgs: previewSectionSvgs,
|
|
313
318
|
profile: userProfile,
|
|
314
319
|
activeProjects,
|
|
315
320
|
maintainedProjects,
|
|
316
321
|
inactiveProjects,
|
|
322
|
+
archivedProjects,
|
|
317
323
|
allProjects: complexProjects,
|
|
318
324
|
categorizedProjects,
|
|
319
325
|
languages,
|
package/src/metrics.ts
CHANGED
|
@@ -117,6 +117,7 @@ const toProjectItem = (repo: RepoNode): ProjectItem => ({
|
|
|
117
117
|
languageCount: repo.languages.edges.length,
|
|
118
118
|
codeSize: repo.diskUsage,
|
|
119
119
|
languages: repoLanguages(repo),
|
|
120
|
+
isArchived: repo.isArchived || undefined,
|
|
120
121
|
});
|
|
121
122
|
|
|
122
123
|
// ── Top Projects by Stars ───────────────────────────────────────────────────
|
|
@@ -190,6 +191,7 @@ export const splitProjectsByRecency = (
|
|
|
190
191
|
active: ProjectItem[];
|
|
191
192
|
maintained: ProjectItem[];
|
|
192
193
|
inactive: ProjectItem[];
|
|
194
|
+
archived: ProjectItem[];
|
|
193
195
|
} => {
|
|
194
196
|
const commitMap = new Map<string, number>();
|
|
195
197
|
for (const entry of contributionData.commitContributionsByRepository || []) {
|
|
@@ -206,8 +208,17 @@ export const splitProjectsByRecency = (
|
|
|
206
208
|
const activeRepos: RepoNode[] = [];
|
|
207
209
|
const maintainedRepos: RepoNode[] = [];
|
|
208
210
|
const inactiveRepos: RepoNode[] = [];
|
|
211
|
+
const archivedRepos: RepoNode[] = [];
|
|
209
212
|
|
|
210
213
|
for (const repo of repos) {
|
|
214
|
+
if (repo.isArchived) {
|
|
215
|
+
archivedRepos.push(repo);
|
|
216
|
+
console.info(
|
|
217
|
+
`[archived ] ${repo.name} (complexity=${complexityScore(repo).toFixed(1)})`,
|
|
218
|
+
);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
|
|
211
222
|
const commits = commitMap.get(repo.name) || 0;
|
|
212
223
|
const aiEntry = aiMap.get(repo.name);
|
|
213
224
|
const status = aiEntry?.status || heuristicStatus(commits, repo.createdAt);
|
|
@@ -227,7 +238,7 @@ export const splitProjectsByRecency = (
|
|
|
227
238
|
}
|
|
228
239
|
|
|
229
240
|
console.info(
|
|
230
|
-
`Split: ${activeRepos.length} active, ${maintainedRepos.length} maintained, ${inactiveRepos.length} inactive`,
|
|
241
|
+
`Split: ${activeRepos.length} active, ${maintainedRepos.length} maintained, ${inactiveRepos.length} inactive, ${archivedRepos.length} archived`,
|
|
231
242
|
);
|
|
232
243
|
|
|
233
244
|
const sortByComplexity = (a: RepoNode, b: RepoNode) =>
|
|
@@ -248,8 +259,11 @@ export const splitProjectsByRecency = (
|
|
|
248
259
|
const inactive: ProjectItem[] = inactiveRepos
|
|
249
260
|
.sort(sortByComplexity)
|
|
250
261
|
.map(toProjectItemWithSummary);
|
|
262
|
+
const archived: ProjectItem[] = archivedRepos
|
|
263
|
+
.sort(sortByComplexity)
|
|
264
|
+
.map(toProjectItemWithSummary);
|
|
251
265
|
|
|
252
|
-
return { active, maintained, inactive };
|
|
266
|
+
return { active, maintained, inactive, archived };
|
|
253
267
|
};
|
|
254
268
|
|
|
255
269
|
// ── Section definitions ─────────────────────────────────────────────────────
|
package/src/readme.test.ts
CHANGED
|
@@ -5,10 +5,10 @@ describe("generateReadme", () => {
|
|
|
5
5
|
it("renders minimal readme (name + single SVG)", () => {
|
|
6
6
|
const result = generateReadme({
|
|
7
7
|
name: "octocat",
|
|
8
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
8
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
9
9
|
});
|
|
10
10
|
expect(result).toContain(
|
|
11
|
-
"# octocat\n\n",
|
|
12
12
|
);
|
|
13
13
|
expect(result).toMatch(
|
|
14
14
|
/Last generated on \d{4}-\d{2}-\d{2} using \[@urmzd\/github-insights\]/,
|
|
@@ -19,7 +19,7 @@ describe("generateReadme", () => {
|
|
|
19
19
|
const result = generateReadme({
|
|
20
20
|
name: "Urmzd",
|
|
21
21
|
pronunciation: "/ˈʊrm.zəd/",
|
|
22
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
22
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
23
23
|
});
|
|
24
24
|
expect(result).toContain("# Urmzd <sub><i>(/ˈʊrm.zəd/)</i></sub>");
|
|
25
25
|
});
|
|
@@ -27,7 +27,7 @@ describe("generateReadme", () => {
|
|
|
27
27
|
it("omits pronunciation when not set", () => {
|
|
28
28
|
const result = generateReadme({
|
|
29
29
|
name: "Urmzd",
|
|
30
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
30
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
31
31
|
});
|
|
32
32
|
expect(result).not.toContain("<sub><i>");
|
|
33
33
|
expect(result).toContain("# Urmzd\n");
|
|
@@ -37,7 +37,7 @@ describe("generateReadme", () => {
|
|
|
37
37
|
const result = generateReadme({
|
|
38
38
|
name: "Urmzd",
|
|
39
39
|
title: "Senior Backend Engineer",
|
|
40
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
40
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
41
41
|
});
|
|
42
42
|
expect(result).toContain("> Senior Backend Engineer");
|
|
43
43
|
});
|
|
@@ -45,7 +45,7 @@ describe("generateReadme", () => {
|
|
|
45
45
|
it("omits title when not set", () => {
|
|
46
46
|
const result = generateReadme({
|
|
47
47
|
name: "Urmzd",
|
|
48
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
48
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
49
49
|
});
|
|
50
50
|
expect(result).not.toContain("> ");
|
|
51
51
|
});
|
|
@@ -54,7 +54,7 @@ describe("generateReadme", () => {
|
|
|
54
54
|
const result = generateReadme({
|
|
55
55
|
name: "Urmzd",
|
|
56
56
|
preamble: "Hello, I build things.",
|
|
57
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
57
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
58
58
|
});
|
|
59
59
|
expect(result).toContain("Hello, I build things.");
|
|
60
60
|
});
|
|
@@ -62,19 +62,19 @@ describe("generateReadme", () => {
|
|
|
62
62
|
it("omits preamble when not set", () => {
|
|
63
63
|
const result = generateReadme({
|
|
64
64
|
name: "Urmzd",
|
|
65
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
65
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
66
66
|
});
|
|
67
67
|
// Only heading + SVG + attribution + trailing newline
|
|
68
68
|
expect(result).not.toContain("Hello");
|
|
69
69
|
expect(result).toContain("# Urmzd");
|
|
70
|
-
expect(result).toContain(".toContain("");
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
it("preamble is not wrapped in code fences", () => {
|
|
74
74
|
const result = generateReadme({
|
|
75
75
|
name: "Urmzd",
|
|
76
76
|
preamble: "Hello, I build things.",
|
|
77
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
77
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
78
78
|
});
|
|
79
79
|
expect(result).toContain("Hello, I build things.");
|
|
80
80
|
expect(result).not.toContain("```");
|
|
@@ -86,7 +86,7 @@ describe("generateReadme", () => {
|
|
|
86
86
|
const result = generateReadme({
|
|
87
87
|
name: "Urmzd",
|
|
88
88
|
preamble: preamble,
|
|
89
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
89
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
90
90
|
});
|
|
91
91
|
expect(result).toContain(preamble);
|
|
92
92
|
expect(result).toContain(`# Urmzd\n\n${preamble}\n\n![GitHub Metrics]`);
|
|
@@ -98,7 +98,7 @@ describe("generateReadme", () => {
|
|
|
98
98
|
const result = generateReadme({
|
|
99
99
|
name: "Urmzd",
|
|
100
100
|
preamble: preamble,
|
|
101
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
101
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
102
102
|
});
|
|
103
103
|
expect(result).toContain("**bold**");
|
|
104
104
|
expect(result).toContain(
|
|
@@ -114,14 +114,14 @@ describe("generateReadme", () => {
|
|
|
114
114
|
pronunciation: "/ˈʊrm.zəd/",
|
|
115
115
|
title: "Senior Backend Engineer",
|
|
116
116
|
preamble: "Welcome to my profile!",
|
|
117
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
117
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
118
118
|
bio: "Building tools for developers",
|
|
119
119
|
});
|
|
120
120
|
expect(result).toContain(
|
|
121
121
|
"> Senior Backend Engineer\n\nWelcome to my profile!",
|
|
122
122
|
);
|
|
123
123
|
expect(result).toContain(
|
|
124
|
-
"Welcome to my profile!\n\n",
|
|
125
125
|
);
|
|
126
126
|
});
|
|
127
127
|
|
|
@@ -129,7 +129,7 @@ describe("generateReadme", () => {
|
|
|
129
129
|
const result = generateReadme({
|
|
130
130
|
name: "Urmzd",
|
|
131
131
|
bio: "Building tools for developers",
|
|
132
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
132
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
133
133
|
});
|
|
134
134
|
expect(result).toContain("---\n\n<sub>Building tools for developers</sub>");
|
|
135
135
|
});
|
|
@@ -137,7 +137,7 @@ describe("generateReadme", () => {
|
|
|
137
137
|
it("omits bio when not set", () => {
|
|
138
138
|
const result = generateReadme({
|
|
139
139
|
name: "Urmzd",
|
|
140
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
140
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
141
141
|
});
|
|
142
142
|
expect(result).not.toContain("---");
|
|
143
143
|
// Should only have the attribution <sub>, not a bio <sub>
|
|
@@ -150,14 +150,20 @@ describe("generateReadme", () => {
|
|
|
150
150
|
const result = generateReadme({
|
|
151
151
|
name: "Urmzd",
|
|
152
152
|
svgs: [
|
|
153
|
-
{ label: "Languages", path: "
|
|
154
|
-
{ label: "Projects", path: "
|
|
155
|
-
{ label: "Expertise", path: "
|
|
153
|
+
{ label: "Languages", path: "assets/insights/metrics-languages.svg" },
|
|
154
|
+
{ label: "Projects", path: "assets/insights/metrics-projects.svg" },
|
|
155
|
+
{ label: "Expertise", path: "assets/insights/metrics-expertise.svg" },
|
|
156
156
|
],
|
|
157
157
|
});
|
|
158
|
-
expect(result).toContain(
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
expect(result).toContain(
|
|
159
|
+
"",
|
|
160
|
+
);
|
|
161
|
+
expect(result).toContain(
|
|
162
|
+
"",
|
|
163
|
+
);
|
|
164
|
+
expect(result).toContain(
|
|
165
|
+
"",
|
|
166
|
+
);
|
|
161
167
|
});
|
|
162
168
|
|
|
163
169
|
it("renders all sections combined", () => {
|
|
@@ -166,7 +172,7 @@ describe("generateReadme", () => {
|
|
|
166
172
|
pronunciation: "/ˈʊrm.zəd/",
|
|
167
173
|
title: "Senior Backend Engineer",
|
|
168
174
|
preamble: "Welcome to my profile!",
|
|
169
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
175
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
170
176
|
bio: "Building tools for developers",
|
|
171
177
|
});
|
|
172
178
|
expect(result).toContain(
|
|
@@ -174,14 +180,14 @@ describe("generateReadme", () => {
|
|
|
174
180
|
);
|
|
175
181
|
expect(result).toContain("> Senior Backend Engineer");
|
|
176
182
|
expect(result).toContain("Welcome to my profile!");
|
|
177
|
-
expect(result).toContain(".toContain("");
|
|
178
184
|
expect(result).toContain("---\n\n<sub>Building tools for developers</sub>");
|
|
179
185
|
});
|
|
180
186
|
|
|
181
187
|
it("ends with a trailing newline", () => {
|
|
182
188
|
const result = generateReadme({
|
|
183
189
|
name: "octocat",
|
|
184
|
-
svgs: [{ label: "GitHub Metrics", path: "
|
|
190
|
+
svgs: [{ label: "GitHub Metrics", path: "assets/insights/index.svg" }],
|
|
185
191
|
});
|
|
186
192
|
expect(result.endsWith("\n")).toBe(true);
|
|
187
193
|
expect(result.endsWith("\n\n")).toBe(false);
|