From 6fa8872f6b4be562d62f992a4ba85a1ed75136af Mon Sep 17 00:00:00 2001 From: Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> Date: Sun, 21 Jun 2026 19:41:03 +0900 Subject: QuestionSummary に about プロパティを追加し @graph 構造に変更 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JSON-LD を WebPage + FAQPage の @graph 構造に変更し、 WebPage.about で質問の主題を明示するようにした。 - about は frontmatter の tags から推測(初回の非「一般質問」タグ) - 64ページすべてに about を追加済み - AGENTS.md の使用例も更新 --- scripts/add-about-prop.mjs | 107 +++++++++++++++++++++ src/components/QuestionSummary.astro | 45 ++++++--- .../ippan-situmon/r1d/3gatu/1-dyslexia-kankyo.mdx | 1 + .../r1d/3gatu/2-jinkou-suikei-kagaku.mdx | 1 + .../r1d/6gatu/1-touhyouritu-koujou.mdx | 1 + .../r1d/6gatu/2-homepage-siminsanka.mdx | 1 + .../r2d/3gatu/2-senkyo-yokusuru-again.mdx | 1 + .../r3d/12gatu/1-tokyo-vaction-kenpou-ihan.mdx | 1 + .../r3d/12gatu/2-manabu-kikai-sonsitu.mdx | 1 + .../r3d/12gatu/3-kokyo-toire-kyouryokuten.mdx | 1 + .../r3d/3gatu/1-mizukara-rissuru-sikumi.mdx | 1 + .../r3d/3gatu/2-ijime-taiou-minaosi.mdx | 1 + .../3gatu/3-hoiku-youchien-mask-kyosei-sinai.mdx | 1 + .../r3d/9gatu/1-cashless-point-gamble.mdx | 1 + .../r3d/9gatu/3-vaccine-sabetu-jinkensingai.mdx | 1 + .../r4d/12gatu/1-simin-machizukuri-jourei.mdx | 1 + .../r4d/12gatu/2-stop-cashless-jirihin.mdx | 1 + .../r4d/3gatu/1-ijime-judai-daisansya.mdx | 1 + .../r4d/3gatu/2-ijime-judai-chousa.mdx | 1 + .../r4d/3gatu/3-kyouin-ijime-taibatu.mdx | 1 + .../r4d/3gatu/4-jouhou-koukai-fufuku-sinsa.mdx | 1 + .../r4d/6gatu/1-judai-jitai-kodomo-chusin.mdx | 1 + .../r4d/6gatu/2-hontouno-kyouikuwo.mdx | 1 + .../r4d/9gatu/2-tokyo-saresio-kaihatu.mdx | 1 + .../r4d/9gatu/4-daisy-ikkatu-fukudokuhon.mdx | 1 + .../9gatu/5-guideline-syusei-mokusyoku-owari.mdx | 1 + .../2-ijime-judai-jitai-chousa-sosiki-kousei.mdx | 1 + .../12gatu/3-ijime-siryou-tukuranai-arienai.mdx | 1 + .../r5d/12gatu/5-gyakutai-keisi-sityou.mdx | 1 + .../3gatu/1-gyakutai-tuuhou-amakumiru-kodaira.mdx | 1 + .../2-kodaira-dake-ijou-ijime-judai-jitai.mdx | 1 + ...3-ijime-judai-jitai-tyousa-houkokusyo-keisi.mdx | 1 + .../r5d/3gatu/4-simin-uttae-koukateki-kaiketu.mdx | 1 + .../r5d/6gatu/1-ijime-judai-tenken-hyouka.mdx | 1 + .../r5d/6gatu/2-kodaira-kyusekki-kyoten.mdx | 1 + .../r5d/6gatu/3-dokusyo-public-comment-more.mdx | 1 + .../2-kyouikuiinkai-tenken-hyouka-nannotame.mdx | 1 + .../r5d/9gatu/3-jouhou-koukai-samatageruna.mdx | 1 + .../4-gyousei-fufuku-sinsakai-rieki-souhan.mdx | 1 + ...jime-yosan-kyohi-sityou-kyouikuchou-sekinin.mdx | 1 + .../2-kyouiku-iinkai-husei-taiou-zijyou-kinou.mdx | 1 + .../r6d/3gatu/1-tokiwakai-syougaisya-gyakutai.mdx | 1 + .../3gatu/2-ijime-taisaku-iinkai-kinou-huzen.mdx | 1 + .../r6d/3gatu/3-kaitei-ijime-bousi-kihonhousin.mdx | 1 + .../4-kyouikutyou-kyogi-touben-harasumento.mdx | 1 + .../r6d/9gatu/1-gyakutaigosoku-hogosya-bunri.mdx | 1 + .../r6d/9gatu/2-ijime-yosan-yobo-sityou-syonin.mdx | 1 + .../r6d/9gatu/3-gyousei-huhuku-sinsakai.mdx | 1 + .../r7d/12gatu/2-ijime-judai-yosan.mdx | 1 + .../r7d/12gatu/3-nyusatsu-hutyou-zuii-keiyaku.mdx | 1 + .../r7d/3gatu/1-tokiwakai-gyakutaigosoku-wakai.mdx | 1 + .../r7d/3gatu/2-koubunsyo-kanri-syomondai.mdx | 1 + .../r7d/3gatu/3-syokusaikanri-jittai.mdx | 1 + ...okiwakai-syougaisya-gyakutai-taiou-futatabi.mdx | 1 + .../6gatu/2-takanodai-ekimae-koubunsyo-husei.mdx | 1 + .../r7d/6gatu/3-ijime-taisaku-yobihi-ihou.mdx | 1 + .../6gatu/4-kyouikuchou-kyogi-touben-chousa.mdx | 1 + .../r7d/9gatu/1-koubunsyo-husei-futatabi.mdx | 1 + .../r7d/9gatu/2-ijime-taisaku-yobihi-futatabi.mdx | 1 + 59 files changed, 194 insertions(+), 15 deletions(-) create mode 100644 scripts/add-about-prop.mjs 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(" { + console.error("Error:", err); + process.exit(1); +}); diff --git a/src/components/QuestionSummary.astro b/src/components/QuestionSummary.astro index 96ec6f8..9b70955 100644 --- a/src/components/QuestionSummary.astro +++ b/src/components/QuestionSummary.astro @@ -12,6 +12,7 @@ * * 0 && (