kordoc 4.14.2 → 4.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/README.md +51 -6
  2. package/dist/{-AQKXLFIM.js → -Z4TJ3QGK.js} +13 -11
  3. package/dist/{chunk-QOMNEWCQ.cjs → chunk-5LAZQCUJ.cjs} +305 -31
  4. package/dist/chunk-5LAZQCUJ.cjs.map +1 -0
  5. package/dist/{chunk-7IAQ4HOK.js → chunk-6BWU6SQX.js} +1 -1
  6. package/dist/chunk-6BWU6SQX.js.map +1 -0
  7. package/dist/{chunk-FOJZNMMK.js → chunk-6CUIXJOC.js} +1 -1
  8. package/dist/chunk-6CUIXJOC.js.map +1 -0
  9. package/dist/{chunk-ZWD734EY.js → chunk-7SE4EZ45.js} +2 -2
  10. package/dist/{chunk-TSFS5VKD.js → chunk-D4U2TXDC.js} +332 -141
  11. package/dist/chunk-D4U2TXDC.js.map +1 -0
  12. package/dist/chunk-DPWWXUOG.js +2222 -0
  13. package/dist/chunk-DPWWXUOG.js.map +1 -0
  14. package/dist/{chunk-GDW4YP7K.js → chunk-GLSBEEZJ.js} +2 -2
  15. package/dist/{chunk-JQEFP45L.js → chunk-GUJ4Q73I.js} +2 -2
  16. package/dist/{chunk-ZWOFQRIB.js → chunk-HIJUKZHM.js} +3 -3
  17. package/dist/chunk-IMAAFSAX.cjs +1352 -0
  18. package/dist/chunk-IMAAFSAX.cjs.map +1 -0
  19. package/dist/{chunk-TNCKOL2O.js → chunk-LCW7SEPG.js} +2 -2
  20. package/dist/chunk-LFSQAMSM.js +1352 -0
  21. package/dist/chunk-LFSQAMSM.js.map +1 -0
  22. package/dist/chunk-MG6DJEX4.js +1299 -0
  23. package/dist/chunk-MG6DJEX4.js.map +1 -0
  24. package/dist/{chunk-QC5T6D4J.js → chunk-NLU6LBLY.js} +299 -25
  25. package/dist/chunk-NLU6LBLY.js.map +1 -0
  26. package/dist/{chunk-EQZI77PP.cjs → chunk-QEJUY6SK.cjs} +3 -3
  27. package/dist/{chunk-EQZI77PP.cjs.map → chunk-QEJUY6SK.cjs.map} +1 -1
  28. package/dist/{chunk-VQ5W4MYO.js → chunk-QIF2VXBQ.js} +298 -24
  29. package/dist/chunk-QIF2VXBQ.js.map +1 -0
  30. package/dist/{chunk-UET462HB.js → chunk-TITDJWVZ.js} +2 -2
  31. package/dist/{chunk-247ANM72.cjs → chunk-USHQCF5T.cjs} +870 -147
  32. package/dist/chunk-USHQCF5T.cjs.map +1 -0
  33. package/dist/{chunk-C7FQBSON.js → chunk-V3DX4DUF.js} +2 -2
  34. package/dist/{chunk-DOGPOY4B.js → chunk-VDN7LMPL.js} +2 -2
  35. package/dist/{chunk-EDNJLUSE.js → chunk-VJIL6PIL.js} +2 -2
  36. package/dist/{chunk-L7DMSMAG.cjs → chunk-VWUYVEFN.cjs} +1 -1
  37. package/dist/chunk-VWUYVEFN.cjs.map +1 -0
  38. package/dist/{chunk-HR2XNERB.cjs → chunk-WJHAU73B.cjs} +2 -2
  39. package/dist/{chunk-HR2XNERB.cjs.map → chunk-WJHAU73B.cjs.map} +1 -1
  40. package/dist/{chunk-NS55SM7A.js → chunk-WJJGW5PL.js} +2 -2
  41. package/dist/{chunk-EISO3POT.js → chunk-XVXHXQIO.js} +788 -194
  42. package/dist/chunk-XVXHXQIO.js.map +1 -0
  43. package/dist/{chunk-ILU76UF3.js → chunk-YAKC46HZ.js} +2 -2
  44. package/dist/chunk-YAKC46HZ.js.map +1 -0
  45. package/dist/{chunk-3DUADAY2.js → chunk-YAVHVFRY.js} +851 -128
  46. package/dist/chunk-YAVHVFRY.js.map +1 -0
  47. package/dist/{chunk-A7QC2ZVP.js → chunk-YT3GC62E.js} +851 -128
  48. package/dist/chunk-YT3GC62E.js.map +1 -0
  49. package/dist/chunks-CCMRL4MJ.js +10 -0
  50. package/dist/cli.js +228 -97
  51. package/dist/cli.js.map +1 -1
  52. package/dist/{formula-PJJ6S3Z2.cjs → formula-5LOVHAKE.cjs} +9 -9
  53. package/dist/{formula-PJJ6S3Z2.cjs.map → formula-5LOVHAKE.cjs.map} +1 -1
  54. package/dist/{formula-JGFTXWYT.js → formula-7RANCW5L.js} +3 -3
  55. package/dist/{formula-5S7WWXGH.js → formula-7UYJOVTB.js} +4 -4
  56. package/dist/{image-ocr-WCAYXLOA.js → image-ocr-I6JOCATS.js} +34 -16
  57. package/dist/image-ocr-I6JOCATS.js.map +1 -0
  58. package/dist/{image-ocr-ZTYAGV3W.cjs → image-ocr-NYBJEOH2.cjs} +36 -18
  59. package/dist/image-ocr-NYBJEOH2.cjs.map +1 -0
  60. package/dist/{image-ocr-FLIL7MGN.js → image-ocr-ZV6PDBUQ.js} +32 -14
  61. package/dist/image-ocr-ZV6PDBUQ.js.map +1 -0
  62. package/dist/index.cjs +4048 -1216
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +66 -28
  65. package/dist/index.d.ts +66 -28
  66. package/dist/index.js +3487 -655
  67. package/dist/index.js.map +1 -1
  68. package/dist/mcp.js +74 -53
  69. package/dist/mcp.js.map +1 -1
  70. package/dist/{model-bundle-FSPZZ2EM.js → model-bundle-2C5IYDLE.js} +5 -5
  71. package/dist/{models-CJPAQK5R.js → models-SEQZHZFT.js} +5 -5
  72. package/dist/{parser-SCUTZAIJ.js → parser-3FNXEP6T.js} +708 -250
  73. package/dist/parser-3FNXEP6T.js.map +1 -0
  74. package/dist/{parser-A4TMPJAM.js → parser-FJBJXRJK.js} +708 -250
  75. package/dist/parser-FJBJXRJK.js.map +1 -0
  76. package/dist/{parser-VCXE4I5A.cjs → parser-HVEKF73B.cjs} +733 -275
  77. package/dist/parser-HVEKF73B.cjs.map +1 -0
  78. package/dist/pdf-ocr-JRDBJ6TA.cjs +14 -0
  79. package/dist/{pdf-ocr-MBZZ57LD.cjs.map → pdf-ocr-JRDBJ6TA.cjs.map} +1 -1
  80. package/dist/pdf-ocr-UUBWBEHL.js +16 -0
  81. package/dist/pdf-ocr-VJSF2SQC.js +13 -0
  82. package/dist/{profile-io-LBM263K7.js → profile-io-RUFZOZO6.js} +3 -3
  83. package/dist/{rasterize-46RG4ZF6.js → rasterize-IOYXR5SI.js} +3 -3
  84. package/dist/redact-NMIKVHMP.js +18 -0
  85. package/dist/redact-doc-QBHNJ2BU.js +1284 -0
  86. package/dist/redact-doc-QBHNJ2BU.js.map +1 -0
  87. package/dist/{render-NGP5T24S.js → render-YZ2TEC3N.js} +7 -7
  88. package/dist/seal-ECV44TUH.js +10 -0
  89. package/dist/{setup-AU4OCHNH.js → setup-MPIEP6XT.js} +3 -3
  90. package/dist/visual-ICMOWUCR.js +19 -0
  91. package/dist/{watch-MKPUCPXM.js → watch-RYO7MN5B.js} +12 -12
  92. package/package.json +2 -2
  93. package/dist/chunk-247ANM72.cjs.map +0 -1
  94. package/dist/chunk-3DUADAY2.js.map +0 -1
  95. package/dist/chunk-422427XJ.cjs +0 -571
  96. package/dist/chunk-422427XJ.cjs.map +0 -1
  97. package/dist/chunk-7IAQ4HOK.js.map +0 -1
  98. package/dist/chunk-A7QC2ZVP.js.map +0 -1
  99. package/dist/chunk-DZIXKL7E.js +0 -145
  100. package/dist/chunk-DZIXKL7E.js.map +0 -1
  101. package/dist/chunk-EISO3POT.js.map +0 -1
  102. package/dist/chunk-EP7KOI2V.js +0 -571
  103. package/dist/chunk-EP7KOI2V.js.map +0 -1
  104. package/dist/chunk-FOJZNMMK.js.map +0 -1
  105. package/dist/chunk-ILU76UF3.js.map +0 -1
  106. package/dist/chunk-KVWV4ULP.js +0 -516
  107. package/dist/chunk-KVWV4ULP.js.map +0 -1
  108. package/dist/chunk-L7DMSMAG.cjs.map +0 -1
  109. package/dist/chunk-QC5T6D4J.js.map +0 -1
  110. package/dist/chunk-QOMNEWCQ.cjs.map +0 -1
  111. package/dist/chunk-TSFS5VKD.js.map +0 -1
  112. package/dist/chunk-VQ5W4MYO.js.map +0 -1
  113. package/dist/chunks-SX77P5CV.js +0 -10
  114. package/dist/image-ocr-FLIL7MGN.js.map +0 -1
  115. package/dist/image-ocr-WCAYXLOA.js.map +0 -1
  116. package/dist/image-ocr-ZTYAGV3W.cjs.map +0 -1
  117. package/dist/parser-A4TMPJAM.js.map +0 -1
  118. package/dist/parser-SCUTZAIJ.js.map +0 -1
  119. package/dist/parser-VCXE4I5A.cjs.map +0 -1
  120. package/dist/pdf-ocr-76SAUXMZ.js +0 -13
  121. package/dist/pdf-ocr-CPU55CVF.js +0 -16
  122. package/dist/pdf-ocr-MBZZ57LD.cjs +0 -14
  123. package/dist/redact-7ILEAUTS.js +0 -12
  124. package/dist/seal-RGUPOLXD.js +0 -10
  125. package/dist/visual-NZLYIYEM.js +0 -19
  126. /package/dist/{-AQKXLFIM.js.map → -Z4TJ3QGK.js.map} +0 -0
  127. /package/dist/{chunk-ZWD734EY.js.map → chunk-7SE4EZ45.js.map} +0 -0
  128. /package/dist/{chunk-GDW4YP7K.js.map → chunk-GLSBEEZJ.js.map} +0 -0
  129. /package/dist/{chunk-JQEFP45L.js.map → chunk-GUJ4Q73I.js.map} +0 -0
  130. /package/dist/{chunk-ZWOFQRIB.js.map → chunk-HIJUKZHM.js.map} +0 -0
  131. /package/dist/{chunk-TNCKOL2O.js.map → chunk-LCW7SEPG.js.map} +0 -0
  132. /package/dist/{chunk-UET462HB.js.map → chunk-TITDJWVZ.js.map} +0 -0
  133. /package/dist/{chunk-C7FQBSON.js.map → chunk-V3DX4DUF.js.map} +0 -0
  134. /package/dist/{chunk-DOGPOY4B.js.map → chunk-VDN7LMPL.js.map} +0 -0
  135. /package/dist/{chunk-EDNJLUSE.js.map → chunk-VJIL6PIL.js.map} +0 -0
  136. /package/dist/{chunk-NS55SM7A.js.map → chunk-WJJGW5PL.js.map} +0 -0
  137. /package/dist/{chunks-SX77P5CV.js.map → chunks-CCMRL4MJ.js.map} +0 -0
  138. /package/dist/{formula-JGFTXWYT.js.map → formula-7RANCW5L.js.map} +0 -0
  139. /package/dist/{formula-5S7WWXGH.js.map → formula-7UYJOVTB.js.map} +0 -0
  140. /package/dist/{model-bundle-FSPZZ2EM.js.map → model-bundle-2C5IYDLE.js.map} +0 -0
  141. /package/dist/{models-CJPAQK5R.js.map → models-SEQZHZFT.js.map} +0 -0
  142. /package/dist/{pdf-ocr-76SAUXMZ.js.map → pdf-ocr-UUBWBEHL.js.map} +0 -0
  143. /package/dist/{pdf-ocr-CPU55CVF.js.map → pdf-ocr-VJSF2SQC.js.map} +0 -0
  144. /package/dist/{profile-io-LBM263K7.js.map → profile-io-RUFZOZO6.js.map} +0 -0
  145. /package/dist/{rasterize-46RG4ZF6.js.map → rasterize-IOYXR5SI.js.map} +0 -0
  146. /package/dist/{redact-7ILEAUTS.js.map → redact-NMIKVHMP.js.map} +0 -0
  147. /package/dist/{render-NGP5T24S.js.map → render-YZ2TEC3N.js.map} +0 -0
  148. /package/dist/{seal-RGUPOLXD.js.map → seal-ECV44TUH.js.map} +0 -0
  149. /package/dist/{setup-AU4OCHNH.js.map → setup-MPIEP6XT.js.map} +0 -0
  150. /package/dist/{visual-NZLYIYEM.js.map → visual-ICMOWUCR.js.map} +0 -0
  151. /package/dist/{watch-MKPUCPXM.js.map → watch-RYO7MN5B.js.map} +0 -0
@@ -6,7 +6,7 @@ import {
6
6
  HEADING_RATIO_H1,
7
7
  HEADING_RATIO_H2,
8
8
  HEADING_RATIO_H3
9
- } from "./chunk-7IAQ4HOK.js";
9
+ } from "./chunk-6BWU6SQX.js";
10
10
  import {
11
11
  parsePageRange
12
12
  } from "./chunk-MOL7MDBG.js";
@@ -19,7 +19,7 @@ import {
19
19
  findChildByLocalName,
20
20
  hwpFaceToCssStack,
21
21
  parseRenderStyles
22
- } from "./chunk-ILU76UF3.js";
22
+ } from "./chunk-YAKC46HZ.js";
23
23
  import {
24
24
  MAX_COLS,
25
25
  MAX_ROWS,
@@ -29,17 +29,17 @@ import {
29
29
  dedupeRunningHeaders,
30
30
  flattenLayoutTables,
31
31
  mapPuaText
32
- } from "./chunk-QC5T6D4J.js";
32
+ } from "./chunk-NLU6LBLY.js";
33
33
  import {
34
34
  loadSharp,
35
35
  rasterizePageSvg
36
- } from "./chunk-C7FQBSON.js";
36
+ } from "./chunk-V3DX4DUF.js";
37
37
  import {
38
38
  KordocError,
39
39
  precheckZipSize,
40
40
  sanitizeHref,
41
41
  toArrayBuffer
42
- } from "./chunk-UET462HB.js";
42
+ } from "./chunk-TITDJWVZ.js";
43
43
 
44
44
  // src/render/svg-render.ts
45
45
  import JSZip from "jszip";
@@ -2813,6 +2813,7 @@ var TAG_TABLE = 77;
2813
2813
  var TAG_SHAPE_COMPONENT = 76;
2814
2814
  var TAG_SHAPE_COMPONENT_PICTURE = 85;
2815
2815
  var TAG_SHAPE_COMPONENT_CONTAINER = 86;
2816
+ var TAG_CTRL_DATA = 87;
2816
2817
  var TAG_EQEDIT = 88;
2817
2818
  var TAG_ID_MAPPINGS = 17;
2818
2819
  var TAG_BIN_DATA = 18;
@@ -2986,6 +2987,8 @@ function parseDocInfo(records) {
2986
2987
  }
2987
2988
  return { charShapes, paraShapes, styles, binData, numberings, bullets };
2988
2989
  }
2990
+ var LEADER_TAB_MARK = "";
2991
+ var LITERAL_DOLLAR_MARK = "\uFDD0";
2989
2992
  function createParaTextState() {
2990
2993
  return { text: "", ctrlIdx: 0, fieldStack: [], fieldRanges: [] };
2991
2994
  }
@@ -3039,8 +3042,9 @@ function appendParaText(state, data, resolveControl) {
3039
3042
  break;
3040
3043
  // 고정폭 공백
3041
3044
  // ── inline 타입 (2바이트 + 14바이트 확장) ──
3045
+ // 확장 u16[7] 중 [2] 의 하위 바이트 = 채움 모양(0 없음·3 점선 …), 상위 = 탭 종류+1 (rhwp tab_extended 실측)
3042
3046
  case CHAR_TAB:
3043
- result += " ";
3047
+ result += state.leaderMark && i + 14 <= data.length && data[i + 4] !== 0 ? LEADER_TAB_MARK : " ";
3044
3048
  if (i + 14 <= data.length) i += 14;
3045
3049
  break;
3046
3050
  default:
@@ -3073,7 +3077,7 @@ function appendParaText(state, data, resolveControl) {
3073
3077
  break;
3074
3078
  }
3075
3079
  }
3076
- result += String.fromCharCode(ch);
3080
+ result += ch === 36 && state.dollarMark ? LITERAL_DOLLAR_MARK : String.fromCharCode(ch);
3077
3081
  }
3078
3082
  break;
3079
3083
  }
@@ -3098,9 +3102,21 @@ function detectImageMime(data) {
3098
3102
  if (data[0] === 71 && data[1] === 73 && data[2] === 70) return "image/gif";
3099
3103
  if (data[0] === 66 && data[1] === 77) return "image/bmp";
3100
3104
  if (data[0] === 215 && data[1] === 205 && data[2] === 198 && data[3] === 154) return "image/wmf";
3105
+ if ((data[0] === 1 || data[0] === 2) && data[1] === 0 && data[2] === 9 && data[3] === 0) return "image/wmf";
3101
3106
  if (data[0] === 1 && data[1] === 0 && data[2] === 0 && data[3] === 0) return "image/emf";
3107
+ if (data[0] === 73 && data[1] === 73 && data[2] === 42 && data[3] === 0 || data[0] === 77 && data[1] === 77 && data[2] === 0 && data[3] === 42) return "image/tiff";
3102
3108
  return null;
3103
3109
  }
3110
+ function mimeExt(mime) {
3111
+ if (mime.includes("jpeg")) return "jpg";
3112
+ if (mime.includes("png")) return "png";
3113
+ if (mime.includes("gif")) return "gif";
3114
+ if (mime.includes("bmp")) return "bmp";
3115
+ if (mime.includes("tiff")) return "tif";
3116
+ if (mime.includes("wmf")) return "wmf";
3117
+ if (mime.includes("emf")) return "emf";
3118
+ return "bin";
3119
+ }
3104
3120
  function normalizeBinPayload(data) {
3105
3121
  if (detectImageMime(data)) return data;
3106
3122
  try {
@@ -3126,29 +3142,28 @@ function collectImageBlocks(blocks, out, depth = 0) {
3126
3142
  if (b.children) collectImageBlocks(b.children, out, depth + 1);
3127
3143
  }
3128
3144
  }
3129
- function forEachTableCell(blocks, fn) {
3145
+ var IMAGE_SENTINEL_RE = /!\[image\]\(hwp5bin:(\d+)\)/g;
3146
+ function resolveImageSentinels(blocks, renamed, depth = 0) {
3147
+ if (depth > MAX_BLOCK_DEPTH) return;
3148
+ const fix = (s) => s.includes("hwp5bin:") ? s.replace(IMAGE_SENTINEL_RE, (_m, idStr) => {
3149
+ const filename = renamed.get(Number(idStr));
3150
+ return filename ? `![image](${filename})` : "[\uC774\uBBF8\uC9C0]";
3151
+ }) : s;
3130
3152
  for (const b of blocks) {
3153
+ if (b.text) b.text = fix(b.text);
3154
+ if (b.footnoteText) b.footnoteText = fix(b.footnoteText);
3131
3155
  if (b.table) {
3156
+ if (b.table.caption) b.table.caption = fix(b.table.caption);
3132
3157
  for (const row of b.table.cells) {
3133
3158
  for (const cell of row) {
3134
- fn(cell);
3135
- if (cell.blocks) forEachTableCell(cell.blocks, fn);
3159
+ cell.text = fix(cell.text);
3160
+ if (cell.blocks) resolveImageSentinels(cell.blocks, renamed, depth + 1);
3136
3161
  }
3137
3162
  }
3138
3163
  }
3139
- if (b.children) forEachTableCell(b.children, fn);
3164
+ if (b.children) resolveImageSentinels(b.children, renamed, depth + 1);
3140
3165
  }
3141
3166
  }
3142
- var CELL_IMAGE_SENTINEL_RE = /!\[image\]\(hwp5bin:(\d+)\)/g;
3143
- function resolveCellImageSentinels(blocks, renamed) {
3144
- forEachTableCell(blocks, (cell) => {
3145
- if (!cell.text.includes("hwp5bin:")) return;
3146
- cell.text = cell.text.replace(CELL_IMAGE_SENTINEL_RE, (_m, idStr) => {
3147
- const filename = renamed.get(Number(idStr));
3148
- return filename ? `![image](${filename})` : "[\uC774\uBBF8\uC9C0]";
3149
- });
3150
- });
3151
- }
3152
3167
  function resolveImageBlocks(binDataMap, blocks, warnings, sweepUnreferenced) {
3153
3168
  const imageBlocks = [];
3154
3169
  collectImageBlocks(blocks, imageBlocks);
@@ -3173,7 +3188,7 @@ function resolveImageBlocks(binDataMap, blocks, warnings, sweepUnreferenced) {
3173
3188
  resolved.set(storageId, null);
3174
3189
  } else {
3175
3190
  imageIndex++;
3176
- const ext = mime.includes("jpeg") ? "jpg" : mime.includes("png") ? "png" : mime.includes("gif") ? "gif" : mime.includes("bmp") ? "bmp" : "bin";
3191
+ const ext = mimeExt(mime);
3177
3192
  img = { filename: `image_${String(imageIndex).padStart(3, "0")}.${ext}`, data: new Uint8Array(bin.data), mime };
3178
3193
  resolved.set(storageId, img);
3179
3194
  images.push({ filename: img.filename, data: img.data, mimeType: img.mime, source: bin.name });
@@ -3197,14 +3212,15 @@ function resolveImageBlocks(binDataMap, blocks, warnings, sweepUnreferenced) {
3197
3212
  const mime = detectImageMime(bin.data);
3198
3213
  if (!mime) continue;
3199
3214
  imageIndex++;
3200
- const ext = mime.includes("jpeg") ? "jpg" : mime.includes("png") ? "png" : mime.includes("gif") ? "gif" : mime.includes("bmp") ? "bmp" : "bin";
3215
+ const ext = mimeExt(mime);
3201
3216
  const filename = `image_${String(imageIndex).padStart(3, "0")}.${ext}`;
3202
3217
  const data = new Uint8Array(bin.data);
3203
3218
  images.push({ filename, data, mimeType: mime, source: bin.name });
3204
3219
  blocks.push({ type: "image", text: filename, imageData: { data, mimeType: mime, filename: bin.name } });
3220
+ renamed.set(storageId, filename);
3205
3221
  }
3206
3222
  }
3207
- resolveCellImageSentinels(blocks, renamed);
3223
+ resolveImageSentinels(blocks, renamed);
3208
3224
  return images;
3209
3225
  }
3210
3226
  function collectHwp5BinData(fileIndex) {
@@ -3237,7 +3253,7 @@ function collectHwp5BinDataLenient(lcfb) {
3237
3253
  function extractHwp5Images(fileIndex, blocks, warnings, sweepUnreferenced) {
3238
3254
  const binDataMap = collectHwp5BinData(fileIndex);
3239
3255
  if (binDataMap.size === 0) {
3240
- resolveCellImageSentinels(blocks, /* @__PURE__ */ new Map());
3256
+ resolveImageSentinels(blocks, /* @__PURE__ */ new Map());
3241
3257
  return [];
3242
3258
  }
3243
3259
  return resolveImageBlocks(binDataMap, blocks, warnings, sweepUnreferenced);
@@ -3245,7 +3261,7 @@ function extractHwp5Images(fileIndex, blocks, warnings, sweepUnreferenced) {
3245
3261
  function extractHwp5ImagesLenient(lcfb, blocks, warnings, sweepUnreferenced) {
3246
3262
  const binDataMap = collectHwp5BinDataLenient(lcfb);
3247
3263
  if (binDataMap.size === 0) {
3248
- resolveCellImageSentinels(blocks, /* @__PURE__ */ new Map());
3264
+ resolveImageSentinels(blocks, /* @__PURE__ */ new Map());
3249
3265
  return [];
3250
3266
  }
3251
3267
  return resolveImageBlocks(binDataMap, blocks, warnings, sweepUnreferenced);
@@ -5003,7 +5019,7 @@ function replaceBracket(strList) {
5003
5019
  }
5004
5020
  function hmlToLatex(hmlEqStr) {
5005
5021
  if (!hmlEqStr) return "";
5006
- let s = hmlEqStr.replace(/`/g, " ");
5022
+ let s = hmlEqStr.replace(/[\r\n\t]+/g, " ").replace(/`/g, " ");
5007
5023
  s = s.replace(/\{/g, " { ").replace(/\}/g, " } ").replace(/&/g, " & ");
5008
5024
  let tokens = s.split(" ");
5009
5025
  for (let i = 0; i < tokens.length; i++) {
@@ -5098,6 +5114,176 @@ function hwpEquationToLatex(equation) {
5098
5114
  return hmlToLatex(s).replace(/\s+/g, " ").trim();
5099
5115
  }
5100
5116
 
5117
+ // src/hwp5/ir-assemble.ts
5118
+ var INLINE_TABLE_MARK = "";
5119
+ var INLINE_JOIN = /* @__PURE__ */ new WeakSet();
5120
+ function emitParagraphBlocks(p) {
5121
+ const { headMarker, style, footnotes, objects, pageNumber } = p;
5122
+ const blocks = [];
5123
+ const decorate = (t) => {
5124
+ let deco = style?.strike ? `~~${t}~~` : t;
5125
+ if (style?.underline) deco = `<u>${deco}</u>`;
5126
+ return deco;
5127
+ };
5128
+ if (p.text.includes(INLINE_TABLE_MARK)) {
5129
+ const segments = p.text.split(INLINE_TABLE_MARK);
5130
+ let segIdx = 0;
5131
+ let first = true;
5132
+ let lineOpen = false;
5133
+ let markerPending = !!headMarker;
5134
+ const flush = () => {
5135
+ if (segIdx >= segments.length) return;
5136
+ const s = segments[segIdx++].replace(/\$\$/g, "$ $").trim();
5137
+ if (!s) return;
5138
+ let t = decorate(s);
5139
+ if (markerPending) {
5140
+ t = `${headMarker} ${t}`;
5141
+ markerPending = false;
5142
+ }
5143
+ const block = { type: "paragraph", text: t, pageNumber };
5144
+ if (first) {
5145
+ if (style) block.style = style;
5146
+ if (footnotes.length > 0) block.footnoteText = footnotes.join("; ");
5147
+ first = false;
5148
+ }
5149
+ if (lineOpen) INLINE_JOIN.add(block);
5150
+ lineOpen = true;
5151
+ blocks.push(block);
5152
+ };
5153
+ for (const obj of objects) {
5154
+ if (obj.table) {
5155
+ flush();
5156
+ if (obj.inline && lineOpen) for (const b of obj.blocks) INLINE_JOIN.add(b);
5157
+ lineOpen = obj.inline;
5158
+ }
5159
+ blocks.push(...obj.blocks);
5160
+ }
5161
+ while (segIdx < segments.length) flush();
5162
+ if (first && footnotes.length > 0) blocks.unshift({ type: "paragraph", text: `(\uC8FC: ${footnotes.join("; ")})`, pageNumber });
5163
+ return blocks;
5164
+ }
5165
+ const trimmed = p.text.replace(/\$\$/g, "$ $").trim();
5166
+ if (trimmed) {
5167
+ const block = {
5168
+ type: p.headingLevel > 0 ? "heading" : "paragraph",
5169
+ text: headMarker ? `${headMarker} ${trimmed}` : trimmed,
5170
+ pageNumber
5171
+ };
5172
+ if (p.headingLevel > 0) block.level = p.headingLevel;
5173
+ if (style) {
5174
+ block.style = style;
5175
+ if (style.strike || style.underline) block.text = headMarker ? `${headMarker} ${decorate(trimmed)}` : decorate(trimmed);
5176
+ }
5177
+ if (footnotes.length > 0) block.footnoteText = footnotes.join("; ");
5178
+ blocks.push(block);
5179
+ } else if (footnotes.length > 0) {
5180
+ blocks.push({ type: "paragraph", text: `(\uC8FC: ${footnotes.join("; ")})`, pageNumber });
5181
+ }
5182
+ for (const obj of objects) blocks.push(...obj.blocks);
5183
+ return blocks;
5184
+ }
5185
+ function tableFlatText(table) {
5186
+ const flat = convertTableToText(table.cells);
5187
+ return table.caption ? table.caption + (flat ? "\n" + flat : "") : flat;
5188
+ }
5189
+ function blocksPlainText(blocks, sep) {
5190
+ const parts = [];
5191
+ for (const b of blocks) {
5192
+ if (b.type === "image") continue;
5193
+ if (b.type === "table") {
5194
+ const flat = b.table ? tableFlatText(b.table) : "";
5195
+ if (flat) parts.push(flat);
5196
+ continue;
5197
+ }
5198
+ if (b.text) {
5199
+ let t = b.text;
5200
+ if (b.footnoteText) t += ` (\uC8FC: ${b.footnoteText})`;
5201
+ parts.push(t);
5202
+ }
5203
+ }
5204
+ return parts.join(sep).trim();
5205
+ }
5206
+ function cellTextFromBlocks(blocks) {
5207
+ let text = "";
5208
+ const add = (part, b) => {
5209
+ text += (text ? INLINE_JOIN.has(b) ? " " : "\n" : "") + part;
5210
+ };
5211
+ let hasStructure = false;
5212
+ for (const b of blocks) {
5213
+ if (b.type === "image" && b.text) {
5214
+ add(`![image](hwp5bin:${b.text})`, b);
5215
+ hasStructure = true;
5216
+ } else if (b.type === "table" && b.table) {
5217
+ const flat = tableFlatText(b.table);
5218
+ if (flat) add(flat, b);
5219
+ hasStructure = true;
5220
+ } else if (b.text) {
5221
+ if (b.footnoteText) {
5222
+ b.text += ` (\uC8FC: ${b.footnoteText})`;
5223
+ delete b.footnoteText;
5224
+ }
5225
+ add(b.text, b);
5226
+ }
5227
+ }
5228
+ return { text, hasStructure };
5229
+ }
5230
+ function resolveCellOverlaps(cells, rows, cols) {
5231
+ const owner = /* @__PURE__ */ new Map();
5232
+ const out = [];
5233
+ for (const cell of cells) {
5234
+ const r0 = cell.rowAddr ?? 0, c0 = cell.colAddr ?? 0;
5235
+ const hit = owner.get(r0 * cols + c0);
5236
+ if (hit) {
5237
+ if (cell.blocks?.length) {
5238
+ hit.blocks = [...hit.blocks ?? (hit.text ? [{ type: "paragraph", text: hit.text }] : []), ...cell.blocks];
5239
+ }
5240
+ if (cell.text.trim()) hit.text = hit.text.trim() ? `${hit.text}
5241
+ ${cell.text}` : cell.text;
5242
+ continue;
5243
+ }
5244
+ const csIn = Math.max(1, Math.min(cell.colSpan, cols - c0));
5245
+ let cs = cell.colSpan;
5246
+ for (let c = c0 + 1; c < c0 + csIn; c++) if (owner.has(r0 * cols + c)) {
5247
+ cs = c - c0;
5248
+ break;
5249
+ }
5250
+ const rsIn = Math.max(1, Math.min(cell.rowSpan, rows - r0));
5251
+ let rs = cell.rowSpan;
5252
+ scan: for (let r = r0 + 1; r < r0 + rsIn; r++) {
5253
+ for (let c = c0; c < c0 + Math.min(cs, csIn); c++) if (owner.has(r * cols + c)) {
5254
+ rs = r - r0;
5255
+ break scan;
5256
+ }
5257
+ }
5258
+ const placed = cs === cell.colSpan && rs === cell.rowSpan ? cell : { ...cell, colSpan: cs, rowSpan: rs };
5259
+ for (let r = r0; r < Math.min(r0 + rs, rows); r++) for (let c = c0; c < Math.min(c0 + cs, cols); c++) owner.set(r * cols + c, placed);
5260
+ out.push(placed);
5261
+ }
5262
+ return out;
5263
+ }
5264
+ function buildAddressedTable(cells, rows, cols, keepAnchoredEmptyCols) {
5265
+ for (const c of cells) {
5266
+ rows = Math.max(rows, Math.min((c.rowAddr ?? 0) + 1, MAX_ROWS));
5267
+ cols = Math.max(cols, Math.min((c.colAddr ?? 0) + 1, MAX_COLS));
5268
+ }
5269
+ const placed = resolveCellOverlaps(cells, rows, cols);
5270
+ const byRow = Array.from({ length: rows }, () => []);
5271
+ for (const c of placed) {
5272
+ const r = c.rowAddr ?? 0;
5273
+ if (r < rows && (c.colAddr ?? 0) < cols) byRow[r].push(c);
5274
+ }
5275
+ const table = buildTable(byRow, { keepAnchoredEmptyCols });
5276
+ if (table.rows === 0) return null;
5277
+ for (const c of placed) {
5278
+ if (!c.blocks?.length && !c.isHeader) continue;
5279
+ const target = table.cells[c.rowAddr ?? 0]?.[c.colAddr ?? 0];
5280
+ if (!target || target.text !== c.text.trim()) continue;
5281
+ if (c.blocks?.length) target.blocks = c.blocks;
5282
+ if (c.isHeader) target.isHeader = true;
5283
+ }
5284
+ return table;
5285
+ }
5286
+
5101
5287
  // src/hwp5/body.ts
5102
5288
  var MAX_NEST_DEPTH = 8;
5103
5289
  function cid(s) {
@@ -5247,8 +5433,13 @@ function parseParagraph(records, start, end, ctx) {
5247
5433
  }
5248
5434
  for (const ctrl of ctrls) {
5249
5435
  applyCtrlEffect(ctrl, records, ctx);
5436
+ if (ctrl.id === CTRL_TBL && ctrl.afterBlocks && ctrl.data.length >= 8 && ctrl.data.readUInt32LE(4) & 1) {
5437
+ ctrl.inlineText = INLINE_TABLE_MARK;
5438
+ }
5250
5439
  }
5251
5440
  const state = createParaTextState();
5441
+ state.leaderMark = true;
5442
+ state.dollarMark = true;
5252
5443
  const resolver = (idx, id) => {
5253
5444
  let ctrl = idx >= 0 && idx < ctrls.length ? ctrls[idx] : void 0;
5254
5445
  if (!ctrl || ctrl.idRaw !== id && ctrl.id !== id) {
@@ -5267,17 +5458,28 @@ function parseParagraph(records, start, end, ctx) {
5267
5458
  const applied = [];
5268
5459
  for (const r of ranges) {
5269
5460
  const ctrl = ctrls[r.ctrlIdx];
5270
- if (!ctrl?.href || r.end <= r.start) continue;
5461
+ if (!ctrl || r.end <= r.start) continue;
5271
5462
  if (applied.some(([s, e]) => r.start < e && r.end > s)) continue;
5463
+ const anchor = text.slice(r.start, r.end);
5464
+ if (ctrl.guide !== void 0) {
5465
+ const plain = anchor.replaceAll(LITERAL_DOLLAR_MARK, "$");
5466
+ if (plain === ctrl.guide || plain.trimEnd() === ctrl.guide) {
5467
+ text = text.slice(0, r.start) + text.slice(r.end);
5468
+ applied.push([r.start, r.end]);
5469
+ }
5470
+ continue;
5471
+ }
5472
+ if (!ctrl.href) continue;
5272
5473
  const href = sanitizeHref(ctrl.href);
5273
5474
  if (!href) continue;
5274
- const anchor = text.slice(r.start, r.end);
5275
- if (!anchor.trim()) continue;
5475
+ if (!anchor.trim() || anchor.includes(INLINE_TABLE_MARK) || anchor.includes(LEADER_TAB_MARK)) continue;
5276
5476
  text = text.slice(0, r.start) + `[${anchor}](${href})` + text.slice(r.end);
5277
5477
  applied.push([r.start, r.end]);
5278
5478
  }
5279
5479
  }
5280
- const trimmed = text.replace(/\$\$/g, "$ $").trim();
5480
+ const leaderAt = text.indexOf(LEADER_TAB_MARK);
5481
+ if (leaderAt >= 0) text = text.slice(0, leaderAt);
5482
+ if (text.includes(LITERAL_DOLLAR_MARK)) text = text.replaceAll(LITERAL_DOLLAR_MARK, "\\$");
5281
5483
  let headingLevel = 0;
5282
5484
  let headMarker = null;
5283
5485
  const ps = ctx.docInfo && paraShapeId >= 0 && paraShapeId < ctx.docInfo.paraShapes.length ? ctx.docInfo.paraShapes[paraShapeId] : null;
@@ -5301,35 +5503,16 @@ function parseParagraph(records, start, end, ctx) {
5301
5503
  if (bullet && bullet.char !== "\uFFFF") headMarker = bullet.char;
5302
5504
  }
5303
5505
  }
5304
- const blocks = [];
5305
- const footnotes = ctrls.filter((c) => c.footnote).map((c) => c.footnote);
5306
- if (trimmed) {
5307
- const block = {
5308
- type: headingLevel > 0 ? "heading" : "paragraph",
5309
- text: headMarker ? `${headMarker} ${trimmed}` : trimmed,
5310
- pageNumber: ctx.page
5311
- };
5312
- if (headingLevel > 0) block.level = headingLevel;
5313
- if (ctx.docInfo && charShapeIds.length > 0) {
5314
- const style = resolveCharStyle(charShapeIds, ctx.docInfo);
5315
- if (style) {
5316
- block.style = style;
5317
- if (style.strike || style.underline) {
5318
- let deco = style.strike ? `~~${trimmed}~~` : trimmed;
5319
- if (style.underline) deco = `<u>${deco}</u>`;
5320
- block.text = headMarker ? `${headMarker} ${deco}` : deco;
5321
- }
5322
- }
5323
- }
5324
- if (footnotes.length > 0) block.footnoteText = footnotes.join("; ");
5325
- blocks.push(block);
5326
- } else if (footnotes.length > 0) {
5327
- blocks.push({ type: "paragraph", text: `(\uC8FC: ${footnotes.join("; ")})`, pageNumber: ctx.page });
5328
- }
5329
- for (const ctrl of ctrls) {
5330
- if (ctrl.afterBlocks) blocks.push(...ctrl.afterBlocks);
5331
- }
5332
- return blocks;
5506
+ return emitParagraphBlocks({
5507
+ text,
5508
+ headMarker,
5509
+ headingLevel,
5510
+ style: ctx.docInfo && charShapeIds.length > 0 ? resolveCharStyle(charShapeIds, ctx.docInfo) : void 0,
5511
+ footnotes: ctrls.filter((c) => c.footnote).map((c) => c.footnote),
5512
+ // 컨트롤 파생 블록 (표/이미지/글상자) — 컨트롤 순서대로
5513
+ objects: ctrls.filter((c) => c.afterBlocks).map((c) => ({ blocks: c.afterBlocks, table: c.id === CTRL_TBL, inline: c.inlineText === INLINE_TABLE_MARK })),
5514
+ pageNumber: ctx.page
5515
+ });
5333
5516
  }
5334
5517
  function applyCtrlEffect(ctrl, records, ctx) {
5335
5518
  switch (ctrl.id) {
@@ -5424,19 +5607,6 @@ function parseListHeaderParagraphs(ctrl, records, ctx) {
5424
5607
  }
5425
5608
  return [];
5426
5609
  }
5427
- function blocksPlainText(blocks, sep) {
5428
- const parts = [];
5429
- for (const b of blocks) {
5430
- if (b.type === "image") continue;
5431
- if (b.type === "table") continue;
5432
- if (b.text) {
5433
- let t = b.text;
5434
- if (b.footnoteText) t += ` (\uC8FC: ${b.footnoteText})`;
5435
- parts.push(t);
5436
- }
5437
- }
5438
- return parts.join(sep).trim();
5439
- }
5440
5610
  function applyNoteEffect(ctrl, records, ctx, autoType) {
5441
5611
  const num3 = ctx.doc.autoCounters.get(autoType) ?? 1;
5442
5612
  let before = "";
@@ -5475,8 +5645,18 @@ function applyFieldEffect(ctrl) {
5475
5645
  const url = hyperlinkUrlFromCommand(command);
5476
5646
  if (url) ctrl.href = url;
5477
5647
  }
5648
+ } else if (ctrl.id === FIELD_CLK && ctrl.data.length >= 8 && !(ctrl.data.readUInt32LE(4) & 1 << 15)) {
5649
+ const command = parseFieldCommand(ctrl.data);
5650
+ const guide = command ? clickHereGuide(command) : void 0;
5651
+ if (guide) ctrl.guide = guide;
5478
5652
  }
5479
5653
  }
5654
+ function clickHereGuide(command) {
5655
+ const m = /Direction:wstring:(\d+):/.exec(command);
5656
+ if (!m) return void 0;
5657
+ const start = m.index + m[0].length;
5658
+ return command.slice(start, start + Number(m[1])) || void 0;
5659
+ }
5480
5660
  function parseFieldCommand(data) {
5481
5661
  if (data.length < 11) return null;
5482
5662
  const cmdLen = data.readUInt16LE(9);
@@ -5505,18 +5685,19 @@ function parseTableControl(ctrl, records, ctx) {
5505
5685
  if (ctx.depth >= MAX_NEST_DEPTH) return null;
5506
5686
  const { childStart, childEnd } = ctrl;
5507
5687
  const sourceId = ctx.tableIds?.get(childStart - 1);
5688
+ const directLevel = records[childStart - 1].level + 1;
5508
5689
  let rows = 0;
5509
5690
  let cols = 0;
5510
5691
  let tableIdx = -1;
5511
5692
  for (let i2 = childStart; i2 < childEnd; i2++) {
5512
- if (records[i2].tagId === TAG_TABLE && records[i2].data.length >= 8) {
5693
+ if (records[i2].tagId === TAG_TABLE && records[i2].level === directLevel && records[i2].data.length >= 8) {
5513
5694
  rows = Math.min(records[i2].data.readUInt16LE(4), MAX_ROWS);
5514
5695
  cols = Math.min(records[i2].data.readUInt16LE(6), MAX_COLS);
5515
5696
  tableIdx = i2;
5516
5697
  break;
5517
5698
  }
5518
5699
  }
5519
- if (tableIdx < 0 || rows === 0 || cols === 0) return null;
5700
+ if (tableIdx < 0) return null;
5520
5701
  let caption;
5521
5702
  for (let i2 = childStart; i2 < tableIdx; i2++) {
5522
5703
  if (records[i2].tagId === TAG_LIST_HEADER) {
@@ -5546,20 +5727,17 @@ function parseTableControl(ctrl, records, ctx) {
5546
5727
  i++;
5547
5728
  }
5548
5729
  if (cells.length === 0) return null;
5549
- const hasAddr = cells.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0);
5550
- if (hasAddr) {
5551
- const cellRows2 = arrangeCells(rows, cols, cells);
5552
- const irCells = cellRows2.map((row) => row.map((c) => {
5553
- const ir = { text: c.text.trim(), colSpan: c.colSpan, rowSpan: c.rowSpan };
5554
- if (c.blocks?.length) ir.blocks = c.blocks;
5555
- if (c.isHeader) ir.isHeader = true;
5556
- return ir;
5557
- }));
5558
- const table2 = { rows, cols, cells: irCells, hasHeader: rows > 1 };
5730
+ if (cells.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0)) {
5731
+ const table2 = buildAddressedTable(cells, rows, cols, ctx.doc.keepTrailingEmptyCols);
5732
+ if (!table2) return null;
5559
5733
  if (caption) table2.caption = caption;
5560
5734
  if (sourceId) table2.sourceId = sourceId;
5561
5735
  return table2;
5562
5736
  }
5737
+ if (rows === 0 || cols === 0) {
5738
+ rows = Math.min(cells.length, MAX_ROWS);
5739
+ cols = 1;
5740
+ }
5563
5741
  const cellRows = arrangeCells(rows, cols, cells);
5564
5742
  const table = buildTable(cellRows, { keepAnchoredEmptyCols: ctx.doc.keepTrailingEmptyCols });
5565
5743
  if (caption && table.rows > 0) table.caption = caption;
@@ -5583,38 +5761,19 @@ function parseCell(records, lhIdx, end, ctx) {
5583
5761
  if (rs > 0) rowSpan = Math.min(rs, MAX_ROWS);
5584
5762
  }
5585
5763
  const blocks = ctx.depth < MAX_NEST_DEPTH ? parseParagraphList(records, lhIdx + 1, end, { ...ctx, depth: ctx.depth + 1 }) : [];
5586
- const parts = [];
5587
- let hasStructure = false;
5588
- for (const b of blocks) {
5589
- if (b.type === "image" && b.text) {
5590
- parts.push(`![image](hwp5bin:${b.text})`);
5591
- hasStructure = true;
5592
- } else if (b.type === "table" && b.table) {
5593
- const flat = convertTableToText(b.table.cells);
5594
- if (flat) parts.push(flat);
5595
- hasStructure = true;
5596
- } else if (b.text) {
5597
- let t = b.text;
5598
- if (b.footnoteText) {
5599
- t += ` (\uC8FC: ${b.footnoteText})`;
5600
- hasStructure = true;
5601
- }
5602
- parts.push(t);
5603
- }
5604
- }
5605
- const cell = { text: parts.join("\n"), colSpan, rowSpan, colAddr, rowAddr };
5764
+ const { text, hasStructure } = cellTextFromBlocks(blocks);
5765
+ const cell = { text, colSpan, rowSpan, colAddr, rowAddr };
5606
5766
  if (hasStructure && blocks.length > 0) cell.blocks = blocks;
5607
5767
  if (isHeader) cell.isHeader = true;
5608
5768
  return cell;
5609
5769
  }
5610
5770
  function arrangeCells(rows, cols, cells) {
5611
5771
  const grid = Array.from({ length: rows }, () => Array(cols).fill(null));
5612
- const hasAddr = cells.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0);
5613
- if (hasAddr) {
5614
- for (const cell of cells) {
5615
- const r = cell.rowAddr ?? 0;
5616
- const c = cell.colAddr ?? 0;
5617
- if (r >= rows || c >= cols) continue;
5772
+ let cellIdx = 0;
5773
+ for (let r = 0; r < rows && cellIdx < cells.length; r++) {
5774
+ for (let c = 0; c < cols && cellIdx < cells.length; c++) {
5775
+ if (grid[r][c] !== null) continue;
5776
+ const cell = cells[cellIdx++];
5618
5777
  grid[r][c] = cell;
5619
5778
  for (let dr = 0; dr < cell.rowSpan; dr++) {
5620
5779
  for (let dc = 0; dc < cell.colSpan; dc++) {
@@ -5624,22 +5783,6 @@ function arrangeCells(rows, cols, cells) {
5624
5783
  }
5625
5784
  }
5626
5785
  }
5627
- } else {
5628
- let cellIdx = 0;
5629
- for (let r = 0; r < rows && cellIdx < cells.length; r++) {
5630
- for (let c = 0; c < cols && cellIdx < cells.length; c++) {
5631
- if (grid[r][c] !== null) continue;
5632
- const cell = cells[cellIdx++];
5633
- grid[r][c] = cell;
5634
- for (let dr = 0; dr < cell.rowSpan; dr++) {
5635
- for (let dc = 0; dc < cell.colSpan; dc++) {
5636
- if (dr === 0 && dc === 0) continue;
5637
- if (r + dr < rows && c + dc < cols)
5638
- grid[r + dr][c + dc] = { text: "", colSpan: 1, rowSpan: 1 };
5639
- }
5640
- }
5641
- }
5642
- }
5643
5786
  }
5644
5787
  return grid.map((row) => row.map((c) => c || { text: "", colSpan: 1, rowSpan: 1 }));
5645
5788
  }
@@ -5893,7 +6036,7 @@ function parseHwp5Document(buffer, options) {
5893
6036
  }
5894
6037
  const outline = flatBlocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
5895
6038
  let markdown = blocksToMarkdown(flatBlocks);
5896
- if (options?.inlineImages && images.length > 0) {
6039
+ if (options?.inlineImages && options.images !== false && images.length > 0) {
5897
6040
  try {
5898
6041
  markdown = inlineImagesIntoMarkdown(markdown, images, { compress: true });
5899
6042
  } catch (inlineErr) {
@@ -5974,6 +6117,11 @@ function detectHwp5Headings(blocks, docInfo) {
5974
6117
  }
5975
6118
  }
5976
6119
  }
6120
+ var VT_I2 = 2;
6121
+ var VT_LPSTR = 30;
6122
+ var VT_LPWSTR = 31;
6123
+ var VT_FILETIME = 64;
6124
+ var CODE_PAGE_LABELS = { 949: "euc-kr", 932: "shift_jis", 936: "gbk", 950: "big5", 65001: "utf-8" };
5977
6125
  function extractHwp5Metadata(cfb, metadata) {
5978
6126
  try {
5979
6127
  const summaryEntry = CFB.find(cfb, "/HwpSummaryInformation") || CFB.find(cfb, "/SummaryInformation");
@@ -5986,26 +6134,60 @@ function extractHwp5Metadata(cfb, metadata) {
5986
6134
  if (setOffset >= data.length - 8) return;
5987
6135
  const numProps = data.readUInt32LE(setOffset + 4);
5988
6136
  if (numProps === 0 || numProps > 100) return;
6137
+ const props = /* @__PURE__ */ new Map();
5989
6138
  for (let i = 0; i < numProps; i++) {
5990
6139
  const entryOffset = setOffset + 8 + i * 8;
5991
6140
  if (entryOffset + 8 > data.length) break;
5992
- const propId = data.readUInt32LE(entryOffset);
5993
6141
  const propOffset = setOffset + data.readUInt32LE(entryOffset + 4);
5994
- if (propOffset + 8 > data.length) continue;
5995
- if (propId !== 2 && propId !== 4 && propId !== 6) continue;
5996
- const propType = data.readUInt32LE(propOffset);
5997
- if (propType !== 30) continue;
5998
- const strLen = data.readUInt32LE(propOffset + 4);
5999
- if (strLen === 0 || strLen > 1e4 || propOffset + 8 + strLen > data.length) continue;
6000
- const str = data.subarray(propOffset + 8, propOffset + 8 + strLen).toString("utf8").replace(/\0+$/, "").trim();
6001
- if (!str) continue;
6002
- if (propId === 2) metadata.title = str;
6003
- else if (propId === 4) metadata.author = str;
6004
- else if (propId === 6) metadata.description = str;
6142
+ if (propOffset + 8 <= data.length) props.set(data.readUInt32LE(entryOffset), propOffset);
6005
6143
  }
6144
+ const cpAt = props.get(1);
6145
+ const codePage = cpAt !== void 0 && data.readUInt32LE(cpAt) === VT_I2 ? data.readUInt16LE(cpAt + 4) : 0;
6146
+ const text = (id) => {
6147
+ const at = props.get(id);
6148
+ return at === void 0 ? void 0 : readPropString(data, at, codePage);
6149
+ };
6150
+ const time = (id) => {
6151
+ const at = props.get(id);
6152
+ return at === void 0 ? void 0 : readPropFileTime(data, at);
6153
+ };
6154
+ const title = text(2), author = text(4), description = text(6) || text(3);
6155
+ if (title) metadata.title = title;
6156
+ if (author) metadata.author = author;
6157
+ if (description) metadata.description = description;
6158
+ const keywords = text(5)?.split(/[,;]/).map((k) => k.trim()).filter(Boolean);
6159
+ if (keywords?.length) metadata.keywords = keywords;
6160
+ const createdAt = time(12), modifiedAt = time(13);
6161
+ if (createdAt) metadata.createdAt = createdAt;
6162
+ if (modifiedAt) metadata.modifiedAt = modifiedAt;
6006
6163
  } catch {
6007
6164
  }
6008
6165
  }
6166
+ function readPropString(data, at, codePage) {
6167
+ const type = data.readUInt32LE(at);
6168
+ const unit = type === VT_LPWSTR ? 2 : type === VT_LPSTR ? 1 : 0;
6169
+ const count = data.readUInt32LE(at + 4);
6170
+ if (!unit || count === 0 || count > 1e4 || at + 8 + count * unit > data.length) return void 0;
6171
+ const bytes = data.subarray(at + 8, at + 8 + count * unit);
6172
+ let s;
6173
+ if (unit === 2 || codePage === 1200) s = bytes.toString("utf16le");
6174
+ else {
6175
+ const label = CODE_PAGE_LABELS[codePage] ?? (codePage >= 1250 && codePage <= 1258 ? `windows-${codePage}` : "utf-8");
6176
+ try {
6177
+ s = new TextDecoder(label).decode(bytes);
6178
+ } catch {
6179
+ s = bytes.toString("utf8");
6180
+ }
6181
+ }
6182
+ const nul = s.indexOf("\0");
6183
+ return (nul >= 0 ? s.slice(0, nul) : s).trim() || void 0;
6184
+ }
6185
+ function readPropFileTime(data, at) {
6186
+ if (data.readUInt32LE(at) !== VT_FILETIME || at + 12 > data.length) return void 0;
6187
+ const ticks = data.readBigUInt64LE(at + 4);
6188
+ if (ticks === 0n) return void 0;
6189
+ return new Date((Number(ticks / 10000000n) - 11644473600) * 1e3).toISOString().replace(".000Z", "Z");
6190
+ }
6009
6191
  function extractHwp5MetadataOnly(buffer) {
6010
6192
  const cfb = CFB.parse(buffer);
6011
6193
  const headerEntry = CFB.find(cfb, "/FileHeader");
@@ -7080,16 +7262,25 @@ export {
7080
7262
  TAG_CTRL_HEADER,
7081
7263
  TAG_LIST_HEADER,
7082
7264
  TAG_TABLE,
7265
+ TAG_CTRL_DATA,
7083
7266
  FLAG_COMPRESSED,
7084
7267
  FLAG_ENCRYPTED,
7085
7268
  FLAG_DISTRIBUTION,
7086
7269
  FLAG_DRM,
7270
+ readRecords,
7087
7271
  decompressStream,
7088
7272
  parseFileHeader,
7089
7273
  createParaTextState,
7090
7274
  isExtendedOnlyCtrlChar,
7091
7275
  appendParaText,
7092
7276
  detectImageMime,
7277
+ formatNumber,
7278
+ hwpEquationToLatex,
7279
+ INLINE_TABLE_MARK,
7280
+ emitParagraphBlocks,
7281
+ blocksPlainText,
7282
+ cellTextFromBlocks,
7283
+ buildAddressedTable,
7093
7284
  parseHwp5Document,
7094
7285
  extractHwp5MetadataOnly,
7095
7286
  charWidthEm1000,
@@ -7119,4 +7310,4 @@ export {
7119
7310
  cropRect,
7120
7311
  extractRenderedRegions
7121
7312
  };
7122
- //# sourceMappingURL=chunk-TSFS5VKD.js.map
7313
+ //# sourceMappingURL=chunk-D4U2TXDC.js.map