/* 802-1 수식 문서 거울 헬퍼 — common_util_formula_doc*.ts 를 그 자리에서 트랜스파일해 Node 로 돌림. * stdin = {문서들: {키: 문서}, 대상: [키], 기록: {열쇠: {값 | 빈 | 끊김}}, 글: [식 글], 표: [{표, 조건, 칸}]} * stdout = {답: {키: calcDoc 답}, 글: [textOf 또는 {틀림}], 표: [tableValue 값 또는 {빈 | 끊김}]} * 기록 열쇠 = 갈래 + "|" + 값 글(파이썬 `_canon` 과 같은 꼴). */ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const cache = new Map(); function load(at) { if (cache.has(at)) return cache.get(at); const js = ts.transpileModule(fs.readFileSync(at, "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; cache.set(at, box.exports); const need = (p) => p.startsWith(".") ? load(path.resolve(path.dirname(at), `${p}.ts`)) : require(p); new Function("exports", "module", "require", js)(box.exports, box, need); return box.exports; } const root = path.join(__dirname, "..", "..", "common_util"); const doc = load(path.join(root, "common_util_formula_doc.ts")); const calc = load(path.join(root, "common_util_formula_doc_calc.ts")); const table = load(path.join(root, "common_util_formula_doc_table.ts")); function canon(v) { if (typeof v === "number") return calc.plainText(v); if (Array.isArray(v)) return v.map(canon); if (v && typeof v === "object") { const out = {}; for (const k of Object.keys(v).sort()) out[k] = canon(v[k]); return out; } return v; } const keyOf = (kind, p) => `${kind}|${JSON.stringify(canon(p))}`; const input = JSON.parse(fs.readFileSync(0, "utf8")); const record = input.기록 || {}; function answer(kind, p) { const k = keyOf(kind, p); if (!(k in record)) throw new calc.Broken(`기록 없음 ${k}`); const got = record[k]; if ("빈" in got) throw new calc.Gap(got.빈); if ("끊김" in got) throw new calc.Broken(got.끊김); return got.값; } const links = { element: (p) => answer("요소", p), table: (p) => answer("표", p), doc: (key) => (input.문서들 || {})[key] || null, }; const out = { 답: {}, 글: [], 표: [] }; for (const key of input.대상 || []) out.답[key] = calc.calcDoc(input.문서들[key], links); for (const text of input.글 || []) { try { out.글.push(doc.textOf(doc.parse(text))); } catch (e) { if (!(e instanceof doc.DocError)) throw e; out.글.push({ 틀림: true }); } } for (const one of input.표 || []) { try { out.표.push({ 값: table.tableValue(one.표, { 조건: one.조건, 칸: one.칸 }) }); } catch (e) { if (e instanceof calc.Gap) out.표.push({ 빈: true }); else if (e instanceof calc.Broken) out.표.push({ 끊김: true }); else throw e; } } process.stdout.write(JSON.stringify(out));