kordoc 4.18.2 → 4.18.4

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 (152) hide show
  1. package/dist/{-I3CP33G4.js → -DDAVBMHD.js} +11 -11
  2. package/dist/{chunk-O2DI4GHD.js → chunk-274ZPMHK.js} +2 -2
  3. package/dist/{chunk-QGFZU3JE.cjs → chunk-3WLZOJIE.cjs} +10 -8
  4. package/dist/chunk-3WLZOJIE.cjs.map +1 -0
  5. package/dist/{chunk-UZGZRGYM.cjs → chunk-3XSP7V5P.cjs} +10 -5
  6. package/dist/chunk-3XSP7V5P.cjs.map +1 -0
  7. package/dist/{chunk-GM7XIZF2.js → chunk-4IBY5LTJ.js} +2 -2
  8. package/dist/chunk-6H25SXDI.js +11 -0
  9. package/dist/chunk-6H25SXDI.js.map +1 -0
  10. package/dist/{chunk-N5DQFA7L.js → chunk-7GR2GCJF.js} +10 -5
  11. package/dist/chunk-7GR2GCJF.js.map +1 -0
  12. package/dist/{chunk-YNLW6EGU.cjs → chunk-AVIZ55NQ.cjs} +3 -3
  13. package/dist/chunk-AVIZ55NQ.cjs.map +1 -0
  14. package/dist/chunk-DC6CTQTK.js +9 -0
  15. package/dist/chunk-DC6CTQTK.js.map +1 -0
  16. package/dist/{chunk-L5RLJPI3.js → chunk-DUV7Y6IQ.js} +3 -3
  17. package/dist/{chunk-KDMAYOWH.cjs → chunk-E2644XCO.cjs} +698 -189
  18. package/dist/chunk-E2644XCO.cjs.map +1 -0
  19. package/dist/{chunk-LSOD2A6N.js → chunk-ELOPDQES.js} +2 -2
  20. package/dist/{chunk-M4P7YS2N.js → chunk-F2GDLA45.js} +81 -61
  21. package/dist/chunk-F2GDLA45.js.map +1 -0
  22. package/dist/{chunk-OBILAVWC.js → chunk-F5YVCJVF.js} +10 -5
  23. package/dist/chunk-F5YVCJVF.js.map +1 -0
  24. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  25. package/dist/{chunk-4B2EXELH.js → chunk-HRJJDNRD.js} +2 -2
  26. package/dist/{chunk-CKUIFTXJ.js → chunk-IAXGGQGD.js} +2 -2
  27. package/dist/{chunk-BL7KRE6X.js → chunk-IBQCK4F3.js} +7 -3
  28. package/dist/chunk-IBQCK4F3.js.map +1 -0
  29. package/dist/chunk-J55UQC5H.cjs.map +1 -1
  30. package/dist/{chunk-OGAYGUJF.js → chunk-KUUSP6OS.js} +581 -72
  31. package/dist/chunk-KUUSP6OS.js.map +1 -0
  32. package/dist/{chunk-LACO375L.js → chunk-LGF2IO66.js} +4 -3
  33. package/dist/chunk-LGF2IO66.js.map +1 -0
  34. package/dist/{chunk-L64QRUMK.js → chunk-MXA6YW2W.js} +582 -73
  35. package/dist/chunk-MXA6YW2W.js.map +1 -0
  36. package/dist/{chunk-OI5ZSSIC.cjs → chunk-OIUSF2VA.cjs} +16 -12
  37. package/dist/chunk-OIUSF2VA.cjs.map +1 -0
  38. package/dist/{chunk-6OKBTY72.js → chunk-QVCHFCT2.js} +2 -2
  39. package/dist/{chunk-C2CVOC5K.js → chunk-RCI7LY4N.js} +8 -4
  40. package/dist/chunk-RCI7LY4N.js.map +1 -0
  41. package/dist/{chunk-W2YYBPW5.cjs → chunk-SVNBZEL6.cjs} +3 -3
  42. package/dist/chunk-SVNBZEL6.cjs.map +1 -0
  43. package/dist/{chunk-VSY5PAJ5.js → chunk-T2BJPT6D.js} +3 -3
  44. package/dist/{chunk-VSY5PAJ5.js.map → chunk-T2BJPT6D.js.map} +1 -1
  45. package/dist/chunk-TK3FDAEE.cjs +9 -0
  46. package/dist/chunk-TK3FDAEE.cjs.map +1 -0
  47. package/dist/{chunk-F5HING4Y.js → chunk-TMJVD6FW.js} +5 -4
  48. package/dist/chunk-TMJVD6FW.js.map +1 -0
  49. package/dist/{chunk-T4MXCSBP.js → chunk-V5X4LLVM.js} +71 -47
  50. package/dist/chunk-V5X4LLVM.js.map +1 -0
  51. package/dist/{chunk-IA3UKDHA.js → chunk-VTVK2JMI.js} +3 -2
  52. package/dist/{chunk-IA3UKDHA.js.map → chunk-VTVK2JMI.js.map} +1 -1
  53. package/dist/{chunk-B2E6C2LH.js → chunk-XG4SYOZL.js} +6 -4
  54. package/dist/chunk-XG4SYOZL.js.map +1 -0
  55. package/dist/{chunk-QP7IXF7R.js → chunk-YCY2R4FM.js} +2 -2
  56. package/dist/{chunk-NZM2SSI4.js → chunk-Z2PPDQK2.js} +2 -2
  57. package/dist/chunks-5QTTAT5T.js +10 -0
  58. package/dist/cli.js +179 -119
  59. package/dist/cli.js.map +1 -1
  60. package/dist/{formula-E3N7KDDG.js → formula-7ZOZ5QJ6.js} +8 -4
  61. package/dist/{formula-E3N7KDDG.js.map → formula-7ZOZ5QJ6.js.map} +1 -1
  62. package/dist/{formula-AQZODKZF.js → formula-HQFZEXFF.js} +7 -3
  63. package/dist/{formula-AQZODKZF.js.map → formula-HQFZEXFF.js.map} +1 -1
  64. package/dist/{formula-VY4ITOMN.cjs → formula-YYJQBKEN.cjs} +13 -9
  65. package/dist/formula-YYJQBKEN.cjs.map +1 -0
  66. package/dist/{image-ocr-IMYXOHHV.js → image-ocr-4BGX2EJJ.js} +7 -6
  67. package/dist/{image-ocr-IMYXOHHV.js.map → image-ocr-4BGX2EJJ.js.map} +1 -1
  68. package/dist/{image-ocr-6LYEBMVR.cjs → image-ocr-CC26Q5KG.cjs} +16 -15
  69. package/dist/image-ocr-CC26Q5KG.cjs.map +1 -0
  70. package/dist/{image-ocr-LN3GSQPW.js → image-ocr-RK3HJVCI.js} +10 -9
  71. package/dist/{image-ocr-LN3GSQPW.js.map → image-ocr-RK3HJVCI.js.map} +1 -1
  72. package/dist/index.cjs +860 -817
  73. package/dist/index.cjs.map +1 -1
  74. package/dist/index.js +141 -98
  75. package/dist/index.js.map +1 -1
  76. package/dist/mcp.js +26 -26
  77. package/dist/mcp.js.map +1 -1
  78. package/dist/{model-bundle-IHKNDLOT.js → model-bundle-VHRXG63R.js} +5 -5
  79. package/dist/{models-YXITRAMR.js → models-G3WA24SY.js} +5 -5
  80. package/dist/page-range-QHHFTL7X.cjs.map +1 -1
  81. package/dist/{parser-7KECZTTP.cjs → parser-BGORCLIU.cjs} +461 -243
  82. package/dist/parser-BGORCLIU.cjs.map +1 -0
  83. package/dist/{parser-M3T2EWUN.js → parser-GFDGAVLV.js} +255 -37
  84. package/dist/parser-GFDGAVLV.js.map +1 -0
  85. package/dist/{parser-KB4BYQBZ.js → parser-SOWTUOMK.js} +258 -40
  86. package/dist/parser-SOWTUOMK.js.map +1 -0
  87. package/dist/pdf-ocr-7IOOVR2I.js +20 -0
  88. package/dist/pdf-ocr-EJ2HNZN6.cjs +17 -0
  89. package/dist/pdf-ocr-EJ2HNZN6.cjs.map +1 -0
  90. package/dist/pdf-ocr-RACAZU3N.js +16 -0
  91. package/dist/{profile-io-GQWQR7YQ.js → profile-io-Q2T47RVH.js} +3 -3
  92. package/dist/{rasterize-Y6TVFQ3M.js → rasterize-OAVMUTE6.js} +3 -3
  93. package/dist/{redact-doc-TRPZ3HNW.js → redact-doc-ECFOVR4X.js} +11 -11
  94. package/dist/{render-GHT5HKBO.js → render-NSKWZVTD.js} +7 -7
  95. package/dist/seal-A4MG7MPQ.js +10 -0
  96. package/dist/{setup-AGSCEHDB.js → setup-REH2KZP2.js} +3 -3
  97. package/dist/visual-B56WQAGW.js +20 -0
  98. package/dist/{watch-ALSEW4GB.js → watch-JXDUZYBY.js} +13 -13
  99. package/dist/watch-JXDUZYBY.js.map +1 -0
  100. package/package.json +1 -1
  101. package/dist/chunk-B2E6C2LH.js.map +0 -1
  102. package/dist/chunk-BL7KRE6X.js.map +0 -1
  103. package/dist/chunk-C2CVOC5K.js.map +0 -1
  104. package/dist/chunk-F5HING4Y.js.map +0 -1
  105. package/dist/chunk-KDMAYOWH.cjs.map +0 -1
  106. package/dist/chunk-L64QRUMK.js.map +0 -1
  107. package/dist/chunk-LACO375L.js.map +0 -1
  108. package/dist/chunk-M4P7YS2N.js.map +0 -1
  109. package/dist/chunk-N5DQFA7L.js.map +0 -1
  110. package/dist/chunk-OBILAVWC.js.map +0 -1
  111. package/dist/chunk-OGAYGUJF.js.map +0 -1
  112. package/dist/chunk-OI5ZSSIC.cjs.map +0 -1
  113. package/dist/chunk-QGFZU3JE.cjs.map +0 -1
  114. package/dist/chunk-T4MXCSBP.js.map +0 -1
  115. package/dist/chunk-UZGZRGYM.cjs.map +0 -1
  116. package/dist/chunk-W2YYBPW5.cjs.map +0 -1
  117. package/dist/chunk-YNLW6EGU.cjs.map +0 -1
  118. package/dist/chunks-IFFRC5IQ.js +0 -10
  119. package/dist/formula-VY4ITOMN.cjs.map +0 -1
  120. package/dist/image-ocr-6LYEBMVR.cjs.map +0 -1
  121. package/dist/parser-7KECZTTP.cjs.map +0 -1
  122. package/dist/parser-KB4BYQBZ.js.map +0 -1
  123. package/dist/parser-M3T2EWUN.js.map +0 -1
  124. package/dist/pdf-ocr-4S2OAHUX.js +0 -15
  125. package/dist/pdf-ocr-IGYCZ7G2.cjs +0 -16
  126. package/dist/pdf-ocr-IGYCZ7G2.cjs.map +0 -1
  127. package/dist/pdf-ocr-YEBFWU2K.js +0 -19
  128. package/dist/seal-3YTXSABW.js +0 -10
  129. package/dist/visual-R3E35Q2K.js +0 -20
  130. package/dist/watch-ALSEW4GB.js.map +0 -1
  131. /package/dist/{-I3CP33G4.js.map → -DDAVBMHD.js.map} +0 -0
  132. /package/dist/{chunk-O2DI4GHD.js.map → chunk-274ZPMHK.js.map} +0 -0
  133. /package/dist/{chunk-GM7XIZF2.js.map → chunk-4IBY5LTJ.js.map} +0 -0
  134. /package/dist/{chunk-L5RLJPI3.js.map → chunk-DUV7Y6IQ.js.map} +0 -0
  135. /package/dist/{chunk-LSOD2A6N.js.map → chunk-ELOPDQES.js.map} +0 -0
  136. /package/dist/{chunk-4B2EXELH.js.map → chunk-HRJJDNRD.js.map} +0 -0
  137. /package/dist/{chunk-CKUIFTXJ.js.map → chunk-IAXGGQGD.js.map} +0 -0
  138. /package/dist/{chunk-6OKBTY72.js.map → chunk-QVCHFCT2.js.map} +0 -0
  139. /package/dist/{chunk-QP7IXF7R.js.map → chunk-YCY2R4FM.js.map} +0 -0
  140. /package/dist/{chunk-NZM2SSI4.js.map → chunk-Z2PPDQK2.js.map} +0 -0
  141. /package/dist/{chunks-IFFRC5IQ.js.map → chunks-5QTTAT5T.js.map} +0 -0
  142. /package/dist/{model-bundle-IHKNDLOT.js.map → model-bundle-VHRXG63R.js.map} +0 -0
  143. /package/dist/{models-YXITRAMR.js.map → models-G3WA24SY.js.map} +0 -0
  144. /package/dist/{pdf-ocr-4S2OAHUX.js.map → pdf-ocr-7IOOVR2I.js.map} +0 -0
  145. /package/dist/{pdf-ocr-YEBFWU2K.js.map → pdf-ocr-RACAZU3N.js.map} +0 -0
  146. /package/dist/{profile-io-GQWQR7YQ.js.map → profile-io-Q2T47RVH.js.map} +0 -0
  147. /package/dist/{rasterize-Y6TVFQ3M.js.map → rasterize-OAVMUTE6.js.map} +0 -0
  148. /package/dist/{redact-doc-TRPZ3HNW.js.map → redact-doc-ECFOVR4X.js.map} +0 -0
  149. /package/dist/{render-GHT5HKBO.js.map → render-NSKWZVTD.js.map} +0 -0
  150. /package/dist/{seal-3YTXSABW.js.map → seal-A4MG7MPQ.js.map} +0 -0
  151. /package/dist/{setup-AGSCEHDB.js.map → setup-REH2KZP2.js.map} +0 -0
  152. /package/dist/{visual-R3E35Q2K.js.map → visual-B56WQAGW.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  parseFormatProfileJson
4
- } from "./chunk-VSY5PAJ5.js";
4
+ } from "./chunk-T2BJPT6D.js";
5
5
  import {
6
6
  BODY_FONTS,
7
7
  BULLET2_CHARS,
@@ -29,26 +29,28 @@ import {
29
29
  parse,
30
30
  readBuiltinTemplate,
31
31
  resolveBuiltinTemplate,
32
+ toHtmlTables,
33
+ toPlainMarkdown,
32
34
  unknownFontWarnings,
33
35
  usesGaejosikMunche
34
- } from "./chunk-M4P7YS2N.js";
35
- import "./chunk-GM7XIZF2.js";
36
- import "./chunk-L5RLJPI3.js";
36
+ } from "./chunk-F2GDLA45.js";
37
+ import "./chunk-4IBY5LTJ.js";
38
+ import "./chunk-DUV7Y6IQ.js";
37
39
  import "./chunk-3WSNLH4B.js";
38
- import "./chunk-QP7IXF7R.js";
40
+ import "./chunk-YCY2R4FM.js";
39
41
  import {
40
42
  detectFormat,
41
43
  detectImageMime,
42
44
  detectZipFormat
43
- } from "./chunk-T4MXCSBP.js";
45
+ } from "./chunk-V5X4LLVM.js";
44
46
  import "./chunk-7FCNOKOR.js";
45
- import "./chunk-F5HING4Y.js";
47
+ import "./chunk-TMJVD6FW.js";
46
48
  import "./chunk-VQFA55IC.js";
47
- import "./chunk-LACO375L.js";
49
+ import "./chunk-LGF2IO66.js";
48
50
  import {
49
51
  blocksToMarkdown
50
- } from "./chunk-IA3UKDHA.js";
51
- import "./chunk-CKUIFTXJ.js";
52
+ } from "./chunk-VTVK2JMI.js";
53
+ import "./chunk-IAXGGQGD.js";
52
54
  import {
53
55
  KordocError,
54
56
  VERSION,
@@ -56,26 +58,57 @@ import {
56
58
  routeConsoleToStderr,
57
59
  sanitizeError,
58
60
  toArrayBuffer
59
- } from "./chunk-OBILAVWC.js";
61
+ } from "./chunk-F5YVCJVF.js";
60
62
 
61
63
  // src/cli.ts
62
64
  import { Command } from "commander";
63
65
 
64
66
  // src/cli/convert.ts
65
- import { readFileSync, writeFileSync, mkdirSync, statSync } from "fs";
67
+ import { readFileSync, writeFileSync, mkdirSync, statSync as statSync2 } from "fs";
68
+ import { basename as basename2, resolve as resolve2 } from "path";
69
+
70
+ // src/cli/output-path.ts
71
+ import { statSync } from "fs";
66
72
  import { basename, resolve } from "path";
73
+ function createOutputGuard(inputs) {
74
+ const paths = new Map(inputs.map((input) => [resolve(input), basename(input)]));
75
+ const identities = /* @__PURE__ */ new Map();
76
+ for (const [input, name] of paths) {
77
+ try {
78
+ const stat = statSync(input, { bigint: true });
79
+ identities.set(`${stat.dev}:${stat.ino}`, name);
80
+ } catch {
81
+ }
82
+ }
83
+ return (outputs) => {
84
+ for (const output of outputs) {
85
+ let input = paths.get(resolve(output));
86
+ if (!input) {
87
+ try {
88
+ const stat = statSync(output, { bigint: true });
89
+ input = identities.get(`${stat.dev}:${stat.ino}`);
90
+ } catch (err) {
91
+ if (err.code !== "ENOENT" && err.code !== "ENOTDIR") throw err;
92
+ }
93
+ }
94
+ if (input) throw new Error(`\uCD9C\uB825 \uACBD\uB85C\uAC00 \uC785\uB825 \uD30C\uC77C\uACFC \uAC19\uC2B5\uB2C8\uB2E4: ${input}`);
95
+ }
96
+ };
97
+ }
98
+
99
+ // src/cli/convert.ts
67
100
  async function convertFiles(files, opts, writeOutput = (text) => {
68
101
  process.stdout.write(text);
69
- }) {
102
+ }, assertSafeOutputs = createOutputGuard(files)) {
70
103
  let failed = false;
71
104
  for (let fi = 0; fi < files.length; fi++) {
72
105
  const filePath = files[fi];
73
- const absPath = resolve(filePath);
74
- const fileName = basename(absPath);
106
+ const absPath = resolve2(filePath);
107
+ const fileName = basename2(absPath);
75
108
  const filePrefix = files.length > 1 ? `[${fi + 1}/${files.length}] ` : "";
76
109
  let detectedFormat = "unknown";
77
110
  try {
78
- const fileSize = statSync(absPath).size;
111
+ const fileSize = statSync2(absPath).size;
79
112
  if (fileSize > 500 * 1024 * 1024) {
80
113
  process.stderr.write(`
81
114
  [kordoc] SKIP: ${fileName} \u2014 \uD30C\uC77C\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${(fileSize / 1024 / 1024).toFixed(1)}MB)
@@ -129,11 +162,10 @@ async function convertFiles(files, opts, writeOutput = (text) => {
129
162
  let markdown = result.markdown;
130
163
  const imagesInlined = opts.inlineImages && result.fileType === "hwp";
131
164
  const savesImageFiles = Boolean(opts.outDir || opts.output && files.length === 1);
132
- const docStem = (opts.output && files.length === 1 ? basename(opts.output) : fileName).replace(/\.[^.]+$/, "");
165
+ const docStem = (opts.output && files.length === 1 ? basename2(opts.output) : fileName).replace(/\.[^.]+$/, "");
133
166
  const imgLink = `images/${docStem.replace(/[ ()]/g, (ch) => encodeURIComponent(ch))}/`;
134
- if (savesImageFiles && result.images?.length && !imagesInlined) {
135
- markdown = markdown.replace(/!\[image\]\(image_/g, `![image](${imgLink}image_`).replace(/(<img\b[^>]*\bsrc=")image_/g, `$1${imgLink}image_`);
136
- }
167
+ const linkImages = (text) => savesImageFiles && result.images?.length && !imagesInlined ? text.replace(/!\[image\]\(image_/g, `![image](${imgLink}image_`).replace(/(<img\b[^>]*\bsrc=")image_/g, `$1${imgLink}image_`) : text;
168
+ markdown = linkImages(markdown);
137
169
  const serializeJson = (refsOnly) => {
138
170
  const payload = refsOnly && result.images?.length ? { ...result, images: result.images.map((img) => ({ filename: img.filename, mimeType: img.mimeType, path: `images/${docStem}/${img.filename}` })) } : result;
139
171
  return JSON.stringify(
@@ -154,17 +186,23 @@ async function convertFiles(files, opts, writeOutput = (text) => {
154
186
  `);
155
187
  }
156
188
  } else if (opts.format === "chunks") {
157
- const { blocksToChunks } = await import("./chunks-IFFRC5IQ.js");
158
- output = JSON.stringify(blocksToChunks(result.blocks), null, 2);
189
+ const { blocksToChunks } = await import("./chunks-5QTTAT5T.js");
190
+ const chunks = blocksToChunks(result.blocks).map((c) => {
191
+ let text = c.text;
192
+ if (opts.plain) text = toPlainMarkdown(text);
193
+ if (opts.htmlTables) text = toHtmlTables(text);
194
+ return { ...c, text: linkImages(text) };
195
+ });
196
+ output = JSON.stringify(chunks, null, 2);
159
197
  } else {
160
198
  output = markdown;
161
199
  }
162
200
  const saveImages = (dir) => {
163
201
  if (!result.images?.length || imagesInlined) return;
164
- const imgDir = resolve(dir, "images", docStem);
202
+ const imgDir = resolve2(dir, "images", docStem);
165
203
  mkdirSync(imgDir, { recursive: true });
166
204
  for (const img of result.images) {
167
- writeFileSync(resolve(imgDir, img.filename), img.data);
205
+ writeFileSync(resolve2(imgDir, img.filename), img.data);
168
206
  }
169
207
  const manifest = result.images.map((img) => ({
170
208
  name: img.filename,
@@ -172,19 +210,25 @@ async function convertFiles(files, opts, writeOutput = (text) => {
172
210
  bytes: img.data.length,
173
211
  ...img.source ? { source: img.source } : {}
174
212
  }));
175
- writeFileSync(resolve(imgDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
213
+ writeFileSync(resolve2(imgDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
176
214
  if (!opts.silent) process.stderr.write(` \u2192 ${result.images.length}\uAC1C \uC774\uBBF8\uC9C0 \u2192 ${imgDir} (manifest.json \uD3EC\uD568)
177
215
  `);
178
216
  };
217
+ const assertSafeDestination = (output2, dir) => {
218
+ const imageOutputs = result.images?.length && !imagesInlined ? [...result.images.map((img) => resolve2(dir, "images", docStem, img.filename)), resolve2(dir, "images", docStem, "manifest.json")] : [];
219
+ assertSafeOutputs([output2, ...imageOutputs]);
220
+ };
179
221
  if (opts.output && files.length === 1) {
222
+ assertSafeDestination(opts.output, resolve2(opts.output, ".."));
180
223
  writeFileSync(opts.output, output, "utf-8");
181
224
  if (!opts.silent) process.stderr.write(` \u2192 ${opts.output}
182
225
  `);
183
- saveImages(resolve(opts.output, ".."));
226
+ saveImages(resolve2(opts.output, ".."));
184
227
  } else if (opts.outDir) {
185
228
  mkdirSync(opts.outDir, { recursive: true });
186
229
  const outExt = opts.format === "json" ? ".json" : opts.format === "chunks" ? ".chunks.json" : ".md";
187
- const outPath = resolve(opts.outDir, fileName.replace(/\.[^.]+$/, outExt));
230
+ const outPath = resolve2(opts.outDir, fileName.replace(/\.[^.]+$/, "") + outExt);
231
+ assertSafeDestination(outPath, opts.outDir);
188
232
  writeFileSync(outPath, output, "utf-8");
189
233
  if (!opts.silent) process.stderr.write(` \u2192 ${outPath}
190
234
  `);
@@ -213,27 +257,32 @@ async function convertFiles(files, opts, writeOutput = (text) => {
213
257
 
214
258
  // src/cli/batch.ts
215
259
  import { fork } from "child_process";
216
- import { basename as basename2 } from "path";
260
+ import { basename as basename3 } from "path";
217
261
  function registerBatchWorker(program2) {
218
262
  program2.command("__convert-worker", { hidden: true }).action(() => {
219
263
  if (!process.send) program2.error("Internal command requires an IPC channel");
220
264
  process.on("disconnect", () => process.exit(0));
221
- process.on("message", async ({ file, opts }) => {
265
+ let assertSafeOutputs;
266
+ process.on("message", async ({ file, opts, inputs }) => {
222
267
  const output = [];
268
+ assertSafeOutputs ??= createOutputGuard(inputs ?? [file]);
223
269
  const ok = await convertFiles([file], opts, (text) => {
224
270
  output.push(text);
225
- });
271
+ }, assertSafeOutputs);
226
272
  process.send({ ok, output });
227
273
  });
228
274
  });
229
275
  }
230
- async function convertParallel(files, opts, jobs) {
276
+ function assertDistinctStems(files) {
231
277
  const stems = /* @__PURE__ */ new Set();
232
278
  for (const file of files) {
233
- const stem = basename2(file).replace(/\.[^.]+$/, "").normalize("NFC").toLowerCase();
234
- if (stems.has(stem)) throw new KordocError(`Parallel output name collision: ${basename2(file)}; use distinct file stems`);
279
+ const stem = basename3(file).replace(/\.[^.]+$/, "").normalize("NFC").toLowerCase();
280
+ if (stems.has(stem)) throw new KordocError(`Output name collision: ${basename3(file)}; use distinct file stems`);
235
281
  stems.add(stem);
236
282
  }
283
+ }
284
+ async function convertParallel(files, opts, jobs) {
285
+ assertDistinctStems(files);
237
286
  const workers = [];
238
287
  let next = 0;
239
288
  let failed = false;
@@ -251,33 +300,35 @@ async function convertParallel(files, opts, jobs) {
251
300
  process.once("SIGINT", onSigint);
252
301
  process.once("SIGTERM", onSigterm);
253
302
  try {
254
- await Promise.all(Array.from({ length: Math.min(jobs, files.length) }, () => new Promise((resolve6, reject) => {
303
+ await Promise.all(Array.from({ length: Math.min(jobs, files.length) }, () => new Promise((resolve7, reject) => {
255
304
  const worker = fork(process.argv[1], ["__convert-worker"], { stdio: ["ignore", "ignore", "inherit", "ipc"] });
256
305
  workers.push(worker);
257
306
  let current;
258
307
  let finished = false;
308
+ let firstJob = true;
259
309
  worker.on("error", reject);
260
310
  worker.on("exit", (code, signal) => {
261
- if (!finished) reject(new KordocError(`Conversion worker exited (${signal ?? code}) while processing ${basename2(current ?? "unknown")}`));
311
+ if (!finished) reject(new KordocError(`Conversion worker exited (${signal ?? code}) while processing ${basename3(current ?? "unknown")}`));
262
312
  });
263
313
  const dispatch = () => {
264
314
  if (next === files.length) {
265
315
  finished = true;
266
316
  worker.disconnect();
267
- resolve6();
317
+ resolve7();
268
318
  return;
269
319
  }
270
320
  current = files[next++];
271
- if (!opts.silent) process.stderr.write(`[kordoc] [${next}/${files.length}] ${basename2(current)} ...
321
+ if (!opts.silent) process.stderr.write(`[kordoc] [${next}/${files.length}] ${basename3(current)} ...
272
322
  `);
273
- worker.send({ file: current, opts: { ...opts, output: void 0, silent: true } }, (err) => {
323
+ worker.send({ file: current, opts: { ...opts, output: void 0, silent: true }, ...firstJob ? { inputs: files } : {} }, (err) => {
274
324
  if (err) reject(err);
275
325
  });
326
+ firstJob = false;
276
327
  };
277
328
  worker.on("message", ({ ok, output }) => {
278
329
  if (!ok) failed = true;
279
330
  for (const text of output) process.stdout.write(text);
280
- if (!opts.silent) process.stderr.write(`[kordoc] ${basename2(current)} ${ok ? "OK" : "FAIL"}
331
+ if (!opts.silent) process.stderr.write(`[kordoc] ${basename3(current)} ${ok ? "OK" : "FAIL"}
281
332
  `);
282
333
  dispatch();
283
334
  });
@@ -292,8 +343,8 @@ async function convertParallel(files, opts, jobs) {
292
343
  }
293
344
 
294
345
  // src/cli/commands-docs.ts
295
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, statSync as statSync2 } from "fs";
296
- import { basename as basename3, dirname, resolve as resolve2, extname } from "path";
346
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, statSync as statSync3 } from "fs";
347
+ import { basename as basename4, dirname, resolve as resolve3, extname } from "path";
297
348
  function registerDocCommands(program2) {
298
349
  program2.command("watch <dir>").description("\uB514\uB809\uD1A0\uB9AC \uAC10\uC2DC \u2014 \uC0C8 \uBB38\uC11C \uC790\uB3D9 \uBCC0\uD658").option("--webhook <url>", "\uACB0\uACFC \uC804\uC1A1 \uC6F9\uD6C5 URL").option("-d, --out-dir <dir>", "\uBCC0\uD658 \uACB0\uACFC \uCD9C\uB825 \uB514\uB809\uD1A0\uB9AC").option("-p, --pages <range>", "\uD398\uC774\uC9C0/\uC139\uC158 \uBC94\uC704").option("--format <type>", "\uCD9C\uB825 \uD615\uC2DD: markdown \uB610\uB294 json", "markdown").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (dir, opts, command) => {
299
350
  const rootOpts = program2.opts();
@@ -303,7 +354,7 @@ function registerDocCommands(program2) {
303
354
  if (command.getOptionValueSource("format") === "default" && program2.getOptionValueSource("format") === "cli") {
304
355
  opts.format = rootOpts.format;
305
356
  }
306
- const { watchDirectory } = await import("./watch-ALSEW4GB.js");
357
+ const { watchDirectory } = await import("./watch-JXDUZYBY.js");
307
358
  await watchDirectory({
308
359
  dir,
309
360
  outDir: opts.outDir,
@@ -343,15 +394,15 @@ function registerDocCommands(program2) {
343
394
  arrayBuffer = readBuiltinTemplate(t);
344
395
  inputName = t.file;
345
396
  } else if (file) {
346
- const absPath = resolve2(file);
347
- const fileSize = statSync2(absPath).size;
397
+ const absPath = resolve3(file);
398
+ const fileSize = statSync3(absPath).size;
348
399
  if (fileSize > 500 * 1024 * 1024) {
349
400
  process.stderr.write(`[kordoc] \uD30C\uC77C\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${(fileSize / 1024 / 1024).toFixed(1)}MB)
350
401
  `);
351
402
  process.exit(1);
352
403
  }
353
404
  arrayBuffer = toArrayBuffer(readFileSync2(absPath));
354
- inputName = basename3(absPath);
405
+ inputName = basename4(absPath);
355
406
  } else {
356
407
  process.stderr.write(`[kordoc] \uC11C\uC2DD \uD30C\uC77C \uACBD\uB85C \uB610\uB294 --template \uC744 \uC9C0\uC815\uD574\uC8FC\uC138\uC694 (\uBAA9\uB85D: kordoc fill --list-templates)
357
408
  `);
@@ -383,8 +434,8 @@ function registerDocCommands(program2) {
383
434
  }
384
435
  let values = {};
385
436
  if (opts.json) {
386
- const jsonPath = resolve2(opts.json);
387
- const jsonContent = readFileSync2(jsonPath, "utf-8");
437
+ const jsonPath = resolve3(opts.json);
438
+ const jsonContent = readFileSync2(jsonPath, "utf-8").replace(/^/, "");
388
439
  values = JSON.parse(jsonContent);
389
440
  } else if (opts.fields) {
390
441
  const fieldsStr = opts.fields;
@@ -459,9 +510,9 @@ function registerDocCommands(program2) {
459
510
  }
460
511
  }
461
512
  if (opts.output) {
462
- mkdirSync2(dirname(resolve2(opts.output)), { recursive: true });
463
- writeFileSync2(resolve2(opts.output), Buffer.from(hwpxResult.buffer));
464
- if (!opts.silent) process.stderr.write(`[kordoc] \u2192 ${resolve2(opts.output)}
513
+ mkdirSync2(dirname(resolve3(opts.output)), { recursive: true });
514
+ writeFileSync2(resolve3(opts.output), Buffer.from(hwpxResult.buffer));
515
+ if (!opts.silent) process.stderr.write(`[kordoc] \u2192 ${resolve3(opts.output)}
465
516
  `);
466
517
  } else {
467
518
  process.stdout.write(Buffer.from(hwpxResult.buffer));
@@ -497,18 +548,18 @@ function registerDocCommands(program2) {
497
548
  if (outputFormat === "hwpx") {
498
549
  const hwpxBuffer = await markdownToHwpx(markdown);
499
550
  if (opts.output) {
500
- mkdirSync2(dirname(resolve2(opts.output)), { recursive: true });
501
- writeFileSync2(resolve2(opts.output), Buffer.from(hwpxBuffer));
502
- if (!opts.silent) process.stderr.write(`[kordoc] \u2192 ${resolve2(opts.output)}
551
+ mkdirSync2(dirname(resolve3(opts.output)), { recursive: true });
552
+ writeFileSync2(resolve3(opts.output), Buffer.from(hwpxBuffer));
553
+ if (!opts.silent) process.stderr.write(`[kordoc] \u2192 ${resolve3(opts.output)}
503
554
  `);
504
555
  } else {
505
556
  process.stdout.write(Buffer.from(hwpxBuffer));
506
557
  }
507
558
  } else {
508
559
  if (opts.output) {
509
- mkdirSync2(dirname(resolve2(opts.output)), { recursive: true });
510
- writeFileSync2(resolve2(opts.output), markdown, "utf-8");
511
- if (!opts.silent) process.stderr.write(`[kordoc] \u2192 ${resolve2(opts.output)}
560
+ mkdirSync2(dirname(resolve3(opts.output)), { recursive: true });
561
+ writeFileSync2(resolve3(opts.output), markdown, "utf-8");
562
+ if (!opts.silent) process.stderr.write(`[kordoc] \u2192 ${resolve3(opts.output)}
512
563
  `);
513
564
  } else if (opts.mask) {
514
565
  process.stdout.write(`\u26A0\uFE0F --mask \uD65C\uC131 \u2014 \uAC1C\uC778\uC815\uBCF4 \uB178\uCD9C \uBC29\uC9C0\uB97C \uC704\uD574 \uBCF8\uBB38\uC744 \uCD9C\uB825\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. -o \uB85C \uD30C\uC77C \uC800\uC7A5 \uD6C4 \uD655\uC778\uD558\uC138\uC694.
@@ -525,7 +576,7 @@ function registerDocCommands(program2) {
525
576
  });
526
577
  program2.command("seal <file>").description('\uB3C4\uC7A5/\uC11C\uBA85 \uC774\uBBF8\uC9C0\uB97C \uC575\uCEE4 \uBB38\uAD6C \uC704\uC5D0 \uBD80\uC720 \uBC30\uCE58 (\uD45C/\uD398\uC774\uC9C0 \uBD88\uD655\uC7A5) \u2014 kordoc seal \uC2E0\uCCAD\uC11C.hwpx --image \uB3C4\uC7A5.png --anchor "(\uC778)" -o \uACB0\uACFC.hwpx').requiredOption("--image <path>", "\uB3C4\uC7A5/\uC11C\uBA85 \uC774\uBBF8\uC9C0 (\uD22C\uBA85 \uBC30\uACBD PNG \uAD8C\uC7A5)").option("--anchor <text>", "\uC575\uCEE4 \uBB38\uAD6C", "(\uC778)").option("-n, --occurrence <num>", "\uAC19\uC740 \uC575\uCEE4\uAC00 \uC5EC\uB7FF\uC77C \uB54C 0-based \uC120\uD0DD", "0").option("--size-mm <num>", "\uB3C4\uC7A5 \uD55C \uBCC0 \uD06C\uAE30 mm (\uAE30\uBCF8: \uC904\uB192\uC774\xD71.6, 7~18 \uD074\uB7A8\uD504)").option("--mode <mode>", "overlap(\uBB38\uAD6C \uC704 \uACB9\uCE68) | right(\uC624\uB978\uCABD \uC606) | auto", "auto").option("--dx <mm>", "x \uBBF8\uC138\uC870\uC815 mm", "0").option("--dy <mm>", "y \uBBF8\uC138\uC870\uC815 mm", "0").option("-o, --output <path>", "\uCD9C\uB825 \uACBD\uB85C (\uAE30\uBCF8: <\uC785\uB825>.sealed.hwpx)").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (file, opts) => {
527
578
  try {
528
- const { placeSealHwpx, detectFormat: detectFormat2 } = await import("./-I3CP33G4.js");
579
+ const { placeSealHwpx, detectFormat: detectFormat2 } = await import("./-DDAVBMHD.js");
529
580
  const rootOpts = program2.opts();
530
581
  const output = opts.output ?? rootOpts.output;
531
582
  const silent = opts.silent ?? rootOpts.silent;
@@ -535,14 +586,14 @@ function registerDocCommands(program2) {
535
586
  `);
536
587
  process.exit(1);
537
588
  }
538
- const buf = new Uint8Array(readFileSync2(resolve2(file)));
589
+ const buf = new Uint8Array(readFileSync2(resolve3(file)));
539
590
  if (detectFormat2(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)) !== "hwpx") {
540
591
  process.stderr.write(`[kordoc] seal \uC740 HWPX \uC804\uC6A9\uC785\uB2C8\uB2E4 (HWP 5.x \uBC14\uC774\uB108\uB9AC\uB294 \uBBF8\uC9C0\uC6D0)
541
592
  `);
542
593
  process.exit(1);
543
594
  }
544
- const imgPath = resolve2(opts.image);
545
- const imgSize = statSync2(imgPath).size;
595
+ const imgPath = resolve3(opts.image);
596
+ const imgSize = statSync3(imgPath).size;
546
597
  if (imgSize > 500 * 1024 * 1024) {
547
598
  process.stderr.write(`[kordoc] \uB3C4\uC7A5 \uC774\uBBF8\uC9C0\uAC00 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${(imgSize / 1024 / 1024).toFixed(0)}MB)
548
599
  `);
@@ -582,7 +633,7 @@ function registerDocCommands(program2) {
582
633
  dyMm: parseNum("--dy", opts.dy, { allowNeg: true })
583
634
  }]
584
635
  );
585
- const outPath = resolve2(output ?? file.replace(/\.hwpx$/i, "") + ".sealed.hwpx");
636
+ const outPath = resolve3(output ?? file.replace(/\.hwpx$/i, "") + ".sealed.hwpx");
586
637
  mkdirSync2(dirname(outPath), { recursive: true });
587
638
  writeFileSync2(outPath, Buffer.from(result.buffer));
588
639
  if (!silent) {
@@ -603,12 +654,12 @@ function registerDocCommands(program2) {
603
654
  });
604
655
  program2.command("patch <original> <edited>").description("\uC11C\uC2DD \uBCF4\uC874 \uB77C\uC6B4\uB4DC\uD2B8\uB9BD \uD328\uCE58 \u2014 \uD3B8\uC9D1\uB41C \uB9C8\uD06C\uB2E4\uC6B4\uC744 \uC6D0\uBCF8 HWPX/HWP\uC5D0 in-place \uBC18\uC601 (kordoc patch \uC6D0\uBCF8.hwpx \uD3B8\uC9D1.md -o \uCD9C\uB825.hwpx). \uBBF8\uC801\uC6A9(skip) \uD3B8\uC9D1\uC774 \uC788\uC73C\uBA74 exit 2").option("-o, --output <path>", "\uCD9C\uB825 \uACBD\uB85C (\uAE30\uBCF8: <\uC6D0\uBCF8>.patched.hwpx|.hwp)").option("--no-verify", "\uD328\uCE58 \uD6C4 \uC7AC\uD30C\uC2F1 \uC790\uB3D9 \uAC80\uC99D \uC0DD\uB7B5").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (original, edited, opts) => {
605
656
  try {
606
- const { patchHwpx, patchHwp, detectFormat: detectFormat2 } = await import("./-I3CP33G4.js");
657
+ const { patchHwpx, patchHwp, detectFormat: detectFormat2 } = await import("./-DDAVBMHD.js");
607
658
  const rootOpts = program2.opts();
608
659
  const output = opts.output ?? rootOpts.output;
609
660
  const silent = opts.silent ?? rootOpts.silent;
610
- const originalBuf = new Uint8Array(readFileSync2(resolve2(original)));
611
- const editedMarkdown = readFileSync2(resolve2(edited), "utf-8");
661
+ const originalBuf = new Uint8Array(readFileSync2(resolve3(original)));
662
+ const editedMarkdown = readFileSync2(resolve3(edited), "utf-8");
612
663
  const format = detectFormat2(originalBuf.buffer);
613
664
  const result = format === "hwp" ? await patchHwp(originalBuf, editedMarkdown, { verify: opts.verify !== false }) : await patchHwpx(originalBuf, editedMarkdown, { verify: opts.verify !== false });
614
665
  if (!result.success || !result.data) {
@@ -617,7 +668,7 @@ function registerDocCommands(program2) {
617
668
  process.exit(1);
618
669
  }
619
670
  const ext = format === "hwp" ? ".hwp" : ".hwpx";
620
- const outPath = resolve2(output ?? original.replace(/\.hwpx?$/i, "") + ".patched" + ext);
671
+ const outPath = resolve3(output ?? original.replace(/\.hwpx?$/i, "") + ".patched" + ext);
621
672
  mkdirSync2(dirname(outPath), { recursive: true });
622
673
  writeFileSync2(outPath, result.data);
623
674
  if (!silent) {
@@ -644,8 +695,8 @@ function registerDocCommands(program2) {
644
695
  });
645
696
  program2.command("validate <file>").description("HWPX \uAD6C\uC870 \uAC80\uC99D \u2014 ZIP\xB7mimetype\xB7\uD544\uC218 \uD30C\uC77C\xB7XML \uC6F0\uD3FC\uB4DC\xB7secCnt\xB7manifest \uCC38\uC870 (\uD55C\uCEF4\uB3C5\uC2A4 \uAC70\uBD80 \uC694\uC778 \uC0AC\uC804 \uCC28\uB2E8)").option("--json", "\uACB0\uACFC\uB97C JSON\uC73C\uB85C stdout\uC5D0 \uCD9C\uB825").action(async (file, opts) => {
646
697
  try {
647
- const { validateHwpx } = await import("./-I3CP33G4.js");
648
- const buf = new Uint8Array(readFileSync2(resolve2(file)));
698
+ const { validateHwpx } = await import("./-DDAVBMHD.js");
699
+ const buf = new Uint8Array(readFileSync2(resolve3(file)));
649
700
  const result = await validateHwpx(buf);
650
701
  if (opts.json) {
651
702
  process.stdout.write(JSON.stringify(result, null, 2) + "\n");
@@ -670,8 +721,8 @@ function registerDocCommands(program2) {
670
721
  }
671
722
 
672
723
  // src/cli/commands-generate.ts
673
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, statSync as statSync3 } from "fs";
674
- import { basename as basename4, dirname as dirname2, resolve as resolve3 } from "path";
724
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, statSync as statSync4 } from "fs";
725
+ import { basename as basename5, dirname as dirname2, resolve as resolve4 } from "path";
675
726
  function registerGenerateCommands(program2) {
676
727
  program2.command("generate <markdown>").alias("gen").description("\uB9C8\uD06C\uB2E4\uC6B4 \u2192 \uACF5\uBB38\uC11C HWPX \uC0DD\uC131 \u2014 kordoc generate \uBCF4\uACE0\uC11C.md -o \uBCF4\uACE0\uC11C.hwpx --preset \uBCF4\uACE0\uC11C (markdown\uC5D0 '-' \uC9C0\uC815 \uC2DC stdin)").option("-o, --output <path>", "\uCD9C\uB825 HWPX \uACBD\uB85C (\uAE30\uBCF8: <\uC785\uB825>.hwpx)").option("--preset <name>", "\uACF5\uBB38\uC11C \uD504\uB9AC\uC14B: \uAE30\uC548\uBB38(official)\xB7\uBCF4\uACE0\uC11C(report)\xB7\uACC4\uD68D\uC11C(plan)\xB7\uD1B5\uC9C0(notice)\xB7\uD68C\uC758\uB85D(minutes)\xB7\uAC1C\uC870\uC2DD(gaejosik \u2014 \uD45C\uC9C0\xB7\uBAA9\uCC28\xB7\uC7A5\uD5E4\uB354 \uC790\uB3D9)\xB7\uC5C5\uBB34\uBCF4\uACE0(ministry \u2014 \uC911\uC559\uBD80\uCC98 \uC5C5\uBB34\uBCF4\uACE0: \uC7A5 \uB760\xB7\uC808 \uC22B\uC790\uCE78\xB7\uC18C\uC81C\uBAA9 \uBC15\uC2A4\xB7\u2460 \uD56D\uBAA9 \uB760\xB7\uC131\uACFC \uC694\uC57D\uBC15\uC2A4\xB7\uBCC4\uCCA8 \uB760)\xB7\uC11C\uC6B8\uBC29\uCE68(bangchim \u2014 \uC11C\uC6B8\uC2DC \uBC29\uCE68\uC11C: \uC81C\uBAA9\uD45C\xB7\uD30C\uB791 \uBD80\uC81C\xB7\uC694\uC57D\uBC15\uC2A4\xB7[\u2160] \uC7A5 \uC0C1\uC790\xB7\uC808 \uB760\xB7\u2776 \uACFC\uC81C)\xB7\uBCF4\uB3C4\uC790\uB8CC(press)", "\uAE30\uC548\uBB38").option("--font <type>", "\uBCF8\uBB38 \uAE00\uAF34: myeongjo(\uD568\uCD08\uB86C\uBC14\uD0D5) \uB610\uB294 gothic(\uB9D1\uC740 \uACE0\uB515)").option("--pt <size>", "\uBCF8\uBB38 \uAE00\uC790 \uD06C\uAE30(pt)").option("--line-spacing <percent>", "\uBCF8\uBB38 \uC904\uAC04\uACA9(%)").option("--profile <path>", "\uC11C\uC2DD \uD504\uB85C\uD544 JSON (kordoc profile\uB85C \uCD94\uCD9C) \u2014 \uCC38\uC870 \uBB38\uC11C\uC758 \uD45C \uD14C\uB450\uB9AC\xB7\uC74C\uC601\xB7\uC5F4\uD3ED\xB7\uC140 \uAE00\uAF34 \uC7AC\uD604").option("--org <name>", "\uD45C\uC9C0 \uAE30\uAD00\uBA85 (\uD45C\uC9C0\uB97C \uCF1C\uB294 \uD504\uB9AC\uC14B \uACF5\uD1B5)").option("--date <date>", "\uD45C\uC9C0 \uB0A0\uC9DC (\uAE30\uBCF8 \uC624\uB298 \u2014 'YYYY. M. D.')").option("--toc", "\uBAA9\uCC28 \uD398\uC774\uC9C0 \uAC15\uC81C \uCF1C\uAE30 (\uAC1C\uC870\uC2DD \uC678 \uD504\uB9AC\uC14B\uC5D0\uC11C\uB3C4 h2 \uBAA9\uB85D\uC73C\uB85C \uC0DD\uC131)").option("--no-toc", "\uBAA9\uCC28 \uD398\uC774\uC9C0 \uB044\uAE30 (\uAC1C\uC870\uC2DD \uD504\uB9AC\uC14B \uAE30\uBCF8 \uCF1C\uC9D0)").option("--cover", "\uD45C\uC9C0 \uD398\uC774\uC9C0 \uAC15\uC81C \uCF1C\uAE30 (\uAC1C\uC870\uC2DD \uC678 \uD504\uB9AC\uC14B\uC5D0\uC11C\uB3C4 \uCCAB h1\uC744 \uD45C\uC9C0\uB85C)").option("--no-cover", "\uD45C\uC9C0 \uD398\uC774\uC9C0 \uB044\uAE30 (\uAC1C\uC870\uC2DD \uD504\uB9AC\uC14B \uAE30\uBCF8 \uCF1C\uC9D0)").option("--approval <labels>", "\uACB0\uC7AC\uB780 \uC9C1\uC704 \uB77C\uBCA8 (\uC27C\uD45C \uAD6C\uBD84, \uC608: \uB2F4\uB2F9,\uD300\uC7A5,\uACFC\uC7A5) \u2014 \uBB38\uC11C \uCD5C\uC0C1\uB2E8 \uC6B0\uCE21").option("--page-numbers", "\uCABD\uBC88\uD638 \uAC15\uC81C \uCF1C\uAE30 (\uD558\uB2E8 \uC911\uC559 '- 1 -')").option("--no-page-numbers", "\uCABD\uBC88\uD638 \uB044\uAE30 (\uAC1C\uC870\uC2DD\xB7\uBCF4\uACE0\uC11C\xB7\uACC4\uD68D\uC11C \uAE30\uBCF8 \uCF1C\uC9D0)").option("--end-mark", "\uBCF8\uBB38 \uB05D '\uB05D.' \uD45C\uC2DC \uAC15\uC81C \uCF1C\uAE30").option("--no-end-mark", "'\uB05D.' \uD45C\uC2DC \uB044\uAE30 (\uAE30\uC548\uBB38 \uAE30\uBCF8 \uCF1C\uC9D0)").option("--no-body-title-box", "\uBCF8\uBB38 \uCCAB \uD398\uC774\uC9C0 \uC81C\uBAA9 \uBC18\uBCF5 \uBC15\uC2A4 \uB044\uAE30 (\uAC1C\uC870\uC2DD+\uD45C\uC9C0 \uAE30\uBCF8 \uCF1C\uC9D0)").option("--chapter-fit", "\uAC1C\uC870\uC2DD \uC7A5 \uD5E4\uB354 \uC81C\uBAA9 \uCE78\uC744 \uAE00\uC790 \uD3ED\uC5D0 \uB9DE\uCDA4 (\uAE30\uBCF8: \uBCF8\uBB38 \uD3ED\uAE4C\uC9C0)").option("--h2-marker <type>", "h2 \uC7A5 \uC81C\uBAA9 \uD45C\uAE30: band(\uB85C\uB9C8\uC790 \uCC44\uC6C0 \uCE78 + \uC81C\uBAA9 \uB760 \uD45C \u2014 \uBCF4\uACE0\uC11C\xB7\uACC4\uD68D\uC11C \uAE30\uBCF8)\xB7roman(\u2160. \uD14D\uC2A4\uD2B8)\xB7number(1. \u2014 \uD1B5\uC9C0 \uAE30\uBCF8)\xB7box(\uC7A5 \uC5C6\uC774 \u25A1 \uB300\uD56D\uBAA9)\xB7none").option("--band-color <hex>", "\uB760 \uC81C\uBAA9 \uBC88\uD638\uCE78 \uCC44\uC6C0\uC0C9 #RRGGBB (\uAE30\uBCF8 #003366 \u2014 \uC2E4\uCE21 \uCD5C\uB2E4. \uAD50\uC721\uCCAD\uD615 \uBC1D\uC740 \uB760: #DFE6F7)").option("--band-text-color <hex>", "\uB760 \uC81C\uBAA9 \uBC88\uD638 \uAE00\uC790\uC0C9 #RRGGBB (\uAE30\uBCF8 #FFFFFF \u2014 \uBC1D\uC740 \uB760\uBA74 #000000)").option("--summary <text>", "\uBCF4\uACE0\uC11C \uC694\uC57D \uBC15\uC2A4 (\uC81C\uBAA9\uD45C \uC544\uB798 \uC74C\uC601 \uC0C1\uC790 \u2014 \uB9C8\uD06C\uB2E4\uC6B4 \uC81C\uBAA9 \uC9C1\uD6C4 \uC778\uC6A9\uBB38(>)\uC73C\uB85C\uB3C4 \uC9C0\uC815)").option("--doc-info <spec>", "\uBCF4\uACE0\uC11C \uD45C\uC9C0 \uBB38\uC11C\uC815\uBCF4\uD45C: docNum=\uC2A4\uB9C8\uD2B8\uB3C4\uC2DC\uACFC-123,date=2026. 9. 6.,disclosure=\uACF5\uAC1C,policyNo= (--cover\uC640 \uD568\uAED8)").option("--dept <name>", "\uD45C\uC9C0 \uBD80\uC11C\uBA85 (\uAE30\uAD00\uBA85 \uC544\uB798 \uAD04\uD638)").option("--checklist [na]", "\uC11C\uC6B8 \uC0AC\uC804 \uAC80\uD1A0\uD56D\uBAA9 \uC810\uAC80\uD45C(\uBCF4\uACE0\uC11C\xB7\uACC4\uD68D\uC11C\xB7\uC11C\uC6B8\uBC29\uCE68) \u2014 \uAC12 \uC5C6\uC73C\uBA74 \uBE48 \uC11C\uC2DD, \uD574\uB2F9\uC5C6\uC74C \uBB38\uD56D \uBC88\uD638\uB97C \uC8FC\uBA74(6,7,8) \uB098\uBA38\uC9C0\uB294 \uAC80\uD1A0\uC644\uB8CC").option("--cover-label <text>", "\uD45C\uC9C0 \uC6B0\uC0C1\uB2E8 \uCDE8\uAE09 \uD45C\uC2DC \u2014 '\uB300\uC678\uC8FC\uC758'\xB7'\uBE44\uACF5\uAC1C' \uBE68\uAC04 \uD14C\uB450\uB9AC \uBC15\uC2A4 (\uC5C5\uBB34\uBCF4\uACE0 \uD504\uB9AC\uC14B \uC2E4\uCE21)").option("--fonts <spec>", "\uC694\uC18C\uBCC4 \uAE00\uAF34 \uC624\uBC84\uB77C\uC774\uB4DC: body=\uB098\uB214\uBA85\uC870,heading=\uB098\uB214\uACE0\uB515,ref=\uD55C\uC591\uC911\uACE0\uB515,table=\uB9D1\uC740 \uACE0\uB515").option("--sizes <spec>", "\uAC1C\uC870\uC2DD \uC694\uC18C\uBCC4 \uD06C\uAE30(pt): dae=16,cham=13,table=12,coverTitle=30 \u2026").option("--levels <spec>", "\uD56D\uBAA9\uBD80\uD638 \uB2E8\uACC4\uBCC4 \uC704\uACC4 \uD0C0\uC774\uD3EC: 0=HY\uACAC\uACE0\uB515/17/bold,1=\uD55C\uCEF4\uB3CB\uC6C0/15/bold,2=\uD734\uBA3C\uBA85\uC870/14 (depth 0~7, \uC22B\uC790=pt\xB7bold\xB7plain\xB7\uAE00\uAF34\uBA85)").option("--bullet2 <char>", "2\uB2E8\uACC4 \uD56D\uBAA9\uBD80\uD638: \u3147(\uC774\uC751 \u2014 \uAE30\uC548\uBB38\xB7\uACF5\uACE0\uBB38 \uC2E4\uCE21 \uC9C0\uBC30) \uB610\uB294 \u25CB(\uC6D0 \u2014 \uBCF4\uACE0\uC11C \uC591\uC2DD)").option("--suppress-single", "\uB2E8\uC77C \uD615\uC81C \uD56D\uBAA9 \uBD80\uD638 \uC0DD\uB7B5 (\uD3B8\uB78C \uADDC\uC815 \u2014 \uAE30\uBCF8\uC740 \uD558\uB098\uC5EC\uB3C4 \uBD80\uD638 \uBD80\uC5EC)").option("--doc-head <spec>", "\uAE30\uC548\uBB38 \uB450\uBB38\uD45C: org=\uAE30\uAD00\uBA85,slogan=\uC6D0\uD6C8,to=\uC218\uC2E0\uCC98,title=\uC81C\uBAA9 (\uBCC4\uC9C0 \uC81C1\uD638\uC11C\uC2DD\xB7\uC11C\uC6B8 \uC2E4\uACB0\uC7AC 6\uD589 \uD45C)").option("--doc-foot <spec>", "\uAE30\uC548\uBB38 \uACB0\uBB38\uD45C: sender=\uBC1C\uC2E0\uBA85\uC758,drafter=\uC8FC\uBB34\uAD00 \uD64D\uAE38\uB3D9,reviewer=\uACFC\uC7A5 \uAE40\uCCA0\uC218,approver=\uAD6D\uC7A5 \uBC15\uC601\uD76C,cooperator=\uD611\uC870\uC790,docNum=\uC2DC\uD589(\uACFC-\uBC88\uD638 (\uB0A0\uC9DC)),receive=\uC811\uC218,zip=\uC6B0\uD3B8\uBC88\uD638,address=\uC8FC\uC18C,site=\uD648\uD398\uC774\uC9C0,phone=\uC804\uD654,fax=\uC804\uC1A1,email=\uBA54\uC77C,disclosure=\uACF5\uAC1C\uAD6C\uBD84").option("--report-info <text>", "\uBCF4\uACE0\uC11C \uB2F4\uB2F9\uC790 \uD589(\uC81C\uBAA9\uD45C \uC544\uB798) / \uAE30\uC548\uBB38 \uC6B0\uC0C1\uB2E8 \uBCF4\uACE0\uC815\uBCF4 \uD589 \u2014 \uC608: '(2026. 7. 11., \uACFC\uC7A5 \uD64D\uAE38\uB3D9, \u260E02-120)'").option("--notice-head <spec>", "\uACF5\uACE0\uBB38 \uB450\uBB38\xB7\uACB0\uBB38: no=\uACF5\uACE0 \uC81C2026-1\uD638,date=2026\uB144 7\uC6D4 11\uC77C,sender=\uD589\uC815\uC548\uC804\uBD80\uC7A5\uAD00").option("--press-head <spec>", "\uBCF4\uB3C4\uC790\uB8CC \uBA38\uB9AC: release=\uBCF4\uB3C4\uC2DC\uC810,distribute=\uBC30\uD3EC\uC77C,dept=\uB2F4\uB2F9\uBD80\uC11C,manager=\uB2F4\uB2F9\uC790,phone=\uC5F0\uB77D\uCC98").option("--press-sub <items>", "\uBCF4\uB3C4\uC790\uB8CC \uBD80\uC81C (\uC138\uBBF8\uCF5C\uB860 \uAD6C\uBD84, \uC81C\uBAA9 \uC544\uB798 '- \u2026 -')").option("--plain", "\uACF5\uBB38\uC11C \uBAA8\uB4DC \uB044\uAE30 (\uBC94\uC6A9 \uB9C8\uD06C\uB2E4\uC6B4 \uBCC0\uD658)").option("--paper <size>", "\uC6A9\uC9C0: A4\xB7A3\xB7B4\xB7B5\xB7Letter \uB610\uB294 '210x297'(mm)").option("--landscape", "\uC6A9\uC9C0 \uAC00\uB85C \uBC29\uD5A5").option("--columns <n>", "\uB2E4\uB2E8 \uAC1C\uC218 (1~8)").option("--header <text>", "\uBA38\uB9AC\uB9D0 \uD14D\uC2A4\uD2B8 (\uBAA8\uB4E0 \uCABD, \uC778\uB77C\uC778 \uB9C8\uD06C\uB2E4\uC6B4 \uD5C8\uC6A9)").option("--footer <text>", "\uAF2C\uB9AC\uB9D0 \uD14D\uC2A4\uD2B8").option("--image-dir <dir>", "\uB9C8\uD06C\uB2E4\uC6B4 \uC774\uBBF8\uC9C0 \uCC38\uC870(![](x.png))\uB97C \uC774 \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC77D\uC5B4 \uC2E4\uB370\uC774\uD130 \uC784\uBCA0\uB4DC").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (markdown, opts) => {
677
728
  try {
@@ -683,9 +734,9 @@ function registerGenerateCommands(program2) {
683
734
  if (markdown === "-") {
684
735
  md = readFileSync3(0, "utf-8");
685
736
  } else {
686
- const inPath = resolve3(markdown);
737
+ const inPath = resolve4(markdown);
687
738
  md = readFileSync3(inPath, "utf-8");
688
- baseName = basename4(inPath).replace(/\.(md|markdown|txt)$/i, "");
739
+ baseName = basename5(inPath).replace(/\.(md|markdown|txt)$/i, "");
689
740
  }
690
741
  let gongmun;
691
742
  if (!opts.plain) {
@@ -786,7 +837,7 @@ function registerGenerateCommands(program2) {
786
837
  }
787
838
  let profile;
788
839
  if (opts.profile) {
789
- profile = parseFormatProfileJson(readFileSync3(resolve3(String(opts.profile)), "utf-8"));
840
+ profile = parseFormatProfileJson(readFileSync3(resolve4(String(opts.profile)), "utf-8"));
790
841
  if (!silent) process.stderr.write(`[kordoc] \uC11C\uC2DD \uD504\uB85C\uD544 \uC801\uC6A9: \uD45C ${profile.tables.length}\uAC1C (${opts.profile})
791
842
  `);
792
843
  }
@@ -807,7 +858,7 @@ function registerGenerateCommands(program2) {
807
858
  }
808
859
  let imageBytes;
809
860
  if (opts.imageDir) {
810
- const dir = resolve3(String(opts.imageDir));
861
+ const dir = resolve4(String(opts.imageDir));
811
862
  const loaded = await loadGenerationImages(md, dir);
812
863
  imageBytes = loaded.images;
813
864
  if (!silent) {
@@ -827,7 +878,7 @@ function registerGenerateCommands(program2) {
827
878
  } : void 0);
828
879
  if (!silent) for (const w of genWarnings) process.stderr.write(`[kordoc] \u26A0 ${w}
829
880
  `);
830
- const outPath = resolve3(output ?? (markdown === "-" ? `${baseName}.hwpx` : markdown.replace(/\.(md|markdown|txt)$/i, "") + ".hwpx"));
881
+ const outPath = resolve4(output ?? (markdown === "-" ? `${baseName}.hwpx` : markdown.replace(/\.(md|markdown|txt)$/i, "") + ".hwpx"));
831
882
  mkdirSync3(dirname2(outPath), { recursive: true });
832
883
  writeFileSync3(outPath, Buffer.from(buf));
833
884
  if (!silent) {
@@ -846,9 +897,9 @@ function registerGenerateCommands(program2) {
846
897
  const rootOpts = program2.opts();
847
898
  const output = opts.output ?? rootOpts.output;
848
899
  const silent = opts.silent ?? rootOpts.silent;
849
- const absPath = resolve3(file);
900
+ const absPath = resolve4(file);
850
901
  const profile = await hwpxToProfile(readFileSync3(absPath));
851
- const outPath = resolve3(output ?? absPath.replace(/\.hwpx$/i, "") + ".profile.json");
902
+ const outPath = resolve4(output ?? absPath.replace(/\.hwpx$/i, "") + ".profile.json");
852
903
  mkdirSync3(dirname2(outPath), { recursive: true });
853
904
  writeFileSync3(outPath, JSON.stringify(profile, null, 2));
854
905
  if (!silent) process.stderr.write(`[kordoc] \uC11C\uC2DD \uD504\uB85C\uD544 \uCD94\uCD9C: \uD45C ${profile.tables.length}\uAC1C \u2192 ${outPath}
@@ -861,7 +912,7 @@ function registerGenerateCommands(program2) {
861
912
  });
862
913
  program2.command("lint <file>").description("\uACF5\uBB38\uC11C \uD45C\uAE30\uBC95 \uAC80\uC218 \u2014 \uB0A0\uC9DC\xB7\uC2DC\uAC04\xB7\uAE08\uC561\xB7\uBD99\uC784 \uB4F1 \uD589\uC815\uC5C5\uBB34\uC6B4\uC601 \uD3B8\uB78C \uD45C\uAE30\uBC95 (md/txt, '-'=stdin). error \uC788\uC73C\uBA74 exit 1").option("--json", "JSON \uCD9C\uB825").option("--munche", "\uAC1C\uC870\uC2DD \uBB38\uCCB4 \uAC80\uC218 \uBCD1\uD589 \u2014 \uC11C\uC220\uD615 \uC885\uACB0\xB7\uB2F9\uC704\xB7\uC218\uC0AC\xB7\uD56D\uBAA9 \uAE38\uC774 (\uBCF4\uACE0\uC11C\xB7\uACC4\uD68D\uC11C \uC6D0\uACE0\uC6A9)").action((file, opts) => {
863
914
  try {
864
- const raw = file === "-" ? readFileSync3(0) : readFileSync3(resolve3(file));
915
+ const raw = file === "-" ? readFileSync3(0) : readFileSync3(resolve4(file));
865
916
  const kind = detectFormat(
866
917
  raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength)
867
918
  );
@@ -910,7 +961,7 @@ function registerGenerateCommands(program2) {
910
961
  });
911
962
  program2.command("redact <files...>").description("\uAC1C\uC778\uC815\uBCF4 \uC11C\uC2DD \uBCF4\uC874 \uB9C8\uC2A4\uD0B9 \u2014 \uC8FC\uBBFC\xB7\uC678\uAD6D\uC778\uB4F1\uB85D\uBC88\uD638\xB7\uC804\uD654\xB7\uC774\uBA54\uC77C\xB7\uCE74\uB4DC\xB7\uACC4\uC88C\xB7\uC0AC\uC5C5\uC790\uB4F1\uB85D\uBC88\uD638\xB7\uC5EC\uAD8C\xB7\uC6B4\uC804\uBA74\uD5C8(--rules \uB85C \uC778\uBA85\xB7\uC8FC\uC18C opt-in)\uB97C \uD0D0\uC9C0\uD574 HWPX/HWP\uB294 \uC6D0\uBCF8 \uC11C\uC2DD \uADF8\uB300\uB85C \uAC19\uC740 \uAE38\uC774\uB85C \uAC00\uB9B0 \uD30C\uC77C(\uBCF8\uBB38\xB7\uD45C\xB7\uBA38\uB9AC\uB9D0/\uAF2C\uB9AC\uB9D0\xB7\uAC01\uC8FC\xB7\uAE00\uC0C1\uC790\xB7\uBBF8\uB9AC\uBCF4\uAE30\xB7\uBA54\uD0C0\uB370\uC774\uD130 \uD3EC\uD568), \uADF8 \uC678 \uD3EC\uB9F7(PDF \uB4F1)\uC740 \uC6D0\uBCF8\uC744 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uACE0 \uB9C8\uC2A4\uD0B9\uB41C \uB9C8\uD06C\uB2E4\uC6B4\uB9CC \uCD9C\uB825. \uC790\uB3D9 \uAC80\uCD9C \uBCF4\uC870 \uB3C4\uAD6C\uC774\uBBC0\uB85C \uACB0\uACFC\uB294 \uBC18\uB4DC\uC2DC \uC0AC\uB78C\uC774 \uCD5C\uC885 \uD655\uC778\uD558\uC138\uC694 (\uC774\uBBF8\uC9C0 \uC18D \uAE00\uC790\uB294 \uD0D0\uC9C0 \uBD88\uAC00)").option("--rules <csv>", "\uC801\uC6A9 \uB8F0 (\uAE30\uBCF8: rrn,phone,email,card,account,brn,passport,driver \u2014 crn(\uBC95\uC778\uB4F1\uB85D\uBC88\uD638),ip,name(\uC778\uBA85),address(\uC8FC\uC18C)\uB294 opt-in)").option("--mask-char <ch>", "\uB9C8\uC2A4\uD06C \uBB38\uC790 1\uAE00\uC790 (\uAE30\uBCF8: \u25CF)").option("-o, --output <path>", "\uCD9C\uB825 \uACBD\uB85C (\uB2E8\uC77C \uD30C\uC77C \uC2DC)").option("-d, --out-dir <dir>", "\uCD9C\uB825 \uB514\uB809\uD1A0\uB9AC (\uB2E4\uC911 \uD30C\uC77C \uC2DC)").option("--dry-run", "\uD0D0\uC9C0 \uB9AC\uD3EC\uD2B8\uB9CC \uCD9C\uB825, \uD30C\uC77C \uBBF8\uC0DD\uC131").option("--json", "\uB9AC\uD3EC\uD2B8\uB97C JSON\uC73C\uB85C stdout \uCD9C\uB825").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (files, opts) => {
912
963
  const { ALL_REDACT_RULES, DEFAULT_REDACT_RULES, redactText } = await import("./redact-NV2QCDGE.js");
913
- const { redactDocument } = await import("./redact-doc-TRPZ3HNW.js");
964
+ const { redactDocument } = await import("./redact-doc-ECFOVR4X.js");
914
965
  const rootOpts = program2.opts();
915
966
  const output = opts.output ?? rootOpts.output;
916
967
  const outDir = opts.outDir ?? rootOpts.outDir;
@@ -944,12 +995,12 @@ function registerGenerateCommands(program2) {
944
995
  }
945
996
  return out.join("");
946
997
  };
947
- const shown = (p) => resolve3(dirname2(p), maskName(basename4(p)));
948
- const inputs = files.map((f) => resolve3(f));
998
+ const shown = (p) => resolve4(dirname2(p), maskName(basename5(p)));
999
+ const inputs = files.map((f) => resolve4(f));
949
1000
  const sameFile = (a, b) => {
950
1001
  if (a === b) return true;
951
1002
  try {
952
- const sa = statSync3(a), sb = statSync3(b);
1003
+ const sa = statSync4(a), sb = statSync4(b);
953
1004
  return sa.ino === sb.ino && sa.dev === sb.dev;
954
1005
  } catch {
955
1006
  return false;
@@ -957,18 +1008,18 @@ function registerGenerateCommands(program2) {
957
1008
  };
958
1009
  const written = /* @__PURE__ */ new Set();
959
1010
  const defaultOut = (absPath, ext) => {
960
- const stem = maskName(basename4(absPath)).replace(/\.[^.]+$/, "");
961
- const dir = resolve3(outDir ?? dirname2(absPath));
1011
+ const stem = maskName(basename5(absPath)).replace(/\.[^.]+$/, "");
1012
+ const dir = resolve4(outDir ?? dirname2(absPath));
962
1013
  for (let n = 1; ; n++) {
963
- const p = resolve3(dir, `${stem}${n > 1 ? `-${n}` : ""}.redacted${ext}`);
1014
+ const p = resolve4(dir, `${stem}${n > 1 ? `-${n}` : ""}.redacted${ext}`);
964
1015
  if (!written.has(p) && !inputs.some((i) => sameFile(i, p))) return p;
965
1016
  }
966
1017
  };
967
1018
  const MAX_LINES = 200;
968
1019
  const jsonReports = [];
969
1020
  for (const absPath of inputs) {
970
- const fileName = maskName(basename4(absPath));
971
- if (output && files.length === 1 && !opts.dryRun && sameFile(absPath, resolve3(output))) {
1021
+ const fileName = maskName(basename5(absPath));
1022
+ if (output && files.length === 1 && !opts.dryRun && sameFile(absPath, resolve4(output))) {
972
1023
  process.stderr.write(`[kordoc] ERROR: ${fileName} \u2014 \uCD9C\uB825 \uACBD\uB85C\uAC00 \uC785\uB825 \uD30C\uC77C\uACFC \uAC19\uC2B5\uB2C8\uB2E4. \uC6D0\uBCF8\uC744 \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 \uB2E4\uB978 -o \uACBD\uB85C\uB97C \uC9C0\uC815\uD558\uC138\uC694
973
1024
  `);
974
1025
  process.exitCode = 1;
@@ -992,7 +1043,7 @@ function registerGenerateCommands(program2) {
992
1043
  const save = r.data ? r.changed : r.markdownHits.length > 0;
993
1044
  if (!opts.dryRun && save) {
994
1045
  const ext = r.data ? r.format === "hwp" ? ".hwp" : ".hwpx" : ".md";
995
- outPath = output && files.length === 1 ? resolve3(output) : defaultOut(absPath, ext);
1046
+ outPath = output && files.length === 1 ? resolve4(output) : defaultOut(absPath, ext);
996
1047
  mkdirSync3(dirname2(outPath), { recursive: true });
997
1048
  if (r.data) writeFileSync3(outPath, r.data);
998
1049
  else {
@@ -1057,7 +1108,7 @@ function registerGenerateCommands(program2) {
1057
1108
 
1058
1109
  // src/cli/commands-render.ts
1059
1110
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
1060
- import { dirname as dirname3, resolve as resolve4 } from "path";
1111
+ import { dirname as dirname3, resolve as resolve5 } from "path";
1061
1112
  function registerRenderCommands(program2) {
1062
1113
  program2.command("render <file>").description("\uB808\uC774\uC544\uC6C3 \uBCF4\uC874 \uB80C\uB354 \u2014 HWPX\xB7HWP(5.x)\uB97C SVG(\uAE30\uBCF8, HWPX \uB294 \uC804\uCCB4 \uD398\uC774\uC9C0 \uC138\uB85C \uC2A4\uD0DD)\xB7HTML\xB7PNG\xB7JPEG\xB7PDF\uB85C. \uD55C\uCEF4 \uC800\uC7A5\uBCF8\uC740 \uC870\uD310 \uCE90\uC2DC \uADF8\uB300\uB85C, \uCE90\uC2DC \uC5C6\uB294 \uC0DD\uC131\uBCF8\xB7\uD3B8\uC9D1\uBCF8\uC740 \uC21C\uC218 TS \uC870\uD310(reflow, \uAE30\uBCF8 \uCF2C) \u2014 kordoc render \uBB38\uC11C.hwpx -o \uBB38\uC11C.svg / --format png --pages 2-4 -d ./pages / --format pdf -o \uBB38\uC11C.pdf").option("-o, --output <path>", "\uCD9C\uB825 \uACBD\uB85C (\uB2E8\uC77C \uC0B0\uCD9C: svg \uC2A4\uD0DD\xB7html\xB7pdf\xB7\uD55C \uCABD png/jpeg. \uAE30\uBCF8: <\uC785\uB825>.<\uD655\uC7A5\uC790>)").option("-d, --out-dir <dir>", "\uD398\uC774\uC9C0\uBCC4 \uC0B0\uCD9C \uB514\uB809\uD1A0\uB9AC (svg/png/jpeg \uC5EC\uB7EC \uCABD \u2192 page_001.png \u2026)").option("--format <fmt>", "svg(\uAE30\uBCF8) | html | png | jpeg | pdf").option("--pages <range>", "\uB80C\uB354\uD560 \uD398\uC774\uC9C0 (1-based: 3 / 1-3 / 1,3,7-9)").option("--max-width <px>", "\uB798\uC2A4\uD130 \uCD5C\uB300 \uD3ED px (\uAE30\uBCF8 1400)").option("--title <text>", "HTML/PDF \uBB38\uC11C \uC81C\uBAA9").option("--browser <path>", "PDF \uC6A9 Chromium \uC2E4\uD589 \uD30C\uC77C (\uAE30\uBCF8: PUPPETEER_EXECUTABLE_PATH \uB610\uB294 \uC790\uB3D9 \uD0D0\uC9C0)").option("--highlight <terms>", "\uAC80\uC0C9\uC5B4 \uD615\uAD11\uD39C (\uC27C\uD45C \uAD6C\uBD84)").option("--no-reflow", "\uC21C\uC218 TS \uC870\uD310 \uB044\uAE30 (\uC870\uD310 \uCE90\uC2DC \uC5C6\uB294 \uBB38\uC11C\uAC00 \uBE48 \uD398\uC774\uC9C0\uB85C \uB098\uC62C \uC218 \uC788\uC74C)").option("--reflow", "\uC21C\uC218 TS \uC870\uD310 \uCF1C\uAE30 \u2014 \uAE30\uBCF8\uAC12\uACFC \uAC19\uB2E4 (\uC61B \uC548\uB0B4 \uD638\uD658, #97)").option("--reflow-mode <mode>", "reflow \uC904\uBC14\uAFC8 \uBAA8\uB4DC: keep(\uC5B4\uC808) | charAll(\uAE00\uC790)", "keep").option("--silent", "\uC9C4\uD589 \uBA54\uC2DC\uC9C0 \uC228\uAE30\uAE30").action(async (file, opts) => {
1063
1114
  try {
@@ -1069,13 +1120,13 @@ function registerRenderCommands(program2) {
1069
1120
  const pages = opts.pages ?? rootOpts.pages;
1070
1121
  if (!["svg", "html", "png", "jpeg", "pdf"].includes(fmt)) throw new KordocError(`--format \uC740 svg|html|png|jpeg|pdf \uC911 \uD558\uB098: ${fmt}`);
1071
1122
  const highlights = opts.highlight ? String(opts.highlight).split(",") : void 0;
1072
- const absPath = resolve4(file);
1123
+ const absPath = resolve5(file);
1073
1124
  const stem = file.replace(/\.hwpx?$/i, "");
1074
1125
  if (fmt === "svg" && !outDir && !pages && !/\.hwp$/i.test(absPath)) {
1075
- const { renderHwpxToSvg } = await import("./render-GHT5HKBO.js");
1126
+ const { renderHwpxToSvg } = await import("./render-NSKWZVTD.js");
1076
1127
  const buffer = readFileSync4(absPath);
1077
1128
  const result = await renderHwpxToSvg(toArrayBuffer(buffer), { highlights, reflow: opts.reflow, reflowMode: opts.reflowMode });
1078
- const outPath = resolve4(output ?? stem + ".svg");
1129
+ const outPath = resolve5(output ?? stem + ".svg");
1079
1130
  mkdirSync4(dirname3(outPath), { recursive: true });
1080
1131
  writeFileSync4(outPath, result.svg, "utf-8");
1081
1132
  if (!silent) {
@@ -1086,7 +1137,7 @@ function registerRenderCommands(program2) {
1086
1137
  }
1087
1138
  return;
1088
1139
  }
1089
- const { renderDocument } = await import("./render-GHT5HKBO.js");
1140
+ const { renderDocument } = await import("./render-NSKWZVTD.js");
1090
1141
  const { scene, assets } = await renderDocument(absPath, {
1091
1142
  format: fmt,
1092
1143
  pages,
@@ -1100,21 +1151,21 @@ function registerRenderCommands(program2) {
1100
1151
  const ext = fmt === "jpeg" ? "jpg" : fmt;
1101
1152
  const written = [];
1102
1153
  if (fmt === "html" || fmt === "pdf" || assets.length === 1 && !outDir) {
1103
- const outPath = resolve4(output ?? stem + "." + ext);
1154
+ const outPath = resolve5(output ?? stem + "." + ext);
1104
1155
  mkdirSync4(dirname3(outPath), { recursive: true });
1105
1156
  writeFileSync4(outPath, assets[0].data);
1106
1157
  written.push(outPath);
1107
1158
  } else {
1108
1159
  if (!outDir) throw new KordocError(`\uD398\uC774\uC9C0 ${assets.length}\uC7A5 \uC0B0\uCD9C\uC740 --out-dir \uC774 \uD544\uC694\uD569\uB2C8\uB2E4 (\uD55C \uCABD\uB9CC \uB0B4\uB824\uBA74 --pages \uB85C \uC120\uD0DD)`);
1109
- mkdirSync4(resolve4(outDir), { recursive: true });
1160
+ mkdirSync4(resolve5(outDir), { recursive: true });
1110
1161
  for (const a of assets) {
1111
- const outPath = resolve4(outDir, `page_${String(a.page).padStart(3, "0")}.${ext}`);
1162
+ const outPath = resolve5(outDir, `page_${String(a.page).padStart(3, "0")}.${ext}`);
1112
1163
  writeFileSync4(outPath, a.data);
1113
1164
  written.push(outPath);
1114
1165
  }
1115
1166
  }
1116
1167
  if (!silent) {
1117
- process.stderr.write(`[kordoc] \uB80C\uB354 ${fmt} (${scene.pages.length}\uD398\uC774\uC9C0 \uC911 ${assets.length}\uAC74, \uD14D\uC2A4\uD2B8 ${scene.stats.texts}\xB7\uC774\uBBF8\uC9C0 ${scene.stats.images}\xB7\uD45C ${scene.stats.tables}\xB7\uB3C4\uD615 ${scene.stats.shapes}) \u2192 ${written.length === 1 ? written[0] : resolve4(outDir)}
1168
+ process.stderr.write(`[kordoc] \uB80C\uB354 ${fmt} (${scene.pages.length}\uD398\uC774\uC9C0 \uC911 ${assets.length}\uAC74, \uD14D\uC2A4\uD2B8 ${scene.stats.texts}\xB7\uC774\uBBF8\uC9C0 ${scene.stats.images}\xB7\uD45C ${scene.stats.tables}\xB7\uB3C4\uD615 ${scene.stats.shapes}) \u2192 ${written.length === 1 ? written[0] : resolve5(outDir)}
1118
1169
  `);
1119
1170
  for (const w of scene.warnings) process.stderr.write(`[kordoc] \u26A0\uFE0F ${w}
1120
1171
  `);
@@ -1136,8 +1187,8 @@ function registerRenderCommands(program2) {
1136
1187
  if (!outDir) throw new KordocError("--out-dir \uC774 \uD544\uC694\uD569\uB2C8\uB2E4 (crop \uC740 \uD30C\uC77C \uC5EC\uB7EC \uAC1C\uB97C \uB0C5\uB2C8\uB2E4)");
1137
1188
  const types = String(opts.target).split(",").map((t) => t.trim()).filter(Boolean);
1138
1189
  for (const t of types) if (!["table", "image", "paragraph", "shape"].includes(t)) throw new KordocError(`--target \uC720\uD615 \uC624\uB958: ${t}`);
1139
- const { extractRenderedRegions } = await import("./render-GHT5HKBO.js");
1140
- const regions = await extractRenderedRegions(resolve4(file), {
1190
+ const { extractRenderedRegions } = await import("./render-NSKWZVTD.js");
1191
+ const regions = await extractRenderedRegions(resolve5(file), {
1141
1192
  types,
1142
1193
  format: fmt,
1143
1194
  pages,
@@ -1146,15 +1197,15 @@ function registerRenderCommands(program2) {
1146
1197
  reflow: opts.reflow,
1147
1198
  reflowMode: opts.reflowMode
1148
1199
  });
1149
- const dir = resolve4(outDir);
1200
+ const dir = resolve5(outDir);
1150
1201
  mkdirSync4(dir, { recursive: true });
1151
1202
  const ext = fmt === "jpeg" ? "jpg" : "png";
1152
1203
  const manifest = regions.map((r) => {
1153
1204
  const name = `${r.region.id.replace("-", "_")}_page_${String(r.page).padStart(3, "0")}.${ext}`;
1154
- writeFileSync4(resolve4(dir, name), r.data);
1205
+ writeFileSync4(resolve5(dir, name), r.data);
1155
1206
  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 };
1156
1207
  });
1157
- writeFileSync4(resolve4(dir, "regions.json"), JSON.stringify(manifest, null, 2));
1208
+ writeFileSync4(resolve5(dir, "regions.json"), JSON.stringify(manifest, null, 2));
1158
1209
  if (!silent) process.stderr.write(`[kordoc] crop ${regions.length}\uAC74 (${types.join(",")}) \u2192 ${dir}
1159
1210
  `);
1160
1211
  } catch (err) {
@@ -1174,15 +1225,15 @@ function registerRenderCommands(program2) {
1174
1225
  if (policy !== "none" && !outDir) throw new KordocError("--visual \uC740 crop \uD30C\uC77C\uC744 \uB0B4\uBBC0\uB85C --out-dir \uC774 \uD544\uC694\uD569\uB2C8\uB2E4");
1175
1226
  const cropFmt = String(opts.cropFormat);
1176
1227
  if (!["png", "jpeg"].includes(cropFmt)) throw new KordocError(`--crop-format \uC740 png|jpeg: ${cropFmt}`);
1177
- const { extractTables } = await import("./visual-R3E35Q2K.js");
1178
- const tables = await extractTables(resolve4(file), { policy, format: cropFmt, paddingPt: Number(opts.padding) || 0 });
1179
- const dir = outDir ? resolve4(outDir) : void 0;
1228
+ const { extractTables } = await import("./visual-B56WQAGW.js");
1229
+ const tables = await extractTables(resolve5(file), { policy, format: cropFmt, paddingPt: Number(opts.padding) || 0 });
1230
+ const dir = outDir ? resolve5(outDir) : void 0;
1180
1231
  if (dir) mkdirSync4(dir, { recursive: true });
1181
1232
  const ext = cropFmt === "jpeg" ? "jpg" : "png";
1182
1233
  const report = tables.map((t) => {
1183
1234
  const crops = t.crops.map((c) => {
1184
1235
  const name = `${t.id.replace(/[^\w.-]/g, "_")}_page_${String(c.page).padStart(3, "0")}.${ext}`;
1185
- if (dir) writeFileSync4(resolve4(dir, name), c.data);
1236
+ if (dir) writeFileSync4(resolve5(dir, name), c.data);
1186
1237
  return { file: dir ? name : void 0, page: c.page, bbox: c.bbox };
1187
1238
  });
1188
1239
  return {
@@ -1197,7 +1248,7 @@ function registerRenderCommands(program2) {
1197
1248
  };
1198
1249
  });
1199
1250
  const json = JSON.stringify(report, null, 2);
1200
- const jsonPath = output ? resolve4(output) : dir ? resolve4(dir, "tables.json") : void 0;
1251
+ const jsonPath = output ? resolve5(output) : dir ? resolve5(dir, "tables.json") : void 0;
1201
1252
  if (jsonPath) {
1202
1253
  mkdirSync4(dirname3(jsonPath), { recursive: true });
1203
1254
  writeFileSync4(jsonPath, json + "\n");
@@ -1218,7 +1269,7 @@ function registerRenderCommands(program2) {
1218
1269
  });
1219
1270
  program2.command("render-worker").description("persistent \uB80C\uB354 \uC6CC\uCEE4 \u2014 stdin NDJSON \uC694\uCCAD \u2192 \uC870\uD310 SVG \uD30C\uC77C \uCD9C\uB825 (\uD504\uB85C\uC138\uC2A4 \uC720\uC9C0, \uCF5C\uB4DC\uC2A4\uD0C0\uD2B8 \uC81C\uAC70)").action(async () => {
1220
1271
  const { createInterface } = await import("readline");
1221
- const { renderHwpxToSvg } = await import("./render-GHT5HKBO.js");
1272
+ const { renderHwpxToSvg } = await import("./render-NSKWZVTD.js");
1222
1273
  const rl = createInterface({ input: process.stdin });
1223
1274
  const write = (o) => void process.stdout.write(JSON.stringify(o) + "\n");
1224
1275
  write({ ready: true, version: VERSION });
@@ -1243,13 +1294,13 @@ function registerRenderCommands(program2) {
1243
1294
  const id = req.id;
1244
1295
  try {
1245
1296
  if (!req.file || !req.out) throw new Error("file\xB7out \uD544\uC218");
1246
- const buffer = readFileSync4(resolve4(req.file));
1297
+ const buffer = readFileSync4(resolve5(req.file));
1247
1298
  const result = await renderHwpxToSvg(toArrayBuffer(buffer), {
1248
1299
  highlights: req.highlight,
1249
1300
  reflow: req.reflow,
1250
1301
  reflowMode: req.reflowMode
1251
1302
  });
1252
- const outPath = resolve4(req.out);
1303
+ const outPath = resolve5(req.out);
1253
1304
  mkdirSync4(dirname3(outPath), { recursive: true });
1254
1305
  writeFileSync4(outPath, result.svg, "utf-8");
1255
1306
  write({ id, ok: true, out: outPath, width: result.width, height: result.height, pageCount: result.pageCount, stats: result.stats, warnings: result.warnings });
@@ -1267,12 +1318,12 @@ function registerSystemCommands(program2) {
1267
1318
  await startMcpServer();
1268
1319
  });
1269
1320
  program2.command("setup").description("\uB300\uD654\uD615 \uC124\uCE58 \uB9C8\uBC95\uC0AC \u2014 AI \uD074\uB77C\uC774\uC5B8\uD2B8 \uC790\uB3D9 \uB4F1\uB85D (Mac/Win/Linux)").action(async () => {
1270
- const { runSetup } = await import("./setup-AGSCEHDB.js");
1321
+ const { runSetup } = await import("./setup-REH2KZP2.js");
1271
1322
  await runSetup();
1272
1323
  });
1273
1324
  program2.command("check-formula-models").description("PDF \uC218\uC2DD OCR \uBAA8\uB378(MFD + MFR + tokenizer, ~155MB) \uC0C1\uD0DC \uD655\uC778 \u2014 \uC5C6\uAC70\uB098 SHA \uBD88\uC77C\uCE58\uBA74 \uB2E4\uC6B4\uB85C\uB4DC").option("--status-only", "\uC0C1\uD0DC\uB9CC JSON \uC73C\uB85C \uCD9C\uB825 (\uB2E4\uC6B4\uB85C\uB4DC \uC548 \uD568)").action(async (opts) => {
1274
1325
  try {
1275
- const { getFormulaModelStatus, ensureFormulaModels, getFormulaModelsDir } = await import("./formula-E3N7KDDG.js");
1326
+ const { getFormulaModelStatus, ensureFormulaModels, getFormulaModelsDir } = await import("./formula-7ZOZ5QJ6.js");
1276
1327
  const dir = getFormulaModelsDir();
1277
1328
  if (opts.statusOnly) {
1278
1329
  const status = await getFormulaModelStatus();
@@ -1326,7 +1377,7 @@ function registerSystemCommands(program2) {
1326
1377
  });
1327
1378
  program2.command("check-ocr-models").description("\uD14D\uC2A4\uD2B8 OCR \uBAA8\uB378(PP-OCRv5 korean det+rec, ~18MB) \uC0C1\uD0DC \uD655\uC778 \u2014 \uC5C6\uAC70\uB098 SHA \uBD88\uC77C\uCE58\uBA74 \uB2E4\uC6B4\uB85C\uB4DC").option("--status-only", "\uC0C1\uD0DC\uB9CC JSON \uC73C\uB85C \uCD9C\uB825 (\uB2E4\uC6B4\uB85C\uB4DC \uC548 \uD568)").action(async (opts) => {
1328
1379
  try {
1329
- const { getOcrModelStatus, ensureOcrModels, getOcrModelsDir } = await import("./models-YXITRAMR.js");
1380
+ const { getOcrModelStatus, ensureOcrModels, getOcrModelsDir } = await import("./models-G3WA24SY.js");
1330
1381
  const dir = getOcrModelsDir();
1331
1382
  if (opts.statusOnly) {
1332
1383
  const status = await getOcrModelStatus();
@@ -1380,7 +1431,7 @@ function registerSystemCommands(program2) {
1380
1431
  });
1381
1432
  program2.command("models").description("OCR/\uC218\uC2DD \uBAA8\uB378 \uC624\uD504\uB77C\uC778 \uC0AC\uC774\uB4DC\uB85C\uB4DC \u2014 \uD3D0\uC1C4\uB9DD \uBC18\uC785\uC6A9 \uB0B4\uBCF4\uB0B4\uAE30/\uAC00\uC838\uC624\uAE30 (SHA-256 \uAC80\uC99D)").option("--status", "\uCE90\uC2DC\uC5D0 \uC124\uCE58\uB41C \uBAA8\uB378 \uC0C1\uD0DC\uB97C JSON \uC73C\uB85C \uCD9C\uB825").option("--export <dir>", "\uB85C\uCEEC \uCE90\uC2DC \u2192 \uBC88\uB4E4 \uB514\uB809\uD1A0\uB9AC\uB85C \uB0B4\uBCF4\uB0B4\uAE30 (\uC628\uB77C\uC778 PC\uC5D0\uC11C \uC2E4\uD589)").option("--import <dir>", "\uBC88\uB4E4 \uB514\uB809\uD1A0\uB9AC \u2192 \uB85C\uCEEC \uCE90\uC2DC\uB85C \uC124\uCE58 (\uB0B4\uBD80\uB9DD PC\uC5D0\uC11C \uC2E4\uD589)").action(async (opts) => {
1382
1433
  try {
1383
- const { exportModels, importModels, modelCacheStatus } = await import("./model-bundle-IHKNDLOT.js");
1434
+ const { exportModels, importModels, modelCacheStatus } = await import("./model-bundle-VHRXG63R.js");
1384
1435
  if (opts.status) {
1385
1436
  process.stdout.write(JSON.stringify(await modelCacheStatus(), null, 2) + "\n");
1386
1437
  return;
@@ -1417,15 +1468,15 @@ function registerSystemCommands(program2) {
1417
1468
  }
1418
1469
 
1419
1470
  // src/cli/commands-worker.ts
1420
- import { readFileSync as readFileSync5, statSync as statSync4 } from "fs";
1421
- import { resolve as resolve5 } from "path";
1471
+ import { readFileSync as readFileSync5, statSync as statSync5 } from "fs";
1472
+ import { resolve as resolve6 } from "path";
1422
1473
  var PARSE_WORKER_PROTOCOL = 1;
1423
1474
  var MAX_FILE_BYTES = 500 * 1024 * 1024;
1424
1475
  var bytesToBase64 = (_key, value) => value instanceof Uint8Array ? Buffer.from(value).toString("base64") : value;
1425
1476
  async function parseOne(req) {
1426
- const absPath = resolve5(req.file);
1477
+ const absPath = resolve6(req.file);
1427
1478
  try {
1428
- const size = statSync4(absPath).size;
1479
+ const size = statSync5(absPath).size;
1429
1480
  if (size > MAX_FILE_BYTES) {
1430
1481
  return { success: false, fileType: "unknown", error: `\uD30C\uC77C\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${(size / 1024 / 1024).toFixed(1)}MB)`, code: "PARSE_ERROR" };
1431
1482
  }
@@ -1504,7 +1555,16 @@ program.name("kordoc").description("\uBAA8\uB450 \uD30C\uC2F1\uD574\uBC84\uB9AC\
1504
1555
  } catch (err) {
1505
1556
  program.error(sanitizeError(err));
1506
1557
  }
1507
- } else if (!await convertFiles(files, opts)) process.exitCode = 1;
1558
+ } else {
1559
+ if (opts.outDir && files.length > 1) {
1560
+ try {
1561
+ assertDistinctStems(files);
1562
+ } catch (err) {
1563
+ program.error(sanitizeError(err));
1564
+ }
1565
+ }
1566
+ if (!await convertFiles(files, opts)) process.exitCode = 1;
1567
+ }
1508
1568
  });
1509
1569
  registerDocCommands(program);
1510
1570
  registerGenerateCommands(program);
@@ -1515,5 +1575,5 @@ registerBatchWorker(program);
1515
1575
  program.hook("preAction", (_program, action) => {
1516
1576
  if (action.name() !== "setup") routeConsoleToStderr();
1517
1577
  });
1518
- program.parse();
1578
+ program.parse(process.argv, { from: "node" });
1519
1579
  //# sourceMappingURL=cli.js.map