Files
tested/scripts/publish-articles.mjs
joshuaandClaude Opus 5.5 54ae9c49a1 Tested: static Astro site answering hard Bible questions
Built from the kit specs (CLAUDE.md, docs/01-05): question index import,
status seals, connections graph, Pagefind search, Scripture margin,
and 157 evidence articles (drafts unless published) with sources and
verified "Learn more" links. Includes link, owner-notes, a11y and
publish scripts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:46:19 +02:00

63 lines
2.3 KiB
JavaScript

#!/usr/bin/env node
// Publishes reviewed articles by removing their `draft: true` line, or puts them back as drafts.
//
// npm run publish -- 7.9 1.1 3B.10 publish these questions' articles
// npm run publish -- --all publish every article
// npm run publish -- --draft 7.9 mark an article as a draft again (also works with --all)
// npm run publish -- --list show which articles are drafts and which are published
import { readFileSync, writeFileSync, readdirSync } from "node:fs";
const dir = "src/content/articles";
const args = process.argv.slice(2);
const toDraft = args.includes("--draft");
const all = args.includes("--all");
const ids = args.filter((a) => !a.startsWith("--"));
const files = readdirSync(dir).filter((f) => f.endsWith(".mdx"));
const questionOf = (text) => text.match(/^question:\s*"([^"]+)"/m)?.[1];
const isDraft = (text) => /^draft:\s*true\s*$/m.test(text);
if (args.includes("--list")) {
const rows = files.map((f) => {
const text = readFileSync(`${dir}/${f}`, "utf8");
return { id: questionOf(text) ?? f, draft: isDraft(text) };
});
const drafts = rows.filter((r) => r.draft).map((r) => r.id);
const published = rows.filter((r) => !r.draft).map((r) => r.id);
console.log(`Published (${published.length}): ${published.join(", ") || "none"}`);
console.log(`Drafts (${drafts.length}): ${drafts.join(", ") || "none"}`);
process.exit(0);
}
if (!all && ids.length === 0) {
console.error("Name question ids (e.g. 7.9 3B.10), or pass --all. Add --draft to unpublish.");
process.exit(1);
}
const wanted = new Set(ids.map((id) => id.toUpperCase()));
let changed = 0;
const missing = new Set(wanted);
for (const f of files) {
const path = `${dir}/${f}`;
const text = readFileSync(path, "utf8");
const id = questionOf(text);
if (!id || (!all && !wanted.has(id.toUpperCase()))) continue;
missing.delete(id.toUpperCase());
let next = text;
if (toDraft && !isDraft(text)) {
next = text.replace(/^(question:.*)$/m, "$1\ndraft: true");
} else if (!toDraft && isDraft(text)) {
next = text.replace(/^draft:\s*true\s*\r?\n/m, "");
}
if (next !== text) {
writeFileSync(path, next);
changed++;
}
}
if (missing.size) console.error(`No article found for: ${[...missing].join(", ")}`);
console.log(`${toDraft ? "Marked as draft" : "Published"}: ${changed} article(s).`);