diff options
Diffstat (limited to 'scripts/add-about-prop.mjs')
| -rw-r--r-- | scripts/add-about-prop.mjs | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/scripts/add-about-prop.mjs b/scripts/add-about-prop.mjs new file mode 100644 index 0000000..e519863 --- /dev/null +++ b/scripts/add-about-prop.mjs @@ -0,0 +1,107 @@ +import { readFileSync, writeFileSync } from "node:fs"; +import { readdir } from "node:fs/promises"; +import { join, extname, relative } from "node:path"; + +const DOCS_DIR = join(import.meta.dirname, "..", "src", "content", "docs"); + +/** + * Recursively collect all .mdx files. + */ +async function collectMdxFiles(dir) { + const entries = await readdir(dir, { withFileTypes: true }); + const files = []; + + for (const entry of entries) { + if (entry.name.startsWith("_")) continue; + const fullPath = join(dir, entry.name); + if (entry.isDirectory()) { + const subFiles = await collectMdxFiles(fullPath); + files.push(...subFiles); + } else if (extname(entry.name) === ".mdx") { + files.push(fullPath); + } + } + + return files; +} + +/** + * Extract tags from frontmatter. + */ +function extractTags(content) { + const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); + if (!match) return []; + const fm = match[1]; + + // Match YAML-style tags array: tags:\n - tag1\n - tag2 + const tagSection = fm.match(/^tags:\s*\n((?:\s+-\s+.+\n?)*)/m); + if (!tagSection) return []; + + const tagLines = tagSection[1].match(/^\s+-\s+(.+)$/gm); + if (!tagLines) return []; + + return tagLines.map((line) => line.replace(/^\s+-\s+/, "").trim()); +} + +/** + * Infer `about` from tags. + * Uses the first tag that is not "一般質問". + */ +function inferAbout(tags) { + for (const tag of tags) { + if (tag !== "一般質問") return tag; + } + return null; +} + +async function main() { + const files = await collectMdxFiles(DOCS_DIR); + + let updated = 0; + let skipped = 0; + + for (const file of files) { + const content = readFileSync(file, "utf-8"); + + // Only process files that use QuestionSummary + if (!content.includes("<QuestionSummary")) continue; + + // Skip files that already have about= + if (content.includes("about=")) { + skipped++; + continue; + } + + const tags = extractTags(content); + const about = inferAbout(tags); + + if (!about) { + console.log(` SKIP (no topic tag): ${relative(DOCS_DIR, file)}`); + skipped++; + continue; + } + + // Insert about prop after headline prop + const newContent = content.replace( + /(headline=.*\n)(\s+datePublished=)/, + `$1 about="${about}"\n$2`, + ); + + if (newContent === content) { + console.log(` SKIP (pattern not matched): ${relative(DOCS_DIR, file)}`); + skipped++; + continue; + } + + writeFileSync(file, newContent, "utf-8"); + console.log(` about="${about}" → ${relative(DOCS_DIR, file)}`); + updated++; + } + + console.log(`\nDone: ${updated} updated, ${skipped} skipped.`); +} + +main().catch((err) => { + console.error("Error:", err); + process.exit(1); +}); |
