import fs from "fs/promises"; import path from "path"; const DOCS_ROOT = path.join(process.cwd(), "content", "zhouyi", "docs"); const OTHER_ROOT = path.join(DOCS_ROOT, "other"); export type LearnVariant = "traditional" | "simplified"; function getVariantRoot(variant: LearnVariant): string { return variant === "traditional" ? DOCS_ROOT : OTHER_ROOT; } export async function listGuaMarks( variant: LearnVariant = "traditional", ): Promise { const dir = getVariantRoot(variant); const entries = await fs.readdir(dir, { withFileTypes: true }); return entries .filter((entry) => entry.isDirectory() && /^\d{2}\./.test(entry.name)) .map((entry) => entry.name) .sort(); } export async function readGuaMarkdown(guaMark: string): Promise { const filePath = path.join(DOCS_ROOT, guaMark, "index.md"); return fs.readFile(filePath, "utf-8"); } export async function readLearnMarkdown( guaMark: string, variant: LearnVariant = "traditional", ): Promise { const root = getVariantRoot(variant); const filePath = guaMark === "index" ? path.join(root, "index.md") : path.join(root, guaMark, "index.md"); return fs.readFile(filePath, "utf-8"); } export function stripFrontmatter(content: string): string { if (!content.startsWith("---")) { return content; } const end = content.indexOf("---", 3); if (end === -1) { return content; } return content.slice(end + 3).trimStart(); } export function extractZhangMingRen(guaDetail: string): string | undefined { return guaDetail .match(/(\*\*台灣張銘仁[\s\S]*?)(?=周易第\d+卦)/)?.[1] ?.replaceAll("\n\n", "\n"); } export function extractChangeDetails( guaDetail: string, guaChange: string, guaTitle: string, ): string[] { const changeList: string[] = []; if (guaChange === "无变爻") { return changeList; } guaChange .split(":")[1] .trim() .split(",") .forEach((change) => { const detail = guaDetail .match(`(\\*\\*${change}變卦[\\s\\S]*?)(?=${guaTitle}|$)`)?.[1] ?.replaceAll("\n\n", "\n"); if (detail) { changeList.push(detail.trim()); } }); return changeList; } export function getGuaNumber(guaMark: string): number { return parseInt(guaMark.split(".")[0], 10); } export function getGuaName(guaMark: string): string { return guaMark.split(".").slice(1).join("."); }