/* 810-3 화면 셈 거울 헬퍼 — 가져온 식 문서를 화면과 같은 길(importView → calcDoc)로 셈 + 줄 쌓기 옵션 칸 꼴. * stdin = {문서들: {키: 문서}, 대상: [키], 기록: {열쇠: {값 | 빈 | 끊김}}, 기준: "엑셀" | "우리"} * stdout = {답: {키: calcDoc 답}, 꼴: {키: {옵션: [기호], 숨김: [기호], 공식: [기호]}}} * 짝 = test_810_3_native_screen.py · 기록 열쇠 = helper_802_1_formula_doc.cjs 와 같음. */ 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 calc = load(path.join(root, "common_util_formula_doc_calc.ts")); const imp = load(path.join(root, "common_util_formula_doc_import.ts")); const stack = load(path.join(root, "common_util_line_stack.ts")); const { varId } = load(path.join(root, "common_util_formula_doc.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 input = JSON.parse(fs.readFileSync(0, "utf8")); const record = input.기록 || {}; function answer(kind, p) { const k = `${kind}|${JSON.stringify(canon(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 docs = input.문서들 || {}; const links = { element: (p) => answer("요소", p), table: (p) => answer("표", p), doc: (key) => (docs[key] ? imp.importView(docs[key], input.기준 || "엑셀") : null), }; const out = { 답: {}, 꼴: {} }; for (const key of input.대상 || []) { const doc = docs[key]; out.답[key] = calc.calcDoc(imp.importView(doc, input.기준 || "엑셀"), links); const hidden = stack.hiddenOf(doc); out.꼴[key] = { 옵션: (doc.변수 || []).filter((v) => stack.sourceOf(doc, v)).map(varId), 숨김: [...hidden], 공식: stack.stackOf(doc).flatMap((it) => it.줄.flatMap((l) => (l.꼴 === "공식" ? l.기호 : []))), }; } process.stdout.write(JSON.stringify(out));