aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/add-about-prop.mjs
blob: e519863252d606d934f17a77166de675759d46d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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);
});