fff77dac3f
Add liuyao/bazi/combined flows with shared calc and AI infrastructure, 64-gua learn routes, and update Ubuntu PM2 deployment docs for port 3130. Co-authored-by: Cursor <cursoragent@cursor.com>
91 lines
2.4 KiB
TypeScript
91 lines
2.4 KiB
TypeScript
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<string[]> {
|
|
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<string> {
|
|
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<string> {
|
|
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(".");
|
|
}
|