kordoc 4.24.0 → 4.24.2

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 (126) hide show
  1. package/README.md +26 -54
  2. package/dist/{-VEOO4BOM.js → -SRNEV7LS.js} +11 -11
  3. package/dist/{chunk-P35SCAJN.js → chunk-3HN65YAL.js} +2 -2
  4. package/dist/{chunk-H5PDQ66I.js → chunk-4745MFQU.js} +3 -3
  5. package/dist/{chunk-ENCAYXDI.js → chunk-4XC4O7FJ.js} +4 -4
  6. package/dist/{chunk-EN3PK6OT.js → chunk-7NTMM6PO.js} +2 -2
  7. package/dist/{chunk-GEY6ZMXH.js → chunk-C6ZVB547.js} +43 -23
  8. package/dist/{chunk-GEY6ZMXH.js.map → chunk-C6ZVB547.js.map} +1 -1
  9. package/dist/{chunk-CKCJU42Y.js → chunk-DHMBPMKC.js} +74 -30
  10. package/dist/chunk-DHMBPMKC.js.map +1 -0
  11. package/dist/{chunk-ZGNHJCDR.js → chunk-E6VBLBOO.js} +2 -2
  12. package/dist/{chunk-O2SLKE4L.js → chunk-E7B5CXYI.js} +2 -2
  13. package/dist/{chunk-DKWEZWCF.cjs → chunk-HLTPMSYW.cjs} +3 -3
  14. package/dist/{chunk-DKWEZWCF.cjs.map → chunk-HLTPMSYW.cjs.map} +1 -1
  15. package/dist/{chunk-DZT3CHNZ.cjs → chunk-IGG63DFK.cjs} +3 -3
  16. package/dist/{chunk-DZT3CHNZ.cjs.map → chunk-IGG63DFK.cjs.map} +1 -1
  17. package/dist/{chunk-IHNIPVPJ.cjs → chunk-JFUUFJZW.cjs} +6 -6
  18. package/dist/{chunk-IHNIPVPJ.cjs.map → chunk-JFUUFJZW.cjs.map} +1 -1
  19. package/dist/{chunk-PX6X4YOR.js → chunk-JMOAMKAR.js} +4 -4
  20. package/dist/{chunk-P6FNIU5P.js → chunk-KUC5I5MB.js} +2 -2
  21. package/dist/{chunk-Z5G6QNVH.js → chunk-LMEF7FN5.js} +2 -2
  22. package/dist/{chunk-OJISMR2Z.js → chunk-M46PB75E.js} +2 -2
  23. package/dist/{chunk-G4HWEM6Q.js → chunk-MHNJOJQV.js} +4 -4
  24. package/dist/{chunk-Z62PHCSU.js → chunk-NJ5RUDCW.js} +3 -3
  25. package/dist/{chunk-DM5YPONO.js → chunk-NMFFIUI6.js} +2 -2
  26. package/dist/{chunk-HOXHBG4C.cjs → chunk-PNSALBXH.cjs} +2 -2
  27. package/dist/{chunk-HOXHBG4C.cjs.map → chunk-PNSALBXH.cjs.map} +1 -1
  28. package/dist/{chunk-FHFPQ6MX.cjs → chunk-PNX5FYHC.cjs} +24 -24
  29. package/dist/{chunk-FHFPQ6MX.cjs.map → chunk-PNX5FYHC.cjs.map} +1 -1
  30. package/dist/{chunk-IZYYKE5F.js → chunk-R2GIGE5H.js} +2 -2
  31. package/dist/{chunk-55DOBEGD.js → chunk-RIRPLFPN.js} +2 -2
  32. package/dist/{chunk-3M2BIQLZ.js → chunk-TDMBTG7U.js} +2 -2
  33. package/dist/{chunk-6YDPTTIY.js → chunk-TW3V6FSH.js} +2 -2
  34. package/dist/{chunk-OHDGEGDJ.cjs → chunk-UNICY546.cjs} +23 -23
  35. package/dist/{chunk-OHDGEGDJ.cjs.map → chunk-UNICY546.cjs.map} +1 -1
  36. package/dist/{chunk-SRUBDR3Z.js → chunk-VPSF5LEM.js} +3 -3
  37. package/dist/{chunk-4VPN5MHS.js → chunk-W24TJJNN.js} +2 -2
  38. package/dist/{chunk-DBPDAG7N.js → chunk-WDSTW3BD.js} +2 -2
  39. package/dist/{chunk-XLY5ZJRP.js → chunk-WJAFE3Z6.js} +2 -2
  40. package/dist/chunks-AL4P5TO5.js +10 -0
  41. package/dist/cli.js +41 -30
  42. package/dist/cli.js.map +1 -1
  43. package/dist/{formula-4GRNVWIQ.js → formula-DSB574H7.js} +4 -4
  44. package/dist/{formula-R3OWFGCZ.cjs → formula-HK2MNZ3Q.cjs} +9 -9
  45. package/dist/{formula-R3OWFGCZ.cjs.map → formula-HK2MNZ3Q.cjs.map} +1 -1
  46. package/dist/{formula-6Y467S4R.js → formula-U2LZ67KI.js} +3 -3
  47. package/dist/{image-ocr-CGJJCD4E.js → image-ocr-3QB2HLSI.js} +9 -9
  48. package/dist/{image-ocr-ZLL66KNO.js → image-ocr-J54Q3YWP.js} +6 -6
  49. package/dist/{image-ocr-EBKG45KF.cjs → image-ocr-QNIMVE5A.cjs} +17 -17
  50. package/dist/{image-ocr-EBKG45KF.cjs.map → image-ocr-QNIMVE5A.cjs.map} +1 -1
  51. package/dist/index.cjs +683 -619
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +1 -1
  54. package/dist/index.d.ts +1 -1
  55. package/dist/index.js +106 -42
  56. package/dist/index.js.map +1 -1
  57. package/dist/mcp.js +36 -33
  58. package/dist/mcp.js.map +1 -1
  59. package/dist/{model-bundle-RD4KSNTB.js → model-bundle-CGWU4ALC.js} +5 -5
  60. package/dist/{models-OLGCZBXI.js → models-A3TF3BDV.js} +5 -5
  61. package/dist/{parse-worker-v2-YZY2GQY5.js → parse-worker-v2-MNUD4WAR.js} +20 -13
  62. package/dist/parse-worker-v2-MNUD4WAR.js.map +1 -0
  63. package/dist/{parser-IHCFHLHN.js → parser-C3ARF26I.js} +12 -12
  64. package/dist/{parser-J22QBXPP.js → parser-OBGWEWSU.js} +9 -9
  65. package/dist/{parser-DX4I3GT7.cjs → parser-RPAHN3OR.cjs} +157 -157
  66. package/dist/{parser-DX4I3GT7.cjs.map → parser-RPAHN3OR.cjs.map} +1 -1
  67. package/dist/{pdf-ocr-TYIH23RP.js → pdf-ocr-ENLVEEYL.js} +9 -9
  68. package/dist/pdf-ocr-GA5QJFNK.cjs +31 -0
  69. package/dist/{pdf-ocr-WU7SZHWM.cjs.map → pdf-ocr-GA5QJFNK.cjs.map} +1 -1
  70. package/dist/{pdf-ocr-H2247ZZH.js → pdf-ocr-K53REDNY.js} +6 -6
  71. package/dist/{profile-io-GH3TYTNJ.js → profile-io-ZGFEO7CB.js} +3 -3
  72. package/dist/{rasterize-7TFTVFMB.js → rasterize-QMC2SAUT.js} +3 -3
  73. package/dist/{redact-doc-DSSQOO3A.js → redact-doc-JH6RZZBE.js} +11 -11
  74. package/dist/{render-NKXZQINI.js → render-ZGKQLKPJ.js} +7 -7
  75. package/dist/seal-KMGYTJAV.js +10 -0
  76. package/dist/{setup-JVLMX2TH.js → setup-LAQGCYQ2.js} +3 -3
  77. package/dist/visual-4OYJFGXL.js +21 -0
  78. package/dist/{watch-5RZVHAKI.js → watch-7YPB4TKC.js} +12 -12
  79. package/package.json +1 -1
  80. package/dist/chunk-CKCJU42Y.js.map +0 -1
  81. package/dist/chunks-LV5EJBZ4.js +0 -10
  82. package/dist/parse-worker-v2-YZY2GQY5.js.map +0 -1
  83. package/dist/pdf-ocr-WU7SZHWM.cjs +0 -31
  84. package/dist/seal-JIVSSI3Z.js +0 -10
  85. package/dist/visual-BKVZN6HP.js +0 -21
  86. /package/dist/{-VEOO4BOM.js.map → -SRNEV7LS.js.map} +0 -0
  87. /package/dist/{chunk-P35SCAJN.js.map → chunk-3HN65YAL.js.map} +0 -0
  88. /package/dist/{chunk-H5PDQ66I.js.map → chunk-4745MFQU.js.map} +0 -0
  89. /package/dist/{chunk-ENCAYXDI.js.map → chunk-4XC4O7FJ.js.map} +0 -0
  90. /package/dist/{chunk-EN3PK6OT.js.map → chunk-7NTMM6PO.js.map} +0 -0
  91. /package/dist/{chunk-ZGNHJCDR.js.map → chunk-E6VBLBOO.js.map} +0 -0
  92. /package/dist/{chunk-O2SLKE4L.js.map → chunk-E7B5CXYI.js.map} +0 -0
  93. /package/dist/{chunk-PX6X4YOR.js.map → chunk-JMOAMKAR.js.map} +0 -0
  94. /package/dist/{chunk-P6FNIU5P.js.map → chunk-KUC5I5MB.js.map} +0 -0
  95. /package/dist/{chunk-Z5G6QNVH.js.map → chunk-LMEF7FN5.js.map} +0 -0
  96. /package/dist/{chunk-OJISMR2Z.js.map → chunk-M46PB75E.js.map} +0 -0
  97. /package/dist/{chunk-G4HWEM6Q.js.map → chunk-MHNJOJQV.js.map} +0 -0
  98. /package/dist/{chunk-Z62PHCSU.js.map → chunk-NJ5RUDCW.js.map} +0 -0
  99. /package/dist/{chunk-DM5YPONO.js.map → chunk-NMFFIUI6.js.map} +0 -0
  100. /package/dist/{chunk-IZYYKE5F.js.map → chunk-R2GIGE5H.js.map} +0 -0
  101. /package/dist/{chunk-55DOBEGD.js.map → chunk-RIRPLFPN.js.map} +0 -0
  102. /package/dist/{chunk-3M2BIQLZ.js.map → chunk-TDMBTG7U.js.map} +0 -0
  103. /package/dist/{chunk-6YDPTTIY.js.map → chunk-TW3V6FSH.js.map} +0 -0
  104. /package/dist/{chunk-SRUBDR3Z.js.map → chunk-VPSF5LEM.js.map} +0 -0
  105. /package/dist/{chunk-4VPN5MHS.js.map → chunk-W24TJJNN.js.map} +0 -0
  106. /package/dist/{chunk-DBPDAG7N.js.map → chunk-WDSTW3BD.js.map} +0 -0
  107. /package/dist/{chunk-XLY5ZJRP.js.map → chunk-WJAFE3Z6.js.map} +0 -0
  108. /package/dist/{chunks-LV5EJBZ4.js.map → chunks-AL4P5TO5.js.map} +0 -0
  109. /package/dist/{formula-4GRNVWIQ.js.map → formula-DSB574H7.js.map} +0 -0
  110. /package/dist/{formula-6Y467S4R.js.map → formula-U2LZ67KI.js.map} +0 -0
  111. /package/dist/{image-ocr-CGJJCD4E.js.map → image-ocr-3QB2HLSI.js.map} +0 -0
  112. /package/dist/{image-ocr-ZLL66KNO.js.map → image-ocr-J54Q3YWP.js.map} +0 -0
  113. /package/dist/{model-bundle-RD4KSNTB.js.map → model-bundle-CGWU4ALC.js.map} +0 -0
  114. /package/dist/{models-OLGCZBXI.js.map → models-A3TF3BDV.js.map} +0 -0
  115. /package/dist/{parser-IHCFHLHN.js.map → parser-C3ARF26I.js.map} +0 -0
  116. /package/dist/{parser-J22QBXPP.js.map → parser-OBGWEWSU.js.map} +0 -0
  117. /package/dist/{pdf-ocr-H2247ZZH.js.map → pdf-ocr-ENLVEEYL.js.map} +0 -0
  118. /package/dist/{pdf-ocr-TYIH23RP.js.map → pdf-ocr-K53REDNY.js.map} +0 -0
  119. /package/dist/{profile-io-GH3TYTNJ.js.map → profile-io-ZGFEO7CB.js.map} +0 -0
  120. /package/dist/{rasterize-7TFTVFMB.js.map → rasterize-QMC2SAUT.js.map} +0 -0
  121. /package/dist/{redact-doc-DSSQOO3A.js.map → redact-doc-JH6RZZBE.js.map} +0 -0
  122. /package/dist/{render-NKXZQINI.js.map → render-ZGKQLKPJ.js.map} +0 -0
  123. /package/dist/{seal-JIVSSI3Z.js.map → seal-KMGYTJAV.js.map} +0 -0
  124. /package/dist/{setup-JVLMX2TH.js.map → setup-LAQGCYQ2.js.map} +0 -0
  125. /package/dist/{visual-BKVZN6HP.js.map → visual-4OYJFGXL.js.map} +0 -0
  126. /package/dist/{watch-5RZVHAKI.js.map → watch-7YPB4TKC.js.map} +0 -0
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/cli/convert.ts","../src/cli/output-path.ts","../src/cli/batch.ts","../src/cli/commands-docs.ts","../src/cli/commands-generate.ts","../src/hwpx/level-styles.ts","../src/cli/commands-render.ts","../src/cli/commands-system.ts","../src/cli/commands-worker.ts"],"sourcesContent":["/** kordoc CLI — 모두 파싱해버리겠다 (하위 명령은 cli/ 아래 명령군 모듈) */\n\nimport { Command } from \"commander\"\nimport { VERSION, sanitizeError, routeConsoleToStderr } from \"./utils.js\"\nimport { convertFiles } from \"./cli/convert.js\"\nimport { assertDistinctStems, convertParallel, registerBatchWorker } from \"./cli/batch.js\"\nimport { registerDocCommands } from \"./cli/commands-docs.js\"\nimport { registerGenerateCommands } from \"./cli/commands-generate.js\"\nimport { registerRenderCommands } from \"./cli/commands-render.js\"\nimport { registerSystemCommands } from \"./cli/commands-system.js\"\nimport { registerWorkerCommands } from \"./cli/commands-worker.js\"\n\nconst program = new Command()\n\nprogram\n .name(\"kordoc\")\n .description(\"모두 파싱해버리겠다 — HWP, HWPX, PDF, XLSX, DOCX, 이미지(PNG/JPG/WebP) → Markdown\")\n .version(VERSION)\n .argument(\"<files...>\", \"변환할 파일 경로 (HWP, HWPX, PDF, XLSX, DOCX, PNG/JPG/WebP — 이미지는 OCR 자동 적용)\")\n .option(\"-o, --output <path>\", \"출력 파일 경로 (단일 파일 시)\")\n .option(\"--jobs <count>\", \"병렬 변환 프로세스 수 (기본 1, 다중 파일은 -d 필요)\", \"1\")\n .option(\"-d, --out-dir <dir>\", \"출력 디렉토리 (다중 파일 시)\")\n .option(\"-p, --pages <range>\", \"페이지 범위 (예: 1-3, 1,3,5) — 한컴 저장본은 실제 페이지, 조판 캐시 없으면 섹션 근사\")\n .option(\"--format <type>\", \"출력 형식: markdown (기본), json, chunks (RAG용 구조 청크 JSON — 헤딩·개조식 위계 breadcrumb + 표 독립 청크)\", \"markdown\")\n .option(\"--no-header-footer\", \"PDF 머리글/바닥글 자동 제거 끄기 (기본: 제거함)\")\n .option(\"--no-tables\", \"PDF 표 감지 끄기 — 테두리 박스를 표로 오인해 읽기 순서가 뒤집히는 문서(2단 시험지 등)에서 자연 읽기순 텍스트만 뽑는다 (#64)\")\n .option(\"--formula-ocr\", \"PDF 수식 OCR 활성화 (MFD+MFR ONNX, 첫 사용 시 모델 ~155MB 자동 다운로드)\")\n .option(\"--ocr\", \"스캔/이미지 PDF 텍스트 OCR (내장 PP-OCRv5 korean, 첫 사용 시 모델 ~18MB 자동 다운로드 — OCR 필요 페이지만 인식)\")\n .option(\"--ocr-force\", \"전 페이지 강제 OCR (텍스트층이 있어도 무시하고 재인식)\")\n .option(\"--ocr-lines\", \"내장 OCR 이 읽은 줄(래스터 px 상자·신뢰도)을 --format json 결과 ocrLines 로\")\n .option(\"--ocr-lines-all\", \"--ocr-lines 에 저신뢰로 버린 줄도 dropped 표시로 함께\")\n .option(\"--ocr-det <model>\", \"OCR 글줄 검출 모델: mobile (기본) | server (~88MB 첫 사용 시 다운로드) | 로컬 ONNX 경로 (--ocr-det-sha256 필수)\")\n .option(\"--ocr-det-sha256 <hex>\", \"--ocr-det 로컬 파일의 SHA-256 — 다르면 로드 거부\")\n .option(\"--ocr-det-long-side <px>\", \"OCR 글줄 검출 입력 긴 변 (32~4096, 기본 960) — 키우면 작은 글자를 더 잡고 느려진다\")\n .option(\"--ocr-rec <model>\", \"OCR 글자 인식 모델: handwriting (수기 서류용 한국어 손글씨 rec, ~15MB 첫 사용 시 다운로드) | 로컬 ONNX 경로 (--ocr-rec-sha256 필수)\")\n .option(\"--ocr-rec-sha256 <hex>\", \"--ocr-rec 파일의 SHA-256\")\n .option(\"--ocr-rec-dict <path>\", \"OCR 글자 인식 사전을 로컬 inference.yml 로 (--ocr-rec-dict-sha256 필수, 기본 내장 한국어 사전)\")\n .option(\"--ocr-rec-dict-sha256 <hex>\", \"--ocr-rec-dict 파일의 SHA-256\")\n .option(\"--dedupe-headers\", \"HWP5 레이아웃 표 페이지 반복 러닝 헤더 중복 제거 (기본 off — 붙임별 재번호 오삭제 주의)\")\n .option(\"--keep-empty-cols\", \"표 오른쪽 끝 빈 열(서식 입력란) 보존 (#47, 기본 off: 후행 빈 열 트림)\")\n .option(\"--keep-empty-paragraphs\", \"빈 문단 보존 — 본문은 빈 paragraph 블록, 표 셀은 빈 줄로 (#57, 기본 off: 빈 문단 제거)\")\n .option(\"--include-field-placeholders\", \"미기입 누름틀 안내문도 출력 — 빈 서식의 칸 용도 보존 (#92, 기본 off: 인쇄되지 않는 안내문 제외)\")\n .option(\"--inline-images\", \"이미지를 base64 data URI 로 마크다운에 인라인 (BMP→PNG 압축, HWP5 전용 — 인라인된 경우만 파일 미저장, 그 외 포맷은 저장 유지)\")\n .option(\"--image-refs\", \"--format json 에서 이미지 바이트를 인라인하지 않고 파일 참조(images/<문서 이름>/<파일명>)만 남김 (#65 — 이미지가 수백 장인 문서의 직렬화 한계 회피, -o/-d 와 함께 사용)\")\n .option(\"--password <pw>\", \"암호로 보호된 문서의 열기 암호 (#59, HWPX·HWP3·HWP5. 한컴 DRM 문서는 해당 없음)\")\n .option(\"--html-tables\", \"모든 표를 HTML 로 — 파이프 표도 HTML 표로, 태그마다 한 줄씩 들여써 냄\")\n .option(\"--table-format <format>\", \"표 출력 형식: gfm — 모든 표를 HTML 없이 GFM 파이프 표로, 셀 안 표는 부모 뒤 독립 표 + 관계 표지(<!-- <table … /> -->) (RAG 색인용, --html-tables 와 함께 못 씀)\")\n .option(\"--keep-layout-tables\", \"테두리가 안 보이는 틀 표도 원본 표 구조 그대로 (기본: 보이는 대로 — 틀은 글, 칸으로 조립한 분수는 수식). patch 로 되돌릴 편집본은 이 옵션으로 뽑는다\")\n .option(\"--script-tags\", \"위·아래첨자를 <sup>·<sub> 로 표기 — PDF 는 기본 끔(논문·수식 PDF 에 권장), HWPX·HWP·DOCX 는 기본 켬\")\n .option(\"--no-script-tags\", \"첨자 표기 끄기 — 모든 형식에서 평문(\\\"104 m2\\\")\")\n .option(\"--plain\", \"평문 Markdown — 그림 자리 표시·링크 URL·밑줄/굵게 표기를 빼고 글만 (제목·목록·표 구조는 유지, 색인·RAG 용)\")\n .option(\"--no-images\", \"이미지 바이트를 추출·출력하지 않음: 글자만 필요할 때 (그림 자리 표시는 남김, PDF 는 PNG 인코딩을 건너뜀)\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (files: string[], opts) => {\n const validFormats = [\"markdown\", \"json\", \"chunks\"]\n if (!validFormats.includes(opts.format)) {\n process.stderr.write(`[kordoc] 지원하지 않는 형식: ${opts.format} (markdown, json, chunks)\\n`)\n process.exit(1)\n }\n if (opts.tableFormat !== undefined && opts.tableFormat !== \"gfm\") {\n process.stderr.write(`[kordoc] 지원하지 않는 표 형식: ${opts.tableFormat} (gfm)\\n`)\n process.exit(1)\n }\n if (opts.tableFormat && opts.htmlTables) {\n process.stderr.write(`[kordoc] --table-format 과 --html-tables 는 함께 쓸 수 없습니다\\n`)\n process.exit(1)\n }\n // -o는 단일 파일 전용 — 다중 파일에서 무음 무시되지 않게 경고\n if (opts.output && files.length > 1) {\n process.stderr.write(`[kordoc] ⚠️ -o/--output 은 단일 파일 전용이라 무시됩니다 — 다중 파일은 -d/--out-dir 를 사용하세요\\n`)\n }\n const jobs = Number(opts.jobs)\n if (!/^\\d+$/.test(opts.jobs) || !Number.isSafeInteger(jobs) || jobs < 1) {\n program.error(\"--jobs must be a positive integer\")\n }\n if (jobs > 1 && files.length > 1) {\n if (!opts.outDir) program.error(\"--jobs > 1 requires --out-dir for multiple files\")\n try {\n if (!await convertParallel(files, opts, jobs)) process.exitCode = 1\n } catch (err) {\n program.error(sanitizeError(err))\n }\n } else {\n if (opts.outDir && files.length > 1) {\n try { assertDistinctStems(files) } catch (err) { program.error(sanitizeError(err)) }\n }\n if (!await convertFiles(files, opts)) process.exitCode = 1\n }\n })\n\nregisterDocCommands(program)\nregisterGenerateCommands(program)\nregisterRenderCommands(program)\nregisterSystemCommands(program)\nregisterWorkerCommands(program)\nregisterBatchWorker(program)\n\n// stdout 은 마크다운·JSON·생성 바이너리 채널 — pdfjs 등이 console 로 찍는 경고가 섞이지 않게 stderr 로\n// (parse-worker·MCP 와 같은 처리). setup 은 사람이 보는 설치 화면이라 그대로 둔다\nprogram.hook(\"preAction\", (_program, action) => {\n if (action.name() !== \"setup\") routeConsoleToStderr()\n})\n\n// 출처를 node 로 고정 — 정하지 않으면 commander 가 process.versions.electron 을 보고 Electron 앱 방식(argv[1]부터)으로\n// 읽어, Electron 을 node 로 띄운(ELECTRON_RUN_AS_NODE) 데스크톱 앱에서 cli.js 자신이 입력 파일로 잡힌다\nprogram.parse(process.argv, { from: \"node\" })\n","/** Shared sequential conversion path for the CLI and batch workers. */\n\nimport { readFileSync, writeFileSync, mkdirSync, statSync } from \"fs\"\nimport { basename, resolve } from \"path\"\nimport type { OptionValues } from \"commander\"\nimport { parse, detectFormat } from \"../index.js\"\nimport type { ParseOptions } from \"../types.js\"\nimport { toArrayBuffer, sanitizeError, classifyError } from \"../utils.js\"\nimport { detectImageMime } from \"../hwp5/images.js\"\nimport { toPlainMarkdown } from \"../plain-markdown.js\"\nimport { toHtmlTables } from \"../html-tables.js\"\nimport { createOutputGuard } from \"./output-path.js\"\n\n/** --ocr-lines·--ocr-det·--ocr-rec… → ParseOptions. 값 검증은 parse() 가 한다(잘못이면 실패 JSON). 로컬 경로는 현재 디렉터리 기준 절대 경로로 */\nexport function cliOcrEngineOptions(opts: OptionValues): Pick<ParseOptions, \"ocrLines\" | \"ocrDet\" | \"ocrDetLongSide\" | \"ocrRec\" | \"ocrRecDict\"> {\n const out: Pick<ParseOptions, \"ocrLines\" | \"ocrDet\" | \"ocrDetLongSide\" | \"ocrRec\" | \"ocrRecDict\"> = {}\n const file = (path: string, sha256: unknown) => ({ path: resolve(path), sha256: typeof sha256 === \"string\" ? sha256 : \"\" })\n if (opts.ocrLinesAll) out.ocrLines = \"all\"\n else if (opts.ocrLines) out.ocrLines = true\n if (opts.ocrDet !== undefined) {\n out.ocrDet = opts.ocrDet === \"mobile\" || opts.ocrDet === \"server\" ? opts.ocrDet : file(String(opts.ocrDet), opts.ocrDetSha256)\n }\n // 숫자가 아니면 받은 글 그대로 넘겨 parse() 가 그 값을 들어 거부한다\n if (opts.ocrDetLongSide !== undefined) out.ocrDetLongSide = /^\\d+$/.test(String(opts.ocrDetLongSide)) ? Number(opts.ocrDetLongSide) : opts.ocrDetLongSide as number\n if (opts.ocrRec !== undefined) out.ocrRec = opts.ocrRec === \"handwriting\" ? opts.ocrRec : file(String(opts.ocrRec), opts.ocrRecSha256)\n if (opts.ocrRecDict !== undefined) out.ocrRecDict = file(String(opts.ocrRecDict), opts.ocrRecDictSha256)\n return out\n}\n\nexport async function convertFiles(files: string[], opts: OptionValues, writeOutput: (text: string) => void = text => { process.stdout.write(text) }, assertSafeOutputs = createOutputGuard(files)): Promise<boolean> {\n let failed = false\n for (let fi = 0; fi < files.length; fi++) {\n const filePath = files[fi]\n const absPath = resolve(filePath)\n const fileName = basename(absPath)\n const filePrefix = files.length > 1 ? `[${fi + 1}/${files.length}] ` : \"\"\n let detectedFormat: ReturnType<typeof detectFormat> = \"unknown\"\n\n try {\n const fileSize = statSync(absPath).size\n if (fileSize > 500 * 1024 * 1024) {\n process.stderr.write(`\\n[kordoc] SKIP: ${fileName} — 파일이 너무 큽니다 (${(fileSize / 1024 / 1024).toFixed(1)}MB)\\n`)\n failed = true\n continue\n }\n const buffer = readFileSync(absPath)\n const arrayBuffer = toArrayBuffer(buffer)\n const format = detectFormat(arrayBuffer)\n detectedFormat = format\n\n if (!opts.silent) {\n process.stderr.write(`[kordoc] ${filePrefix}${fileName} (${format}) ...`)\n }\n\n const parseOptions: ParseOptions = { filePath: absPath }\n if (opts.pages) parseOptions.pages = opts.pages as string\n if (opts.headerFooter === false) parseOptions.removeHeaderFooter = false\n if (opts.tables === false) parseOptions.tables = false\n if (opts.formulaOcr) parseOptions.formulaOcr = true\n if (opts.ocrForce) parseOptions.ocr = \"force\"\n else if (opts.ocr) parseOptions.ocr = true\n Object.assign(parseOptions, cliOcrEngineOptions(opts))\n if (opts.dedupeHeaders) parseOptions.dedupeRunningHeaders = true\n if (opts.keepEmptyCols) parseOptions.keepTrailingEmptyCols = true\n if (opts.keepEmptyParagraphs) parseOptions.keepEmptyParagraphs = true\n if (opts.includeFieldPlaceholders) parseOptions.includeFieldPlaceholders = true\n if (opts.inlineImages) parseOptions.inlineImages = true\n if (opts.password) parseOptions.password = opts.password as string\n if (opts.images === false) parseOptions.images = false\n if (opts.plain) parseOptions.plain = true\n if (opts.scriptTags !== undefined) parseOptions.scriptTags = opts.scriptTags as boolean\n if (opts.htmlTables) parseOptions.htmlTables = true\n if (opts.tableFormat === \"gfm\") parseOptions.tableFormat = \"gfm\"\n if (opts.keepLayoutTables) parseOptions.layoutTables = \"keep\"\n if (!opts.silent) {\n parseOptions.onProgress = (current: number, total: number) => {\n process.stderr.write(`\\r[kordoc] ${filePrefix}${fileName} (${format}) [${current}/${total}]`)\n }\n }\n const result = await parse(arrayBuffer, parseOptions)\n detectedFormat = result.fileType // ZIP 세분화(xlsx·docx) 반영 — 실패 JSON 의 fileType\n\n if (!result.success) {\n process.stderr.write(` FAIL\\n`)\n process.stderr.write(` → ${result.error}\\n`)\n // 실패는 모든 --format 에서 stdout 에 동일한 실패 JSON(success:false + code)을 낸다(#69)\n // — 호출자가 원인 코드(ENCRYPTED 등)로 분기할 수 있는 기계 계약. 성공 출력과 충돌하지\n // 않는다: markdown 성공은 마크다운, chunks 성공은 JSON 배열이고 실패는 객체 + exit 1.\n // stderr 의 FAIL 문구는 사람용으로 그대로 둔다.\n writeOutput(JSON.stringify({ ...result, file: fileName }, null, 2) + \"\\n\")\n failed = true\n continue\n }\n\n if (!opts.silent) process.stderr.write(` OK\\n`)\n\n let markdown = result.markdown\n // 이미지 인라인은 HWP5 경로에서만 실제로 일어난다(parser.ts). 그 외 포맷(HWPX/DOCX 등)은\n // --inline-images 를 줘도 인라인되지 않으므로, 이미지 저장/경로접두사를 생략하면 참조가\n // 깨지고(dangling) 바이트가 유실된다 → 실제 인라인된 경우에만 생략한다.\n const imagesInlined = opts.inlineImages && result.fileType === \"hwp\"\n // 그림을 파일로 저장하는 실행(--out-dir 또는 단일 파일 --output, 아래 saveImages)이면 이미지 참조 경로에 images/ 접두사 추가\n // (인라인 모드에선 이미지가 마크다운에 임베드되므로 건너뜀). 종전엔 --out-dir 만 봐서 -o 결과의 그림 링크가 전부 깨졌다(#94).\n // <img src> 는 병합/중첩 표 셀 경로(table/builder.ts) — 마크다운 문법과 함께 둘 다 바꿔야 참조가 안 깨진다\n const savesImageFiles = Boolean(opts.outDir || (opts.output && files.length === 1))\n // 그림은 문서마다 images/<문서 이름>/ 에 — 같은 폴더로 여러 문서를 변환하면 image_001.png 가 서로 덮어써졌다(#98).\n // 문서 이름은 출력 파일 이름(-o) 또는 입력 파일 이름(-d)에서 확장자를 뺀 것. 링크에서는 공백·괄호만 퍼센트 인코딩한다\n const docStem = (opts.output && files.length === 1 ? basename(opts.output) : fileName).replace(/\\.[^.]+$/, \"\")\n const imgLink = `images/${docStem.replace(/[ ()]/g, ch => encodeURIComponent(ch))}/`\n const linkImages = (text: string): string => savesImageFiles && result.images?.length && !imagesInlined\n ? text.replace(/!\\[image\\]\\(image_/g, `![image](${imgLink}image_`).replace(/(<img\\b[^>]*\\bsrc=\")image_/g, `$1${imgLink}image_`)\n : text\n markdown = linkImages(markdown)\n // json 직렬화 — refsOnly면 이미지 바이트를 빼고 저장 경로만 남긴다.\n // 이미지가 수백 장인 문서는 base64 총량이 V8 문자열 한계를 넘어 RangeError 로\n // 터졌고, 그 예외가 성공 로그 뒤 비-JSON 출력이 되어 파이프라인이 깨졌다 (#65).\n const serializeJson = (refsOnly: boolean): string => {\n const payload = refsOnly && result.images?.length\n ? { ...result, images: result.images.map(img => ({ filename: img.filename, mimeType: img.mimeType, path: `images/${docStem}/${img.filename}` })) }\n : result\n return JSON.stringify(payload, (_key, value) =>\n value instanceof Uint8Array ? Buffer.from(value).toString(\"base64\") : value\n , 2)\n }\n let output: string\n if (opts.format === \"json\") {\n const savesImages = Boolean((opts.output && files.length === 1) || opts.outDir) && !imagesInlined\n try {\n output = serializeJson(Boolean(opts.imageRefs) && savesImages)\n } catch (err) {\n // 한계 초과 — 이미지를 어차피 파일로 저장하는 실행이면 참조 모드로 자동 강등한다.\n // 저장 위치가 없으면(stdout) 구제할 방법이 없으므로 실패 JSON 계약으로 넘긴다.\n if (!savesImages || !result.images?.length) throw err\n output = serializeJson(true)\n process.stderr.write(` ⚠️ 이미지 base64 인라인이 직렬화 한계를 넘어 파일 참조로 대체했습니다 (${result.images.length}개 → images/${docStem}/)\\n`)\n }\n } else if (opts.format === \"chunks\") {\n // 청크 글에도 본문 마크다운과 같은 후처리(평문·HTML 표·그림 경로) — 종전엔 IR 에서 바로 만들어 --plain·--html-tables 를 무시했다\n const { blocksToChunks } = await import(\"../chunks.js\")\n const chunks = blocksToChunks(result.blocks, { tableFormat: parseOptions.tableFormat }).map(c => {\n let text = c.text\n if (opts.plain) text = toPlainMarkdown(text)\n if (opts.htmlTables) text = toHtmlTables(text)\n return { ...c, text: linkImages(text) }\n })\n output = JSON.stringify(chunks, null, 2)\n } else {\n output = markdown\n }\n\n // 이미지 저장 (--out-dir 또는 --output 시) — 실제 인라인된 경우(HWP5)에만 미저장, 그 외엔 저장 유지\n const saveImages = (dir: string) => {\n if (!result.images?.length || imagesInlined) return\n const imgDir = resolve(dir, \"images\", docStem)\n mkdirSync(imgDir, { recursive: true })\n for (const img of result.images) {\n writeFileSync(resolve(imgDir, img.filename), img.data)\n }\n // images/<문서 이름>/manifest.json — 소비자가 확장자·매직바이트 추측 없이 형식 분기(#70).\n // mimeType 은 매직바이트 실측 우선 — 확장자 유래 선언값은 실데이터와 어긋날 수 있다.\n const manifest = result.images.map(img => ({\n name: img.filename,\n mimeType: detectImageMime(img.data) ?? img.mimeType,\n bytes: img.data.length,\n ...(img.source ? { source: img.source } : {}),\n }))\n writeFileSync(resolve(imgDir, \"manifest.json\"), JSON.stringify(manifest, null, 2), \"utf-8\")\n if (!opts.silent) process.stderr.write(` → ${result.images.length}개 이미지 → ${imgDir} (manifest.json 포함)\\n`)\n }\n\n // Validate the document and all image destinations together, before any file is written.\n const assertSafeDestination = (output: string, dir: string) => {\n const imageOutputs = result.images?.length && !imagesInlined\n ? [...result.images.map(img => resolve(dir, \"images\", docStem, img.filename)), resolve(dir, \"images\", docStem, \"manifest.json\")]\n : []\n assertSafeOutputs([output, ...imageOutputs])\n }\n\n if (opts.output && files.length === 1) {\n assertSafeDestination(opts.output, resolve(opts.output, \"..\"))\n writeFileSync(opts.output, output, \"utf-8\")\n if (!opts.silent) process.stderr.write(` → ${opts.output}\\n`)\n saveImages(resolve(opts.output, \"..\"))\n } else if (opts.outDir) {\n mkdirSync(opts.outDir, { recursive: true })\n const outExt = opts.format === \"json\" ? \".json\" : opts.format === \"chunks\" ? \".chunks.json\" : \".md\"\n // 확장자 없는 입력(\"slides\")도 이름 뒤에 붙인다 — 종전 replace 는 그대로 두어 -d 가 입력 폴더면 입력 파일을 덮어썼다\n const outPath = resolve(opts.outDir, fileName.replace(/\\.[^.]+$/, \"\") + outExt)\n assertSafeDestination(outPath, opts.outDir)\n writeFileSync(outPath, output, \"utf-8\")\n if (!opts.silent) process.stderr.write(` → ${outPath}\\n`)\n saveImages(opts.outDir)\n } else {\n writeOutput(output + \"\\n\")\n }\n } catch (err) {\n process.stderr.write(`\\n[kordoc] ERROR: ${fileName} — ${sanitizeError(err)}\\n`)\n // 파싱 이후(출력·직렬화) 단계에서 터져도 실패 JSON 을 내야 호출자가 원인 코드로\n // 분기할 수 있다 — 종전엔 성공 로그 뒤 비-JSON 이었다 (#65). json 외 포맷에도\n // 동일 계약을 적용한다 (#69).\n writeOutput(JSON.stringify({\n success: false,\n fileType: detectedFormat,\n // 다중 입력에서 어느 파일이 실패했는지 호출자가 기계적으로 특정할 수 있게 한다 (#69).\n // basename 만 노출 — 전체 경로는 내부 정보로 보아 넣지 않는다.\n file: fileName,\n error: sanitizeError(err),\n code: classifyError(err),\n }, null, 2) + \"\\n\")\n failed = true\n }\n }\n return !failed\n}\n","/** Protect every batch input, including symlink and hardlink aliases, before writing output. */\nimport { statSync } from \"node:fs\"\nimport { basename, resolve } from \"node:path\"\n\nexport function createOutputGuard(inputs: string[]): (outputs: string[]) => void {\n const paths = new Map(inputs.map(input => [resolve(input), basename(input)]))\n const identities = new Map<string, string>()\n for (const [input, name] of paths) {\n try {\n const stat = statSync(input, { bigint: true })\n identities.set(`${stat.dev}:${stat.ino}`, name)\n } catch { /* Missing or unreadable inputs are reported by the normal conversion path. */ }\n }\n return outputs => {\n for (const output of outputs) {\n let input = paths.get(resolve(output))\n if (!input) {\n try {\n const stat = statSync(output, { bigint: true })\n input = identities.get(`${stat.dev}:${stat.ino}`)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\" && (err as NodeJS.ErrnoException).code !== \"ENOTDIR\") throw err\n }\n }\n if (input) throw new Error(`출력 경로가 입력 파일과 같습니다: ${input}`)\n }\n }\n}\n","/** Bounded, persistent process pool: CPU-heavy parsers get separate JS runtimes. */\nimport { fork, type ChildProcess } from \"node:child_process\"\nimport { basename } from \"node:path\"\nimport type { Command, OptionValues } from \"commander\"\nimport { KordocError } from \"../utils.js\"\nimport { convertFiles } from \"./convert.js\"\nimport { createOutputGuard } from \"./output-path.js\"\n\ninterface Job { file: string; opts: OptionValues; inputs?: string[] }\ninterface Done { ok: boolean; output: string[] }\n\nexport function registerBatchWorker(program: Command): void {\n program.command(\"__convert-worker\", { hidden: true }).action(() => {\n if (!process.send) program.error(\"Internal command requires an IPC channel\")\n // Do not leave native parser handles alive if the parent disappears.\n process.on(\"disconnect\", () => process.exit(0))\n let assertSafeOutputs: ReturnType<typeof createOutputGuard> | undefined\n process.on(\"message\", async ({ file, opts, inputs }: Job) => {\n const output: string[] = []\n assertSafeOutputs ??= createOutputGuard(inputs ?? [file])\n const ok = await convertFiles([file], opts, text => { output.push(text) }, assertSafeOutputs)\n process.send!({ ok, output } satisfies Done)\n })\n })\n}\n\n/**\n * Both converted documents and image directories are named after the input stem. Reject ambiguous\n * destinations before anything is written, including case variants — sequential `-d` runs used to\n * overwrite `a.md` and mix `images/a/` silently when two inputs shared a stem.\n */\nexport function assertDistinctStems(files: string[]): void {\n const stems = new Set<string>()\n for (const file of files) {\n const stem = basename(file).replace(/\\.[^.]+$/, \"\").normalize(\"NFC\").toLowerCase()\n if (stems.has(stem)) throw new KordocError(`Output name collision: ${basename(file)}; use distinct file stems`)\n stems.add(stem)\n }\n}\n\nexport async function convertParallel(files: string[], opts: OptionValues, jobs: number): Promise<boolean> {\n assertDistinctStems(files)\n\n const workers: ChildProcess[] = []\n let next = 0\n let failed = false\n const stop = () => { for (const worker of workers) worker.kill() }\n const onSigint = () => { stop(); process.exit(130) }\n const onSigterm = () => { stop(); process.exit(143) }\n process.once(\"SIGINT\", onSigint)\n process.once(\"SIGTERM\", onSigterm)\n try {\n await Promise.all(Array.from({ length: Math.min(jobs, files.length) }, () => new Promise<void>((resolve, reject) => {\n // Fork the same entry point: works in the bundled CLI and under tsx in tests.\n // Options travel over IPC so passwords never appear in child command lines.\n const worker = fork(process.argv[1], [\"__convert-worker\"], { stdio: [\"ignore\", \"ignore\", \"inherit\", \"ipc\"] })\n workers.push(worker)\n let current: string | undefined\n let finished = false\n let firstJob = true\n worker.on(\"error\", reject)\n worker.on(\"exit\", (code, signal) => {\n if (!finished) reject(new KordocError(`Conversion worker exited (${signal ?? code}) while processing ${basename(current ?? \"unknown\")}`))\n })\n const dispatch = () => {\n if (next === files.length) {\n finished = true\n worker.disconnect()\n resolve()\n return\n }\n current = files[next++]\n if (!opts.silent) process.stderr.write(`[kordoc] [${next}/${files.length}] ${basename(current)} ...\\n`)\n // Each worker writes a separate output tree; successful document data stays\n // in the worker, avoiding large IPC copies and buffering the entire batch.\n worker.send({ file: current, opts: { ...opts, output: undefined, silent: true }, ...(firstJob ? { inputs: files } : {}) } satisfies Job, err => {\n if (err) reject(err)\n })\n firstJob = false\n }\n worker.on(\"message\", ({ ok, output }: Done) => {\n if (!ok) failed = true\n // Only the parent writes stdout, preserving each failure JSON as one unit.\n for (const text of output) process.stdout.write(text)\n if (!opts.silent) process.stderr.write(`[kordoc] ${basename(current!)} ${ok ? \"OK\" : \"FAIL\"}\\n`)\n dispatch()\n })\n dispatch()\n })))\n return !failed\n } finally {\n stop()\n process.removeListener(\"SIGINT\", onSigint)\n process.removeListener(\"SIGTERM\", onSigterm)\n }\n}\n","/** kordoc CLI 명령 — 문서 처리 — watch·fill·seal·patch·validate */\n\nimport { readFileSync, writeFileSync, mkdirSync, statSync } from \"fs\"\nimport { basename, dirname, resolve, extname } from \"path\"\nimport { Command } from \"commander\"\nimport { parse, detectFormat, detectZipFormat, fillFormFields, extractFormFields, blocksToMarkdown, markdownToHwpx, fillHwpx, fillWithUniqueGuard, PRESET_ALIAS, extractClickHereFields, BUILTIN_TEMPLATES, resolveBuiltinTemplate, readBuiltinTemplate } from \"../index.js\"\nimport type { FillInput } from \"../index.js\"\nimport { fillPlan } from \"../form/match.js\"\nimport { toArrayBuffer, sanitizeError } from \"../utils.js\"\n\n\nexport function registerDocCommands(program: Command): void {\n program\n .command(\"watch <dir>\")\n .description(\"디렉토리 감시 — 새 문서 자동 변환\")\n .option(\"--webhook <url>\", \"결과 전송 웹훅 URL\")\n .option(\"-d, --out-dir <dir>\", \"변환 결과 출력 디렉토리\")\n .option(\"-p, --pages <range>\", \"페이지/섹션 범위\")\n .option(\"--format <type>\", \"출력 형식: markdown 또는 json\", \"markdown\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (dir: string, opts, command: Command) => {\n // 루트 커맨드의 동명 옵션(-d/--out-dir·-p/--pages·--format·--silent)이 서브커맨드 뒤에서도 루트로 흡수되는 commander 동작 보완\n const rootOpts = program.opts()\n opts.outDir ??= rootOpts.outDir\n opts.pages ??= rootOpts.pages\n opts.silent ??= rootOpts.silent\n if (command.getOptionValueSource(\"format\") === \"default\" && program.getOptionValueSource(\"format\") === \"cli\") {\n opts.format = rootOpts.format\n }\n const { watchDirectory } = await import(\"../watch.js\")\n await watchDirectory({\n dir,\n outDir: opts.outDir,\n webhook: opts.webhook,\n format: opts.format,\n pages: opts.pages,\n silent: opts.silent,\n })\n })\n\n program\n .command(\"fill [file]\")\n .description(\"서식 문서의 빈칸을 채워서 출력 — kordoc fill 신청서.hwpx -f '성명=홍길동,전화=010-1234-5678' -o 결과.hwpx / 내장 기안문 서식은 kordoc fill --template gian\")\n .option(\"-f, --fields <pairs>\", \"채울 필드 (key=value 쉼표 구분 또는 JSON)\")\n .option(\"-j, --json <path>\", \"채울 필드 JSON 파일 경로\")\n .option(\"-o, --output <path>\", \"출력 파일 경로 (확장자로 포맷 결정: .md, .hwpx)\")\n .option(\"--format <type>\", \"출력 포맷: hwpx-preserve (기본, 원본 스타일 보존), hwpx, markdown\", \"hwpx-preserve\")\n .option(\"--formats <json>\", \"필드별 값 서식 JSON (라벨→포맷) — 예: '{\\\"날짜\\\":\\\"yy.mm.dd\\\",\\\"주민등록번호\\\":\\\"rrn:masked\\\"}'\")\n .option(\"--template <name>\", \"내장 표준 서식 사용 (파일 경로 불필요): gian(일반기안문) | gian-simple(간이기안문). 위치 인자 'templates:일반기안문' 표기도 동일\")\n .option(\"--list-templates\", \"내장 표준 서식 목록 + 누름틀 필드 나열\")\n .option(\"--require-unique\", \"한 키가 서식의 2곳 이상에 매칭되면 채우지 않고 거부 (반복 라벨 양식 오염 방지)\")\n .option(\"--mask\", \"채운 값 미노출 — 출력 파일 없이 markdown을 stdout으로 낼 때 본문 대신 안내만 표시\")\n .option(\"--dry-run\", \"채우지 않고 서식 필드 목록만 출력 — -j/-f 를 함께 주면 키·배열 번호별로 값을 쓸 칸(표·행·열)을 JSON 으로\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string | undefined, opts, command: Command) => {\n try {\n // 루트 커맨드의 동명 옵션(-o/--output·--format·--silent)이 서브커맨드 뒤에서도 루트로 흡수되는 commander 동작 보완\n const rootOpts = program.opts()\n opts.output ??= rootOpts.output\n opts.silent ??= rootOpts.silent\n if (command.getOptionValueSource(\"format\") === \"default\" && program.getOptionValueSource(\"format\") === \"cli\") {\n opts.format = rootOpts.format\n }\n\n if (![\"hwpx-preserve\", \"hwpx\", \"markdown\"].includes(opts.format)) {\n process.stderr.write(`[kordoc] --format 는 hwpx-preserve/hwpx/markdown 중 하나여야 합니다: ${opts.format}\\n`)\n process.exit(1)\n }\n\n // --list-templates: 내장 서식 목록 + 누름틀 필드\n if (opts.listTemplates) {\n const list = []\n for (const t of BUILTIN_TEMPLATES) {\n const fields = await extractClickHereFields(readBuiltinTemplate(t))\n list.push({ id: t.id, aliases: t.aliases, title: t.title, fields: fields.map(f => f.name) })\n }\n process.stdout.write(JSON.stringify(list, null, 2) + \"\\n\")\n return\n }\n\n // 입력 소스 결정 — 내장 템플릿(--template 또는 'templates:이름' 위치 인자) 우선\n const templateName = opts.template ?? (file && /^templates?:/i.test(file) ? file : undefined)\n let arrayBuffer: ArrayBuffer\n let inputName: string\n if (templateName) {\n const t = resolveBuiltinTemplate(templateName)\n if (!t) {\n process.stderr.write(`[kordoc] 알 수 없는 내장 템플릿: ${templateName} (사용 가능: ${BUILTIN_TEMPLATES.map(x => `${x.id}(${x.aliases[0]})`).join(\", \")})\\n`)\n process.exit(1)\n }\n arrayBuffer = readBuiltinTemplate(t)\n inputName = t.file\n } else if (file) {\n const absPath = resolve(file)\n const fileSize = statSync(absPath).size\n if (fileSize > 500 * 1024 * 1024) {\n process.stderr.write(`[kordoc] 파일이 너무 큽니다 (${(fileSize / 1024 / 1024).toFixed(1)}MB)\\n`)\n process.exit(1)\n }\n arrayBuffer = toArrayBuffer(readFileSync(absPath))\n inputName = basename(absPath)\n } else {\n process.stderr.write(`[kordoc] 서식 파일 경로 또는 --template 을 지정해주세요 (목록: kordoc fill --list-templates)\\n`)\n process.exit(1)\n return\n }\n\n if (!opts.silent) process.stderr.write(`[kordoc] ${inputName} 파싱 중...\\n`)\n\n // --dry-run: 필드 목록만 출력 — 서식 입력란(빈 후행 열)이 목록에 나오도록 보존 (#47). 값을 함께 주면 아래에서 대상 칸을 낸다\n if (opts.dryRun && !opts.json && !opts.fields) {\n const result = await parse(arrayBuffer, { keepTrailingEmptyCols: true, layoutTables: \"keep\" })\n if (!result.success) {\n process.stderr.write(`[kordoc] 파싱 실패: ${result.error}\\n`)\n process.exit(1)\n }\n const formInfo = extractFormFields(result.blocks)\n // 누름틀(CLICK_HERE) 필드도 함께 나열 — 표준 서식은 라벨 표 없이 누름틀만 있을 수 있다\n const clickHereFields = detectFormat(arrayBuffer) === \"hwpx\"\n ? await extractClickHereFields(arrayBuffer)\n : []\n if (formInfo.fields.length === 0 && clickHereFields.length === 0) {\n process.stderr.write(`[kordoc] 서식 필드를 찾을 수 없습니다.\\n`)\n process.exit(1)\n }\n process.stdout.write(JSON.stringify(\n clickHereFields.length > 0 ? { ...formInfo, clickHereFields } : formInfo,\n null, 2,\n ) + \"\\n\")\n return\n }\n\n // 필드 값 파싱\n let values: Record<string, string> = {}\n if (opts.json) {\n const jsonPath = resolve(opts.json)\n // Windows 메모장·PowerShell 이 붙이는 UTF-8 BOM 은 JSON.parse 가 거부한다\n const jsonContent = readFileSync(jsonPath, \"utf-8\").replace(/^/, \"\")\n values = JSON.parse(jsonContent)\n } else if (opts.fields) {\n const fieldsStr: string = opts.fields\n if (fieldsStr.startsWith(\"{\")) {\n values = JSON.parse(fieldsStr)\n } else {\n // \"key1=value1,key2=value2\" 파싱 — 값에 쉼표가 있을 수 있으므로\n // '=' 앞의 키를 기준으로 분리 (쉼표+한글/영문+= 패턴)\n const pairs = fieldsStr.split(/,(?=[가-힣A-Za-z][가-힣A-Za-z\\s]*=)/)\n for (const pair of pairs) {\n const eqIdx = pair.indexOf(\"=\")\n if (eqIdx > 0) {\n const key = pair.slice(0, eqIdx).trim()\n const val = pair.slice(eqIdx + 1).trim()\n values[key] = val\n }\n }\n }\n } else {\n process.stderr.write(`[kordoc] 채울 필드를 지정해주세요 (-f 또는 -j 옵션)\\n`)\n process.exit(1)\n }\n\n // 필드별 값 서식 결합 — MCP fill_form(formats)과 동일 의미론 (form/match.js FillInput)\n let inputs: Record<string, FillInput> = values\n if (opts.formats) {\n let formatMap: Record<string, string>\n try {\n formatMap = JSON.parse(String(opts.formats))\n } catch {\n process.stderr.write(`[kordoc] --formats 는 JSON 객체여야 합니다 (라벨→포맷)\\n`)\n process.exit(1)\n }\n inputs = Object.fromEntries(Object.entries(values).map(([k, v]) => {\n const format = formatMap[k]\n return [k, format ? { value: v, format } : v]\n }))\n }\n\n // 출력 포맷 결정 — 확장자 오버라이드가 명시 --format 과 충돌하면 경고 후 확장자 우선\n let outputFormat = opts.format as string\n if (opts.output) {\n const ext = extname(opts.output).toLowerCase()\n const explicitFormat = command.getOptionValueSource(\"format\") === \"cli\" || program.getOptionValueSource(\"format\") === \"cli\"\n const before = outputFormat\n if (ext === \".hwpx\") outputFormat = outputFormat === \"markdown\" ? \"hwpx-preserve\" : outputFormat\n else if (ext === \".md\") outputFormat = \"markdown\"\n if (explicitFormat && before !== outputFormat) {\n process.stderr.write(`[kordoc] ⚠️ --format ${before} 가 출력 확장자(${ext})와 충돌합니다 — 확장자 기준 ${outputFormat} 로 진행\\n`)\n }\n }\n\n // ─── hwpx-preserve: 원본 ZIP 직접 수정 ───\n if (outputFormat === \"hwpx-preserve\") {\n const format = detectFormat(arrayBuffer)\n let isHwpx = format === \"hwpx\"\n if (isHwpx) {\n const zipFormat = await detectZipFormat(arrayBuffer)\n isHwpx = zipFormat === \"hwpx\"\n }\n if (!isHwpx) {\n if (!opts.silent) process.stderr.write(`[kordoc] HWPX가 아니므로 hwpx 모드로 전환합니다\\n`)\n outputFormat = \"hwpx\"\n } else {\n const hwpxResult = opts.requireUnique\n ? await fillWithUniqueGuard(inputs, (vals, blocked) => fillHwpx(arrayBuffer, vals, blocked))\n : { ...(await fillHwpx(arrayBuffer, inputs)), rejected: [] as string[] }\n if (opts.dryRun) {\n process.stdout.write(JSON.stringify(fillPlan(inputs, hwpxResult.filled, hwpxResult.unmatched, hwpxResult.rejected), null, 2) + \"\\n\")\n return\n }\n if (!opts.silent) {\n process.stderr.write(`[kordoc] ${hwpxResult.filled.length}개 필드 채움 (원본 스타일 보존)\\n`)\n if (hwpxResult.rejected.length > 0) {\n process.stderr.write(`[kordoc] ⚠️ 모호 라벨 거부(2곳+ 매칭): ${hwpxResult.rejected.join(\", \")}\\n`)\n }\n if (hwpxResult.unmatched.length > 0) {\n process.stderr.write(`[kordoc] ⚠️ 매칭 실패: ${hwpxResult.unmatched.join(\", \")}\\n`)\n }\n }\n if (opts.output) {\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\n writeFileSync(resolve(opts.output), Buffer.from(hwpxResult.buffer))\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\n } else {\n process.stdout.write(Buffer.from(hwpxResult.buffer))\n }\n return\n }\n }\n\n // ─── 일반 경로: parse → fill → output ─── (양식 입력란 보존, #47)\n const result = await parse(arrayBuffer, { keepTrailingEmptyCols: true, layoutTables: \"keep\" })\n if (!result.success) {\n process.stderr.write(`[kordoc] 파싱 실패: ${result.error}\\n`)\n process.exit(1)\n }\n\n const formInfo = extractFormFields(result.blocks)\n if (!opts.silent) {\n process.stderr.write(`[kordoc] 서식 필드 ${formInfo.fields.length}개 감지 (확신도 ${(formInfo.confidence * 100).toFixed(0)}%)\\n`)\n }\n\n const fillResult = opts.requireUnique\n ? await fillWithUniqueGuard(inputs, (vals, blocked) => fillFormFields(result.blocks, vals, blocked))\n : { ...fillFormFields(result.blocks, inputs), rejected: [] as string[] }\n if (opts.dryRun) {\n process.stdout.write(JSON.stringify(fillPlan(inputs, fillResult.filled, fillResult.unmatched, fillResult.rejected), null, 2) + \"\\n\")\n return\n }\n if (!opts.silent) {\n process.stderr.write(`[kordoc] ${fillResult.filled.length}개 필드 채움\\n`)\n if (fillResult.rejected.length > 0) {\n process.stderr.write(`[kordoc] ⚠️ 모호 라벨 거부(2곳+ 매칭): ${fillResult.rejected.join(\", \")}\\n`)\n }\n if (fillResult.unmatched.length > 0) {\n process.stderr.write(`[kordoc] ⚠️ 매칭 실패: ${fillResult.unmatched.join(\", \")}\\n`)\n }\n }\n\n const markdown = blocksToMarkdown(fillResult.blocks)\n\n if (outputFormat === \"hwpx\") {\n const hwpxBuffer = await markdownToHwpx(markdown)\n if (opts.output) {\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\n writeFileSync(resolve(opts.output), Buffer.from(hwpxBuffer))\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\n } else {\n process.stdout.write(Buffer.from(hwpxBuffer))\n }\n } else {\n if (opts.output) {\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\n writeFileSync(resolve(opts.output), markdown, \"utf-8\")\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\n } else if (opts.mask) {\n // 채운 값(주민번호·연락처 등)이 터미널 로그에 남지 않게 본문 대신 안내 (MCP mask_values와 동일 취지)\n process.stdout.write(`⚠️ --mask 활성 — 개인정보 노출 방지를 위해 본문을 출력하지 않습니다. -o 로 파일 저장 후 확인하세요.\\n`)\n } else {\n process.stdout.write(markdown + \"\\n\")\n }\n }\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"seal <file>\")\n .description('도장/서명 이미지를 앵커 문구 위에 부유 배치 (표/페이지 불확장) — kordoc seal 신청서.hwpx --image 도장.png --anchor \"(인)\" -o 결과.hwpx')\n .requiredOption(\"--image <path>\", \"도장/서명 이미지 (투명 배경 PNG 권장)\")\n .option(\"--anchor <text>\", \"앵커 문구\", \"(인)\")\n .option(\"-n, --occurrence <num>\", \"같은 앵커가 여럿일 때 0-based 선택\", \"0\")\n .option(\"--size-mm <num>\", \"도장 한 변 크기 mm (기본: 줄높이×1.6, 7~18 클램프)\")\n .option(\"--mode <mode>\", \"overlap(문구 위 겹침) | right(오른쪽 옆) | auto\", \"auto\")\n .option(\"--dx <mm>\", \"x 미세조정 mm\", \"0\")\n .option(\"--dy <mm>\", \"y 미세조정 mm\", \"0\")\n .option(\"-o, --output <path>\", \"출력 경로 (기본: <입력>.sealed.hwpx)\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const { placeSealHwpx, detectFormat } = await import(\"../index.js\")\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const silent: boolean = opts.silent ?? rootOpts.silent\n const mode = String(opts.mode).toLowerCase()\n if (![\"overlap\", \"right\", \"auto\"].includes(mode)) {\n process.stderr.write(`[kordoc] --mode 는 overlap/right/auto 중 하나여야 합니다\\n`)\n process.exit(1)\n }\n const buf = new Uint8Array(readFileSync(resolve(file)))\n if (detectFormat(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer) !== \"hwpx\") {\n process.stderr.write(`[kordoc] seal 은 HWPX 전용입니다 (HWP 5.x 바이너리는 미지원)\\n`)\n process.exit(1)\n }\n const imgPath = resolve(opts.image)\n const imgSize = statSync(imgPath).size\n if (imgSize > 500 * 1024 * 1024) {\n process.stderr.write(`[kordoc] 도장 이미지가 너무 큽니다 (${(imgSize / 1024 / 1024).toFixed(0)}MB)\\n`)\n process.exit(1)\n }\n const image = new Uint8Array(readFileSync(imgPath))\n const ext = extname(opts.image).slice(1).toLowerCase() || \"png\"\n // 숫자 플래그 엄격 검증 — 비숫자가 NaN→0 무증상 강제, 음수 occurrence가 truthy로\n // 통과하던 것 차단 (MCP zod와 동등, v4.0.6: --size-mm만 검증하던 것을 전 숫자 플래그로)\n const parseNum = (flag: string, raw: unknown, { min, allowNeg = false }: { min?: number; allowNeg?: boolean } = {}): number => {\n const n = Number(raw)\n if (!Number.isFinite(n) || (!allowNeg && n < 0) || (min !== undefined && n < min)) {\n process.stderr.write(`[kordoc] ${flag} 값이 잘못됐습니다: ${raw}${allowNeg ? \"\" : \" (0 이상 숫자)\"}\\n`)\n process.exit(1)\n }\n return n\n }\n let sizeMm: number | undefined\n if (opts.sizeMm != null) {\n const n = Number(opts.sizeMm)\n if (!Number.isFinite(n) || n <= 0) {\n process.stderr.write(`[kordoc] --size-mm 은 양수여야 합니다: ${opts.sizeMm}\\n`)\n process.exit(1)\n }\n sizeMm = n\n }\n const result = await placeSealHwpx(\n buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer,\n [{\n anchor: opts.anchor,\n occurrence: parseNum(\"--occurrence\", opts.occurrence),\n image,\n ext: ext as \"png\" | \"jpg\" | \"jpeg\" | \"bmp\" | \"gif\",\n sizeMm,\n mode: mode as \"overlap\" | \"right\" | \"auto\",\n dxMm: parseNum(\"--dx\", opts.dx, { allowNeg: true }),\n dyMm: parseNum(\"--dy\", opts.dy, { allowNeg: true }),\n }],\n )\n const outPath = resolve(output ?? file.replace(/\\.hwpx$/i, \"\") + \".sealed.hwpx\")\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, Buffer.from(result.buffer))\n if (!silent) {\n for (const p of result.placed) {\n process.stderr.write(`[kordoc] 도장 배치: \"${p.anchor}\" #${p.occurrence} → ${p.mode} (${p.posXMm}mm, ${p.posYMm}mm, ${p.sizeMm}mm) [${p.entry}]\\n`)\n for (const w of p.warnings ?? []) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n }\n process.stderr.write(`[kordoc] → ${outPath}\\n`)\n }\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"patch <original> <edited>\")\n .description(\"서식 보존 라운드트립 패치 — 편집된 마크다운을 원본 HWPX/HWP에 in-place 반영 (kordoc patch 원본.hwpx 편집.md -o 출력.hwpx). 견본 서식 그대로 새 문서 쓰기(서식 베끼기)도 이 경로: 견본을 --keep-layout-tables 로 읽어 내용만 새로 쓴 뒤 patch — HWPX 는 문단 추가·삭제를 같은 항목 부호 견본 문단 서식으로 반영. 미적용(skip) 편집이 있으면 exit 2\")\n .option(\"-o, --output <path>\", \"출력 경로 (기본: <원본>.patched.hwpx|.hwp)\")\n .option(\"--no-verify\", \"패치 후 재파싱 자동 검증 생략\")\n .option(\"--no-structure\", \"문단 추가·삭제를 반영하지 않고 건너뜀 (HWPX — 글 수정만, 문서 골격 고정)\")\n .option(\"--keep-lineseg\", \"글이 바뀐 문단의 줄 나눔 정보를 지우지 않고 원본 줄 위치를 남김 (HWP 5.x — 기본은 지워서 한컴이 다시 짬)\")\n .option(\"--json\", \"결과(적용 수·건너뛴 편집·검증 잔차)를 JSON 으로 stdout 출력 — --silent 와 함께 써도 나온다\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (original: string, edited: string, opts) => {\n try {\n const { patchHwpx, patchHwp, detectFormat } = await import(\"../index.js\")\n // 루트 커맨드의 동명 옵션(-o/--silent)이 서브커맨드 옵션을 가로채는 commander 동작 보완\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const silent: boolean = opts.silent ?? rootOpts.silent\n const originalBuf = new Uint8Array(readFileSync(resolve(original)))\n const editedMarkdown = readFileSync(resolve(edited), \"utf-8\")\n\n const format = detectFormat(originalBuf.buffer as ArrayBuffer)\n const result = format === \"hwp\"\n ? await patchHwp(originalBuf, editedMarkdown, { verify: opts.verify !== false, keepLineseg: opts.keepLineseg === true })\n : await patchHwpx(originalBuf, editedMarkdown, { verify: opts.verify !== false, structure: opts.structure !== false })\n if (!result.success || !result.data) {\n if (opts.json) process.stdout.write(JSON.stringify({ success: false, error: result.error ?? \"알 수 없는 오류\", applied: result.applied, skipped: result.skipped }, null, 2) + \"\\n\")\n process.stderr.write(`[kordoc] 패치 실패: ${result.error ?? \"알 수 없는 오류\"}\\n`)\n process.exit(1)\n }\n\n const ext = format === \"hwp\" ? \".hwp\" : \".hwpx\"\n const outPath = resolve(output ?? original.replace(/\\.hwpx?$/i, \"\") + \".patched\" + ext)\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, result.data)\n\n if (opts.json) {\n // 외부 도구가 부분 적용(skip)·검증 잔차를 사용자에게 알릴 수 있게 — --silent 로는 사유가 통째로 사라졌다\n process.stdout.write(JSON.stringify({\n success: true, output: outPath, applied: result.applied, skipped: result.skipped,\n ...(result.warnings ? { warnings: result.warnings } : {}),\n ...(result.verification ? { verification: result.verification.stats } : {}),\n }, null, 2) + \"\\n\")\n }\n if (!silent && !opts.json) {\n process.stderr.write(`[kordoc] ${result.applied}개 변경 적용 (원본 서식 보존) → ${outPath}\\n`)\n for (const s of result.skipped) {\n process.stderr.write(`[kordoc] ⚠️ SKIP: ${s.reason}${s.before ? ` | ${s.before}` : \"\"}\\n`)\n }\n for (const w of result.warnings ?? []) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n if (result.verification) {\n const v = result.verification.stats\n const residual = v.added + v.removed + v.modified\n process.stderr.write(residual === 0\n ? `[kordoc] ✓ 검증: 편집 마크다운과 재파싱 결과 완전 일치 (${v.unchanged}블록)\\n`\n : `[kordoc] ⚠️ 검증 잔차: 수정 ${v.modified}, 추가 ${v.added}, 삭제 ${v.removed} (미지원 변경은 skip 목록 참조)\\n`)\n }\n }\n if (result.skipped.length > 0) process.exitCode = 2\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"compare <a> <b>\")\n .description(\"두 문서 비교 — 추가·삭제·변경 블록 (HWP↔HWPX 등 형식이 달라도 됨, 신구대조표용). 차이가 있으면 exit 1\")\n .option(\"--json\", \"비교 결과(stats·diffs)를 JSON 으로 stdout 출력\")\n .action(async (a: string, b: string, opts) => {\n try {\n const { compare } = await import(\"../index.js\")\n const read = (p: string): ArrayBuffer => { const buf = readFileSync(resolve(p)); return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer }\n const result = await compare(read(a), read(b))\n const { stats, diffs } = result\n if (opts.json) process.stdout.write(JSON.stringify(result, null, 2) + \"\\n\")\n else {\n process.stdout.write(`추가 ${stats.added} · 삭제 ${stats.removed} · 변경 ${stats.modified} · 동일 ${stats.unchanged}\\n`)\n for (const d of diffs) {\n if (d.type === \"unchanged\") continue\n const mark = d.type === \"added\" ? \"+\" : d.type === \"removed\" ? \"-\" : \"~\"\n const text = (blk?: { text?: string; table?: unknown }) => (blk?.text ?? (blk?.table ? \"[표]\" : \"\")).replace(/\\s+/g, \" \").slice(0, 160)\n if (d.type === \"modified\") process.stdout.write(`~ ${text(d.before)}\\n → ${text(d.after)}\\n`)\n else process.stdout.write(`${mark} ${text(d.after ?? d.before)}\\n`)\n }\n }\n process.exit(stats.added + stats.removed + stats.modified > 0 ? 1 : 0)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(2)\n }\n })\n\n program\n .command(\"validate <file>\")\n .description(\"HWPX 구조 검증 — ZIP·mimetype·필수 파일·XML 웰폼드·secCnt·manifest 참조 (한컴독스 거부 요인 사전 차단)\")\n .option(\"--json\", \"결과를 JSON으로 stdout에 출력\")\n .action(async (file: string, opts) => {\n try {\n const { validateHwpx } = await import(\"../index.js\")\n const buf = new Uint8Array(readFileSync(resolve(file)))\n const result = await validateHwpx(buf)\n if (opts.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + \"\\n\")\n } else if (result.ok) {\n process.stderr.write(`[kordoc] ✓ 구조 검증 통과 (엔트리 ${result.entryCount}개): ${file}\\n`)\n } else {\n process.stderr.write(`[kordoc] ✗ 구조 문제 ${result.issues.length}건: ${file}\\n`)\n for (const i of result.issues) {\n process.stderr.write(`[kordoc] - ${i.path ? `${i.path}: ` : \"\"}${i.message}\\n`)\n }\n }\n if (!result.ok) process.exit(1)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n // 공문서 프리셋 별칭(한글/영문) → 내부 preset 키 — gongmun.ts와 공용(PRESET_ALIAS)\n}\n","/** kordoc CLI 명령 — 생성·검수 — generate·profile·lint·redact */\n\nimport { readFileSync, writeFileSync, mkdirSync, statSync } from \"fs\"\nimport { basename, dirname, resolve } from \"path\"\nimport type { numberBlocksFromIR } from \"../hwpx/number-lint.js\"\nimport { runLintSuite } from \"../hwpx/lint-suite.js\"\nimport { lintBlocks } from \"../hwpx/lint-blocks.js\"\nimport { extractLevelStyles } from \"../hwpx/level-styles.js\"\nimport { detectFormat, markdownToHwpx, hwpxToProfile, PRESET_ALIAS, unknownFontWarnings, incompatibleGongmunWarnings, gongmunLintWarnings, muncheLintWarnings, usesGaejosikMunche, slopLintWarnings, logicLintWarnings, usesLogicStructure, gongmunGate, formatGateFinding } from \"../index.js\"\nimport { parseFormatProfileJson } from \"../hwpx/profile-io.js\"\nimport { loadGenerationImages } from \"../shared/generate-images.js\"\nimport { buildGongmunOptions, BODY_FONTS, H2_MARKERS, BULLET2_CHARS, TOTAL_ROWS, parseLevelsSpec, levelFontRecord, templateConflictMessage } from \"../hwpx/gongmun-surface.js\"\nimport type { FormatProfile } from \"../hwpx/gen-profile.js\"\nimport { toArrayBuffer, sanitizeError } from \"../utils.js\"\nimport type { Command } from \"commander\"\n\n/** --template 과 함께 못 쓰는 옵션 (commander 키) — 서식·쪽·이미지는 견본이 정한다 */\nconst TEMPLATE_CLI_CONFLICTS = [\n \"preset\", \"font\", \"pt\", \"lineSpacing\", \"profile\", \"org\", \"date\", \"toc\", \"cover\", \"approval\", \"pageNumbers\", \"endMark\",\n \"bodyTitleBox\", \"chapterFit\", \"h2Marker\", \"bandColor\", \"bandTextColor\", \"summary\", \"docInfo\", \"dept\", \"checklist\", \"coverLabel\",\n \"fonts\", \"sizes\", \"levels\", \"levelsFrom\", \"bullet2\", \"agency\", \"suppressSingle\", \"docHead\", \"docFoot\", \"reportInfo\",\n \"noticeHead\", \"pressHead\", \"pressSub\", \"pressPeople\", \"plain\", \"paper\", \"landscape\", \"columns\", \"header\", \"footer\",\n \"imageDir\", \"inlineMath\",\n]\n\nexport function registerGenerateCommands(program: Command): void {\n program\n .command(\"generate <markdown>\")\n .alias(\"gen\")\n .description(\"마크다운 → 공문서 HWPX 생성 — kordoc generate 보고서.md -o 보고서.hwpx --preset 보고서 (markdown에 '-' 지정 시 stdin)\")\n .option(\"-o, --output <path>\", \"출력 HWPX 경로 (기본: <입력>.hwpx)\")\n .option(\"--preset <name>\", \"공문서 프리셋: 기안문(official)·보고서(report)·계획서(plan)·통지(notice)·회의록(minutes)·개조식(gaejosik — 표지·목차·장헤더 자동)·업무보고(ministry — 중앙부처 업무보고: 장 띠·절 숫자칸·소제목 박스·① 항목 띠·성과 요약박스·별첨 띠)·서울방침(bangchim — 서울시 방침서: 제목표·파랑 부제·요약박스·[Ⅰ] 장 상자·절 띠·❶ 과제)·보도자료(press)\", \"기안문\")\n .option(\"--font <type>\", \"본문 글꼴: myeongjo(함초롬바탕) 또는 gothic(맑은 고딕)\")\n .option(\"--pt <size>\", \"본문 글자 크기(pt)\")\n .option(\"--line-spacing <percent>\", \"본문 줄간격(%)\")\n .option(\"--profile <path>\", \"서식 프로필 JSON (kordoc profile로 추출) — 참조 문서의 표 테두리·음영·열폭·셀 글꼴 재현\")\n .option(\"--template <hwpx>\", \"부서 서식 견본 HWPX — 견본의 쪽 설정·글꼴·제목표·담당 줄·요약 상자·□○-·※ 문단·표·참고 띠 서식을 그대로 쓰고 내용만 마크다운으로 (프리셋·서식·쪽 옵션과 함께 못 씀)\")\n .option(\"--org <name>\", \"표지 기관명 (표지를 켜는 프리셋 공통)\")\n .option(\"--date <date>\", \"표지 날짜 (기본 오늘 — 'YYYY. M. D.')\")\n .option(\"--toc\", \"목차 페이지 강제 켜기 (개조식 외 프리셋에서도 h2 목록으로 생성)\")\n .option(\"--no-toc\", \"목차 페이지 끄기 (개조식 프리셋 기본 켜짐)\")\n .option(\"--cover\", \"표지 페이지 강제 켜기 (개조식 외 프리셋에서도 첫 h1을 표지로)\")\n .option(\"--no-cover\", \"표지 페이지 끄기 (개조식 프리셋 기본 켜짐)\")\n .option(\"--approval <labels>\", \"결재란 직위 라벨 (쉼표 구분, 예: 담당,팀장,과장) — 문서 최상단 우측\")\n .option(\"--page-numbers\", \"쪽번호 강제 켜기 (하단 중앙 '- 1 -')\")\n .option(\"--no-page-numbers\", \"쪽번호 끄기 (개조식·보고서·계획서 기본 켜짐)\")\n .option(\"--end-mark\", \"본문 끝 '끝.' 표시 강제 켜기\")\n .option(\"--no-end-mark\", \"'끝.' 표시 끄기 (기안문 기본 켜짐)\")\n .option(\"--no-body-title-box\", \"본문 첫 페이지 제목 반복 박스 끄기 (개조식+표지 기본 켜짐)\")\n .option(\"--chapter-fit\", \"개조식 장 헤더 제목 칸을 글자 폭에 맞춤 (기본: 본문 폭까지)\")\n .option(\"--h2-marker <type>\", \"h2 장 제목 표기: band(로마자 채움 칸 + 제목 띠 표 — 보고서·계획서 기본)·roman(Ⅰ. 텍스트)·number(1. — 통지 기본)·box(장 없이 □ 대항목)·none\")\n .option(\"--band-color <hex>\", \"띠 제목 번호칸 채움색 #RRGGBB (기본 #003366 — 실측 최다. 교육청형 밝은 띠: #DFE6F7)\")\n .option(\"--band-text-color <hex>\", \"띠 제목 번호 글자색 #RRGGBB (기본 #FFFFFF — 밝은 띠면 #000000)\")\n .option(\"--summary <text>\", \"요약 박스 — 보고서·계획서·개조식·서울방침 (제목표·개조식 본문 첫 쪽 제목 상자 아래 음영 상자 — 마크다운 제목 직후 인용문(>)으로도 지정)\")\n .option(\"--doc-info <spec>\", \"보고서 표지 문서정보표: docNum=스마트도시과-123,date=2026. 9. 6.,disclosure=공개,policyNo= (--cover와 함께)\")\n .option(\"--dept <name>\", \"표지 부서명 (기관명 아래 괄호)\")\n .option(\"--checklist [na]\", \"서울 사전 검토항목 점검표(보고서·계획서·서울방침) — 값 없으면 빈 서식, 해당없음 문항 번호를 주면(6,7,8) 나머지는 검토완료\")\n .option(\"--cover-label <text>\", \"표지 우상단 취급 표시 — '대외주의'·'비공개' 빨간 테두리 박스 (업무보고 프리셋 실측)\")\n .option(\"--fonts <spec>\", \"요소별 글꼴 오버라이드: body=나눔명조,heading=나눔고딕,ref=한양중고딕,table=맑은 고딕\")\n .option(\"--sizes <spec>\", \"개조식 요소별 크기(pt): dae=16,cham=13,table=12,coverTitle=30 …\")\n .option(\"--levels <spec>\", \"항목부호 단계별 위계 타이포: 0=HY견고딕/17/bold,1=한컴돋움/15/bold,2=휴먼명조/14 (depth 0~7, 숫자=pt·bold·plain·글꼴명)\")\n .option(\"--levels-from <hwpx>\", \"견본 HWPX 에서 항목부호 단계별 글꼴·크기·굵기를 배워 적용 (kordoc levels 와 같은 추출, --levels 로 준 단계가 우선)\")\n .option(\"--bullet2 <char>\", \"2단계 항목부호: ㅇ(이응 — 기안문·공고문 실측 지배)·○(원 — 보고서 양식)·◦·❍\")\n .option(\"--agency <name>\", \"기관 서식 — 중앙행정기관 이름(국세청·교육부 …) 또는 공통. 보도자료 2,670건 실측 단계 글꼴·크기·2단계 부호·표 머리·기관 색 (보고서·계획서·업무보고·개조식·보도자료)\")\n .option(\"--suppress-single\", \"단일 형제 항목 부호 생략 (편람 규정 — 기본은 하나여도 부호 부여)\")\n .option(\"--total-row <pos>\", \"표 합계·총계·계 행 위치: top(머리행 바로 아래, 기본 — 공문 실무 관행) | bottom | keep(원고 그대로)\")\n .option(\"--doc-head <spec>\", \"기안문 두문표: org=기관명,slogan=원훈,to=수신처,title=제목 (별지 제1호서식·서울 실결재 6행 표)\")\n .option(\"--doc-foot <spec>\", \"기안문 결문표: sender=발신명의,drafter=주무관 홍길동,reviewer=과장 김철수,approver=국장 박영희,cooperator=협조자,docNum=시행(과-번호 (날짜)),receive=접수,zip=우편번호,address=주소,site=홈페이지,phone=전화,fax=전송,email=메일,disclosure=공개구분\")\n .option(\"--report-info <text>\", \"보고서 담당자 행(제목표 아래) / 기안문 우상단 보고정보 행 — 예: '(2026. 7. 11., 과장 홍길동, ☎02-120)'\")\n .option(\"--notice-head <spec>\", \"공고문 두문·결문: no=공고 제2026-1호,date=2026년 7월 11일,sender=행정안전부장관\")\n .option(\"--press-head <spec>\", \"보도자료 머리: release=보도시점,distribute=배포일,dept=담당부서,manager=담당자,phone=연락처\")\n .option(\"--press-sub <items>\", \"보도자료 부제 (세미콜론 구분, 제목 아래 '- … -')\")\n .option(\"--press-people <items>\", \"보도자료 담당 표 사람별 행 — 구분/직급/이름/전화 를 세미콜론으로: '책임자/과장/이○○/044-000-0000;담당자/사무관/김○○/044-000-0001' (부서는 --press-head dept=)\")\n .option(\"--plain\", \"공문서 모드 끄기 (범용 마크다운 변환)\")\n .option(\"--paper <size>\", \"용지: A4·A3·B4·B5·Letter 또는 '210x297'(mm)\")\n .option(\"--landscape\", \"용지 가로 방향\")\n .option(\"--columns <n>\", \"다단 개수 (1~8)\")\n .option(\"--header <text>\", \"머리말 텍스트 (모든 쪽, 인라인 마크다운 허용)\")\n .option(\"--footer <text>\", \"꼬리말 텍스트\")\n .option(\"--image-dir <dir>\", \"마크다운 이미지 참조(![](x.png))를 이 디렉토리에서 읽어 실데이터 임베드\")\n .option(\"--inline-math\", \"본문·표 셀의 인라인 수식 $…$ 를 한글 수식 개체로 (기본: 글자 유지 — 가격 표기 $ 오인 방지)\")\n .option(\"--gate\", \"공문서 게이트 — 표기법·문체 error 와 윤문(AI 문체)·구성(논리 구조) 지적이 하나라도 있으면 파일을 만들지 않고 exit 1\")\n .option(\"--json\", \"결과를 JSON 한 줄로 stdout 출력 — {output, preset, bytes, warnings}\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (markdown: string, opts, cmd: Command) => {\n try {\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const silent: boolean = opts.silent ?? rootOpts.silent\n const plain: boolean = opts.plain ?? rootOpts.plain\n\n // 입력: '-' 이면 stdin, 아니면 파일\n let md: string\n let baseName = \"document\"\n if (markdown === \"-\") {\n md = readFileSync(0, \"utf-8\")\n } else {\n const inPath = resolve(markdown)\n md = readFileSync(inPath, \"utf-8\")\n baseName = basename(inPath).replace(/\\.(md|markdown|txt)$/i, \"\")\n }\n\n // 부서 서식 견본 — 서식은 견본이 정하므로 프리셋·서식·쪽 옵션과 함께 쓰면 조용히 버리지 않고 멈춘다\n if (opts.template) {\n const clash = TEMPLATE_CLI_CONFLICTS.filter((k) => cmd.getOptionValueSource(k) === \"cli\")\n // 루트에 준 --plain(kordoc --plain generate …)도 같은 충돌\n if (plain && !clash.includes(\"plain\")) clash.push(\"plain\")\n if (clash.length) {\n // --no-x 로 준 플래그는 값이 false — 사용자가 친 이름 그대로 알린다\n process.stderr.write(`[kordoc] ${templateConflictMessage(clash.map((k) => `--${opts[k] === false ? \"no-\" : \"\"}${k.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`))}\\n`)\n process.exit(1)\n }\n if (!silent) {\n for (const w of [...gongmunLintWarnings(md, 5), ...muncheLintWarnings(md, 5), ...(opts.gate ? [] : slopLintWarnings(md, 5))]) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n if (opts.gate) {\n const gate = gongmunGate(md, {})\n if (!gate.pass) {\n process.stderr.write(`[kordoc] 게이트 미통과 — ${gate.blocking.length}건을 고쳐 쓰고 다시 생성하세요 (파일 미생성)\\n`)\n for (const f of gate.blocking) process.stderr.write(` ${formatGateFinding(f)}\\n`)\n process.exit(1)\n }\n }\n const tplPath = resolve(String(opts.template))\n const warnings: string[] = []\n if (opts.totalRow !== undefined && !(TOTAL_ROWS as readonly string[]).includes(String(opts.totalRow))) {\n process.stderr.write(`[kordoc] --total-row 는 ${TOTAL_ROWS.join(\"/\")}\\n`)\n process.exit(1)\n }\n const buf = await markdownToHwpx(md, { template: readFileSync(tplPath), warnings, ...(opts.totalRow ? { totalRow: opts.totalRow } : {}) })\n if (!silent) for (const w of warnings) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n const outPath = resolve(output ?? (markdown === \"-\" ? `${baseName}.hwpx` : markdown.replace(/\\.(md|markdown|txt)$/i, \"\") + \".hwpx\"))\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, Buffer.from(buf))\n if (!silent) process.stderr.write(`[kordoc] HWPX 생성 (견본:${basename(tplPath)}) → ${outPath}\\n`)\n if (opts.json) process.stdout.write(JSON.stringify({ output: outPath, preset: null, template: tplPath, bytes: buf.byteLength, warnings }) + \"\\n\")\n return\n }\n\n // 공문서 옵션 구성 — 값 검증(열거)과 조립은 gongmun-surface SSOT, 여기는\n // commander 표면 사정(kv 파싱·--no-x 기본값)을 중립 입력으로 정돈하는 어댑터만\n let gongmun: import(\"../index.js\").GongmunOptions | undefined\n if (!plain) {\n const presetKey = String(opts.preset).trim()\n const preset = Object.hasOwn(PRESET_ALIAS, presetKey) ? PRESET_ALIAS[presetKey] : undefined\n if (!preset) {\n process.stderr.write(`[kordoc] 알 수 없는 프리셋: ${opts.preset} (기안문/보고서/계획서/통지/회의록/개조식/업무보고/서울방침/보도자료)\\n`)\n process.exit(1)\n }\n const enumCheck = <T extends readonly string[]>(flag: string, value: unknown, allowed: T): (typeof allowed)[number] | undefined => {\n if (value === undefined) return undefined\n if (!allowed.includes(String(value))) {\n process.stderr.write(`[kordoc] ${flag} 는 ${allowed.join(\"/\")}\\n`)\n process.exit(1)\n }\n return value as (typeof allowed)[number]\n }\n // 견본 HWPX 단계별 서식 — 대표값이 정해진 단계·속성만 (--levels 가 우선)\n let learnedLevels: Record<string, { font?: string; pt?: number; bold?: boolean }> | undefined\n if (opts.levelsFrom) {\n const learned = await extractLevelStyles(toArrayBuffer(readFileSync(resolve(String(opts.levelsFrom)))))\n learnedLevels = learned.levels\n if (!silent) process.stderr.write(learned.spec\n ? `[kordoc] 견본 단계별 서식: ${learned.spec}\\n`\n : `[kordoc] ⚠️ 견본에서 단계별 대표 서식을 정하지 못함 (단계마다 표본 3개 이상·한 값 60% 이상 필요) — 엔진 기본값 사용\\n`)\n }\n // \"key=value,key=value\" 스펙 파싱 — 값의 '='는 보존(첫 '='만 분리). 쉼표는\n // 구분자라 값에 못 들어감 — '=' 없는 조각(잘린 값의 꼬리 등)은 무증상 드랍\n // 대신 경고로 노출 (v4.0.6: 두문 title 값 유실이 조용히 지나가던 것 봉합)\n const parseKv = (spec: string, flag: string): Record<string, string> => {\n const out: Record<string, string> = {}\n for (const piece of spec.split(\",\")) {\n const p = piece.trim()\n if (!p) continue\n const eq = p.indexOf(\"=\")\n const key = eq > 0 ? p.slice(0, eq).trim() : \"\"\n const value = eq > 0 ? p.slice(eq + 1).trim() : \"\"\n if (!key || !value) {\n process.stderr.write(`[kordoc] ${flag}: 'key=value' 형식이 아닌 조각 무시 — \"${p}\" (값에 쉼표는 쓸 수 없습니다)\\n`)\n continue\n }\n out[key] = value\n }\n return out\n }\n const pressKv = opts.pressHead ? parseKv(String(opts.pressHead), \"--press-head\") : {}\n gongmun = buildGongmunOptions({\n preset,\n font: enumCheck(\"--font\", opts.font, BODY_FONTS),\n bodyPt: opts.pt ? Number(opts.pt) : undefined,\n lineSpacing: opts.lineSpacing ? Number(opts.lineSpacing) : undefined,\n org: opts.org, date: opts.date,\n cover: opts.cover, toc: opts.toc,\n approval: opts.approval ? String(opts.approval).split(\",\").map((s: string) => s.trim()).filter(Boolean) : undefined,\n pageNumbers: opts.pageNumbers, endMark: opts.endMark,\n // --no-body-title-box 단독 플래그 — commander 기본 true는 \"미지정\"으로 정돈\n bodyTitleBox: opts.bodyTitleBox === false ? false : undefined,\n chapterFit: opts.chapterFit,\n h2Marker: enumCheck(\"--h2-marker\", opts.h2Marker, H2_MARKERS),\n bandColor: opts.bandColor, bandTextColor: opts.bandTextColor,\n fonts: opts.fonts ? parseKv(String(opts.fonts), \"--fonts\") : undefined,\n sizes: opts.sizes\n ? Object.fromEntries(\n Object.entries(parseKv(String(opts.sizes), \"--sizes\")).map(([k, v]) => [k, Number(v)]).filter(([, v]) => Number.isFinite(v as number)),\n )\n : undefined,\n levels: opts.levels || learnedLevels\n ? { ...learnedLevels, ...(opts.levels ? parseLevelsSpec(String(opts.levels)) : {}) }\n : undefined,\n bullet2: enumCheck(\"--bullet2\", opts.bullet2, BULLET2_CHARS),\n suppressSingle: opts.suppressSingle ? true : undefined,\n totalRow: enumCheck(\"--total-row\", opts.totalRow, TOTAL_ROWS),\n docHead: opts.docHead ? parseKv(String(opts.docHead), \"--doc-head\") : undefined,\n docFoot: opts.docFoot ? parseKv(String(opts.docFoot), \"--doc-foot\") : undefined,\n reportInfo: opts.reportInfo ? String(opts.reportInfo) : undefined,\n summary: opts.summary ? String(opts.summary) : undefined,\n docInfo: opts.docInfo ? parseKv(String(opts.docInfo), \"--doc-info\") : undefined,\n checklist: opts.checklist === undefined ? undefined : opts.checklist === true ? true : { na: String(opts.checklist).split(\",\").map((x) => Number(x.trim())).filter((x) => x !== 0) },\n dept: opts.dept ? String(opts.dept) : undefined,\n coverLabel: opts.coverLabel ? String(opts.coverLabel) : undefined,\n agency: opts.agency ? String(opts.agency) : undefined,\n noticeHead: opts.noticeHead ? parseKv(String(opts.noticeHead), \"--notice-head\") : undefined,\n press: opts.pressHead || opts.pressSub || opts.pressPeople\n ? {\n release: pressKv.release, distribute: pressKv.distribute,\n sub: opts.pressSub ? String(opts.pressSub).split(\";\").map((s: string) => s.trim()).filter(Boolean) : undefined,\n contact: pressKv.dept || pressKv.manager || pressKv.phone || opts.pressPeople\n ? {\n dept: pressKv.dept, manager: pressKv.manager, phone: pressKv.phone,\n ...(opts.pressPeople ? {\n people: String(opts.pressPeople).split(\";\").map((s: string) => s.trim()).filter(Boolean)\n .map((s: string) => { const [role, title, name, phone] = s.split(\"/\").map((x) => x.trim()); return { role, title, name, phone } }),\n } : {}),\n }\n : undefined,\n }\n : undefined,\n })\n }\n\n // 폰트 오버라이드 오타·미설치 경고 (A2) — 생성은 진행\n if (gongmun?.fonts && !silent) {\n for (const w of unknownFontWarnings(gongmun.fonts)) process.stderr.write(`[kordoc] ${w}\\n`)\n }\n if (gongmun?.levels && !silent) {\n for (const w of unknownFontWarnings(levelFontRecord(gongmun.levels))) process.stderr.write(`[kordoc] ${w}\\n`)\n }\n // 프리셋 비호환 옵션 경고 (v4.0.6) — 조용한 폐기 대신 노출, 생성은 진행\n if (gongmun && !silent) {\n for (const w of incompatibleGongmunWarnings(gongmun)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n // 공문서 표기법 검수 (편람 기준, 조언용) — 생성은 진행, stderr 경고만\n if (gongmun && !silent) {\n for (const w of gongmunLintWarnings(md, 5)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n // 개조식 문체 검수 — 보고서·계획서·개조식 프리셋만. 기안문(경어)·통지·보도자료는\n // 문체 관행이 달라 적용하지 않는다 (범위를 좁히는 것이 오탐을 막는다)\n if (gongmun && !silent && usesGaejosikMunche(gongmun.preset)) {\n for (const w of muncheLintWarnings(md, 5)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n // 윤문(AI 문체)·구성(논리 구조) 검수 — 구성은 보고서·계획서 계열만 (기안문·통지·회의록·보도자료는 서식이 따로 있다)\n if (gongmun && !silent && !opts.gate) {\n for (const w of slopLintWarnings(md, 5)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n if (usesLogicStructure(gongmun.preset)) for (const w of logicLintWarnings(md, 5)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n if (opts.gate) {\n const gate = gongmunGate(md, { preset: gongmun?.preset })\n if (!gate.pass) {\n process.stderr.write(`[kordoc] 게이트 미통과 — ${gate.blocking.length}건을 고쳐 쓰고 다시 생성하세요 (파일 미생성)\\n`)\n for (const f of gate.blocking) process.stderr.write(` ${formatGateFinding(f)}\\n`)\n process.exit(1)\n }\n if (!silent) process.stderr.write(`[kordoc] 게이트 통과 (표기법·문체·윤문·구성)\\n`)\n }\n\n // 서식 프로필 (이슈 #41) — 경계 zod 검증 후 라이브러리에 전달 (MCP와 공유 스키마)\n let profile: FormatProfile | undefined\n if (opts.profile) {\n profile = parseFormatProfileJson(readFileSync(resolve(String(opts.profile)), \"utf-8\"))\n if (!silent) process.stderr.write(`[kordoc] 서식 프로필 적용: 표 ${profile.tables.length}개 (${opts.profile})\\n`)\n }\n\n // 페이지 옵션 (v4.5.0) — 용지·방향·다단·머리말/꼬리말\n let page: import(\"../index.js\").PageOptions | undefined\n if (opts.paper || opts.landscape || opts.columns || opts.header || opts.footer) {\n let size: import(\"../index.js\").PageOptions[\"size\"]\n if (opts.paper) {\n const wh = /^(\\d+(?:\\.\\d+)?)x(\\d+(?:\\.\\d+)?)$/i.exec(String(opts.paper).trim())\n size = wh ? { widthMm: Number(wh[1]), heightMm: Number(wh[2]) } : (String(opts.paper) as \"A4\")\n }\n page = {\n ...(size !== undefined ? { size } : {}),\n ...(opts.landscape ? { orientation: \"landscape\" as const } : {}),\n ...(opts.columns ? { columns: Number(opts.columns) } : {}),\n ...(opts.header ? { header: String(opts.header) } : {}),\n ...(opts.footer ? { footer: String(opts.footer) } : {}),\n }\n }\n // MCP와 같은 Unicode·실경로 검증을 적용한다.\n let imageBytes: Record<string, Uint8Array> | undefined\n if (opts.imageDir) {\n const dir = resolve(String(opts.imageDir))\n const loaded = await loadGenerationImages(md, dir)\n imageBytes = loaded.images\n if (!silent) {\n process.stderr.write(`[kordoc] 이미지 임베드: ${Object.keys(imageBytes ?? {}).length}개 (${dir})\\n`)\n for (const warning of loaded.warnings) process.stderr.write(`[kordoc] ⚠ ${warning}\\n`)\n }\n }\n\n const genWarnings: string[] = []\n const inlineMath = opts.inlineMath === true\n const buf = await markdownToHwpx(md, gongmun || profile || page || imageBytes || inlineMath\n ? {\n ...(gongmun ? { gongmun } : {}), ...(profile ? { profile } : {}),\n ...(page ? { page } : {}), ...(imageBytes ? { images: imageBytes } : {}),\n ...(inlineMath ? { inlineMath } : {}),\n warnings: genWarnings,\n }\n : undefined)\n if (!silent) for (const w of genWarnings) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n const outPath = resolve(output ?? (markdown === \"-\" ? `${baseName}.hwpx` : markdown.replace(/\\.(md|markdown|txt)$/i, \"\") + \".hwpx\"))\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, Buffer.from(buf))\n\n if (!silent) {\n const mode = gongmun ? `공문서:${gongmun.preset}` : \"범용\"\n process.stderr.write(`[kordoc] HWPX 생성 (${mode}) → ${outPath}\\n`)\n }\n // 다른 프로그램(한/글 실시간 편집 도구 등)이 결과를 받아 이어 쓰도록 — 사람용 메시지는 그대로 stderr\n if (opts.json) {\n process.stdout.write(JSON.stringify({ output: outPath, preset: gongmun?.preset ?? null, bytes: buf.byteLength, warnings: genWarnings }) + \"\\n\")\n }\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"levels <file>\")\n .description(\"견본 HWPX 의 항목부호 단계별 글꼴·크기·굵기 추출 — generate --levels 값과 단계별 분포·서식 편차 (kordoc levels 견본.hwpx, generate --levels-from 으로 바로 적용)\")\n .option(\"--json\", \"추출 결과(levels·spec·stats·deviations)를 JSON 으로 stdout 출력\")\n .action(async (file: string, opts) => {\n try {\n const r = await extractLevelStyles(toArrayBuffer(readFileSync(resolve(file))))\n if (opts.json) {\n process.stdout.write(JSON.stringify(r, null, 2) + \"\\n\")\n return\n }\n if (!r.scheme) {\n process.stderr.write(`[kordoc] ${r.note ?? \"항목부호(□·ㅇ·- 또는 1.·가.)로 시작하는 문단이 없음\"}\\n`)\n return\n }\n process.stdout.write(`${r.spec || \"(대표값 없음 — 단계마다 표본 3개 이상·한 값 60% 이상 필요)\"}\\n`)\n for (const st of r.stats.filter(x => x.scheme === r.scheme)) {\n const top = (m: Record<string, number>) => Object.entries(m).sort((a, b) => b[1] - a[1]).map(([k, n]) => `${k}×${n}`).join(\" \")\n process.stderr.write(` ${st.depth}단계 ${st.markers.join(\"\")} 표본 ${st.samples} — 글꼴 ${top(st.font)} · 크기 ${top(st.pt)} · 굵게 ${top(st.bold)}\\n`)\n }\n if (r.deviations.length) process.stderr.write(`[kordoc] 서식 편차 ${r.deviations.length}건 — kordoc lint ${file} --styles 로 확인\\n`)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"profile <file>\")\n .description(\"HWPX 표 서식 프로필 추출 — 참조 문서의 표 테두리·음영·열폭·셀 글꼴을 JSON으로 (generate --profile로 재현) — kordoc profile 참조.hwpx -o 서식.json\")\n .option(\"-o, --output <path>\", \"출력 JSON 경로 (기본: <입력>.profile.json)\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const silent: boolean = opts.silent ?? rootOpts.silent\n const absPath = resolve(file)\n const profile = await hwpxToProfile(readFileSync(absPath))\n const outPath = resolve(output ?? absPath.replace(/\\.hwpx$/i, \"\") + \".profile.json\")\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, JSON.stringify(profile, null, 2))\n if (!silent) process.stderr.write(`[kordoc] 서식 프로필 추출: 표 ${profile.tables.length}개 → ${outPath}\\n`)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"lint <file>\")\n .description(\"공문서 표기법 검수 — 날짜·시간·금액·붙임 등 행정업무운영 편람 표기법 (md/txt 또는 HWPX·HWP·PDF 등 문서, '-'=stdin). error 있으면 exit 1\")\n .option(\"--json\", \"JSON 출력\")\n .option(\"--munche\", \"개조식 문체 검수 병행 — 서술형 종결·당위·수사·항목 길이 (보고서·계획서 원고용)\")\n .option(\"--numbers\", \"본문 수치 ↔ 표 수치 대조 병행 — 표 가까이 본문의 수치가 그 표에 있는지 (확인 목록, exit 코드에는 영향 없음)\")\n .option(\"--styles\", \"단계별 서식 편차 병행 (HWPX) — 같은 항목부호 단계인데 글꼴·크기·굵기가 대표값과 다른 문단 (exit 코드에는 영향 없음)\")\n .option(\"--slop\", \"윤문 검수 병행 — 생성형 AI 문체(결산 접속어·평론 상투구·체감 상투구·추상 성과 줄·번역투)\")\n .option(\"--logic\", \"구성 검수 병행 — 보고서·계획서의 논리 구조(왜→무엇→어떻게, 문제점↔방안 짝, 배경 사실·기대효과 목표치)\")\n .option(\"--budget\", \"예산 문서 검수 병행 — 산출근거 곱셈 검산·표 합계 재계산(틀리면 error, exit 1)·합계 행 위치·외화 표기(원화 먼저·환율 기준)·증감 기준(본예산/최종예산)\")\n .option(\"--gate\", \"공문서 게이트 — 표기법·문체 error 와 윤문·구성 지적(경고 포함)이 하나라도 있으면 exit 1 (결재 올리기 전 최종 점검)\")\n .option(\"--preset <name>\", \"게이트 범위를 프리셋에 맞춤 — 개조식 계열이면 문체, 보고서·계획서 계열이면 구성 검수를 켬\")\n .action(async (file: string, opts) => {\n try {\n const raw = file === \"-\" ? readFileSync(0) : readFileSync(resolve(file))\n // 문서 파일은 파싱한 본문 마크다운을 검사한다 — UTF-8 텍스트로 읽으면 압축 바이트가 본문으로 둔갑해\n // 위반 수백~수천 건이 쏟아졌다(\"보고서.hwpx\" 실측 1,193건)\n const ab = raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength) as ArrayBuffer\n const kind = detectFormat(ab)\n let text: string\n let irBlocks: Parameters<typeof numberBlocksFromIR>[0] | undefined\n if (kind === \"unknown\") text = raw.toString(\"utf-8\")\n else {\n const { parse } = await import(\"../index.js\")\n const parsed = await parse(ab, file === \"-\" ? undefined : { filePath: resolve(file) })\n if (!parsed.success) {\n process.stderr.write(`[kordoc] 오류: ${kind} 문서를 읽지 못했습니다 — ${parsed.error}\\n`)\n process.exit(1)\n }\n text = parsed.markdown\n irBlocks = parsed.blocks\n }\n // 문체 검수는 옵트인 — 축이 다르고(표기법 vs 종결·수사), 개조식이 아닌 원고에는\n // 적용하면 안 되기 때문에 기본 동작은 종전 그대로 둔다 (판정은 MCP lint_document 와 같은 runLintSuite)\n const presetKey = opts.preset === undefined ? undefined : String(opts.preset).trim()\n const preset = presetKey !== undefined && Object.hasOwn(PRESET_ALIAS, presetKey) ? PRESET_ALIAS[presetKey] : undefined\n if (opts.preset !== undefined && !preset) {\n process.stderr.write(`[kordoc] 알 수 없는 프리셋: ${opts.preset}\\n`)\n process.exit(1)\n }\n const suite = runLintSuite(text, {\n parsed: kind !== \"unknown\", irBlocks, preset,\n munche: opts.munche, numbers: opts.numbers, budget: opts.budget, slop: opts.slop, logic: opts.logic, gate: opts.gate,\n })\n const { findings, numbers } = suite\n const munche = suite.munche ?? [], slop = suite.slop ?? [], logic = suite.logic ?? [], budget = suite.budget ?? []\n const styles = opts.styles && kind === \"hwpx\" ? (await extractLevelStyles(ab)).deviations : undefined\n if (opts.styles && kind !== \"hwpx\") process.stderr.write(`[kordoc] --styles 는 HWPX 문서만 — 건너뜀\\n`)\n const failed = !suite.summary.ok\n if (opts.json) {\n const { summary, ...rest } = suite\n process.stdout.write(JSON.stringify({ ...rest, ...(styles ? { styles } : {}), summary }, null, 2) + \"\\n\")\n } else {\n // 사람용 리포트는 stderr — 기계용(--json)만 stdout (validate와 채널 일관)\n process.stderr.write(`[kordoc] 표기법 검수: 위반 ${findings.length}건 (error ${findings.filter((f) => f.severity === \"error\").length}, warning ${findings.filter((f) => f.severity !== \"error\").length})\\n`)\n for (const f of findings) {\n process.stderr.write(` L${f.line} [${f.severity}] ${f.rule}: \"${f.match}\" — ${f.message}${f.suggest ? ` → ${f.suggest}` : \"\"}\\n`)\n }\n if (styles) {\n process.stderr.write(`[kordoc] 단계별 서식 편차: ${styles.length}건\\n`)\n const show = (st: { font?: string; pt?: number; bold?: boolean }) => [st.font, st.pt === undefined ? undefined : `${st.pt}pt`, st.bold === undefined ? undefined : st.bold ? \"굵게\" : \"보통\"].filter(Boolean).join(\"/\")\n for (const d of styles) process.stderr.write(` ${d.depth}단계 \"${d.text}\" — ${show(d.got)} (대표 ${show(d.expected)})\\n`)\n }\n if (numbers) {\n process.stderr.write(`[kordoc] 수치 대조: 표 가까이 본문 수치 ${numbers.checked}개 중 표에서 못 찾은 ${numbers.review.length}개 (확인 필요)\\n`)\n for (const r of numbers.review) process.stderr.write(` \"${r.match}\" — ${r.context}\\n`)\n }\n const section = (label: string, list: typeof findings) => {\n const e = list.filter((f) => f.severity === \"error\").length\n process.stderr.write(`[kordoc] ${label}: 위반 ${list.length}건 (error ${e}, warning ${list.length - e})\\n`)\n for (const f of list) process.stderr.write(` L${f.line} [${f.severity}] ${f.rule}: \"${f.match}\" — ${f.message}${f.suggest ? ` → ${f.suggest}` : \"\"}\\n`)\n }\n if (opts.slop || opts.gate) section(\"윤문 검수\", slop)\n if (opts.logic || opts.gate) section(\"구성 검수\", logic)\n if (opts.budget) section(\"예산 검수\", budget)\n if (munche.length || opts.munche || (opts.gate && preset && usesGaejosikMunche(preset))) {\n const me = munche.filter((f) => f.severity === \"error\").length\n process.stderr.write(`[kordoc] 문체 검수: 위반 ${munche.length}건 (error ${me}, warning ${munche.length - me})\\n`)\n for (const f of munche) {\n process.stderr.write(` L${f.line} [${f.severity}] ${f.rule}: \"${f.match}\" — ${f.message}${f.suggest ? ` → ${f.suggest}` : \"\"}\\n`)\n }\n }\n if (opts.gate) process.stderr.write(failed ? `[kordoc] 게이트 미통과 — 표기법·문체 error 와 윤문·구성 지적을 모두 고쳐 쓰세요\\n` : `[kordoc] 게이트 통과\\n`)\n }\n process.exit(failed ? 1 : 0)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"lint-blocks <file>\")\n .description(\"블록 단위 검수 — JSON {blocks:[{id,text,table?:{id,row,col}}], options?:{munche,slop,logic,numbers,budget,gate,preset}} 를 받아 지적마다 block·offset·length 로 (열린 문서 편집 도구용, '-'=stdin). 결과 JSON 은 stdout, error 있으면 exit 1\")\n .action(async (file: string) => {\n try {\n const raw = (file === \"-\" ? readFileSync(0) : readFileSync(resolve(file))).toString(\"utf-8\")\n const input = JSON.parse(raw) as { blocks?: unknown; options?: Record<string, unknown> }\n if (!Array.isArray(input.blocks)) throw new Error(\"blocks 배열이 없습니다\")\n const blocks = input.blocks.map((b, i) => {\n const o = b as { id?: unknown; text?: unknown; table?: { id?: unknown; row?: unknown; col?: unknown } }\n if (typeof o.id !== \"string\" || typeof o.text !== \"string\") throw new Error(`blocks[${i}] 에 문자열 id·text 가 필요합니다`)\n const t = o.table\n if (t !== undefined && (typeof t.id !== \"string\" || !Number.isInteger(t.row) || !Number.isInteger(t.col))) throw new Error(`blocks[${i}].table 은 {id, row, col}`)\n return { id: o.id, text: o.text, ...(t ? { table: { id: t.id as string, row: t.row as number, col: t.col as number } } : {}) }\n })\n const opt = input.options ?? {}\n const presetKey = typeof opt.preset === \"string\" ? opt.preset.trim() : undefined\n const preset = presetKey !== undefined && Object.hasOwn(PRESET_ALIAS, presetKey) ? PRESET_ALIAS[presetKey] : undefined\n if (presetKey !== undefined && !preset) throw new Error(`알 수 없는 프리셋: ${presetKey}`)\n const flag = (k: string) => opt[k] === true\n const result = lintBlocks(blocks, { preset, munche: flag(\"munche\"), slop: flag(\"slop\"), logic: flag(\"logic\"), numbers: flag(\"numbers\"), budget: flag(\"budget\"), gate: flag(\"gate\") })\n process.stdout.write(JSON.stringify(result) + \"\\n\")\n process.exitCode = result.summary.ok ? 0 : 1\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exitCode = 2\n }\n })\n\n program\n .command(\"redact <files...>\")\n .description(\"개인정보 서식 보존 마스킹 — 주민·외국인등록번호·전화·이메일·카드·계좌·사업자등록번호·여권·운전면허(--rules 로 인명·주소 opt-in)를 탐지해 HWPX/HWP는 원본 서식 그대로 같은 길이로 가린 파일(본문·표·머리말/꼬리말·각주·글상자·미리보기·메타데이터 포함), 그 외 포맷(PDF 등)은 원본을 건드리지 않고 마스킹된 마크다운만 출력. 자동 검출 보조 도구이므로 결과는 반드시 사람이 최종 확인하세요 (이미지 속 글자는 탐지 불가)\")\n .option(\"--rules <csv>\", \"적용 룰 (기본: rrn,phone,email,card,account,brn,passport,driver — crn(법인등록번호),ip,name(인명),address(주소)는 opt-in)\")\n .option(\"--mask-char <ch>\", \"마스크 문자 1글자 (기본: ●)\")\n .option(\"-o, --output <path>\", \"출력 경로 (단일 파일 시)\")\n .option(\"-d, --out-dir <dir>\", \"출력 디렉토리 (다중 파일 시)\")\n .option(\"--dry-run\", \"탐지 리포트만 출력, 파일 미생성\")\n .option(\"--json\", \"리포트를 JSON으로 stdout 출력\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (files: string[], opts) => {\n const { ALL_REDACT_RULES, DEFAULT_REDACT_RULES, redactText } = await import(\"../redact.js\")\n const { redactDocument } = await import(\"../redact-doc.js\")\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n // 루트 명령도 -d/--out-dir 를 정의해 먼저 삼킨다 — -o 와 같은 방식으로 양쪽을 본다\n const outDir: string | undefined = opts.outDir ?? rootOpts.outDir\n const silent: boolean = opts.silent ?? rootOpts.silent\n const KNOWN_RULES = new Set<string>(ALL_REDACT_RULES)\n const rules = opts.rules\n ? String(opts.rules).split(\",\").map((r: string) => r.trim()).filter(Boolean)\n : [...DEFAULT_REDACT_RULES]\n const badRule = rules.find((r: string) => !KNOWN_RULES.has(r))\n if (badRule) {\n process.stderr.write(`[kordoc] 알 수 없는 룰: ${badRule} (허용: ${[...KNOWN_RULES].join(\", \")})\\n`)\n process.exit(1)\n }\n const maskChar: string = opts.maskChar ?? \"●\"\n try { redactText(\"\", { maskChar }) } catch (err) {\n process.stderr.write(`[kordoc] ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n if (output && files.length > 1) {\n process.stderr.write(`[kordoc] ⚠️ -o/--output 은 단일 파일 전용이라 무시됩니다 — 다중 파일은 -d/--out-dir 를 사용하세요\\n`)\n }\n // 파일 이름에도 PII 가 있을 수 있다 — 결과 파일 이름·메시지·JSON 에는 가린 이름을 쓴다\n // (디렉토리 이름은 그대로). 윈도가 파일 이름에 못 쓰는 마스크 문자(* ?)는 ●로\n const nameMask = /[*?]/.test(maskChar) ? \"●\" : maskChar\n const maskName = (name: string): string => {\n // 파일 이름은 _ 로 낱말을 잇는다(\"민원_010-2345-6789\") — 탐지만 공백으로 보고 같은 자리를 가린다\n const probe = name.replace(/_/g, \" \")\n const out = [...name]\n for (const h of redactText(probe, { rules: rules as never, maskChar: nameMask }).hits) {\n for (let k = 0; k < h.length; k++) if (h.masked[k] !== probe[h.index + k]) out[h.index + k] = nameMask\n }\n return out.join(\"\")\n }\n const shown = (p: string): string => resolve(dirname(p), maskName(basename(p)))\n const inputs = files.map((f) => resolve(f))\n const sameFile = (a: string, b: string): boolean => {\n if (a === b) return true\n try {\n const sa = statSync(a), sb = statSync(b)\n return sa.ino === sb.ino && sa.dev === sb.dev // 대소문자 무시 파일시스템·하드링크\n } catch { return false }\n }\n const written = new Set<string>()\n /** 기본 출력 경로 — 입력 파일·이번 실행의 다른 출력과 겹치면 -2, -3 … 을 붙인다 */\n const defaultOut = (absPath: string, ext: string): string => {\n const stem = maskName(basename(absPath)).replace(/\\.[^.]+$/, \"\")\n const dir = resolve(outDir ?? dirname(absPath))\n for (let n = 1; ; n++) {\n const p = resolve(dir, `${stem}${n > 1 ? `-${n}` : \"\"}.redacted${ext}`)\n if (!written.has(p) && !inputs.some((i) => sameFile(i, p))) return p\n }\n }\n const MAX_LINES = 200\n const jsonReports: unknown[] = []\n for (const absPath of inputs) {\n const fileName = maskName(basename(absPath))\n if (output && files.length === 1 && !opts.dryRun && sameFile(absPath, resolve(output))) {\n process.stderr.write(`[kordoc] ERROR: ${fileName} — 출력 경로가 입력 파일과 같습니다. 원본을 덮어쓰지 않습니다 — 다른 -o 경로를 지정하세요\\n`)\n process.exitCode = 1\n continue\n }\n try {\n const buffer = readFileSync(absPath)\n const r = await redactDocument(toArrayBuffer(buffer), {\n rules: rules as never, maskChar, filePath: absPath, dryRun: opts.dryRun,\n })\n // 리포트 기준: HWPX/HWP 는 파일 안 위치(본문·머리말·미리보기 …), 그 외 포맷은 본문 마크다운\n const listed = r.fileHits.length > 0\n ? r.fileHits.map((h) => ({ rule: h.rule, masked: h.masked, at: `${h.where} @ ${h.part}` }))\n : r.markdownHits.map((h) => ({ rule: h.rule, masked: h.masked, at: \"\" }))\n const byRule = new Map<string, number>()\n for (const h of listed) byRule.set(h.rule, (byRule.get(h.rule) ?? 0) + 1)\n const ruleSummary = [...byRule.entries()].map(([k, v]) => `${k} ${v}건`).join(\", \") || \"0건\"\n const failed = r.residual.length > 0 || r.unscanned.length > 0\n\n let outPath: string | null = null\n let note = \"\"\n // HWPX/HWP 는 결과 바이트가 원본과 다르면 저장 (탐지 0건이어도 미할당 영역을 비웠으면 저장),\n // 그 외 포맷은 본문에서 찾은 게 있을 때 마스킹된 마크다운을 저장\n const save = r.data ? r.changed : r.markdownHits.length > 0\n if (!opts.dryRun && save) {\n const ext = r.data ? (r.format === \"hwp\" ? \".hwp\" : \".hwpx\") : \".md\"\n outPath = output && files.length === 1 ? resolve(output) : defaultOut(absPath, ext)\n mkdirSync(dirname(outPath), { recursive: true })\n if (r.data) writeFileSync(outPath, r.data)\n else {\n writeFileSync(outPath, r.markdown, \"utf-8\")\n note = ` (${r.format} 원본은 수정하지 않음 — 마스킹된 마크다운만 출력)`\n }\n written.add(outPath)\n } else if (!opts.dryRun && r.data && listed.length > 0) {\n note = \" (❌ 파일에서 가린 곳이 없어 출력하지 않음)\"\n }\n if (failed && process.exitCode !== 1) process.exitCode = 2 // 실패(1)가 우선\n if (opts.json) {\n jsonReports.push({\n file: shown(absPath), format: r.format, rules, hits: r.markdownHits, fileHits: r.fileHits,\n residual: r.residual, unscanned: r.unscanned, warnings: r.warnings, output: outPath,\n })\n }\n if (!silent) {\n process.stderr.write(`[kordoc] ${fileName}: ${ruleSummary}${outPath ? ` → ${outPath}` : opts.dryRun ? \" (dry-run)\" : \"\"}${note}\\n`)\n // 같은 값·같은 위치는 한 줄로 (미리보기·메타데이터에 같은 번호가 반복되는 경우), 너무 길면 자른다\n const grouped = new Map<string, number>()\n for (const h of listed) {\n const key = ` - [${h.rule}] ${h.masked}${h.at ? ` (${h.at})` : \"\"}`\n grouped.set(key, (grouped.get(key) ?? 0) + 1)\n }\n const lines = [...grouped].map(([line, n]) => `${line}${n > 1 ? ` ×${n}` : \"\"}`)\n for (const line of lines.slice(0, MAX_LINES)) process.stderr.write(`${line}\\n`)\n if (lines.length > MAX_LINES) process.stderr.write(` … 외 ${lines.length - MAX_LINES}줄 (전체는 --json)\\n`)\n if (r.residual.length > 0) {\n process.stderr.write(`[kordoc] ❌ 마스킹 후 재검사에서 PII ${r.residual.length}건이 남아 있습니다 — 출력 파일을 공개하지 말고 수동 확인하세요:\\n`)\n for (const h of r.residual.slice(0, MAX_LINES)) process.stderr.write(` - [${h.rule}] ${h.masked} (${h.where} @ ${h.part})\\n`)\n if (r.residual.length > MAX_LINES) process.stderr.write(` … 외 ${r.residual.length - MAX_LINES}건 (전체는 --json)\\n`)\n }\n if (r.unscanned.length > 0) {\n process.stderr.write(`[kordoc] ❌ 글자를 검사하지 못한 곳이 있습니다 — 출력 파일을 공개하지 말고 수동 확인하세요: ${r.unscanned.join(\", \")}\\n`)\n }\n for (const w of r.warnings) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n }\n } catch (err) {\n process.stderr.write(`[kordoc] ERROR: ${fileName} — ${sanitizeError(err)}\\n`)\n process.exitCode = 1\n }\n }\n if (opts.json) process.stdout.write(JSON.stringify(files.length === 1 ? jsonReports[0] ?? null : jsonReports, null, 2) + \"\\n\")\n })\n}\n","/**\n * 견본 HWPX 의 항목부호 단계별 서식 — 기관마다 □·ㅇ·- (또는 1. 가. 1)) 단계의 글꼴·크기·굵기 관행이 달라, 그 기관 문서\n * 한 벌에서 배워 generate 의 단계별 위계 타이포(GongmunOptions.levels, `--levels`)로 넘긴다. 같은 단계인데 서식이 다른\n * 문단(편차)도 함께 낸다(`kordoc lint --styles`).\n *\n * 문단 단계는 생성 엔진과 같은 부호 해석(outline.parseLeadingMarker)으로, 서식은 부호 뒤 첫 글자가 든 글자 모양으로 잰다.\n * 칸이 여럿인 데이터 표 안 문단은 표 서식(작은 글씨 '-' 항목 등)이라 빼고, 본문을 담는 1×1 틀 상자 안 문단은 남긴다.\n * 대표값은 단계·속성마다 표본 MIN_SAMPLES 개 이상이고 한 값이 MIN_SHARE 이상일 때만 정한다 — 섞여 쓴 속성은 비워 엔진\n * 기본을 따르게 한다. □·ㅇ·- 계열과 법정 계열 가운데 표본이 많은 쪽을 문서의 계열로 본다.\n */\n\nimport JSZip from \"jszip\"\nimport type { Element as XmlElement } from \"@xmldom/xmldom\"\nimport { extractHwpxStyles } from \"./styles.js\"\nimport { resolveSectionPaths } from \"./zip-sections.js\"\nimport { parseLeadingMarker } from \"./outline.js\"\nimport { createXmlParser, readZipEntry } from \"./parser-shared.js\"\nimport { KordocError, stripDtd, precheckZipSize } from \"../utils.js\"\nimport { detectFormat } from \"../detect.js\"\nimport type { GongmunLevelStyle } from \"./gongmun.js\"\n\nconst MIN_SAMPLES = 3\nconst MIN_SHARE = 0.6\n\n/** 한 문단의 단계 서식 표본 */\ninterface LevelSample {\n scheme: \"box\" | \"legal\"\n depth: number\n marker: string\n text: string\n font?: string\n pt?: number\n bold: boolean\n}\n\nexport interface LevelStat {\n scheme: \"box\" | \"legal\"\n depth: number\n /** 이 단계에 쓰인 부호 (등장 순) */\n markers: string[]\n samples: number\n /** 속성별 값 → 문단 수 */\n font: Record<string, number>\n pt: Record<string, number>\n bold: Record<string, number>\n}\n\nexport interface LevelDeviation {\n depth: number\n /** 문단 앞 40자 */\n text: string\n got: GongmunLevelStyle\n expected: GongmunLevelStyle\n}\n\nexport interface LevelStyleReport {\n /** 표본을 잴 수 없었던 사유 (글자 모양 정의가 없는 HWPX 등) */\n note?: string\n /** 문서의 부호 계열 — 표본 없으면 null */\n scheme: \"box\" | \"legal\" | null\n /** 대표값이 정해진 단계·속성만 (generate levels 입력) */\n levels: Record<string, GongmunLevelStyle>\n /** `--levels` 문자열 (\"0=HY견고딕/17/bold,1=…\") — 대표값이 없으면 \"\" */\n spec: string\n stats: LevelStat[]\n /** 대표값과 다른 문단 (문서 계열만) */\n deviations: LevelDeviation[]\n}\n\nconst local = (n: { nodeName: string }): string => n.nodeName.replace(/^.*:/, \"\")\n\n/** <hp:t> 글 — 탭 요소는 \"\\t\" (항목부호 뒤는 공백이 아니라 탭인 문서가 많다: \"□<hp:tab/>\" + \"첫째 대항목\") */\nfunction runText(t: XmlElement): string {\n let out = \"\"\n for (let n = t.firstChild; n; n = n.nextSibling) {\n if (n.nodeType === 3) out += n.nodeValue ?? \"\"\n else if (n.nodeType === 1 && local(n) === \"tab\") out += \"\\t\"\n }\n return out\n}\n\n/** 칸이 여럿인 표 안 문단 — 가장 가까운 표의 행·열 수로 (1×1 틀 상자는 본문으로 본다) */\nfunction inDataTable(p: XmlElement): boolean {\n for (let n = p.parentNode as XmlElement | null; n; n = n.parentNode as XmlElement | null) {\n if (n.nodeType === 1 && local(n) === \"tbl\") {\n const el = n\n return Number(el.getAttribute(\"rowCnt\") ?? 1) * Number(el.getAttribute(\"colCnt\") ?? 1) > 1\n }\n }\n return false\n}\n\n/** 글자 모양 id → 한글 글꼴명 — 한컴 HWPX 는 글꼴을 번호(<hh:fontRef hangul=\"1\">)로 가리키고 이름은 글꼴 목록\n * (<hh:fontface lang=\"HANGUL\"><hh:font id face>)에 둔다 */\nfunction hangulFaces(headerXml: string): Map<string, string> {\n const doc = createXmlParser().parseFromString(stripDtd(headerXml), \"text/xml\")\n const faces = new Map<string, string>()\n const fontfaces = doc.getElementsByTagNameNS(\"*\", \"fontface\")\n for (let i = 0; i < fontfaces.length; i++) {\n if (fontfaces[i].getAttribute(\"lang\") !== \"HANGUL\") continue\n const fonts = fontfaces[i].getElementsByTagNameNS(\"*\", \"font\")\n for (let k = 0; k < fonts.length; k++) faces.set(fonts[k].getAttribute(\"id\") ?? \"\", fonts[k].getAttribute(\"face\") ?? \"\")\n }\n const out = new Map<string, string>()\n const charPrs = doc.getElementsByTagNameNS(\"*\", \"charPr\")\n for (let i = 0; i < charPrs.length; i++) {\n const ref = charPrs[i].getElementsByTagNameNS(\"*\", \"fontRef\")[0]\n const face = ref ? faces.get(ref.getAttribute(\"hangul\") ?? \"\") : undefined\n if (face) out.set(charPrs[i].getAttribute(\"id\") ?? \"\", face)\n }\n return out\n}\n\n/** 견본 HWPX → 단계별 대표 서식과 편차 */\nexport async function extractLevelStyles(buffer: ArrayBuffer): Promise<LevelStyleReport> {\n const format = detectFormat(buffer)\n if (format !== \"hwpx\") throw new KordocError(`단계별 서식은 HWPX 견본에서만 잽니다 (감지된 포맷: ${format}) — 한글에서 HWPX 로 저장해 넘기세요`)\n precheckZipSize(buffer)\n const zip = await JSZip.loadAsync(buffer)\n const decompressed = { total: 0 }\n const styles = await extractHwpxStyles(zip, decompressed)\n const header = zip.file(\"Contents/header.xml\") ?? zip.file(\"Contents/head.xml\")\n const faces = header ? hangulFaces(await readZipEntry(header, \"text\", decompressed.total)) : new Map<string, string>()\n const samples: LevelSample[] = []\n for (const path of await resolveSectionPaths(zip)) {\n const file = zip.file(path)\n if (!file) continue\n const xml = await readZipEntry(file, \"text\", decompressed.total)\n decompressed.total += xml.length * 2\n const doc = createXmlParser().parseFromString(stripDtd(xml), \"text/xml\")\n const paras = doc.getElementsByTagNameNS(\"*\", \"p\")\n for (let i = 0; i < paras.length; i++) {\n const p = paras[i]\n if (inDataTable(p)) continue\n // 문단 직속 run 만 — 칸 안 문단은 그 문단이 따로 잡힌다\n const runs: Array<{ text: string; charPr: string | null }> = []\n for (let c = p.firstChild; c; c = c.nextSibling) {\n if (c.nodeType !== 1 || local(c) !== \"run\") continue\n const el = c as unknown as Element\n let text = \"\"\n const ts = el.getElementsByTagNameNS(\"*\", \"t\")\n for (let k = 0; k < ts.length; k++) if (ts[k].parentNode === el) text += runText(ts[k] as unknown as XmlElement)\n runs.push({ text, charPr: el.getAttribute(\"charPrIDRef\") })\n }\n const text = runs.map(r => r.text).join(\"\")\n const lm = parseLeadingMarker(text)\n if ((lm.kind !== \"box\" && lm.kind !== \"legal\") || !lm.rest) continue\n // 부호 뒤 첫 글자가 든 run 의 글자 모양\n const at = text.indexOf(lm.rest)\n let pos = 0, charPr: string | null = null\n for (const r of runs) {\n if (at < pos + r.text.length) { charPr = r.charPr; break }\n pos += r.text.length\n }\n const cp = charPr ? styles.charProperties.get(charPr) : undefined\n if (!cp) continue\n samples.push({ scheme: lm.kind, depth: lm.depth, marker: lm.marker, text: lm.rest, font: faces.get(charPr!) ?? cp.fontName, pt: cp.fontSize, bold: !!cp.bold })\n }\n }\n const report = summarize(samples)\n return styles.charProperties.size === 0 ? { ...report, note: \"글자 모양 정의(header.xml charPr)가 없어 서식을 잴 수 없음\" } : report\n}\n\nconst tally = (values: Array<string | undefined>): Record<string, number> => {\n const out: Record<string, number> = {}\n for (const v of values) if (v !== undefined) out[v] = (out[v] ?? 0) + 1\n return out\n}\n/** 표본 MIN_SAMPLES 이상·점유 MIN_SHARE 이상인 값 */\nconst dominant = (counts: Record<string, number>, total: number): string | undefined => {\n const [value, n] = Object.entries(counts).sort((a, b) => b[1] - a[1])[0] ?? []\n return value !== undefined && total >= MIN_SAMPLES && n! >= total * MIN_SHARE ? value : undefined\n}\n\nfunction summarize(samples: LevelSample[]): LevelStyleReport {\n const box = samples.filter(s => s.scheme === \"box\").length, legal = samples.length - box\n const scheme = samples.length === 0 ? null : box >= legal ? \"box\" : \"legal\"\n const stats: LevelStat[] = []\n const levels: Record<string, GongmunLevelStyle> = {}\n for (const sch of [\"box\", \"legal\"] as const) {\n for (const depth of [...new Set(samples.filter(s => s.scheme === sch).map(s => s.depth))].sort((a, b) => a - b)) {\n const group = samples.filter(s => s.scheme === sch && s.depth === depth)\n const st: LevelStat = {\n scheme: sch, depth, markers: [...new Set(group.map(s => s.marker))], samples: group.length,\n font: tally(group.map(s => s.font)), pt: tally(group.map(s => s.pt?.toString())), bold: tally(group.map(s => String(s.bold))),\n }\n stats.push(st)\n if (sch !== scheme) continue\n const font = dominant(st.font, group.length), pt = dominant(st.pt, group.length), bold = dominant(st.bold, group.length)\n const style: GongmunLevelStyle = { ...(font ? { font } : {}), ...(pt ? { pt: Number(pt) } : {}), ...(bold ? { bold: bold === \"true\" } : {}) }\n if (Object.keys(style).length) levels[depth] = style\n }\n }\n const deviations: LevelDeviation[] = []\n for (const s of samples) {\n const want = s.scheme === scheme ? levels[s.depth] : undefined\n if (!want) continue\n const got: GongmunLevelStyle = { font: s.font, pt: s.pt, bold: s.bold }\n if ((want.font !== undefined && want.font !== s.font) || (want.pt !== undefined && want.pt !== s.pt) || (want.bold !== undefined && want.bold !== s.bold)) {\n deviations.push({ depth: s.depth, text: s.text.slice(0, 40), got, expected: want })\n }\n }\n const spec = Object.entries(levels).map(([d, st]) =>\n `${d}=${[st.font, st.pt, st.bold === undefined ? undefined : st.bold ? \"bold\" : \"plain\"].filter(v => v !== undefined).join(\"/\")}`).join(\",\")\n return { scheme, levels, spec, stats, deviations }\n}\n","/** kordoc CLI 명령 — 렌더 — render·crop·tables·render-worker */\n\nimport { readFileSync, writeFileSync, mkdirSync } from \"fs\"\nimport { dirname, resolve } from \"path\"\nimport { parse } from \"../index.js\"\nimport { VERSION, toArrayBuffer, sanitizeError, KordocError } from \"../utils.js\"\nimport type { Command } from \"commander\"\n\nexport function registerRenderCommands(program: Command): void {\n program\n .command(\"render <file>\")\n .description(\"레이아웃 보존 렌더 — HWPX·HWP(5.x)를 SVG(기본, HWPX 는 전체 페이지 세로 스택)·HTML·PNG·JPEG·PDF로. 한컴 저장본은 조판 캐시 그대로, 캐시 없는 생성본·편집본은 순수 TS 조판(reflow, 기본 켬) — kordoc render 문서.hwpx -o 문서.svg / --format png --pages 2-4 -d ./pages / --format pdf -o 문서.pdf\")\n .option(\"-o, --output <path>\", \"출력 경로 (단일 산출: svg 스택·html·pdf·한 쪽 png/jpeg. 기본: <입력>.<확장자>)\")\n .option(\"-d, --out-dir <dir>\", \"페이지별 산출 디렉토리 (svg/png/jpeg 여러 쪽 → page_001.png …)\")\n .option(\"--format <fmt>\", \"svg(기본) | html | png | jpeg | pdf\")\n .option(\"--pages <range>\", \"렌더할 페이지 (1-based: 3 / 1-3 / 1,3,7-9)\")\n .option(\"--max-width <px>\", \"래스터 최대 폭 px (기본 1400)\")\n .option(\"--title <text>\", \"HTML/PDF 문서 제목\")\n .option(\"--browser <path>\", \"PDF 용 Chromium 실행 파일 (기본: PUPPETEER_EXECUTABLE_PATH 또는 자동 탐지)\")\n .option(\"--highlight <terms>\", \"검색어 형광펜 (쉼표 구분)\")\n .option(\"--no-reflow\", \"순수 TS 조판 끄기 (조판 캐시 없는 문서가 빈 페이지로 나올 수 있음)\")\n .option(\"--reflow\", \"순수 TS 조판 켜기 — 기본값과 같다 (옛 안내 호환, #97)\")\n .option(\"--reflow-mode <mode>\", \"reflow 줄바꿈 모드: keep(어절) | charAll(글자)\", \"keep\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const outDir: string | undefined = opts.outDir ?? rootOpts.outDir\n const silent: boolean = opts.silent ?? rootOpts.silent\n // 루트 --format(markdown 기본) 이 서브커맨드 뒤 --format 을 흡수한다(cli-options 회귀) — 기본값이 아니면 그 값을 쓴다\n const fmt: string = opts.format ?? (rootOpts.format && rootOpts.format !== \"markdown\" ? rootOpts.format : \"svg\")\n const pages: string | undefined = opts.pages ?? rootOpts.pages\n if (![\"svg\", \"html\", \"png\", \"jpeg\", \"pdf\"].includes(fmt)) throw new KordocError(`--format 은 svg|html|png|jpeg|pdf 중 하나: ${fmt}`)\n const highlights = opts.highlight ? String(opts.highlight).split(\",\") : undefined\n const absPath = resolve(file)\n const stem = file.replace(/\\.hwpx?$/i, \"\")\n if (fmt === \"svg\" && !outDir && !pages && !/\\.hwp$/i.test(absPath)) {\n // 종전 동작(HWPX) — 전체 페이지 세로 스택 SVG 한 파일. HWP5 는 통합 렌더러(페이지별)\n const { renderHwpxToSvg } = await import(\"../render/index.js\")\n const buffer = readFileSync(absPath)\n const result = await renderHwpxToSvg(toArrayBuffer(buffer), { highlights, reflow: opts.reflow, reflowMode: opts.reflowMode })\n const outPath = resolve(output ?? stem + \".svg\")\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, result.svg, \"utf-8\")\n if (!silent) {\n process.stderr.write(`[kordoc] 렌더 (${result.pageCount}페이지, ${result.width}x${result.height}pt, 텍스트 ${result.stats.texts}·이미지 ${result.stats.images}·표 ${result.stats.tables}) → ${outPath}\\n`)\n for (const w of result.warnings) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n }\n return\n }\n const { renderDocument } = await import(\"../render/index.js\")\n const { scene, assets } = await renderDocument(absPath, {\n format: fmt as \"svg\" | \"html\" | \"png\" | \"jpeg\" | \"pdf\", pages, highlights, reflow: opts.reflow, reflowMode: opts.reflowMode,\n maxWidthPx: opts.maxWidth ? Number(opts.maxWidth) : undefined, title: opts.title, browserExecutablePath: opts.browser,\n })\n const ext = fmt === \"jpeg\" ? \"jpg\" : fmt\n const written: string[] = []\n if (fmt === \"html\" || fmt === \"pdf\" || (assets.length === 1 && !outDir)) {\n const outPath = resolve(output ?? stem + \".\" + ext)\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, assets[0].data)\n written.push(outPath)\n } else {\n if (!outDir) throw new KordocError(`페이지 ${assets.length}장 산출은 --out-dir 이 필요합니다 (한 쪽만 내려면 --pages 로 선택)`)\n mkdirSync(resolve(outDir), { recursive: true })\n for (const a of assets) {\n const outPath = resolve(outDir, `page_${String(a.page).padStart(3, \"0\")}.${ext}`)\n writeFileSync(outPath, a.data)\n written.push(outPath)\n }\n }\n if (!silent) {\n process.stderr.write(`[kordoc] 렌더 ${fmt} (${scene.pages.length}페이지 중 ${assets.length}건, 텍스트 ${scene.stats.texts}·이미지 ${scene.stats.images}·표 ${scene.stats.tables}·도형 ${scene.stats.shapes}) → ${written.length === 1 ? written[0] : resolve(outDir!)}\\n`)\n for (const w of scene.warnings) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n }\n } catch (err) {\n // exit(1) 을 바로 부르면 파이프 stderr 가 유실된다 — exitCode 로 정상 종료\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exitCode = 1\n }\n })\n\n program\n .command(\"crop <file>\")\n .description(\"렌더 영역 잘라내기 — 표·이미지·문단·도형을 페이지 이미지에서 crop (HWPX·HWP) — kordoc crop 문서.hwpx --target table -d ./regions\")\n .option(\"-d, --out-dir <dir>\", \"출력 디렉토리 (필수) — <유형>_<번호>_page_<쪽>.png + regions.json\")\n .option(\"--target <types>\", \"유형(쉼표): table | image | paragraph | shape\", \"table\")\n .option(\"--format <fmt>\", \"png(기본) | jpeg\")\n .option(\"--pages <range>\", \"대상 페이지 (1-based)\")\n .option(\"--padding <pt>\", \"bbox 둘레 여백 pt\", \"0\")\n .option(\"--max-width <px>\", \"페이지 래스터 최대 폭 px (crop 해상도, 기본 1400)\")\n .option(\"--no-reflow\", \"순수 TS 조판 끄기\")\n .option(\"--reflow\", \"순수 TS 조판 켜기 — 기본값과 같다 (옛 안내 호환)\")\n .option(\"--reflow-mode <mode>\", \"reflow 줄바꿈 모드: keep | charAll\", \"keep\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const rootOpts = program.opts()\n const outDir: string | undefined = opts.outDir ?? rootOpts.outDir\n const silent: boolean = opts.silent ?? rootOpts.silent\n const fmt: string = opts.format ?? (rootOpts.format && rootOpts.format !== \"markdown\" ? rootOpts.format : \"png\")\n const pages: string | undefined = opts.pages ?? rootOpts.pages\n if (![\"png\", \"jpeg\"].includes(fmt)) throw new KordocError(`--format 은 png|jpeg 중 하나: ${fmt}`)\n if (!outDir) throw new KordocError(\"--out-dir 이 필요합니다 (crop 은 파일 여러 개를 냅니다)\")\n const types = String(opts.target).split(\",\").map((t: string) => t.trim()).filter(Boolean)\n for (const t of types) if (![\"table\", \"image\", \"paragraph\", \"shape\"].includes(t)) throw new KordocError(`--target 유형 오류: ${t}`)\n const { extractRenderedRegions } = await import(\"../render/index.js\")\n const regions = await extractRenderedRegions(resolve(file), {\n types: types as Array<\"table\" | \"image\" | \"paragraph\" | \"shape\">, format: fmt as \"png\" | \"jpeg\", pages,\n paddingPt: Number(opts.padding) || 0, maxWidthPx: opts.maxWidth ? Number(opts.maxWidth) : undefined, reflow: opts.reflow, reflowMode: opts.reflowMode,\n })\n const dir = resolve(outDir)\n mkdirSync(dir, { recursive: true })\n const ext = fmt === \"jpeg\" ? \"jpg\" : \"png\"\n const manifest = regions.map(r => {\n const name = `${r.region.id.replace(\"-\", \"_\")}_page_${String(r.page).padStart(3, \"0\")}.${ext}`\n writeFileSync(resolve(dir, name), r.data)\n return { file: name, id: r.region.id, type: r.region.type, sourceId: r.region.sourceId, parentId: r.region.parentId, page: r.page, bbox: r.bbox, widthPx: r.widthPx, heightPx: r.heightPx }\n })\n writeFileSync(resolve(dir, \"regions.json\"), JSON.stringify(manifest, null, 2))\n if (!silent) process.stderr.write(`[kordoc] crop ${regions.length}건 (${types.join(\",\")}) → ${dir}\\n`)\n } catch (err) {\n // exit(1) 을 바로 부르면 파이프 stderr 가 유실된다 — exitCode 로 정상 종료\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exitCode = 1\n }\n })\n\n program\n .command(\"tables <file>\")\n .description(\"표 추출·분류 — 의미표/레이아웃(조직도 등)/불확실 분류 JSON + 선택적 시각 crop (HWPX·HWP) — kordoc tables 문서.hwpx --visual non-tabular-and-uncertain -d ./tables\")\n .option(\"-o, --output <path>\", \"JSON 출력 경로 (기본 stdout; -d 지정 시 <out-dir>/tables.json)\")\n .option(\"-d, --out-dir <dir>\", \"crop 저장 디렉토리 (--visual 지정 시 필수)\")\n .option(\"--visual <policy>\", \"crop 대상: none(기본) | non-tabular | non-tabular-and-uncertain | all\", \"none\")\n .option(\"--crop-format <fmt>\", \"png(기본) | jpeg\", \"png\")\n .option(\"--padding <pt>\", \"crop 여백 pt\", \"0\")\n .option(\"--cells\", \"JSON 에 셀 텍스트 격자 포함\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const outDir: string | undefined = opts.outDir ?? rootOpts.outDir\n const silent: boolean = opts.silent ?? rootOpts.silent\n const policy = String(opts.visual)\n if (![\"none\", \"non-tabular\", \"non-tabular-and-uncertain\", \"all\"].includes(policy)) throw new KordocError(`--visual 은 none|non-tabular|non-tabular-and-uncertain|all: ${policy}`)\n if (policy !== \"none\" && !outDir) throw new KordocError(\"--visual 은 crop 파일을 내므로 --out-dir 이 필요합니다\")\n const cropFmt = String(opts.cropFormat)\n if (![\"png\", \"jpeg\"].includes(cropFmt)) throw new KordocError(`--crop-format 은 png|jpeg: ${cropFmt}`)\n const { extractTables } = await import(\"../table/visual.js\")\n const tables = await extractTables(resolve(file), { policy: policy as \"none\" | \"non-tabular\" | \"non-tabular-and-uncertain\" | \"all\", format: cropFmt as \"png\" | \"jpeg\", paddingPt: Number(opts.padding) || 0 })\n const dir = outDir ? resolve(outDir) : undefined\n if (dir) mkdirSync(dir, { recursive: true })\n const ext = cropFmt === \"jpeg\" ? \"jpg\" : \"png\"\n const report = tables.map(t => {\n const crops = t.crops.map(c => {\n const name = `${t.id.replace(/[^\\w.-]/g, \"_\")}_page_${String(c.page).padStart(3, \"0\")}.${ext}`\n if (dir) writeFileSync(resolve(dir, name), c.data)\n return { file: dir ? name : undefined, page: c.page, bbox: c.bbox }\n })\n return {\n id: t.id, sourceId: t.sourceId, page: t.page, classification: t.classification,\n table: { rows: t.table.rows, cols: t.table.cols, hasHeader: t.table.hasHeader, caption: t.table.caption, ...(opts.cells ? { cells: t.table.cells.map(r => r.map(c => c.text)) } : {}) },\n regions: t.regions, crops, warnings: t.warnings,\n }\n })\n const json = JSON.stringify(report, null, 2)\n const jsonPath = output ? resolve(output) : dir ? resolve(dir, \"tables.json\") : undefined\n if (jsonPath) { mkdirSync(dirname(jsonPath), { recursive: true }); writeFileSync(jsonPath, json + \"\\n\") }\n else process.stdout.write(json + \"\\n\")\n if (!silent) {\n const kinds = report.reduce<Record<string, number>>((m, r) => { m[r.classification.kind] = (m[r.classification.kind] ?? 0) + 1; return m }, {})\n process.stderr.write(`[kordoc] 표 ${report.length}개 (${Object.entries(kinds).map(([k, v]) => `${k} ${v}`).join(\", \")}) crop ${report.reduce((n, r) => n + r.crops.length, 0)}건${jsonPath ? ` → ${jsonPath}` : \"\"}\\n`)\n }\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exitCode = 1\n }\n })\n\n program\n .command(\"render-worker\")\n .description(\"persistent 렌더 워커 — stdin NDJSON 요청 → 조판 SVG 파일 출력 (프로세스 유지, 콜드스타트 제거)\")\n .action(async () => {\n // 프로토콜(NDJSON, 한 줄=한 요청/응답):\n // 요청 {\"id\":1,\"file\":\"a.hwpx\",\"out\":\"a.svg\",\"reflow\":true,\"highlight\":[\"term\"]}\n // 응답 {\"id\":1,\"ok\":true,\"out\":\"a.svg\",\"width\":..,\"height\":..,\"pageCount\":..,\"stats\":{..},\"warnings\":[..]}\n // {\"cmd\":\"quit\"} 로 종료. 모듈은 최초 1회만 로드 → 이후 요청은 콜드스타트 없음.\n const { createInterface } = await import(\"node:readline\")\n const { renderHwpxToSvg } = await import(\"../render/index.js\")\n const rl = createInterface({ input: process.stdin })\n const write = (o: unknown): void => void process.stdout.write(JSON.stringify(o) + \"\\n\")\n write({ ready: true, version: VERSION })\n for await (const line of rl) {\n const t = line.trim()\n if (!t) continue\n let req: { id?: number; cmd?: string; file?: string; out?: string; reflow?: boolean; reflowMode?: string; highlight?: string[] }\n // 비JSON 라인도 응답은 낸다 — 무음 삼킴이면 id 대기 클라이언트가 영구 행\n try { req = JSON.parse(t) } catch { write({ ok: false, error: \"잘못된 JSON 라인\" }); continue }\n if (req === null || typeof req !== \"object\") { write({ ok: false, error: \"JSON 객체가 아닙니다\" }); continue }\n if (req.cmd === \"quit\") { rl.close(); break }\n const id = req.id\n try {\n if (!req.file || !req.out) throw new Error(\"file·out 필수\")\n const buffer = readFileSync(resolve(req.file))\n const result = await renderHwpxToSvg(toArrayBuffer(buffer), {\n highlights: req.highlight, reflow: req.reflow, reflowMode: req.reflowMode as \"keep\" | \"charAll\" | undefined,\n })\n const outPath = resolve(req.out)\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, result.svg, \"utf-8\")\n write({ id, ok: true, out: outPath, width: result.width, height: result.height, pageCount: result.pageCount, stats: result.stats, warnings: result.warnings })\n } catch (err) {\n write({ id, ok: false, error: sanitizeError(err) })\n }\n }\n })\n}\n","/** kordoc CLI 명령 — 서버·설정·모델 — mcp·setup·check-formula-models·check-ocr-models·models */\n\nimport { sanitizeError } from \"../utils.js\"\nimport type { Command } from \"commander\"\n\nexport function registerSystemCommands(program: Command): void {\n program\n .command(\"mcp\")\n .description(\"MCP 서버 실행 (Claude / Cursor / Windsurf 연동)\")\n .action(async () => {\n const { startMcpServer } = await import(\"../mcp.js\")\n await startMcpServer()\n })\n\n program\n .command(\"setup\")\n .description(\"대화형 설치 마법사 — AI 클라이언트 자동 등록 (Mac/Win/Linux)\")\n .action(async () => {\n const { runSetup } = await import(\"../setup.js\")\n await runSetup()\n })\n\n program\n .command(\"check-formula-models\")\n .description(\"PDF 수식 OCR 모델(MFD + MFR + tokenizer, ~155MB) 상태 확인 — 없거나 SHA 불일치면 다운로드\")\n .option(\"--status-only\", \"상태만 JSON 으로 출력 (다운로드 안 함)\")\n .action(async (opts) => {\n try {\n const { getFormulaModelStatus, ensureFormulaModels, getFormulaModelsDir } = await import(\n \"../pdf/formula/index.js\"\n )\n const dir = getFormulaModelsDir()\n if (opts.statusOnly) {\n const status = await getFormulaModelStatus()\n process.stdout.write(\n JSON.stringify(\n {\n modelsDir: dir,\n allReady: status.every((s) => s.verified),\n models: status.map((s) => ({\n name: s.spec.name,\n filename: s.spec.filename,\n sizeMb: s.spec.sizeMb,\n exists: s.exists,\n verified: s.verified,\n invalidReason: s.invalidReason,\n path: s.localPath,\n })),\n },\n null,\n 2,\n ) + \"\\n\",\n )\n return\n }\n process.stderr.write(`[kordoc-formula] 캐시 디렉토리: ${dir}\\n`)\n await ensureFormulaModels((p) => {\n if (p.phase === \"download\" && p.total) {\n const pct = Math.floor((p.downloaded / p.total) * 100)\n process.stderr.write(\n `\\r[kordoc-formula] ${p.spec.name} ${pct}% (${(p.downloaded / 1024 / 1024).toFixed(1)}/${(p.total / 1024 / 1024).toFixed(1)}MB)`,\n )\n if (p.downloaded >= p.total) process.stderr.write(\"\\n\")\n } else if (p.phase === \"verify\") {\n process.stderr.write(`[kordoc-formula] ${p.spec.name} SHA-256 검증 중...\\n`)\n } else if (p.phase === \"done\") {\n process.stderr.write(`[kordoc-formula] ${p.spec.name} 준비 완료\\n`)\n } else if (p.phase === \"skip\") {\n process.stderr.write(`[kordoc-formula] ${p.spec.name} 이미 존재 (skip)\\n`)\n }\n })\n process.stdout.write(\"ok\\n\")\n } catch (err) {\n process.stderr.write(`[kordoc] 수식 모델 준비 실패: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"check-ocr-models\")\n .description(\"텍스트 OCR 모델(PP-OCRv5 korean det+rec, ~18MB) 상태 확인 — 없거나 SHA 불일치면 다운로드\")\n .option(\"--status-only\", \"상태만 JSON 으로 출력 (다운로드 안 함)\")\n .action(async (opts) => {\n try {\n const { getOcrModelStatus, ensureOcrModels, getOcrModelsDir } = await import(\"../ocr/models.js\")\n const dir = getOcrModelsDir()\n if (opts.statusOnly) {\n const status = await getOcrModelStatus()\n process.stdout.write(\n JSON.stringify(\n {\n modelsDir: dir,\n allReady: status.every((s) => s.verified),\n models: status.map((s) => ({\n name: s.spec.name,\n filename: s.spec.filename,\n sizeMb: s.spec.sizeMb,\n exists: s.exists,\n verified: s.verified,\n invalidReason: s.invalidReason,\n path: s.localPath,\n })),\n },\n null,\n 2,\n ) + \"\\n\",\n )\n return\n }\n process.stderr.write(`[kordoc-ocr] 캐시 디렉토리: ${dir}\\n`)\n await ensureOcrModels((p) => {\n if (p.phase === \"download\" && p.total) {\n const pct = Math.floor((p.downloaded / p.total) * 100)\n process.stderr.write(\n `\\r[kordoc-ocr] ${p.spec.name} ${pct}% (${(p.downloaded / 1024 / 1024).toFixed(1)}/${(p.total / 1024 / 1024).toFixed(1)}MB)`,\n )\n if (p.downloaded >= p.total) process.stderr.write(\"\\n\")\n } else if (p.phase === \"verify\") {\n process.stderr.write(`[kordoc-ocr] ${p.spec.name} SHA-256 검증 중...\\n`)\n } else if (p.phase === \"done\") {\n process.stderr.write(`[kordoc-ocr] ${p.spec.name} 준비 완료\\n`)\n } else if (p.phase === \"skip\") {\n process.stderr.write(`[kordoc-ocr] ${p.spec.name} 이미 존재 (skip)\\n`)\n }\n })\n process.stdout.write(\"ok\\n\")\n } catch (err) {\n process.stderr.write(`[kordoc] OCR 모델 준비 실패: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"models\")\n .description(\"OCR/수식 모델 오프라인 사이드로드 — 폐쇄망 반입용 내보내기/가져오기 (SHA-256 검증)\")\n .option(\"--status\", \"캐시에 설치된 모델 상태를 JSON 으로 출력\")\n .option(\"--export <dir>\", \"로컬 캐시 → 번들 디렉토리로 내보내기 (온라인 PC에서 실행)\")\n .option(\"--import <dir>\", \"번들 디렉토리 → 로컬 캐시로 설치 (내부망 PC에서 실행)\")\n .action(async (opts) => {\n try {\n const { exportModels, importModels, modelCacheStatus } = await import(\"../shared/model-bundle.js\")\n if (opts.status) {\n process.stdout.write(JSON.stringify(await modelCacheStatus(), null, 2) + \"\\n\")\n return\n }\n const dir = opts.export ?? opts.import\n if (!dir) {\n process.stderr.write(\"[kordoc] --status / --export <dir> / --import <dir> 중 하나가 필요합니다\\n\")\n process.exit(1)\n }\n if (opts.export && opts.import) {\n process.stderr.write(\"[kordoc] --export 와 --import 는 함께 쓸 수 없습니다\\n\")\n process.exit(1)\n }\n const result = opts.export ? await exportModels(dir) : await importModels(dir)\n for (const f of result.files) {\n const mark = f.status === \"copied\" ? \"+\" : f.status === \"invalid\" ? \"!\" : \"-\"\n process.stderr.write(` ${mark} ${f.group}/${f.filename}${f.reason ? ` — ${f.reason}` : \"\"}\\n`)\n }\n const verb = opts.export ? \"내보내기\" : \"설치\"\n const copied = result.files.filter((f) => f.status === \"copied\").length\n process.stderr.write(\n `[kordoc-models] ${verb} ${result.ok ? `완료 (${copied}개)` : \"실패 — 위 ! / - 항목 확인\"}: ${dir}\\n`,\n )\n if (!result.ok) process.exit(1)\n process.stdout.write(\"ok\\n\")\n } catch (err) {\n process.stderr.write(`[kordoc] 모델 사이드로드 실패: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n}\n","/** kordoc CLI 명령: 상주 파싱 워커 (parse-worker) */\n\nimport { resolve } from \"path\"\nimport type { ParseOptions, ParseResult } from \"../types.js\"\nimport { VERSION, sanitizeError, classifyError, routeConsoleToStderr } from \"../utils.js\"\nimport type { Command } from \"commander\"\nimport { parseWorkerFile } from \"./worker-parse.js\"\n\n/** 요청·응답 필드가 바뀌면 올린다. 호스트가 ready 줄로 호환을 판단한다 */\nexport const PARSE_WORKER_PROTOCOL = 1\n\ninterface ParseWorkerRequest {\n id?: number\n cmd?: string\n file?: string\n /** false 면 이미지 바이트를 싣지 않는다 (ParseOptions.images) */\n images?: boolean\n /** \"off\"(기본) | \"auto\"(OCR 필요 페이지만) | \"force\"(전 페이지) */\n ocr?: \"off\" | \"auto\" | \"force\"\n formulaOcr?: boolean\n password?: string | null\n}\n\n/** 이미지 바이트는 --format json 과 같게 base64 로 */\nconst bytesToBase64 = (_key: string, value: unknown): unknown =>\n value instanceof Uint8Array ? Buffer.from(value).toString(\"base64\") : value\n\nasync function parseOne(req: ParseWorkerRequest & { file: string }): Promise<ParseResult> {\n const absPath = resolve(req.file)\n const options: ParseOptions = { filePath: absPath }\n if (req.images === false) options.images = false\n if (req.ocr === \"force\") options.ocr = \"force\"\n else if (req.ocr === \"auto\") options.ocr = true\n if (req.formulaOcr) options.formulaOcr = true\n if (req.password) options.password = req.password\n return parseWorkerFile(absPath, options)\n}\n\nexport function registerWorkerCommands(program: Command): void {\n program\n .command(\"parse-worker\")\n .description(\"상주 파싱 워커: stdin NDJSON 요청 → 한 줄 JSON 응답 (프로세스 유지, 파일마다 node 를 새로 띄우는 비용 제거)\")\n .option(\"--protocol <version>\", \"프로토콜 버전: 1(기본) | 2(Java·Python SDK — ParseOptions·이미지 파일 전송, docs/parse-worker-protocol.md)\", \"1\")\n .option(\"--max-request-bytes <n>\", \"protocol 2: 요청 한 줄 상한 바이트\")\n .option(\"--max-response-bytes <n>\", \"protocol 2: 응답 한 줄 상한 바이트\")\n .action(async (opts: { protocol: string; maxRequestBytes?: string; maxResponseBytes?: string }) => {\n if (opts.protocol === \"2\") {\n const limit = (v: string | undefined, name: string): number | undefined => {\n if (v === undefined) return undefined\n const n = Number(v)\n if (!/^\\d+$/.test(v) || !Number.isSafeInteger(n) || n < 1) {\n process.stderr.write(`[kordoc] ${name} 는 양의 정수여야 합니다: ${v}\\n`)\n process.exit(2)\n }\n return n\n }\n const maxRequestBytes = limit(opts.maxRequestBytes, \"--max-request-bytes\")\n const maxResponseBytes = limit(opts.maxResponseBytes, \"--max-response-bytes\")\n routeConsoleToStderr()\n const { runParseWorkerV2 } = await import(\"./parse-worker-v2.js\")\n await runParseWorkerV2({ maxRequestBytes, maxResponseBytes })\n process.exit(0)\n }\n if (opts.protocol !== \"1\") {\n // CLI 단건 실행 등으로 조용히 대체하지 않는다 — 호스트가 엔진 버전 불일치를 바로 알게\n process.stderr.write(`[kordoc] 지원하지 않는 parse-worker protocol: ${opts.protocol} (1, 2)\\n`)\n process.exit(2)\n }\n // 프로토콜(NDJSON, 한 줄 = 한 메시지):\n // 시작 {\"ready\":true,\"version\":\"4.14.3\",\"protocol\":1}\n // 요청 {\"id\":1,\"file\":\"a.hwpx\",\"images\":false,\"ocr\":\"off\",\"formulaOcr\":false,\"password\":null}\n // 응답 {\"id\":1,\"rss\":123456789,\"result\":{…}}: result 는 --format json 과 같은 ParseResult (실패도 success:false 로)\n // {\"id\":1,\"error\":\"…\"}: 요청 자체가 잘못됐을 때\n // {\"cmd\":\"quit\"} 또는 stdin 닫힘으로 종료. rss 는 호스트가 워커 교체 시점을 정하는 데 쓴다.\n // pdfjs 등이 console 로 찍는 경고가 stdout 프로토콜 줄을 깨지 않게 stderr 로 돌린다\n routeConsoleToStderr()\n const { createInterface } = await import(\"node:readline\")\n const rl = createInterface({ input: process.stdin, crlfDelay: Infinity })\n const write = (o: unknown): void => void process.stdout.write(JSON.stringify(o, bytesToBase64) + \"\\n\")\n write({ ready: true, version: VERSION, protocol: PARSE_WORKER_PROTOCOL })\n for await (const line of rl) {\n const t = line.trim()\n if (!t) continue\n let req: ParseWorkerRequest\n // 비JSON 라인도 응답은 낸다. 무음 삼킴이면 id 를 기다리는 호스트가 영구 대기\n try { req = JSON.parse(t) } catch { write({ error: \"잘못된 JSON 라인\" }); continue }\n if (req === null || typeof req !== \"object\") { write({ error: \"JSON 객체가 아닙니다\" }); continue }\n if (req.cmd === \"quit\") break\n const id = req.id\n if (typeof req.file !== \"string\" || !req.file) { write({ id, error: \"file 필수\" }); continue }\n const result = await parseOne({ ...req, file: req.file })\n try {\n write({ id, rss: process.memoryUsage.rss(), result })\n } catch (err) {\n // 직렬화 한계(이미지 수백 장 base64 등, #65)는 실패 JSON 계약으로\n write({ id, rss: process.memoryUsage.rss(), result: { success: false, fileType: result.fileType, error: sanitizeError(err), code: classifyError(err) } })\n }\n }\n rl.close()\n // 파이프 stdout 은 맥·윈도에서 비동기라 바로 exit 하면 마지막 응답이 잘린다. 다 비운 뒤 끝낸다.\n // pdfjs 등이 남긴 핸들이 있어도 워커는 끝낸다 (호스트가 죽어 stdin 이 닫힌 경우의 고아 방지)\n await new Promise<void>((done) => process.stdout.write(\"\", () => done()))\n process.exit(0)\n })\n}\n"],"mappings":"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","names":["statSync","basename","resolve","resolve","basename","statSync","output","basename","program","basename","resolve","readFileSync","writeFileSync","mkdirSync","statSync","basename","resolve","program","resolve","statSync","readFileSync","basename","result","formInfo","mkdirSync","writeFileSync","detectFormat","readFileSync","writeFileSync","mkdirSync","statSync","basename","dirname","resolve","text","program","readFileSync","resolve","basename","buf","outPath","mkdirSync","dirname","writeFileSync","parse","statSync","readFileSync","writeFileSync","mkdirSync","dirname","resolve","program","resolve","readFileSync","mkdirSync","dirname","writeFileSync","program","resolve","resolve","program"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/cli/convert.ts","../src/cli/output-path.ts","../src/cli/batch.ts","../src/cli/commands-docs.ts","../src/cli/commands-generate.ts","../src/hwpx/level-styles.ts","../src/cli/commands-render.ts","../src/cli/commands-system.ts","../src/cli/commands-worker.ts"],"sourcesContent":["/** kordoc CLI — 모두 파싱해버리겠다 (하위 명령은 cli/ 아래 명령군 모듈) */\n\nimport { Command } from \"commander\"\nimport { VERSION, sanitizeError, routeConsoleToStderr } from \"./utils.js\"\nimport { convertFiles } from \"./cli/convert.js\"\nimport { assertDistinctStems, convertParallel, registerBatchWorker } from \"./cli/batch.js\"\nimport { registerDocCommands } from \"./cli/commands-docs.js\"\nimport { registerGenerateCommands } from \"./cli/commands-generate.js\"\nimport { registerRenderCommands } from \"./cli/commands-render.js\"\nimport { registerSystemCommands } from \"./cli/commands-system.js\"\nimport { registerWorkerCommands } from \"./cli/commands-worker.js\"\n\nconst program = new Command()\n\nprogram\n .name(\"kordoc\")\n .description(\"모두 파싱해버리겠다 — HWP, HWPX, PDF, XLSX, DOCX, 이미지(PNG/JPG/WebP) → Markdown\")\n .version(VERSION)\n .argument(\"<files...>\", \"변환할 파일 경로 (HWP, HWPX, PDF, XLSX, DOCX, PNG/JPG/WebP — 이미지는 OCR 자동 적용)\")\n .option(\"-o, --output <path>\", \"출력 파일 경로 (단일 파일 시)\")\n .option(\"--jobs <count>\", \"병렬 변환 프로세스 수 (기본 1, 다중 파일은 -d 필요)\", \"1\")\n .option(\"-d, --out-dir <dir>\", \"출력 디렉토리 (다중 파일 시)\")\n .option(\"-p, --pages <range>\", \"페이지 범위 (예: 1-3, 1,3,5) — 한컴 저장본은 실제 페이지, 조판 캐시 없으면 섹션 근사\")\n .option(\"--format <type>\", \"출력 형식: markdown (기본), json, chunks (RAG용 구조 청크 JSON — 헤딩·개조식 위계 breadcrumb + 표 독립 청크)\", \"markdown\")\n .option(\"--no-header-footer\", \"PDF 머리글/바닥글 자동 제거 끄기 (기본: 제거함)\")\n .option(\"--no-tables\", \"PDF 표 감지 끄기 — 테두리 박스를 표로 오인해 읽기 순서가 뒤집히는 문서(2단 시험지 등)에서 자연 읽기순 텍스트만 뽑는다 (#64)\")\n .option(\"--formula-ocr\", \"PDF 수식 OCR 활성화 (MFD+MFR ONNX, 첫 사용 시 모델 ~155MB 자동 다운로드)\")\n .option(\"--ocr\", \"스캔/이미지 PDF 텍스트 OCR (내장 PP-OCRv5 korean, 첫 사용 시 모델 ~18MB 자동 다운로드 — OCR 필요 페이지만 인식)\")\n .option(\"--ocr-force\", \"전 페이지 강제 OCR (텍스트층이 있어도 무시하고 재인식)\")\n .option(\"--ocr-lines\", \"내장 OCR 이 읽은 줄(래스터 px 상자·신뢰도)을 --format json 결과 ocrLines 로\")\n .option(\"--ocr-lines-all\", \"--ocr-lines 에 저신뢰로 버린 줄도 dropped 표시로 함께\")\n .option(\"--ocr-det <model>\", \"OCR 글줄 검출 모델: mobile (기본) | server (~88MB 첫 사용 시 다운로드) | 로컬 ONNX 경로 (--ocr-det-sha256 필수)\")\n .option(\"--ocr-det-sha256 <hex>\", \"--ocr-det 로컬 파일의 SHA-256 — 다르면 로드 거부\")\n .option(\"--ocr-det-long-side <px>\", \"OCR 글줄 검출 입력 긴 변 (32~4096, 기본 960) — 키우면 작은 글자를 더 잡고 느려진다\")\n .option(\"--ocr-rec <model>\", \"OCR 글자 인식 모델: handwriting (수기 서류용 한국어 손글씨 rec, ~15MB 첫 사용 시 다운로드) | 로컬 ONNX 경로 (--ocr-rec-sha256 필수)\")\n .option(\"--ocr-rec-sha256 <hex>\", \"--ocr-rec 파일의 SHA-256\")\n .option(\"--ocr-rec-dict <path>\", \"OCR 글자 인식 사전을 로컬 inference.yml 로 (--ocr-rec-dict-sha256 필수, 기본 내장 한국어 사전)\")\n .option(\"--ocr-rec-dict-sha256 <hex>\", \"--ocr-rec-dict 파일의 SHA-256\")\n .option(\"--dedupe-headers\", \"HWP5 레이아웃 표 페이지 반복 러닝 헤더 중복 제거 (기본 off — 붙임별 재번호 오삭제 주의)\")\n .option(\"--keep-empty-cols\", \"표 오른쪽 끝 빈 열(서식 입력란) 보존 (#47, 기본 off: 후행 빈 열 트림)\")\n .option(\"--keep-empty-paragraphs\", \"빈 문단 보존 — 본문은 빈 paragraph 블록, 표 셀은 빈 줄로 (#57, 기본 off: 빈 문단 제거)\")\n .option(\"--include-field-placeholders\", \"미기입 누름틀 안내문도 출력 — 빈 서식의 칸 용도 보존 (#92, 기본 off: 인쇄되지 않는 안내문 제외)\")\n .option(\"--inline-images\", \"이미지를 base64 data URI 로 마크다운에 인라인 (BMP→PNG 압축, HWP5 전용 — 인라인된 경우만 파일 미저장, 그 외 포맷은 저장 유지)\")\n .option(\"--image-refs\", \"--format json 에서 이미지 바이트를 인라인하지 않고 파일 참조(images/<문서 이름>/<파일명>)만 남김 (#65 — 이미지가 수백 장인 문서의 직렬화 한계 회피, -o/-d 와 함께 사용)\")\n .option(\"--password <pw>\", \"암호로 보호된 문서의 열기 암호 (#59, HWPX·HWP3·HWP5. 한컴 DRM 문서는 해당 없음)\")\n .option(\"--html-tables\", \"모든 표를 HTML 로 — 파이프 표도 HTML 표로, 태그마다 한 줄씩 들여써 냄\")\n .option(\"--table-format <format>\", \"표 출력 형식: gfm — 모든 표를 HTML 없이 GFM 파이프 표로, 셀 안 표는 부모 뒤 독립 표 + 관계 표지(<!-- <table … /> -->) (RAG 색인용, --html-tables 와 함께 못 씀)\")\n .option(\"--keep-layout-tables\", \"테두리가 안 보이는 틀 표도 원본 표 구조 그대로 (기본: 보이는 대로 — 틀은 글, 칸으로 조립한 분수는 수식). patch 로 되돌릴 편집본은 이 옵션으로 뽑는다\")\n .option(\"--script-tags\", \"위·아래첨자를 <sup>·<sub> 로 표기 — PDF 는 기본 끔(논문·수식 PDF 에 권장), HWPX·HWP·DOCX 는 기본 켬\")\n .option(\"--no-script-tags\", \"첨자 표기 끄기 — 모든 형식에서 평문(\\\"104 m2\\\")\")\n .option(\"--plain\", \"평문 Markdown — 그림 자리 표시·링크 URL·밑줄/굵게 표기를 빼고 글만 (제목·목록·표 구조는 유지, 색인·RAG 용)\")\n .option(\"--no-images\", \"이미지 바이트를 추출·출력하지 않음: 글자만 필요할 때 (그림 자리 표시는 남김, PDF 는 PNG 인코딩을 건너뜀)\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (files: string[], opts) => {\n const validFormats = [\"markdown\", \"json\", \"chunks\"]\n if (!validFormats.includes(opts.format)) {\n process.stderr.write(`[kordoc] 지원하지 않는 형식: ${opts.format} (markdown, json, chunks)\\n`)\n process.exit(1)\n }\n if (opts.tableFormat !== undefined && opts.tableFormat !== \"gfm\") {\n process.stderr.write(`[kordoc] 지원하지 않는 표 형식: ${opts.tableFormat} (gfm)\\n`)\n process.exit(1)\n }\n if (opts.tableFormat && opts.htmlTables) {\n process.stderr.write(`[kordoc] --table-format 과 --html-tables 는 함께 쓸 수 없습니다\\n`)\n process.exit(1)\n }\n // -o는 단일 파일 전용 — 다중 파일에서 무음 무시되지 않게 경고\n if (opts.output && files.length > 1) {\n process.stderr.write(`[kordoc] ⚠️ -o/--output 은 단일 파일 전용이라 무시됩니다 — 다중 파일은 -d/--out-dir 를 사용하세요\\n`)\n }\n const jobs = Number(opts.jobs)\n if (!/^\\d+$/.test(opts.jobs) || !Number.isSafeInteger(jobs) || jobs < 1) {\n program.error(\"--jobs must be a positive integer\")\n }\n if (jobs > 1 && files.length > 1) {\n if (!opts.outDir) program.error(\"--jobs > 1 requires --out-dir for multiple files\")\n try {\n if (!await convertParallel(files, opts, jobs)) process.exitCode = 1\n } catch (err) {\n program.error(sanitizeError(err))\n }\n } else {\n if (opts.outDir && files.length > 1) {\n try { assertDistinctStems(files) } catch (err) { program.error(sanitizeError(err)) }\n }\n if (!await convertFiles(files, opts)) process.exitCode = 1\n }\n })\n\nregisterDocCommands(program)\nregisterGenerateCommands(program)\nregisterRenderCommands(program)\nregisterSystemCommands(program)\nregisterWorkerCommands(program)\nregisterBatchWorker(program)\n\n// stdout 은 마크다운·JSON·생성 바이너리 채널 — pdfjs 등이 console 로 찍는 경고가 섞이지 않게 stderr 로\n// (parse-worker·MCP 와 같은 처리). setup 은 사람이 보는 설치 화면이라 그대로 둔다\nprogram.hook(\"preAction\", (_program, action) => {\n if (action.name() !== \"setup\") routeConsoleToStderr()\n})\n\n// 출처를 node 로 고정 — 정하지 않으면 commander 가 process.versions.electron 을 보고 Electron 앱 방식(argv[1]부터)으로\n// 읽어, Electron 을 node 로 띄운(ELECTRON_RUN_AS_NODE) 데스크톱 앱에서 cli.js 자신이 입력 파일로 잡힌다\nprogram.parse(process.argv, { from: \"node\" })\n","/** Shared sequential conversion path for the CLI and batch workers. */\n\nimport { readFileSync, writeFileSync, mkdirSync, statSync } from \"fs\"\nimport { basename, resolve } from \"path\"\nimport type { OptionValues } from \"commander\"\nimport { parse, detectFormat } from \"../index.js\"\nimport type { ParseOptions } from \"../types.js\"\nimport { toArrayBuffer, sanitizeError, classifyError } from \"../utils.js\"\nimport { detectImageMime } from \"../hwp5/images.js\"\nimport { toPlainMarkdown } from \"../plain-markdown.js\"\nimport { toHtmlTables } from \"../html-tables.js\"\nimport { createOutputGuard } from \"./output-path.js\"\n\n/** --ocr-lines·--ocr-det·--ocr-rec… → ParseOptions. 값 검증은 parse() 가 한다(잘못이면 실패 JSON). 로컬 경로는 현재 디렉터리 기준 절대 경로로 */\nexport function cliOcrEngineOptions(opts: OptionValues): Pick<ParseOptions, \"ocrLines\" | \"ocrDet\" | \"ocrDetLongSide\" | \"ocrRec\" | \"ocrRecDict\"> {\n const out: Pick<ParseOptions, \"ocrLines\" | \"ocrDet\" | \"ocrDetLongSide\" | \"ocrRec\" | \"ocrRecDict\"> = {}\n const file = (path: string, sha256: unknown) => ({ path: resolve(path), sha256: typeof sha256 === \"string\" ? sha256 : \"\" })\n if (opts.ocrLinesAll) out.ocrLines = \"all\"\n else if (opts.ocrLines) out.ocrLines = true\n if (opts.ocrDet !== undefined) {\n out.ocrDet = opts.ocrDet === \"mobile\" || opts.ocrDet === \"server\" ? opts.ocrDet : file(String(opts.ocrDet), opts.ocrDetSha256)\n }\n // 숫자가 아니면 받은 글 그대로 넘겨 parse() 가 그 값을 들어 거부한다\n if (opts.ocrDetLongSide !== undefined) out.ocrDetLongSide = /^\\d+$/.test(String(opts.ocrDetLongSide)) ? Number(opts.ocrDetLongSide) : opts.ocrDetLongSide as number\n if (opts.ocrRec !== undefined) out.ocrRec = opts.ocrRec === \"handwriting\" ? opts.ocrRec : file(String(opts.ocrRec), opts.ocrRecSha256)\n if (opts.ocrRecDict !== undefined) out.ocrRecDict = file(String(opts.ocrRecDict), opts.ocrRecDictSha256)\n return out\n}\n\nexport async function convertFiles(files: string[], opts: OptionValues, writeOutput: (text: string) => void = text => { process.stdout.write(text) }, assertSafeOutputs = createOutputGuard(files)): Promise<boolean> {\n let failed = false\n for (let fi = 0; fi < files.length; fi++) {\n const filePath = files[fi]\n const absPath = resolve(filePath)\n const fileName = basename(absPath)\n const filePrefix = files.length > 1 ? `[${fi + 1}/${files.length}] ` : \"\"\n let detectedFormat: ReturnType<typeof detectFormat> = \"unknown\"\n\n try {\n const fileSize = statSync(absPath).size\n if (fileSize > 500 * 1024 * 1024) {\n process.stderr.write(`\\n[kordoc] SKIP: ${fileName} — 파일이 너무 큽니다 (${(fileSize / 1024 / 1024).toFixed(1)}MB)\\n`)\n failed = true\n continue\n }\n const buffer = readFileSync(absPath)\n const arrayBuffer = toArrayBuffer(buffer)\n const format = detectFormat(arrayBuffer)\n detectedFormat = format\n\n if (!opts.silent) {\n process.stderr.write(`[kordoc] ${filePrefix}${fileName} (${format}) ...`)\n }\n\n const parseOptions: ParseOptions = { filePath: absPath }\n if (opts.pages) parseOptions.pages = opts.pages as string\n if (opts.headerFooter === false) parseOptions.removeHeaderFooter = false\n if (opts.tables === false) parseOptions.tables = false\n if (opts.formulaOcr) parseOptions.formulaOcr = true\n if (opts.ocrForce) parseOptions.ocr = \"force\"\n else if (opts.ocr) parseOptions.ocr = true\n Object.assign(parseOptions, cliOcrEngineOptions(opts))\n if (opts.dedupeHeaders) parseOptions.dedupeRunningHeaders = true\n if (opts.keepEmptyCols) parseOptions.keepTrailingEmptyCols = true\n if (opts.keepEmptyParagraphs) parseOptions.keepEmptyParagraphs = true\n if (opts.includeFieldPlaceholders) parseOptions.includeFieldPlaceholders = true\n if (opts.inlineImages) parseOptions.inlineImages = true\n if (opts.password) parseOptions.password = opts.password as string\n if (opts.images === false) parseOptions.images = false\n if (opts.plain) parseOptions.plain = true\n if (opts.scriptTags !== undefined) parseOptions.scriptTags = opts.scriptTags as boolean\n if (opts.htmlTables) parseOptions.htmlTables = true\n if (opts.tableFormat === \"gfm\") parseOptions.tableFormat = \"gfm\"\n if (opts.keepLayoutTables) parseOptions.layoutTables = \"keep\"\n if (!opts.silent) {\n parseOptions.onProgress = (current: number, total: number) => {\n process.stderr.write(`\\r[kordoc] ${filePrefix}${fileName} (${format}) [${current}/${total}]`)\n }\n }\n const result = await parse(arrayBuffer, parseOptions)\n detectedFormat = result.fileType // ZIP 세분화(xlsx·docx) 반영 — 실패 JSON 의 fileType\n\n if (!result.success) {\n process.stderr.write(` FAIL\\n`)\n process.stderr.write(` → ${result.error}\\n`)\n // 실패는 모든 --format 에서 stdout 에 동일한 실패 JSON(success:false + code)을 낸다(#69)\n // — 호출자가 원인 코드(ENCRYPTED 등)로 분기할 수 있는 기계 계약. 성공 출력과 충돌하지\n // 않는다: markdown 성공은 마크다운, chunks 성공은 JSON 배열이고 실패는 객체 + exit 1.\n // stderr 의 FAIL 문구는 사람용으로 그대로 둔다.\n writeOutput(JSON.stringify({ ...result, file: fileName }, null, 2) + \"\\n\")\n failed = true\n continue\n }\n\n if (!opts.silent) process.stderr.write(` OK\\n`)\n\n let markdown = result.markdown\n // 이미지 인라인은 HWP5 경로에서만 실제로 일어난다(parser.ts). 그 외 포맷(HWPX/DOCX 등)은\n // --inline-images 를 줘도 인라인되지 않으므로, 이미지 저장/경로접두사를 생략하면 참조가\n // 깨지고(dangling) 바이트가 유실된다 → 실제 인라인된 경우에만 생략한다.\n const imagesInlined = opts.inlineImages && result.fileType === \"hwp\"\n // 그림을 파일로 저장하는 실행(--out-dir 또는 단일 파일 --output, 아래 saveImages)이면 이미지 참조 경로에 images/ 접두사 추가\n // (인라인 모드에선 이미지가 마크다운에 임베드되므로 건너뜀). 종전엔 --out-dir 만 봐서 -o 결과의 그림 링크가 전부 깨졌다(#94).\n // <img src> 는 병합/중첩 표 셀 경로(table/builder.ts) — 마크다운 문법과 함께 둘 다 바꿔야 참조가 안 깨진다\n const savesImageFiles = Boolean(opts.outDir || (opts.output && files.length === 1))\n // 그림은 문서마다 images/<문서 이름>/ 에 — 같은 폴더로 여러 문서를 변환하면 image_001.png 가 서로 덮어써졌다(#98).\n // 문서 이름은 출력 파일 이름(-o) 또는 입력 파일 이름(-d)에서 확장자를 뺀 것. 링크에서는 공백·괄호만 퍼센트 인코딩한다\n const docStem = (opts.output && files.length === 1 ? basename(opts.output) : fileName).replace(/\\.[^.]+$/, \"\")\n const imgLink = `images/${docStem.replace(/[ ()]/g, ch => encodeURIComponent(ch))}/`\n const linkImages = (text: string): string => savesImageFiles && result.images?.length && !imagesInlined\n ? text.replace(/!\\[image\\]\\(image_/g, `![image](${imgLink}image_`).replace(/(<img\\b[^>]*\\bsrc=\")image_/g, `$1${imgLink}image_`)\n : text\n markdown = linkImages(markdown)\n // json 직렬화 — refsOnly면 이미지 바이트를 빼고 저장 경로만 남긴다.\n // 이미지가 수백 장인 문서는 base64 총량이 V8 문자열 한계를 넘어 RangeError 로\n // 터졌고, 그 예외가 성공 로그 뒤 비-JSON 출력이 되어 파이프라인이 깨졌다 (#65).\n const serializeJson = (refsOnly: boolean): string => {\n const payload = refsOnly && result.images?.length\n ? { ...result, images: result.images.map(img => ({ filename: img.filename, mimeType: img.mimeType, path: `images/${docStem}/${img.filename}` })) }\n : result\n return JSON.stringify(payload, (_key, value) =>\n value instanceof Uint8Array ? Buffer.from(value).toString(\"base64\") : value\n , 2)\n }\n let output: string\n if (opts.format === \"json\") {\n const savesImages = Boolean((opts.output && files.length === 1) || opts.outDir) && !imagesInlined\n try {\n output = serializeJson(Boolean(opts.imageRefs) && savesImages)\n } catch (err) {\n // 한계 초과 — 이미지를 어차피 파일로 저장하는 실행이면 참조 모드로 자동 강등한다.\n // 저장 위치가 없으면(stdout) 구제할 방법이 없으므로 실패 JSON 계약으로 넘긴다.\n if (!savesImages || !result.images?.length) throw err\n output = serializeJson(true)\n process.stderr.write(` ⚠️ 이미지 base64 인라인이 직렬화 한계를 넘어 파일 참조로 대체했습니다 (${result.images.length}개 → images/${docStem}/)\\n`)\n }\n } else if (opts.format === \"chunks\") {\n // 청크 글에도 본문 마크다운과 같은 후처리(평문·HTML 표·그림 경로) — 종전엔 IR 에서 바로 만들어 --plain·--html-tables 를 무시했다\n const { blocksToChunks } = await import(\"../chunks.js\")\n const chunks = blocksToChunks(result.blocks, { tableFormat: parseOptions.tableFormat }).map(c => {\n let text = c.text\n if (opts.plain) text = toPlainMarkdown(text)\n if (opts.htmlTables) text = toHtmlTables(text)\n return { ...c, text: linkImages(text) }\n })\n output = JSON.stringify(chunks, null, 2)\n } else {\n output = markdown\n }\n\n // 이미지 저장 (--out-dir 또는 --output 시) — 실제 인라인된 경우(HWP5)에만 미저장, 그 외엔 저장 유지\n const saveImages = (dir: string) => {\n if (!result.images?.length || imagesInlined) return\n const imgDir = resolve(dir, \"images\", docStem)\n mkdirSync(imgDir, { recursive: true })\n for (const img of result.images) {\n writeFileSync(resolve(imgDir, img.filename), img.data)\n }\n // images/<문서 이름>/manifest.json — 소비자가 확장자·매직바이트 추측 없이 형식 분기(#70).\n // mimeType 은 매직바이트 실측 우선 — 확장자 유래 선언값은 실데이터와 어긋날 수 있다.\n const manifest = result.images.map(img => ({\n name: img.filename,\n mimeType: detectImageMime(img.data) ?? img.mimeType,\n bytes: img.data.length,\n ...(img.source ? { source: img.source } : {}),\n }))\n writeFileSync(resolve(imgDir, \"manifest.json\"), JSON.stringify(manifest, null, 2), \"utf-8\")\n if (!opts.silent) process.stderr.write(` → ${result.images.length}개 이미지 → ${imgDir} (manifest.json 포함)\\n`)\n }\n\n // Validate the document and all image destinations together, before any file is written.\n const assertSafeDestination = (output: string, dir: string) => {\n const imageOutputs = result.images?.length && !imagesInlined\n ? [...result.images.map(img => resolve(dir, \"images\", docStem, img.filename)), resolve(dir, \"images\", docStem, \"manifest.json\")]\n : []\n assertSafeOutputs([output, ...imageOutputs])\n }\n\n if (opts.output && files.length === 1) {\n assertSafeDestination(opts.output, resolve(opts.output, \"..\"))\n writeFileSync(opts.output, output, \"utf-8\")\n if (!opts.silent) process.stderr.write(` → ${opts.output}\\n`)\n saveImages(resolve(opts.output, \"..\"))\n } else if (opts.outDir) {\n mkdirSync(opts.outDir, { recursive: true })\n const outExt = opts.format === \"json\" ? \".json\" : opts.format === \"chunks\" ? \".chunks.json\" : \".md\"\n // 확장자 없는 입력(\"slides\")도 이름 뒤에 붙인다 — 종전 replace 는 그대로 두어 -d 가 입력 폴더면 입력 파일을 덮어썼다\n const outPath = resolve(opts.outDir, fileName.replace(/\\.[^.]+$/, \"\") + outExt)\n assertSafeDestination(outPath, opts.outDir)\n writeFileSync(outPath, output, \"utf-8\")\n if (!opts.silent) process.stderr.write(` → ${outPath}\\n`)\n saveImages(opts.outDir)\n } else {\n writeOutput(output + \"\\n\")\n }\n } catch (err) {\n process.stderr.write(`\\n[kordoc] ERROR: ${fileName} — ${sanitizeError(err)}\\n`)\n // 파싱 이후(출력·직렬화) 단계에서 터져도 실패 JSON 을 내야 호출자가 원인 코드로\n // 분기할 수 있다 — 종전엔 성공 로그 뒤 비-JSON 이었다 (#65). json 외 포맷에도\n // 동일 계약을 적용한다 (#69).\n writeOutput(JSON.stringify({\n success: false,\n fileType: detectedFormat,\n // 다중 입력에서 어느 파일이 실패했는지 호출자가 기계적으로 특정할 수 있게 한다 (#69).\n // basename 만 노출 — 전체 경로는 내부 정보로 보아 넣지 않는다.\n file: fileName,\n error: sanitizeError(err),\n code: classifyError(err),\n }, null, 2) + \"\\n\")\n failed = true\n }\n }\n return !failed\n}\n","/** Protect every batch input, including symlink and hardlink aliases, before writing output. */\nimport { statSync } from \"node:fs\"\nimport { basename, resolve } from \"node:path\"\n\nexport function createOutputGuard(inputs: string[]): (outputs: string[]) => void {\n const paths = new Map(inputs.map(input => [resolve(input), basename(input)]))\n const identities = new Map<string, string>()\n for (const [input, name] of paths) {\n try {\n const stat = statSync(input, { bigint: true })\n identities.set(`${stat.dev}:${stat.ino}`, name)\n } catch { /* Missing or unreadable inputs are reported by the normal conversion path. */ }\n }\n return outputs => {\n for (const output of outputs) {\n let input = paths.get(resolve(output))\n if (!input) {\n try {\n const stat = statSync(output, { bigint: true })\n input = identities.get(`${stat.dev}:${stat.ino}`)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\" && (err as NodeJS.ErrnoException).code !== \"ENOTDIR\") throw err\n }\n }\n if (input) throw new Error(`출력 경로가 입력 파일과 같습니다: ${input}`)\n }\n }\n}\n","/** Bounded, persistent process pool: CPU-heavy parsers get separate JS runtimes. */\nimport { fork, type ChildProcess } from \"node:child_process\"\nimport { basename } from \"node:path\"\nimport type { Command, OptionValues } from \"commander\"\nimport { KordocError } from \"../utils.js\"\nimport { convertFiles } from \"./convert.js\"\nimport { createOutputGuard } from \"./output-path.js\"\n\ninterface Job { file: string; opts: OptionValues; inputs?: string[] }\ninterface Done { ok: boolean; output: string[] }\n\nexport function registerBatchWorker(program: Command): void {\n program.command(\"__convert-worker\", { hidden: true }).action(() => {\n if (!process.send) program.error(\"Internal command requires an IPC channel\")\n // Do not leave native parser handles alive if the parent disappears.\n process.on(\"disconnect\", () => process.exit(0))\n let assertSafeOutputs: ReturnType<typeof createOutputGuard> | undefined\n process.on(\"message\", async ({ file, opts, inputs }: Job) => {\n const output: string[] = []\n assertSafeOutputs ??= createOutputGuard(inputs ?? [file])\n const ok = await convertFiles([file], opts, text => { output.push(text) }, assertSafeOutputs)\n process.send!({ ok, output } satisfies Done)\n })\n })\n}\n\n/**\n * Both converted documents and image directories are named after the input stem. Reject ambiguous\n * destinations before anything is written, including case variants — sequential `-d` runs used to\n * overwrite `a.md` and mix `images/a/` silently when two inputs shared a stem.\n */\nexport function assertDistinctStems(files: string[]): void {\n const stems = new Set<string>()\n for (const file of files) {\n const stem = basename(file).replace(/\\.[^.]+$/, \"\").normalize(\"NFC\").toLowerCase()\n if (stems.has(stem)) throw new KordocError(`Output name collision: ${basename(file)}; use distinct file stems`)\n stems.add(stem)\n }\n}\n\nexport async function convertParallel(files: string[], opts: OptionValues, jobs: number): Promise<boolean> {\n assertDistinctStems(files)\n\n const workers: ChildProcess[] = []\n let next = 0\n let failed = false\n const stop = () => { for (const worker of workers) worker.kill() }\n const onSigint = () => { stop(); process.exit(130) }\n const onSigterm = () => { stop(); process.exit(143) }\n process.once(\"SIGINT\", onSigint)\n process.once(\"SIGTERM\", onSigterm)\n try {\n await Promise.all(Array.from({ length: Math.min(jobs, files.length) }, () => new Promise<void>((resolve, reject) => {\n // Fork the same entry point: works in the bundled CLI and under tsx in tests.\n // Options travel over IPC so passwords never appear in child command lines.\n const worker = fork(process.argv[1], [\"__convert-worker\"], { stdio: [\"ignore\", \"ignore\", \"inherit\", \"ipc\"] })\n workers.push(worker)\n let current: string | undefined\n let finished = false\n let firstJob = true\n worker.on(\"error\", reject)\n worker.on(\"exit\", (code, signal) => {\n if (!finished) reject(new KordocError(`Conversion worker exited (${signal ?? code}) while processing ${basename(current ?? \"unknown\")}`))\n })\n const dispatch = () => {\n if (next === files.length) {\n finished = true\n worker.disconnect()\n resolve()\n return\n }\n current = files[next++]\n if (!opts.silent) process.stderr.write(`[kordoc] [${next}/${files.length}] ${basename(current)} ...\\n`)\n // Each worker writes a separate output tree; successful document data stays\n // in the worker, avoiding large IPC copies and buffering the entire batch.\n worker.send({ file: current, opts: { ...opts, output: undefined, silent: true }, ...(firstJob ? { inputs: files } : {}) } satisfies Job, err => {\n if (err) reject(err)\n })\n firstJob = false\n }\n worker.on(\"message\", ({ ok, output }: Done) => {\n if (!ok) failed = true\n // Only the parent writes stdout, preserving each failure JSON as one unit.\n for (const text of output) process.stdout.write(text)\n if (!opts.silent) process.stderr.write(`[kordoc] ${basename(current!)} ${ok ? \"OK\" : \"FAIL\"}\\n`)\n dispatch()\n })\n dispatch()\n })))\n return !failed\n } finally {\n stop()\n process.removeListener(\"SIGINT\", onSigint)\n process.removeListener(\"SIGTERM\", onSigterm)\n }\n}\n","/** kordoc CLI 명령 — 문서 처리 — watch·fill·seal·patch·validate */\n\nimport { readFileSync, writeFileSync, mkdirSync, statSync } from \"fs\"\nimport { basename, dirname, resolve, extname } from \"path\"\nimport { Command } from \"commander\"\nimport { parse, detectFormat, detectZipFormat, fillFormFields, extractFormFields, blocksToMarkdown, markdownToHwpx, fillHwpx, fillWithUniqueGuard, PRESET_ALIAS, extractClickHereFields, BUILTIN_TEMPLATES, resolveBuiltinTemplate, readBuiltinTemplate } from \"../index.js\"\nimport type { FillInput } from \"../index.js\"\nimport { fillPlan } from \"../form/match.js\"\nimport { toArrayBuffer, sanitizeError } from \"../utils.js\"\n\n\nexport function registerDocCommands(program: Command): void {\n program\n .command(\"watch <dir>\")\n .description(\"디렉토리 감시 — 새 문서 자동 변환\")\n .option(\"--webhook <url>\", \"결과 전송 웹훅 URL\")\n .option(\"-d, --out-dir <dir>\", \"변환 결과 출력 디렉토리\")\n .option(\"-p, --pages <range>\", \"페이지/섹션 범위\")\n .option(\"--format <type>\", \"출력 형식: markdown 또는 json\", \"markdown\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (dir: string, opts, command: Command) => {\n // 루트 커맨드의 동명 옵션(-d/--out-dir·-p/--pages·--format·--silent)이 서브커맨드 뒤에서도 루트로 흡수되는 commander 동작 보완\n const rootOpts = program.opts()\n opts.outDir ??= rootOpts.outDir\n opts.pages ??= rootOpts.pages\n opts.silent ??= rootOpts.silent\n if (command.getOptionValueSource(\"format\") === \"default\" && program.getOptionValueSource(\"format\") === \"cli\") {\n opts.format = rootOpts.format\n }\n const { watchDirectory } = await import(\"../watch.js\")\n await watchDirectory({\n dir,\n outDir: opts.outDir,\n webhook: opts.webhook,\n format: opts.format,\n pages: opts.pages,\n silent: opts.silent,\n })\n })\n\n program\n .command(\"fill [file]\")\n .description(\"서식 문서의 빈칸을 채워서 출력 — kordoc fill 신청서.hwpx -f '성명=홍길동,전화=010-1234-5678' -o 결과.hwpx / 내장 기안문 서식은 kordoc fill --template gian\")\n .option(\"-f, --fields <pairs>\", \"채울 필드 (key=value 쉼표 구분 또는 JSON)\")\n .option(\"-j, --json <path>\", \"채울 필드 JSON 파일 경로\")\n .option(\"-o, --output <path>\", \"출력 파일 경로 (확장자로 포맷 결정: .md, .hwpx)\")\n .option(\"--format <type>\", \"출력 포맷: hwpx-preserve (기본, 원본 스타일 보존), hwpx, markdown\", \"hwpx-preserve\")\n .option(\"--formats <json>\", \"필드별 값 서식 JSON (라벨→포맷) — 예: '{\\\"날짜\\\":\\\"yy.mm.dd\\\",\\\"주민등록번호\\\":\\\"rrn:masked\\\"}'\")\n .option(\"--template <name>\", \"내장 표준 서식 사용 (파일 경로 불필요): gian(일반기안문) | gian-simple(간이기안문). 위치 인자 'templates:일반기안문' 표기도 동일\")\n .option(\"--list-templates\", \"내장 표준 서식 목록 + 누름틀 필드 나열\")\n .option(\"--require-unique\", \"한 키가 서식의 2곳 이상에 매칭되면 채우지 않고 거부 (반복 라벨 양식 오염 방지)\")\n .option(\"--mask\", \"채운 값 미노출 — 출력 파일 없이 markdown을 stdout으로 낼 때 본문 대신 안내만 표시\")\n .option(\"--dry-run\", \"채우지 않고 서식 필드 목록만 출력 — -j/-f 를 함께 주면 키·배열 번호별로 값을 쓸 칸(표·행·열)을 JSON 으로\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string | undefined, opts, command: Command) => {\n try {\n // 루트 커맨드의 동명 옵션(-o/--output·--format·--silent)이 서브커맨드 뒤에서도 루트로 흡수되는 commander 동작 보완\n const rootOpts = program.opts()\n opts.output ??= rootOpts.output\n opts.silent ??= rootOpts.silent\n if (command.getOptionValueSource(\"format\") === \"default\" && program.getOptionValueSource(\"format\") === \"cli\") {\n opts.format = rootOpts.format\n }\n\n if (![\"hwpx-preserve\", \"hwpx\", \"markdown\"].includes(opts.format)) {\n process.stderr.write(`[kordoc] --format 는 hwpx-preserve/hwpx/markdown 중 하나여야 합니다: ${opts.format}\\n`)\n process.exit(1)\n }\n\n // --list-templates: 내장 서식 목록 + 누름틀 필드\n if (opts.listTemplates) {\n const list = []\n for (const t of BUILTIN_TEMPLATES) {\n const fields = await extractClickHereFields(readBuiltinTemplate(t))\n list.push({ id: t.id, aliases: t.aliases, title: t.title, fields: fields.map(f => f.name) })\n }\n process.stdout.write(JSON.stringify(list, null, 2) + \"\\n\")\n return\n }\n\n // 입력 소스 결정 — 내장 템플릿(--template 또는 'templates:이름' 위치 인자) 우선\n const templateName = opts.template ?? (file && /^templates?:/i.test(file) ? file : undefined)\n let arrayBuffer: ArrayBuffer\n let inputName: string\n if (templateName) {\n const t = resolveBuiltinTemplate(templateName)\n if (!t) {\n process.stderr.write(`[kordoc] 알 수 없는 내장 템플릿: ${templateName} (사용 가능: ${BUILTIN_TEMPLATES.map(x => `${x.id}(${x.aliases[0]})`).join(\", \")})\\n`)\n process.exit(1)\n }\n arrayBuffer = readBuiltinTemplate(t)\n inputName = t.file\n } else if (file) {\n const absPath = resolve(file)\n const fileSize = statSync(absPath).size\n if (fileSize > 500 * 1024 * 1024) {\n process.stderr.write(`[kordoc] 파일이 너무 큽니다 (${(fileSize / 1024 / 1024).toFixed(1)}MB)\\n`)\n process.exit(1)\n }\n arrayBuffer = toArrayBuffer(readFileSync(absPath))\n inputName = basename(absPath)\n } else {\n process.stderr.write(`[kordoc] 서식 파일 경로 또는 --template 을 지정해주세요 (목록: kordoc fill --list-templates)\\n`)\n process.exit(1)\n return\n }\n\n if (!opts.silent) process.stderr.write(`[kordoc] ${inputName} 파싱 중...\\n`)\n\n // --dry-run: 필드 목록만 출력 — 서식 입력란(빈 후행 열)이 목록에 나오도록 보존 (#47). 값을 함께 주면 아래에서 대상 칸을 낸다\n if (opts.dryRun && !opts.json && !opts.fields) {\n const result = await parse(arrayBuffer, { keepTrailingEmptyCols: true, layoutTables: \"keep\" })\n if (!result.success) {\n process.stderr.write(`[kordoc] 파싱 실패: ${result.error}\\n`)\n process.exit(1)\n }\n const formInfo = extractFormFields(result.blocks)\n // 누름틀(CLICK_HERE) 필드도 함께 나열 — 표준 서식은 라벨 표 없이 누름틀만 있을 수 있다\n const clickHereFields = detectFormat(arrayBuffer) === \"hwpx\"\n ? await extractClickHereFields(arrayBuffer)\n : []\n if (formInfo.fields.length === 0 && clickHereFields.length === 0) {\n process.stderr.write(`[kordoc] 서식 필드를 찾을 수 없습니다.\\n`)\n process.exit(1)\n }\n process.stdout.write(JSON.stringify(\n clickHereFields.length > 0 ? { ...formInfo, clickHereFields } : formInfo,\n null, 2,\n ) + \"\\n\")\n return\n }\n\n // 필드 값 파싱\n let values: Record<string, string> = {}\n if (opts.json) {\n const jsonPath = resolve(opts.json)\n // Windows 메모장·PowerShell 이 붙이는 UTF-8 BOM 은 JSON.parse 가 거부한다\n const jsonContent = readFileSync(jsonPath, \"utf-8\").replace(/^/, \"\")\n values = JSON.parse(jsonContent)\n } else if (opts.fields) {\n const fieldsStr: string = opts.fields\n if (fieldsStr.startsWith(\"{\")) {\n values = JSON.parse(fieldsStr)\n } else {\n // \"key1=value1,key2=value2\" 파싱 — 값에 쉼표가 있을 수 있으므로\n // '=' 앞의 키를 기준으로 분리 (쉼표+한글/영문+= 패턴)\n const pairs = fieldsStr.split(/,(?=[가-힣A-Za-z][가-힣A-Za-z\\s]*=)/)\n for (const pair of pairs) {\n const eqIdx = pair.indexOf(\"=\")\n if (eqIdx > 0) {\n const key = pair.slice(0, eqIdx).trim()\n const val = pair.slice(eqIdx + 1).trim()\n values[key] = val\n }\n }\n }\n } else {\n process.stderr.write(`[kordoc] 채울 필드를 지정해주세요 (-f 또는 -j 옵션)\\n`)\n process.exit(1)\n }\n\n // 필드별 값 서식 결합 — MCP fill_form(formats)과 동일 의미론 (form/match.js FillInput)\n let inputs: Record<string, FillInput> = values\n if (opts.formats) {\n let formatMap: Record<string, string>\n try {\n formatMap = JSON.parse(String(opts.formats))\n } catch {\n process.stderr.write(`[kordoc] --formats 는 JSON 객체여야 합니다 (라벨→포맷)\\n`)\n process.exit(1)\n }\n inputs = Object.fromEntries(Object.entries(values).map(([k, v]) => {\n const format = formatMap[k]\n return [k, format ? { value: v, format } : v]\n }))\n }\n\n // 출력 포맷 결정 — 확장자 오버라이드가 명시 --format 과 충돌하면 경고 후 확장자 우선\n let outputFormat = opts.format as string\n if (opts.output) {\n const ext = extname(opts.output).toLowerCase()\n const explicitFormat = command.getOptionValueSource(\"format\") === \"cli\" || program.getOptionValueSource(\"format\") === \"cli\"\n const before = outputFormat\n if (ext === \".hwpx\") outputFormat = outputFormat === \"markdown\" ? \"hwpx-preserve\" : outputFormat\n else if (ext === \".md\") outputFormat = \"markdown\"\n if (explicitFormat && before !== outputFormat) {\n process.stderr.write(`[kordoc] ⚠️ --format ${before} 가 출력 확장자(${ext})와 충돌합니다 — 확장자 기준 ${outputFormat} 로 진행\\n`)\n }\n }\n\n // ─── hwpx-preserve: 원본 ZIP 직접 수정 ───\n if (outputFormat === \"hwpx-preserve\") {\n const format = detectFormat(arrayBuffer)\n let isHwpx = format === \"hwpx\"\n if (isHwpx) {\n const zipFormat = await detectZipFormat(arrayBuffer)\n isHwpx = zipFormat === \"hwpx\"\n }\n if (!isHwpx) {\n if (!opts.silent) process.stderr.write(`[kordoc] HWPX가 아니므로 hwpx 모드로 전환합니다\\n`)\n outputFormat = \"hwpx\"\n } else {\n const hwpxResult = opts.requireUnique\n ? await fillWithUniqueGuard(inputs, (vals, blocked) => fillHwpx(arrayBuffer, vals, blocked))\n : { ...(await fillHwpx(arrayBuffer, inputs)), rejected: [] as string[] }\n if (opts.dryRun) {\n process.stdout.write(JSON.stringify(fillPlan(inputs, hwpxResult.filled, hwpxResult.unmatched, hwpxResult.rejected), null, 2) + \"\\n\")\n return\n }\n if (!opts.silent) {\n process.stderr.write(`[kordoc] ${hwpxResult.filled.length}개 필드 채움 (원본 스타일 보존)\\n`)\n if (hwpxResult.rejected.length > 0) {\n process.stderr.write(`[kordoc] ⚠️ 모호 라벨 거부(2곳+ 매칭): ${hwpxResult.rejected.join(\", \")}\\n`)\n }\n if (hwpxResult.unmatched.length > 0) {\n process.stderr.write(`[kordoc] ⚠️ 매칭 실패: ${hwpxResult.unmatched.join(\", \")}\\n`)\n }\n }\n if (opts.output) {\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\n writeFileSync(resolve(opts.output), Buffer.from(hwpxResult.buffer))\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\n } else {\n process.stdout.write(Buffer.from(hwpxResult.buffer))\n }\n return\n }\n }\n\n // ─── 일반 경로: parse → fill → output ─── (양식 입력란 보존, #47)\n const result = await parse(arrayBuffer, { keepTrailingEmptyCols: true, layoutTables: \"keep\" })\n if (!result.success) {\n process.stderr.write(`[kordoc] 파싱 실패: ${result.error}\\n`)\n process.exit(1)\n }\n\n const formInfo = extractFormFields(result.blocks)\n if (!opts.silent) {\n process.stderr.write(`[kordoc] 서식 필드 ${formInfo.fields.length}개 감지 (확신도 ${(formInfo.confidence * 100).toFixed(0)}%)\\n`)\n }\n\n const fillResult = opts.requireUnique\n ? await fillWithUniqueGuard(inputs, (vals, blocked) => fillFormFields(result.blocks, vals, blocked))\n : { ...fillFormFields(result.blocks, inputs), rejected: [] as string[] }\n if (opts.dryRun) {\n process.stdout.write(JSON.stringify(fillPlan(inputs, fillResult.filled, fillResult.unmatched, fillResult.rejected), null, 2) + \"\\n\")\n return\n }\n if (!opts.silent) {\n process.stderr.write(`[kordoc] ${fillResult.filled.length}개 필드 채움\\n`)\n if (fillResult.rejected.length > 0) {\n process.stderr.write(`[kordoc] ⚠️ 모호 라벨 거부(2곳+ 매칭): ${fillResult.rejected.join(\", \")}\\n`)\n }\n if (fillResult.unmatched.length > 0) {\n process.stderr.write(`[kordoc] ⚠️ 매칭 실패: ${fillResult.unmatched.join(\", \")}\\n`)\n }\n }\n\n const markdown = blocksToMarkdown(fillResult.blocks)\n\n if (outputFormat === \"hwpx\") {\n const hwpxBuffer = await markdownToHwpx(markdown)\n if (opts.output) {\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\n writeFileSync(resolve(opts.output), Buffer.from(hwpxBuffer))\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\n } else {\n process.stdout.write(Buffer.from(hwpxBuffer))\n }\n } else {\n if (opts.output) {\n mkdirSync(dirname(resolve(opts.output)), { recursive: true })\n writeFileSync(resolve(opts.output), markdown, \"utf-8\")\n if (!opts.silent) process.stderr.write(`[kordoc] → ${resolve(opts.output)}\\n`)\n } else if (opts.mask) {\n // 채운 값(주민번호·연락처 등)이 터미널 로그에 남지 않게 본문 대신 안내 (MCP mask_values와 동일 취지)\n process.stdout.write(`⚠️ --mask 활성 — 개인정보 노출 방지를 위해 본문을 출력하지 않습니다. -o 로 파일 저장 후 확인하세요.\\n`)\n } else {\n process.stdout.write(markdown + \"\\n\")\n }\n }\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"seal <file>\")\n .description('도장/서명 이미지를 앵커 문구 위에 부유 배치 (표/페이지 불확장) — kordoc seal 신청서.hwpx --image 도장.png --anchor \"(인)\" -o 결과.hwpx')\n .requiredOption(\"--image <path>\", \"도장/서명 이미지 (투명 배경 PNG 권장)\")\n .option(\"--anchor <text>\", \"앵커 문구\", \"(인)\")\n .option(\"-n, --occurrence <num>\", \"같은 앵커가 여럿일 때 0-based 선택\", \"0\")\n .option(\"--size-mm <num>\", \"도장 한 변 크기 mm (기본: 줄높이×1.6, 7~18 클램프)\")\n .option(\"--mode <mode>\", \"overlap(문구 위 겹침) | right(오른쪽 옆) | auto\", \"auto\")\n .option(\"--dx <mm>\", \"x 미세조정 mm\", \"0\")\n .option(\"--dy <mm>\", \"y 미세조정 mm\", \"0\")\n .option(\"-o, --output <path>\", \"출력 경로 (기본: <입력>.sealed.hwpx)\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const { placeSealHwpx, detectFormat } = await import(\"../index.js\")\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const silent: boolean = opts.silent ?? rootOpts.silent\n const mode = String(opts.mode).toLowerCase()\n if (![\"overlap\", \"right\", \"auto\"].includes(mode)) {\n process.stderr.write(`[kordoc] --mode 는 overlap/right/auto 중 하나여야 합니다\\n`)\n process.exit(1)\n }\n const buf = new Uint8Array(readFileSync(resolve(file)))\n if (detectFormat(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer) !== \"hwpx\") {\n process.stderr.write(`[kordoc] seal 은 HWPX 전용입니다 (HWP 5.x 바이너리는 미지원)\\n`)\n process.exit(1)\n }\n const imgPath = resolve(opts.image)\n const imgSize = statSync(imgPath).size\n if (imgSize > 500 * 1024 * 1024) {\n process.stderr.write(`[kordoc] 도장 이미지가 너무 큽니다 (${(imgSize / 1024 / 1024).toFixed(0)}MB)\\n`)\n process.exit(1)\n }\n const image = new Uint8Array(readFileSync(imgPath))\n const ext = extname(opts.image).slice(1).toLowerCase() || \"png\"\n // 숫자 플래그 엄격 검증 — 비숫자가 NaN→0 무증상 강제, 음수 occurrence가 truthy로\n // 통과하던 것 차단 (MCP zod와 동등, v4.0.6: --size-mm만 검증하던 것을 전 숫자 플래그로)\n const parseNum = (flag: string, raw: unknown, { min, allowNeg = false }: { min?: number; allowNeg?: boolean } = {}): number => {\n const n = Number(raw)\n if (!Number.isFinite(n) || (!allowNeg && n < 0) || (min !== undefined && n < min)) {\n process.stderr.write(`[kordoc] ${flag} 값이 잘못됐습니다: ${raw}${allowNeg ? \"\" : \" (0 이상 숫자)\"}\\n`)\n process.exit(1)\n }\n return n\n }\n let sizeMm: number | undefined\n if (opts.sizeMm != null) {\n const n = Number(opts.sizeMm)\n if (!Number.isFinite(n) || n <= 0) {\n process.stderr.write(`[kordoc] --size-mm 은 양수여야 합니다: ${opts.sizeMm}\\n`)\n process.exit(1)\n }\n sizeMm = n\n }\n const result = await placeSealHwpx(\n buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer,\n [{\n anchor: opts.anchor,\n occurrence: parseNum(\"--occurrence\", opts.occurrence),\n image,\n ext: ext as \"png\" | \"jpg\" | \"jpeg\" | \"bmp\" | \"gif\",\n sizeMm,\n mode: mode as \"overlap\" | \"right\" | \"auto\",\n dxMm: parseNum(\"--dx\", opts.dx, { allowNeg: true }),\n dyMm: parseNum(\"--dy\", opts.dy, { allowNeg: true }),\n }],\n )\n const outPath = resolve(output ?? file.replace(/\\.hwpx$/i, \"\") + \".sealed.hwpx\")\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, Buffer.from(result.buffer))\n if (!silent) {\n for (const p of result.placed) {\n process.stderr.write(`[kordoc] 도장 배치: \"${p.anchor}\" #${p.occurrence} → ${p.mode} (${p.posXMm}mm, ${p.posYMm}mm, ${p.sizeMm}mm) [${p.entry}]\\n`)\n for (const w of p.warnings ?? []) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n }\n process.stderr.write(`[kordoc] → ${outPath}\\n`)\n }\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"patch <original> <edited>\")\n .description(\"서식 보존 라운드트립 패치 — 편집된 마크다운을 원본 HWPX/HWP에 in-place 반영 (kordoc patch 원본.hwpx 편집.md -o 출력.hwpx). 견본 서식 그대로 새 문서 쓰기(서식 베끼기)도 이 경로: 견본을 --keep-layout-tables 로 읽어 내용만 새로 쓴 뒤 patch — HWPX 는 문단 추가·삭제를 같은 항목 부호 견본 문단 서식으로 반영. 미적용(skip) 편집이 있으면 exit 2\")\n .option(\"-o, --output <path>\", \"출력 경로 (기본: <원본>.patched.hwpx|.hwp)\")\n .option(\"--no-verify\", \"패치 후 재파싱 자동 검증 생략\")\n .option(\"--no-structure\", \"문단 추가·삭제를 반영하지 않고 건너뜀 (HWPX — 글 수정만, 문서 골격 고정)\")\n .option(\"--keep-lineseg\", \"글이 바뀐 문단의 줄 나눔 정보를 지우지 않고 원본 줄 위치를 남김 (HWP 5.x — 기본은 지워서 한컴이 다시 짬)\")\n .option(\"--json\", \"결과(적용 수·건너뛴 편집·검증 잔차)를 JSON 으로 stdout 출력 — --silent 와 함께 써도 나온다\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (original: string, edited: string, opts) => {\n try {\n const { patchHwpx, patchHwp, detectFormat } = await import(\"../index.js\")\n // 루트 커맨드의 동명 옵션(-o/--silent)이 서브커맨드 옵션을 가로채는 commander 동작 보완\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const silent: boolean = opts.silent ?? rootOpts.silent\n const originalBuf = new Uint8Array(readFileSync(resolve(original)))\n const editedMarkdown = readFileSync(resolve(edited), \"utf-8\")\n\n const format = detectFormat(originalBuf.buffer as ArrayBuffer)\n const result = format === \"hwp\"\n ? await patchHwp(originalBuf, editedMarkdown, { verify: opts.verify !== false, keepLineseg: opts.keepLineseg === true })\n : await patchHwpx(originalBuf, editedMarkdown, { verify: opts.verify !== false, structure: opts.structure !== false })\n if (!result.success || !result.data) {\n if (opts.json) process.stdout.write(JSON.stringify({ success: false, error: result.error ?? \"알 수 없는 오류\", applied: result.applied, skipped: result.skipped }, null, 2) + \"\\n\")\n process.stderr.write(`[kordoc] 패치 실패: ${result.error ?? \"알 수 없는 오류\"}\\n`)\n process.exit(1)\n }\n\n const ext = format === \"hwp\" ? \".hwp\" : \".hwpx\"\n const outPath = resolve(output ?? original.replace(/\\.hwpx?$/i, \"\") + \".patched\" + ext)\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, result.data)\n\n if (opts.json) {\n // 외부 도구가 부분 적용(skip)·검증 잔차를 사용자에게 알릴 수 있게 — --silent 로는 사유가 통째로 사라졌다\n process.stdout.write(JSON.stringify({\n success: true, output: outPath, applied: result.applied, skipped: result.skipped,\n ...(result.warnings ? { warnings: result.warnings } : {}),\n ...(result.verification ? { verification: result.verification.stats } : {}),\n }, null, 2) + \"\\n\")\n }\n if (!silent && !opts.json) {\n process.stderr.write(`[kordoc] ${result.applied}개 변경 적용 (원본 서식 보존) → ${outPath}\\n`)\n for (const s of result.skipped) {\n process.stderr.write(`[kordoc] ⚠️ SKIP: ${s.reason}${s.before ? ` | ${s.before}` : \"\"}\\n`)\n }\n for (const w of result.warnings ?? []) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n if (result.verification) {\n const v = result.verification.stats\n const residual = v.added + v.removed + v.modified\n process.stderr.write(residual === 0\n ? `[kordoc] ✓ 검증: 편집 마크다운과 재파싱 결과 완전 일치 (${v.unchanged}블록)\\n`\n : `[kordoc] ⚠️ 검증 잔차: 수정 ${v.modified}, 추가 ${v.added}, 삭제 ${v.removed} (미지원 변경은 skip 목록 참조)\\n`)\n }\n }\n if (result.skipped.length > 0) process.exitCode = 2\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"compare <a> <b>\")\n .description(\"두 문서 비교 — 추가·삭제·변경 블록 (HWP↔HWPX 등 형식이 달라도 됨, 신구대조표용). 차이가 있으면 exit 1\")\n .option(\"--json\", \"비교 결과(stats·diffs)를 JSON 으로 stdout 출력\")\n .action(async (a: string, b: string, opts) => {\n try {\n const { compare } = await import(\"../index.js\")\n const read = (p: string): ArrayBuffer => { const buf = readFileSync(resolve(p)); return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer }\n const result = await compare(read(a), read(b))\n const { stats, diffs } = result\n if (opts.json) process.stdout.write(JSON.stringify(result, null, 2) + \"\\n\")\n else {\n process.stdout.write(`추가 ${stats.added} · 삭제 ${stats.removed} · 변경 ${stats.modified} · 동일 ${stats.unchanged}\\n`)\n for (const d of diffs) {\n if (d.type === \"unchanged\") continue\n const mark = d.type === \"added\" ? \"+\" : d.type === \"removed\" ? \"-\" : \"~\"\n const text = (blk?: { text?: string; table?: unknown }) => (blk?.text ?? (blk?.table ? \"[표]\" : \"\")).replace(/\\s+/g, \" \").slice(0, 160)\n if (d.type === \"modified\") process.stdout.write(`~ ${text(d.before)}\\n → ${text(d.after)}\\n`)\n else process.stdout.write(`${mark} ${text(d.after ?? d.before)}\\n`)\n }\n }\n process.exit(stats.added + stats.removed + stats.modified > 0 ? 1 : 0)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(2)\n }\n })\n\n program\n .command(\"validate <file>\")\n .description(\"HWPX 구조 검증 — ZIP·mimetype·필수 파일·XML 웰폼드·secCnt·manifest 참조 (한컴독스 거부 요인 사전 차단)\")\n .option(\"--json\", \"결과를 JSON으로 stdout에 출력\")\n .action(async (file: string, opts) => {\n try {\n const { validateHwpx } = await import(\"../index.js\")\n const buf = new Uint8Array(readFileSync(resolve(file)))\n const result = await validateHwpx(buf)\n if (opts.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + \"\\n\")\n } else if (result.ok) {\n process.stderr.write(`[kordoc] ✓ 구조 검증 통과 (엔트리 ${result.entryCount}개): ${file}\\n`)\n } else {\n process.stderr.write(`[kordoc] ✗ 구조 문제 ${result.issues.length}건: ${file}\\n`)\n for (const i of result.issues) {\n process.stderr.write(`[kordoc] - ${i.path ? `${i.path}: ` : \"\"}${i.message}\\n`)\n }\n }\n if (!result.ok) process.exit(1)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n // 공문서 프리셋 별칭(한글/영문) → 내부 preset 키 — gongmun.ts와 공용(PRESET_ALIAS)\n}\n","/** kordoc CLI 명령 — 생성·검수 — generate·profile·lint·redact */\n\nimport { readFileSync, writeFileSync, mkdirSync, statSync } from \"fs\"\nimport { basename, dirname, resolve } from \"path\"\nimport type { numberBlocksFromIR } from \"../hwpx/number-lint.js\"\nimport { runLintSuite } from \"../hwpx/lint-suite.js\"\nimport { lintBlocks } from \"../hwpx/lint-blocks.js\"\nimport { extractLevelStyles } from \"../hwpx/level-styles.js\"\nimport { detectFormat, markdownToHwpx, hwpxToProfile, PRESET_ALIAS, unknownFontWarnings, incompatibleGongmunWarnings, gongmunLintWarnings, muncheLintWarnings, usesGaejosikMunche, slopLintWarnings, logicLintWarnings, usesLogicStructure, gongmunGate, formatGateFinding } from \"../index.js\"\nimport { parseFormatProfileJson } from \"../hwpx/profile-io.js\"\nimport { loadGenerationImages } from \"../shared/generate-images.js\"\nimport { buildGongmunOptions, BODY_FONTS, H2_MARKERS, BULLET2_CHARS, TOTAL_ROWS, parseLevelsSpec, levelFontRecord, templateConflictMessage } from \"../hwpx/gongmun-surface.js\"\nimport type { FormatProfile } from \"../hwpx/gen-profile.js\"\nimport { toArrayBuffer, sanitizeError } from \"../utils.js\"\nimport type { Command } from \"commander\"\n\n/** --template 과 함께 못 쓰는 옵션 (commander 키) — 서식·쪽·이미지는 견본이 정한다 */\nconst TEMPLATE_CLI_CONFLICTS = [\n \"preset\", \"font\", \"pt\", \"lineSpacing\", \"profile\", \"org\", \"date\", \"toc\", \"cover\", \"approval\", \"pageNumbers\", \"endMark\",\n \"bodyTitleBox\", \"chapterFit\", \"h2Marker\", \"bandColor\", \"bandTextColor\", \"summary\", \"docInfo\", \"dept\", \"checklist\", \"coverLabel\",\n \"fonts\", \"sizes\", \"levels\", \"levelsFrom\", \"bullet2\", \"agency\", \"suppressSingle\", \"docHead\", \"docFoot\", \"reportInfo\",\n \"noticeHead\", \"pressHead\", \"pressSub\", \"pressPeople\", \"plain\", \"paper\", \"landscape\", \"columns\", \"header\", \"footer\",\n \"imageDir\", \"inlineMath\",\n]\n\nexport function registerGenerateCommands(program: Command): void {\n program\n .command(\"generate <markdown>\")\n .alias(\"gen\")\n .description(\"마크다운 → 공문서 HWPX 생성 — kordoc generate 보고서.md -o 보고서.hwpx --preset 보고서 (markdown에 '-' 지정 시 stdin)\")\n .option(\"-o, --output <path>\", \"출력 HWPX 경로 (기본: <입력>.hwpx)\")\n .option(\"--preset <name>\", \"공문서 프리셋: 기안문(official)·보고서(report)·계획서(plan)·통지(notice)·회의록(minutes)·개조식(gaejosik — 표지·목차·장헤더 자동)·업무보고(ministry — 중앙부처 업무보고: 장 띠·절 숫자칸·소제목 박스·① 항목 띠·성과 요약박스·별첨 띠)·서울방침(bangchim — 서울시 방침서: 제목표·파랑 부제·요약박스·[Ⅰ] 장 상자·절 띠·❶ 과제)·보도자료(press)\", \"기안문\")\n .option(\"--font <type>\", \"본문 글꼴: myeongjo(함초롬바탕) 또는 gothic(맑은 고딕)\")\n .option(\"--pt <size>\", \"본문 글자 크기(pt)\")\n .option(\"--line-spacing <percent>\", \"본문 줄간격(%)\")\n .option(\"--profile <path>\", \"서식 프로필 JSON (kordoc profile로 추출) — 참조 문서의 표 테두리·음영·열폭·셀 글꼴 재현\")\n .option(\"--template <hwpx>\", \"부서 서식 견본 HWPX — 견본의 쪽 설정·글꼴·제목표·담당 줄·요약 상자·□○-·※ 문단·표·참고 띠 서식을 그대로 쓰고 내용만 마크다운으로 (프리셋·서식·쪽 옵션과 함께 못 씀)\")\n .option(\"--org <name>\", \"표지 기관명 (표지를 켜는 프리셋 공통)\")\n .option(\"--date <date>\", \"표지 날짜 (기본 오늘 — 'YYYY. M. D.')\")\n .option(\"--toc\", \"목차 페이지 강제 켜기 (개조식 외 프리셋에서도 h2 목록으로 생성)\")\n .option(\"--no-toc\", \"목차 페이지 끄기 (개조식 프리셋 기본 켜짐)\")\n .option(\"--cover\", \"표지 페이지 강제 켜기 (개조식 외 프리셋에서도 첫 h1을 표지로)\")\n .option(\"--no-cover\", \"표지 페이지 끄기 (개조식 프리셋 기본 켜짐)\")\n .option(\"--approval <labels>\", \"결재란 직위 라벨 (쉼표 구분, 예: 담당,팀장,과장) — 문서 최상단 우측\")\n .option(\"--page-numbers\", \"쪽번호 강제 켜기 (하단 중앙 '- 1 -')\")\n .option(\"--no-page-numbers\", \"쪽번호 끄기 (개조식·보고서·계획서 기본 켜짐)\")\n .option(\"--end-mark\", \"본문 끝 '끝.' 표시 강제 켜기\")\n .option(\"--no-end-mark\", \"'끝.' 표시 끄기 (기안문 기본 켜짐)\")\n .option(\"--no-body-title-box\", \"본문 첫 페이지 제목 반복 박스 끄기 (개조식+표지 기본 켜짐)\")\n .option(\"--chapter-fit\", \"개조식 장 헤더 제목 칸을 글자 폭에 맞춤 (기본: 본문 폭까지)\")\n .option(\"--h2-marker <type>\", \"h2 장 제목 표기: band(로마자 채움 칸 + 제목 띠 표 — 보고서·계획서 기본)·roman(Ⅰ. 텍스트)·number(1. — 통지 기본)·box(장 없이 □ 대항목)·none\")\n .option(\"--band-color <hex>\", \"띠 제목 번호칸 채움색 #RRGGBB (기본 #003366 — 실측 최다. 교육청형 밝은 띠: #DFE6F7)\")\n .option(\"--band-text-color <hex>\", \"띠 제목 번호 글자색 #RRGGBB (기본 #FFFFFF — 밝은 띠면 #000000)\")\n .option(\"--summary <text>\", \"요약 박스 — 보고서·계획서·개조식·서울방침 (제목표·개조식 본문 첫 쪽 제목 상자 아래 음영 상자 — 마크다운 제목 직후 인용문(>)으로도 지정)\")\n .option(\"--doc-info <spec>\", \"보고서 표지 문서정보표: docNum=스마트도시과-123,date=2026. 9. 6.,disclosure=공개,policyNo= (--cover와 함께)\")\n .option(\"--dept <name>\", \"표지 부서명 (기관명 아래 괄호)\")\n .option(\"--checklist [na]\", \"서울 사전 검토항목 점검표(보고서·계획서·서울방침) — 값 없으면 빈 서식, 해당없음 문항 번호를 주면(6,7,8) 나머지는 검토완료\")\n .option(\"--cover-label <text>\", \"표지 우상단 취급 표시 — '대외주의'·'비공개' 빨간 테두리 박스 (업무보고 프리셋 실측)\")\n .option(\"--fonts <spec>\", \"요소별 글꼴 오버라이드: body=나눔명조,heading=나눔고딕,ref=한양중고딕,table=맑은 고딕\")\n .option(\"--sizes <spec>\", \"개조식 요소별 크기(pt): dae=16,cham=13,table=12,coverTitle=30 …\")\n .option(\"--levels <spec>\", \"항목부호 단계별 위계 타이포: 0=HY견고딕/17/bold,1=한컴돋움/15/bold,2=휴먼명조/14 (depth 0~7, 숫자=pt·bold·plain·글꼴명)\")\n .option(\"--levels-from <hwpx>\", \"견본 HWPX 에서 항목부호 단계별 글꼴·크기·굵기를 배워 적용 (kordoc levels 와 같은 추출, --levels 로 준 단계가 우선)\")\n .option(\"--bullet2 <char>\", \"2단계 항목부호: ㅇ(이응 — 기안문·공고문 실측 지배)·○(원 — 보고서 양식)·◦·❍\")\n .option(\"--agency <name>\", \"기관 서식 — 중앙행정기관 이름(국세청·교육부 …) 또는 공통. 보도자료 2,670건 실측 단계 글꼴·크기·2단계 부호·표 머리·기관 색 (보고서·계획서·업무보고·개조식·보도자료)\")\n .option(\"--suppress-single\", \"단일 형제 항목 부호 생략 (편람 규정 — 기본은 하나여도 부호 부여)\")\n .option(\"--total-row <pos>\", \"표 합계·총계·계 행 위치: top(머리행 바로 아래, 기본 — 공문 실무 관행) | bottom | keep(원고 그대로)\")\n .option(\"--doc-head <spec>\", \"기안문 두문표: org=기관명,slogan=원훈,to=수신처,title=제목 (별지 제1호서식·서울 실결재 6행 표)\")\n .option(\"--doc-foot <spec>\", \"기안문 결문표: sender=발신명의,drafter=주무관 홍길동,reviewer=과장 김철수,approver=국장 박영희,cooperator=협조자,docNum=시행(과-번호 (날짜)),receive=접수,zip=우편번호,address=주소,site=홈페이지,phone=전화,fax=전송,email=메일,disclosure=공개구분\")\n .option(\"--report-info <text>\", \"보고서 담당자 행(제목표 아래) / 기안문 우상단 보고정보 행 — 예: '(2026. 7. 11., 과장 홍길동, ☎02-120)'\")\n .option(\"--notice-head <spec>\", \"공고문 두문·결문: no=공고 제2026-1호,date=2026년 7월 11일,sender=행정안전부장관\")\n .option(\"--press-head <spec>\", \"보도자료 머리: release=보도시점,distribute=배포일,dept=담당부서,manager=담당자,phone=연락처\")\n .option(\"--press-sub <items>\", \"보도자료 부제 (세미콜론 구분, 제목 아래 '- … -')\")\n .option(\"--press-people <items>\", \"보도자료 담당 표 사람별 행 — 구분/직급/이름/전화 를 세미콜론으로: '책임자/과장/이○○/044-000-0000;담당자/사무관/김○○/044-000-0001' (부서는 --press-head dept=)\")\n .option(\"--plain\", \"공문서 모드 끄기 (범용 마크다운 변환)\")\n .option(\"--paper <size>\", \"용지: A4·A3·B4·B5·Letter 또는 '210x297'(mm)\")\n .option(\"--landscape\", \"용지 가로 방향\")\n .option(\"--columns <n>\", \"다단 개수 (1~8)\")\n .option(\"--header <text>\", \"머리말 텍스트 (모든 쪽, 인라인 마크다운 허용)\")\n .option(\"--footer <text>\", \"꼬리말 텍스트\")\n .option(\"--image-dir <dir>\", \"마크다운 이미지 참조(![](x.png))를 이 디렉토리에서 읽어 실데이터 임베드\")\n .option(\"--inline-math\", \"본문·표 셀의 인라인 수식 $…$ 를 한글 수식 개체로 (기본: 글자 유지 — 가격 표기 $ 오인 방지)\")\n .option(\"--gate\", \"공문서 게이트 — 표기법·문체 error 와 윤문(AI 문체)·구성(논리 구조) 지적이 하나라도 있으면 파일을 만들지 않고 exit 1\")\n .option(\"--json\", \"결과를 JSON 한 줄로 stdout 출력 — {output, preset, bytes, warnings}\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (markdown: string, opts, cmd: Command) => {\n try {\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const silent: boolean = opts.silent ?? rootOpts.silent\n const plain: boolean = opts.plain ?? rootOpts.plain\n\n // 입력: '-' 이면 stdin, 아니면 파일\n let md: string\n let baseName = \"document\"\n if (markdown === \"-\") {\n md = readFileSync(0, \"utf-8\")\n } else {\n const inPath = resolve(markdown)\n md = readFileSync(inPath, \"utf-8\")\n baseName = basename(inPath).replace(/\\.(md|markdown|txt)$/i, \"\")\n }\n\n // 부서 서식 견본 — 서식은 견본이 정하므로 프리셋·서식·쪽 옵션과 함께 쓰면 조용히 버리지 않고 멈춘다\n if (opts.template) {\n const clash = TEMPLATE_CLI_CONFLICTS.filter((k) => cmd.getOptionValueSource(k) === \"cli\")\n // 루트에 준 --plain(kordoc --plain generate …)도 같은 충돌\n if (plain && !clash.includes(\"plain\")) clash.push(\"plain\")\n if (clash.length) {\n // --no-x 로 준 플래그는 값이 false — 사용자가 친 이름 그대로 알린다\n process.stderr.write(`[kordoc] ${templateConflictMessage(clash.map((k) => `--${opts[k] === false ? \"no-\" : \"\"}${k.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`))}\\n`)\n process.exit(1)\n }\n if (!silent) {\n for (const w of [...gongmunLintWarnings(md, 5), ...muncheLintWarnings(md, 5), ...(opts.gate ? [] : slopLintWarnings(md, 5))]) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n if (opts.gate) {\n const gate = gongmunGate(md, {})\n if (!gate.pass) {\n process.stderr.write(`[kordoc] 게이트 미통과 — ${gate.blocking.length}건을 고쳐 쓰고 다시 생성하세요 (파일 미생성)\\n`)\n for (const f of gate.blocking) process.stderr.write(` ${formatGateFinding(f)}\\n`)\n process.exit(1)\n }\n }\n const tplPath = resolve(String(opts.template))\n const warnings: string[] = []\n if (opts.totalRow !== undefined && !(TOTAL_ROWS as readonly string[]).includes(String(opts.totalRow))) {\n process.stderr.write(`[kordoc] --total-row 는 ${TOTAL_ROWS.join(\"/\")}\\n`)\n process.exit(1)\n }\n const buf = await markdownToHwpx(md, { template: readFileSync(tplPath), warnings, ...(opts.totalRow ? { totalRow: opts.totalRow } : {}) })\n if (!silent) for (const w of warnings) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n const outPath = resolve(output ?? (markdown === \"-\" ? `${baseName}.hwpx` : markdown.replace(/\\.(md|markdown|txt)$/i, \"\") + \".hwpx\"))\n // 원고와 견본 이름이 같으면(보고서.md --template 보고서.hwpx) 기본 출력 경로가 견본이 된다\n let sameAsTemplate = outPath === tplPath\n try { const a = statSync(outPath), b = statSync(tplPath); sameAsTemplate ||= a.ino === b.ino && a.dev === b.dev } catch { /* 출력 파일 없음 */ }\n if (sameAsTemplate) {\n process.stderr.write(`[kordoc] 출력 경로가 견본과 같습니다. 견본을 덮어쓰지 않습니다. -o 로 다른 경로를 지정하세요\\n`)\n process.exit(1)\n }\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, Buffer.from(buf))\n if (!silent) process.stderr.write(`[kordoc] HWPX 생성 (견본:${basename(tplPath)}) → ${outPath}\\n`)\n if (opts.json) process.stdout.write(JSON.stringify({ output: outPath, preset: null, template: tplPath, bytes: buf.byteLength, warnings }) + \"\\n\")\n return\n }\n\n // 공문서 옵션 구성 — 값 검증(열거)과 조립은 gongmun-surface SSOT, 여기는\n // commander 표면 사정(kv 파싱·--no-x 기본값)을 중립 입력으로 정돈하는 어댑터만\n let gongmun: import(\"../index.js\").GongmunOptions | undefined\n if (!plain) {\n const presetKey = String(opts.preset).trim()\n const preset = Object.hasOwn(PRESET_ALIAS, presetKey) ? PRESET_ALIAS[presetKey] : undefined\n if (!preset) {\n process.stderr.write(`[kordoc] 알 수 없는 프리셋: ${opts.preset} (기안문/보고서/계획서/통지/회의록/개조식/업무보고/서울방침/보도자료)\\n`)\n process.exit(1)\n }\n const enumCheck = <T extends readonly string[]>(flag: string, value: unknown, allowed: T): (typeof allowed)[number] | undefined => {\n if (value === undefined) return undefined\n if (!allowed.includes(String(value))) {\n process.stderr.write(`[kordoc] ${flag} 는 ${allowed.join(\"/\")}\\n`)\n process.exit(1)\n }\n return value as (typeof allowed)[number]\n }\n // 견본 HWPX 단계별 서식 — 대표값이 정해진 단계·속성만 (--levels 가 우선)\n let learnedLevels: Record<string, { font?: string; pt?: number; bold?: boolean }> | undefined\n if (opts.levelsFrom) {\n const learned = await extractLevelStyles(toArrayBuffer(readFileSync(resolve(String(opts.levelsFrom)))))\n learnedLevels = learned.levels\n if (!silent) process.stderr.write(learned.spec\n ? `[kordoc] 견본 단계별 서식: ${learned.spec}\\n`\n : `[kordoc] ⚠️ 견본에서 단계별 대표 서식을 정하지 못함 (단계마다 표본 3개 이상·한 값 60% 이상 필요) — 엔진 기본값 사용\\n`)\n }\n // \"key=value,key=value\" 스펙 파싱 — 값의 '='는 보존(첫 '='만 분리). 쉼표는\n // 구분자라 값에 못 들어감 — '=' 없는 조각(잘린 값의 꼬리 등)은 무증상 드랍\n // 대신 경고로 노출 (v4.0.6: 두문 title 값 유실이 조용히 지나가던 것 봉합)\n const parseKv = (spec: string, flag: string): Record<string, string> => {\n const out: Record<string, string> = {}\n for (const piece of spec.split(\",\")) {\n const p = piece.trim()\n if (!p) continue\n const eq = p.indexOf(\"=\")\n const key = eq > 0 ? p.slice(0, eq).trim() : \"\"\n const value = eq > 0 ? p.slice(eq + 1).trim() : \"\"\n if (!key || !value) {\n process.stderr.write(`[kordoc] ${flag}: 'key=value' 형식이 아닌 조각 무시 — \"${p}\" (값에 쉼표는 쓸 수 없습니다)\\n`)\n continue\n }\n out[key] = value\n }\n return out\n }\n const pressKv = opts.pressHead ? parseKv(String(opts.pressHead), \"--press-head\") : {}\n gongmun = buildGongmunOptions({\n preset,\n font: enumCheck(\"--font\", opts.font, BODY_FONTS),\n bodyPt: opts.pt ? Number(opts.pt) : undefined,\n lineSpacing: opts.lineSpacing ? Number(opts.lineSpacing) : undefined,\n org: opts.org, date: opts.date,\n cover: opts.cover, toc: opts.toc,\n approval: opts.approval ? String(opts.approval).split(\",\").map((s: string) => s.trim()).filter(Boolean) : undefined,\n pageNumbers: opts.pageNumbers, endMark: opts.endMark,\n // --no-body-title-box 단독 플래그 — commander 기본 true는 \"미지정\"으로 정돈\n bodyTitleBox: opts.bodyTitleBox === false ? false : undefined,\n chapterFit: opts.chapterFit,\n h2Marker: enumCheck(\"--h2-marker\", opts.h2Marker, H2_MARKERS),\n bandColor: opts.bandColor, bandTextColor: opts.bandTextColor,\n fonts: opts.fonts ? parseKv(String(opts.fonts), \"--fonts\") : undefined,\n sizes: opts.sizes\n ? Object.fromEntries(\n Object.entries(parseKv(String(opts.sizes), \"--sizes\")).map(([k, v]) => [k, Number(v)]).filter(([, v]) => Number.isFinite(v as number)),\n )\n : undefined,\n levels: opts.levels || learnedLevels\n ? { ...learnedLevels, ...(opts.levels ? parseLevelsSpec(String(opts.levels)) : {}) }\n : undefined,\n bullet2: enumCheck(\"--bullet2\", opts.bullet2, BULLET2_CHARS),\n suppressSingle: opts.suppressSingle ? true : undefined,\n totalRow: enumCheck(\"--total-row\", opts.totalRow, TOTAL_ROWS),\n docHead: opts.docHead ? parseKv(String(opts.docHead), \"--doc-head\") : undefined,\n docFoot: opts.docFoot ? parseKv(String(opts.docFoot), \"--doc-foot\") : undefined,\n reportInfo: opts.reportInfo ? String(opts.reportInfo) : undefined,\n summary: opts.summary ? String(opts.summary) : undefined,\n docInfo: opts.docInfo ? parseKv(String(opts.docInfo), \"--doc-info\") : undefined,\n checklist: opts.checklist === undefined ? undefined : opts.checklist === true ? true : { na: String(opts.checklist).split(\",\").map((x) => Number(x.trim())).filter((x) => x !== 0) },\n dept: opts.dept ? String(opts.dept) : undefined,\n coverLabel: opts.coverLabel ? String(opts.coverLabel) : undefined,\n agency: opts.agency ? String(opts.agency) : undefined,\n noticeHead: opts.noticeHead ? parseKv(String(opts.noticeHead), \"--notice-head\") : undefined,\n press: opts.pressHead || opts.pressSub || opts.pressPeople\n ? {\n release: pressKv.release, distribute: pressKv.distribute,\n sub: opts.pressSub ? String(opts.pressSub).split(\";\").map((s: string) => s.trim()).filter(Boolean) : undefined,\n contact: pressKv.dept || pressKv.manager || pressKv.phone || opts.pressPeople\n ? {\n dept: pressKv.dept, manager: pressKv.manager, phone: pressKv.phone,\n ...(opts.pressPeople ? {\n people: String(opts.pressPeople).split(\";\").map((s: string) => s.trim()).filter(Boolean)\n .map((s: string) => { const [role, title, name, phone] = s.split(\"/\").map((x) => x.trim()); return { role, title, name, phone } }),\n } : {}),\n }\n : undefined,\n }\n : undefined,\n })\n }\n\n // 폰트 오버라이드 오타·미설치 경고 (A2) — 생성은 진행\n if (gongmun?.fonts && !silent) {\n for (const w of unknownFontWarnings(gongmun.fonts)) process.stderr.write(`[kordoc] ${w}\\n`)\n }\n if (gongmun?.levels && !silent) {\n for (const w of unknownFontWarnings(levelFontRecord(gongmun.levels))) process.stderr.write(`[kordoc] ${w}\\n`)\n }\n // 프리셋 비호환 옵션 경고 (v4.0.6) — 조용한 폐기 대신 노출, 생성은 진행\n if (gongmun && !silent) {\n for (const w of incompatibleGongmunWarnings(gongmun)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n // 공문서 표기법 검수 (편람 기준, 조언용) — 생성은 진행, stderr 경고만\n if (gongmun && !silent) {\n for (const w of gongmunLintWarnings(md, 5)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n // 개조식 문체 검수 — 보고서·계획서·개조식 프리셋만. 기안문(경어)·통지·보도자료는\n // 문체 관행이 달라 적용하지 않는다 (범위를 좁히는 것이 오탐을 막는다)\n if (gongmun && !silent && usesGaejosikMunche(gongmun.preset)) {\n for (const w of muncheLintWarnings(md, 5)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n // 윤문(AI 문체)·구성(논리 구조) 검수 — 구성은 보고서·계획서 계열만 (기안문·통지·회의록·보도자료는 서식이 따로 있다)\n if (gongmun && !silent && !opts.gate) {\n for (const w of slopLintWarnings(md, 5)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n if (usesLogicStructure(gongmun.preset)) for (const w of logicLintWarnings(md, 5)) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n }\n if (opts.gate) {\n const gate = gongmunGate(md, { preset: gongmun?.preset })\n if (!gate.pass) {\n process.stderr.write(`[kordoc] 게이트 미통과 — ${gate.blocking.length}건을 고쳐 쓰고 다시 생성하세요 (파일 미생성)\\n`)\n for (const f of gate.blocking) process.stderr.write(` ${formatGateFinding(f)}\\n`)\n process.exit(1)\n }\n if (!silent) process.stderr.write(`[kordoc] 게이트 통과 (표기법·문체·윤문·구성)\\n`)\n }\n\n // 서식 프로필 (이슈 #41) — 경계 zod 검증 후 라이브러리에 전달 (MCP와 공유 스키마)\n let profile: FormatProfile | undefined\n if (opts.profile) {\n profile = parseFormatProfileJson(readFileSync(resolve(String(opts.profile)), \"utf-8\"))\n if (!silent) process.stderr.write(`[kordoc] 서식 프로필 적용: 표 ${profile.tables.length}개 (${opts.profile})\\n`)\n }\n\n // 페이지 옵션 (v4.5.0) — 용지·방향·다단·머리말/꼬리말\n let page: import(\"../index.js\").PageOptions | undefined\n if (opts.paper || opts.landscape || opts.columns || opts.header || opts.footer) {\n let size: import(\"../index.js\").PageOptions[\"size\"]\n if (opts.paper) {\n const wh = /^(\\d+(?:\\.\\d+)?)x(\\d+(?:\\.\\d+)?)$/i.exec(String(opts.paper).trim())\n size = wh ? { widthMm: Number(wh[1]), heightMm: Number(wh[2]) } : (String(opts.paper) as \"A4\")\n }\n page = {\n ...(size !== undefined ? { size } : {}),\n ...(opts.landscape ? { orientation: \"landscape\" as const } : {}),\n ...(opts.columns ? { columns: Number(opts.columns) } : {}),\n ...(opts.header ? { header: String(opts.header) } : {}),\n ...(opts.footer ? { footer: String(opts.footer) } : {}),\n }\n }\n // MCP와 같은 Unicode·실경로 검증을 적용한다.\n let imageBytes: Record<string, Uint8Array> | undefined\n if (opts.imageDir) {\n const dir = resolve(String(opts.imageDir))\n const loaded = await loadGenerationImages(md, dir)\n imageBytes = loaded.images\n if (!silent) {\n process.stderr.write(`[kordoc] 이미지 임베드: ${Object.keys(imageBytes ?? {}).length}개 (${dir})\\n`)\n for (const warning of loaded.warnings) process.stderr.write(`[kordoc] ⚠ ${warning}\\n`)\n }\n }\n\n const genWarnings: string[] = []\n const inlineMath = opts.inlineMath === true\n const buf = await markdownToHwpx(md, gongmun || profile || page || imageBytes || inlineMath\n ? {\n ...(gongmun ? { gongmun } : {}), ...(profile ? { profile } : {}),\n ...(page ? { page } : {}), ...(imageBytes ? { images: imageBytes } : {}),\n ...(inlineMath ? { inlineMath } : {}),\n warnings: genWarnings,\n }\n : undefined)\n if (!silent) for (const w of genWarnings) process.stderr.write(`[kordoc] ⚠ ${w}\\n`)\n const outPath = resolve(output ?? (markdown === \"-\" ? `${baseName}.hwpx` : markdown.replace(/\\.(md|markdown|txt)$/i, \"\") + \".hwpx\"))\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, Buffer.from(buf))\n\n if (!silent) {\n const mode = gongmun ? `공문서:${gongmun.preset}` : \"범용\"\n process.stderr.write(`[kordoc] HWPX 생성 (${mode}) → ${outPath}\\n`)\n }\n // 다른 프로그램(한/글 실시간 편집 도구 등)이 결과를 받아 이어 쓰도록 — 사람용 메시지는 그대로 stderr\n if (opts.json) {\n process.stdout.write(JSON.stringify({ output: outPath, preset: gongmun?.preset ?? null, bytes: buf.byteLength, warnings: genWarnings }) + \"\\n\")\n }\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"levels <file>\")\n .description(\"견본 HWPX 의 항목부호 단계별 글꼴·크기·굵기 추출 — generate --levels 값과 단계별 분포·서식 편차 (kordoc levels 견본.hwpx, generate --levels-from 으로 바로 적용)\")\n .option(\"--json\", \"추출 결과(levels·spec·stats·deviations)를 JSON 으로 stdout 출력\")\n .action(async (file: string, opts) => {\n try {\n const r = await extractLevelStyles(toArrayBuffer(readFileSync(resolve(file))))\n if (opts.json) {\n process.stdout.write(JSON.stringify(r, null, 2) + \"\\n\")\n return\n }\n if (!r.scheme) {\n process.stderr.write(`[kordoc] ${r.note ?? \"항목부호(□·ㅇ·- 또는 1.·가.)로 시작하는 문단이 없음\"}\\n`)\n return\n }\n process.stdout.write(`${r.spec || \"(대표값 없음 — 단계마다 표본 3개 이상·한 값 60% 이상 필요)\"}\\n`)\n for (const st of r.stats.filter(x => x.scheme === r.scheme)) {\n const top = (m: Record<string, number>) => Object.entries(m).sort((a, b) => b[1] - a[1]).map(([k, n]) => `${k}×${n}`).join(\" \")\n process.stderr.write(` ${st.depth}단계 ${st.markers.join(\"\")} 표본 ${st.samples} — 글꼴 ${top(st.font)} · 크기 ${top(st.pt)} · 굵게 ${top(st.bold)}\\n`)\n }\n if (r.deviations.length) process.stderr.write(`[kordoc] 서식 편차 ${r.deviations.length}건 — kordoc lint ${file} --styles 로 확인\\n`)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"profile <file>\")\n .description(\"HWPX 표 서식 프로필 추출 — 참조 문서의 표 테두리·음영·열폭·셀 글꼴을 JSON으로 (generate --profile로 재현) — kordoc profile 참조.hwpx -o 서식.json\")\n .option(\"-o, --output <path>\", \"출력 JSON 경로 (기본: <입력>.profile.json)\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const silent: boolean = opts.silent ?? rootOpts.silent\n const absPath = resolve(file)\n const profile = await hwpxToProfile(readFileSync(absPath))\n const outPath = resolve(output ?? absPath.replace(/\\.hwpx$/i, \"\") + \".profile.json\")\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, JSON.stringify(profile, null, 2))\n if (!silent) process.stderr.write(`[kordoc] 서식 프로필 추출: 표 ${profile.tables.length}개 → ${outPath}\\n`)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"lint <file>\")\n .description(\"공문서 표기법 검수 — 날짜·시간·금액·붙임 등 행정업무운영 편람 표기법 (md/txt 또는 HWPX·HWP·PDF 등 문서, '-'=stdin). error 있으면 exit 1\")\n .option(\"--json\", \"JSON 출력\")\n .option(\"--munche\", \"개조식 문체 검수 병행 — 서술형 종결·당위·수사·항목 길이 (보고서·계획서 원고용)\")\n .option(\"--numbers\", \"본문 수치 ↔ 표 수치 대조 병행 — 표 가까이 본문의 수치가 그 표에 있는지 (확인 목록, exit 코드에는 영향 없음)\")\n .option(\"--styles\", \"단계별 서식 편차 병행 (HWPX) — 같은 항목부호 단계인데 글꼴·크기·굵기가 대표값과 다른 문단 (exit 코드에는 영향 없음)\")\n .option(\"--slop\", \"윤문 검수 병행 — 생성형 AI 문체(결산 접속어·평론 상투구·체감 상투구·추상 성과 줄·번역투)\")\n .option(\"--logic\", \"구성 검수 병행 — 보고서·계획서의 논리 구조(왜→무엇→어떻게, 문제점↔방안 짝, 배경 사실·기대효과 목표치)\")\n .option(\"--budget\", \"예산 문서 검수 병행 — 산출근거 곱셈 검산·표 합계 재계산(틀리면 error, exit 1)·합계 행 위치·외화 표기(원화 먼저·환율 기준)·증감 기준(본예산/최종예산)\")\n .option(\"--gate\", \"공문서 게이트 — 표기법·문체 error 와 윤문·구성 지적(경고 포함)이 하나라도 있으면 exit 1 (결재 올리기 전 최종 점검)\")\n .option(\"--preset <name>\", \"게이트 범위를 프리셋에 맞춤 — 개조식 계열이면 문체, 보고서·계획서 계열이면 구성 검수를 켬\")\n .action(async (file: string, opts) => {\n try {\n const raw = file === \"-\" ? readFileSync(0) : readFileSync(resolve(file))\n // 문서 파일은 파싱한 본문 마크다운을 검사한다 — UTF-8 텍스트로 읽으면 압축 바이트가 본문으로 둔갑해\n // 위반 수백~수천 건이 쏟아졌다(\"보고서.hwpx\" 실측 1,193건)\n const ab = raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength) as ArrayBuffer\n const kind = detectFormat(ab)\n let text: string\n let irBlocks: Parameters<typeof numberBlocksFromIR>[0] | undefined\n if (kind === \"unknown\") text = raw.toString(\"utf-8\")\n else {\n const { parse } = await import(\"../index.js\")\n const parsed = await parse(ab, file === \"-\" ? undefined : { filePath: resolve(file) })\n if (!parsed.success) {\n process.stderr.write(`[kordoc] 오류: ${kind} 문서를 읽지 못했습니다 — ${parsed.error}\\n`)\n process.exit(1)\n }\n text = parsed.markdown\n irBlocks = parsed.blocks\n }\n // 문체 검수는 옵트인 — 축이 다르고(표기법 vs 종결·수사), 개조식이 아닌 원고에는\n // 적용하면 안 되기 때문에 기본 동작은 종전 그대로 둔다 (판정은 MCP lint_document 와 같은 runLintSuite)\n const presetKey = opts.preset === undefined ? undefined : String(opts.preset).trim()\n const preset = presetKey !== undefined && Object.hasOwn(PRESET_ALIAS, presetKey) ? PRESET_ALIAS[presetKey] : undefined\n if (opts.preset !== undefined && !preset) {\n process.stderr.write(`[kordoc] 알 수 없는 프리셋: ${opts.preset}\\n`)\n process.exit(1)\n }\n const suite = runLintSuite(text, {\n parsed: kind !== \"unknown\", irBlocks, preset,\n munche: opts.munche, numbers: opts.numbers, budget: opts.budget, slop: opts.slop, logic: opts.logic, gate: opts.gate,\n })\n const { findings, numbers } = suite\n const munche = suite.munche ?? [], slop = suite.slop ?? [], logic = suite.logic ?? [], budget = suite.budget ?? []\n const styles = opts.styles && kind === \"hwpx\" ? (await extractLevelStyles(ab)).deviations : undefined\n if (opts.styles && kind !== \"hwpx\") process.stderr.write(`[kordoc] --styles 는 HWPX 문서만 — 건너뜀\\n`)\n const failed = !suite.summary.ok\n if (opts.json) {\n const { summary, ...rest } = suite\n process.stdout.write(JSON.stringify({ ...rest, ...(styles ? { styles } : {}), summary }, null, 2) + \"\\n\")\n } else {\n // 사람용 리포트는 stderr — 기계용(--json)만 stdout (validate와 채널 일관)\n process.stderr.write(`[kordoc] 표기법 검수: 위반 ${findings.length}건 (error ${findings.filter((f) => f.severity === \"error\").length}, warning ${findings.filter((f) => f.severity !== \"error\").length})\\n`)\n for (const f of findings) {\n process.stderr.write(` L${f.line} [${f.severity}] ${f.rule}: \"${f.match}\" — ${f.message}${f.suggest ? ` → ${f.suggest}` : \"\"}\\n`)\n }\n if (styles) {\n process.stderr.write(`[kordoc] 단계별 서식 편차: ${styles.length}건\\n`)\n const show = (st: { font?: string; pt?: number; bold?: boolean }) => [st.font, st.pt === undefined ? undefined : `${st.pt}pt`, st.bold === undefined ? undefined : st.bold ? \"굵게\" : \"보통\"].filter(Boolean).join(\"/\")\n for (const d of styles) process.stderr.write(` ${d.depth}단계 \"${d.text}\" — ${show(d.got)} (대표 ${show(d.expected)})\\n`)\n }\n if (numbers) {\n process.stderr.write(`[kordoc] 수치 대조: 표 가까이 본문 수치 ${numbers.checked}개 중 표에서 못 찾은 ${numbers.review.length}개 (확인 필요)\\n`)\n for (const r of numbers.review) process.stderr.write(` \"${r.match}\" — ${r.context}\\n`)\n }\n const section = (label: string, list: typeof findings) => {\n const e = list.filter((f) => f.severity === \"error\").length\n process.stderr.write(`[kordoc] ${label}: 위반 ${list.length}건 (error ${e}, warning ${list.length - e})\\n`)\n for (const f of list) process.stderr.write(` L${f.line} [${f.severity}] ${f.rule}: \"${f.match}\" — ${f.message}${f.suggest ? ` → ${f.suggest}` : \"\"}\\n`)\n }\n if (opts.slop || opts.gate) section(\"윤문 검수\", slop)\n if (opts.logic || opts.gate) section(\"구성 검수\", logic)\n if (opts.budget) section(\"예산 검수\", budget)\n if (munche.length || opts.munche || (opts.gate && preset && usesGaejosikMunche(preset))) {\n const me = munche.filter((f) => f.severity === \"error\").length\n process.stderr.write(`[kordoc] 문체 검수: 위반 ${munche.length}건 (error ${me}, warning ${munche.length - me})\\n`)\n for (const f of munche) {\n process.stderr.write(` L${f.line} [${f.severity}] ${f.rule}: \"${f.match}\" — ${f.message}${f.suggest ? ` → ${f.suggest}` : \"\"}\\n`)\n }\n }\n if (opts.gate) process.stderr.write(failed ? `[kordoc] 게이트 미통과 — 표기법·문체 error 와 윤문·구성 지적을 모두 고쳐 쓰세요\\n` : `[kordoc] 게이트 통과\\n`)\n }\n process.exit(failed ? 1 : 0)\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"lint-blocks <file>\")\n .description(\"블록 단위 검수 — JSON {blocks:[{id,text,table?:{id,row,col}}], options?:{munche,slop,logic,numbers,budget,gate,preset}} 를 받아 지적마다 block·offset·length 로 (열린 문서 편집 도구용, '-'=stdin). 결과 JSON 은 stdout, error 있으면 exit 1\")\n .action(async (file: string) => {\n try {\n const raw = (file === \"-\" ? readFileSync(0) : readFileSync(resolve(file))).toString(\"utf-8\")\n const input = JSON.parse(raw) as { blocks?: unknown; options?: Record<string, unknown> }\n if (!Array.isArray(input.blocks)) throw new Error(\"blocks 배열이 없습니다\")\n const blocks = input.blocks.map((b, i) => {\n const o = b as { id?: unknown; text?: unknown; table?: { id?: unknown; row?: unknown; col?: unknown } }\n if (typeof o.id !== \"string\" || typeof o.text !== \"string\") throw new Error(`blocks[${i}] 에 문자열 id·text 가 필요합니다`)\n const t = o.table\n if (t !== undefined && (typeof t.id !== \"string\" || !Number.isInteger(t.row) || !Number.isInteger(t.col))) throw new Error(`blocks[${i}].table 은 {id, row, col}`)\n return { id: o.id, text: o.text, ...(t ? { table: { id: t.id as string, row: t.row as number, col: t.col as number } } : {}) }\n })\n const opt = input.options ?? {}\n const presetKey = typeof opt.preset === \"string\" ? opt.preset.trim() : undefined\n const preset = presetKey !== undefined && Object.hasOwn(PRESET_ALIAS, presetKey) ? PRESET_ALIAS[presetKey] : undefined\n if (presetKey !== undefined && !preset) throw new Error(`알 수 없는 프리셋: ${presetKey}`)\n const flag = (k: string) => opt[k] === true\n const result = lintBlocks(blocks, { preset, munche: flag(\"munche\"), slop: flag(\"slop\"), logic: flag(\"logic\"), numbers: flag(\"numbers\"), budget: flag(\"budget\"), gate: flag(\"gate\") })\n process.stdout.write(JSON.stringify(result) + \"\\n\")\n process.exitCode = result.summary.ok ? 0 : 1\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exitCode = 2\n }\n })\n\n program\n .command(\"redact <files...>\")\n .description(\"개인정보 서식 보존 마스킹 — 주민·외국인등록번호·전화·이메일·카드·계좌·사업자등록번호·여권·운전면허(--rules 로 인명·주소 opt-in)를 탐지해 HWPX/HWP는 원본 서식 그대로 같은 길이로 가린 파일(본문·표·머리말/꼬리말·각주·글상자·미리보기·메타데이터 포함), 그 외 포맷(PDF 등)은 원본을 건드리지 않고 마스킹된 마크다운만 출력. 자동 검출 보조 도구이므로 결과는 반드시 사람이 최종 확인하세요 (이미지 속 글자는 탐지 불가)\")\n .option(\"--rules <csv>\", \"적용 룰 (기본: rrn,phone,email,card,account,brn,passport,driver — crn(법인등록번호),ip,name(인명),address(주소)는 opt-in)\")\n .option(\"--mask-char <ch>\", \"마스크 문자 1글자 (기본: ●)\")\n .option(\"-o, --output <path>\", \"출력 경로 (단일 파일 시)\")\n .option(\"-d, --out-dir <dir>\", \"출력 디렉토리 (다중 파일 시)\")\n .option(\"--dry-run\", \"탐지 리포트만 출력, 파일 미생성\")\n .option(\"--json\", \"리포트를 JSON으로 stdout 출력\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (files: string[], opts) => {\n const { ALL_REDACT_RULES, DEFAULT_REDACT_RULES, redactText } = await import(\"../redact.js\")\n const { redactDocument } = await import(\"../redact-doc.js\")\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n // 루트 명령도 -d/--out-dir 를 정의해 먼저 삼킨다 — -o 와 같은 방식으로 양쪽을 본다\n const outDir: string | undefined = opts.outDir ?? rootOpts.outDir\n const silent: boolean = opts.silent ?? rootOpts.silent\n const KNOWN_RULES = new Set<string>(ALL_REDACT_RULES)\n const rules = opts.rules\n ? String(opts.rules).split(\",\").map((r: string) => r.trim()).filter(Boolean)\n : [...DEFAULT_REDACT_RULES]\n const badRule = rules.find((r: string) => !KNOWN_RULES.has(r))\n if (badRule) {\n process.stderr.write(`[kordoc] 알 수 없는 룰: ${badRule} (허용: ${[...KNOWN_RULES].join(\", \")})\\n`)\n process.exit(1)\n }\n const maskChar: string = opts.maskChar ?? \"●\"\n try { redactText(\"\", { maskChar }) } catch (err) {\n process.stderr.write(`[kordoc] ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n if (output && files.length > 1) {\n process.stderr.write(`[kordoc] ⚠️ -o/--output 은 단일 파일 전용이라 무시됩니다 — 다중 파일은 -d/--out-dir 를 사용하세요\\n`)\n }\n // 파일 이름에도 PII 가 있을 수 있다 — 결과 파일 이름·메시지·JSON 에는 가린 이름을 쓴다\n // (디렉토리 이름은 그대로). 윈도가 파일 이름에 못 쓰는 마스크 문자(* ?)는 ●로\n const nameMask = /[*?]/.test(maskChar) ? \"●\" : maskChar\n const maskName = (name: string): string => {\n // 파일 이름은 _ 로 낱말을 잇는다(\"민원_010-2345-6789\") — 탐지만 공백으로 보고 같은 자리를 가린다\n const probe = name.replace(/_/g, \" \")\n const out = [...name]\n for (const h of redactText(probe, { rules: rules as never, maskChar: nameMask }).hits) {\n for (let k = 0; k < h.length; k++) if (h.masked[k] !== probe[h.index + k]) out[h.index + k] = nameMask\n }\n return out.join(\"\")\n }\n const shown = (p: string): string => resolve(dirname(p), maskName(basename(p)))\n const inputs = files.map((f) => resolve(f))\n const sameFile = (a: string, b: string): boolean => {\n if (a === b) return true\n try {\n const sa = statSync(a), sb = statSync(b)\n return sa.ino === sb.ino && sa.dev === sb.dev // 대소문자 무시 파일시스템·하드링크\n } catch { return false }\n }\n const written = new Set<string>()\n /** 기본 출력 경로 — 입력 파일·이번 실행의 다른 출력과 겹치면 -2, -3 … 을 붙인다 */\n const defaultOut = (absPath: string, ext: string): string => {\n const stem = maskName(basename(absPath)).replace(/\\.[^.]+$/, \"\")\n const dir = resolve(outDir ?? dirname(absPath))\n for (let n = 1; ; n++) {\n const p = resolve(dir, `${stem}${n > 1 ? `-${n}` : \"\"}.redacted${ext}`)\n if (!written.has(p) && !inputs.some((i) => sameFile(i, p))) return p\n }\n }\n const MAX_LINES = 200\n const jsonReports: unknown[] = []\n for (const absPath of inputs) {\n const fileName = maskName(basename(absPath))\n if (output && files.length === 1 && !opts.dryRun && sameFile(absPath, resolve(output))) {\n process.stderr.write(`[kordoc] ERROR: ${fileName} — 출력 경로가 입력 파일과 같습니다. 원본을 덮어쓰지 않습니다 — 다른 -o 경로를 지정하세요\\n`)\n process.exitCode = 1\n continue\n }\n try {\n const buffer = readFileSync(absPath)\n const r = await redactDocument(toArrayBuffer(buffer), {\n rules: rules as never, maskChar, filePath: absPath, dryRun: opts.dryRun,\n })\n // 리포트 기준: HWPX/HWP 는 파일 안 위치(본문·머리말·미리보기 …), 그 외 포맷은 본문 마크다운\n const listed = r.fileHits.length > 0\n ? r.fileHits.map((h) => ({ rule: h.rule, masked: h.masked, at: `${h.where} @ ${h.part}` }))\n : r.markdownHits.map((h) => ({ rule: h.rule, masked: h.masked, at: \"\" }))\n const byRule = new Map<string, number>()\n for (const h of listed) byRule.set(h.rule, (byRule.get(h.rule) ?? 0) + 1)\n const ruleSummary = [...byRule.entries()].map(([k, v]) => `${k} ${v}건`).join(\", \") || \"0건\"\n const failed = r.residual.length > 0 || r.unscanned.length > 0\n\n let outPath: string | null = null\n let note = \"\"\n // HWPX/HWP 는 결과 바이트가 원본과 다르면 저장 (탐지 0건이어도 미할당 영역을 비웠으면 저장),\n // 그 외 포맷은 본문에서 찾은 게 있을 때 마스킹된 마크다운을 저장\n const save = r.data ? r.changed : r.markdownHits.length > 0\n if (!opts.dryRun && save) {\n const ext = r.data ? (r.format === \"hwp\" ? \".hwp\" : \".hwpx\") : \".md\"\n outPath = output && files.length === 1 ? resolve(output) : defaultOut(absPath, ext)\n mkdirSync(dirname(outPath), { recursive: true })\n if (r.data) writeFileSync(outPath, r.data)\n else {\n writeFileSync(outPath, r.markdown, \"utf-8\")\n note = ` (${r.format} 원본은 수정하지 않음 — 마스킹된 마크다운만 출력)`\n }\n written.add(outPath)\n } else if (!opts.dryRun && r.data && listed.length > 0) {\n note = \" (❌ 파일에서 가린 곳이 없어 출력하지 않음)\"\n }\n if (failed && process.exitCode !== 1) process.exitCode = 2 // 실패(1)가 우선\n if (opts.json) {\n jsonReports.push({\n file: shown(absPath), format: r.format, rules, hits: r.markdownHits, fileHits: r.fileHits,\n residual: r.residual, unscanned: r.unscanned, warnings: r.warnings, output: outPath,\n })\n }\n if (!silent) {\n process.stderr.write(`[kordoc] ${fileName}: ${ruleSummary}${outPath ? ` → ${outPath}` : opts.dryRun ? \" (dry-run)\" : \"\"}${note}\\n`)\n // 같은 값·같은 위치는 한 줄로 (미리보기·메타데이터에 같은 번호가 반복되는 경우), 너무 길면 자른다\n const grouped = new Map<string, number>()\n for (const h of listed) {\n const key = ` - [${h.rule}] ${h.masked}${h.at ? ` (${h.at})` : \"\"}`\n grouped.set(key, (grouped.get(key) ?? 0) + 1)\n }\n const lines = [...grouped].map(([line, n]) => `${line}${n > 1 ? ` ×${n}` : \"\"}`)\n for (const line of lines.slice(0, MAX_LINES)) process.stderr.write(`${line}\\n`)\n if (lines.length > MAX_LINES) process.stderr.write(` … 외 ${lines.length - MAX_LINES}줄 (전체는 --json)\\n`)\n if (r.residual.length > 0) {\n process.stderr.write(`[kordoc] ❌ 마스킹 후 재검사에서 PII ${r.residual.length}건이 남아 있습니다 — 출력 파일을 공개하지 말고 수동 확인하세요:\\n`)\n for (const h of r.residual.slice(0, MAX_LINES)) process.stderr.write(` - [${h.rule}] ${h.masked} (${h.where} @ ${h.part})\\n`)\n if (r.residual.length > MAX_LINES) process.stderr.write(` … 외 ${r.residual.length - MAX_LINES}건 (전체는 --json)\\n`)\n }\n if (r.unscanned.length > 0) {\n process.stderr.write(`[kordoc] ❌ 글자를 검사하지 못한 곳이 있습니다 — 출력 파일을 공개하지 말고 수동 확인하세요: ${r.unscanned.join(\", \")}\\n`)\n }\n for (const w of r.warnings) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n }\n } catch (err) {\n process.stderr.write(`[kordoc] ERROR: ${fileName} — ${sanitizeError(err)}\\n`)\n process.exitCode = 1\n }\n }\n if (opts.json) process.stdout.write(JSON.stringify(files.length === 1 ? jsonReports[0] ?? null : jsonReports, null, 2) + \"\\n\")\n })\n}\n","/**\n * 견본 HWPX 의 항목부호 단계별 서식 — 기관마다 □·ㅇ·- (또는 1. 가. 1)) 단계의 글꼴·크기·굵기 관행이 달라, 그 기관 문서\n * 한 벌에서 배워 generate 의 단계별 위계 타이포(GongmunOptions.levels, `--levels`)로 넘긴다. 같은 단계인데 서식이 다른\n * 문단(편차)도 함께 낸다(`kordoc lint --styles`).\n *\n * 문단 단계는 생성 엔진과 같은 부호 해석(outline.parseLeadingMarker)으로, 서식은 부호 뒤 첫 글자가 든 글자 모양으로 잰다.\n * 칸이 여럿인 데이터 표 안 문단은 표 서식(작은 글씨 '-' 항목 등)이라 빼고, 본문을 담는 1×1 틀 상자 안 문단은 남긴다.\n * 대표값은 단계·속성마다 표본 MIN_SAMPLES 개 이상이고 한 값이 MIN_SHARE 이상일 때만 정한다 — 섞여 쓴 속성은 비워 엔진\n * 기본을 따르게 한다. □·ㅇ·- 계열과 법정 계열 가운데 표본이 많은 쪽을 문서의 계열로 본다.\n */\n\nimport JSZip from \"jszip\"\nimport type { Element as XmlElement } from \"@xmldom/xmldom\"\nimport { extractHwpxStyles } from \"./styles.js\"\nimport { resolveSectionPaths } from \"./zip-sections.js\"\nimport { parseLeadingMarker } from \"./outline.js\"\nimport { createXmlParser, readZipEntry } from \"./parser-shared.js\"\nimport { KordocError, stripDtd, precheckZipSize } from \"../utils.js\"\nimport { detectFormat } from \"../detect.js\"\nimport type { GongmunLevelStyle } from \"./gongmun.js\"\n\nconst MIN_SAMPLES = 3\nconst MIN_SHARE = 0.6\n\n/** 한 문단의 단계 서식 표본 */\ninterface LevelSample {\n scheme: \"box\" | \"legal\"\n depth: number\n marker: string\n text: string\n font?: string\n pt?: number\n bold: boolean\n}\n\nexport interface LevelStat {\n scheme: \"box\" | \"legal\"\n depth: number\n /** 이 단계에 쓰인 부호 (등장 순) */\n markers: string[]\n samples: number\n /** 속성별 값 → 문단 수 */\n font: Record<string, number>\n pt: Record<string, number>\n bold: Record<string, number>\n}\n\nexport interface LevelDeviation {\n depth: number\n /** 문단 앞 40자 */\n text: string\n got: GongmunLevelStyle\n expected: GongmunLevelStyle\n}\n\nexport interface LevelStyleReport {\n /** 표본을 잴 수 없었던 사유 (글자 모양 정의가 없는 HWPX 등) */\n note?: string\n /** 문서의 부호 계열 — 표본 없으면 null */\n scheme: \"box\" | \"legal\" | null\n /** 대표값이 정해진 단계·속성만 (generate levels 입력) */\n levels: Record<string, GongmunLevelStyle>\n /** `--levels` 문자열 (\"0=HY견고딕/17/bold,1=…\") — 대표값이 없으면 \"\" */\n spec: string\n stats: LevelStat[]\n /** 대표값과 다른 문단 (문서 계열만) */\n deviations: LevelDeviation[]\n}\n\nconst local = (n: { nodeName: string }): string => n.nodeName.replace(/^.*:/, \"\")\n\n/** <hp:t> 글 — 탭 요소는 \"\\t\" (항목부호 뒤는 공백이 아니라 탭인 문서가 많다: \"□<hp:tab/>\" + \"첫째 대항목\") */\nfunction runText(t: XmlElement): string {\n let out = \"\"\n for (let n = t.firstChild; n; n = n.nextSibling) {\n if (n.nodeType === 3) out += n.nodeValue ?? \"\"\n else if (n.nodeType === 1 && local(n) === \"tab\") out += \"\\t\"\n }\n return out\n}\n\n/** 칸이 여럿인 표 안 문단 — 가장 가까운 표의 행·열 수로 (1×1 틀 상자는 본문으로 본다) */\nfunction inDataTable(p: XmlElement): boolean {\n for (let n = p.parentNode as XmlElement | null; n; n = n.parentNode as XmlElement | null) {\n if (n.nodeType === 1 && local(n) === \"tbl\") {\n const el = n\n return Number(el.getAttribute(\"rowCnt\") ?? 1) * Number(el.getAttribute(\"colCnt\") ?? 1) > 1\n }\n }\n return false\n}\n\n/** 글자 모양 id → 한글 글꼴명 — 한컴 HWPX 는 글꼴을 번호(<hh:fontRef hangul=\"1\">)로 가리키고 이름은 글꼴 목록\n * (<hh:fontface lang=\"HANGUL\"><hh:font id face>)에 둔다 */\nfunction hangulFaces(headerXml: string): Map<string, string> {\n const doc = createXmlParser().parseFromString(stripDtd(headerXml), \"text/xml\")\n const faces = new Map<string, string>()\n const fontfaces = doc.getElementsByTagNameNS(\"*\", \"fontface\")\n for (let i = 0; i < fontfaces.length; i++) {\n if (fontfaces[i].getAttribute(\"lang\") !== \"HANGUL\") continue\n const fonts = fontfaces[i].getElementsByTagNameNS(\"*\", \"font\")\n for (let k = 0; k < fonts.length; k++) faces.set(fonts[k].getAttribute(\"id\") ?? \"\", fonts[k].getAttribute(\"face\") ?? \"\")\n }\n const out = new Map<string, string>()\n const charPrs = doc.getElementsByTagNameNS(\"*\", \"charPr\")\n for (let i = 0; i < charPrs.length; i++) {\n const ref = charPrs[i].getElementsByTagNameNS(\"*\", \"fontRef\")[0]\n const face = ref ? faces.get(ref.getAttribute(\"hangul\") ?? \"\") : undefined\n if (face) out.set(charPrs[i].getAttribute(\"id\") ?? \"\", face)\n }\n return out\n}\n\n/** 견본 HWPX → 단계별 대표 서식과 편차 */\nexport async function extractLevelStyles(buffer: ArrayBuffer): Promise<LevelStyleReport> {\n const format = detectFormat(buffer)\n if (format !== \"hwpx\") throw new KordocError(`단계별 서식은 HWPX 견본에서만 잽니다 (감지된 포맷: ${format}) — 한글에서 HWPX 로 저장해 넘기세요`)\n precheckZipSize(buffer)\n const zip = await JSZip.loadAsync(buffer)\n const decompressed = { total: 0 }\n const styles = await extractHwpxStyles(zip, decompressed)\n const header = zip.file(\"Contents/header.xml\") ?? zip.file(\"Contents/head.xml\")\n const faces = header ? hangulFaces(await readZipEntry(header, \"text\", decompressed.total)) : new Map<string, string>()\n const samples: LevelSample[] = []\n for (const path of await resolveSectionPaths(zip)) {\n const file = zip.file(path)\n if (!file) continue\n const xml = await readZipEntry(file, \"text\", decompressed.total)\n decompressed.total += xml.length * 2\n const doc = createXmlParser().parseFromString(stripDtd(xml), \"text/xml\")\n const paras = doc.getElementsByTagNameNS(\"*\", \"p\")\n for (let i = 0; i < paras.length; i++) {\n const p = paras[i]\n if (inDataTable(p)) continue\n // 문단 직속 run 만 — 칸 안 문단은 그 문단이 따로 잡힌다\n const runs: Array<{ text: string; charPr: string | null }> = []\n for (let c = p.firstChild; c; c = c.nextSibling) {\n if (c.nodeType !== 1 || local(c) !== \"run\") continue\n const el = c as unknown as Element\n let text = \"\"\n const ts = el.getElementsByTagNameNS(\"*\", \"t\")\n for (let k = 0; k < ts.length; k++) if (ts[k].parentNode === el) text += runText(ts[k] as unknown as XmlElement)\n runs.push({ text, charPr: el.getAttribute(\"charPrIDRef\") })\n }\n const text = runs.map(r => r.text).join(\"\")\n const lm = parseLeadingMarker(text)\n if ((lm.kind !== \"box\" && lm.kind !== \"legal\") || !lm.rest) continue\n // 부호 뒤 첫 글자가 든 run 의 글자 모양\n const at = text.indexOf(lm.rest)\n let pos = 0, charPr: string | null = null\n for (const r of runs) {\n if (at < pos + r.text.length) { charPr = r.charPr; break }\n pos += r.text.length\n }\n const cp = charPr ? styles.charProperties.get(charPr) : undefined\n if (!cp) continue\n samples.push({ scheme: lm.kind, depth: lm.depth, marker: lm.marker, text: lm.rest, font: faces.get(charPr!) ?? cp.fontName, pt: cp.fontSize, bold: !!cp.bold })\n }\n }\n const report = summarize(samples)\n return styles.charProperties.size === 0 ? { ...report, note: \"글자 모양 정의(header.xml charPr)가 없어 서식을 잴 수 없음\" } : report\n}\n\nconst tally = (values: Array<string | undefined>): Record<string, number> => {\n const out: Record<string, number> = {}\n for (const v of values) if (v !== undefined) out[v] = (out[v] ?? 0) + 1\n return out\n}\n/** 표본 MIN_SAMPLES 이상·점유 MIN_SHARE 이상인 값 */\nconst dominant = (counts: Record<string, number>, total: number): string | undefined => {\n const [value, n] = Object.entries(counts).sort((a, b) => b[1] - a[1])[0] ?? []\n return value !== undefined && total >= MIN_SAMPLES && n! >= total * MIN_SHARE ? value : undefined\n}\n\nfunction summarize(samples: LevelSample[]): LevelStyleReport {\n const box = samples.filter(s => s.scheme === \"box\").length, legal = samples.length - box\n const scheme = samples.length === 0 ? null : box >= legal ? \"box\" : \"legal\"\n const stats: LevelStat[] = []\n const levels: Record<string, GongmunLevelStyle> = {}\n for (const sch of [\"box\", \"legal\"] as const) {\n for (const depth of [...new Set(samples.filter(s => s.scheme === sch).map(s => s.depth))].sort((a, b) => a - b)) {\n const group = samples.filter(s => s.scheme === sch && s.depth === depth)\n const st: LevelStat = {\n scheme: sch, depth, markers: [...new Set(group.map(s => s.marker))], samples: group.length,\n font: tally(group.map(s => s.font)), pt: tally(group.map(s => s.pt?.toString())), bold: tally(group.map(s => String(s.bold))),\n }\n stats.push(st)\n if (sch !== scheme) continue\n const font = dominant(st.font, group.length), pt = dominant(st.pt, group.length), bold = dominant(st.bold, group.length)\n const style: GongmunLevelStyle = { ...(font ? { font } : {}), ...(pt ? { pt: Number(pt) } : {}), ...(bold ? { bold: bold === \"true\" } : {}) }\n if (Object.keys(style).length) levels[depth] = style\n }\n }\n const deviations: LevelDeviation[] = []\n for (const s of samples) {\n const want = s.scheme === scheme ? levels[s.depth] : undefined\n if (!want) continue\n const got: GongmunLevelStyle = { font: s.font, pt: s.pt, bold: s.bold }\n if ((want.font !== undefined && want.font !== s.font) || (want.pt !== undefined && want.pt !== s.pt) || (want.bold !== undefined && want.bold !== s.bold)) {\n deviations.push({ depth: s.depth, text: s.text.slice(0, 40), got, expected: want })\n }\n }\n const spec = Object.entries(levels).map(([d, st]) =>\n `${d}=${[st.font, st.pt, st.bold === undefined ? undefined : st.bold ? \"bold\" : \"plain\"].filter(v => v !== undefined).join(\"/\")}`).join(\",\")\n return { scheme, levels, spec, stats, deviations }\n}\n","/** kordoc CLI 명령 — 렌더 — render·crop·tables·render-worker */\n\nimport { readFileSync, writeFileSync, mkdirSync } from \"fs\"\nimport { dirname, resolve } from \"path\"\nimport { parse } from \"../index.js\"\nimport { VERSION, toArrayBuffer, sanitizeError, KordocError } from \"../utils.js\"\nimport type { Command } from \"commander\"\n\nexport function registerRenderCommands(program: Command): void {\n program\n .command(\"render <file>\")\n .description(\"레이아웃 보존 렌더 — HWPX·HWP(5.x)를 SVG(기본, HWPX 는 전체 페이지 세로 스택)·HTML·PNG·JPEG·PDF로. 한컴 저장본은 조판 캐시 그대로, 캐시 없는 생성본·편집본은 순수 TS 조판(reflow, 기본 켬) — kordoc render 문서.hwpx -o 문서.svg / --format png --pages 2-4 -d ./pages / --format pdf -o 문서.pdf\")\n .option(\"-o, --output <path>\", \"출력 경로 (단일 산출: svg 스택·html·pdf·한 쪽 png/jpeg. 기본: <입력>.<확장자>)\")\n .option(\"-d, --out-dir <dir>\", \"페이지별 산출 디렉토리 (svg/png/jpeg 여러 쪽 → page_001.png …)\")\n .option(\"--format <fmt>\", \"svg(기본) | html | png | jpeg | pdf\")\n .option(\"--pages <range>\", \"렌더할 페이지 (1-based: 3 / 1-3 / 1,3,7-9)\")\n .option(\"--max-width <px>\", \"래스터 최대 폭 px (기본 1400)\")\n .option(\"--title <text>\", \"HTML/PDF 문서 제목\")\n .option(\"--browser <path>\", \"PDF 용 Chromium 실행 파일 (기본: PUPPETEER_EXECUTABLE_PATH 또는 자동 탐지)\")\n .option(\"--highlight <terms>\", \"검색어 형광펜 (쉼표 구분)\")\n .option(\"--no-reflow\", \"순수 TS 조판 끄기 (조판 캐시 없는 문서가 빈 페이지로 나올 수 있음)\")\n .option(\"--reflow\", \"순수 TS 조판 켜기 — 기본값과 같다 (옛 안내 호환, #97)\")\n .option(\"--reflow-mode <mode>\", \"reflow 줄바꿈 모드: keep(어절) | charAll(글자)\", \"keep\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const outDir: string | undefined = opts.outDir ?? rootOpts.outDir\n const silent: boolean = opts.silent ?? rootOpts.silent\n // 루트 --format(markdown 기본) 이 서브커맨드 뒤 --format 을 흡수한다(cli-options 회귀) — 기본값이 아니면 그 값을 쓴다\n const fmt: string = opts.format ?? (rootOpts.format && rootOpts.format !== \"markdown\" ? rootOpts.format : \"svg\")\n const pages: string | undefined = opts.pages ?? rootOpts.pages\n if (![\"svg\", \"html\", \"png\", \"jpeg\", \"pdf\"].includes(fmt)) throw new KordocError(`--format 은 svg|html|png|jpeg|pdf 중 하나: ${fmt}`)\n const highlights = opts.highlight ? String(opts.highlight).split(\",\") : undefined\n const absPath = resolve(file)\n const stem = file.replace(/\\.hwpx?$/i, \"\")\n if (fmt === \"svg\" && !outDir && !pages && !/\\.hwp$/i.test(absPath)) {\n // 종전 동작(HWPX) — 전체 페이지 세로 스택 SVG 한 파일. HWP5 는 통합 렌더러(페이지별)\n const { renderHwpxToSvg } = await import(\"../render/index.js\")\n const buffer = readFileSync(absPath)\n const result = await renderHwpxToSvg(toArrayBuffer(buffer), { highlights, reflow: opts.reflow, reflowMode: opts.reflowMode })\n const outPath = resolve(output ?? stem + \".svg\")\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, result.svg, \"utf-8\")\n if (!silent) {\n process.stderr.write(`[kordoc] 렌더 (${result.pageCount}페이지, ${result.width}x${result.height}pt, 텍스트 ${result.stats.texts}·이미지 ${result.stats.images}·표 ${result.stats.tables}) → ${outPath}\\n`)\n for (const w of result.warnings) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n }\n return\n }\n const { renderDocument } = await import(\"../render/index.js\")\n const { scene, assets } = await renderDocument(absPath, {\n format: fmt as \"svg\" | \"html\" | \"png\" | \"jpeg\" | \"pdf\", pages, highlights, reflow: opts.reflow, reflowMode: opts.reflowMode,\n maxWidthPx: opts.maxWidth ? Number(opts.maxWidth) : undefined, title: opts.title, browserExecutablePath: opts.browser,\n })\n const ext = fmt === \"jpeg\" ? \"jpg\" : fmt\n const written: string[] = []\n if (fmt === \"html\" || fmt === \"pdf\" || (assets.length === 1 && !outDir)) {\n const outPath = resolve(output ?? stem + \".\" + ext)\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, assets[0].data)\n written.push(outPath)\n } else {\n if (!outDir) throw new KordocError(`페이지 ${assets.length}장 산출은 --out-dir 이 필요합니다 (한 쪽만 내려면 --pages 로 선택)`)\n mkdirSync(resolve(outDir), { recursive: true })\n for (const a of assets) {\n const outPath = resolve(outDir, `page_${String(a.page).padStart(3, \"0\")}.${ext}`)\n writeFileSync(outPath, a.data)\n written.push(outPath)\n }\n }\n if (!silent) {\n process.stderr.write(`[kordoc] 렌더 ${fmt} (${scene.pages.length}페이지 중 ${assets.length}건, 텍스트 ${scene.stats.texts}·이미지 ${scene.stats.images}·표 ${scene.stats.tables}·도형 ${scene.stats.shapes}) → ${written.length === 1 ? written[0] : resolve(outDir!)}\\n`)\n for (const w of scene.warnings) process.stderr.write(`[kordoc] ⚠️ ${w}\\n`)\n }\n } catch (err) {\n // exit(1) 을 바로 부르면 파이프 stderr 가 유실된다 — exitCode 로 정상 종료\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exitCode = 1\n }\n })\n\n program\n .command(\"crop <file>\")\n .description(\"렌더 영역 잘라내기 — 표·이미지·문단·도형을 페이지 이미지에서 crop (HWPX·HWP) — kordoc crop 문서.hwpx --target table -d ./regions\")\n .option(\"-d, --out-dir <dir>\", \"출력 디렉토리 (필수) — <유형>_<번호>_page_<쪽>.png + regions.json\")\n .option(\"--target <types>\", \"유형(쉼표): table | image | paragraph | shape\", \"table\")\n .option(\"--format <fmt>\", \"png(기본) | jpeg\")\n .option(\"--pages <range>\", \"대상 페이지 (1-based)\")\n .option(\"--padding <pt>\", \"bbox 둘레 여백 pt\", \"0\")\n .option(\"--max-width <px>\", \"페이지 래스터 최대 폭 px (crop 해상도, 기본 1400)\")\n .option(\"--no-reflow\", \"순수 TS 조판 끄기\")\n .option(\"--reflow\", \"순수 TS 조판 켜기 — 기본값과 같다 (옛 안내 호환)\")\n .option(\"--reflow-mode <mode>\", \"reflow 줄바꿈 모드: keep | charAll\", \"keep\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const rootOpts = program.opts()\n const outDir: string | undefined = opts.outDir ?? rootOpts.outDir\n const silent: boolean = opts.silent ?? rootOpts.silent\n const fmt: string = opts.format ?? (rootOpts.format && rootOpts.format !== \"markdown\" ? rootOpts.format : \"png\")\n const pages: string | undefined = opts.pages ?? rootOpts.pages\n if (![\"png\", \"jpeg\"].includes(fmt)) throw new KordocError(`--format 은 png|jpeg 중 하나: ${fmt}`)\n if (!outDir) throw new KordocError(\"--out-dir 이 필요합니다 (crop 은 파일 여러 개를 냅니다)\")\n const types = String(opts.target).split(\",\").map((t: string) => t.trim()).filter(Boolean)\n for (const t of types) if (![\"table\", \"image\", \"paragraph\", \"shape\"].includes(t)) throw new KordocError(`--target 유형 오류: ${t}`)\n const { extractRenderedRegions } = await import(\"../render/index.js\")\n const regions = await extractRenderedRegions(resolve(file), {\n types: types as Array<\"table\" | \"image\" | \"paragraph\" | \"shape\">, format: fmt as \"png\" | \"jpeg\", pages,\n paddingPt: Number(opts.padding) || 0, maxWidthPx: opts.maxWidth ? Number(opts.maxWidth) : undefined, reflow: opts.reflow, reflowMode: opts.reflowMode,\n })\n const dir = resolve(outDir)\n mkdirSync(dir, { recursive: true })\n const ext = fmt === \"jpeg\" ? \"jpg\" : \"png\"\n const manifest = regions.map(r => {\n const name = `${r.region.id.replace(\"-\", \"_\")}_page_${String(r.page).padStart(3, \"0\")}.${ext}`\n writeFileSync(resolve(dir, name), r.data)\n return { file: name, id: r.region.id, type: r.region.type, sourceId: r.region.sourceId, parentId: r.region.parentId, page: r.page, bbox: r.bbox, widthPx: r.widthPx, heightPx: r.heightPx }\n })\n writeFileSync(resolve(dir, \"regions.json\"), JSON.stringify(manifest, null, 2))\n if (!silent) process.stderr.write(`[kordoc] crop ${regions.length}건 (${types.join(\",\")}) → ${dir}\\n`)\n } catch (err) {\n // exit(1) 을 바로 부르면 파이프 stderr 가 유실된다 — exitCode 로 정상 종료\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exitCode = 1\n }\n })\n\n program\n .command(\"tables <file>\")\n .description(\"표 추출·분류 — 의미표/레이아웃(조직도 등)/불확실 분류 JSON + 선택적 시각 crop (HWPX·HWP) — kordoc tables 문서.hwpx --visual non-tabular-and-uncertain -d ./tables\")\n .option(\"-o, --output <path>\", \"JSON 출력 경로 (기본 stdout; -d 지정 시 <out-dir>/tables.json)\")\n .option(\"-d, --out-dir <dir>\", \"crop 저장 디렉토리 (--visual 지정 시 필수)\")\n .option(\"--visual <policy>\", \"crop 대상: none(기본) | non-tabular | non-tabular-and-uncertain | all\", \"none\")\n .option(\"--crop-format <fmt>\", \"png(기본) | jpeg\", \"png\")\n .option(\"--padding <pt>\", \"crop 여백 pt\", \"0\")\n .option(\"--cells\", \"JSON 에 셀 텍스트 격자 포함\")\n .option(\"--silent\", \"진행 메시지 숨기기\")\n .action(async (file: string, opts) => {\n try {\n const rootOpts = program.opts()\n const output: string | undefined = opts.output ?? rootOpts.output\n const outDir: string | undefined = opts.outDir ?? rootOpts.outDir\n const silent: boolean = opts.silent ?? rootOpts.silent\n const policy = String(opts.visual)\n if (![\"none\", \"non-tabular\", \"non-tabular-and-uncertain\", \"all\"].includes(policy)) throw new KordocError(`--visual 은 none|non-tabular|non-tabular-and-uncertain|all: ${policy}`)\n if (policy !== \"none\" && !outDir) throw new KordocError(\"--visual 은 crop 파일을 내므로 --out-dir 이 필요합니다\")\n const cropFmt = String(opts.cropFormat)\n if (![\"png\", \"jpeg\"].includes(cropFmt)) throw new KordocError(`--crop-format 은 png|jpeg: ${cropFmt}`)\n const { extractTables } = await import(\"../table/visual.js\")\n const tables = await extractTables(resolve(file), { policy: policy as \"none\" | \"non-tabular\" | \"non-tabular-and-uncertain\" | \"all\", format: cropFmt as \"png\" | \"jpeg\", paddingPt: Number(opts.padding) || 0 })\n const dir = outDir ? resolve(outDir) : undefined\n if (dir) mkdirSync(dir, { recursive: true })\n const ext = cropFmt === \"jpeg\" ? \"jpg\" : \"png\"\n const report = tables.map(t => {\n const crops = t.crops.map(c => {\n const name = `${t.id.replace(/[^\\w.-]/g, \"_\")}_page_${String(c.page).padStart(3, \"0\")}.${ext}`\n if (dir) writeFileSync(resolve(dir, name), c.data)\n return { file: dir ? name : undefined, page: c.page, bbox: c.bbox }\n })\n return {\n id: t.id, sourceId: t.sourceId, page: t.page, classification: t.classification,\n table: { rows: t.table.rows, cols: t.table.cols, hasHeader: t.table.hasHeader, caption: t.table.caption, ...(opts.cells ? { cells: t.table.cells.map(r => r.map(c => c.text)) } : {}) },\n regions: t.regions, crops, warnings: t.warnings,\n }\n })\n const json = JSON.stringify(report, null, 2)\n const jsonPath = output ? resolve(output) : dir ? resolve(dir, \"tables.json\") : undefined\n if (jsonPath) { mkdirSync(dirname(jsonPath), { recursive: true }); writeFileSync(jsonPath, json + \"\\n\") }\n else process.stdout.write(json + \"\\n\")\n if (!silent) {\n const kinds = report.reduce<Record<string, number>>((m, r) => { m[r.classification.kind] = (m[r.classification.kind] ?? 0) + 1; return m }, {})\n process.stderr.write(`[kordoc] 표 ${report.length}개 (${Object.entries(kinds).map(([k, v]) => `${k} ${v}`).join(\", \")}) crop ${report.reduce((n, r) => n + r.crops.length, 0)}건${jsonPath ? ` → ${jsonPath}` : \"\"}\\n`)\n }\n } catch (err) {\n process.stderr.write(`[kordoc] 오류: ${sanitizeError(err)}\\n`)\n process.exitCode = 1\n }\n })\n\n program\n .command(\"render-worker\")\n .description(\"persistent 렌더 워커 — stdin NDJSON 요청 → 조판 SVG 파일 출력 (프로세스 유지, 콜드스타트 제거)\")\n .action(async () => {\n // 프로토콜(NDJSON, 한 줄=한 요청/응답):\n // 요청 {\"id\":1,\"file\":\"a.hwpx\",\"out\":\"a.svg\",\"reflow\":true,\"highlight\":[\"term\"]}\n // 응답 {\"id\":1,\"ok\":true,\"out\":\"a.svg\",\"width\":..,\"height\":..,\"pageCount\":..,\"stats\":{..},\"warnings\":[..]}\n // {\"cmd\":\"quit\"} 로 종료. 모듈은 최초 1회만 로드 → 이후 요청은 콜드스타트 없음.\n const { createInterface } = await import(\"node:readline\")\n const { renderHwpxToSvg } = await import(\"../render/index.js\")\n const rl = createInterface({ input: process.stdin })\n const write = (o: unknown): void => void process.stdout.write(JSON.stringify(o) + \"\\n\")\n write({ ready: true, version: VERSION })\n for await (const line of rl) {\n const t = line.trim()\n if (!t) continue\n let req: { id?: number; cmd?: string; file?: string; out?: string; reflow?: boolean; reflowMode?: string; highlight?: string[] }\n // 비JSON 라인도 응답은 낸다 — 무음 삼킴이면 id 대기 클라이언트가 영구 행\n try { req = JSON.parse(t) } catch { write({ ok: false, error: \"잘못된 JSON 라인\" }); continue }\n if (req === null || typeof req !== \"object\") { write({ ok: false, error: \"JSON 객체가 아닙니다\" }); continue }\n if (req.cmd === \"quit\") { rl.close(); break }\n const id = req.id\n try {\n if (!req.file || !req.out) throw new Error(\"file·out 필수\")\n const buffer = readFileSync(resolve(req.file))\n const result = await renderHwpxToSvg(toArrayBuffer(buffer), {\n highlights: req.highlight, reflow: req.reflow, reflowMode: req.reflowMode as \"keep\" | \"charAll\" | undefined,\n })\n const outPath = resolve(req.out)\n mkdirSync(dirname(outPath), { recursive: true })\n writeFileSync(outPath, result.svg, \"utf-8\")\n write({ id, ok: true, out: outPath, width: result.width, height: result.height, pageCount: result.pageCount, stats: result.stats, warnings: result.warnings })\n } catch (err) {\n write({ id, ok: false, error: sanitizeError(err) })\n }\n }\n })\n}\n","/** kordoc CLI 명령 — 서버·설정·모델 — mcp·setup·check-formula-models·check-ocr-models·models */\n\nimport { sanitizeError } from \"../utils.js\"\nimport type { Command } from \"commander\"\n\nexport function registerSystemCommands(program: Command): void {\n program\n .command(\"mcp\")\n .description(\"MCP 서버 실행 (Claude / Cursor / Windsurf 연동)\")\n .action(async () => {\n const { startMcpServer } = await import(\"../mcp.js\")\n await startMcpServer()\n })\n\n program\n .command(\"setup\")\n .description(\"대화형 설치 마법사 — AI 클라이언트 자동 등록 (Mac/Win/Linux)\")\n .action(async () => {\n const { runSetup } = await import(\"../setup.js\")\n await runSetup()\n })\n\n program\n .command(\"check-formula-models\")\n .description(\"PDF 수식 OCR 모델(MFD + MFR + tokenizer, ~155MB) 상태 확인 — 없거나 SHA 불일치면 다운로드\")\n .option(\"--status-only\", \"상태만 JSON 으로 출력 (다운로드 안 함)\")\n .action(async (opts) => {\n try {\n const { getFormulaModelStatus, ensureFormulaModels, getFormulaModelsDir } = await import(\n \"../pdf/formula/index.js\"\n )\n const dir = getFormulaModelsDir()\n if (opts.statusOnly) {\n const status = await getFormulaModelStatus()\n process.stdout.write(\n JSON.stringify(\n {\n modelsDir: dir,\n allReady: status.every((s) => s.verified),\n models: status.map((s) => ({\n name: s.spec.name,\n filename: s.spec.filename,\n sizeMb: s.spec.sizeMb,\n exists: s.exists,\n verified: s.verified,\n invalidReason: s.invalidReason,\n path: s.localPath,\n })),\n },\n null,\n 2,\n ) + \"\\n\",\n )\n return\n }\n process.stderr.write(`[kordoc-formula] 캐시 디렉토리: ${dir}\\n`)\n await ensureFormulaModels((p) => {\n if (p.phase === \"download\" && p.total) {\n const pct = Math.floor((p.downloaded / p.total) * 100)\n process.stderr.write(\n `\\r[kordoc-formula] ${p.spec.name} ${pct}% (${(p.downloaded / 1024 / 1024).toFixed(1)}/${(p.total / 1024 / 1024).toFixed(1)}MB)`,\n )\n if (p.downloaded >= p.total) process.stderr.write(\"\\n\")\n } else if (p.phase === \"verify\") {\n process.stderr.write(`[kordoc-formula] ${p.spec.name} SHA-256 검증 중...\\n`)\n } else if (p.phase === \"done\") {\n process.stderr.write(`[kordoc-formula] ${p.spec.name} 준비 완료\\n`)\n } else if (p.phase === \"skip\") {\n process.stderr.write(`[kordoc-formula] ${p.spec.name} 이미 존재 (skip)\\n`)\n }\n })\n process.stdout.write(\"ok\\n\")\n } catch (err) {\n process.stderr.write(`[kordoc] 수식 모델 준비 실패: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"check-ocr-models\")\n .description(\"텍스트 OCR 모델(PP-OCRv5 korean det+rec, ~18MB) 상태 확인 — 없거나 SHA 불일치면 다운로드\")\n .option(\"--status-only\", \"상태만 JSON 으로 출력 (다운로드 안 함)\")\n .action(async (opts) => {\n try {\n const { getOcrModelStatus, ensureOcrModels, getOcrModelsDir } = await import(\"../ocr/models.js\")\n const dir = getOcrModelsDir()\n if (opts.statusOnly) {\n const status = await getOcrModelStatus()\n process.stdout.write(\n JSON.stringify(\n {\n modelsDir: dir,\n allReady: status.every((s) => s.verified),\n models: status.map((s) => ({\n name: s.spec.name,\n filename: s.spec.filename,\n sizeMb: s.spec.sizeMb,\n exists: s.exists,\n verified: s.verified,\n invalidReason: s.invalidReason,\n path: s.localPath,\n })),\n },\n null,\n 2,\n ) + \"\\n\",\n )\n return\n }\n process.stderr.write(`[kordoc-ocr] 캐시 디렉토리: ${dir}\\n`)\n await ensureOcrModels((p) => {\n if (p.phase === \"download\" && p.total) {\n const pct = Math.floor((p.downloaded / p.total) * 100)\n process.stderr.write(\n `\\r[kordoc-ocr] ${p.spec.name} ${pct}% (${(p.downloaded / 1024 / 1024).toFixed(1)}/${(p.total / 1024 / 1024).toFixed(1)}MB)`,\n )\n if (p.downloaded >= p.total) process.stderr.write(\"\\n\")\n } else if (p.phase === \"verify\") {\n process.stderr.write(`[kordoc-ocr] ${p.spec.name} SHA-256 검증 중...\\n`)\n } else if (p.phase === \"done\") {\n process.stderr.write(`[kordoc-ocr] ${p.spec.name} 준비 완료\\n`)\n } else if (p.phase === \"skip\") {\n process.stderr.write(`[kordoc-ocr] ${p.spec.name} 이미 존재 (skip)\\n`)\n }\n })\n process.stdout.write(\"ok\\n\")\n } catch (err) {\n process.stderr.write(`[kordoc] OCR 모델 준비 실패: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n\n program\n .command(\"models\")\n .description(\"OCR/수식 모델 오프라인 사이드로드 — 폐쇄망 반입용 내보내기/가져오기 (SHA-256 검증)\")\n .option(\"--status\", \"캐시에 설치된 모델 상태를 JSON 으로 출력\")\n .option(\"--export <dir>\", \"로컬 캐시 → 번들 디렉토리로 내보내기 (온라인 PC에서 실행)\")\n .option(\"--import <dir>\", \"번들 디렉토리 → 로컬 캐시로 설치 (내부망 PC에서 실행)\")\n .action(async (opts) => {\n try {\n const { exportModels, importModels, modelCacheStatus } = await import(\"../shared/model-bundle.js\")\n if (opts.status) {\n process.stdout.write(JSON.stringify(await modelCacheStatus(), null, 2) + \"\\n\")\n return\n }\n const dir = opts.export ?? opts.import\n if (!dir) {\n process.stderr.write(\"[kordoc] --status / --export <dir> / --import <dir> 중 하나가 필요합니다\\n\")\n process.exit(1)\n }\n if (opts.export && opts.import) {\n process.stderr.write(\"[kordoc] --export 와 --import 는 함께 쓸 수 없습니다\\n\")\n process.exit(1)\n }\n const result = opts.export ? await exportModels(dir) : await importModels(dir)\n for (const f of result.files) {\n const mark = f.status === \"copied\" ? \"+\" : f.status === \"invalid\" ? \"!\" : \"-\"\n process.stderr.write(` ${mark} ${f.group}/${f.filename}${f.reason ? ` — ${f.reason}` : \"\"}\\n`)\n }\n const verb = opts.export ? \"내보내기\" : \"설치\"\n const copied = result.files.filter((f) => f.status === \"copied\").length\n process.stderr.write(\n `[kordoc-models] ${verb} ${result.ok ? `완료 (${copied}개)` : \"실패 — 위 ! / - 항목 확인\"}: ${dir}\\n`,\n )\n if (!result.ok) process.exit(1)\n process.stdout.write(\"ok\\n\")\n } catch (err) {\n process.stderr.write(`[kordoc] 모델 사이드로드 실패: ${sanitizeError(err)}\\n`)\n process.exit(1)\n }\n })\n}\n","/** kordoc CLI 명령: 상주 파싱 워커 (parse-worker) */\n\nimport { resolve } from \"path\"\nimport type { ParseOptions, ParseResult } from \"../types.js\"\nimport { VERSION, sanitizeError, classifyError, routeConsoleToStderr } from \"../utils.js\"\nimport type { Command } from \"commander\"\nimport { parseWorkerFile } from \"./worker-parse.js\"\n\n/** 요청·응답 필드가 바뀌면 올린다. 호스트가 ready 줄로 호환을 판단한다 */\nexport const PARSE_WORKER_PROTOCOL = 1\n\ninterface ParseWorkerRequest {\n id?: number\n cmd?: string\n file?: string\n /** false 면 이미지 바이트를 싣지 않는다 (ParseOptions.images) */\n images?: boolean\n /** \"off\"(기본) | \"auto\"(OCR 필요 페이지만) | \"force\"(전 페이지) */\n ocr?: \"off\" | \"auto\" | \"force\"\n formulaOcr?: boolean\n password?: string | null\n}\n\n/** 이미지 바이트는 --format json 과 같게 base64 로 */\nconst bytesToBase64 = (_key: string, value: unknown): unknown =>\n value instanceof Uint8Array ? Buffer.from(value).toString(\"base64\") : value\n\nasync function parseOne(req: ParseWorkerRequest & { file: string }): Promise<ParseResult> {\n const absPath = resolve(req.file)\n const options: ParseOptions = { filePath: absPath }\n if (req.images === false) options.images = false\n if (req.ocr === \"force\") options.ocr = \"force\"\n else if (req.ocr === \"auto\") options.ocr = true\n if (req.formulaOcr) options.formulaOcr = true\n if (req.password) options.password = req.password\n return parseWorkerFile(absPath, options)\n}\n\nexport function registerWorkerCommands(program: Command): void {\n program\n .command(\"parse-worker\")\n .description(\"상주 파싱 워커: stdin NDJSON 요청 → 한 줄 JSON 응답 (프로세스 유지, 파일마다 node 를 새로 띄우는 비용 제거)\")\n .option(\"--protocol <version>\", \"프로토콜 버전: 1(기본) | 2(Java·Python SDK — ParseOptions·이미지 파일 전송, docs/parse-worker-protocol.md)\", \"1\")\n .option(\"--max-request-bytes <n>\", \"protocol 2: 요청 한 줄 상한 바이트\")\n .option(\"--max-response-bytes <n>\", \"protocol 2: 응답 한 줄 상한 바이트\")\n .action(async (opts: { protocol: string; maxRequestBytes?: string; maxResponseBytes?: string }) => {\n if (opts.protocol === \"2\") {\n const limit = (v: string | undefined, name: string): number | undefined => {\n if (v === undefined) return undefined\n const n = Number(v)\n if (!/^\\d+$/.test(v) || !Number.isSafeInteger(n) || n < 1) {\n process.stderr.write(`[kordoc] ${name} 는 양의 정수여야 합니다: ${v}\\n`)\n process.exit(2)\n }\n return n\n }\n const maxRequestBytes = limit(opts.maxRequestBytes, \"--max-request-bytes\")\n const maxResponseBytes = limit(opts.maxResponseBytes, \"--max-response-bytes\")\n routeConsoleToStderr()\n const { runParseWorkerV2 } = await import(\"./parse-worker-v2.js\")\n await runParseWorkerV2({ maxRequestBytes, maxResponseBytes })\n process.exit(0)\n }\n if (opts.protocol !== \"1\") {\n // CLI 단건 실행 등으로 조용히 대체하지 않는다 — 호스트가 엔진 버전 불일치를 바로 알게\n process.stderr.write(`[kordoc] 지원하지 않는 parse-worker protocol: ${opts.protocol} (1, 2)\\n`)\n process.exit(2)\n }\n // 프로토콜(NDJSON, 한 줄 = 한 메시지):\n // 시작 {\"ready\":true,\"version\":\"4.14.3\",\"protocol\":1}\n // 요청 {\"id\":1,\"file\":\"a.hwpx\",\"images\":false,\"ocr\":\"off\",\"formulaOcr\":false,\"password\":null}\n // 응답 {\"id\":1,\"rss\":123456789,\"result\":{…}}: result 는 --format json 과 같은 ParseResult (실패도 success:false 로)\n // {\"id\":1,\"error\":\"…\"}: 요청 자체가 잘못됐을 때\n // {\"cmd\":\"quit\"} 또는 stdin 닫힘으로 종료. rss 는 호스트가 워커 교체 시점을 정하는 데 쓴다.\n // pdfjs 등이 console 로 찍는 경고가 stdout 프로토콜 줄을 깨지 않게 stderr 로 돌린다\n routeConsoleToStderr()\n const { createInterface } = await import(\"node:readline\")\n const rl = createInterface({ input: process.stdin, crlfDelay: Infinity })\n const write = (o: unknown): void => void process.stdout.write(JSON.stringify(o, bytesToBase64) + \"\\n\")\n write({ ready: true, version: VERSION, protocol: PARSE_WORKER_PROTOCOL })\n for await (const line of rl) {\n const t = line.trim()\n if (!t) continue\n let req: ParseWorkerRequest\n // 비JSON 라인도 응답은 낸다. 무음 삼킴이면 id 를 기다리는 호스트가 영구 대기\n try { req = JSON.parse(t) } catch { write({ error: \"잘못된 JSON 라인\" }); continue }\n if (req === null || typeof req !== \"object\") { write({ error: \"JSON 객체가 아닙니다\" }); continue }\n if (req.cmd === \"quit\") break\n const id = req.id\n if (typeof req.file !== \"string\" || !req.file) { write({ id, error: \"file 필수\" }); continue }\n const result = await parseOne({ ...req, file: req.file })\n try {\n write({ id, rss: process.memoryUsage.rss(), result })\n } catch (err) {\n // 직렬화 한계(이미지 수백 장 base64 등, #65)는 실패 JSON 계약으로\n write({ id, rss: process.memoryUsage.rss(), result: { success: false, fileType: result.fileType, error: sanitizeError(err), code: classifyError(err) } })\n }\n }\n rl.close()\n // 파이프 stdout 은 맥·윈도에서 비동기라 바로 exit 하면 마지막 응답이 잘린다. 다 비운 뒤 끝낸다.\n // pdfjs 등이 남긴 핸들이 있어도 워커는 끝낸다 (호스트가 죽어 stdin 이 닫힌 경우의 고아 방지)\n await new Promise<void>((done) => process.stdout.write(\"\", () => done()))\n process.exit(0)\n })\n}\n"],"mappings":"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","names":["statSync","basename","resolve","resolve","basename","statSync","output","basename","program","basename","resolve","readFileSync","writeFileSync","mkdirSync","statSync","basename","resolve","program","resolve","statSync","readFileSync","basename","result","formInfo","mkdirSync","writeFileSync","detectFormat","readFileSync","writeFileSync","mkdirSync","statSync","basename","dirname","resolve","text","program","readFileSync","resolve","basename","buf","outPath","statSync","mkdirSync","dirname","writeFileSync","parse","readFileSync","writeFileSync","mkdirSync","dirname","resolve","program","resolve","readFileSync","mkdirSync","dirname","writeFileSync","program","resolve","resolve","program"]}