kordoc 4.16.1 → 4.16.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 (137) hide show
  1. package/README.md +6 -7
  2. package/dist/{-3DURLXSO.js → -4G6MA4X6.js} +11 -11
  3. package/dist/chunk-3IB7LBHC.js +57 -0
  4. package/dist/chunk-3IB7LBHC.js.map +1 -0
  5. package/dist/{chunk-EEVAPRPD.js → chunk-4VODJKFL.js} +3 -3
  6. package/dist/{chunk-NCXRSQNE.js → chunk-5KS5PWJR.js} +2 -2
  7. package/dist/chunk-62W7QCEX.cjs +57 -0
  8. package/dist/chunk-62W7QCEX.cjs.map +1 -0
  9. package/dist/{chunk-ANZTLTKU.js → chunk-7KNGSQU7.js} +4 -4
  10. package/dist/chunk-7KNGSQU7.js.map +1 -0
  11. package/dist/{chunk-63YGGAQW.js → chunk-AUWGDP4G.js} +2 -2
  12. package/dist/{chunk-2BZFKIRB.cjs → chunk-CEIATRDW.cjs} +3 -3
  13. package/dist/{chunk-2BZFKIRB.cjs.map → chunk-CEIATRDW.cjs.map} +1 -1
  14. package/dist/{chunk-BIHS4VWR.js → chunk-DES2LGFZ.js} +2 -2
  15. package/dist/{chunk-N65ZXWNQ.js → chunk-F4NRLLY4.js} +2 -2
  16. package/dist/{chunk-NV37CQFN.cjs → chunk-FKUDAIJI.cjs} +12 -12
  17. package/dist/{chunk-NV37CQFN.cjs.map → chunk-FKUDAIJI.cjs.map} +1 -1
  18. package/dist/{chunk-VCRBR72A.js → chunk-GO5IFOUF.js} +2 -2
  19. package/dist/{chunk-BTO7ZEE4.js → chunk-IQGIT2VX.js} +37 -7
  20. package/dist/chunk-IQGIT2VX.js.map +1 -0
  21. package/dist/chunk-J3IF6KGW.js +59 -0
  22. package/dist/chunk-J3IF6KGW.js.map +1 -0
  23. package/dist/{chunk-VNOQTDTE.js → chunk-JELRWAZC.js} +2 -2
  24. package/dist/{chunk-CXWWX6BQ.js → chunk-JFLAM3MM.js} +2 -2
  25. package/dist/{chunk-7XAGIPOX.js → chunk-KIOQ4N37.js} +2 -2
  26. package/dist/{chunk-UZHT3LBF.js → chunk-LEIAEWZ7.js} +4 -4
  27. package/dist/chunk-LEIAEWZ7.js.map +1 -0
  28. package/dist/{chunk-NUPXPKIQ.js → chunk-MLIS253L.js} +2 -2
  29. package/dist/{chunk-DJ2BBQ5P.js → chunk-OXLPVQYK.js} +3 -3
  30. package/dist/{chunk-3VLVNKJV.js → chunk-P6ZDXTV6.js} +2 -2
  31. package/dist/{chunk-OBRPYCIS.js → chunk-QOCS7W7R.js} +58 -23
  32. package/dist/chunk-QOCS7W7R.js.map +1 -0
  33. package/dist/{chunk-24N4IJ5I.js → chunk-S2PL227Q.js} +2 -2
  34. package/dist/{chunk-PVMROO3A.js → chunk-SFEQYKYJ.js} +86 -94
  35. package/dist/chunk-SFEQYKYJ.js.map +1 -0
  36. package/dist/{chunk-YRRBA4HW.cjs → chunk-STM3ORY7.cjs} +2 -2
  37. package/dist/{chunk-YRRBA4HW.cjs.map → chunk-STM3ORY7.cjs.map} +1 -1
  38. package/dist/{chunk-7FKPPIDZ.js → chunk-TXUKTOG2.js} +166 -14
  39. package/dist/chunk-TXUKTOG2.js.map +1 -0
  40. package/dist/{chunk-3WIQSM3Z.js → chunk-UTP2WCHS.js} +4 -4
  41. package/dist/{chunk-7IRHSRPU.cjs → chunk-WDQTFAXY.cjs} +97 -25
  42. package/dist/chunk-WDQTFAXY.cjs.map +1 -0
  43. package/dist/{chunk-D2QCXK2X.cjs → chunk-XTFN5WKS.cjs} +7 -7
  44. package/dist/chunk-XTFN5WKS.cjs.map +1 -0
  45. package/dist/chunks-NUNIKS2J.js +10 -0
  46. package/dist/cli.js +28 -27
  47. package/dist/cli.js.map +1 -1
  48. package/dist/{formula-IPLFHEBD.js → formula-EPKLPDU7.js} +3 -3
  49. package/dist/{formula-U4BTEZ6I.js → formula-NARUOXRX.js} +4 -4
  50. package/dist/{formula-TRTONZMA.cjs → formula-WIMV5TUX.cjs} +9 -9
  51. package/dist/{formula-TRTONZMA.cjs.map → formula-WIMV5TUX.cjs.map} +1 -1
  52. package/dist/{image-ocr-3IJ25PS4.js → image-ocr-3WJ4QH3T.js} +8 -8
  53. package/dist/{image-ocr-GTDG4SAJ.js → image-ocr-5BUJQ4TK.js} +6 -6
  54. package/dist/{image-ocr-THFLQ3DC.cjs → image-ocr-AXWXR6JV.cjs} +15 -15
  55. package/dist/{image-ocr-THFLQ3DC.cjs.map → image-ocr-AXWXR6JV.cjs.map} +1 -1
  56. package/dist/index.cjs +723 -659
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.cts +7 -1
  59. package/dist/index.d.ts +7 -1
  60. package/dist/index.js +82 -18
  61. package/dist/index.js.map +1 -1
  62. package/dist/mcp.js +25 -23
  63. package/dist/mcp.js.map +1 -1
  64. package/dist/{model-bundle-PVWIAVEX.js → model-bundle-IMBW7D2Z.js} +5 -5
  65. package/dist/{models-VCRF3JMT.js → models-SY75IBOE.js} +5 -5
  66. package/dist/{parser-2CN2DIPV.cjs → parser-2LU4EVU3.cjs} +86 -83
  67. package/dist/parser-2LU4EVU3.cjs.map +1 -0
  68. package/dist/{parser-T4RITZDP.js → parser-N6476XAC.js} +15 -12
  69. package/dist/{parser-UEROAPYZ.js.map → parser-N6476XAC.js.map} +1 -1
  70. package/dist/{parser-UEROAPYZ.js → parser-ZQM3664Z.js} +12 -9
  71. package/dist/{parser-T4RITZDP.js.map → parser-ZQM3664Z.js.map} +1 -1
  72. package/dist/pdf-ocr-6DEE23IP.js +15 -0
  73. package/dist/pdf-ocr-GHEJVPX2.cjs +16 -0
  74. package/dist/{pdf-ocr-NARV2AQI.cjs.map → pdf-ocr-GHEJVPX2.cjs.map} +1 -1
  75. package/dist/pdf-ocr-MQTWODVU.js +18 -0
  76. package/dist/{profile-io-YD54CDXY.js → profile-io-GJPKCYPT.js} +3 -3
  77. package/dist/{rasterize-3THYOOUN.js → rasterize-UOALJQDS.js} +3 -3
  78. package/dist/{redact-doc-65L2YJN6.js → redact-doc-22SYW3KH.js} +11 -11
  79. package/dist/{render-YU7QJVZ7.js → render-MJ4H3R23.js} +7 -7
  80. package/dist/seal-XWMRUTI4.js +10 -0
  81. package/dist/{setup-CFHKXDY4.js → setup-2URYVUEO.js} +3 -3
  82. package/dist/visual-USPS4QRC.js +20 -0
  83. package/dist/{watch-D6FCAYKJ.js → watch-ALXZGTOB.js} +12 -12
  84. package/package.json +1 -1
  85. package/dist/chunk-7FKPPIDZ.js.map +0 -1
  86. package/dist/chunk-7IRHSRPU.cjs.map +0 -1
  87. package/dist/chunk-ANZTLTKU.js.map +0 -1
  88. package/dist/chunk-BTO7ZEE4.js.map +0 -1
  89. package/dist/chunk-D2QCXK2X.cjs.map +0 -1
  90. package/dist/chunk-DO74GYSM.cjs +0 -11
  91. package/dist/chunk-DO74GYSM.cjs.map +0 -1
  92. package/dist/chunk-KBAQLAEL.js +0 -11
  93. package/dist/chunk-KBAQLAEL.js.map +0 -1
  94. package/dist/chunk-OBRPYCIS.js.map +0 -1
  95. package/dist/chunk-PVMROO3A.js.map +0 -1
  96. package/dist/chunk-T77M2QP7.js +0 -13
  97. package/dist/chunk-T77M2QP7.js.map +0 -1
  98. package/dist/chunk-UZHT3LBF.js.map +0 -1
  99. package/dist/chunks-PYYQURNO.js +0 -10
  100. package/dist/parser-2CN2DIPV.cjs.map +0 -1
  101. package/dist/pdf-ocr-NARV2AQI.cjs +0 -16
  102. package/dist/pdf-ocr-SYLMM727.js +0 -18
  103. package/dist/pdf-ocr-YMQZDJBO.js +0 -15
  104. package/dist/seal-6CQGFTML.js +0 -10
  105. package/dist/visual-ED2H75Q5.js +0 -20
  106. /package/dist/{-3DURLXSO.js.map → -4G6MA4X6.js.map} +0 -0
  107. /package/dist/{chunk-EEVAPRPD.js.map → chunk-4VODJKFL.js.map} +0 -0
  108. /package/dist/{chunk-NCXRSQNE.js.map → chunk-5KS5PWJR.js.map} +0 -0
  109. /package/dist/{chunk-63YGGAQW.js.map → chunk-AUWGDP4G.js.map} +0 -0
  110. /package/dist/{chunk-BIHS4VWR.js.map → chunk-DES2LGFZ.js.map} +0 -0
  111. /package/dist/{chunk-N65ZXWNQ.js.map → chunk-F4NRLLY4.js.map} +0 -0
  112. /package/dist/{chunk-VCRBR72A.js.map → chunk-GO5IFOUF.js.map} +0 -0
  113. /package/dist/{chunk-VNOQTDTE.js.map → chunk-JELRWAZC.js.map} +0 -0
  114. /package/dist/{chunk-CXWWX6BQ.js.map → chunk-JFLAM3MM.js.map} +0 -0
  115. /package/dist/{chunk-7XAGIPOX.js.map → chunk-KIOQ4N37.js.map} +0 -0
  116. /package/dist/{chunk-NUPXPKIQ.js.map → chunk-MLIS253L.js.map} +0 -0
  117. /package/dist/{chunk-DJ2BBQ5P.js.map → chunk-OXLPVQYK.js.map} +0 -0
  118. /package/dist/{chunk-3VLVNKJV.js.map → chunk-P6ZDXTV6.js.map} +0 -0
  119. /package/dist/{chunk-24N4IJ5I.js.map → chunk-S2PL227Q.js.map} +0 -0
  120. /package/dist/{chunk-3WIQSM3Z.js.map → chunk-UTP2WCHS.js.map} +0 -0
  121. /package/dist/{chunks-PYYQURNO.js.map → chunks-NUNIKS2J.js.map} +0 -0
  122. /package/dist/{formula-IPLFHEBD.js.map → formula-EPKLPDU7.js.map} +0 -0
  123. /package/dist/{formula-U4BTEZ6I.js.map → formula-NARUOXRX.js.map} +0 -0
  124. /package/dist/{image-ocr-3IJ25PS4.js.map → image-ocr-3WJ4QH3T.js.map} +0 -0
  125. /package/dist/{image-ocr-GTDG4SAJ.js.map → image-ocr-5BUJQ4TK.js.map} +0 -0
  126. /package/dist/{model-bundle-PVWIAVEX.js.map → model-bundle-IMBW7D2Z.js.map} +0 -0
  127. /package/dist/{models-VCRF3JMT.js.map → models-SY75IBOE.js.map} +0 -0
  128. /package/dist/{pdf-ocr-SYLMM727.js.map → pdf-ocr-6DEE23IP.js.map} +0 -0
  129. /package/dist/{pdf-ocr-YMQZDJBO.js.map → pdf-ocr-MQTWODVU.js.map} +0 -0
  130. /package/dist/{profile-io-YD54CDXY.js.map → profile-io-GJPKCYPT.js.map} +0 -0
  131. /package/dist/{rasterize-3THYOOUN.js.map → rasterize-UOALJQDS.js.map} +0 -0
  132. /package/dist/{redact-doc-65L2YJN6.js.map → redact-doc-22SYW3KH.js.map} +0 -0
  133. /package/dist/{render-YU7QJVZ7.js.map → render-MJ4H3R23.js.map} +0 -0
  134. /package/dist/{seal-6CQGFTML.js.map → seal-XWMRUTI4.js.map} +0 -0
  135. /package/dist/{setup-CFHKXDY4.js.map → setup-2URYVUEO.js.map} +0 -0
  136. /package/dist/{visual-ED2H75Q5.js.map → visual-USPS4QRC.js.map} +0 -0
  137. /package/dist/{watch-D6FCAYKJ.js.map → watch-ALXZGTOB.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -194,8 +194,14 @@ interface ParseOptions {
194
194
  onProgress?: (current: number, total: number) => void;
195
195
  /** PDF 머리글/바닥글 자동 제거 */
196
196
  removeHeaderFooter?: boolean;
197
+ /**
198
+ * 위·아래첨자를 인라인 HTML `<sup>`·`<sub>` 로 표기 — 평문으로 펴면 "10⁴ m²" 가 "104 m2", "x_i" 가 "xi" 로 값이 바뀐다.
199
+ * 기본: HWPX·HWP·DOCX 켬(글자 모양에 적힌 첨자), PDF 끔(글자 크기·기준선으로 추정 — 논문·수식 문서는 true 권장.
200
+ * 공개 벤치 ODL 정답이 첨자를 평문으로 적어 기본값을 두지 않는다). false 면 모든 형식에서 평문. OCR 로 읽은 글은 늘 평문
201
+ */
202
+ scriptTags?: boolean;
197
203
  /** 평문 Markdown — 그림 자리 표시·링크 URL·밑줄(`<u>`)·굵게(`**`) 표기를 빼고 글만 (제목·목록·표 구조는 유지).
198
- * 이미지 바이트를 따로 저장하지 않는 색인·RAG 용. 기본 false. `blocks` IR 은 그대로 */
204
+ * 첨자 `<sup>`·`<sub>` 는 값이 남게 `10^4`·`H_2O` 로 편다. 이미지 바이트를 따로 저장하지 않는 색인·RAG 용. 기본 false. `blocks` IR 은 그대로 */
199
205
  plain?: boolean;
200
206
  /** 모든 표를 HTML 로 — 파이프 표도 HTML 표로 옮기고, 표마다 태그를 한 줄씩 들여써 낸다(BeautifulSoup prettify 모양, 첫 행 `<th>`).
201
207
  * HTML 표만 다루는 소비자·채점기용. 기본 false(병합·중첩 없는 표는 GFM 파이프 표) */
package/dist/index.d.ts CHANGED
@@ -194,8 +194,14 @@ interface ParseOptions {
194
194
  onProgress?: (current: number, total: number) => void;
195
195
  /** PDF 머리글/바닥글 자동 제거 */
196
196
  removeHeaderFooter?: boolean;
197
+ /**
198
+ * 위·아래첨자를 인라인 HTML `<sup>`·`<sub>` 로 표기 — 평문으로 펴면 "10⁴ m²" 가 "104 m2", "x_i" 가 "xi" 로 값이 바뀐다.
199
+ * 기본: HWPX·HWP·DOCX 켬(글자 모양에 적힌 첨자), PDF 끔(글자 크기·기준선으로 추정 — 논문·수식 문서는 true 권장.
200
+ * 공개 벤치 ODL 정답이 첨자를 평문으로 적어 기본값을 두지 않는다). false 면 모든 형식에서 평문. OCR 로 읽은 글은 늘 평문
201
+ */
202
+ scriptTags?: boolean;
197
203
  /** 평문 Markdown — 그림 자리 표시·링크 URL·밑줄(`<u>`)·굵게(`**`) 표기를 빼고 글만 (제목·목록·표 구조는 유지).
198
- * 이미지 바이트를 따로 저장하지 않는 색인·RAG 용. 기본 false. `blocks` IR 은 그대로 */
204
+ * 첨자 `<sup>`·`<sub>` 는 값이 남게 `10^4`·`H_2O` 로 편다. 이미지 바이트를 따로 저장하지 않는 색인·RAG 용. 기본 false. `blocks` IR 은 그대로 */
199
205
  plain?: boolean;
200
206
  /** 모든 표를 HTML 로 — 파이프 표도 HTML 표로 옮기고, 표마다 태그를 한 줄씩 들여써 낸다(BeautifulSoup prettify 모양, 첫 행 `<th>`).
201
207
  * HTML 표만 다루는 소비자·채점기용. 기본 false(병합·중첩 없는 표는 GFM 파이프 표) */
package/dist/index.js CHANGED
@@ -16,15 +16,19 @@ import {
16
16
  mapPuaText,
17
17
  markNonLayoutTable,
18
18
  noteSuffix
19
- } from "./chunk-ANZTLTKU.js";
19
+ } from "./chunk-7KNGSQU7.js";
20
20
  import {
21
21
  parsePageRange
22
22
  } from "./chunk-V4BH5SRQ.js";
23
23
  import {
24
24
  HEADING_RATIO_H1,
25
25
  HEADING_RATIO_H2,
26
- HEADING_RATIO_H3
27
- } from "./chunk-KBAQLAEL.js";
26
+ HEADING_RATIO_H3,
27
+ plainScripts,
28
+ stripScriptTags,
29
+ tidyScriptTags,
30
+ wrapScript
31
+ } from "./chunk-3IB7LBHC.js";
28
32
  import {
29
33
  KordocError,
30
34
  OPTIONAL_DEP_INSTALL_HINT,
@@ -41,17 +45,17 @@ import {
41
45
  toArrayBuffer,
42
46
  unescapeHtml,
43
47
  unzipLimitBytes
44
- } from "./chunk-NUPXPKIQ.js";
48
+ } from "./chunk-MLIS253L.js";
45
49
 
46
50
  // src/plain-markdown.ts
47
51
  function toPlainMarkdown(md2) {
48
- return md2.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();
52
+ return plainScripts(md2).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();
49
53
  }
50
54
 
51
55
  // src/html-tables.ts
52
56
  var TABLE_TAG = /(<\/?(?:table|tr|th|td)\b[^>]*>)/i;
53
57
  function pipeCellToHtml(cell2) {
54
- return cell2.split(/(<br>|<\/?u>|<img\b[^>]*>)/).map((part, i) => i % 2 ? part : part.replace(/\\([\\`*_{}[\]()#+\-.!|~<>$])/g, "$1").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")).join("");
58
+ 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("");
55
59
  }
56
60
  function splitPipeRow(line) {
57
61
  const t = line.trim().replace(/^\|/, "").replace(/(?<!\\)\|$/, "");
@@ -770,7 +774,9 @@ function parseCharProperties(doc, map) {
770
774
  else if (localTag === "strikeout") {
771
775
  const shape = k.getAttribute("shape") || "";
772
776
  if (isRealStrikeShape(shape)) prop.strike = true;
773
- } else if (localTag === "underline") {
777
+ } else if (localTag === "supscript") prop.script = "sup";
778
+ else if (localTag === "subscript") prop.script = "sub";
779
+ else if (localTag === "underline") {
774
780
  if (k.getAttribute("type") === "BOTTOM") prop.underline = true;
775
781
  }
776
782
  }
@@ -1848,6 +1854,7 @@ function extractRunSpans(para2, ctx, mode, requireMixed) {
1848
1854
  const span2 = { text };
1849
1855
  if (mode !== "foreign" && prId === KORDOC_CHAR_CODE) span2.code = true;
1850
1856
  else {
1857
+ if (cp?.script) span2.text = wrapScript(text, cp.script);
1851
1858
  if (cp?.bold) span2.bold = true;
1852
1859
  if (cp?.italic) span2.italic = true;
1853
1860
  if (cp?.strike) span2.strike = true;
@@ -1867,6 +1874,7 @@ function extractRunSpans(para2, ctx, mode, requireMixed) {
1867
1874
  }
1868
1875
  }
1869
1876
  if (requireMixed && !merged.some((s) => s.strike || s.underline) && !merged.some((s) => !(s.bold || s.italic || s.code))) return null;
1877
+ for (const s of merged) s.text = tidyScriptTags(s.text);
1870
1878
  return merged;
1871
1879
  }
1872
1880
  function gongmunDepthFromIndent(para2, left, ctx) {
@@ -2516,6 +2524,16 @@ function extractHyperlinkHref(fieldBegin) {
2516
2524
  function isInDeletedRange(ctx) {
2517
2525
  return (ctx?.shared.track.deleteDepth ?? 0) > 0;
2518
2526
  }
2527
+ function runHasOnlyText(run) {
2528
+ const kids = run.childNodes;
2529
+ for (let i = 0; i < (kids?.length ?? 0); i++) {
2530
+ const k = kids[i];
2531
+ if (k.nodeType !== 1) continue;
2532
+ const t = (k.tagName || k.localName || "").replace(/^[^:]+:/, "");
2533
+ if (t !== "t" && t !== "linesegarray") return false;
2534
+ }
2535
+ return true;
2536
+ }
2519
2537
  function extractParagraphInfo(para2, styleMap, ctx) {
2520
2538
  let text = "";
2521
2539
  let href;
@@ -2772,11 +2790,19 @@ function extractParagraphInfo(para2, styleMap, ctx) {
2772
2790
  }
2773
2791
  break;
2774
2792
  }
2775
- // run 요소에서 charPrIDRef 추출
2776
- case "r": {
2793
+ // run 요소 — hp:r 은 charPrIDRef 를 문단 대표 스타일로. 첨자 글자 모양이면 이 run 이 더한 글을 <sup>·<sub> 로
2794
+ // (개체·각주 등 컨트롤을 품은 run·필드 경계가 걸친 run 은 글 위치가 섞여 감싸지 않는다)
2795
+ case "r":
2796
+ case "run": {
2777
2797
  const runCharPr = child.getAttribute("charPrIDRef");
2778
- if (runCharPr && !charPrId) charPrId = runCharPr;
2798
+ if (tag === "r" && runCharPr && !charPrId) charPrId = runCharPr;
2799
+ const script = runCharPr ? styleMap?.charProperties.get(runCharPr)?.script : void 0;
2800
+ const start = text.length, nLinks = linkRanges.length, nOpen = openFields.length;
2779
2801
  walk(child, depth + 1);
2802
+ if (script && linkRanges.length === nLinks && openFields.length === nOpen && runHasOnlyText(child)) {
2803
+ const added = text.slice(start);
2804
+ if (added && !/[\x1E\x1F\n$]/.test(added)) text = text.slice(0, start) + wrapScript(added, script);
2805
+ }
2780
2806
  break;
2781
2807
  }
2782
2808
  default:
@@ -2800,6 +2826,7 @@ function extractParagraphInfo(para2, styleMap, ctx) {
2800
2826
  }
2801
2827
  const leaderIdx = text.indexOf("");
2802
2828
  if (leaderIdx >= 0) text = text.substring(0, leaderIdx);
2829
+ text = tidyScriptTags(text);
2803
2830
  const cleanParaText = (raw) => {
2804
2831
  let t = raw.replace(/[ \t]+/g, " ").trim();
2805
2832
  if (/^그림입니다\.?\s*원본\s*그림의\s*(이름|크기)/.test(t)) t = "";
@@ -3043,6 +3070,14 @@ function isExtendedOnlyCtrlChar(ch) {
3043
3070
  function appendParaText(state, data, resolveControl) {
3044
3071
  let result = "";
3045
3072
  let i = 0;
3073
+ const wbase = state.wpos ?? 0;
3074
+ const setScript = (want) => {
3075
+ const cur = state.script ?? null;
3076
+ if (cur === want) return;
3077
+ if (cur) result += `</${cur}>`;
3078
+ if (want) result += `<${want}>`;
3079
+ state.script = want;
3080
+ };
3046
3081
  const base = state.text.length;
3047
3082
  const resolveAt = (byteOffset, extended) => {
3048
3083
  const ctrlId = data.readUInt32LE(byteOffset);
@@ -3053,6 +3088,7 @@ function appendParaText(state, data, resolveControl) {
3053
3088
  };
3054
3089
  while (i + 1 < data.length) {
3055
3090
  const ch = data.readUInt16LE(i);
3091
+ if (state.scriptAt) setScript(ch >= 32 ? state.scriptAt(wbase + i / 2) : null);
3056
3092
  i += 2;
3057
3093
  switch (ch) {
3058
3094
  // ── char 타입 (2바이트만, 확장 데이터 없음) ──
@@ -3124,6 +3160,8 @@ function appendParaText(state, data, resolveControl) {
3124
3160
  break;
3125
3161
  }
3126
3162
  }
3163
+ if (state.scriptAt) setScript(null);
3164
+ state.wpos = wbase + Math.floor(data.length / 2);
3127
3165
  state.text += result;
3128
3166
  }
3129
3167
  function extractEquationText(data) {
@@ -5210,6 +5248,7 @@ function parseParagraph(records, start, end, ctx) {
5210
5248
  const paraShapeId = header.data.length >= 10 ? header.data.readUInt16LE(8) : -1;
5211
5249
  const textRecords = [];
5212
5250
  const charShapeIds = [];
5251
+ const charShapeRuns = [];
5213
5252
  const ctrls = [];
5214
5253
  let i = start + 1;
5215
5254
  while (i < end) {
@@ -5228,6 +5267,7 @@ function parseParagraph(records, start, end, ctx) {
5228
5267
  } else if (rec.tagId === TAG_CHAR_SHAPE && rec.level === baseLevel + 1 && rec.data.length >= 8) {
5229
5268
  for (let offset = 0; offset + 7 < rec.data.length; offset += 8) {
5230
5269
  charShapeIds.push(rec.data.readUInt32LE(offset + 4));
5270
+ charShapeRuns.push([rec.data.readUInt32LE(offset), rec.data.readUInt32LE(offset + 4)]);
5231
5271
  }
5232
5272
  }
5233
5273
  i++;
@@ -5241,6 +5281,7 @@ function parseParagraph(records, start, end, ctx) {
5241
5281
  const state = createParaTextState();
5242
5282
  state.leaderMark = true;
5243
5283
  state.dollarMark = true;
5284
+ state.scriptAt = scriptLookup(charShapeRuns, ctx.docInfo);
5244
5285
  const resolver = (idx, id) => {
5245
5286
  let ctrl = idx >= 0 && idx < ctrls.length ? ctrls[idx] : void 0;
5246
5287
  if (!ctrl || ctrl.idRaw !== id && ctrl.id !== id) {
@@ -5282,6 +5323,7 @@ function parseParagraph(records, start, end, ctx) {
5282
5323
  const leaderAt = text.indexOf(LEADER_TAB_MARK);
5283
5324
  if (leaderAt >= 0) text = text.slice(0, leaderAt);
5284
5325
  if (text.includes(LITERAL_DOLLAR_MARK)) text = text.replaceAll(LITERAL_DOLLAR_MARK, "\\$");
5326
+ text = tidyScriptTags(text);
5285
5327
  let headingLevel = 0;
5286
5328
  let headMarker = null;
5287
5329
  const ps = ctx.docInfo && paraShapeId >= 0 && paraShapeId < ctx.docInfo.paraShapes.length ? ctx.docInfo.paraShapes[paraShapeId] : null;
@@ -5647,6 +5689,20 @@ function pictureToImageBlock(data, ctx) {
5647
5689
  const storageId = item && item.storageId > 0 ? item.storageId : binDataId;
5648
5690
  return { type: "image", text: String(storageId), pageNumber: ctx.page };
5649
5691
  }
5692
+ function scriptLookup(runs, docInfo) {
5693
+ if (!docInfo || !runs.length) return void 0;
5694
+ const kindOf = (id) => {
5695
+ const f = docInfo.charShapes[id]?.attrFlags ?? 0;
5696
+ return f & 1 << 15 ? "sup" : f & 1 << 16 ? "sub" : null;
5697
+ };
5698
+ if (!runs.some(([, id]) => kindOf(id))) return void 0;
5699
+ let k = -1;
5700
+ return (pos) => {
5701
+ if (k >= 0 && runs[k][0] > pos) k = -1;
5702
+ while (k + 1 < runs.length && runs[k + 1][0] <= pos) k++;
5703
+ return k >= 0 ? kindOf(runs[k][1]) : null;
5704
+ };
5705
+ }
5650
5706
  function resolveCharStyle(charShapeIds, docInfo) {
5651
5707
  if (charShapeIds.length === 0 || docInfo.charShapes.length === 0) return void 0;
5652
5708
  const freq = /* @__PURE__ */ new Map();
@@ -20734,6 +20790,9 @@ function extractRun(r) {
20734
20790
  if (rPrEls.length > 0) {
20735
20791
  bold = getChildElements(rPrEls[0], "b").length > 0;
20736
20792
  italic = getChildElements(rPrEls[0], "i").length > 0;
20793
+ const va = getChildElements(rPrEls[0], "vertAlign")[0];
20794
+ const v = va ? getAttr(va, "val") : null;
20795
+ if (v === "superscript" || v === "subscript") text = wrapScript(text, v === "superscript" ? "sup" : "sub");
20737
20796
  }
20738
20797
  return { text, bold, italic };
20739
20798
  }
@@ -20831,7 +20890,7 @@ function collectInline(p, footnotes, rels) {
20831
20890
  if (isDisplayMath(om)) parts.push(" $$" + latex + "$$ ");
20832
20891
  else parts.push(" $" + latex + "$ ");
20833
20892
  }
20834
- const text = parts.join("").replace(/[ \t]{2,}/g, " ").trim();
20893
+ const text = tidyScriptTags(parts.join("")).replace(/[ \t]{2,}/g, " ").trim();
20835
20894
  return { text, bold, italic, footnoteText };
20836
20895
  }
20837
20896
  var COUNTERS = /* @__PURE__ */ new WeakMap();
@@ -21704,7 +21763,7 @@ var ValueCursor = class {
21704
21763
  }
21705
21764
  };
21706
21765
  function normalizeLabel(label) {
21707
- return label.trim().replace(/[::\s()()·]/g, "");
21766
+ return label.trim().replace(/<\/?su[bp]>/g, "").replace(/[::\s()()·]/g, "");
21708
21767
  }
21709
21768
  function findMatchingKey(cellLabel, values) {
21710
21769
  if (values.has(cellLabel)) return cellLabel;
@@ -26780,6 +26839,7 @@ function parseInlineMarkdown(text) {
26780
26839
  text = text.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1");
26781
26840
  text = text.replace(/~~([^~]+)~~/g, "$1");
26782
26841
  text = text.replace(/<u>([^<]*)<\/u>/g, "$1");
26842
+ text = text.replace(/<(sup|sub)>([^<]*)<\/\1>/g, "$2");
26783
26843
  let spans;
26784
26844
  if (inlineDoc) {
26785
26845
  spans = [];
@@ -40540,10 +40600,14 @@ async function dispatch(format2, buffer, opts) {
40540
40600
  return { success: false, fileType: "unknown", error: "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD\uC785\uB2C8\uB2E4.", code: "UNSUPPORTED_FORMAT" };
40541
40601
  }
40542
40602
  }
40603
+ function scriptsOff(r, off) {
40604
+ return off ? stripScriptTags(r) : r;
40605
+ }
40543
40606
  async function parseImage(buffer, options) {
40544
40607
  try {
40545
- const { parseImageDocument } = await import("./image-ocr-GTDG4SAJ.js");
40608
+ const { parseImageDocument } = await import("./image-ocr-5BUJQ4TK.js");
40546
40609
  const { blocks, warnings } = await parseImageDocument(buffer, options);
40610
+ stripScriptTags({ blocks });
40547
40611
  return {
40548
40612
  success: true,
40549
40613
  fileType: "image",
@@ -40567,7 +40631,7 @@ async function parseHwp3(buffer, options) {
40567
40631
  async function parseHwpx(buffer, options) {
40568
40632
  try {
40569
40633
  const { markdown, blocks, metadata, outline, warnings, images } = await parseHwpxDocument(buffer, options);
40570
- return { success: true, fileType: "hwpx", markdown, blocks, metadata, outline, warnings, images: images?.length ? images : void 0, pageCount: metadata?.pageCount };
40634
+ return scriptsOff({ success: true, fileType: "hwpx", markdown, blocks, metadata, outline, warnings, images: images?.length ? images : void 0, pageCount: metadata?.pageCount }, options?.scriptTags === false);
40571
40635
  } catch (err) {
40572
40636
  return { success: false, fileType: "hwpx", error: sanitizeError(err), code: classifyError(err) };
40573
40637
  }
@@ -40593,7 +40657,7 @@ async function parseHwp(buffer, options) {
40593
40657
  } catch {
40594
40658
  }
40595
40659
  }
40596
- return { success: true, fileType: "hwp", markdown, blocks, metadata, outline, warnings, images: images?.length ? images : void 0, pageCount: metadata?.pageCount };
40660
+ return scriptsOff({ success: true, fileType: "hwp", markdown, blocks, metadata, outline, warnings, images: images?.length ? images : void 0, pageCount: metadata?.pageCount }, options?.scriptTags === false);
40597
40661
  } catch (err) {
40598
40662
  return { success: false, fileType: "hwp", error: sanitizeError(err), code: classifyError(err) };
40599
40663
  }
@@ -40601,7 +40665,7 @@ async function parseHwp(buffer, options) {
40601
40665
  async function parsePdf(buffer, options) {
40602
40666
  let parsePdfDocument;
40603
40667
  try {
40604
- const mod = await import("./parser-UEROAPYZ.js");
40668
+ const mod = await import("./parser-ZQM3664Z.js");
40605
40669
  parsePdfDocument = mod.parsePdfDocument;
40606
40670
  } catch {
40607
40671
  return {
@@ -40613,7 +40677,7 @@ async function parsePdf(buffer, options) {
40613
40677
  }
40614
40678
  try {
40615
40679
  const { markdown, blocks, metadata, outline, warnings, isImageBased, pageQuality, qualitySummary, images, pages } = await parsePdfDocument(buffer, options);
40616
- return { success: true, fileType: "pdf", markdown, blocks, metadata, outline, warnings, isImageBased, pageQuality, qualitySummary, images, pages, pageCount: metadata?.pageCount };
40680
+ return scriptsOff({ success: true, fileType: "pdf", markdown, blocks, metadata, outline, warnings, isImageBased, pageQuality, qualitySummary, images, pages, pageCount: metadata?.pageCount }, options?.scriptTags !== true);
40617
40681
  } catch (err) {
40618
40682
  const isImageBased = err instanceof Error && "isImageBased" in err ? true : void 0;
40619
40683
  return { success: false, fileType: "pdf", error: sanitizeError(err), code: classifyError(err), isImageBased };
@@ -40638,7 +40702,7 @@ async function parseXls(buffer, options) {
40638
40702
  async function parseDocx(buffer, options) {
40639
40703
  try {
40640
40704
  const { markdown, blocks, metadata, outline, warnings, images } = await parseDocxDocument(buffer, options);
40641
- return { success: true, fileType: "docx", markdown, blocks, metadata, outline, warnings, images: images?.length ? images : void 0, pageCount: metadata?.pageCount };
40705
+ return scriptsOff({ success: true, fileType: "docx", markdown, blocks, metadata, outline, warnings, images: images?.length ? images : void 0, pageCount: metadata?.pageCount }, options?.scriptTags === false);
40642
40706
  } catch (err) {
40643
40707
  return { success: false, fileType: "docx", error: sanitizeError(err), code: classifyError(err) };
40644
40708
  }