kordoc 4.4.1 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/LICENSE +21 -21
  2. package/NOTICE +176 -176
  3. package/README.md +958 -942
  4. package/THIRD_PARTY/apache-2.0.LICENSE +201 -201
  5. package/THIRD_PARTY/claw-hwp.LICENSE +21 -21
  6. package/THIRD_PARTY/hml-equation-parser.LICENSE +201 -201
  7. package/THIRD_PARTY/hml-equation-parser.txt +35 -35
  8. package/THIRD_PARTY/opendataloader-pdf.txt +32 -32
  9. package/THIRD_PARTY/pix2text.txt +17 -17
  10. package/THIRD_PARTY/rhwp-forms.txt +35 -35
  11. package/dist/{-7X4H77Z7.js → -DEVLQKIT.js} +12 -12
  12. package/dist/{chunk-TGAWXMXB.js → chunk-2CABQYTT.js} +23 -12
  13. package/dist/chunk-2CABQYTT.js.map +1 -0
  14. package/dist/{chunk-5A2TGIN7.js → chunk-2CENWSAW.js} +10 -10
  15. package/dist/chunk-2CENWSAW.js.map +1 -0
  16. package/dist/{chunk-3H5X63BQ.js → chunk-3FFPHTXD.js} +1 -1
  17. package/dist/chunk-3FFPHTXD.js.map +1 -0
  18. package/dist/{chunk-MOL7MDBG.js → chunk-3TBUDJDE.js} +1 -1
  19. package/dist/chunk-3TBUDJDE.js.map +1 -0
  20. package/dist/{chunk-5RPYBC2Q.js → chunk-6GBLFQMA.js} +1 -1
  21. package/dist/chunk-6GBLFQMA.js.map +1 -0
  22. package/dist/{chunk-GZDOWYJM.js → chunk-6XPXIG57.js} +2 -2
  23. package/dist/chunk-6XPXIG57.js.map +1 -0
  24. package/dist/{chunk-2352RXHG.js → chunk-7BTO44Q7.js} +337 -87
  25. package/dist/chunk-7BTO44Q7.js.map +1 -0
  26. package/dist/{chunk-GE43BE46.js → chunk-AIQ3ISQU.js} +1 -1
  27. package/dist/chunk-AIQ3ISQU.js.map +1 -0
  28. package/dist/{chunk-GC7WBHAN.cjs → chunk-CARNWWGI.cjs} +4 -4
  29. package/dist/chunk-CARNWWGI.cjs.map +1 -0
  30. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  31. package/dist/{chunk-FR65WNLF.cjs → chunk-HPRGVU6A.cjs} +25 -14
  32. package/dist/chunk-HPRGVU6A.cjs.map +1 -0
  33. package/dist/{chunk-3DX6VJGH.cjs → chunk-I42DND3B.cjs} +17 -17
  34. package/dist/chunk-I42DND3B.cjs.map +1 -0
  35. package/dist/{chunk-SMPEZINI.js → chunk-IBVMJIHR.js} +2 -2
  36. package/dist/chunk-IBVMJIHR.js.map +1 -0
  37. package/dist/{chunk-UA53AA7R.js → chunk-IHK5LCYX.js} +2 -2
  38. package/dist/chunk-IHK5LCYX.js.map +1 -0
  39. package/dist/{chunk-JGHQFUKI.js → chunk-KC63W72C.js} +2 -2
  40. package/dist/chunk-KC63W72C.js.map +1 -0
  41. package/dist/{chunk-NUGTEPKT.js → chunk-KQOTL4WI.js} +2 -2
  42. package/dist/chunk-KQOTL4WI.js.map +1 -0
  43. package/dist/{chunk-ZV5OKQ3Z.cjs → chunk-MGGU3ZRK.cjs} +1 -1
  44. package/dist/chunk-MGGU3ZRK.cjs.map +1 -0
  45. package/dist/{chunk-AYM6UHFX.js → chunk-MSMSHU2F.js} +23 -12
  46. package/dist/chunk-MSMSHU2F.js.map +1 -0
  47. package/dist/{chunk-DZIXKL7E.js → chunk-O5EK52TG.js} +1 -1
  48. package/dist/chunk-O5EK52TG.js.map +1 -0
  49. package/dist/{chunk-IPOVUGXD.js → chunk-OPL22SYF.js} +3 -3
  50. package/dist/chunk-OPL22SYF.js.map +1 -0
  51. package/dist/{chunk-HGSO2H44.js → chunk-PQDNCWAZ.js} +11 -11
  52. package/dist/chunk-PQDNCWAZ.js.map +1 -0
  53. package/dist/{chunk-A73RMJ6B.js → chunk-PSAHY5XW.js} +1 -1
  54. package/dist/chunk-PSAHY5XW.js.map +1 -0
  55. package/dist/{chunk-T25FBUMN.js → chunk-UGKXJA3W.js} +4 -3
  56. package/dist/chunk-UGKXJA3W.js.map +1 -0
  57. package/dist/{chunk-5PXCA3DN.js → chunk-UQ4NSK66.js} +3 -3
  58. package/dist/chunk-UQ4NSK66.js.map +1 -0
  59. package/dist/{chunk-7MDLAKVO.js → chunk-VNEV6VKD.js} +2 -2
  60. package/dist/chunk-VNEV6VKD.js.map +1 -0
  61. package/dist/{chunk-7FCNOKOR.js → chunk-W34QSJFF.js} +1 -1
  62. package/dist/chunk-W34QSJFF.js.map +1 -0
  63. package/dist/{chunk-7BIVNIK5.cjs → chunk-WX7WQTOT.cjs} +4 -3
  64. package/dist/chunk-WX7WQTOT.cjs.map +1 -0
  65. package/dist/{chunk-DCZVOIEO.cjs → chunk-X34YWRL5.cjs} +1 -1
  66. package/dist/chunk-X34YWRL5.cjs.map +1 -0
  67. package/dist/{chunk-UAFSPWU7.js → chunk-YNJDNP44.js} +1 -1
  68. package/dist/chunk-YNJDNP44.js.map +1 -0
  69. package/dist/{chunk-WA7XLWZW.js → chunk-ZYQ5X6PG.js} +4 -3
  70. package/dist/chunk-ZYQ5X6PG.js.map +1 -0
  71. package/dist/chunks-Y2VE2WCJ.js +10 -0
  72. package/dist/cli.js +91 -31
  73. package/dist/cli.js.map +1 -1
  74. package/dist/{formula-JLYS73QL.js → formula-ETB6MESN.js} +2 -2
  75. package/dist/formula-ETB6MESN.js.map +1 -0
  76. package/dist/{formula-LIVQSCMM.js → formula-KW4NI5IO.js} +2 -2
  77. package/dist/formula-KW4NI5IO.js.map +1 -0
  78. package/dist/{formula-CG4S7TWO.cjs → formula-WKGP3D3Y.cjs} +8 -8
  79. package/dist/formula-WKGP3D3Y.cjs.map +1 -0
  80. package/dist/{image-ocr-AHHY42OI.js → image-ocr-C6U7YHRC.js} +15 -7
  81. package/dist/image-ocr-C6U7YHRC.js.map +1 -0
  82. package/dist/{image-ocr-K4XCRBTY.js → image-ocr-YIBJCOUQ.js} +17 -9
  83. package/dist/image-ocr-YIBJCOUQ.js.map +1 -0
  84. package/dist/{image-ocr-VCXLT5Q6.cjs → image-ocr-YID6TDN5.cjs} +20 -12
  85. package/dist/image-ocr-YID6TDN5.cjs.map +1 -0
  86. package/dist/index.cjs +676 -426
  87. package/dist/index.cjs.map +1 -1
  88. package/dist/index.d.cts +55 -3
  89. package/dist/index.d.ts +55 -3
  90. package/dist/index.js +331 -81
  91. package/dist/index.js.map +1 -1
  92. package/dist/mcp.js +61 -28
  93. package/dist/mcp.js.map +1 -1
  94. package/dist/{models-6SIKLKRH.js → models-6VMAVZR6.js} +3 -3
  95. package/dist/page-range-CIRRJPXJ.js +7 -0
  96. package/dist/page-range-OF5I4PQY.js +8 -0
  97. package/dist/page-range-TPIRSA3J.cjs +8 -0
  98. package/dist/page-range-TPIRSA3J.cjs.map +1 -0
  99. package/dist/{parser-ABYM2MVN.cjs → parser-EYCVDUJA.cjs} +33 -33
  100. package/dist/parser-EYCVDUJA.cjs.map +1 -0
  101. package/dist/{parser-I3ELUUOG.js → parser-GFXZV2VJ.js} +11 -11
  102. package/dist/parser-GFXZV2VJ.js.map +1 -0
  103. package/dist/{parser-IPVY56U3.js → parser-SHM3JEH6.js} +9 -9
  104. package/dist/parser-SHM3JEH6.js.map +1 -0
  105. package/dist/pdf-ocr-TMAWPOHC.cjs +13 -0
  106. package/dist/pdf-ocr-TMAWPOHC.cjs.map +1 -0
  107. package/dist/pdf-ocr-UKFYODLP.js +15 -0
  108. package/dist/pdf-ocr-ZG4UVUIT.js +12 -0
  109. package/dist/{profile-io-YADU6SKH.js → profile-io-FQZNNA3O.js} +3 -3
  110. package/dist/{rasterize-YV5VDSQX.js → rasterize-QGKFNTXO.js} +2 -2
  111. package/dist/rasterize-QGKFNTXO.js.map +1 -0
  112. package/dist/{redact-7ILEAUTS.js → redact-W5K3ILQH.js} +2 -2
  113. package/dist/render-YFIWQYVB.js +10 -0
  114. package/dist/seal-GZ7NDWLR.js +10 -0
  115. package/dist/{setup-GUQT5ELJ.js → setup-I4I75QJU.js} +1 -1
  116. package/dist/setup-I4I75QJU.js.map +1 -0
  117. package/dist/{watch-5K2ZERXI.js → watch-OIVXH2RN.js} +12 -12
  118. package/dist/watch-OIVXH2RN.js.map +1 -0
  119. package/package.json +103 -103
  120. package/templates//352/260/204/354/235/264/352/270/260/354/225/210/353/254/270_/354/230/210/354/213/234/352/260/222.json +9 -9
  121. package/templates//354/235/274/353/260/230/352/270/260/354/225/210/353/254/270_/354/230/210/354/213/234/352/260/222.json +24 -24
  122. package/dist/chunk-2352RXHG.js.map +0 -1
  123. package/dist/chunk-3DX6VJGH.cjs.map +0 -1
  124. package/dist/chunk-3H5X63BQ.js.map +0 -1
  125. package/dist/chunk-5A2TGIN7.js.map +0 -1
  126. package/dist/chunk-5PXCA3DN.js.map +0 -1
  127. package/dist/chunk-5RPYBC2Q.js.map +0 -1
  128. package/dist/chunk-7BIVNIK5.cjs.map +0 -1
  129. package/dist/chunk-7FCNOKOR.js.map +0 -1
  130. package/dist/chunk-7MDLAKVO.js.map +0 -1
  131. package/dist/chunk-A73RMJ6B.js.map +0 -1
  132. package/dist/chunk-AYM6UHFX.js.map +0 -1
  133. package/dist/chunk-DCZVOIEO.cjs.map +0 -1
  134. package/dist/chunk-DZIXKL7E.js.map +0 -1
  135. package/dist/chunk-FR65WNLF.cjs.map +0 -1
  136. package/dist/chunk-GC7WBHAN.cjs.map +0 -1
  137. package/dist/chunk-GE43BE46.js.map +0 -1
  138. package/dist/chunk-GZDOWYJM.js.map +0 -1
  139. package/dist/chunk-HGSO2H44.js.map +0 -1
  140. package/dist/chunk-IPOVUGXD.js.map +0 -1
  141. package/dist/chunk-JGHQFUKI.js.map +0 -1
  142. package/dist/chunk-MOL7MDBG.js.map +0 -1
  143. package/dist/chunk-NUGTEPKT.js.map +0 -1
  144. package/dist/chunk-SMPEZINI.js.map +0 -1
  145. package/dist/chunk-T25FBUMN.js.map +0 -1
  146. package/dist/chunk-TGAWXMXB.js.map +0 -1
  147. package/dist/chunk-UA53AA7R.js.map +0 -1
  148. package/dist/chunk-UAFSPWU7.js.map +0 -1
  149. package/dist/chunk-WA7XLWZW.js.map +0 -1
  150. package/dist/chunk-ZV5OKQ3Z.cjs.map +0 -1
  151. package/dist/chunks-FMZK4QHL.js +0 -10
  152. package/dist/formula-CG4S7TWO.cjs.map +0 -1
  153. package/dist/formula-JLYS73QL.js.map +0 -1
  154. package/dist/formula-LIVQSCMM.js.map +0 -1
  155. package/dist/image-ocr-AHHY42OI.js.map +0 -1
  156. package/dist/image-ocr-K4XCRBTY.js.map +0 -1
  157. package/dist/image-ocr-VCXLT5Q6.cjs.map +0 -1
  158. package/dist/page-range-737B4EZW.js +0 -8
  159. package/dist/page-range-LNMXJU6W.js +0 -7
  160. package/dist/page-range-P7SDW6LR.cjs +0 -8
  161. package/dist/page-range-P7SDW6LR.cjs.map +0 -1
  162. package/dist/parser-ABYM2MVN.cjs.map +0 -1
  163. package/dist/parser-I3ELUUOG.js.map +0 -1
  164. package/dist/parser-IPVY56U3.js.map +0 -1
  165. package/dist/pdf-ocr-EL3VSWWY.js +0 -12
  166. package/dist/pdf-ocr-FVLKQNAT.js +0 -15
  167. package/dist/pdf-ocr-VQ3QWXGE.cjs +0 -13
  168. package/dist/pdf-ocr-VQ3QWXGE.cjs.map +0 -1
  169. package/dist/rasterize-YV5VDSQX.js.map +0 -1
  170. package/dist/render-K6M3P24X.js +0 -10
  171. package/dist/seal-YW3U5BCY.js +0 -10
  172. package/dist/setup-GUQT5ELJ.js.map +0 -1
  173. package/dist/watch-5K2ZERXI.js.map +0 -1
  174. /package/dist/{-7X4H77Z7.js.map → -DEVLQKIT.js.map} +0 -0
  175. /package/dist/{chunks-FMZK4QHL.js.map → chunks-Y2VE2WCJ.js.map} +0 -0
  176. /package/dist/{models-6SIKLKRH.js.map → models-6VMAVZR6.js.map} +0 -0
  177. /package/dist/{page-range-737B4EZW.js.map → page-range-CIRRJPXJ.js.map} +0 -0
  178. /package/dist/{page-range-LNMXJU6W.js.map → page-range-OF5I4PQY.js.map} +0 -0
  179. /package/dist/{pdf-ocr-EL3VSWWY.js.map → pdf-ocr-UKFYODLP.js.map} +0 -0
  180. /package/dist/{pdf-ocr-FVLKQNAT.js.map → pdf-ocr-ZG4UVUIT.js.map} +0 -0
  181. /package/dist/{profile-io-YADU6SKH.js.map → profile-io-FQZNNA3O.js.map} +0 -0
  182. /package/dist/{redact-7ILEAUTS.js.map → redact-W5K3ILQH.js.map} +0 -0
  183. /package/dist/{render-K6M3P24X.js.map → render-YFIWQYVB.js.map} +0 -0
  184. /package/dist/{seal-YW3U5BCY.js.map → seal-GZ7NDWLR.js.map} +0 -0
package/dist/index.js CHANGED
@@ -8,10 +8,10 @@ import {
8
8
  flattenLayoutTables,
9
9
  inlineImagesIntoMarkdown,
10
10
  mapPuaText
11
- } from "./chunk-UA53AA7R.js";
11
+ } from "./chunk-IHK5LCYX.js";
12
12
  import {
13
13
  parsePageRange
14
- } from "./chunk-GE43BE46.js";
14
+ } from "./chunk-AIQ3ISQU.js";
15
15
  import {
16
16
  HEADING_RATIO_H1,
17
17
  HEADING_RATIO_H2,
@@ -27,7 +27,7 @@ import {
27
27
  sanitizeHref,
28
28
  stripDtd,
29
29
  toArrayBuffer
30
- } from "./chunk-T25FBUMN.js";
30
+ } from "./chunk-UGKXJA3W.js";
31
31
 
32
32
  // src/index.ts
33
33
  import { readFile } from "fs/promises";
@@ -17892,7 +17892,7 @@ async function parseXlsxDocument(buffer, options) {
17892
17892
  }
17893
17893
  let pageFilter = null;
17894
17894
  if (options?.pages) {
17895
- const { parsePageRange: parsePageRange2 } = await import("./page-range-LNMXJU6W.js");
17895
+ const { parsePageRange: parsePageRange2 } = await import("./page-range-CIRRJPXJ.js");
17896
17896
  pageFilter = parsePageRange2(options.pages, sheets.length);
17897
17897
  }
17898
17898
  const blocks = [];
@@ -18592,7 +18592,7 @@ async function parseXlsDocument(buffer, options) {
18592
18592
  const totalSheets = Math.min(globals.sheets.length, MAX_SHEETS2);
18593
18593
  let pageFilter = null;
18594
18594
  if (options?.pages) {
18595
- const { parsePageRange: parsePageRange2 } = await import("./page-range-LNMXJU6W.js");
18595
+ const { parsePageRange: parsePageRange2 } = await import("./page-range-CIRRJPXJ.js");
18596
18596
  pageFilter = parsePageRange2(options.pages, totalSheets);
18597
18597
  }
18598
18598
  const allBlocks = [];
@@ -22666,6 +22666,26 @@ function charVariantBase(richAssets, isGongmun = true) {
22666
22666
  var GONGMUN_BODY_RATIO = 95;
22667
22667
 
22668
22668
  // src/hwpx/md-runs.ts
22669
+ var HYPERLINK_FIELDID = 627600491;
22670
+ var FIELD_ID_BASE = 18e8;
22671
+ var FOOTNOTE_INST_BASE = 185e7;
22672
+ var inlineDoc = null;
22673
+ function beginInlineDoc(footnotes) {
22674
+ inlineDoc = { footnotes, fieldSeq: 0, noteSeq: 0, inNote: false };
22675
+ }
22676
+ function endInlineDoc() {
22677
+ inlineDoc = null;
22678
+ }
22679
+ function extractFootnoteDefs(md2) {
22680
+ const defs = /* @__PURE__ */ new Map();
22681
+ const out = md2.replace(/\r\n?/g, "\n").split("\n").filter((line) => {
22682
+ const m = /^\[\^([^\]\s]+)\]:\s?(.*)$/.exec(line);
22683
+ if (!m) return true;
22684
+ defs.set(m[1], m[2].trim());
22685
+ return false;
22686
+ }).join("\n");
22687
+ return { md: defs.size > 0 ? out : md2, defs };
22688
+ }
22669
22689
  function buildPrvText(blocks) {
22670
22690
  const lines = [];
22671
22691
  let bytes = 0;
@@ -22857,12 +22877,49 @@ function parseInlineMarkdown(text) {
22857
22877
  return `\0${literals.length - 1}\0`;
22858
22878
  });
22859
22879
  text = text.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1");
22860
- text = text.replace(/\[([^\]]*)\]\(([^)]*)\)/g, (_, t, u) => t || u);
22861
22880
  text = text.replace(/~~([^~]+)~~/g, "$1");
22881
+ let spans;
22882
+ if (inlineDoc) {
22883
+ spans = [];
22884
+ const re = /\[\^([^\]\s]+)\]|\[([^\]]*)\]\(([^)]*)\)/g;
22885
+ let last = 0;
22886
+ for (const m of text.matchAll(re)) {
22887
+ const idx = m.index;
22888
+ if (idx > last) spans.push(...emphasisSpans(text.slice(last, idx)));
22889
+ if (m[1] !== void 0) {
22890
+ const def = inlineDoc.inNote ? void 0 : inlineDoc.footnotes.get(m[1]);
22891
+ if (def !== void 0) spans.push({ text: "", bold: false, italic: false, code: false, note: def });
22892
+ else spans.push(...emphasisSpans(m[0]));
22893
+ } else {
22894
+ const anchor = m[2] || m[3];
22895
+ const href = sanitizeHref(m[3].trim()) ?? void 0;
22896
+ const sub = emphasisSpans(anchor);
22897
+ if (href) for (const s of sub) s.href = href;
22898
+ spans.push(...sub);
22899
+ }
22900
+ last = idx + m[0].length;
22901
+ }
22902
+ if (last < text.length) spans.push(...emphasisSpans(text.slice(last)));
22903
+ if (spans.length === 0) spans.push({ text, bold: false, italic: false, code: false });
22904
+ } else {
22905
+ text = text.replace(/\[([^\]]*)\]\(([^)]*)\)/g, (_, t, u) => t || u);
22906
+ spans = emphasisSpans(text);
22907
+ if (spans.length === 0) spans.push({ text, bold: false, italic: false, code: false });
22908
+ }
22909
+ for (const span of spans) {
22910
+ if (!span.text.includes("\0")) continue;
22911
+ span.text = span.text.replace(/\x00(\d+)\x00/g, (_, i) => {
22912
+ const c = literals[+i] ?? "";
22913
+ return span.code ? "\\" + c : c;
22914
+ });
22915
+ }
22916
+ return spans;
22917
+ }
22918
+ var INLINE_REGEX = /(`[^`]+`|\*{3}(?:[^*]|\*(?!\*\*))+\*{3}|\*{2}(?:[^*]|\*(?!\*))+\*{2}|\*(?:[^*]|\*{2}(?:[^*]|\*(?!\*))+\*{2})+\*|(?<![^\s\p{P}\p{S}\x00])(?<!_)_{2}(?=\S)[^_]+(?<=\S)_{2}(?!_)(?![^\s\p{P}\p{S}\x00])|(?<![^\s\p{P}\p{S}\x00])(?<!_)_(?=\S)[^_]+(?<=\S)_(?!_)(?![^\s\p{P}\p{S}\x00]))/gu;
22919
+ function emphasisSpans(text, depth = 0) {
22862
22920
  const spans = [];
22863
- const regex = /(`[^`]+`|\*{3}[^*]+\*{3}|\*{2}[^*]+\*{2}|\*[^*]+\*|(?<![^\s\p{P}\p{S}\x00])(?<!_)_{2}(?=\S)[^_]+(?<=\S)_{2}(?!_)(?![^\s\p{P}\p{S}\x00])|(?<![^\s\p{P}\p{S}\x00])(?<!_)_(?=\S)[^_]+(?<=\S)_(?!_)(?![^\s\p{P}\p{S}\x00]))/gu;
22864
22921
  let lastIdx = 0;
22865
- for (const match of text.matchAll(regex)) {
22922
+ for (const match of text.matchAll(INLINE_REGEX)) {
22866
22923
  const idx = match.index;
22867
22924
  if (idx > lastIdx) {
22868
22925
  spans.push({ text: text.slice(lastIdx, idx), bold: false, italic: false, code: false });
@@ -22870,28 +22927,34 @@ function parseInlineMarkdown(text) {
22870
22927
  const raw = match[0];
22871
22928
  if (raw.startsWith("`")) {
22872
22929
  spans.push({ text: raw.slice(1, -1), bold: false, italic: false, code: true });
22873
- } else if (raw.startsWith("***") || raw.startsWith("___")) {
22874
- spans.push({ text: raw.slice(3, -3), bold: true, italic: true, code: false });
22875
- } else if (raw.startsWith("**") || raw.startsWith("__")) {
22876
- spans.push({ text: raw.slice(2, -2), bold: true, italic: false, code: false });
22877
22930
  } else {
22878
- spans.push({ text: raw.slice(1, -1), bold: false, italic: true, code: false });
22931
+ let inner;
22932
+ let bold = false;
22933
+ let italic = false;
22934
+ if (raw.startsWith("***") || raw.startsWith("___")) {
22935
+ inner = raw.slice(3, -3);
22936
+ bold = true;
22937
+ italic = true;
22938
+ } else if (raw.startsWith("**") || raw.startsWith("__")) {
22939
+ inner = raw.slice(2, -2);
22940
+ bold = true;
22941
+ } else {
22942
+ inner = raw.slice(1, -1);
22943
+ italic = true;
22944
+ }
22945
+ if (depth < 3 && /[`*_]/.test(inner)) {
22946
+ for (const child of emphasisSpans(inner, depth + 1)) {
22947
+ spans.push(child.code ? child : { ...child, bold: child.bold || bold, italic: child.italic || italic });
22948
+ }
22949
+ } else {
22950
+ spans.push({ text: inner, bold, italic, code: false });
22951
+ }
22879
22952
  }
22880
22953
  lastIdx = idx + raw.length;
22881
22954
  }
22882
22955
  if (lastIdx < text.length) {
22883
22956
  spans.push({ text: text.slice(lastIdx), bold: false, italic: false, code: false });
22884
22957
  }
22885
- if (spans.length === 0) {
22886
- spans.push({ text, bold: false, italic: false, code: false });
22887
- }
22888
- for (const span of spans) {
22889
- if (!span.text.includes("\0")) continue;
22890
- span.text = span.text.replace(/\x00(\d+)\x00/g, (_, i) => {
22891
- const c = literals[+i] ?? "";
22892
- return span.code ? "\\" + c : c;
22893
- });
22894
- }
22895
22958
  return spans;
22896
22959
  }
22897
22960
  function spanToCharPrId(span) {
@@ -22901,13 +22964,54 @@ function spanToCharPrId(span) {
22901
22964
  if (span.italic) return CHAR_ITALIC;
22902
22965
  return CHAR_NORMAL;
22903
22966
  }
22967
+ function hyperlinkBeginXml(fid, href) {
22968
+ const cmd = escapeXml(href.replace(/:/g, "\\:"));
22969
+ const path = escapeXml(href);
22970
+ return `<hp:ctrl><hp:fieldBegin id="${fid}" type="HYPERLINK" name="" editable="0" dirty="0" zorder="-1" fieldid="${HYPERLINK_FIELDID}"><hp:parameters cnt="6" name=""><hp:integerParam name="Prop">0</hp:integerParam><hp:stringParam name="Command">${cmd};1;0;0</hp:stringParam><hp:stringParam name="Path">${path}</hp:stringParam><hp:stringParam name="Category">HWPHYPERLINK_TYPE_URL</hp:stringParam><hp:stringParam name="TargetType">HWPHYPERLINK_TARGET_BOOKMARK</hp:stringParam><hp:stringParam name="DocOpenType">HWPHYPERLINK_JUMP_CURRENTTAB</hp:stringParam></hp:parameters></hp:fieldBegin></hp:ctrl>`;
22971
+ }
22972
+ function footnoteXml(note, mapCharId) {
22973
+ const d = inlineDoc;
22974
+ const n = ++d.noteSeq;
22975
+ d.inNote = true;
22976
+ let body;
22977
+ try {
22978
+ body = generateRuns(note, CHAR_NORMAL, mapCharId);
22979
+ } finally {
22980
+ d.inNote = false;
22981
+ }
22982
+ return `<hp:ctrl><hp:footNote number="${n}" suffixChar="41" instId="${FOOTNOTE_INST_BASE + n}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0"><hp:p paraPrIDRef="0" styleIDRef="0">${body}</hp:p></hp:subList></hp:footNote></hp:ctrl>`;
22983
+ }
22904
22984
  function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
22905
22985
  const spans = parseInlineMarkdown(text);
22906
- return spans.map((span) => {
22907
- let charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
22908
- if (mapCharId) charId = mapCharId(charId);
22909
- return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
22910
- }).join("");
22986
+ const mapped = (id) => mapCharId ? mapCharId(id) : id;
22987
+ const out = [];
22988
+ let openHref = null;
22989
+ let openFid = 0;
22990
+ const closeField = () => {
22991
+ if (openHref === null) return;
22992
+ out.push(`<hp:run charPrIDRef="${mapped(defaultCharPr)}"><hp:ctrl><hp:fieldEnd beginIDRef="${openFid}" fieldid="${HYPERLINK_FIELDID}"/></hp:ctrl></hp:run>`);
22993
+ openHref = null;
22994
+ };
22995
+ for (const span of spans) {
22996
+ if (span.note !== void 0 && inlineDoc) {
22997
+ closeField();
22998
+ out.push(`<hp:run charPrIDRef="${mapped(defaultCharPr)}">${footnoteXml(span.note, mapCharId)}</hp:run>`);
22999
+ continue;
23000
+ }
23001
+ const href = inlineDoc ? span.href ?? null : null;
23002
+ if (href !== openHref) {
23003
+ closeField();
23004
+ if (href !== null) {
23005
+ openFid = FIELD_ID_BASE + ++inlineDoc.fieldSeq;
23006
+ openHref = href;
23007
+ out.push(`<hp:run charPrIDRef="${mapped(defaultCharPr)}">${hyperlinkBeginXml(openFid, href)}</hp:run>`);
23008
+ }
23009
+ }
23010
+ const charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
23011
+ out.push(`<hp:run charPrIDRef="${mapped(charId)}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`);
23012
+ }
23013
+ closeField();
23014
+ return out.join("");
22911
23015
  }
22912
23016
  function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId, styleId = 0) {
22913
23017
  if (paraPrId === PARA_CODE) {
@@ -22917,6 +23021,56 @@ function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL,
22917
23021
  return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="${styleId}">${runs}</hp:p>`;
22918
23022
  }
22919
23023
 
23024
+ // src/hwpx/gen-page.ts
23025
+ var PAPER_MM = {
23026
+ A4: [210, 297],
23027
+ A3: [297, 420],
23028
+ B4: [257, 364],
23029
+ B5: [182, 257],
23030
+ Letter: [215.9, 279.4]
23031
+ };
23032
+ function resolvePage(opts) {
23033
+ if (!opts) return null;
23034
+ const { size, orientation, columns, header, footer } = opts;
23035
+ if (size === void 0 && orientation === void 0 && columns === void 0 && header === void 0 && footer === void 0) return null;
23036
+ let wMm = 210, hMm = 297;
23037
+ if (size !== void 0) {
23038
+ if (typeof size === "string") {
23039
+ const preset = PAPER_MM[size];
23040
+ if (!preset) throw new Error(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC6A9\uC9C0 \uD504\uB9AC\uC14B: ${size} (A4\xB7A3\xB7B4\xB7B5\xB7Letter)`);
23041
+ [wMm, hMm] = preset;
23042
+ } else {
23043
+ if (!(size.widthMm > 0) || !(size.heightMm > 0) || size.widthMm > 1e3 || size.heightMm > 1e3) {
23044
+ throw new Error(`\uC6A9\uC9C0 \uCE58\uC218\uB294 0~1000mm \uBC94\uC704\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${size.widthMm}\xD7${size.heightMm}`);
23045
+ }
23046
+ wMm = size.widthMm;
23047
+ hMm = size.heightMm;
23048
+ }
23049
+ }
23050
+ const cols = columns ?? 1;
23051
+ if (!Number.isInteger(cols) || cols < 1 || cols > 8) {
23052
+ throw new Error(`\uB2E4\uB2E8 \uAC1C\uC218\uB294 1~8 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${columns}`);
23053
+ }
23054
+ const paperHU = (mm) => Math.floor(mm * 7200 / 25.4);
23055
+ return {
23056
+ widthHU: size === void 0 ? A4_W_HU : paperHU(wMm),
23057
+ heightHU: size === void 0 ? A4_H_HU : paperHU(hMm),
23058
+ // 실측: 용지 치수는 방향과 무관하게 유지, 방향은 landscape 속성만 바뀐다
23059
+ landscape: orientation === "landscape" ? "NARROWLY" : "WIDELY",
23060
+ columns: cols,
23061
+ header: header?.trim() ? header.trim() : null,
23062
+ footer: footer?.trim() ? footer.trim() : null
23063
+ };
23064
+ }
23065
+ function columnColPrXml(columns) {
23066
+ const gap = columns > 1 ? 2268 : 0;
23067
+ return `<hp:ctrl><hp:colPr id="" type="NEWSPAPER" layout="LEFT" colCount="${columns}" sameSz="1" sameGap="${gap}"/></hp:ctrl>`;
23068
+ }
23069
+ function headerFooterCtrl(tag, text, id, mapCharId) {
23070
+ const runs = generateRuns(text, void 0, mapCharId);
23071
+ return `<hp:ctrl><hp:${tag} id="${id}" applyPageType="BOTH"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0"><hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p></hp:subList></hp:${tag}></hp:ctrl>`;
23072
+ }
23073
+
22920
23074
  // src/hwpx/gen-header.ts
22921
23075
  function generateContainerXml() {
22922
23076
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
@@ -24507,15 +24661,65 @@ var IMAGE_EXT_MIME = {
24507
24661
  tif: "image/tiff",
24508
24662
  tiff: "image/tiff"
24509
24663
  };
24664
+ function sniffImage(b) {
24665
+ if (b.length >= 8 && b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71) return { mime: "image/png", ext: "png" };
24666
+ if (b.length >= 3 && b[0] === 255 && b[1] === 216 && b[2] === 255) return { mime: "image/jpeg", ext: "jpg" };
24667
+ if (b.length >= 6 && b[0] === 71 && b[1] === 73 && b[2] === 70) return { mime: "image/gif", ext: "gif" };
24668
+ if (b.length >= 2 && b[0] === 66 && b[1] === 77) return { mime: "image/bmp", ext: "bmp" };
24669
+ return null;
24670
+ }
24671
+ function probeImageSize(b) {
24672
+ const dv = new DataView(b.buffer, b.byteOffset, b.byteLength);
24673
+ try {
24674
+ if (b[0] === 137 && b[1] === 80) {
24675
+ return { w: dv.getUint32(16), h: dv.getUint32(20) };
24676
+ }
24677
+ if (b[0] === 255 && b[1] === 216) {
24678
+ let i = 2;
24679
+ while (i + 9 < b.length) {
24680
+ if (b[i] !== 255) {
24681
+ i++;
24682
+ continue;
24683
+ }
24684
+ const marker = b[i + 1];
24685
+ if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) {
24686
+ return { w: dv.getUint16(i + 7), h: dv.getUint16(i + 5) };
24687
+ }
24688
+ i += 2 + dv.getUint16(i + 2);
24689
+ }
24690
+ return null;
24691
+ }
24692
+ if (b[0] === 71 && b[1] === 73) {
24693
+ return { w: dv.getUint16(6, true), h: dv.getUint16(8, true) };
24694
+ }
24695
+ if (b[0] === 66 && b[1] === 77) {
24696
+ return { w: dv.getUint32(18, true), h: Math.abs(dv.getInt32(22, true)) };
24697
+ }
24698
+ } catch {
24699
+ }
24700
+ return null;
24701
+ }
24702
+ var PX_TO_HU = 75;
24703
+ var MAX_IMG_W_HU = 48189;
24510
24704
  var ImageRegistry = class {
24705
+ /** @param supplied url → 실데이터 바이트 (markdownToHwpx images 옵션) */
24706
+ constructor(supplied) {
24707
+ this.supplied = supplied;
24708
+ }
24511
24709
  byUrl = /* @__PURE__ */ new Map();
24512
24710
  ids = /* @__PURE__ */ new Set();
24513
24711
  parts = [];
24514
24712
  picSeq = 0;
24713
+ binSeq = 0;
24515
24714
  /** url 등록(중복 시 기존 파트) — 수용 불가면 null */
24516
24715
  take(url) {
24517
24716
  const cached = this.byUrl.get(url);
24518
24717
  if (cached !== void 0) return cached;
24718
+ const real = this.takeReal(url);
24719
+ if (real) {
24720
+ this.byUrl.set(url, real);
24721
+ return real;
24722
+ }
24519
24723
  let part = null;
24520
24724
  const m = /^([A-Za-z0-9._-]+)\.([A-Za-z0-9]+)$/.exec(url);
24521
24725
  const mime = m ? IMAGE_EXT_MIME[m[2].toLowerCase()] : void 0;
@@ -24535,6 +24739,41 @@ var ImageRegistry = class {
24535
24739
  this.byUrl.set(url, part);
24536
24740
  return part;
24537
24741
  }
24742
+ /** 실데이터 등록 — images 맵 바이트·data: URI. 포맷 미상(webp 등)은 null → placeholder 폴백 */
24743
+ takeReal(url) {
24744
+ let bytes = this.supplied?.get(url);
24745
+ if (!bytes && url.startsWith("data:")) {
24746
+ const m = /^data:image\/[a-z+]+;base64,([A-Za-z0-9+/=\s]+)$/i.exec(url);
24747
+ if (m) {
24748
+ try {
24749
+ bytes = new Uint8Array(Buffer.from(m[1].replace(/\s+/g, ""), "base64"));
24750
+ } catch {
24751
+ }
24752
+ }
24753
+ }
24754
+ if (!bytes || bytes.length === 0) return null;
24755
+ const sniffed = sniffImage(bytes);
24756
+ if (!sniffed) return null;
24757
+ const safe = /^([A-Za-z0-9._-]+)\.([A-Za-z0-9]+)$/.exec(url);
24758
+ const base = safe && !url.includes("..") ? safe[1] : `image${++this.binSeq}`;
24759
+ let itemId = base.replace(/[^A-Za-z0-9_]/g, "_");
24760
+ let n = 1;
24761
+ while (this.ids.has(itemId)) itemId = `${base.replace(/[^A-Za-z0-9_]/g, "_")}_${n++}`;
24762
+ this.ids.add(itemId);
24763
+ const dim = probeImageSize(bytes);
24764
+ let wHU, hHU;
24765
+ if (dim && dim.w > 0 && dim.h > 0) {
24766
+ wHU = dim.w * PX_TO_HU;
24767
+ hHU = dim.h * PX_TO_HU;
24768
+ if (wHU > MAX_IMG_W_HU) {
24769
+ hHU = Math.round(hHU * (MAX_IMG_W_HU / wHU));
24770
+ wHU = MAX_IMG_W_HU;
24771
+ }
24772
+ }
24773
+ const part = { name: `BinData/${itemId}.${sniffed.ext}`, itemId, mime: sniffed.mime, data: bytes, wHU, hHU };
24774
+ this.parts.push(part);
24775
+ return part;
24776
+ }
24538
24777
  /** manifest <opf:item> 조각들 (실측: isEmbeded="1") */
24539
24778
  manifestItems() {
24540
24779
  return this.parts.map((p) => `<opf:item id="${p.itemId}" href="${p.name}" media-type="${p.mime}" isEmbeded="1"/>`);
@@ -24542,8 +24781,9 @@ var ImageRegistry = class {
24542
24781
  /** 인라인 <hp:pic> XML — 실측 저장본 미러, treatAsChar=1 (셀·문단 안 배치) */
24543
24782
  inlinePicXml(part) {
24544
24783
  const id = PIC_ID_BASE + ++this.picSeq;
24545
- const s = 1130;
24546
- return `<hp:pic id="${id}" zOrder="0" numberingType="PICTURE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" href="" groupLevel="0" instid="${id}" reverse="0" xmlns:hc="http://www.hancom.co.kr/hwpml/2011/core"><hp:offset x="0" y="0"/><hp:orgSz width="${s}" height="${s}"/><hp:curSz width="${s}" height="${s}"/><hp:flip horizontal="0" vertical="0"/><hp:rotationInfo angle="0" centerX="${s / 2}" centerY="${s / 2}" rotateimage="1"/><hp:renderingInfo><hc:transMatrix e1="1" e2="0" e3="0" e4="0" e5="1" e6="0"/><hc:scaMatrix e1="1" e2="0" e3="0" e4="0" e5="1" e6="0"/><hc:rotMatrix e1="1" e2="0" e3="0" e4="0" e5="1" e6="0"/></hp:renderingInfo><hp:imgRect><hc:pt0 x="0" y="0"/><hc:pt1 x="${s}" y="0"/><hc:pt2 x="${s}" y="${s}"/><hc:pt3 x="0" y="${s}"/></hp:imgRect><hp:imgClip left="0" right="${s}" top="0" bottom="${s}"/><hp:inMargin left="0" right="0" top="0" bottom="0"/><hp:imgDim dimwidth="${s}" dimheight="${s}"/><hc:img binaryItemIDRef="${part.itemId}" bright="0" contrast="0" effect="REAL_PIC" alpha="0"/><hp:effects/><hp:sz width="${s}" widthRelTo="ABSOLUTE" height="${s}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="1" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="0" right="0" top="0" bottom="0"/></hp:pic>`;
24784
+ const w = part.wHU ?? 1130;
24785
+ const h = part.hHU ?? 1130;
24786
+ return `<hp:pic id="${id}" zOrder="0" numberingType="PICTURE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" href="" groupLevel="0" instid="${id}" reverse="0" xmlns:hc="http://www.hancom.co.kr/hwpml/2011/core"><hp:offset x="0" y="0"/><hp:orgSz width="${w}" height="${h}"/><hp:curSz width="${w}" height="${h}"/><hp:flip horizontal="0" vertical="0"/><hp:rotationInfo angle="0" centerX="${Math.floor(w / 2)}" centerY="${Math.floor(h / 2)}" rotateimage="1"/><hp:renderingInfo><hc:transMatrix e1="1" e2="0" e3="0" e4="0" e5="1" e6="0"/><hc:scaMatrix e1="1" e2="0" e3="0" e4="0" e5="1" e6="0"/><hc:rotMatrix e1="1" e2="0" e3="0" e4="0" e5="1" e6="0"/></hp:renderingInfo><hp:imgRect><hc:pt0 x="0" y="0"/><hc:pt1 x="${w}" y="0"/><hc:pt2 x="${w}" y="${h}"/><hc:pt3 x="0" y="${h}"/></hp:imgRect><hp:imgClip left="0" right="${w}" top="0" bottom="${h}"/><hp:inMargin left="0" right="0" top="0" bottom="0"/><hp:imgDim dimwidth="${w}" dimheight="${h}"/><hc:img binaryItemIDRef="${part.itemId}" bright="0" contrast="0" effect="REAL_PIC" alpha="0"/><hp:effects/><hp:sz width="${w}" widthRelTo="ABSOLUTE" height="${h}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="1" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="0" right="0" top="0" bottom="0"/></hp:pic>`;
24547
24787
  }
24548
24788
  };
24549
24789
  var MD_IMAGE_RE = /!\[[^\]]*\]\(([^)\s]+)\)/g;
@@ -25430,7 +25670,7 @@ function generateEquationParagraph(input, zOrder = 0) {
25430
25670
  }
25431
25671
 
25432
25672
  // src/hwpx/gen-section.ts
25433
- function generateSecPr(gongmun) {
25673
+ function generateSecPr(gongmun, page = null) {
25434
25674
  const m = gongmun ? {
25435
25675
  top: mmToHwpunit(gongmun.margins.top),
25436
25676
  bottom: mmToHwpunit(gongmun.margins.bottom),
@@ -25443,13 +25683,15 @@ function generateSecPr(gongmun) {
25443
25683
  m.header = gongmun.headerFooter;
25444
25684
  m.footer = gongmun.headerFooter;
25445
25685
  }
25446
- const secPr = `<hp:secPr textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="1" memoShapeIDRef="0" textVerticalWidthHead="0" masterPageCnt="0"><hp:grid lineGrid="0" charGrid="0" wonggojiFormat="0"/><hp:startNum pageStartsOn="BOTH" page="0" pic="0" tbl="0" equation="0"/><hp:visibility hideFirstHeader="0" hideFirstFooter="0" hideFirstMasterPage="0" border="SHOW_ALL" fill="SHOW_ALL" hideFirstPageNum="0" hideFirstEmptyLine="0" showLineNumber="0"/><hp:pagePr landscape="WIDELY" width="${A4_W_HU}" height="${A4_H_HU}" gutterType="LEFT_ONLY"><hp:margin header="${m.header}" footer="${m.footer}" gutter="0" left="${m.left}" right="${m.right}" top="${m.top}" bottom="${m.bottom}"/></hp:pagePr><hp:footNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="-1" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="283" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="EACH_COLUMN" beneathText="0"/></hp:footNotePr><hp:endNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="14692344" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="0" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="END_OF_DOCUMENT" beneathText="0"/></hp:endNotePr></hp:secPr>`;
25447
- const colPr = `<hp:ctrl><hp:colPr id="" type="NEWSPAPER" layout="LEFT" colCount="1" sameSz="1" sameGap="0"/></hp:ctrl>`;
25448
- return secPr + colPr + (gongmun?.pageNumbers ? pageNumCtrl() : "");
25686
+ const secPr = `<hp:secPr textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="1" memoShapeIDRef="0" textVerticalWidthHead="0" masterPageCnt="0"><hp:grid lineGrid="0" charGrid="0" wonggojiFormat="0"/><hp:startNum pageStartsOn="BOTH" page="0" pic="0" tbl="0" equation="0"/><hp:visibility hideFirstHeader="0" hideFirstFooter="0" hideFirstMasterPage="0" border="SHOW_ALL" fill="SHOW_ALL" hideFirstPageNum="0" hideFirstEmptyLine="0" showLineNumber="0"/><hp:pagePr landscape="${page?.landscape ?? "WIDELY"}" width="${page?.widthHU ?? A4_W_HU}" height="${page?.heightHU ?? A4_H_HU}" gutterType="LEFT_ONLY"><hp:margin header="${m.header}" footer="${m.footer}" gutter="0" left="${m.left}" right="${m.right}" top="${m.top}" bottom="${m.bottom}"/></hp:pagePr><hp:footNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="-1" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="283" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="EACH_COLUMN" beneathText="0"/></hp:footNotePr><hp:endNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="14692344" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="0" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="END_OF_DOCUMENT" beneathText="0"/></hp:endNotePr></hp:secPr>`;
25687
+ const colPr = columnColPrXml(page?.columns ?? 1);
25688
+ const hf = (page?.header ? headerFooterCtrl("header", page.header, 1) : "") + (page?.footer ? headerFooterCtrl("footer", page.footer, 2) : "");
25689
+ return secPr + colPr + hf + (gongmun?.pageNumbers ? pageNumCtrl() : "");
25449
25690
  }
25450
25691
  var SectionOpener = class {
25451
- constructor(gongmun) {
25692
+ constructor(gongmun, page = null) {
25452
25693
  this.gongmun = gongmun;
25694
+ this.page = page;
25453
25695
  }
25454
25696
  pending = true;
25455
25697
  /** 아직 secPr를 나를 첫 문단이 안 나왔는가 */
@@ -25461,7 +25703,7 @@ var SectionOpener = class {
25461
25703
  this.pending = false;
25462
25704
  return xml.replace(
25463
25705
  /<hp:run charPrIDRef="(\d+)">/,
25464
- `<hp:run charPrIDRef="$1">${generateSecPr(this.gongmun)}`
25706
+ `<hp:run charPrIDRef="$1">${generateSecPr(this.gongmun, this.page)}`
25465
25707
  );
25466
25708
  }
25467
25709
  /**
@@ -25471,13 +25713,13 @@ var SectionOpener = class {
25471
25713
  emitCarrier(paraXmls) {
25472
25714
  if (!this.pending) return;
25473
25715
  this.pending = false;
25474
- const secRun = `<hp:run charPrIDRef="0">${generateSecPr(this.gongmun)}<hp:t></hp:t></hp:run>`;
25716
+ const secRun = `<hp:run charPrIDRef="0">${generateSecPr(this.gongmun, this.page)}<hp:t></hp:t></hp:run>`;
25475
25717
  paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
25476
25718
  }
25477
25719
  /** 빈 문서 폴백 — secPr를 실은 빈 단락 XML */
25478
25720
  emptyDoc() {
25479
25721
  this.pending = false;
25480
- return `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${generateSecPr(this.gongmun)}<hp:t></hp:t></hp:run></hp:p>`;
25722
+ return `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${generateSecPr(this.gongmun, this.page)}<hp:t></hp:t></hp:run></hp:p>`;
25481
25723
  }
25482
25724
  };
25483
25725
  function buildPreamble(blocks, ctx) {
@@ -25718,7 +25960,7 @@ function appendPostamble(blocks, ctx) {
25718
25960
  paraXmls.push(...buildPressContact(gongmun, dfIds, tableStyle.totalWidth, bfReg));
25719
25961
  }
25720
25962
  }
25721
- function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null, dfIds = null, images = null) {
25963
+ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, bfReg = null, remap = null, dfIds = null, images = null, page = null) {
25722
25964
  resetTableIds();
25723
25965
  resetGjTableIds();
25724
25966
  resetExtraTableIds();
@@ -25757,7 +25999,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
25757
25999
  // 개조식 장식표(표지·목차·장헤더·제목박스) 폭 스케일용 본문폭 — margins 오버라이드 대응
25758
26000
  gjBodyW: gongmun ? mmToHwpunit(210 - gongmun.margins.left - gongmun.margins.right) : GAEJOSIK_BASE_WIDTH,
25759
26001
  chamMap: (id) => id === CHAR_BOLD ? GJ_CHAR_CHAM_BOLD : id,
25760
- opener: new SectionOpener(gongmun),
26002
+ opener: new SectionOpener(gongmun, page),
25761
26003
  paraXmls: [],
25762
26004
  // 표 방출 순번 — 생성 성공 여부와 무관하게 '시도' 기준으로 센다. 실패한 표가 이후
25763
26005
  // 표들의 순번을 밀면 앵커 없는 프로필(손편집·구버전)의 table_index 매칭이 어긋난다.
@@ -25842,45 +26084,53 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
25842
26084
  async function markdownToHwpx(markdown, options) {
25843
26085
  const theme = resolveTheme(options?.theme);
25844
26086
  const gongmun = options?.gongmun ? resolveGongmun(options.gongmun) : null;
25845
- const measured = !!gongmun && usesReportFonts(gongmun.preset);
25846
- const richAssets = !!gongmun && needsGaejosikAssets(gongmun);
25847
- const blocks = parseMarkdownToBlocks(markdown);
25848
- const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
25849
- const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
25850
- const staticBfEnd = staticBorderFillNext(gongmun);
25851
- const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(richAssets, !!gongmun) + (fit?.variants?.length ?? 0) * 4, staticBfEnd, staticFontNext(gongmun)) : null;
25852
- const bfReg = gongmun ? new TableBfRegistry(staticBfEnd + (remap?.borderFillXmls.length ?? 0)) : null;
25853
- const dfActive = !!gongmun && docframeActive(gongmun);
25854
- const dfBase = charVariantBase(richAssets, !!gongmun) + (fit?.variants?.length ?? 0) * 4 + (remap?.charPrXmls.length ?? 0);
25855
- const dfIds = dfActive ? docframeIds(dfBase) : null;
25856
- const chartParts = [];
25857
- const images = new ImageRegistry();
25858
- const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap, dfIds, images);
25859
- if (remap && remap.tables.length > 0) {
25860
- const unused = remap.tables.filter((t) => !t.used).length;
25861
- if (unused === remap.tables.length) {
25862
- console.warn(`[kordoc] format profile: \uD504\uB85C\uD544 \uD45C ${unused}\uAC1C\uAC00 \uBB38\uC11C \uD45C\uC640 \uB9E4\uCE6D\uB418\uC9C0 \uC54A\uC544 \uBBF8\uC801\uC6A9 (\uD589\xB7\uC5F4/\uCCAB \uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58)`);
25863
- }
25864
- }
25865
- const extraBorderFills = [...remap?.borderFillXmls ?? [], ...bfReg?.emit() ?? []];
25866
- const zip = new JSZip8();
25867
- zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
25868
- zip.file("META-INF/container.xml", generateContainerXml());
25869
- zip.file("Contents/content.hpf", generateManifest(chartParts, images.manifestItems(), gongmun ? "gongmun" : "default"));
25870
- for (const part of images.parts) zip.file(part.name, part.data);
25871
- zip.file("Contents/header.xml", generateHeaderXml(
25872
- theme,
25873
- gongmun,
25874
- fit?.variants ?? [],
25875
- extraBorderFills,
25876
- [...remap?.charPrXmls ?? [], ...dfActive ? docframeCharPrXmls(dfBase, richAssets) : []],
25877
- gongmunList?.indentVariants ?? [],
25878
- remap?.fontFaces ?? []
25879
- ));
25880
- zip.file("Contents/section0.xml", sectionXml);
25881
- for (const part of chartParts) zip.file(part.name, part.xml);
25882
- zip.file("Preview/PrvText.txt", buildPrvText(blocks));
25883
- return await zip.generateAsync({ type: "arraybuffer" });
26087
+ const page = resolvePage(options?.page);
26088
+ const { md: md2, defs } = extractFootnoteDefs(markdown);
26089
+ beginInlineDoc(defs);
26090
+ try {
26091
+ const measured = !!gongmun && usesReportFonts(gongmun.preset);
26092
+ const richAssets = !!gongmun && needsGaejosikAssets(gongmun);
26093
+ const blocks = parseMarkdownToBlocks(md2);
26094
+ const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
26095
+ const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
26096
+ const staticBfEnd = staticBorderFillNext(gongmun);
26097
+ const remap = options?.profile ? buildProfileRemap(options.profile, charVariantBase(richAssets, !!gongmun) + (fit?.variants?.length ?? 0) * 4, staticBfEnd, staticFontNext(gongmun)) : null;
26098
+ const bfReg = gongmun ? new TableBfRegistry(staticBfEnd + (remap?.borderFillXmls.length ?? 0)) : null;
26099
+ const dfActive = !!gongmun && docframeActive(gongmun);
26100
+ const dfBase = charVariantBase(richAssets, !!gongmun) + (fit?.variants?.length ?? 0) * 4 + (remap?.charPrXmls.length ?? 0);
26101
+ const dfIds = dfActive ? docframeIds(dfBase) : null;
26102
+ const chartParts = [];
26103
+ const supplied = options?.images ? new Map(Object.entries(options.images).map(([k, v]) => [k, v instanceof Uint8Array ? v : new Uint8Array(v)])) : void 0;
26104
+ const images = new ImageRegistry(supplied);
26105
+ const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, bfReg, remap, dfIds, images, page);
26106
+ if (remap && remap.tables.length > 0) {
26107
+ const unused = remap.tables.filter((t) => !t.used).length;
26108
+ if (unused === remap.tables.length) {
26109
+ console.warn(`[kordoc] format profile: \uD504\uB85C\uD544 \uD45C ${unused}\uAC1C\uAC00 \uBB38\uC11C \uD45C\uC640 \uB9E4\uCE6D\uB418\uC9C0 \uC54A\uC544 \uBBF8\uC801\uC6A9 (\uD589\xB7\uC5F4/\uCCAB \uC140 \uD14D\uC2A4\uD2B8 \uBD88\uC77C\uCE58)`);
26110
+ }
26111
+ }
26112
+ const extraBorderFills = [...remap?.borderFillXmls ?? [], ...bfReg?.emit() ?? []];
26113
+ const zip = new JSZip8();
26114
+ zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
26115
+ zip.file("META-INF/container.xml", generateContainerXml());
26116
+ zip.file("Contents/content.hpf", generateManifest(chartParts, images.manifestItems(), gongmun ? "gongmun" : "default"));
26117
+ for (const part of images.parts) zip.file(part.name, part.data);
26118
+ zip.file("Contents/header.xml", generateHeaderXml(
26119
+ theme,
26120
+ gongmun,
26121
+ fit?.variants ?? [],
26122
+ extraBorderFills,
26123
+ [...remap?.charPrXmls ?? [], ...dfActive ? docframeCharPrXmls(dfBase, richAssets) : []],
26124
+ gongmunList?.indentVariants ?? [],
26125
+ remap?.fontFaces ?? []
26126
+ ));
26127
+ zip.file("Contents/section0.xml", sectionXml);
26128
+ for (const part of chartParts) zip.file(part.name, part.xml);
26129
+ zip.file("Preview/PrvText.txt", buildPrvText(blocks));
26130
+ return await zip.generateAsync({ type: "arraybuffer" });
26131
+ } finally {
26132
+ endInlineDoc();
26133
+ }
25884
26134
  }
25885
26135
 
25886
26136
  // src/diff/compare.ts
@@ -31062,7 +31312,7 @@ async function parse(input, options) {
31062
31312
  }
31063
31313
  async function parseImage(buffer, options) {
31064
31314
  try {
31065
- const { parseImageDocument } = await import("./image-ocr-AHHY42OI.js");
31315
+ const { parseImageDocument } = await import("./image-ocr-C6U7YHRC.js");
31066
31316
  const { blocks, warnings } = await parseImageDocument(buffer, options);
31067
31317
  return {
31068
31318
  success: true,
@@ -31121,7 +31371,7 @@ async function parseHwp(buffer, options) {
31121
31371
  async function parsePdf(buffer, options) {
31122
31372
  let parsePdfDocument;
31123
31373
  try {
31124
- const mod = await import("./parser-IPVY56U3.js");
31374
+ const mod = await import("./parser-SHM3JEH6.js");
31125
31375
  parsePdfDocument = mod.parsePdfDocument;
31126
31376
  } catch {
31127
31377
  return {