kordoc 4.18.1 → 4.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/README.md +7 -6
  2. package/dist/{-X4KTLQC6.js → -I3CP33G4.js} +13 -11
  3. package/dist/{chunk-NQR3VKWN.js → chunk-4B2EXELH.js} +2 -2
  4. package/dist/{chunk-SQQ4ITJ5.js → chunk-6OKBTY72.js} +2 -2
  5. package/dist/{chunk-HUGBJVAA.js → chunk-B2E6C2LH.js} +12 -7
  6. package/dist/chunk-B2E6C2LH.js.map +1 -0
  7. package/dist/{chunk-X625PCZM.js → chunk-BL7KRE6X.js} +3 -3
  8. package/dist/{chunk-5PNQIF3V.js → chunk-C2CVOC5K.js} +4 -4
  9. package/dist/{chunk-AQUNBGXH.js → chunk-CKUIFTXJ.js} +2 -2
  10. package/dist/{chunk-TMC4A3FM.js → chunk-F5HING4Y.js} +10 -5
  11. package/dist/chunk-F5HING4Y.js.map +1 -0
  12. package/dist/{chunk-PWRY4W6Q.js → chunk-GM7XIZF2.js} +2 -2
  13. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  14. package/dist/{chunk-K35WIYBD.js → chunk-IA3UKDHA.js} +4 -4
  15. package/dist/chunk-IA3UKDHA.js.map +1 -0
  16. package/dist/chunk-J55UQC5H.cjs.map +1 -1
  17. package/dist/{chunk-7DC2KL3V.cjs → chunk-KDMAYOWH.cjs} +158 -43
  18. package/dist/chunk-KDMAYOWH.cjs.map +1 -0
  19. package/dist/{chunk-Z4KCEERM.js → chunk-L5RLJPI3.js} +3 -3
  20. package/dist/{chunk-WWOTHS2E.js → chunk-L64QRUMK.js} +202 -7
  21. package/dist/chunk-L64QRUMK.js.map +1 -0
  22. package/dist/{chunk-6N5BOPJI.js → chunk-LACO375L.js} +2 -2
  23. package/dist/{chunk-KXR4CTFT.js → chunk-LSOD2A6N.js} +2 -2
  24. package/dist/{chunk-UTVMLJZE.js → chunk-M4P7YS2N.js} +389 -57
  25. package/dist/chunk-M4P7YS2N.js.map +1 -0
  26. package/dist/{chunk-VDIXNEWV.js → chunk-N5DQFA7L.js} +2 -2
  27. package/dist/{chunk-R2IFWAHI.js → chunk-NZM2SSI4.js} +2 -2
  28. package/dist/{chunk-KBZ3MQJX.js → chunk-O2DI4GHD.js} +2 -2
  29. package/dist/{chunk-I7YWXECO.js → chunk-OBILAVWC.js} +2 -2
  30. package/dist/{chunk-6V7QRQY3.js → chunk-OGAYGUJF.js} +122 -87
  31. package/dist/chunk-OGAYGUJF.js.map +1 -0
  32. package/dist/{chunk-IUMV45TX.cjs → chunk-OI5ZSSIC.cjs} +12 -12
  33. package/dist/chunk-OI5ZSSIC.cjs.map +1 -0
  34. package/dist/{chunk-Q5N4YS3T.cjs → chunk-QGFZU3JE.cjs} +16 -11
  35. package/dist/chunk-QGFZU3JE.cjs.map +1 -0
  36. package/dist/{chunk-2VFZQ634.js → chunk-QP7IXF7R.js} +2 -2
  37. package/dist/{chunk-CWJ5KY2F.js → chunk-T4MXCSBP.js} +137 -27
  38. package/dist/chunk-T4MXCSBP.js.map +1 -0
  39. package/dist/{chunk-PCSOJ523.cjs → chunk-UZGZRGYM.cjs} +2 -2
  40. package/dist/chunk-UZGZRGYM.cjs.map +1 -0
  41. package/dist/{chunk-MTTYJEKA.js → chunk-VSY5PAJ5.js} +2 -2
  42. package/dist/{chunk-IXAXI2S3.cjs → chunk-W2YYBPW5.cjs} +3 -3
  43. package/dist/chunk-W2YYBPW5.cjs.map +1 -0
  44. package/dist/{chunk-SIZ63E5G.cjs → chunk-YNLW6EGU.cjs} +3 -3
  45. package/dist/chunk-YNLW6EGU.cjs.map +1 -0
  46. package/dist/chunks-IFFRC5IQ.js +10 -0
  47. package/dist/cli.js +26 -26
  48. package/dist/{formula-LICM6K27.js → formula-AQZODKZF.js} +3 -3
  49. package/dist/{formula-T4Q2UHWO.js → formula-E3N7KDDG.js} +4 -4
  50. package/dist/{formula-W3GQC6L6.cjs → formula-VY4ITOMN.cjs} +9 -9
  51. package/dist/formula-VY4ITOMN.cjs.map +1 -0
  52. package/dist/{image-ocr-7PNHBD2G.cjs → image-ocr-6LYEBMVR.cjs} +15 -15
  53. package/dist/image-ocr-6LYEBMVR.cjs.map +1 -0
  54. package/dist/{image-ocr-WZJURDX6.js → image-ocr-IMYXOHHV.js} +6 -6
  55. package/dist/{image-ocr-XB2NFKGZ.js → image-ocr-LN3GSQPW.js} +9 -9
  56. package/dist/index.cjs +1037 -603
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.cts +7 -5
  59. package/dist/index.d.ts +7 -5
  60. package/dist/index.js +523 -89
  61. package/dist/index.js.map +1 -1
  62. package/dist/mcp.js +26 -27
  63. package/dist/mcp.js.map +1 -1
  64. package/dist/{model-bundle-O2XYR54X.js → model-bundle-IHKNDLOT.js} +5 -5
  65. package/dist/{models-SKK3NH3V.js → models-YXITRAMR.js} +5 -5
  66. package/dist/page-range-QHHFTL7X.cjs.map +1 -1
  67. package/dist/{parser-PJUZSMFR.cjs → parser-7KECZTTP.cjs} +176 -228
  68. package/dist/parser-7KECZTTP.cjs.map +1 -0
  69. package/dist/{parser-4D2M5BKY.js → parser-KB4BYQBZ.js} +14 -66
  70. package/dist/parser-KB4BYQBZ.js.map +1 -0
  71. package/dist/{parser-5G5G7HHG.js → parser-M3T2EWUN.js} +11 -63
  72. package/dist/parser-M3T2EWUN.js.map +1 -0
  73. package/dist/pdf-ocr-4S2OAHUX.js +15 -0
  74. package/dist/pdf-ocr-IGYCZ7G2.cjs +16 -0
  75. package/dist/pdf-ocr-IGYCZ7G2.cjs.map +1 -0
  76. package/dist/pdf-ocr-YEBFWU2K.js +19 -0
  77. package/dist/{profile-io-BAQTYPK7.js → profile-io-GQWQR7YQ.js} +3 -3
  78. package/dist/{rasterize-A2ZEACKV.js → rasterize-Y6TVFQ3M.js} +3 -3
  79. package/dist/{redact-doc-26KN2LSZ.js → redact-doc-TRPZ3HNW.js} +11 -11
  80. package/dist/{render-62ZUDMHB.js → render-GHT5HKBO.js} +7 -7
  81. package/dist/seal-3YTXSABW.js +10 -0
  82. package/dist/{setup-2A3E6WRE.js → setup-AGSCEHDB.js} +3 -3
  83. package/dist/visual-R3E35Q2K.js +20 -0
  84. package/dist/{watch-D2T5FEKT.js → watch-ALSEW4GB.js} +13 -13
  85. package/dist/watch-ALSEW4GB.js.map +1 -0
  86. package/package.json +1 -1
  87. package/dist/chunk-6V7QRQY3.js.map +0 -1
  88. package/dist/chunk-7DC2KL3V.cjs.map +0 -1
  89. package/dist/chunk-CWJ5KY2F.js.map +0 -1
  90. package/dist/chunk-HUGBJVAA.js.map +0 -1
  91. package/dist/chunk-IUMV45TX.cjs.map +0 -1
  92. package/dist/chunk-IXAXI2S3.cjs.map +0 -1
  93. package/dist/chunk-K35WIYBD.js.map +0 -1
  94. package/dist/chunk-PCSOJ523.cjs.map +0 -1
  95. package/dist/chunk-Q5N4YS3T.cjs.map +0 -1
  96. package/dist/chunk-SIZ63E5G.cjs.map +0 -1
  97. package/dist/chunk-TMC4A3FM.js.map +0 -1
  98. package/dist/chunk-UTVMLJZE.js.map +0 -1
  99. package/dist/chunk-WWOTHS2E.js.map +0 -1
  100. package/dist/chunks-ACUC63N3.js +0 -10
  101. package/dist/formula-W3GQC6L6.cjs.map +0 -1
  102. package/dist/image-ocr-7PNHBD2G.cjs.map +0 -1
  103. package/dist/parser-4D2M5BKY.js.map +0 -1
  104. package/dist/parser-5G5G7HHG.js.map +0 -1
  105. package/dist/parser-PJUZSMFR.cjs.map +0 -1
  106. package/dist/pdf-ocr-EGWOIB6O.cjs +0 -16
  107. package/dist/pdf-ocr-EGWOIB6O.cjs.map +0 -1
  108. package/dist/pdf-ocr-NJTFXBRC.js +0 -19
  109. package/dist/pdf-ocr-ZXR6Q6BK.js +0 -15
  110. package/dist/seal-3GXC2API.js +0 -10
  111. package/dist/visual-4ZBZRMCM.js +0 -20
  112. package/dist/watch-D2T5FEKT.js.map +0 -1
  113. /package/dist/{-X4KTLQC6.js.map → -I3CP33G4.js.map} +0 -0
  114. /package/dist/{chunk-NQR3VKWN.js.map → chunk-4B2EXELH.js.map} +0 -0
  115. /package/dist/{chunk-SQQ4ITJ5.js.map → chunk-6OKBTY72.js.map} +0 -0
  116. /package/dist/{chunk-X625PCZM.js.map → chunk-BL7KRE6X.js.map} +0 -0
  117. /package/dist/{chunk-5PNQIF3V.js.map → chunk-C2CVOC5K.js.map} +0 -0
  118. /package/dist/{chunk-AQUNBGXH.js.map → chunk-CKUIFTXJ.js.map} +0 -0
  119. /package/dist/{chunk-PWRY4W6Q.js.map → chunk-GM7XIZF2.js.map} +0 -0
  120. /package/dist/{chunk-Z4KCEERM.js.map → chunk-L5RLJPI3.js.map} +0 -0
  121. /package/dist/{chunk-6N5BOPJI.js.map → chunk-LACO375L.js.map} +0 -0
  122. /package/dist/{chunk-KXR4CTFT.js.map → chunk-LSOD2A6N.js.map} +0 -0
  123. /package/dist/{chunk-VDIXNEWV.js.map → chunk-N5DQFA7L.js.map} +0 -0
  124. /package/dist/{chunk-R2IFWAHI.js.map → chunk-NZM2SSI4.js.map} +0 -0
  125. /package/dist/{chunk-KBZ3MQJX.js.map → chunk-O2DI4GHD.js.map} +0 -0
  126. /package/dist/{chunk-I7YWXECO.js.map → chunk-OBILAVWC.js.map} +0 -0
  127. /package/dist/{chunk-2VFZQ634.js.map → chunk-QP7IXF7R.js.map} +0 -0
  128. /package/dist/{chunk-MTTYJEKA.js.map → chunk-VSY5PAJ5.js.map} +0 -0
  129. /package/dist/{chunks-ACUC63N3.js.map → chunks-IFFRC5IQ.js.map} +0 -0
  130. /package/dist/{formula-LICM6K27.js.map → formula-AQZODKZF.js.map} +0 -0
  131. /package/dist/{formula-T4Q2UHWO.js.map → formula-E3N7KDDG.js.map} +0 -0
  132. /package/dist/{image-ocr-WZJURDX6.js.map → image-ocr-IMYXOHHV.js.map} +0 -0
  133. /package/dist/{image-ocr-XB2NFKGZ.js.map → image-ocr-LN3GSQPW.js.map} +0 -0
  134. /package/dist/{model-bundle-O2XYR54X.js.map → model-bundle-IHKNDLOT.js.map} +0 -0
  135. /package/dist/{models-SKK3NH3V.js.map → models-YXITRAMR.js.map} +0 -0
  136. /package/dist/{pdf-ocr-NJTFXBRC.js.map → pdf-ocr-4S2OAHUX.js.map} +0 -0
  137. /package/dist/{pdf-ocr-ZXR6Q6BK.js.map → pdf-ocr-YEBFWU2K.js.map} +0 -0
  138. /package/dist/{profile-io-BAQTYPK7.js.map → profile-io-GQWQR7YQ.js.map} +0 -0
  139. /package/dist/{rasterize-A2ZEACKV.js.map → rasterize-Y6TVFQ3M.js.map} +0 -0
  140. /package/dist/{redact-doc-26KN2LSZ.js.map → redact-doc-TRPZ3HNW.js.map} +0 -0
  141. /package/dist/{render-62ZUDMHB.js.map → render-GHT5HKBO.js.map} +0 -0
  142. /package/dist/{seal-3GXC2API.js.map → seal-3YTXSABW.js.map} +0 -0
  143. /package/dist/{setup-2A3E6WRE.js.map → setup-AGSCEHDB.js.map} +0 -0
  144. /package/dist/{visual-4ZBZRMCM.js.map → visual-R3E35Q2K.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  blocksToPages
4
- } from "./chunk-PWRY4W6Q.js";
4
+ } from "./chunk-GM7XIZF2.js";
5
5
  import {
6
6
  allLinesegRemovalSplices,
7
7
  applySplices,
@@ -15,7 +15,7 @@ import {
15
15
  paraTextPureT,
16
16
  patchZipEntries,
17
17
  scanSectionXml
18
- } from "./chunk-Z4KCEERM.js";
18
+ } from "./chunk-L5RLJPI3.js";
19
19
  import {
20
20
  CONVERT_MAP,
21
21
  FLAG_COMPRESSED,
@@ -31,6 +31,8 @@ import {
31
31
  TAG_PARA_HEADER,
32
32
  TAG_PARA_TEXT,
33
33
  TAG_TABLE,
34
+ TOC_ENTRY_BLOCKS,
35
+ TOC_LEADER,
34
36
  appendParaText,
35
37
  blocksPlainText,
36
38
  buildAddressedTable,
@@ -61,19 +63,21 @@ import {
61
63
  prepareWrap,
62
64
  renderDocumentToScene,
63
65
  romanNumeral,
64
- simulateWrap
65
- } from "./chunk-CWJ5KY2F.js";
66
+ simulateWrap,
67
+ takeTocLeaders
68
+ } from "./chunk-T4MXCSBP.js";
66
69
  import {
67
70
  CELL_EDGES,
68
71
  HEADING_RATIO_H1,
69
72
  HEADING_RATIO_H2,
70
73
  HEADING_RATIO_H3,
74
+ escapeLiteralTags,
71
75
  plainScripts,
72
76
  stripScriptTags,
73
77
  tidyScriptTags,
74
78
  unframeLayoutTables,
75
79
  wrapScript
76
- } from "./chunk-TMC4A3FM.js";
80
+ } from "./chunk-F5HING4Y.js";
77
81
  import {
78
82
  parsePageRange
79
83
  } from "./chunk-VQFA55IC.js";
@@ -92,7 +96,7 @@ import {
92
96
  findChildByLocalName,
93
97
  localName,
94
98
  rawTextContent
95
- } from "./chunk-6N5BOPJI.js";
99
+ } from "./chunk-LACO375L.js";
96
100
  import {
97
101
  MAX_COLS,
98
102
  MAX_ROWS,
@@ -107,7 +111,7 @@ import {
107
111
  hasStructuredCellContent,
108
112
  mapPuaText,
109
113
  noteSuffix
110
- } from "./chunk-K35WIYBD.js";
114
+ } from "./chunk-IA3UKDHA.js";
111
115
  import {
112
116
  KordocError,
113
117
  classifyError,
@@ -122,20 +126,20 @@ import {
122
126
  toArrayBuffer,
123
127
  unescapeHtml,
124
128
  unzipLimitBytes
125
- } from "./chunk-I7YWXECO.js";
129
+ } from "./chunk-OBILAVWC.js";
126
130
 
127
131
  // src/table/visual.ts
128
132
  import { readFile as readFile2 } from "fs/promises";
129
133
 
130
134
  // src/plain-markdown.ts
131
135
  function toPlainMarkdown(md) {
132
- return plainScripts(md).replace(/!\[[^\]\n]*\]\([^)\n]*\)/g, "").replace(/<img\b[^>]*>/gi, "").replace(/(?<!!)\[([^\]\n]*)\]\((?:https?|mailto|ftp):[^)\s]*\)/g, "$1").replace(/<\/?u>/g, "").replace(/(?<!\\)\*\*(?=\S)([^\n]*?\S)(?<!\\)\*\*/g, "$1").replace(/(<br>)+(?=<\/t[dh]>)/g, "").replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
136
+ return plainScripts(md).replace(/!\[[^\]\n]*\]\([^)\n]*\)/g, "").replace(/<img\b[^>]*>/gi, "").replace(/(?<!!)\[([^\]\n]*)\]\((?:https?|mailto|ftp):[^)\s]*\)/g, "$1").replace(/(?<!\\)<\/?u>/g, "").replace(/(?<!\\)\*\*(?=\S)([^\n]*?\S)(?<!\\)\*\*/g, "$1").replace(/(<br>)+(?=<\/t[dh]>)/g, "").replace(/[ \t]+$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
133
137
  }
134
138
 
135
139
  // src/html-tables.ts
136
140
  var TABLE_TAG = /(<\/?(?:table|tr|th|td)\b[^>]*>)/i;
137
141
  function pipeCellToHtml(cell2) {
138
- return cell2.split(/(<br>|<\/?(?:u|sup|sub)>|<img\b[^>]*>)/).map((part, i) => i % 2 ? part : part.replace(/\\([\\`*_{}[\]()#+\-.!|~<>$])/g, "$1").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")).join("");
142
+ return cell2.split(/(<br>|(?<!\\)<\/?(?:u|sup|sub)>|<img\b[^>]*>)/).map((part, i) => i % 2 ? part : part.replace(/\\([\\`*_{}[\]()#+\-.!|~<>$])/g, "$1").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")).join("");
139
143
  }
140
144
  function splitPipeRow(line) {
141
145
  const t = line.trim().replace(/^\|/, "").replace(/(?<!\\)\|$/, "");
@@ -645,7 +649,7 @@ function detectHwpxHeadings(blocks, styleMap) {
645
649
  }
646
650
  }
647
651
  for (const block of blocks) {
648
- if (block.type !== "paragraph" || !block.text) continue;
652
+ if (block.type !== "paragraph" || !block.text || TOC_ENTRY_BLOCKS.has(block)) continue;
649
653
  const text = block.text.trim();
650
654
  if (text.length === 0 || text.length > 200 || /^\d+$/.test(text)) continue;
651
655
  let level = 0;
@@ -1183,7 +1187,7 @@ function extractRunSpans(para2, ctx, mode, requireMixed) {
1183
1187
  const tkids = rc.childNodes;
1184
1188
  for (let k = 0; k < (tkids?.length ?? 0); k++) {
1185
1189
  const tk = tkids[k];
1186
- if (tk.nodeType === 3 || tk.nodeType === 4) text += escapeLiteralDollar(tk.textContent || "");
1190
+ if (tk.nodeType === 3 || tk.nodeType === 4) text += escapeLiteralTags(escapeLiteralDollar(tk.textContent || ""));
1187
1191
  else if (tk.nodeType === 1) {
1188
1192
  const ttag = (tk.tagName || tk.localName || "").replace(/^[^:]+:/, "");
1189
1193
  if (ttag === "tab" || ttag === "fwSpace" || ttag === "hwSpace" || ttag === "nbSpace") text += " ";
@@ -1356,13 +1360,13 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1356
1360
  case "p": {
1357
1361
  const paraPg = ctx.paraPage?.get(el);
1358
1362
  if (paraPg !== void 0 && ctx.pageBase !== void 0) ctx.page = ctx.pageBase + paraPg + 1;
1359
- const { text: rawText, href, footnote, style, segments, placeholderSpans } = extractParagraphInfo(el, ctx.styleMap, ctx);
1363
+ const { text: rawText, href, footnote, style, segments, placeholderSpans, tocEntry } = extractParagraphInfo(el, ctx.styleMap, ctx);
1360
1364
  let text = rawText;
1361
1365
  let headingLevel;
1362
1366
  const ph = resolveParaHeading(el, ctx);
1363
1367
  if (text) {
1364
1368
  if (ph?.prefix) text = ph.prefix + " " + text;
1365
- headingLevel = ph?.headingLevel;
1369
+ headingLevel = tocEntry ? void 0 : ph?.headingLevel;
1366
1370
  }
1367
1371
  if (segments) {
1368
1372
  const cell2 = tableCtx?.cell ?? null;
@@ -1424,6 +1428,7 @@ function walkSection(node, blocks, tableCtx, tableStack, ctx, depth = 0) {
1424
1428
  }
1425
1429
  const block = { type: headingLevel ? "heading" : "paragraph", text, pageNumber: ctx.page };
1426
1430
  if (headingLevel) block.level = headingLevel;
1431
+ if (tocEntry) TOC_ENTRY_BLOCKS.add(block);
1427
1432
  if (style) block.style = style;
1428
1433
  if (href) block.href = href;
1429
1434
  if (footnote) block.footnoteText = footnote;
@@ -1856,7 +1861,7 @@ function extractParagraphInfo(para2, styleMap, ctx) {
1856
1861
  const open = openFields.pop();
1857
1862
  if (open?.rangeIdx !== void 0) linkRanges[open.rangeIdx].end = text.length;
1858
1863
  if (open?.guide !== void 0 && open.start !== void 0) {
1859
- const value = text.slice(open.start).replace(/\\\$/g, "$");
1864
+ const value = text.slice(open.start).replace(/\\([$<])/g, "$1");
1860
1865
  if (value && (value === open.guide || value.trimEnd() === open.guide)) {
1861
1866
  text = text.slice(0, open.start) + PH_OPEN + text.slice(open.start) + PH_CLOSE;
1862
1867
  }
@@ -1965,7 +1970,7 @@ function extractParagraphInfo(para2, styleMap, ctx) {
1965
1970
  ctx.warnings?.push({ page: ctx.page, message: "\uBCC0\uACBD\uCD94\uC801 \uC0AD\uC81C \uD14D\uC2A4\uD2B8 \uCD9C\uB825 \uC81C\uC678", code: "HIDDEN_TEXT_FILTERED" });
1966
1971
  }
1967
1972
  } else {
1968
- text += escapeLiteralDollar(t.replace(/\x1E/g, ""));
1973
+ text += escapeLiteralTags(escapeLiteralDollar(t.replace(/\x1E/g, "")));
1969
1974
  }
1970
1975
  continue;
1971
1976
  }
@@ -1985,8 +1990,9 @@ function extractParagraphInfo(para2, styleMap, ctx) {
1985
1990
  // 점 채움을 탭 하나로 바꾸고 쪽 번호를 남기는 것과 같다). 종전엔 채움 탭 뒤를 쪽 번호로 보고 잘라, 목차 쪽 번호만이 아니라
1986
1991
  // 일정표 "사용자 의견조사 ····· '26년 8~9월"(gate-fill 36646162)의 일정, 줄바꿈 뒤 다음 목차 항목
1987
1992
  // "<참고2> 직종별사업체노동력조사 개요"(rhwp issue6044)까지 사라졌다
1993
+ // (채움 탭은 목차 항목 판정까지 TOC_LEADER 표지로 들고 가다 보통 탭으로 바꾼다 — toc-entry.ts)
1988
1994
  case "tab":
1989
- text += " ";
1995
+ text += /^(?:|0|NONE)$/i.test(child.getAttribute("leader") ?? "") ? " " : TOC_LEADER;
1990
1996
  break;
1991
1997
  case "br":
1992
1998
  if ((child.getAttribute("type") || "line") === "line") text += "\n";
@@ -2133,6 +2139,9 @@ function extractParagraphInfo(para2, styleMap, ctx) {
2133
2139
  if (applied.length) href = void 0;
2134
2140
  }
2135
2141
  text = tidyScriptTags(text);
2142
+ const toc = takeTocLeaders(text);
2143
+ text = toc.text;
2144
+ const tocEntry = toc.tocEntry;
2136
2145
  const cleanParaText = (raw) => {
2137
2146
  let t = raw.replace(/[ \t]+/g, " ").trim();
2138
2147
  if (/^그림입니다\.?\s*원본\s*그림의\s*(이름|크기)/.test(t)) t = "";
@@ -2168,7 +2177,7 @@ function extractParagraphInfo(para2, styleMap, ctx) {
2168
2177
  if (!style.fontSize && !style.bold && !style.italic) style = void 0;
2169
2178
  }
2170
2179
  }
2171
- return { text: cleanText, href, footnote, style, segments, placeholderSpans };
2180
+ return { text: cleanText, href, footnote, style, segments, placeholderSpans, ...tocEntry ? { tocEntry } : {} };
2172
2181
  }
2173
2182
  function withPrefixSpan(spans, prefix) {
2174
2183
  return prefix ? [{ text: prefix + " " }, ...spans] : spans;
@@ -15384,7 +15393,7 @@ function parseCharStream(reader, charCount, ctx, para2) {
15384
15393
  continue;
15385
15394
  }
15386
15395
  if (ch >= 32) {
15387
- para2.text += escapeLiteralDollar(decodeJohabText(ch) ?? "");
15396
+ para2.text += escapeLiteralTags(escapeLiteralDollar(decodeJohabText(ch) ?? ""));
15388
15397
  continue;
15389
15398
  }
15390
15399
  if (ch === 9) {
@@ -15732,7 +15741,7 @@ function collectRichText(root) {
15732
15741
  const el = children[i];
15733
15742
  const local = el.localName || el.tagName?.replace(/^[^:]+:/, "") || "";
15734
15743
  if (local === "rPh") continue;
15735
- if (local === "t") out += el.textContent ?? "";
15744
+ if (local === "t") out += escapeLiteralTags(el.textContent ?? "");
15736
15745
  else walk(el);
15737
15746
  }
15738
15747
  };
@@ -16356,14 +16365,14 @@ function extractSheetCells(records, bofIndex, sst, convertNum) {
16356
16365
  const h = readCellHeader(rec.data);
16357
16366
  if (h && rec.data.length >= 10) {
16358
16367
  const isst = rec.data.readUInt32LE(6);
16359
- cells.push({ row: h.row, col: h.col, value: sst[isst] ?? "" });
16368
+ cells.push({ row: h.row, col: h.col, value: escapeLiteralTags(sst[isst] ?? "") });
16360
16369
  }
16361
16370
  break;
16362
16371
  }
16363
16372
  case OP_LABEL: {
16364
16373
  const h = readCellHeader(rec.data);
16365
16374
  if (h) {
16366
- cells.push({ row: h.row, col: h.col, value: decodeLabelString(rec.data) });
16375
+ cells.push({ row: h.row, col: h.col, value: escapeLiteralTags(decodeLabelString(rec.data)) });
16367
16376
  }
16368
16377
  break;
16369
16378
  }
@@ -16379,7 +16388,7 @@ function extractSheetCells(records, bofIndex, sst, convertNum) {
16379
16388
  cells.push({
16380
16389
  row: h.row,
16381
16390
  col: h.col,
16382
- value: decodeFormulaStringRecord(next.data)
16391
+ value: escapeLiteralTags(decodeFormulaStringRecord(next.data))
16383
16392
  });
16384
16393
  i = j;
16385
16394
  } else {
@@ -17282,7 +17291,7 @@ function parseFootnotes(xml) {
17282
17291
  const runs = findElements(p, "r");
17283
17292
  for (const r of runs) {
17284
17293
  const tElements = getChildElements(r, "t");
17285
- for (const t of tElements) texts.push(t.textContent ?? "");
17294
+ for (const t of tElements) texts.push(escapeLiteralTags(t.textContent ?? ""));
17286
17295
  }
17287
17296
  }
17288
17297
  notes.set(id, texts.join("").trim());
@@ -17313,7 +17322,7 @@ function collectOmmlRoots(p) {
17313
17322
  function extractRun(r) {
17314
17323
  let text = "";
17315
17324
  for (const el of effectiveChildElements(r)) {
17316
- if (matchesLocal(el, "t")) text += el.textContent ?? "";
17325
+ if (matchesLocal(el, "t")) text += escapeLiteralTags(el.textContent ?? "");
17317
17326
  else if (matchesLocal(el, "br") || matchesLocal(el, "cr")) text += "\n";
17318
17327
  else if (matchesLocal(el, "tab")) text += " ";
17319
17328
  else if (matchesLocal(el, "sym")) text += symbolChar(getAttr(el, "font"), getAttr(el, "char"));
@@ -17824,8 +17833,323 @@ async function parseDocxDocument(buffer, options) {
17824
17833
  };
17825
17834
  }
17826
17835
 
17827
- // src/hwpml/parser.ts
17836
+ // src/pptx/parser.ts
17837
+ import JSZip5 from "jszip";
17828
17838
  import { DOMParser as DOMParser3 } from "@xmldom/xmldom";
17839
+ var MAX_DECOMPRESS_SIZE5 = unzipLimitBytes(100 * 1024 * 1024);
17840
+ var MEDIA_PART_RE2 = /^ppt\/(?:media|embeddings)\//;
17841
+ var MAX_ZIP_ENTRIES2 = 1e4;
17842
+ var MAX_SLIDES = 2e3;
17843
+ var SKIP_PLACEHOLDERS = /* @__PURE__ */ new Set(["sldNum", "dt", "ftr", "hdr", "sldImg"]);
17844
+ var BULLET_PLACEHOLDERS = /* @__PURE__ */ new Set(["body", "obj"]);
17845
+ var REL_NOTES = "/notesSlide";
17846
+ var REL_IMAGE = "/image";
17847
+ var SLIDE_PART_RE = /^ppt\/slides\/slide(\d+)\.xml$/;
17848
+ var IMAGE_MIME = {
17849
+ png: "image/png",
17850
+ jpg: "image/jpeg",
17851
+ jpeg: "image/jpeg",
17852
+ gif: "image/gif",
17853
+ bmp: "image/bmp",
17854
+ wmf: "image/wmf",
17855
+ emf: "image/emf",
17856
+ tif: "image/tiff",
17857
+ tiff: "image/tiff",
17858
+ svg: "image/svg+xml"
17859
+ };
17860
+ function parseXml3(text) {
17861
+ return new DOMParser3().parseFromString(stripDtd(text), "text/xml");
17862
+ }
17863
+ function getAttr2(el, name) {
17864
+ const attrs = el.attributes;
17865
+ for (let i = 0; i < attrs.length; i++) {
17866
+ const attr = attrs[i];
17867
+ if (attr.localName === name || attr.name === name) return attr.value;
17868
+ }
17869
+ return null;
17870
+ }
17871
+ var NS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
17872
+ function getRelId(el) {
17873
+ const attrs = el.attributes;
17874
+ for (let i = 0; i < attrs.length; i++) {
17875
+ const attr = attrs[i];
17876
+ if (attr.localName === "id" && (attr.namespaceURI === NS_REL || attr.name === "r:id")) return attr.value;
17877
+ }
17878
+ return null;
17879
+ }
17880
+ function findPath(el, ...names) {
17881
+ for (const name of names) {
17882
+ if (!el) return null;
17883
+ el = findChildByLocalName(el, name);
17884
+ }
17885
+ return el;
17886
+ }
17887
+ function resolvePart(baseDir, target) {
17888
+ if (target.startsWith("/")) return target.slice(1);
17889
+ const parts = baseDir ? baseDir.split("/") : [];
17890
+ for (const seg of target.split("/")) {
17891
+ if (seg === "..") parts.pop();
17892
+ else if (seg && seg !== ".") parts.push(seg);
17893
+ }
17894
+ return parts.join("/");
17895
+ }
17896
+ async function readRels(zip, part) {
17897
+ const map = /* @__PURE__ */ new Map();
17898
+ const slash = part.lastIndexOf("/");
17899
+ const dir = slash >= 0 ? part.slice(0, slash) : "";
17900
+ const file = zip.file(`${dir ? dir + "/" : ""}_rels/${part.slice(slash + 1)}.rels`);
17901
+ if (!file) return map;
17902
+ const doc = parseXml3(await file.async("text"));
17903
+ for (const rel of childrenByLocalName(doc.documentElement, "Relationship")) {
17904
+ const id = getAttr2(rel, "Id");
17905
+ const target = getAttr2(rel, "Target");
17906
+ if (!id || !target || getAttr2(rel, "TargetMode") === "External") continue;
17907
+ map.set(id, { type: getAttr2(rel, "Type") ?? "", target: resolvePart(dir, target) });
17908
+ }
17909
+ return map;
17910
+ }
17911
+ async function slideParts(zip) {
17912
+ const ordered = [];
17913
+ const presFile = zip.file("ppt/presentation.xml");
17914
+ if (presFile) {
17915
+ const pres = parseXml3(await presFile.async("text"));
17916
+ const rels = await readRels(zip, "ppt/presentation.xml");
17917
+ const list = findChildByLocalName(pres.documentElement, "sldIdLst");
17918
+ for (const sld of list ? childrenByLocalName(list, "sldId") : []) {
17919
+ const target = rels.get(getRelId(sld) ?? "")?.target;
17920
+ if (target && zip.file(target)) ordered.push(target);
17921
+ }
17922
+ }
17923
+ if (ordered.length === 0) {
17924
+ const names = Object.keys(zip.files).filter((n) => SLIDE_PART_RE.test(n));
17925
+ names.sort((a, b) => Number(SLIDE_PART_RE.exec(a)[1]) - Number(SLIDE_PART_RE.exec(b)[1]));
17926
+ ordered.push(...names);
17927
+ }
17928
+ if (ordered.length > MAX_SLIDES) throw new KordocError(`PPTX \uC2AC\uB77C\uC774\uB4DC \uC218 \uCD08\uACFC: ${ordered.length} (\uCD5C\uB300 ${MAX_SLIDES})`);
17929
+ return ordered;
17930
+ }
17931
+ function paragraphText(p) {
17932
+ let text = "";
17933
+ for (const child of elementChildren(p)) {
17934
+ const name = localName(child);
17935
+ if (name === "r" || name === "fld") {
17936
+ const t = findChildByLocalName(child, "t");
17937
+ if (t) text += escapeLiteralTags(escapeLiteralDollar(rawTextContent(t)));
17938
+ } else if (name === "br") {
17939
+ text += " ";
17940
+ }
17941
+ }
17942
+ return text.replace(/\s+/g, " ").trim();
17943
+ }
17944
+ function bodyParagraphs(txBody) {
17945
+ const out = [];
17946
+ for (const p of childrenByLocalName(txBody, "p")) {
17947
+ const text = paragraphText(p);
17948
+ if (!text) continue;
17949
+ const pPr = findChildByLocalName(p, "pPr");
17950
+ let bullet;
17951
+ if (pPr) {
17952
+ if (findChildByLocalName(pPr, "buNone")) bullet = "none";
17953
+ else if (findChildByLocalName(pPr, "buAutoNum")) bullet = "ordered";
17954
+ else if (findChildByLocalName(pPr, "buChar") || findChildByLocalName(pPr, "buBlip")) bullet = "unordered";
17955
+ }
17956
+ const lvl = Math.max(0, parseInt(pPr ? getAttr2(pPr, "lvl") ?? "0" : "0", 10) || 0);
17957
+ out.push({ text, lvl, bullet });
17958
+ }
17959
+ return out;
17960
+ }
17961
+ function placeholderType(sp) {
17962
+ const ph = findPath(sp, "nvSpPr", "nvPr", "ph");
17963
+ return ph ? getAttr2(ph, "type") ?? "obj" : null;
17964
+ }
17965
+ function pushParagraphs(paras, bulletDefault, page, out) {
17966
+ let lastList = null;
17967
+ for (const para2 of paras) {
17968
+ const bullet = para2.bullet ?? (bulletDefault ? "unordered" : "none");
17969
+ if (bullet === "none") {
17970
+ out.push({ type: "paragraph", text: para2.text, pageNumber: page });
17971
+ lastList = null;
17972
+ continue;
17973
+ }
17974
+ const item = { type: "list", text: para2.text, listType: bullet, pageNumber: page };
17975
+ if (para2.lvl > 0 && lastList) {
17976
+ ;
17977
+ (lastList.children ??= []).push(item);
17978
+ } else {
17979
+ out.push(item);
17980
+ lastList = item;
17981
+ }
17982
+ }
17983
+ }
17984
+ function parseTable2(tbl2, page, keepEmptyCols) {
17985
+ const rows = childrenByLocalName(tbl2, "tr");
17986
+ if (rows.length === 0) return null;
17987
+ const cellRows = rows.map((tr, r) => {
17988
+ const cells = [];
17989
+ childrenByLocalName(tr, "tc").forEach((tc2, c) => {
17990
+ if (getAttr2(tc2, "hMerge") === "1" || getAttr2(tc2, "vMerge") === "1") return;
17991
+ const txBody = findChildByLocalName(tc2, "txBody");
17992
+ const text = txBody ? bodyParagraphs(txBody).map((p) => p.text).join("\n") : "";
17993
+ cells.push({
17994
+ text,
17995
+ colSpan: Math.max(1, parseInt(getAttr2(tc2, "gridSpan") ?? "1", 10) || 1),
17996
+ rowSpan: Math.max(1, parseInt(getAttr2(tc2, "rowSpan") ?? "1", 10) || 1),
17997
+ colAddr: c,
17998
+ rowAddr: r
17999
+ });
18000
+ });
18001
+ return cells;
18002
+ });
18003
+ const table2 = buildTable(cellRows, { keepAnchoredEmptyCols: keepEmptyCols });
18004
+ if (table2.rows === 0 || table2.cols === 0) return null;
18005
+ return { type: "table", table: table2, pageNumber: page };
18006
+ }
18007
+ async function pictureBlock(pic, ctx) {
18008
+ const blip = findPath(pic, "blipFill", "blip");
18009
+ const embed = blip ? getAttr2(blip, "embed") : null;
18010
+ const rel = embed ? ctx.rels.get(embed) : void 0;
18011
+ if (!rel || !rel.type.endsWith(REL_IMAGE)) return null;
18012
+ let filename = ctx.imageNames.get(rel.target);
18013
+ if (!filename) {
18014
+ const file = ctx.zip.file(rel.target);
18015
+ if (!file) return null;
18016
+ const ext = rel.target.split(".").pop()?.toLowerCase() ?? "png";
18017
+ filename = `image_${String(ctx.imageNames.size + 1).padStart(3, "0")}.${ext}`;
18018
+ try {
18019
+ if (ctx.options?.images !== false) {
18020
+ const data = await file.async("uint8array");
18021
+ ctx.images.push({ filename, data, mimeType: IMAGE_MIME[ext] ?? detectImageMime(data) ?? "application/octet-stream", source: rel.target });
18022
+ }
18023
+ } catch (err) {
18024
+ ctx.warnings.push({
18025
+ page: ctx.page,
18026
+ code: "SKIPPED_IMAGE",
18027
+ message: `PPTX \uC774\uBBF8\uC9C0 \uCD94\uCD9C \uC2E4\uD328 (${rel.target}): ${err instanceof Error ? err.message : String(err)}`
18028
+ });
18029
+ return null;
18030
+ }
18031
+ ctx.imageNames.set(rel.target, filename);
18032
+ }
18033
+ return { type: "image", text: filename, pageNumber: ctx.page };
18034
+ }
18035
+ async function walkShapes(tree, ctx, out, depth = 0) {
18036
+ if (depth > MAX_XML_DEPTH) return;
18037
+ for (const el of elementChildren(tree)) {
18038
+ switch (localName(el)) {
18039
+ case "grpSp":
18040
+ await walkShapes(el, ctx, out, depth + 1);
18041
+ break;
18042
+ case "AlternateContent": {
18043
+ const choice = findChildByLocalName(el, "Choice");
18044
+ if (choice) await walkShapes(choice, ctx, out, depth + 1);
18045
+ break;
18046
+ }
18047
+ case "sp": {
18048
+ const ph = placeholderType(el);
18049
+ const txBody = findChildByLocalName(el, "txBody");
18050
+ if (ph && SKIP_PLACEHOLDERS.has(ph) || !txBody) break;
18051
+ const paras = bodyParagraphs(txBody);
18052
+ if (paras.length === 0) break;
18053
+ if (ph === "title" || ph === "ctrTitle") {
18054
+ out.push({ type: "heading", level: ph === "ctrTitle" ? 1 : 2, text: paras.map((p) => p.text).join(" "), pageNumber: ctx.page });
18055
+ } else {
18056
+ pushParagraphs(paras, ph !== null && BULLET_PLACEHOLDERS.has(ph), ctx.page, out);
18057
+ }
18058
+ break;
18059
+ }
18060
+ case "graphicFrame": {
18061
+ const data = findPath(el, "graphic", "graphicData");
18062
+ const tbl2 = data ? findChildByLocalName(data, "tbl") : null;
18063
+ if (tbl2) {
18064
+ const block = parseTable2(tbl2, ctx.page, ctx.options?.keepTrailingEmptyCols);
18065
+ if (block) out.push(block);
18066
+ } else if (data) {
18067
+ const uri = getAttr2(data, "uri") ?? "";
18068
+ const kind = /chart/i.test(uri) ? "\uCC28\uD2B8" : /diagram/i.test(uri) ? "SmartArt" : "\uAC1C\uCCB4";
18069
+ ctx.warnings.push({ page: ctx.page, code: "UNSUPPORTED_ELEMENT", message: `PPTX ${kind}\uC758 \uAE00\uC740 \uC77D\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (${ctx.page}\uCABD)` });
18070
+ }
18071
+ break;
18072
+ }
18073
+ case "pic": {
18074
+ const block = await pictureBlock(el, ctx);
18075
+ if (block) out.push(block);
18076
+ break;
18077
+ }
18078
+ }
18079
+ }
18080
+ }
18081
+ async function notesText(zip, rels) {
18082
+ const rel = [...rels.values()].find((r) => r.type.endsWith(REL_NOTES));
18083
+ const file = rel ? zip.file(rel.target) : null;
18084
+ if (!file) return "";
18085
+ const tree = findPath(parseXml3(await file.async("text")).documentElement, "cSld", "spTree");
18086
+ const texts = [];
18087
+ for (const sp of tree ? childrenByLocalName(tree, "sp") : []) {
18088
+ const txBody = findChildByLocalName(sp, "txBody");
18089
+ if (placeholderType(sp) === "body" && txBody) texts.push(...bodyParagraphs(txBody).map((p) => p.text));
18090
+ }
18091
+ return texts.join(" ");
18092
+ }
18093
+ async function parsePptxDocument(buffer, options) {
18094
+ precheckZipSize(buffer, MAX_DECOMPRESS_SIZE5, MAX_ZIP_ENTRIES2, { re: MEDIA_PART_RE2, skip: options?.images === false });
18095
+ const zip = await JSZip5.loadAsync(buffer);
18096
+ if (!zip.file("ppt/presentation.xml")) {
18097
+ throw new KordocError("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 PPTX \uD30C\uC77C: ppt/presentation.xml\uC774 \uC5C6\uC2B5\uB2C8\uB2E4");
18098
+ }
18099
+ const warnings = [];
18100
+ const blocks = [];
18101
+ const imageNames = /* @__PURE__ */ new Map();
18102
+ const images = [];
18103
+ const slides = await slideParts(zip);
18104
+ for (let i = 0; i < slides.length; i++) {
18105
+ const page = i + 1;
18106
+ const root = parseXml3(await zip.file(slides[i]).async("text")).documentElement;
18107
+ if (getAttr2(root, "show") === "0") {
18108
+ warnings.push({ page, code: "HIDDEN_TEXT_FILTERED", message: `PPTX \uC228\uAE34 \uC2AC\uB77C\uC774\uB4DC ${page}\uCABD\uC744 \uAC74\uB108\uB701\uB2C8\uB2E4` });
18109
+ continue;
18110
+ }
18111
+ const rels = await readRels(zip, slides[i]);
18112
+ const tree = findPath(root, "cSld", "spTree");
18113
+ if (tree) await walkShapes(tree, { zip, rels, page, warnings, options, imageNames, images }, blocks);
18114
+ const notes = await notesText(zip, rels);
18115
+ if (notes) blocks.push({ type: "paragraph", text: `\uBC1C\uD45C\uC790 \uB178\uD2B8: ${notes}`, quote: true, pageNumber: page });
18116
+ }
18117
+ const metadata = { pageCount: slides.length, pageMode: "layout" };
18118
+ const coreFile = zip.file("docProps/core.xml");
18119
+ if (coreFile) {
18120
+ try {
18121
+ const coreDoc = parseXml3(await coreFile.async("text"));
18122
+ const getFirst = (tag) => {
18123
+ const els = coreDoc.getElementsByTagName(tag);
18124
+ return els.length > 0 ? (els[0].textContent ?? "").trim() || void 0 : void 0;
18125
+ };
18126
+ metadata.title = getFirst("dc:title") || getFirst("dcterms:title");
18127
+ metadata.author = getFirst("dc:creator");
18128
+ metadata.description = getFirst("dc:description");
18129
+ const created = getFirst("dcterms:created");
18130
+ if (created) metadata.createdAt = created;
18131
+ const modified = getFirst("dcterms:modified");
18132
+ if (modified) metadata.modifiedAt = modified;
18133
+ } catch (err) {
18134
+ warnings.push({
18135
+ code: "PARTIAL_PARSE",
18136
+ message: `PPTX \uBA54\uD0C0\uB370\uC774\uD130(core.xml) \uD30C\uC2F1 \uC2E4\uD328: ${err instanceof Error ? err.message : String(err)}`
18137
+ });
18138
+ }
18139
+ }
18140
+ const outline = blocks.filter((b) => b.type === "heading").map((b) => ({ level: b.level ?? 2, text: b.text ?? "", pageNumber: b.pageNumber }));
18141
+ return {
18142
+ markdown: blocksToMarkdown(blocks),
18143
+ blocks,
18144
+ metadata,
18145
+ outline: outline.length > 0 ? outline : void 0,
18146
+ warnings: warnings.length > 0 ? warnings : void 0,
18147
+ images: images.length > 0 ? images : void 0
18148
+ };
18149
+ }
18150
+
18151
+ // src/hwpml/parser.ts
18152
+ import { DOMParser as DOMParser4 } from "@xmldom/xmldom";
17829
18153
  var MAX_TABLE_ROWS = 5e3;
17830
18154
  var MAX_TABLE_COLS = 500;
17831
18155
  var MAX_HWPML_BYTES = 50 * 1024 * 1024;
@@ -17837,7 +18161,7 @@ function parseHwpmlDocument(buffer, options) {
17837
18161
  const normalized = text.replace(/&nbsp;/g, "&#160;");
17838
18162
  const xml = stripDtd(normalized);
17839
18163
  const warnings = [];
17840
- const parser = new DOMParser3({
18164
+ const parser = new DOMParser4({
17841
18165
  onError: (_level, msg2) => {
17842
18166
  warnings.push({ message: `HWPML XML \uD30C\uC2F1 \uACBD\uACE0: ${msg2}`, code: "MALFORMED_XML" });
17843
18167
  }
@@ -17930,7 +18254,7 @@ function walkContent(node, blocks, paraShapeMap, sectionNum, warnings, inHeaderF
17930
18254
  }
17931
18255
  if (tag === "TABLE") {
17932
18256
  if (!inHeaderFooter) {
17933
- parseTable2(el, blocks, paraShapeMap, sectionNum, warnings, keep);
18257
+ parseTable3(el, blocks, paraShapeMap, sectionNum, warnings, keep);
17934
18258
  }
17935
18259
  continue;
17936
18260
  }
@@ -17949,7 +18273,7 @@ function walkTablesInP(node, blocks, paraShapeMap, sectionNum, warnings, keep, d
17949
18273
  if (el.nodeType !== 1) continue;
17950
18274
  const tag = localName(el);
17951
18275
  if (tag === "TABLE") {
17952
- parseTable2(el, blocks, paraShapeMap, sectionNum, warnings, keep);
18276
+ parseTable3(el, blocks, paraShapeMap, sectionNum, warnings, keep);
17953
18277
  continue;
17954
18278
  }
17955
18279
  if (tag === "FOOTNOTE" || tag === "ENDNOTE" || tag === "HEADER" || tag === "FOOTER") continue;
@@ -17982,7 +18306,7 @@ function collectCharText(node, parts, depth = 0) {
17982
18306
  if (tag === "CHAR") {
17983
18307
  for (const c of Array.from(el.childNodes)) {
17984
18308
  const t = c.nodeType === 1 ? localName(c) === "TAB" ? " " : rawTextContent(c) : c.nodeType === 3 || c.nodeType === 4 ? c.nodeValue ?? "" : "";
17985
- if (t) parts.push(t);
18309
+ if (t) parts.push(escapeLiteralTags(t));
17986
18310
  }
17987
18311
  } else if (tag === "TABLE" || tag === "PICTURE" || tag === "SHAPEOBJECT") {
17988
18312
  } else if (tag === "AUTONUM") {
@@ -17991,7 +18315,7 @@ function collectCharText(node, parts, depth = 0) {
17991
18315
  }
17992
18316
  }
17993
18317
  }
17994
- function parseTable2(el, blocks, _paraShapeMap, sectionNum, warnings, keep) {
18318
+ function parseTable3(el, blocks, _paraShapeMap, sectionNum, warnings, keep) {
17995
18319
  const table2 = buildHmlTable(el, warnings, keep, 0);
17996
18320
  if (!table2) return;
17997
18321
  const caption = extractShapeCaption(el);
@@ -18933,10 +19257,10 @@ function fillInlineFields(text, values, filled, matchedLabels, blockedLabels) {
18933
19257
  }
18934
19258
 
18935
19259
  // src/form/filler-hwpx.ts
18936
- import JSZip6 from "jszip";
19260
+ import JSZip7 from "jszip";
18937
19261
 
18938
19262
  // src/form/click-here.ts
18939
- import JSZip5 from "jszip";
19263
+ import JSZip6 from "jszip";
18940
19264
  var FIELD_BEGIN_RE = /<([A-Za-z0-9_]+:)?fieldBegin\b([^>]*?)(\/?)>/g;
18941
19265
  function attrOf2(attrs, name) {
18942
19266
  const m = attrs.match(new RegExp(`(?:^|\\s)${name}="([^"]*)"`));
@@ -19052,7 +19376,7 @@ function fillClickHereInXml(xml, cursor, blockedLabels) {
19052
19376
  }
19053
19377
  async function extractClickHereFields(hwpxBuffer) {
19054
19378
  precheckZipSize(hwpxBuffer);
19055
- const zip = await JSZip5.loadAsync(hwpxBuffer);
19379
+ const zip = await JSZip6.loadAsync(hwpxBuffer);
19056
19380
  const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
19057
19381
  const fields = [];
19058
19382
  for (let si = 0; si < sectionPaths.length; si++) {
@@ -19073,7 +19397,7 @@ async function extractClickHereFields(hwpxBuffer) {
19073
19397
  async function fillHwpx(hwpxBuffer, values, blockedLabels) {
19074
19398
  const u8 = new Uint8Array(hwpxBuffer);
19075
19399
  precheckZipSize(hwpxBuffer);
19076
- const zip = await JSZip6.loadAsync(hwpxBuffer);
19400
+ const zip = await JSZip7.loadAsync(hwpxBuffer);
19077
19401
  const sectionPaths = Object.keys(zip.files).filter((name) => /[Ss]ection\d+\.xml$/i.test(name)).sort();
19078
19402
  if (sectionPaths.length === 0) {
19079
19403
  throw new KordocError("HWPX\uC5D0\uC11C \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
@@ -19532,7 +19856,7 @@ function chooseTableRepresentation(table2, opts = {}) {
19532
19856
  }
19533
19857
 
19534
19858
  // src/hwpx/generator.ts
19535
- import JSZip7 from "jszip";
19859
+ import JSZip8 from "jszip";
19536
19860
 
19537
19861
  // src/hwpx/geometry.ts
19538
19862
  var A4_W_HU = 59528;
@@ -24204,7 +24528,8 @@ function renderListItem(block, blockIdx, ctx) {
24204
24528
  ctx.prevWasOrdered = false;
24205
24529
  }
24206
24530
  const indentPrefix = " ".repeat(indent);
24207
- return generateParagraph(indentPrefix + marker + (block.text || ""), PARA_LIST);
24531
+ const markerRun = `<hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t>${escapeTextXml(indentPrefix + marker)}</hp:t></hp:run>`;
24532
+ return `<hp:p paraPrIDRef="${PARA_LIST}" styleIDRef="0">${markerRun}${generateRuns(block.text || "")}</hp:p>`;
24208
24533
  }
24209
24534
  function renderHr(ctx) {
24210
24535
  return ctx.gongmun ? `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}"><hp:t></hp:t></hp:run></hp:p>` : `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0"><hp:t>\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500</hp:t></hp:run></hp:p>`;
@@ -25712,7 +26037,7 @@ async function markdownToHwpx(markdown, options) {
25712
26037
  if (remap2 && remap2.tables.length > 0 && remap2.tables.every((t) => !t.used)) {
25713
26038
  console.warn(`[kordoc] format profile: \uD504\uB85C\uD544 \uD45C ${remap2.tables.length}\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)`);
25714
26039
  }
25715
- const zip2 = new JSZip7();
26040
+ const zip2 = new JSZip8();
25716
26041
  zip2.file("mimetype", "application/hwp+zip", { compression: "STORE" });
25717
26042
  zip2.file("META-INF/container.xml", generateContainerXml());
25718
26043
  zip2.file("Contents/content.hpf", generateManifest(chartParts2, images2.manifestItems(), "gongmun"));
@@ -25759,7 +26084,7 @@ async function markdownToHwpx(markdown, options) {
25759
26084
  }
25760
26085
  }
25761
26086
  const extraBorderFills = [...remap?.borderFillXmls ?? [], ...bfReg?.emit() ?? []];
25762
- const zip = new JSZip7();
26087
+ const zip = new JSZip8();
25763
26088
  zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
25764
26089
  zip.file("META-INF/container.xml", generateContainerXml());
25765
26090
  zip.file("Contents/content.hpf", generateManifest(chartParts, images.manifestItems(), gongmun ? "gongmun" : "default"));
@@ -25979,7 +26304,7 @@ function readBuiltinTemplateSample(t) {
25979
26304
  }
25980
26305
 
25981
26306
  // src/hwpx/extract-profile.ts
25982
- import JSZip8 from "jszip";
26307
+ import JSZip9 from "jszip";
25983
26308
  function elemsByLocal(root, name) {
25984
26309
  const all = root.getElementsByTagName("*");
25985
26310
  const out = [];
@@ -26066,7 +26391,7 @@ function num(s) {
26066
26391
  const n = parseInt(s, 10);
26067
26392
  return Number.isFinite(n) ? n : void 0;
26068
26393
  }
26069
- function parseTable3(tbl2, tableIndex, borderFills, charPrs) {
26394
+ function parseTable4(tbl2, tableIndex, borderFills, charPrs) {
26070
26395
  const rows = num(tbl2.getAttribute("rowCnt")) ?? 0;
26071
26396
  const cols = num(tbl2.getAttribute("colCnt")) ?? 0;
26072
26397
  const sz = findChildByLocalName(tbl2, "sz");
@@ -26182,7 +26507,7 @@ function pick(map, keys) {
26182
26507
  }
26183
26508
  async function hwpxToProfile(input) {
26184
26509
  const buf = input instanceof ArrayBuffer ? input : toArrayBuffer(input);
26185
- const zip = await JSZip8.loadAsync(buf);
26510
+ const zip = await JSZip9.loadAsync(buf);
26186
26511
  const parser = createXmlParser();
26187
26512
  const headerFile = zip.file("Contents/header.xml") ?? zip.file(/[Hh]eader\.xml$/)?.[0];
26188
26513
  let headerXml = "<root/>";
@@ -26197,7 +26522,7 @@ async function hwpxToProfile(input) {
26197
26522
  const doc = parser.parseFromString(await f.async("text"), "text/xml");
26198
26523
  for (const tbl2 of elemsByLocal(doc, "tbl")) {
26199
26524
  if (!isTopLevelTable(tbl2)) continue;
26200
- tables.push(parseTable3(tbl2, tableIndex++, borderFills, charPrs));
26525
+ tables.push(parseTable4(tbl2, tableIndex++, borderFills, charPrs));
26201
26526
  }
26202
26527
  }
26203
26528
  return { schema_version: "0.3.0", tables };
@@ -26899,7 +27224,7 @@ function muncheLintWarnings(text, limit = 10) {
26899
27224
  }
26900
27225
 
26901
27226
  // src/roundtrip/patcher.ts
26902
- import JSZip9 from "jszip";
27227
+ import JSZip10 from "jszip";
26903
27228
 
26904
27229
  // src/roundtrip/table-rows.ts
26905
27230
  var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
@@ -28771,7 +29096,7 @@ async function patchHwpx(original, editedMarkdown, options) {
28771
29096
  }
28772
29097
  let zip;
28773
29098
  try {
28774
- zip = await JSZip9.loadAsync(original);
29099
+ zip = await JSZip10.loadAsync(original);
28775
29100
  } catch {
28776
29101
  return { success: false, applied: 0, skipped, error: "ZIP \uB85C\uB4DC \uC2E4\uD328" };
28777
29102
  }
@@ -29216,8 +29541,8 @@ async function resolveHeaderEntryName(zip) {
29216
29541
  }
29217
29542
 
29218
29543
  // src/validate.ts
29219
- import JSZip10 from "jszip";
29220
- import { DOMParser as DOMParser4 } from "@xmldom/xmldom";
29544
+ import JSZip11 from "jszip";
29545
+ import { DOMParser as DOMParser5 } from "@xmldom/xmldom";
29221
29546
  var REQUIRED_FILES = [
29222
29547
  "mimetype",
29223
29548
  "META-INF/container.xml",
@@ -29234,7 +29559,7 @@ async function validateHwpx(buffer) {
29234
29559
  const issues = [];
29235
29560
  let zip;
29236
29561
  try {
29237
- zip = await JSZip10.loadAsync(buffer);
29562
+ zip = await JSZip11.loadAsync(buffer);
29238
29563
  } catch (err) {
29239
29564
  return {
29240
29565
  ok: false,
@@ -29263,7 +29588,7 @@ async function validateHwpx(buffer) {
29263
29588
  const text = await zip.files[name].async("string");
29264
29589
  let firstError = null;
29265
29590
  try {
29266
- new DOMParser4({
29591
+ new DOMParser5({
29267
29592
  onError(level, msg2) {
29268
29593
  if (level !== "warning" && firstError === null) firstError = String(msg2);
29269
29594
  }
@@ -29302,12 +29627,12 @@ async function validateHwpx(buffer) {
29302
29627
  }
29303
29628
 
29304
29629
  // src/roundtrip/session.ts
29305
- import JSZip11 from "jszip";
29630
+ import JSZip12 from "jszip";
29306
29631
  async function buildState(bytes) {
29307
29632
  const format2 = detectFormat(new Uint8Array(bytes.subarray(0, 512)).buffer);
29308
29633
  if (format2 !== "hwpx") throw new Error(`HWPX \uC138\uC158\uC740 HWPX \uBB38\uC11C\uB9CC \uC5FD\uB2C8\uB2E4 (\uAC10\uC9C0\uB41C \uD3EC\uB9F7: ${format2}) \u2014 HWP 5.x \uB294 patchHwp \uB85C \uD328\uCE58\uD558\uC138\uC694`);
29309
29634
  const parsed = await parseHwpxDocument(u8ToArrayBuffer2(bytes), { layoutTables: "keep" });
29310
- const zip = await JSZip11.loadAsync(bytes);
29635
+ const zip = await JSZip12.loadAsync(bytes);
29311
29636
  const sectionPaths = await resolveSectionEntryNames(zip);
29312
29637
  if (sectionPaths.length === 0) {
29313
29638
  throw new Error("HWPX \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
@@ -29710,9 +30035,7 @@ async function dispatch(format2, buffer, opts) {
29710
30035
  const zipFormat = await detectZipFormat(buffer);
29711
30036
  if (zipFormat === "xlsx") return parseXlsx(buffer, opts);
29712
30037
  if (zipFormat === "docx") return parseDocx(buffer, opts);
29713
- if (zipFormat === "pptx") {
29714
- return { success: false, fileType: "pptx", error: "PPTX \uD30C\uC77C\uC740 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD\uC785\uB2C8\uB2E4.", code: "UNSUPPORTED_FORMAT" };
29715
- }
30038
+ if (zipFormat === "pptx") return parsePptx(buffer, opts);
29716
30039
  return parseHwpx(buffer, opts);
29717
30040
  }
29718
30041
  case "hwp": {
@@ -29737,7 +30060,7 @@ function scriptsOff(r, off) {
29737
30060
  }
29738
30061
  async function parseImage(buffer, options) {
29739
30062
  try {
29740
- const { parseImageDocument } = await import("./image-ocr-XB2NFKGZ.js");
30063
+ const { parseImageDocument } = await import("./image-ocr-LN3GSQPW.js");
29741
30064
  const { blocks, warnings } = await parseImageDocument(buffer, options);
29742
30065
  stripScriptTags({ blocks });
29743
30066
  return {
@@ -29797,7 +30120,7 @@ async function parseHwp(buffer, options) {
29797
30120
  async function parsePdf(buffer, options) {
29798
30121
  let parsePdfDocument;
29799
30122
  try {
29800
- const mod = await import("./parser-4D2M5BKY.js");
30123
+ const mod = await import("./parser-KB4BYQBZ.js");
29801
30124
  parsePdfDocument = mod.parsePdfDocument;
29802
30125
  } catch {
29803
30126
  return {
@@ -29839,6 +30162,14 @@ async function parseDocx(buffer, options) {
29839
30162
  return { success: false, fileType: "docx", error: sanitizeError(err), code: classifyError(err) };
29840
30163
  }
29841
30164
  }
30165
+ async function parsePptx(buffer, options) {
30166
+ try {
30167
+ const { markdown, blocks, metadata, outline, warnings, images } = await parsePptxDocument(buffer, options);
30168
+ return { success: true, fileType: "pptx", markdown, blocks, metadata, outline, warnings, images: images?.length ? images : void 0, pageCount: metadata?.pageCount };
30169
+ } catch (err) {
30170
+ return { success: false, fileType: "pptx", error: sanitizeError(err), code: classifyError(err) };
30171
+ }
30172
+ }
29842
30173
  async function parseHwpml(buffer, options) {
29843
30174
  try {
29844
30175
  const { markdown, blocks, metadata, outline, warnings } = parseHwpmlDocument(buffer, options);
@@ -30006,7 +30337,8 @@ export {
30006
30337
  parseXlsx,
30007
30338
  parseXls,
30008
30339
  parseDocx,
30340
+ parsePptx,
30009
30341
  parseHwpml,
30010
30342
  fillForm
30011
30343
  };
30012
- //# sourceMappingURL=chunk-UTVMLJZE.js.map
30344
+ //# sourceMappingURL=chunk-M4P7YS2N.js.map