kordoc 3.4.1 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +6 -0
  2. package/dist/{-YOQGQ22S.js → -GKNSTVEZ.js} +7 -3
  3. package/dist/{chunk-W7JHJQ2O.cjs → chunk-4JLD2IT7.cjs} +2 -2
  4. package/dist/{chunk-W7JHJQ2O.cjs.map → chunk-4JLD2IT7.cjs.map} +1 -1
  5. package/dist/{chunk-FPFB7AFX.js → chunk-A4LSWJEC.js} +2 -2
  6. package/dist/{chunk-SE3KEL4G.js → chunk-AHDNELBR.js} +2 -2
  7. package/dist/{chunk-CGHPBI3X.js → chunk-GTCJQANY.js} +165 -9
  8. package/dist/chunk-GTCJQANY.js.map +1 -0
  9. package/dist/cli.js +6 -23
  10. package/dist/cli.js.map +1 -1
  11. package/dist/index.cjs +302 -146
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +9 -3
  14. package/dist/index.d.ts +9 -3
  15. package/dist/index.js +164 -8
  16. package/dist/index.js.map +1 -1
  17. package/dist/mcp.js +39 -3
  18. package/dist/mcp.js.map +1 -1
  19. package/dist/{parser-JAZCZJI6.cjs → parser-25ISHR7Q.cjs} +14 -14
  20. package/dist/{parser-JAZCZJI6.cjs.map → parser-25ISHR7Q.cjs.map} +1 -1
  21. package/dist/{parser-5HDZZWDH.js → parser-LBLPN3KY.js} +2 -2
  22. package/dist/{parser-ET64VEEX.js → parser-LMBDB7RM.js} +2 -2
  23. package/dist/{watch-56GNC2YN.js → watch-77CYT54V.js} +3 -3
  24. package/package.json +1 -1
  25. package/dist/chunk-CGHPBI3X.js.map +0 -1
  26. /package/dist/{-YOQGQ22S.js.map → -GKNSTVEZ.js.map} +0 -0
  27. /package/dist/{chunk-FPFB7AFX.js.map → chunk-A4LSWJEC.js.map} +0 -0
  28. /package/dist/{chunk-SE3KEL4G.js.map → chunk-AHDNELBR.js.map} +0 -0
  29. /package/dist/{parser-5HDZZWDH.js.map → parser-LBLPN3KY.js.map} +0 -0
  30. /package/dist/{parser-ET64VEEX.js.map → parser-LMBDB7RM.js.map} +0 -0
  31. /package/dist/{watch-56GNC2YN.js.map → watch-77CYT54V.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ PRESET_ALIAS,
3
4
  extractFormFields,
4
5
  fillFormFields,
5
6
  fillHwpx,
6
7
  markdownToHwpx,
7
8
  parse
8
- } from "./chunk-CGHPBI3X.js";
9
+ } from "./chunk-GTCJQANY.js";
9
10
  import {
10
11
  detectFormat,
11
12
  detectZipFormat
@@ -15,7 +16,7 @@ import {
15
16
  blocksToMarkdown,
16
17
  sanitizeError,
17
18
  toArrayBuffer
18
- } from "./chunk-FPFB7AFX.js";
19
+ } from "./chunk-A4LSWJEC.js";
19
20
  import "./chunk-3TBUDJDE.js";
20
21
 
21
22
  // src/cli.ts
@@ -114,7 +115,7 @@ program.name("kordoc").description("\uBAA8\uB450 \uD30C\uC2F1\uD574\uBC84\uB9AC\
114
115
  }
115
116
  });
116
117
  program.command("watch <dir>").description("\uB514\uB809\uD1A0\uB9AC \uAC10\uC2DC \u2014 \uC0C8 \uBB38\uC11C \uC790\uB3D9 \uBCC0\uD658").option("--webhook <url>", "\uACB0\uACFC \uC804\uC1A1 \uC6F9\uD6C5 URL").option("-d, --out-dir <dir>", "\uBCC0\uD658 \uACB0\uACFC \uCD9C\uB825 \uB514\uB809\uD1A0\uB9AC").option("-p, --pages <range>", "\uD398\uC774\uC9C0/\uC139\uC158 \uBC94\uC704").option("--format <type>", "\uCD9C\uB825 \uD615\uC2DD: markdown \uB610\uB294 json", "markdown").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (dir, opts) => {
117
- const { watchDirectory } = await import("./watch-56GNC2YN.js");
118
+ const { watchDirectory } = await import("./watch-77CYT54V.js");
118
119
  await watchDirectory({
119
120
  dir,
120
121
  outDir: opts.outDir,
@@ -265,7 +266,7 @@ program.command("fill <template>").description("\uC11C\uC2DD \uBB38\uC11C\uC758
265
266
  });
266
267
  program.command("patch <original> <edited>").description("\uC11C\uC2DD \uBCF4\uC874 \uB77C\uC6B4\uB4DC\uD2B8\uB9BD \uD328\uCE58 \u2014 \uD3B8\uC9D1\uB41C \uB9C8\uD06C\uB2E4\uC6B4\uC744 \uC6D0\uBCF8 HWPX/HWP\uC5D0 in-place \uBC18\uC601 (kordoc patch \uC6D0\uBCF8.hwpx \uD3B8\uC9D1.md -o \uCD9C\uB825.hwpx)").option("-o, --output <path>", "\uCD9C\uB825 \uACBD\uB85C (\uAE30\uBCF8: <\uC6D0\uBCF8>.patched.hwpx|.hwp)").option("--no-verify", "\uD328\uCE58 \uD6C4 \uC7AC\uD30C\uC2F1 \uC790\uB3D9 \uAC80\uC99D \uC0DD\uB7B5").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (original, edited, opts) => {
267
268
  try {
268
- const { patchHwpx, patchHwp, detectFormat: detectFormat2 } = await import("./-YOQGQ22S.js");
269
+ const { patchHwpx, patchHwp, detectFormat: detectFormat2 } = await import("./-GKNSTVEZ.js");
269
270
  const rootOpts = program.opts();
270
271
  const output = opts.output ?? rootOpts.output;
271
272
  const silent = opts.silent ?? rootOpts.silent;
@@ -304,24 +305,6 @@ program.command("patch <original> <edited>").description("\uC11C\uC2DD \uBCF4\uC
304
305
  process.exit(1);
305
306
  }
306
307
  });
307
- var GONGMUN_PRESET_ALIAS = {
308
- official: "official",
309
- \uAE30\uC548\uBB38: "official",
310
- \uC2DC\uD589\uBB38: "official",
311
- \uACF5\uBB38: "official",
312
- \uACF5\uBB38\uC11C: "official",
313
- report: "report",
314
- \uBCF4\uACE0\uC11C: "report",
315
- plan: "plan",
316
- \uACC4\uD68D\uC11C: "plan",
317
- \uACC4\uD68D: "plan",
318
- notice: "notice",
319
- \uD1B5\uC9C0: "notice",
320
- \uC54C\uB9BC: "notice",
321
- \uC548\uB0B4: "notice",
322
- minutes: "minutes",
323
- \uD68C\uC758\uB85D: "minutes"
324
- };
325
308
  program.command("generate <markdown>").alias("gen").description("\uB9C8\uD06C\uB2E4\uC6B4 \u2192 \uACF5\uBB38\uC11C HWPX \uC0DD\uC131 \u2014 kordoc generate \uBCF4\uACE0\uC11C.md -o \uBCF4\uACE0\uC11C.hwpx --preset \uBCF4\uACE0\uC11C (markdown\uC5D0 '-' \uC9C0\uC815 \uC2DC stdin)").option("-o, --output <path>", "\uCD9C\uB825 HWPX \uACBD\uB85C (\uAE30\uBCF8: <\uC785\uB825>.hwpx)").option("--preset <name>", "\uACF5\uBB38\uC11C \uD504\uB9AC\uC14B: \uAE30\uC548\uBB38(official)\xB7\uBCF4\uACE0\uC11C(report)\xB7\uACC4\uD68D\uC11C(plan)\xB7\uD1B5\uC9C0(notice)\xB7\uD68C\uC758\uB85D(minutes)", "\uAE30\uC548\uBB38").option("--font <type>", "\uBCF8\uBB38 \uAE00\uAF34: myeongjo(\uD568\uCD08\uB86C\uBC14\uD0D5) \uB610\uB294 gothic(\uB9D1\uC740 \uACE0\uB515)").option("--pt <size>", "\uBCF8\uBB38 \uAE00\uC790 \uD06C\uAE30(pt)").option("--line-spacing <percent>", "\uBCF8\uBB38 \uC904\uAC04\uACA9(%)").option("--plain", "\uACF5\uBB38\uC11C \uBAA8\uB4DC \uB044\uAE30 (\uBC94\uC6A9 \uB9C8\uD06C\uB2E4\uC6B4 \uBCC0\uD658)").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (markdown, opts) => {
326
309
  try {
327
310
  const rootOpts = program.opts();
@@ -338,7 +321,7 @@ program.command("generate <markdown>").alias("gen").description("\uB9C8\uD06C\uB
338
321
  }
339
322
  let gongmun;
340
323
  if (!opts.plain) {
341
- const preset = GONGMUN_PRESET_ALIAS[String(opts.preset).trim()];
324
+ const preset = PRESET_ALIAS[String(opts.preset).trim()];
342
325
  if (!preset) {
343
326
  process.stderr.write(`[kordoc] \uC54C \uC218 \uC5C6\uB294 \uD504\uB9AC\uC14B: ${opts.preset} (\uAE30\uC548\uBB38/\uBCF4\uACE0\uC11C/\uACC4\uD68D\uC11C/\uD1B5\uC9C0/\uD68C\uC758\uB85D)
344
327
  `);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["/** kordoc CLI — 모두 파싱해버리겠다 */\r\n\r\nimport { readFileSync, writeFileSync, mkdirSync, statSync } from \"fs\"\r\nimport { basename, dirname, resolve, extname } from \"path\"\r\nimport { Command } from \"commander\"\r\nimport { parse, detectFormat, detectZipFormat, fillFormFields, extractFormFields, blocksToMarkdown, markdownToHwpx, fillHwpx } from \"./index.js\"\r\nimport type { ParseOptions } from \"./types.js\"\r\nimport { VERSION, toArrayBuffer, sanitizeError } from \"./utils.js\"\r\n\r\nconst program = new Command()\r\n\r\nprogram\r\n .name(\"kordoc\")\r\n .description(\"모두 파싱해버리겠다 — HWP, HWPX, PDF, XLSX, DOCX → Markdown\")\r\n .version(VERSION)\r\n .argument(\"<files...>\", \"변환할 파일 경로 (HWP, HWPX, PDF, XLSX, DOCX)\")\r\n .option(\"-o, --output <path>\", \"출력 파일 경로 (단일 파일 시)\")\r\n .option(\"-d, --out-dir <dir>\", \"출력 디렉토리 (다중 파일 시)\")\r\n .option(\"-p, --pages <range>\", \"페이지/섹션 범위 (예: 1-3, 1,3,5)\")\r\n .option(\"--format <type>\", \"출력 형식: markdown (기본) 또는 json\", \"markdown\")\r\n .option(\"--no-header-footer\", \"PDF 머리글/바닥글 자동 제거\")\r\n .option(\"--formula-ocr\", \"PDF 수식 OCR 활성화 (MFD+MFR ONNX, 첫 사용 시 모델 ~155MB 자동 다운로드)\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (files: string[], opts) => {\r\n const validFormats = [\"markdown\", \"json\"]\r\n if (!validFormats.includes(opts.format)) {\r\n process.stderr.write(`[kordoc] 지원하지 않는 형식: ${opts.format} (markdown 또는 json)\\n`)\r\n process.exit(1)\r\n }\r\n for (let fi = 0; fi < files.length; fi++) {\r\n const filePath = files[fi]\r\n const absPath = resolve(filePath)\r\n const fileName = basename(absPath)\r\n const filePrefix = files.length > 1 ? `[${fi + 1}/${files.length}] ` : \"\"\r\n\r\n try {\r\n const fileSize = statSync(absPath).size\r\n if (fileSize > 500 * 1024 * 1024) {\r\n process.stderr.write(`\\n[kordoc] SKIP: ${fileName} — 파일이 너무 큽니다 (${(fileSize / 1024 / 1024).toFixed(1)}MB)\\n`)\r\n process.exitCode = 1\r\n continue\r\n }\r\n const buffer = readFileSync(absPath)\r\n const arrayBuffer = toArrayBuffer(buffer)\r\n const format = detectFormat(arrayBuffer)\r\n\r\n if (!opts.silent) {\r\n process.stderr.write(`[kordoc] ${filePrefix}${fileName} (${format}) ...`)\r\n }\r\n\r\n const parseOptions: ParseOptions = { filePath: absPath }\r\n if (opts.pages) parseOptions.pages = opts.pages as string\r\n if (opts.headerFooter === false) parseOptions.removeHeaderFooter = false\r\n if (opts.formulaOcr) parseOptions.formulaOcr = true\r\n if (!opts.silent) {\r\n parseOptions.onProgress = (current: number, total: number) => {\r\n process.stderr.write(`\\r[kordoc] ${filePrefix}${fileName} (${format}) [${current}/${total}]`)\r\n }\r\n }\r\n const result = await parse(arrayBuffer, parseOptions)\r\n\r\n if (!result.success) {\r\n process.stderr.write(` FAIL\\n`)\r\n process.stderr.write(` → ${result.error}\\n`)\r\n process.exitCode = 1\r\n continue\r\n }\r\n\r\n if (!opts.silent) process.stderr.write(` OK\\n`)\r\n\r\n let markdown = result.markdown\r\n // --out-dir 시 이미지 참조 경로에 images/ 접두사 추가\r\n if (opts.outDir && result.images?.length) {\r\n markdown = markdown.replace(/!\\[image\\]\\(image_/g, \"![image](images/image_\")\r\n }\r\n const output = opts.format === \"json\"\r\n ? JSON.stringify(result, (_key, value) =>\r\n value instanceof Uint8Array ? Buffer.from(value).toString(\"base64\") : value\r\n , 2)\r\n : markdown\r\n\r\n // 이미지 저장 (--out-dir 또는 --output 시)\r\n const saveImages = (dir: string) => {\r\n if (!result.images?.length) return\r\n const imgDir = resolve(dir, \"images\")\r\n mkdirSync(imgDir, { recursive: true })\r\n for (const img of result.images) {\r\n writeFileSync(resolve(imgDir, img.filename), img.data)\r\n }\r\n if (!opts.silent) process.stderr.write(` → ${result.images.length}개 이미지 → ${imgDir}\\n`)\r\n }\r\n\r\n if (opts.output && files.length === 1) {\r\n writeFileSync(opts.output, output, \"utf-8\")\r\n if (!opts.silent) process.stderr.write(` → ${opts.output}\\n`)\r\n saveImages(resolve(opts.output, \"..\"))\r\n } else if (opts.outDir) {\r\n mkdirSync(opts.outDir, { recursive: true })\r\n const outExt = opts.format === \"json\" ? \".json\" : \".md\"\r\n const outPath = resolve(opts.outDir, fileName.replace(/\\.[^.]+$/, outExt))\r\n writeFileSync(outPath, output, \"utf-8\")\r\n if (!opts.silent) process.stderr.write(` → ${outPath}\\n`)\r\n saveImages(opts.outDir)\r\n } else {\r\n process.stdout.write(output + \"\\n\")\r\n }\r\n } catch (err) {\r\n process.stderr.write(`\\n[kordoc] ERROR: ${fileName} — ${sanitizeError(err)}\\n`)\r\n process.exitCode = 1\r\n }\r\n }\r\n })\r\n\r\nprogram\r\n .command(\"watch <dir>\")\r\n .description(\"디렉토리 감시 — 새 문서 자동 변환\")\r\n .option(\"--webhook <url>\", \"결과 전송 웹훅 URL\")\r\n .option(\"-d, --out-dir <dir>\", \"변환 결과 출력 디렉토리\")\r\n .option(\"-p, --pages <range>\", \"페이지/섹션 범위\")\r\n .option(\"--format <type>\", \"출력 형식: markdown 또는 json\", \"markdown\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (dir: string, opts) => {\r\n const { watchDirectory } = await import(\"./watch.js\")\r\n await watchDirectory({\r\n dir,\r\n outDir: opts.outDir,\r\n webhook: opts.webhook,\r\n format: opts.format,\r\n pages: opts.pages,\r\n silent: opts.silent,\r\n })\r\n })\r\n\r\nprogram\r\n .command(\"fill <template>\")\r\n .description(\"서식 문서의 빈칸을 채워서 출력 — kordoc fill 신청서.hwpx -f '성명=홍길동,전화=010-1234-5678' -o 결과.hwpx\")\r\n .option(\"-f, --fields <pairs>\", \"채울 필드 (key=value 쉼표 구분 또는 JSON)\")\r\n .option(\"-j, --json <path>\", \"채울 필드 JSON 파일 경로\")\r\n .option(\"-o, --output <path>\", \"출력 파일 경로 (확장자로 포맷 결정: .md, .hwpx)\")\r\n .option(\"--format <type>\", \"출력 포맷: hwpx-preserve (기본, 원본 스타일 보존), hwpx, markdown\", \"hwpx-preserve\")\r\n .option(\"--dry-run\", \"채우지 않고 서식 필드 목록만 출력\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (template: string, opts) => {\r\n try {\r\n const absPath = resolve(template)\r\n const fileSize = statSync(absPath).size\r\n if (fileSize > 500 * 1024 * 1024) {\r\n process.stderr.write(`[kordoc] 파일이 너무 큽니다 (${(fileSize / 1024 / 1024).toFixed(1)}MB)\\n`)\r\n process.exit(1)\r\n }\r\n\r\n const buffer = readFileSync(absPath)\r\n const arrayBuffer = toArrayBuffer(buffer)\r\n\r\n if (!opts.silent) process.stderr.write(`[kordoc] ${basename(absPath)} 파싱 중...\\n`)\r\n\r\n // --dry-run: 필드 목록만 출력\r\n if (opts.dryRun) {\r\n const result = await parse(arrayBuffer)\r\n if (!result.success) {\r\n process.stderr.write(`[kordoc] 파싱 실패: ${result.error}\\n`)\r\n process.exit(1)\r\n }\r\n const formInfo = extractFormFields(result.blocks)\r\n if (formInfo.fields.length === 0) {\r\n process.stderr.write(`[kordoc] 서식 필드를 찾을 수 없습니다.\\n`)\r\n process.exit(1)\r\n }\r\n process.stdout.write(JSON.stringify(formInfo, null, 2) + \"\\n\")\r\n return\r\n }\r\n\r\n // 필드 값 파싱\r\n let values: Record<string, string> = {}\r\n if (opts.json) {\r\n const jsonPath = resolve(opts.json)\r\n const jsonContent = readFileSync(jsonPath, \"utf-8\")\r\n values = JSON.parse(jsonContent)\r\n } else if (opts.fields) {\r\n const fieldsStr: string = opts.fields\r\n if (fieldsStr.startsWith(\"{\")) {\r\n values = JSON.parse(fieldsStr)\r\n } else {\r\n // \"key1=value1,key2=value2\" 파싱 — 값에 쉼표가 있을 수 있으므로\r\n // '=' 앞의 키를 기준으로 분리 (쉼표+한글/영문+= 패턴)\r\n const pairs = fieldsStr.split(/,(?=[가-힣A-Za-z][가-힣A-Za-z\\s]*=)/)\r\n for (const pair of pairs) {\r\n const eqIdx = pair.indexOf(\"=\")\r\n if (eqIdx > 0) {\r\n const key = pair.slice(0, eqIdx).trim()\r\n const val = pair.slice(eqIdx + 1).trim()\r\n values[key] = val\r\n }\r\n }\r\n }\r\n } else {\r\n process.stderr.write(`[kordoc] 채울 필드를 지정해주세요 (-f 또는 -j 옵션)\\n`)\r\n process.exit(1)\r\n }\r\n\r\n // 출력 포맷 결정\r\n let outputFormat = opts.format as string\r\n if (opts.output) {\r\n const ext = extname(opts.output).toLowerCase()\r\n if (ext === \".hwpx\") outputFormat = outputFormat === \"markdown\" ? \"hwpx-preserve\" : outputFormat\r\n else if (ext === \".md\") outputFormat = \"markdown\"\r\n }\r\n\r\n // ─── hwpx-preserve: 원본 ZIP 직접 수정 ───\r\n if (outputFormat === \"hwpx-preserve\") {\r\n const format = detectFormat(arrayBuffer)\r\n let isHwpx = format === \"hwpx\"\r\n if (isHwpx) {\r\n const zipFormat = await detectZipFormat(arrayBuffer)\r\n isHwpx = zipFormat === \"hwpx\"\r\n }\r\n if (!isHwpx) {\r\n if (!opts.silent) process.stderr.write(`[kordoc] HWPX가 아니므로 hwpx 모드로 전환합니다\\n`)\r\n outputFormat = \"hwpx\"\r\n } else {\r\n const hwpxResult = await fillHwpx(arrayBuffer, values)\r\n if (!opts.silent) {\r\n process.stderr.write(`[kordoc] ${hwpxResult.filled.length}개 필드 채움 (원본 스타일 보존)\\n`)\r\n if (hwpxResult.unmatched.length > 0) {\r\n process.stderr.write(`[kordoc] ⚠️ 매칭 실패: ${hwpxResult.unmatched.join(\", \")}\\n`)\r\n }\r\n }\r\n if (opts.output) {\r\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\r\n writeFileSync(resolve(opts.output), Buffer.from(hwpxResult.buffer))\r\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\r\n } else {\r\n process.stdout.write(Buffer.from(hwpxResult.buffer))\r\n }\r\n return\r\n }\r\n }\r\n\r\n // ─── 일반 경로: parse → fill → output ───\r\n const result = await parse(arrayBuffer)\r\n if (!result.success) {\r\n process.stderr.write(`[kordoc] 파싱 실패: ${result.error}\\n`)\r\n process.exit(1)\r\n }\r\n\r\n const formInfo = extractFormFields(result.blocks)\r\n if (!opts.silent) {\r\n process.stderr.write(`[kordoc] 서식 필드 ${formInfo.fields.length}개 감지 (확신도 ${(formInfo.confidence * 100).toFixed(0)}%)\\n`)\r\n }\r\n\r\n const fillResult = fillFormFields(result.blocks, values)\r\n if (!opts.silent) {\r\n process.stderr.write(`[kordoc] ${fillResult.filled.length}개 필드 채움\\n`)\r\n if (fillResult.unmatched.length > 0) {\r\n process.stderr.write(`[kordoc] ⚠️ 매칭 실패: ${fillResult.unmatched.join(\", \")}\\n`)\r\n }\r\n }\r\n\r\n const markdown = blocksToMarkdown(fillResult.blocks)\r\n\r\n if (outputFormat === \"hwpx\") {\r\n const hwpxBuffer = await markdownToHwpx(markdown)\r\n if (opts.output) {\r\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\r\n writeFileSync(resolve(opts.output), Buffer.from(hwpxBuffer))\r\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\r\n } else {\r\n process.stdout.write(Buffer.from(hwpxBuffer))\r\n }\r\n } else {\r\n if (opts.output) {\r\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\r\n writeFileSync(resolve(opts.output), markdown, \"utf-8\")\r\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\r\n } else {\r\n process.stdout.write(markdown + \"\\n\")\r\n }\r\n }\r\n } catch (err) {\r\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram\r\n .command(\"patch <original> <edited>\")\r\n .description(\"서식 보존 라운드트립 패치 — 편집된 마크다운을 원본 HWPX/HWP에 in-place 반영 (kordoc patch 원본.hwpx 편집.md -o 출력.hwpx)\")\r\n .option(\"-o, --output <path>\", \"출력 경로 (기본: <원본>.patched.hwpx|.hwp)\")\r\n .option(\"--no-verify\", \"패치 후 재파싱 자동 검증 생략\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (original: string, edited: string, opts) => {\r\n try {\r\n const { patchHwpx, patchHwp, detectFormat } = await import(\"./index.js\")\r\n // 루트 커맨드의 동명 옵션(-o/--silent)이 서브커맨드 옵션을 가로채는 commander 동작 보완\r\n const rootOpts = program.opts()\r\n const output: string | undefined = opts.output ?? rootOpts.output\r\n const silent: boolean = opts.silent ?? rootOpts.silent\r\n const originalBuf = new Uint8Array(readFileSync(resolve(original)))\r\n const editedMarkdown = readFileSync(resolve(edited), \"utf-8\")\r\n\r\n const format = detectFormat(originalBuf.buffer as ArrayBuffer)\r\n const result = format === \"hwp\"\r\n ? await patchHwp(originalBuf, editedMarkdown, { verify: opts.verify !== false })\r\n : await patchHwpx(originalBuf, editedMarkdown, { verify: opts.verify !== false })\r\n if (!result.success || !result.data) {\r\n process.stderr.write(`[kordoc] 패치 실패: ${result.error ?? \"알 수 없는 오류\"}\\n`)\r\n process.exit(1)\r\n }\r\n\r\n const ext = format === \"hwp\" ? \".hwp\" : \".hwpx\"\r\n const outPath = resolve(output ?? original.replace(/\\.hwpx?$/i, \"\") + \".patched\" + ext)\r\n mkdirSync(dirname(outPath), { recursive: true })\r\n writeFileSync(outPath, result.data)\r\n\r\n if (!silent) {\r\n process.stderr.write(`[kordoc] ${result.applied}개 변경 적용 (원본 서식 보존) → ${outPath}\\n`)\r\n for (const s of result.skipped) {\r\n process.stderr.write(`[kordoc] ⚠️ SKIP: ${s.reason}${s.before ? ` | ${s.before}` : \"\"}\\n`)\r\n }\r\n if (result.verification) {\r\n const v = result.verification.stats\r\n const residual = v.added + v.removed + v.modified\r\n process.stderr.write(residual === 0\r\n ? `[kordoc] ✓ 검증: 편집 마크다운과 재파싱 결과 완전 일치 (${v.unchanged}블록)\\n`\r\n : `[kordoc] ⚠️ 검증 잔차: 수정 ${v.modified}, 추가 ${v.added}, 삭제 ${v.removed} (미지원 변경은 skip 목록 참조)\\n`)\r\n }\r\n }\r\n if (result.skipped.length > 0) process.exitCode = 2\r\n } catch (err) {\r\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\n// 공문서 프리셋 별칭(한글/영문) → 내부 preset 키\r\nconst GONGMUN_PRESET_ALIAS: Record<string, \"official\" | \"report\" | \"plan\" | \"notice\" | \"minutes\"> = {\r\n official: \"official\", 기안문: \"official\", 시행문: \"official\", 공문: \"official\", 공문서: \"official\",\r\n report: \"report\", 보고서: \"report\",\r\n plan: \"plan\", 계획서: \"plan\", 계획: \"plan\",\r\n notice: \"notice\", 통지: \"notice\", 알림: \"notice\", 안내: \"notice\",\r\n minutes: \"minutes\", 회의록: \"minutes\",\r\n}\r\n\r\nprogram\r\n .command(\"generate <markdown>\")\r\n .alias(\"gen\")\r\n .description(\"마크다운 → 공문서 HWPX 생성 — kordoc generate 보고서.md -o 보고서.hwpx --preset 보고서 (markdown에 '-' 지정 시 stdin)\")\r\n .option(\"-o, --output <path>\", \"출력 HWPX 경로 (기본: <입력>.hwpx)\")\r\n .option(\"--preset <name>\", \"공문서 프리셋: 기안문(official)·보고서(report)·계획서(plan)·통지(notice)·회의록(minutes)\", \"기안문\")\r\n .option(\"--font <type>\", \"본문 글꼴: myeongjo(함초롬바탕) 또는 gothic(맑은 고딕)\")\r\n .option(\"--pt <size>\", \"본문 글자 크기(pt)\")\r\n .option(\"--line-spacing <percent>\", \"본문 줄간격(%)\")\r\n .option(\"--plain\", \"공문서 모드 끄기 (범용 마크다운 변환)\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (markdown: string, opts) => {\r\n try {\r\n const rootOpts = program.opts()\r\n const output: string | undefined = opts.output ?? rootOpts.output\r\n const silent: boolean = opts.silent ?? rootOpts.silent\r\n\r\n // 입력: '-' 이면 stdin, 아니면 파일\r\n let md: string\r\n let baseName = \"document\"\r\n if (markdown === \"-\") {\r\n md = readFileSync(0, \"utf-8\")\r\n } else {\r\n const inPath = resolve(markdown)\r\n md = readFileSync(inPath, \"utf-8\")\r\n baseName = basename(inPath).replace(/\\.(md|markdown|txt)$/i, \"\")\r\n }\r\n\r\n // 공문서 옵션 구성\r\n let gongmun: import(\"./index.js\").GongmunOptions | undefined\r\n if (!opts.plain) {\r\n const preset = GONGMUN_PRESET_ALIAS[String(opts.preset).trim()]\r\n if (!preset) {\r\n process.stderr.write(`[kordoc] 알 수 없는 프리셋: ${opts.preset} (기안문/보고서/계획서/통지/회의록)\\n`)\r\n process.exit(1)\r\n }\r\n gongmun = { preset }\r\n if (opts.font) {\r\n if (opts.font !== \"myeongjo\" && opts.font !== \"gothic\") {\r\n process.stderr.write(`[kordoc] --font 은 myeongjo 또는 gothic\\n`)\r\n process.exit(1)\r\n }\r\n gongmun.bodyFont = opts.font\r\n }\r\n if (opts.pt) gongmun.bodyPt = Number(opts.pt)\r\n if (opts.lineSpacing) gongmun.lineSpacing = Number(opts.lineSpacing)\r\n }\r\n\r\n const buf = await markdownToHwpx(md, gongmun ? { gongmun } : undefined)\r\n const outPath = resolve(output ?? (markdown === \"-\" ? `${baseName}.hwpx` : markdown.replace(/\\.(md|markdown|txt)$/i, \"\") + \".hwpx\"))\r\n mkdirSync(dirname(outPath), { recursive: true })\r\n writeFileSync(outPath, Buffer.from(buf))\r\n\r\n if (!silent) {\r\n const mode = gongmun ? `공문서:${gongmun.preset}` : \"범용\"\r\n process.stderr.write(`[kordoc] HWPX 생성 (${mode}) → ${outPath}\\n`)\r\n }\r\n } catch (err) {\r\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram\r\n .command(\"mcp\")\r\n .description(\"MCP 서버 실행 (Claude / Cursor / Windsurf 연동)\")\r\n .action(async () => {\r\n await import(\"./mcp.js\")\r\n })\r\n\r\nprogram\r\n .command(\"setup\")\r\n .description(\"대화형 설치 마법사 — AI 클라이언트 자동 등록 (Mac/Win/Linux)\")\r\n .action(async () => {\r\n const { runSetup } = await import(\"./setup.js\")\r\n await runSetup()\r\n })\r\n\r\nprogram\r\n .command(\"check-formula-models\")\r\n .description(\"PDF 수식 OCR 모델(MFD + MFR + tokenizer, ~155MB) 상태 확인 — 없거나 SHA 불일치면 다운로드\")\r\n .option(\"--status-only\", \"상태만 JSON 으로 출력 (다운로드 안 함)\")\r\n .action(async (opts) => {\r\n try {\r\n const { getFormulaModelStatus, ensureFormulaModels, getFormulaModelsDir } = await import(\r\n \"./pdf/formula/index.js\"\r\n )\r\n const dir = getFormulaModelsDir()\r\n if (opts.statusOnly) {\r\n const status = await getFormulaModelStatus()\r\n process.stdout.write(\r\n JSON.stringify(\r\n {\r\n modelsDir: dir,\r\n allReady: status.every((s) => s.verified),\r\n models: status.map((s) => ({\r\n name: s.spec.name,\r\n filename: s.spec.filename,\r\n sizeMb: s.spec.sizeMb,\r\n exists: s.exists,\r\n verified: s.verified,\r\n invalidReason: s.invalidReason,\r\n path: s.localPath,\r\n })),\r\n },\r\n null,\r\n 2,\r\n ) + \"\\n\",\r\n )\r\n return\r\n }\r\n process.stderr.write(`[kordoc-formula] 캐시 디렉토리: ${dir}\\n`)\r\n await ensureFormulaModels((p) => {\r\n if (p.phase === \"download\" && p.total) {\r\n const pct = Math.floor((p.downloaded / p.total) * 100)\r\n process.stderr.write(\r\n `\\r[kordoc-formula] ${p.spec.name} ${pct}% (${(p.downloaded / 1024 / 1024).toFixed(1)}/${(p.total / 1024 / 1024).toFixed(1)}MB)`,\r\n )\r\n if (p.downloaded >= p.total) process.stderr.write(\"\\n\")\r\n } else if (p.phase === \"verify\") {\r\n process.stderr.write(`[kordoc-formula] ${p.spec.name} SHA-256 검증 중...\\n`)\r\n } else if (p.phase === \"done\") {\r\n process.stderr.write(`[kordoc-formula] ${p.spec.name} 준비 완료\\n`)\r\n } else if (p.phase === \"skip\") {\r\n process.stderr.write(`[kordoc-formula] ${p.spec.name} 이미 존재 (skip)\\n`)\r\n }\r\n })\r\n process.stdout.write(\"ok\\n\")\r\n } catch (err) {\r\n process.stderr.write(`[kordoc] 수식 모델 준비 실패: ${sanitizeError(err)}\\n`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram.parse()\r\n"],"mappings":"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","names":["result","formInfo","detectFormat"]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["/** kordoc CLI — 모두 파싱해버리겠다 */\r\n\r\nimport { readFileSync, writeFileSync, mkdirSync, statSync } from \"fs\"\r\nimport { basename, dirname, resolve, extname } from \"path\"\r\nimport { Command } from \"commander\"\r\nimport { parse, detectFormat, detectZipFormat, fillFormFields, extractFormFields, blocksToMarkdown, markdownToHwpx, fillHwpx, PRESET_ALIAS } from \"./index.js\"\r\nimport type { ParseOptions } from \"./types.js\"\r\nimport { VERSION, toArrayBuffer, sanitizeError } from \"./utils.js\"\r\n\r\nconst program = new Command()\r\n\r\nprogram\r\n .name(\"kordoc\")\r\n .description(\"모두 파싱해버리겠다 — HWP, HWPX, PDF, XLSX, DOCX → Markdown\")\r\n .version(VERSION)\r\n .argument(\"<files...>\", \"변환할 파일 경로 (HWP, HWPX, PDF, XLSX, DOCX)\")\r\n .option(\"-o, --output <path>\", \"출력 파일 경로 (단일 파일 시)\")\r\n .option(\"-d, --out-dir <dir>\", \"출력 디렉토리 (다중 파일 시)\")\r\n .option(\"-p, --pages <range>\", \"페이지/섹션 범위 (예: 1-3, 1,3,5)\")\r\n .option(\"--format <type>\", \"출력 형식: markdown (기본) 또는 json\", \"markdown\")\r\n .option(\"--no-header-footer\", \"PDF 머리글/바닥글 자동 제거\")\r\n .option(\"--formula-ocr\", \"PDF 수식 OCR 활성화 (MFD+MFR ONNX, 첫 사용 시 모델 ~155MB 자동 다운로드)\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (files: string[], opts) => {\r\n const validFormats = [\"markdown\", \"json\"]\r\n if (!validFormats.includes(opts.format)) {\r\n process.stderr.write(`[kordoc] 지원하지 않는 형식: ${opts.format} (markdown 또는 json)\\n`)\r\n process.exit(1)\r\n }\r\n for (let fi = 0; fi < files.length; fi++) {\r\n const filePath = files[fi]\r\n const absPath = resolve(filePath)\r\n const fileName = basename(absPath)\r\n const filePrefix = files.length > 1 ? `[${fi + 1}/${files.length}] ` : \"\"\r\n\r\n try {\r\n const fileSize = statSync(absPath).size\r\n if (fileSize > 500 * 1024 * 1024) {\r\n process.stderr.write(`\\n[kordoc] SKIP: ${fileName} — 파일이 너무 큽니다 (${(fileSize / 1024 / 1024).toFixed(1)}MB)\\n`)\r\n process.exitCode = 1\r\n continue\r\n }\r\n const buffer = readFileSync(absPath)\r\n const arrayBuffer = toArrayBuffer(buffer)\r\n const format = detectFormat(arrayBuffer)\r\n\r\n if (!opts.silent) {\r\n process.stderr.write(`[kordoc] ${filePrefix}${fileName} (${format}) ...`)\r\n }\r\n\r\n const parseOptions: ParseOptions = { filePath: absPath }\r\n if (opts.pages) parseOptions.pages = opts.pages as string\r\n if (opts.headerFooter === false) parseOptions.removeHeaderFooter = false\r\n if (opts.formulaOcr) parseOptions.formulaOcr = true\r\n if (!opts.silent) {\r\n parseOptions.onProgress = (current: number, total: number) => {\r\n process.stderr.write(`\\r[kordoc] ${filePrefix}${fileName} (${format}) [${current}/${total}]`)\r\n }\r\n }\r\n const result = await parse(arrayBuffer, parseOptions)\r\n\r\n if (!result.success) {\r\n process.stderr.write(` FAIL\\n`)\r\n process.stderr.write(` → ${result.error}\\n`)\r\n process.exitCode = 1\r\n continue\r\n }\r\n\r\n if (!opts.silent) process.stderr.write(` OK\\n`)\r\n\r\n let markdown = result.markdown\r\n // --out-dir 시 이미지 참조 경로에 images/ 접두사 추가\r\n if (opts.outDir && result.images?.length) {\r\n markdown = markdown.replace(/!\\[image\\]\\(image_/g, \"![image](images/image_\")\r\n }\r\n const output = opts.format === \"json\"\r\n ? JSON.stringify(result, (_key, value) =>\r\n value instanceof Uint8Array ? Buffer.from(value).toString(\"base64\") : value\r\n , 2)\r\n : markdown\r\n\r\n // 이미지 저장 (--out-dir 또는 --output 시)\r\n const saveImages = (dir: string) => {\r\n if (!result.images?.length) return\r\n const imgDir = resolve(dir, \"images\")\r\n mkdirSync(imgDir, { recursive: true })\r\n for (const img of result.images) {\r\n writeFileSync(resolve(imgDir, img.filename), img.data)\r\n }\r\n if (!opts.silent) process.stderr.write(` → ${result.images.length}개 이미지 → ${imgDir}\\n`)\r\n }\r\n\r\n if (opts.output && files.length === 1) {\r\n writeFileSync(opts.output, output, \"utf-8\")\r\n if (!opts.silent) process.stderr.write(` → ${opts.output}\\n`)\r\n saveImages(resolve(opts.output, \"..\"))\r\n } else if (opts.outDir) {\r\n mkdirSync(opts.outDir, { recursive: true })\r\n const outExt = opts.format === \"json\" ? \".json\" : \".md\"\r\n const outPath = resolve(opts.outDir, fileName.replace(/\\.[^.]+$/, outExt))\r\n writeFileSync(outPath, output, \"utf-8\")\r\n if (!opts.silent) process.stderr.write(` → ${outPath}\\n`)\r\n saveImages(opts.outDir)\r\n } else {\r\n process.stdout.write(output + \"\\n\")\r\n }\r\n } catch (err) {\r\n process.stderr.write(`\\n[kordoc] ERROR: ${fileName} — ${sanitizeError(err)}\\n`)\r\n process.exitCode = 1\r\n }\r\n }\r\n })\r\n\r\nprogram\r\n .command(\"watch <dir>\")\r\n .description(\"디렉토리 감시 — 새 문서 자동 변환\")\r\n .option(\"--webhook <url>\", \"결과 전송 웹훅 URL\")\r\n .option(\"-d, --out-dir <dir>\", \"변환 결과 출력 디렉토리\")\r\n .option(\"-p, --pages <range>\", \"페이지/섹션 범위\")\r\n .option(\"--format <type>\", \"출력 형식: markdown 또는 json\", \"markdown\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (dir: string, opts) => {\r\n const { watchDirectory } = await import(\"./watch.js\")\r\n await watchDirectory({\r\n dir,\r\n outDir: opts.outDir,\r\n webhook: opts.webhook,\r\n format: opts.format,\r\n pages: opts.pages,\r\n silent: opts.silent,\r\n })\r\n })\r\n\r\nprogram\r\n .command(\"fill <template>\")\r\n .description(\"서식 문서의 빈칸을 채워서 출력 — kordoc fill 신청서.hwpx -f '성명=홍길동,전화=010-1234-5678' -o 결과.hwpx\")\r\n .option(\"-f, --fields <pairs>\", \"채울 필드 (key=value 쉼표 구분 또는 JSON)\")\r\n .option(\"-j, --json <path>\", \"채울 필드 JSON 파일 경로\")\r\n .option(\"-o, --output <path>\", \"출력 파일 경로 (확장자로 포맷 결정: .md, .hwpx)\")\r\n .option(\"--format <type>\", \"출력 포맷: hwpx-preserve (기본, 원본 스타일 보존), hwpx, markdown\", \"hwpx-preserve\")\r\n .option(\"--dry-run\", \"채우지 않고 서식 필드 목록만 출력\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (template: string, opts) => {\r\n try {\r\n const absPath = resolve(template)\r\n const fileSize = statSync(absPath).size\r\n if (fileSize > 500 * 1024 * 1024) {\r\n process.stderr.write(`[kordoc] 파일이 너무 큽니다 (${(fileSize / 1024 / 1024).toFixed(1)}MB)\\n`)\r\n process.exit(1)\r\n }\r\n\r\n const buffer = readFileSync(absPath)\r\n const arrayBuffer = toArrayBuffer(buffer)\r\n\r\n if (!opts.silent) process.stderr.write(`[kordoc] ${basename(absPath)} 파싱 중...\\n`)\r\n\r\n // --dry-run: 필드 목록만 출력\r\n if (opts.dryRun) {\r\n const result = await parse(arrayBuffer)\r\n if (!result.success) {\r\n process.stderr.write(`[kordoc] 파싱 실패: ${result.error}\\n`)\r\n process.exit(1)\r\n }\r\n const formInfo = extractFormFields(result.blocks)\r\n if (formInfo.fields.length === 0) {\r\n process.stderr.write(`[kordoc] 서식 필드를 찾을 수 없습니다.\\n`)\r\n process.exit(1)\r\n }\r\n process.stdout.write(JSON.stringify(formInfo, null, 2) + \"\\n\")\r\n return\r\n }\r\n\r\n // 필드 값 파싱\r\n let values: Record<string, string> = {}\r\n if (opts.json) {\r\n const jsonPath = resolve(opts.json)\r\n const jsonContent = readFileSync(jsonPath, \"utf-8\")\r\n values = JSON.parse(jsonContent)\r\n } else if (opts.fields) {\r\n const fieldsStr: string = opts.fields\r\n if (fieldsStr.startsWith(\"{\")) {\r\n values = JSON.parse(fieldsStr)\r\n } else {\r\n // \"key1=value1,key2=value2\" 파싱 — 값에 쉼표가 있을 수 있으므로\r\n // '=' 앞의 키를 기준으로 분리 (쉼표+한글/영문+= 패턴)\r\n const pairs = fieldsStr.split(/,(?=[가-힣A-Za-z][가-힣A-Za-z\\s]*=)/)\r\n for (const pair of pairs) {\r\n const eqIdx = pair.indexOf(\"=\")\r\n if (eqIdx > 0) {\r\n const key = pair.slice(0, eqIdx).trim()\r\n const val = pair.slice(eqIdx + 1).trim()\r\n values[key] = val\r\n }\r\n }\r\n }\r\n } else {\r\n process.stderr.write(`[kordoc] 채울 필드를 지정해주세요 (-f 또는 -j 옵션)\\n`)\r\n process.exit(1)\r\n }\r\n\r\n // 출력 포맷 결정\r\n let outputFormat = opts.format as string\r\n if (opts.output) {\r\n const ext = extname(opts.output).toLowerCase()\r\n if (ext === \".hwpx\") outputFormat = outputFormat === \"markdown\" ? \"hwpx-preserve\" : outputFormat\r\n else if (ext === \".md\") outputFormat = \"markdown\"\r\n }\r\n\r\n // ─── hwpx-preserve: 원본 ZIP 직접 수정 ───\r\n if (outputFormat === \"hwpx-preserve\") {\r\n const format = detectFormat(arrayBuffer)\r\n let isHwpx = format === \"hwpx\"\r\n if (isHwpx) {\r\n const zipFormat = await detectZipFormat(arrayBuffer)\r\n isHwpx = zipFormat === \"hwpx\"\r\n }\r\n if (!isHwpx) {\r\n if (!opts.silent) process.stderr.write(`[kordoc] HWPX가 아니므로 hwpx 모드로 전환합니다\\n`)\r\n outputFormat = \"hwpx\"\r\n } else {\r\n const hwpxResult = await fillHwpx(arrayBuffer, values)\r\n if (!opts.silent) {\r\n process.stderr.write(`[kordoc] ${hwpxResult.filled.length}개 필드 채움 (원본 스타일 보존)\\n`)\r\n if (hwpxResult.unmatched.length > 0) {\r\n process.stderr.write(`[kordoc] ⚠️ 매칭 실패: ${hwpxResult.unmatched.join(\", \")}\\n`)\r\n }\r\n }\r\n if (opts.output) {\r\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\r\n writeFileSync(resolve(opts.output), Buffer.from(hwpxResult.buffer))\r\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\r\n } else {\r\n process.stdout.write(Buffer.from(hwpxResult.buffer))\r\n }\r\n return\r\n }\r\n }\r\n\r\n // ─── 일반 경로: parse → fill → output ───\r\n const result = await parse(arrayBuffer)\r\n if (!result.success) {\r\n process.stderr.write(`[kordoc] 파싱 실패: ${result.error}\\n`)\r\n process.exit(1)\r\n }\r\n\r\n const formInfo = extractFormFields(result.blocks)\r\n if (!opts.silent) {\r\n process.stderr.write(`[kordoc] 서식 필드 ${formInfo.fields.length}개 감지 (확신도 ${(formInfo.confidence * 100).toFixed(0)}%)\\n`)\r\n }\r\n\r\n const fillResult = fillFormFields(result.blocks, values)\r\n if (!opts.silent) {\r\n process.stderr.write(`[kordoc] ${fillResult.filled.length}개 필드 채움\\n`)\r\n if (fillResult.unmatched.length > 0) {\r\n process.stderr.write(`[kordoc] ⚠️ 매칭 실패: ${fillResult.unmatched.join(\", \")}\\n`)\r\n }\r\n }\r\n\r\n const markdown = blocksToMarkdown(fillResult.blocks)\r\n\r\n if (outputFormat === \"hwpx\") {\r\n const hwpxBuffer = await markdownToHwpx(markdown)\r\n if (opts.output) {\r\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\r\n writeFileSync(resolve(opts.output), Buffer.from(hwpxBuffer))\r\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\r\n } else {\r\n process.stdout.write(Buffer.from(hwpxBuffer))\r\n }\r\n } else {\r\n if (opts.output) {\r\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\r\n writeFileSync(resolve(opts.output), markdown, \"utf-8\")\r\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\r\n } else {\r\n process.stdout.write(markdown + \"\\n\")\r\n }\r\n }\r\n } catch (err) {\r\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram\r\n .command(\"patch <original> <edited>\")\r\n .description(\"서식 보존 라운드트립 패치 — 편집된 마크다운을 원본 HWPX/HWP에 in-place 반영 (kordoc patch 원본.hwpx 편집.md -o 출력.hwpx)\")\r\n .option(\"-o, --output <path>\", \"출력 경로 (기본: <원본>.patched.hwpx|.hwp)\")\r\n .option(\"--no-verify\", \"패치 후 재파싱 자동 검증 생략\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (original: string, edited: string, opts) => {\r\n try {\r\n const { patchHwpx, patchHwp, detectFormat } = await import(\"./index.js\")\r\n // 루트 커맨드의 동명 옵션(-o/--silent)이 서브커맨드 옵션을 가로채는 commander 동작 보완\r\n const rootOpts = program.opts()\r\n const output: string | undefined = opts.output ?? rootOpts.output\r\n const silent: boolean = opts.silent ?? rootOpts.silent\r\n const originalBuf = new Uint8Array(readFileSync(resolve(original)))\r\n const editedMarkdown = readFileSync(resolve(edited), \"utf-8\")\r\n\r\n const format = detectFormat(originalBuf.buffer as ArrayBuffer)\r\n const result = format === \"hwp\"\r\n ? await patchHwp(originalBuf, editedMarkdown, { verify: opts.verify !== false })\r\n : await patchHwpx(originalBuf, editedMarkdown, { verify: opts.verify !== false })\r\n if (!result.success || !result.data) {\r\n process.stderr.write(`[kordoc] 패치 실패: ${result.error ?? \"알 수 없는 오류\"}\\n`)\r\n process.exit(1)\r\n }\r\n\r\n const ext = format === \"hwp\" ? \".hwp\" : \".hwpx\"\r\n const outPath = resolve(output ?? original.replace(/\\.hwpx?$/i, \"\") + \".patched\" + ext)\r\n mkdirSync(dirname(outPath), { recursive: true })\r\n writeFileSync(outPath, result.data)\r\n\r\n if (!silent) {\r\n process.stderr.write(`[kordoc] ${result.applied}개 변경 적용 (원본 서식 보존) → ${outPath}\\n`)\r\n for (const s of result.skipped) {\r\n process.stderr.write(`[kordoc] ⚠️ SKIP: ${s.reason}${s.before ? ` | ${s.before}` : \"\"}\\n`)\r\n }\r\n if (result.verification) {\r\n const v = result.verification.stats\r\n const residual = v.added + v.removed + v.modified\r\n process.stderr.write(residual === 0\r\n ? `[kordoc] ✓ 검증: 편집 마크다운과 재파싱 결과 완전 일치 (${v.unchanged}블록)\\n`\r\n : `[kordoc] ⚠️ 검증 잔차: 수정 ${v.modified}, 추가 ${v.added}, 삭제 ${v.removed} (미지원 변경은 skip 목록 참조)\\n`)\r\n }\r\n }\r\n if (result.skipped.length > 0) process.exitCode = 2\r\n } catch (err) {\r\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\n// 공문서 프리셋 별칭(한글/영문) → 내부 preset 키 — gongmun.ts와 공용(PRESET_ALIAS)\r\n\r\nprogram\r\n .command(\"generate <markdown>\")\r\n .alias(\"gen\")\r\n .description(\"마크다운 → 공문서 HWPX 생성 — kordoc generate 보고서.md -o 보고서.hwpx --preset 보고서 (markdown에 '-' 지정 시 stdin)\")\r\n .option(\"-o, --output <path>\", \"출력 HWPX 경로 (기본: <입력>.hwpx)\")\r\n .option(\"--preset <name>\", \"공문서 프리셋: 기안문(official)·보고서(report)·계획서(plan)·통지(notice)·회의록(minutes)\", \"기안문\")\r\n .option(\"--font <type>\", \"본문 글꼴: myeongjo(함초롬바탕) 또는 gothic(맑은 고딕)\")\r\n .option(\"--pt <size>\", \"본문 글자 크기(pt)\")\r\n .option(\"--line-spacing <percent>\", \"본문 줄간격(%)\")\r\n .option(\"--plain\", \"공문서 모드 끄기 (범용 마크다운 변환)\")\r\n .option(\"--silent\", \"진행 메시지 숨기기\")\r\n .action(async (markdown: string, opts) => {\r\n try {\r\n const rootOpts = program.opts()\r\n const output: string | undefined = opts.output ?? rootOpts.output\r\n const silent: boolean = opts.silent ?? rootOpts.silent\r\n\r\n // 입력: '-' 이면 stdin, 아니면 파일\r\n let md: string\r\n let baseName = \"document\"\r\n if (markdown === \"-\") {\r\n md = readFileSync(0, \"utf-8\")\r\n } else {\r\n const inPath = resolve(markdown)\r\n md = readFileSync(inPath, \"utf-8\")\r\n baseName = basename(inPath).replace(/\\.(md|markdown|txt)$/i, \"\")\r\n }\r\n\r\n // 공문서 옵션 구성\r\n let gongmun: import(\"./index.js\").GongmunOptions | undefined\r\n if (!opts.plain) {\r\n const preset = PRESET_ALIAS[String(opts.preset).trim()]\r\n if (!preset) {\r\n process.stderr.write(`[kordoc] 알 수 없는 프리셋: ${opts.preset} (기안문/보고서/계획서/통지/회의록)\\n`)\r\n process.exit(1)\r\n }\r\n gongmun = { preset }\r\n if (opts.font) {\r\n if (opts.font !== \"myeongjo\" && opts.font !== \"gothic\") {\r\n process.stderr.write(`[kordoc] --font 은 myeongjo 또는 gothic\\n`)\r\n process.exit(1)\r\n }\r\n gongmun.bodyFont = opts.font\r\n }\r\n if (opts.pt) gongmun.bodyPt = Number(opts.pt)\r\n if (opts.lineSpacing) gongmun.lineSpacing = Number(opts.lineSpacing)\r\n }\r\n\r\n const buf = await markdownToHwpx(md, gongmun ? { gongmun } : undefined)\r\n const outPath = resolve(output ?? (markdown === \"-\" ? `${baseName}.hwpx` : markdown.replace(/\\.(md|markdown|txt)$/i, \"\") + \".hwpx\"))\r\n mkdirSync(dirname(outPath), { recursive: true })\r\n writeFileSync(outPath, Buffer.from(buf))\r\n\r\n if (!silent) {\r\n const mode = gongmun ? `공문서:${gongmun.preset}` : \"범용\"\r\n process.stderr.write(`[kordoc] HWPX 생성 (${mode}) → ${outPath}\\n`)\r\n }\r\n } catch (err) {\r\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram\r\n .command(\"mcp\")\r\n .description(\"MCP 서버 실행 (Claude / Cursor / Windsurf 연동)\")\r\n .action(async () => {\r\n await import(\"./mcp.js\")\r\n })\r\n\r\nprogram\r\n .command(\"setup\")\r\n .description(\"대화형 설치 마법사 — AI 클라이언트 자동 등록 (Mac/Win/Linux)\")\r\n .action(async () => {\r\n const { runSetup } = await import(\"./setup.js\")\r\n await runSetup()\r\n })\r\n\r\nprogram\r\n .command(\"check-formula-models\")\r\n .description(\"PDF 수식 OCR 모델(MFD + MFR + tokenizer, ~155MB) 상태 확인 — 없거나 SHA 불일치면 다운로드\")\r\n .option(\"--status-only\", \"상태만 JSON 으로 출력 (다운로드 안 함)\")\r\n .action(async (opts) => {\r\n try {\r\n const { getFormulaModelStatus, ensureFormulaModels, getFormulaModelsDir } = await import(\r\n \"./pdf/formula/index.js\"\r\n )\r\n const dir = getFormulaModelsDir()\r\n if (opts.statusOnly) {\r\n const status = await getFormulaModelStatus()\r\n process.stdout.write(\r\n JSON.stringify(\r\n {\r\n modelsDir: dir,\r\n allReady: status.every((s) => s.verified),\r\n models: status.map((s) => ({\r\n name: s.spec.name,\r\n filename: s.spec.filename,\r\n sizeMb: s.spec.sizeMb,\r\n exists: s.exists,\r\n verified: s.verified,\r\n invalidReason: s.invalidReason,\r\n path: s.localPath,\r\n })),\r\n },\r\n null,\r\n 2,\r\n ) + \"\\n\",\r\n )\r\n return\r\n }\r\n process.stderr.write(`[kordoc-formula] 캐시 디렉토리: ${dir}\\n`)\r\n await ensureFormulaModels((p) => {\r\n if (p.phase === \"download\" && p.total) {\r\n const pct = Math.floor((p.downloaded / p.total) * 100)\r\n process.stderr.write(\r\n `\\r[kordoc-formula] ${p.spec.name} ${pct}% (${(p.downloaded / 1024 / 1024).toFixed(1)}/${(p.total / 1024 / 1024).toFixed(1)}MB)`,\r\n )\r\n if (p.downloaded >= p.total) process.stderr.write(\"\\n\")\r\n } else if (p.phase === \"verify\") {\r\n process.stderr.write(`[kordoc-formula] ${p.spec.name} SHA-256 검증 중...\\n`)\r\n } else if (p.phase === \"done\") {\r\n process.stderr.write(`[kordoc-formula] ${p.spec.name} 준비 완료\\n`)\r\n } else if (p.phase === \"skip\") {\r\n process.stderr.write(`[kordoc-formula] ${p.spec.name} 이미 존재 (skip)\\n`)\r\n }\r\n })\r\n process.stdout.write(\"ok\\n\")\r\n } catch (err) {\r\n process.stderr.write(`[kordoc] 수식 모델 준비 실패: ${sanitizeError(err)}\\n`)\r\n process.exit(1)\r\n }\r\n })\r\n\r\nprogram.parse()\r\n"],"mappings":"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","names":["result","formInfo","detectFormat"]}