Skip to content

Commit 90cf92d

Browse files
TMHSDigitalclaude
andcommitted
counts: headline, badge and README tables count listed entries only
The hero, README badge, "Browse N sources" and category tables counted deprecated entries, which the catalog hides, so they disagreed with the "All" chip. They now count listed entries (418); the catalog blurb names the deprecated ones separately, and expectedEntryCount still counts every file. sync-counts and the V6 check use the same rule. Closes #175 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpkeXRUqm7oDedPDk3QWtK
1 parent e7c97de commit 90cf92d

7 files changed

Lines changed: 39 additions & 14 deletions

File tree

‎README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
**Free assets and tools for commercial games, with every licence read at its source.**
66

7-
[**Browse 420 sources**](https://tmhsdigital.github.io/Free-Game-Dev-Assets/) · [Starter stacks](#starter-stacks) · [Choose by job](#start-here) · [Licences](#licences) · [Contribute](#contributing)
7+
[**Browse 418 sources**](https://tmhsdigital.github.io/Free-Game-Dev-Assets/) · [Starter stacks](#starter-stacks) · [Choose by job](#start-here) · [Licences](#licences) · [Contribute](#contributing)
88

99
[![Website](https://img.shields.io/website?url=https%3A%2F%2Ftmhsdigital.github.io%2FFree-Game-Dev-Assets%2F&up_message=live&down_message=down&label=website)](https://tmhsdigital.github.io/Free-Game-Dev-Assets/)
1010
[![Pages](https://img.shields.io/github/actions/workflow/status/TMHSDigital/Free-Game-Dev-Assets/pages.yml?label=pages)](https://github.com/TMHSDigital/Free-Game-Dev-Assets/actions/workflows/pages.yml)
11-
[![Sources](https://img.shields.io/badge/sources-420-informational)](https://tmhsdigital.github.io/Free-Game-Dev-Assets/)
11+
[![Sources](https://img.shields.io/badge/sources-418-informational)](https://tmhsdigital.github.io/Free-Game-Dev-Assets/)
1212
[![License: CC0-1.0](https://img.shields.io/badge/license-CC0--1.0-lightgrey.svg)](LICENSE)
1313
<br />
1414
[![GitHub stars](https://img.shields.io/github/stars/TMHSDigital/Free-Game-Dev-Assets)](https://github.com/TMHSDigital/Free-Game-Dev-Assets/stargazers)
@@ -150,7 +150,7 @@ is a page on the site.
150150

151151
## Browse the catalog
152152

153-
The [website](https://tmhsdigital.github.io/Free-Game-Dev-Assets/) searches all 420 entries
153+
The [website](https://tmhsdigital.github.io/Free-Game-Dev-Assets/) searches all 418 entries
154154
and filters them by category, commercial use, attribution, review status and 2D camera
155155
view. Press `/` to search. Filtered views and individual entries have their own URLs, so you can send
156156
someone exactly what you are looking at.
@@ -160,7 +160,7 @@ someone exactly what you are looking at.
160160
| **3D** | 77 | Models, scans, PBR textures and materials | [`catalog/3d/`](catalog/3d/) |
161161
| **Tools** | 121 | Editors, pipeline, TTS, Godot add-ons | [`catalog/tools/`](catalog/tools/) |
162162
| **2D** | 60 | Sprites, tilesets, UI and HUD, icons, palettes | [`catalog/2d/`](catalog/2d/) |
163-
| **Audio** | 38 | SFX, music, foley, impulse responses | [`catalog/audio/`](catalog/audio/) |
163+
| **Audio** | 36 | SFX, music, foley, impulse responses | [`catalog/audio/`](catalog/audio/) |
164164
| **Characters** | 30 | Rigged packs, generators, modular humanoids | [`catalog/characters/`](catalog/characters/) |
165165
| **Fonts** | 25 | OFL and commercial-ok typefaces, CJK | [`catalog/fonts/`](catalog/fonts/) |
166166
| **Environment** | 20 | HDRI, terrain DEMs, geodata | [`catalog/environment/`](catalog/environment/) |

‎catalog/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ One markdown file per source under a category folder. Copy [`TEMPLATE.md`](TEMPL
77
| 3D | 77 | [`3d/`](3d/) | Models, scans, PBR textures |
88
| Tools | 121 | [`tools/`](tools/) | Editors, pipeline, TTS, Godot add-ons |
99
| 2D | 60 | [`2d/`](2d/) | Sprites, UI, icons, palettes |
10-
| Audio | 38 | [`audio/`](audio/) | SFX, music, foley, IRs |
10+
| Audio | 36 | [`audio/`](audio/) | SFX, music, foley, IRs |
1111
| Characters | 30 | [`characters/`](characters/) | Generators & modular humanoids |
1212
| Fonts | 25 | [`fonts/`](fonts/) | OFL / commercial-ok type |
1313
| Environment | 20 | [`environment/`](environment/) | HDRI, terrain, geodata |

‎site/build.mjs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ function headMetaHtml(site, stats, generatedAt, hasCard) {
216216
baseHeadHtml({ site, title: site.title, description: site.tagline, url: site.siteUrl, hasCard, root: "./", modules: PAGE_MODULES.home }),
217217
`<meta name="generator" content="site/build.mjs ${esc(generatedAt)}" />`,
218218
`<meta name="catalog:entries" content="${stats.total}" />`,
219-
`<script type="application/ld+json">${scriptJson(homeJsonLd({ site, generatedAt, total: stats.total }))}</script>`,
219+
`<script type="application/ld+json">${scriptJson(homeJsonLd({ site, generatedAt, total: stats.total - stats.deprecated }))}</script>`,
220220
].join("\n ");
221221
}
222222

@@ -674,11 +674,12 @@ function main() {
674674
STARTER_ROWS: starterRowsHtml(featured),
675675
// Each category shows its first few entries; the category pages hold the rest.
676676
ENTRY_ROWS: groupedEntriesHtml(visible, config.categories, { root: "", repo: repoUrl, now }),
677-
HERO_COUNT: String(stats.total),
677+
// The headline counts what the catalog lists; deprecated entries are hidden by default.
678+
HERO_COUNT: String(visible.length),
678679
FILMSTRIP: filmstripHtml(filmstripPick(visible, { count: 9, cardCategories }), { root: "" }),
679680
CATEGORY_CHIPS: categoryChipsHtml(visible, config.categories),
680681
GUIDE_ROWS: guideRowsHtml(config.guides, repoUrl),
681-
CATALOG_BLURB: `${stats.total} sources &middot; ${stats.active} active &middot; ${stats.commercialOk} commercial-ok &middot; ${stats.commercialVaries} per-file &middot; ${stats.deprecated} deprecated`,
682+
CATALOG_BLURB: `${visible.length} sources &middot; ${stats.active} active &middot; ${stats.commercialOk} commercial-ok &middot; ${stats.commercialVaries} per-file${stats.deprecated ? ` &middot; plus ${stats.deprecated} deprecated, hidden by default` : ""}`,
682683
RESULT_COUNT: `${visible.length} of ${stats.total} entries shown`,
683684
SPONSOR_BUTTON: sponsorButtonHtml(),
684685
PREVIEW_CREDIT: PREVIEW_CREDIT_LINE,

‎site/lib/entry-files.mjs‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,31 @@ export function listEntryFiles(dir) {
4040
return out.sort();
4141
}
4242

43+
/** True when an entry file's frontmatter says `status: deprecated`. */
44+
export function isDeprecated(text) {
45+
const fm = String(text).match(/^---\r?\n([\s\S]*?)\r?\n---/);
46+
return Boolean(fm && /^status:\s*["']?deprecated["']?\s*(#.*)?$/m.test(fm[1]));
47+
}
48+
4349
/**
4450
* Entry counts per category folder, from the same list build and validate
4551
* use, so a skipped folder (catalog/_scratch) never counts. `total` also
4652
* includes any entry file outside a category folder, as validate's does.
4753
*/
4854
export function countEntriesByCategory(catalogDir) {
4955
const files = listEntryFiles(catalogDir);
56+
let deprecated = 0;
5057
const counts = {};
5158
for (const d of fs.readdirSync(catalogDir, { withFileTypes: true })) {
5259
if (d.isDirectory() && !d.name.startsWith(".") && !SKIP_DIRS.has(d.name)) counts[d.name] = 0;
5360
}
5461
for (const file of files) {
5562
const [first, ...rest] = path.relative(catalogDir, file).split(path.sep);
63+
if (isDeprecated(fs.readFileSync(file, "utf8"))) {
64+
deprecated += 1;
65+
continue;
66+
}
5667
if (rest.length && first in counts) counts[first] += 1;
5768
}
58-
return { counts, total: files.length };
69+
return { counts, total: files.length - deprecated, files: files.length, deprecated };
5970
}

‎site/lib/lib.test.mjs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,12 @@ eq("search: q from the URL is capped", readState(`?q=${"a".repeat(5000)}`, { q:
14481448
eq("counts: per category, nested files included", Object.entries(counts).sort().map(([k, n]) => `${k}=${n}`).join(","), "2d=2,audio=1");
14491449
eq("counts: total skips _scratch and hidden folders", total, 3);
14501450
eq("counts: total matches the entry list build and validate use", total, listEntryFiles(root).length);
1451+
nodeFs.writeFileSync(nodePath.join(root, "audio/old.md"), "---\nid: old\nstatus: deprecated # moved\n---\n\nGone.\n");
1452+
nodeFs.writeFileSync(nodePath.join(root, "audio/body.md"), "---\nid: body\nstatus: active\n---\n\nstatus: deprecated\n");
1453+
const listed = countEntriesByCategory(root);
1454+
eq("counts: a deprecated entry is not listed", listed.counts.audio, 2);
1455+
eq("counts: total is listed entries only", listed.total, 4);
1456+
eq("counts: files and deprecated are reported", `${listed.files}/${listed.deprecated}`, "5/1");
14511457
} finally {
14521458
nodeFs.rmSync(root, { recursive: true, force: true });
14531459
}

‎site/sync-counts.mjs‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
* Rewrites every place the repo restates the entry count, from the catalog
44
* itself: the category tables in README.md and catalog/README.md, the README
55
* badge, "Browse N sources", "searches all N entries", and
6-
* expectedEntryCount in site/config.json. Run after adding or removing
7-
* entries: node site/sync-counts.mjs. The validator (V6) checks the same
6+
* expectedEntryCount in site/config.json. The README and table counts are
7+
* of listed entries (deprecated ones are hidden on the site, so the numbers
8+
* match its "All" chip); expectedEntryCount counts every file. Run after
9+
* adding, removing or deprecating entries: node site/sync-counts.mjs. The validator (V6) checks the same
810
* places, so it passes afterwards.
911
*/
1012
import fs from "node:fs";
@@ -27,10 +29,10 @@ function update(file, fn) {
2729
}
2830
}
2931

30-
const { counts, total } = countEntriesByCategory(CATALOG);
32+
const { counts, total, files, deprecated } = countEntriesByCategory(CATALOG);
3133

3234
update("README.md", (t) => syncReadme(t, counts, total));
3335
update("catalog/README.md", (t) => syncCatalogReadme(t, counts));
34-
update("site/config.json", (t) => syncConfig(t, total));
36+
update("site/config.json", (t) => syncConfig(t, files));
3537

36-
console.log(`${total} entries: ${Object.entries(counts).map(([c, n]) => `${c} ${n}`).join(", ")}`);
38+
console.log(`${total} listed entries (${files} files, ${deprecated} deprecated): ${Object.entries(counts).map(([c, n]) => `${c} ${n}`).join(", ")}`);

‎site/validate.mjs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ function main() {
372372
const measured = {};
373373
for (const { meta } of records) {
374374
const cat = String(meta.category);
375+
// The README counts match the site's "All" chip: deprecated entries are not listed.
376+
if (meta.status === "deprecated") {
377+
measured[cat] = measured[cat] || 0;
378+
continue;
379+
}
375380
measured[cat] = (measured[cat] || 0) + 1;
376381
}
377382
errors.push(

0 commit comments

Comments
 (0)