/* 812-3 가져온 단가산출 차림 헬퍼 — 줄 쌓기 모델(common_util_line_stack.ts)을 그 자리에서 트랜스파일해 Node 로 돌림. * stdin = [{키, 문서, 파이썬 [{제목, 가나다?, 줄 [{꼴, i | 기호 | 글}]}]}] * stdout = [{키, 같음(문서 → 줄 → 문서 · 칸 차례 무시), 거울(TS stackOf = 파이썬 stack_of), 항목 · 제목 · 공식 · 글 · 쌓기}] * 짝 = test_812_3_native_layout.py · 파이썬 거울 = M02_Doc_NativeLayout.py */ 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 ls = load(path.join(__dirname, "..", "..", "common_util", "common_util_line_stack.ts")); function canon(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 same = (a, b) => JSON.stringify(canon(a)) === JSON.stringify(canon(b)); const input = JSON.parse(fs.readFileSync(0, "utf8")); const out = input.map(({ 키, 문서, 파이썬 }) => { const items = ls.stackOf(문서); const back = ls.docOf(문서, items); const lines = items.flatMap((it) => it.줄); return { 키, 같음: same(back, 문서), 거울: same(items, 파이썬), 항목: items.length, 제목: items.filter((it) => it.제목.trim()).length, 공식: lines.filter((l) => l.꼴 === "공식" && l.기호.length).length, 글: lines.filter((l) => l.꼴 === "글").length, 쌓기: "쌓기" in 문서, ...(same(items, 파이썬) ? {} : { ts: items }), }; }); process.stdout.write(JSON.stringify(out));