Files
ai-for-dummies/scripts/build-skill-review.mjs
T
Marcos Paulo db4ae19c0a feat: add reviews content collection
Move all 24 review entries from skills-review/catalog.js +
skills-review/submitted-catalog.js into a typed Astro content collection at
src/content/reviews/. Each entry is a Markdown file with frontmatter for the
review metadata (id, author, focus, wins, improve, extras, name, description)
and a body that holds the 'improved' SKILL.md content.

Re-point scripts/build-skill-review.mjs at the new collection. The generator
reads each .md file, parses its YAML frontmatter, and writes
skill-reviews/improved/{id}/SKILL.md in the same shape the legacy catalog
produced — verified byte-identical via 'git diff --exit-code skill-reviews/'.

The 'name' field is preserved separately from 'id' because two entries
renamed the skill during review (id angular-accessibility-root → name
angular-accessibility; id confectionary-skill-hub → name confectionery-orders).
Without it the generator output would drift on those two files.

Does not yet delete skills-review/catalog.js or submitted-catalog.js —
verify.mjs and the legacy review-desk page both still read them, so they
stay as a mirror until task 16 rewires the page to the collection. Adding a
new submission today requires editing both the .md file (new source of
truth) and the legacy catalog.js (until task 16).

Done-when:
- 24 entries under src/content/reviews/ ✓
- verify.mjs's id:' count assertion still passes ✓
- git diff --exit-code skill-reviews/ clean after regenerating ✓
- astro check passes (22 files: 0 errors, 0 warnings, 2 hints) ✓

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-05 06:21:58 +00:00

69 lines
2.9 KiB
JavaScript

// Regenerate skill-reviews/improved/**/SKILL.md from the content collection.
//
// Source of truth: src/content/reviews/{id}.md. Each file's frontmatter holds
// the review metadata (id, author, focus, wins, improve, extras,
// description); its body is the Markdown that becomes the SKILL.md file.
// This script reconstructs the SKILL.md frontmatter (name + description) and
// concatenates it with the body, so the committed output stays byte-identical
// to what the legacy catalog produced:
//
// --- <- SKILL.md frontmatter starts
// name: <id>
// description: <description>
// ---
//
// # <id>
// <- body, as written in the .md file
// ...
//
// Run from the repository root:
//
// node scripts/build-skill-review.mjs && git diff --exit-code skill-reviews/
//
// A non-empty diff means the collection drifted from the committed output;
// regenerate after every entry edit.
import { mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const here = dirname(fileURLToPath(import.meta.url));
const root = dirname(here);
const REVIEWS_DIR = join(root, 'src', 'content', 'reviews');
const OUTPUT_DIR = join(root, 'skill-reviews', 'improved');
const parseFrontmatter = (text) => {
// Strict shape: starts with `---\n`, ends at the next `---\n`, then body.
if (!text.startsWith('---\n')) throw new Error('missing leading ---');
const end = text.indexOf('\n---\n', 4);
if (end === -1) throw new Error('missing closing ---');
const yaml = text.slice(4, end);
const body = text.slice(end + 5);
const id = yaml.match(/^id:\s*"?([^"\n]+)"?\s*$/m)?.[1];
const name = yaml.match(/^name:\s*"?([^"\n]+)"?\s*$/m)?.[1];
const description = yaml.match(/^description:\s*"?((?:\\.|[^"\\])*)"?\s*$/m)?.[1];
if (!id) throw new Error('frontmatter missing id');
if (!name) throw new Error('frontmatter missing name');
if (!description) throw new Error('frontmatter missing description');
return { id, name, description, body };
};
const files = readdirSync(REVIEWS_DIR)
.filter((f) => f.endsWith('.md'))
.sort();
let count = 0;
for (const file of files) {
const source = readFileSync(join(REVIEWS_DIR, file), 'utf8');
const { id, name, description, body } = parseFrontmatter(source);
// The body in the .md file starts with `# <name>\n\n` then the Markdown
// content; strip a single leading newline if present so the reconstructed
// SKILL.md matches the legacy `skill(...)` output exactly.
const stripped = body.startsWith('\n') ? body.slice(1) : body;
const output = `---\nname: ${name}\ndescription: ${description}\n---\n\n${stripped.trim()}\n`;
const outPath = join(OUTPUT_DIR, id, 'SKILL.md');
mkdirSync(dirname(outPath), { recursive: true });
writeFileSync(outPath, output);
count += 1;
}
console.log(`wrote ${count} improved skill drafts`);