kordoc 4.18.2 → 4.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/{-I3CP33G4.js → -DDAVBMHD.js} +11 -11
  2. package/dist/{chunk-O2DI4GHD.js → chunk-274ZPMHK.js} +2 -2
  3. package/dist/{chunk-QGFZU3JE.cjs → chunk-3WLZOJIE.cjs} +10 -8
  4. package/dist/chunk-3WLZOJIE.cjs.map +1 -0
  5. package/dist/{chunk-UZGZRGYM.cjs → chunk-3XSP7V5P.cjs} +10 -5
  6. package/dist/chunk-3XSP7V5P.cjs.map +1 -0
  7. package/dist/{chunk-GM7XIZF2.js → chunk-4IBY5LTJ.js} +2 -2
  8. package/dist/chunk-6H25SXDI.js +11 -0
  9. package/dist/chunk-6H25SXDI.js.map +1 -0
  10. package/dist/{chunk-N5DQFA7L.js → chunk-7GR2GCJF.js} +10 -5
  11. package/dist/chunk-7GR2GCJF.js.map +1 -0
  12. package/dist/{chunk-YNLW6EGU.cjs → chunk-AVIZ55NQ.cjs} +3 -3
  13. package/dist/chunk-AVIZ55NQ.cjs.map +1 -0
  14. package/dist/chunk-DC6CTQTK.js +9 -0
  15. package/dist/chunk-DC6CTQTK.js.map +1 -0
  16. package/dist/{chunk-L5RLJPI3.js → chunk-DUV7Y6IQ.js} +3 -3
  17. package/dist/{chunk-KDMAYOWH.cjs → chunk-E2644XCO.cjs} +698 -189
  18. package/dist/chunk-E2644XCO.cjs.map +1 -0
  19. package/dist/{chunk-LSOD2A6N.js → chunk-ELOPDQES.js} +2 -2
  20. package/dist/{chunk-M4P7YS2N.js → chunk-F2GDLA45.js} +81 -61
  21. package/dist/chunk-F2GDLA45.js.map +1 -0
  22. package/dist/{chunk-OBILAVWC.js → chunk-F5YVCJVF.js} +10 -5
  23. package/dist/chunk-F5YVCJVF.js.map +1 -0
  24. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  25. package/dist/{chunk-4B2EXELH.js → chunk-HRJJDNRD.js} +2 -2
  26. package/dist/{chunk-CKUIFTXJ.js → chunk-IAXGGQGD.js} +2 -2
  27. package/dist/{chunk-BL7KRE6X.js → chunk-IBQCK4F3.js} +7 -3
  28. package/dist/chunk-IBQCK4F3.js.map +1 -0
  29. package/dist/chunk-J55UQC5H.cjs.map +1 -1
  30. package/dist/{chunk-OGAYGUJF.js → chunk-KUUSP6OS.js} +581 -72
  31. package/dist/chunk-KUUSP6OS.js.map +1 -0
  32. package/dist/{chunk-LACO375L.js → chunk-LGF2IO66.js} +4 -3
  33. package/dist/chunk-LGF2IO66.js.map +1 -0
  34. package/dist/{chunk-L64QRUMK.js → chunk-MXA6YW2W.js} +582 -73
  35. package/dist/chunk-MXA6YW2W.js.map +1 -0
  36. package/dist/{chunk-OI5ZSSIC.cjs → chunk-OIUSF2VA.cjs} +16 -12
  37. package/dist/chunk-OIUSF2VA.cjs.map +1 -0
  38. package/dist/{chunk-6OKBTY72.js → chunk-QVCHFCT2.js} +2 -2
  39. package/dist/{chunk-C2CVOC5K.js → chunk-RCI7LY4N.js} +8 -4
  40. package/dist/chunk-RCI7LY4N.js.map +1 -0
  41. package/dist/{chunk-W2YYBPW5.cjs → chunk-SVNBZEL6.cjs} +3 -3
  42. package/dist/chunk-SVNBZEL6.cjs.map +1 -0
  43. package/dist/{chunk-VSY5PAJ5.js → chunk-T2BJPT6D.js} +3 -3
  44. package/dist/{chunk-VSY5PAJ5.js.map → chunk-T2BJPT6D.js.map} +1 -1
  45. package/dist/chunk-TK3FDAEE.cjs +9 -0
  46. package/dist/chunk-TK3FDAEE.cjs.map +1 -0
  47. package/dist/{chunk-F5HING4Y.js → chunk-TMJVD6FW.js} +5 -4
  48. package/dist/chunk-TMJVD6FW.js.map +1 -0
  49. package/dist/{chunk-T4MXCSBP.js → chunk-V5X4LLVM.js} +71 -47
  50. package/dist/chunk-V5X4LLVM.js.map +1 -0
  51. package/dist/{chunk-IA3UKDHA.js → chunk-VTVK2JMI.js} +3 -2
  52. package/dist/{chunk-IA3UKDHA.js.map → chunk-VTVK2JMI.js.map} +1 -1
  53. package/dist/{chunk-B2E6C2LH.js → chunk-XG4SYOZL.js} +6 -4
  54. package/dist/chunk-XG4SYOZL.js.map +1 -0
  55. package/dist/{chunk-QP7IXF7R.js → chunk-YCY2R4FM.js} +2 -2
  56. package/dist/{chunk-NZM2SSI4.js → chunk-Z2PPDQK2.js} +2 -2
  57. package/dist/chunks-5QTTAT5T.js +10 -0
  58. package/dist/cli.js +179 -119
  59. package/dist/cli.js.map +1 -1
  60. package/dist/{formula-E3N7KDDG.js → formula-7ZOZ5QJ6.js} +8 -4
  61. package/dist/{formula-E3N7KDDG.js.map → formula-7ZOZ5QJ6.js.map} +1 -1
  62. package/dist/{formula-AQZODKZF.js → formula-HQFZEXFF.js} +7 -3
  63. package/dist/{formula-AQZODKZF.js.map → formula-HQFZEXFF.js.map} +1 -1
  64. package/dist/{formula-VY4ITOMN.cjs → formula-YYJQBKEN.cjs} +13 -9
  65. package/dist/formula-YYJQBKEN.cjs.map +1 -0
  66. package/dist/{image-ocr-IMYXOHHV.js → image-ocr-4BGX2EJJ.js} +7 -6
  67. package/dist/{image-ocr-IMYXOHHV.js.map → image-ocr-4BGX2EJJ.js.map} +1 -1
  68. package/dist/{image-ocr-6LYEBMVR.cjs → image-ocr-CC26Q5KG.cjs} +16 -15
  69. package/dist/image-ocr-CC26Q5KG.cjs.map +1 -0
  70. package/dist/{image-ocr-LN3GSQPW.js → image-ocr-RK3HJVCI.js} +10 -9
  71. package/dist/{image-ocr-LN3GSQPW.js.map → image-ocr-RK3HJVCI.js.map} +1 -1
  72. package/dist/index.cjs +860 -817
  73. package/dist/index.cjs.map +1 -1
  74. package/dist/index.js +141 -98
  75. package/dist/index.js.map +1 -1
  76. package/dist/mcp.js +26 -26
  77. package/dist/mcp.js.map +1 -1
  78. package/dist/{model-bundle-IHKNDLOT.js → model-bundle-VHRXG63R.js} +5 -5
  79. package/dist/{models-YXITRAMR.js → models-G3WA24SY.js} +5 -5
  80. package/dist/page-range-QHHFTL7X.cjs.map +1 -1
  81. package/dist/{parser-7KECZTTP.cjs → parser-BGORCLIU.cjs} +461 -243
  82. package/dist/parser-BGORCLIU.cjs.map +1 -0
  83. package/dist/{parser-M3T2EWUN.js → parser-GFDGAVLV.js} +255 -37
  84. package/dist/parser-GFDGAVLV.js.map +1 -0
  85. package/dist/{parser-KB4BYQBZ.js → parser-SOWTUOMK.js} +258 -40
  86. package/dist/parser-SOWTUOMK.js.map +1 -0
  87. package/dist/pdf-ocr-7IOOVR2I.js +20 -0
  88. package/dist/pdf-ocr-EJ2HNZN6.cjs +17 -0
  89. package/dist/pdf-ocr-EJ2HNZN6.cjs.map +1 -0
  90. package/dist/pdf-ocr-RACAZU3N.js +16 -0
  91. package/dist/{profile-io-GQWQR7YQ.js → profile-io-Q2T47RVH.js} +3 -3
  92. package/dist/{rasterize-Y6TVFQ3M.js → rasterize-OAVMUTE6.js} +3 -3
  93. package/dist/{redact-doc-TRPZ3HNW.js → redact-doc-ECFOVR4X.js} +11 -11
  94. package/dist/{render-GHT5HKBO.js → render-NSKWZVTD.js} +7 -7
  95. package/dist/seal-A4MG7MPQ.js +10 -0
  96. package/dist/{setup-AGSCEHDB.js → setup-REH2KZP2.js} +3 -3
  97. package/dist/visual-B56WQAGW.js +20 -0
  98. package/dist/{watch-ALSEW4GB.js → watch-JXDUZYBY.js} +13 -13
  99. package/dist/watch-JXDUZYBY.js.map +1 -0
  100. package/package.json +1 -1
  101. package/dist/chunk-B2E6C2LH.js.map +0 -1
  102. package/dist/chunk-BL7KRE6X.js.map +0 -1
  103. package/dist/chunk-C2CVOC5K.js.map +0 -1
  104. package/dist/chunk-F5HING4Y.js.map +0 -1
  105. package/dist/chunk-KDMAYOWH.cjs.map +0 -1
  106. package/dist/chunk-L64QRUMK.js.map +0 -1
  107. package/dist/chunk-LACO375L.js.map +0 -1
  108. package/dist/chunk-M4P7YS2N.js.map +0 -1
  109. package/dist/chunk-N5DQFA7L.js.map +0 -1
  110. package/dist/chunk-OBILAVWC.js.map +0 -1
  111. package/dist/chunk-OGAYGUJF.js.map +0 -1
  112. package/dist/chunk-OI5ZSSIC.cjs.map +0 -1
  113. package/dist/chunk-QGFZU3JE.cjs.map +0 -1
  114. package/dist/chunk-T4MXCSBP.js.map +0 -1
  115. package/dist/chunk-UZGZRGYM.cjs.map +0 -1
  116. package/dist/chunk-W2YYBPW5.cjs.map +0 -1
  117. package/dist/chunk-YNLW6EGU.cjs.map +0 -1
  118. package/dist/chunks-IFFRC5IQ.js +0 -10
  119. package/dist/formula-VY4ITOMN.cjs.map +0 -1
  120. package/dist/image-ocr-6LYEBMVR.cjs.map +0 -1
  121. package/dist/parser-7KECZTTP.cjs.map +0 -1
  122. package/dist/parser-KB4BYQBZ.js.map +0 -1
  123. package/dist/parser-M3T2EWUN.js.map +0 -1
  124. package/dist/pdf-ocr-4S2OAHUX.js +0 -15
  125. package/dist/pdf-ocr-IGYCZ7G2.cjs +0 -16
  126. package/dist/pdf-ocr-IGYCZ7G2.cjs.map +0 -1
  127. package/dist/pdf-ocr-YEBFWU2K.js +0 -19
  128. package/dist/seal-3YTXSABW.js +0 -10
  129. package/dist/visual-R3E35Q2K.js +0 -20
  130. package/dist/watch-ALSEW4GB.js.map +0 -1
  131. /package/dist/{-I3CP33G4.js.map → -DDAVBMHD.js.map} +0 -0
  132. /package/dist/{chunk-O2DI4GHD.js.map → chunk-274ZPMHK.js.map} +0 -0
  133. /package/dist/{chunk-GM7XIZF2.js.map → chunk-4IBY5LTJ.js.map} +0 -0
  134. /package/dist/{chunk-L5RLJPI3.js.map → chunk-DUV7Y6IQ.js.map} +0 -0
  135. /package/dist/{chunk-LSOD2A6N.js.map → chunk-ELOPDQES.js.map} +0 -0
  136. /package/dist/{chunk-4B2EXELH.js.map → chunk-HRJJDNRD.js.map} +0 -0
  137. /package/dist/{chunk-CKUIFTXJ.js.map → chunk-IAXGGQGD.js.map} +0 -0
  138. /package/dist/{chunk-6OKBTY72.js.map → chunk-QVCHFCT2.js.map} +0 -0
  139. /package/dist/{chunk-QP7IXF7R.js.map → chunk-YCY2R4FM.js.map} +0 -0
  140. /package/dist/{chunk-NZM2SSI4.js.map → chunk-Z2PPDQK2.js.map} +0 -0
  141. /package/dist/{chunks-IFFRC5IQ.js.map → chunks-5QTTAT5T.js.map} +0 -0
  142. /package/dist/{model-bundle-IHKNDLOT.js.map → model-bundle-VHRXG63R.js.map} +0 -0
  143. /package/dist/{models-YXITRAMR.js.map → models-G3WA24SY.js.map} +0 -0
  144. /package/dist/{pdf-ocr-4S2OAHUX.js.map → pdf-ocr-7IOOVR2I.js.map} +0 -0
  145. /package/dist/{pdf-ocr-YEBFWU2K.js.map → pdf-ocr-RACAZU3N.js.map} +0 -0
  146. /package/dist/{profile-io-GQWQR7YQ.js.map → profile-io-Q2T47RVH.js.map} +0 -0
  147. /package/dist/{rasterize-Y6TVFQ3M.js.map → rasterize-OAVMUTE6.js.map} +0 -0
  148. /package/dist/{redact-doc-TRPZ3HNW.js.map → redact-doc-ECFOVR4X.js.map} +0 -0
  149. /package/dist/{render-GHT5HKBO.js.map → render-NSKWZVTD.js.map} +0 -0
  150. /package/dist/{seal-3YTXSABW.js.map → seal-A4MG7MPQ.js.map} +0 -0
  151. /package/dist/{setup-AGSCEHDB.js.map → setup-REH2KZP2.js.map} +0 -0
  152. /package/dist/{visual-R3E35Q2K.js.map → visual-B56WQAGW.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  blocksToPages,
3
3
  encodePng
4
- } from "./chunk-O2DI4GHD.js";
4
+ } from "./chunk-274ZPMHK.js";
5
5
  import {
6
6
  hasRequestedPagesAfter,
7
7
  parsePageRange
@@ -12,6 +12,8 @@ import {
12
12
  CONT_PARTS,
13
13
  EMPTY_PARTS,
14
14
  FILLER_CELLS,
15
+ FRAME_READING_UNITS,
16
+ FRAME_TITLE_BLOCKS,
15
17
  IMAGE_CELLS,
16
18
  NO_EDGES,
17
19
  PART_COLXS,
@@ -22,6 +24,7 @@ import {
22
24
  TOC_BLOCKS,
23
25
  WrapLexicon,
24
26
  collapseEvenSpacing,
27
+ computeBBox,
25
28
  computeMedianFontSizeFromFreq,
26
29
  detectDocumentStyleHeadings,
27
30
  detectHeadings,
@@ -29,26 +32,32 @@ import {
29
32
  detectMarkerHeadings,
30
33
  detectPageLeadHeadings,
31
34
  detectRepeatedPageLabels,
35
+ detectRightArrowRegions,
32
36
  detectSiblingStyleHeadings,
33
37
  detectTableCaptions,
34
38
  detectTypographyHeadings,
39
+ dominantStyle,
35
40
  extractImageRegions,
36
41
  extractLines,
37
42
  extractPageBlocksWithLines,
38
43
  filterHiddenText,
44
+ groupByY,
39
45
  joinCellEdges,
40
46
  joinPageBreakWraps,
41
47
  latinSoftWrap,
48
+ mergeLineSimple,
42
49
  mergeStackedHeadingLines,
43
50
  normalizeItems,
44
51
  ocrModelsCached,
52
+ recordFrameReadingUnit,
45
53
  refineDocumentStyleHeadings,
46
54
  removeHeaderFooterBlocks,
47
55
  removeSideTabs,
56
+ restoreImageBullets,
48
57
  startsNewItem,
49
58
  trimTrailingEmptyTableCols,
50
59
  wrapJoiner
51
- } from "./chunk-L64QRUMK.js";
60
+ } from "./chunk-MXA6YW2W.js";
52
61
  import {
53
62
  CELL_EDGES,
54
63
  CONTENT_CELLS,
@@ -58,12 +67,12 @@ import {
58
67
  escapeLiteralTags,
59
68
  stripScriptTags,
60
69
  unframeLayoutTables
61
- } from "./chunk-B2E6C2LH.js";
62
- import "./chunk-LSOD2A6N.js";
70
+ } from "./chunk-XG4SYOZL.js";
71
+ import "./chunk-ELOPDQES.js";
63
72
  import {
64
73
  KordocError,
65
74
  sanitizeHref
66
- } from "./chunk-N5DQFA7L.js";
75
+ } from "./chunk-7GR2GCJF.js";
67
76
 
68
77
  // src/pdf/ocr-region-merge.ts
69
78
  function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
@@ -76,8 +85,10 @@ function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
76
85
  const overlapH = Math.max(0, Math.min(b.y + b.height, region.y2) - Math.max(b.y, region.y1));
77
86
  return overlapW * overlapH >= b.width * b.height * 0.8;
78
87
  });
88
+ const labels = candidates.filter((b) => b.type === "paragraph" && b.bbox.height <= 24 && (b.text?.match(/[\p{L}\p{N}]/gu)?.length ?? 0) >= 2);
89
+ const axisFragments = rotatedAxisFragments(candidates);
79
90
  const accepted = candidates.filter((b) => {
80
- if (b.type === "paragraph") return (b.text?.match(/[\p{L}\p{N}]/gu)?.length ?? 0) >= 2;
91
+ if (b.type === "paragraph") return (b.text?.match(/[\p{L}\p{N}]/gu)?.length ?? 0) >= 2 || !axisFragments.has(b) && supportedDiagramLabel(b, labels, region);
81
92
  const t = b.table;
82
93
  if (b.type !== "table" || !t) return false;
83
94
  if (t.rows === 1 && t.cols === 1) {
@@ -88,29 +99,89 @@ function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
88
99
  return t.rows >= 2 && t.cols >= 2 && headerLabels >= t.cols * 0.75 && t.cells.slice(1).some((row) => row.filter((c) => c.text.trim()).length >= 2);
89
100
  });
90
101
  const selected = candidates.flatMap((b) => accepted.includes(b) ? [b] : b.type === "table" && b.table ? rowParagraphs(b).filter((p) => /[\p{L}\p{N}]{2}/u.test(p.text ?? "")) : []);
91
- for (const block of selected) {
102
+ const hasOriginal = (block) => blocks.some((existing) => {
92
103
  const b = block.bbox;
93
- const hasOriginal = blocks.some((existing) => {
94
- if (existing.pageNumber !== page || !existing.bbox || existing.type === "image") return false;
95
- const e = existing.bbox;
96
- const x = Math.max(0, Math.min(e.x + e.width, b.x + b.width) - Math.max(e.x, b.x));
97
- const y = Math.max(0, Math.min(e.y + e.height, b.y + b.height) - Math.max(e.y, b.y));
98
- return x * y > b.width * b.height * 0.2;
99
- });
100
- if (hasOriginal) continue;
101
- const index = blocks.findIndex((existing) => {
102
- const e = existing.bbox;
103
- if (existing.pageNumber !== page || !e) return false;
104
- const beside = e.y < region.y2 && e.y + e.height > region.y1 && e.x >= region.x2 - 1;
105
- return e.y < b.y || beside;
106
- });
107
- const placed = block.type === "paragraph" ? { ...block, style: void 0 } : block;
108
- blocks.splice(index < 0 ? blocks.length : index, 0, placed);
109
- added++;
104
+ if (existing.pageNumber !== page || !existing.bbox || existing.type === "image") return false;
105
+ const e = existing.bbox;
106
+ const x = Math.max(0, Math.min(e.x + e.width, b.x + b.width) - Math.max(e.x, b.x));
107
+ const y = Math.max(0, Math.min(e.y + e.height, b.y + b.height) - Math.max(e.y, b.y));
108
+ return x * y > b.width * b.height * 0.2;
109
+ });
110
+ const selectedSet = new Set(selected), seen = /* @__PURE__ */ new Set();
111
+ for (const block of selected) {
112
+ if (seen.has(block)) continue;
113
+ const frame = FRAME_READING_UNITS.get(block);
114
+ const source = frame?.blocks.every((member) => selectedSet.has(member)) ? frame.blocks : [block];
115
+ source.forEach((member) => seen.add(member));
116
+ const available = source.filter((member) => !hasOriginal(member));
117
+ const units = frame && available.length === source.length && source === frame.blocks ? [{ blocks: available, bbox: frame.bbox, atomic: true }] : available.map((member) => ({ blocks: [member], bbox: member.bbox, atomic: false }));
118
+ for (const unit of units) {
119
+ const b = unit.bbox;
120
+ const index = blocks.findIndex((existing) => {
121
+ const e = FRAME_READING_UNITS.get(existing)?.bbox ?? existing.bbox;
122
+ if (existing.pageNumber !== page || !e) return false;
123
+ const beside = e.y < region.y2 && e.y + e.height > region.y1 && e.x >= region.x2 - 1;
124
+ return e.y < b.y || beside;
125
+ });
126
+ const placed = unit.blocks.map((member) => member.type === "paragraph" ? { ...member, style: void 0 } : member);
127
+ if (unit.atomic) recordFrameReadingUnit(placed, unit.bbox);
128
+ blocks.splice(index < 0 ? blocks.length : index, 0, ...placed);
129
+ added += placed.length;
130
+ }
110
131
  }
111
132
  }
112
133
  return added;
113
134
  }
135
+ function supportedDiagramLabel(block, labels, region) {
136
+ const b = block.bbox, text = block.text?.trim() ?? "";
137
+ if (!b || !/^[\p{L}\p{N}]$/u.test(text) || b.height < 4 || b.width < 1 || b.width > b.height * 2 || b.x < region.x1 || b.y < region.y1 || b.x + b.width > region.x2 || b.y + b.height > region.y2 || b.width * b.height > (region.x2 - region.x1) * (region.y2 - region.y1) * 5e-3 || labels.length < 3 || !labels.some((l) => /\p{L}{3}/u.test(l.text ?? "")) || labels.filter((l) => !/\p{L}/u.test(l.text ?? "") && (l.text?.match(/\p{N}/gu)?.length ?? 0) >= 2).length < 2) return false;
138
+ let above = false, below = false;
139
+ for (const label of labels) {
140
+ const a = label.bbox, em = Math.max(b.height, a.height);
141
+ if (b.x + b.width < a.x - em * 2 || b.x > a.x + a.width + em * 2) continue;
142
+ const upperGap = a.y - (b.y + b.height), lowerGap = b.y - (a.y + a.height);
143
+ if (upperGap >= 0 && upperGap <= em * 4) above = true;
144
+ if (lowerGap >= 0 && lowerGap <= em * 4) below = true;
145
+ }
146
+ return above && below;
147
+ }
148
+ function rotatedAxisFragments(candidates) {
149
+ const paragraphs = candidates.filter((b) => b.type === "paragraph" && b.bbox.height <= 24);
150
+ const axes = [];
151
+ for (const block of paragraphs) {
152
+ const b = block.bbox, text = block.text?.trim() ?? "";
153
+ if (!/^[\d\s.,%+−-]+$/u.test(text) || !/\d/u.test(text) || b.width > b.height * 6) continue;
154
+ const axis = axes.find((a) => Math.abs(a[0].bbox.x + a[0].bbox.width - b.x - b.width) <= Math.max(a[0].bbox.height, b.height) * 0.5);
155
+ if (axis) axis.push(block);
156
+ else axes.push([block]);
157
+ }
158
+ const fragments = /* @__PURE__ */ new Set();
159
+ const aligned = (a, b) => {
160
+ const x = a.bbox, y = b.bbox, tolerance = Math.max(x.height, y.height) * 0.5;
161
+ return Math.abs(x.x - y.x) <= tolerance || Math.abs(x.x + x.width - y.x - y.width) <= tolerance;
162
+ };
163
+ for (const axis of axes) {
164
+ if (axis.length < 3) continue;
165
+ const bottom = Math.min(...axis.map((a) => a.bbox.y)), top = Math.max(...axis.map((a) => a.bbox.y + a.bbox.height));
166
+ const em = Math.max(...axis.map((a) => a.bbox.height)), right = axis[0].bbox.x + axis[0].bbox.width;
167
+ if (top - bottom < em * 6) continue;
168
+ const left = paragraphs.filter((block) => {
169
+ const b = block.bbox, text = block.text?.trim() ?? "";
170
+ return /\p{Script=Latin}/u.test(text) && (text.match(/[\p{L}\p{N}]/gu)?.length ?? 0) <= 3 && b.width <= b.height * 3 && b.x + b.width >= right - em * 6 && b.x + b.width <= right - Math.max(em, b.height) && b.y >= bottom && b.y + b.height <= top;
171
+ });
172
+ const stack = left.filter((a) => left.some((b) => {
173
+ if (a === b || !aligned(a, b)) return false;
174
+ const x = a.bbox, y = b.bbox, gap = Math.max(x.y, y.y) - Math.min(x.y + x.height, y.y + y.height);
175
+ return gap >= -Math.min(x.height, y.height) * 0.5 && gap <= Math.max(x.height, y.height);
176
+ }));
177
+ if (stack.length < 2) continue;
178
+ for (const block of paragraphs) {
179
+ const b = block.bbox;
180
+ if (b.y >= bottom && b.y + b.height <= top && b.x + b.width >= right - em * 6 && b.x + b.width <= right - Math.max(em, b.height) && /^[\p{L}\p{N}]$/u.test(block.text?.trim() ?? "") && stack.some((s) => aligned(s, block))) fragments.add(block);
181
+ }
182
+ }
183
+ return fragments;
184
+ }
114
185
  function rowParagraphs(block) {
115
186
  const t = block.table, b = block.bbox;
116
187
  const h = b.height / t.rows;
@@ -916,6 +987,17 @@ var CARRIED_MIN_COL_W = 4;
916
987
  var LABEL_ROOM = 1.5;
917
988
  var HANGING_MIN = 0.5;
918
989
  var HANGING_TOL = 1;
990
+ var KO_ITEMS = "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC\uC544\uC790\uCC28\uCE74\uD0C0\uD30C\uD558\uAC70\uB108\uB354\uB7EC\uBA38\uBC84\uC11C\uC5B4\uC800\uCC98\uCEE4\uD130\uD37C\uD5C8\uACE0\uB178\uB3C4\uB85C\uBAA8\uBCF4\uC18C\uC624\uC870\uCD08\uCF54\uD1A0\uD3EC\uD638\uAD6C\uB204\uB450\uB8E8\uBB34\uBD80\uC218\uC6B0\uC8FC\uCD94\uCFE0\uD22C\uD478\uD6C4";
991
+ var ITEM_MARK = /^\s*(?:([가-힣])\.|(\d{1,3})[.)]|\(([가-힣\d]{1,3})\))(?=\s)/;
992
+ function nextItemHead(prev, next) {
993
+ const a = ITEM_MARK.exec(prev), b = ITEM_MARK.exec(next);
994
+ if (!a || !b) return false;
995
+ const succ = (x, y) => /^\d+$/.test(x) ? /^\d+$/.test(y) && Number(y) === Number(x) + 1 : KO_ITEMS.indexOf(x) >= 0 && KO_ITEMS.indexOf(y) === KO_ITEMS.indexOf(x) + 1;
996
+ if (a[1] && b[1]) return succ(a[1], b[1]);
997
+ if (a[2] && b[2]) return succ(a[2], b[2]) && prev.trimStart()[a[2].length] === next.trimStart()[b[2].length];
998
+ if (a[3] && b[3]) return succ(a[3], b[3]);
999
+ return false;
1000
+ }
919
1001
  function continuesAcross(u, d, x1, x2) {
920
1002
  const U = CELL_LINES.get(u), D = CELL_LINES.get(d);
921
1003
  if (!U?.length || !D?.length) return false;
@@ -1047,6 +1129,8 @@ function mergeSplitRow(table, owner, first, colXs, textOnly = false, cut = NO_CU
1047
1129
  if (!carriedSplit) {
1048
1130
  const norm = (c) => flowText(c.text).replace(/\s+/g, "");
1049
1131
  if (pairs.some(([u, d]) => hasContent(d.cell) && norm(cell(d)) !== norm(cell(u)) && lineEnded(cell(u), colXs[u.c], colXs[u.c + u.cs], cell(d)))) return false;
1132
+ const oneLine = (c) => CELL_LINES.get(c)?.length === 1;
1133
+ if (pairs.some(([u, d]) => nextItemHead(cell(u).text, cell(d).text)) && pairs.some(([u, d]) => hasContent(u.cell) && hasContent(d.cell) && oneLine(cell(u)) && oneLine(cell(d)) && norm(cell(u)) !== norm(cell(d)))) return false;
1050
1134
  const flows = ([u, d]) => continuesAcross(cell(u), cell(d), colXs[u.c], colXs[u.c + u.cs]) || clauseContinues(cell(u), cell(d));
1051
1135
  if (!(cut.open && !newCell)) {
1052
1136
  if (pairs.some((p) => p[1].rs > 1 && !flows(p))) return false;
@@ -1107,7 +1191,7 @@ function sameHeadShape(a, b) {
1107
1191
  let tall = false;
1108
1192
  for (let c = 0; c < a.length; c++) {
1109
1193
  if (a[c].colSpan !== b[c].colSpan || a[c].rowSpan !== b[c].rowSpan) return false;
1110
- if (a[c].rowSpan >= 2 && a[c].text.trim()) tall = true;
1194
+ if (a[c].rowSpan >= 2 && a[c].text.trim() && b[c].text.trim()) tall = true;
1111
1195
  }
1112
1196
  return tall;
1113
1197
  }
@@ -1144,9 +1228,10 @@ function mergeCrossPageTables(blocks, pageHeights, lex) {
1144
1228
  if (px && cx && !shiftedSame(px, cx, !CLIP_TABLES.has(prev.table) && !CLIP_TABLES.has(curr.table))) continue;
1145
1229
  if (!rowTextsEqual(prev.table.cells[0], curr.table.cells[0]) && sameHeadShape(prev.table.cells[0], curr.table.cells[0])) continue;
1146
1230
  let currCells = curr.table.cells;
1147
- if (currCells.length > 1 && prev.table.cells.length > 0 && rowTextsEqual(prev.table.cells[0], currCells[0])) {
1148
- currCells = currCells.slice(1);
1149
- }
1231
+ const headRows = repeatedHeaderRows(prev.table, curr.table);
1232
+ if (headRows < 0) continue;
1233
+ if (headRows) currCells = currCells.slice(headRows);
1234
+ if (currCells.length) continueRowSpans(prev.table.cells, currCells);
1150
1235
  if (currCells.length === 0) {
1151
1236
  blocks.splice(j, 1);
1152
1237
  continue;
@@ -1348,6 +1433,45 @@ function chainHead(blocks, i, pageHeights) {
1348
1433
  }
1349
1434
  return k;
1350
1435
  }
1436
+ var ROW_CONTINUATIONS = /* @__PURE__ */ new WeakMap();
1437
+ function continueRowSpans(prevCells, currCells) {
1438
+ const first = currCells[0];
1439
+ const last = prevCells.length;
1440
+ for (let c = 0; c < first.length; c++) {
1441
+ const cell = first[c];
1442
+ if (hasContent(cell) || (cell.rowSpan || 1) < 2) continue;
1443
+ let anchor;
1444
+ for (let r = last - 1; r >= 0 && !anchor; r--) {
1445
+ const a = prevCells[r]?.[c];
1446
+ if (a && r + (a.rowSpan || 1) === last && (a.colSpan || 1) === (cell.colSpan || 1) && (hasContent(a) || a.rowSpan >= 2)) anchor = a;
1447
+ }
1448
+ if (!anchor) continue;
1449
+ if (!hasContent(anchor)) {
1450
+ ROW_CONTINUATIONS.set(anchor, cell);
1451
+ continue;
1452
+ }
1453
+ for (let part = cell; part; ) {
1454
+ const next = ROW_CONTINUATIONS.get(part);
1455
+ anchor.rowSpan = (anchor.rowSpan || 1) + part.rowSpan;
1456
+ part.rowSpan = 1;
1457
+ part.colSpan = 1;
1458
+ ROW_CONTINUATIONS.delete(part);
1459
+ part = next;
1460
+ }
1461
+ }
1462
+ }
1463
+ function repeatedHeaderRows(prev, curr) {
1464
+ if (!rowTextsEqual(prev.cells[0], curr.cells[0])) return 0;
1465
+ const pa = anchorsOf(prev), ca = anchorsOf(curr);
1466
+ let depth = 1;
1467
+ for (let r = 0; r < depth && r < prev.rows; r++) {
1468
+ for (const a of pa) if (a.r === r) depth = Math.max(depth, r + a.rs);
1469
+ }
1470
+ if (depth >= curr.rows || depth > prev.rows) return -1;
1471
+ const p = pa.filter((a) => a.r < depth), d = ca.filter((a) => a.r < depth);
1472
+ const norm = (text) => flowText(text).replace(/\s+/g, "");
1473
+ return p.length === d.length && p.every((a, i) => a.r === d[i].r && a.c === d[i].c && a.rs === d[i].rs && a.cs === d[i].cs && norm(a.cell.text) === norm(d[i].cell.text)) ? depth : -1;
1474
+ }
1351
1475
  function rowTextsEqual(a, b) {
1352
1476
  if (a.length !== b.length) return false;
1353
1477
  const norm = (t) => flowText(t).replace(/\s+/g, "");
@@ -1442,6 +1566,34 @@ function fillNestedContinuation(blocks, at) {
1442
1566
  blocks.splice(at, 1);
1443
1567
  }
1444
1568
 
1569
+ // src/pdf/selection-context.ts
1570
+ function selectionContextPages(selected, pageCount) {
1571
+ const out = /* @__PURE__ */ new Set();
1572
+ for (const page of selected) {
1573
+ for (let distance = 1; distance <= 4; distance++) {
1574
+ for (const neighbor of [page - distance, page + distance]) {
1575
+ if (neighbor < 1 || neighbor > pageCount || selected.has(neighbor)) continue;
1576
+ out.add(neighbor);
1577
+ }
1578
+ }
1579
+ }
1580
+ return [...out].sort((a, b) => a - b);
1581
+ }
1582
+ function marginContextBlocks(raw, page, view) {
1583
+ const [x1, y1, x2, y2] = view;
1584
+ const width = x2 - x1, height = y2 - y1;
1585
+ const items = filterHiddenText(normalizeItems(raw), width, height, x1, y1).visible;
1586
+ for (const item of items) {
1587
+ item.x -= x1;
1588
+ item.y -= y1;
1589
+ }
1590
+ return groupByY(items).flatMap((line) => {
1591
+ const bbox = computeBBox(line, page);
1592
+ if (bbox.y + bbox.height < height * 0.88 && bbox.y > height * 0.12) return [];
1593
+ return [{ type: "paragraph", text: mergeLineSimple(line), pageNumber: page, bbox, style: dominantStyle(line) }];
1594
+ });
1595
+ }
1596
+
1445
1597
  // src/pdf/symbol-fonts.ts
1446
1598
  var WINANSI_REVERSE = {
1447
1599
  8364: 128,
@@ -1749,6 +1901,9 @@ var NAMED = {
1749
1901
  quotedblright: "\u201D",
1750
1902
  quotesingle: "'",
1751
1903
  quotedbl: '"',
1904
+ bullet: "\u2022",
1905
+ openbullet: "\u25E6",
1906
+ whitebullet: "\u25E6",
1752
1907
  question: "?",
1753
1908
  exclam: "!",
1754
1909
  percent: "%",
@@ -1765,7 +1920,9 @@ function glyphNameText(name) {
1765
1920
  let out = "";
1766
1921
  for (const part of base.split("_")) {
1767
1922
  const uni = /^uni([0-9A-F]{4})$/.exec(part) ?? /^u([0-9A-F]{4,6})$/.exec(part);
1768
- const ch = /^[A-Za-z]$/.test(part) ? part : NAMED[part] ?? (uni ? String.fromCodePoint(parseInt(uni[1], 16)) : void 0);
1923
+ const code = uni ? parseInt(uni[1], 16) : void 0;
1924
+ if (code !== void 0 && (code > 1114111 || code >= 55296 && code <= 57343)) return void 0;
1925
+ const ch = /^[A-Za-z]$/.test(part) ? part : NAMED[part] ?? (code !== void 0 ? String.fromCodePoint(code) : void 0);
1769
1926
  if (ch === void 0) return void 0;
1770
1927
  out += ch;
1771
1928
  }
@@ -2451,6 +2608,35 @@ function demoteNonHeadingRoles(blocks, pageHeights, faceNames) {
2451
2608
  }
2452
2609
  }
2453
2610
  }
2611
+ const citedProse = /* @__PURE__ */ new Set();
2612
+ const numberedProse = /* @__PURE__ */ new Set();
2613
+ for (const page of byPage.values()) {
2614
+ const numbered = page.filter((b) => (b.type === "heading" || b.type === "paragraph") && /^[①-⑮]\s*/.test(b.text?.trim() ?? "") && b.bbox && b.style?.fontName && b.style.fontSize && !/Bold|Black|Heavy|Semibold/i.test(faceNames?.get(b.style.fontName) ?? ""));
2615
+ let chain = [];
2616
+ const finish = () => {
2617
+ if (chain.length < 3 || !chain.some((b) => (b.text?.length ?? 0) >= 40 && b.bbox.height >= b.style.fontSize * 2.4)) return;
2618
+ for (const b of chain) numberedProse.add(b);
2619
+ const first = chain[0], size = first.style.fontSize;
2620
+ for (const b of page) if (/^[○●•◦]\s/.test(b.text?.trim() ?? "") && b.style?.fontName === first.style?.fontName && b.style?.fontSize === size && b.bbox && Math.abs(b.bbox.x - first.bbox.x) <= size * 0.5 && (b.text?.length ?? 0) >= 15) numberedProse.add(b);
2621
+ };
2622
+ for (const b of numbered) {
2623
+ const prev = chain.at(-1), size = b.style.fontSize;
2624
+ if (!prev || b.text.trim().charCodeAt(0) !== prev.text.trim().charCodeAt(0) + 1 || b.style.fontName !== prev.style.fontName || size !== prev.style.fontSize || Math.abs(b.bbox.x - prev.bbox.x) > size * 0.5 || prev.bbox.y - (b.bbox.y + b.bbox.height) > size * 8) {
2625
+ finish();
2626
+ chain = [];
2627
+ }
2628
+ chain.push(b);
2629
+ }
2630
+ finish();
2631
+ }
2632
+ for (let i = 0; i + 1 < blocks.length; i++) {
2633
+ const prose = blocks[i], reference = blocks[i + 1];
2634
+ const a = prose.bbox, b = reference.bbox, size = prose.style?.fontSize ?? 0;
2635
+ const source = reference.text?.replace(/<[^>]+>/g, "").trim() ?? "";
2636
+ if (prose.type !== "heading" && prose.type !== "paragraph" && prose.type !== "list" || reference.type !== "heading" && reference.type !== "paragraph" || (prose.text?.length ?? 0) < 40 || !a || !b || size <= 0 || a.height < size * 2.4 || prose.pageNumber !== reference.pageNumber || prose.style?.fontName !== reference.style?.fontName || prose.style?.fontSize !== reference.style?.fontSize || Math.abs(a.x - b.x) > size && !(/^[○●•◦]\s/.test(prose.text ?? "") && b.x >= a.x && b.x - a.x <= size * 2) || a.y - (b.y + b.height) < 0 || a.y - (b.y + b.height) > size || !/^[((].*(?:제\s*\d+\s*조|(?:Article|Section)\s+\d+).*[))]$/i.test(source)) continue;
2637
+ citedProse.add(prose);
2638
+ citedProse.add(reference);
2639
+ }
2454
2640
  for (let i = 0; i < blocks.length; i++) {
2455
2641
  const block = blocks[i];
2456
2642
  if (block.type !== "heading" || !block.text) continue;
@@ -2498,7 +2684,7 @@ function demoteNonHeadingRoles(blocks, pageHeights, faceNames) {
2498
2684
  const byline = /Italic|Oblique/i.test(face) && !/Bold|Black|Heavy|Semibold/i.test(face) && !!bodyFace && size <= Number(bodySize) + 0.5 && blocks[i - 1]?.type === "heading" && blocks[i - 1].pageNumber === block.pageNumber;
2499
2685
  const ocrFragment = block.style?.fontName === "ocr" && (/^[.,;:…·•-]/.test(text) || text.includes("\u2026") || (text.match(/\p{L}/gu)?.length ?? 0) < 2 || text.split(/\s+/).length > 7);
2500
2686
  const crowdedOcr = block.style?.fontName === "ocr" && !!box && [prev, next].every((o) => o?.type === "paragraph" && o.pageNumber === block.pageNumber && o.style?.fontName === "ocr" && !!o.bbox && (o.text?.length ?? 0) >= 15 && Math.abs(o.bbox.x - box.x) <= size * 0.25 && Math.min(o.bbox.y + o.bbox.height, box.y + box.height) - Math.max(o.bbox.y, box.y) >= o.bbox.height * 0.2) && prev.bbox.y > box.y && next.bbox.y < box.y;
2501
- if (ocrFragment || crowdedOcr || tocEntry || proseStyle || kicker || byline || tiny || !/\p{L}/u.test(text) && !chapterNumber || /^[a-z]/.test(text) || CAPTION.test(text) || EQUATION_NUMBER.test(block.text) || DISPLAY_MATH.test(text) || // 닫는 괄호가 여는 괄호보다 많으면 앞 줄에서 이어진 문장 조각이다 ("Fact-checking) and is used …") — "1)"·"가)" 앞머리 번호는 빼고 센다
2687
+ if (numberedProse.has(block) || citedProse.has(block) || ocrFragment || crowdedOcr || tocEntry || proseStyle || kicker || byline || tiny || !/\p{L}/u.test(text) && !chapterNumber || /^[a-z]/.test(text) || CAPTION.test(text) || EQUATION_NUMBER.test(block.text) || DISPLAY_MATH.test(text) || // 닫는 괄호가 여는 괄호보다 많으면 앞 줄에서 이어진 문장 조각이다 ("Fact-checking) and is used …") — "1)"·"가)" 앞머리 번호는 빼고 센다
2502
2688
  unbalancedClose(text.replace(/^\s*[\dA-Za-z가-힣ⅰ-ⅹ]{1,3}\)\s*/, "")) || isRunningHead(block, page, pageHeights.get(block.pageNumber ?? 0))) {
2503
2689
  block.type = "paragraph";
2504
2690
  block.level = void 0;
@@ -2539,6 +2725,11 @@ function splitSingleCellTables(blocks) {
2539
2725
  const out = [];
2540
2726
  for (const b of blocks) {
2541
2727
  const t = b.type === "table" ? b.table : void 0;
2728
+ const title = t && FRAME_TITLE_BLOCKS.get(t);
2729
+ if (title) {
2730
+ out.push({ ...title, text: `${t.cells[0][0].text.trim()} ${t.cells[0][2].text.trim()}` });
2731
+ continue;
2732
+ }
2542
2733
  const only = t && t.rows === 1 && t.cols === 1 && t.cells[0]?.[0]?.blocks?.length === 1 ? t.cells[0][0].blocks[0] : void 0;
2543
2734
  const squash = (s) => s.replace(/\s/g, "");
2544
2735
  const inner = only && (!squash(t.cells[0][0].text) || only.type === "table" && squash(t.cells[0][0].text) === squash(only.table.cells.flat().map((c) => c.text).join(""))) ? only : void 0;
@@ -2548,12 +2739,16 @@ function splitSingleCellTables(blocks) {
2548
2739
  continue;
2549
2740
  }
2550
2741
  const cell = t && t.rows === 1 && t.cols === 1 ? t.cells[0]?.[0] : void 0;
2551
- if (!cell || cell.blocks?.some((x) => x.type === "table")) {
2742
+ if (!cell) {
2552
2743
  out.push(b);
2553
2744
  continue;
2554
2745
  }
2555
2746
  const lines = (cell.text ?? "").split(/\n/).map((l) => l.trim()).filter(Boolean);
2556
2747
  if (t?.caption?.trim()) out.push({ type: "paragraph", text: t.caption.trim(), pageNumber: b.pageNumber, bbox: b.bbox });
2748
+ if (cell.blocks?.length) {
2749
+ out.push(...splitSingleCellTables(cell.blocks));
2750
+ continue;
2751
+ }
2557
2752
  for (const text of lines) out.push({ type: "paragraph", text, pageNumber: b.pageNumber, bbox: b.bbox });
2558
2753
  }
2559
2754
  return out;
@@ -2678,7 +2873,7 @@ function mergeLinkRuns(markdown) {
2678
2873
 
2679
2874
  // src/pdf/formula-ocr.ts
2680
2875
  async function applyFormulaOcr(buffer, blocks, pageFilter, effectivePageCount, warnings, _onProgress) {
2681
- const formulaMod = await import("./formula-AQZODKZF.js");
2876
+ const formulaMod = await import("./formula-HQFZEXFF.js");
2682
2877
  const { FormulaPipeline, ensureFormulaModels } = formulaMod;
2683
2878
  await ensureFormulaModels((p) => {
2684
2879
  if (p.phase === "download" && p.total) {
@@ -2901,12 +3096,29 @@ async function parsePdfDocument(buffer, options) {
2901
3096
  const uncoveredImageRegions = /* @__PURE__ */ new Map();
2902
3097
  const largeImageRegions = /* @__PURE__ */ new Set();
2903
3098
  const imageState = createPdfImageState();
3099
+ const imageBulletShapes = /* @__PURE__ */ new Map();
3100
+ const imageArrowDirections = /* @__PURE__ */ new Map();
2904
3101
  const extractedImages = [];
2905
3102
  const pageImageBlocks = /* @__PURE__ */ new Map();
2906
3103
  const carry = {};
2907
3104
  const vectorPageOps = /* @__PURE__ */ new Map();
2908
3105
  const wrapLexicon = new WrapLexicon();
2909
3106
  const noteMarks = /* @__PURE__ */ new Map();
3107
+ const headerContext = [];
3108
+ if (pageFilter && options?.removeHeaderFooter !== false && pageFilter.size < effectivePageCount) {
3109
+ for (const number of selectionContextPages(pageFilter, effectivePageCount)) {
3110
+ let contextPage;
3111
+ try {
3112
+ contextPage = await doc.getPage(number);
3113
+ const content = await contextPage.getTextContent();
3114
+ pageHeights.set(number, contextPage.view[3] - contextPage.view[1]);
3115
+ headerContext.push(...marginContextBlocks(content.items, number, contextPage.view));
3116
+ } catch {
3117
+ } finally {
3118
+ contextPage?.cleanup();
3119
+ }
3120
+ }
3121
+ }
2910
3122
  let parsedPages = 0;
2911
3123
  for (let i = 1; i <= effectivePageCount; i++) {
2912
3124
  if (pageFilter && !pageFilter.has(i)) continue;
@@ -2960,6 +3172,7 @@ async function parsePdfDocument(buffer, options) {
2960
3172
  } : rawOps;
2961
3173
  remapSymbolFontItems(visible, (loadedName) => fontObj(loadedName)?.name);
2962
3174
  remapControlGlyphs(visible, differencesOf);
3175
+ await restoreImageBullets(visible, page, opList.fnArray, opList.argsArray, imageBulletShapes);
2963
3176
  const faces = /* @__PURE__ */ new Map();
2964
3177
  for (const it of visible) {
2965
3178
  if (!it.fontName) continue;
@@ -3006,7 +3219,8 @@ async function parsePdfDocument(buffer, options) {
3006
3219
  if (marks.length) noteMarks.set(i, { marks, seps: footnoteSeparators(extractLines(opList.fnArray, opList.argsArray).horizontals, pageW, pageH) });
3007
3220
  const stamp = marginStamp(visible);
3008
3221
  const flow = stamp.length ? visible.filter((it) => !stamp.includes(it)) : visible;
3009
- const pageBlocks = orderTwoUpPage(extractPageBlocksWithLines(flow, i, opList, pageW, pageH, void 0, options?.tables !== false, carry, wrapLexicon), pageW, pageH);
3222
+ const rightArrows = options?.tables !== false ? await detectRightArrowRegions(page, opList.fnArray, opList.argsArray, imageArrowDirections) : [];
3223
+ const pageBlocks = orderTwoUpPage(extractPageBlocksWithLines(flow, i, opList, pageW, pageH, void 0, options?.tables !== false, carry, wrapLexicon, rightArrows), pageW, pageH);
3010
3224
  if (stamp.length) pageBlocks.unshift({ type: "paragraph", text: [...stamp].sort((a, b) => a.y - b.y).map((it) => it.text).join(" "), pageNumber: i });
3011
3225
  for (const b of pageBlocks) blocks.push(b);
3012
3226
  try {
@@ -3062,7 +3276,7 @@ async function parsePdfDocument(buffer, options) {
3062
3276
  }
3063
3277
  if (targets.size > 0) {
3064
3278
  try {
3065
- const { runPdfOcr } = await import("./pdf-ocr-4S2OAHUX.js");
3279
+ const { runPdfOcr } = await import("./pdf-ocr-RACAZU3N.js");
3066
3280
  const mode = typeof options?.ocr === "function" ? options.ocr : "builtin";
3067
3281
  const regionPages = new Map([...ocrRegions].filter(([p]) => options?.ocr !== "force" && !isImageBased && !pageQuality.find((q) => q.page === p)?.needsOcr));
3068
3282
  const ocrPageBlocks = await runPdfOcr(ocrBuffer, targets, mode, warnings, options?.onProgress, options?.tables !== false, vectorPageOps, regionPages);
@@ -3129,8 +3343,8 @@ async function parsePdfDocument(buffer, options) {
3129
3343
  warnings.push({ page, message: `${count}\uAC1C \uC774\uBBF8\uC9C0 \uC601\uC5ED\uC5D0 \uCD94\uCD9C \uAC00\uB2A5\uD55C \uD14D\uC2A4\uD2B8 \uC5C6\uC74C (\uADF8\uB9BC/\uCC28\uD2B8/\uB3C4\uC7A5 \uB0B4\uC6A9 \uB204\uB77D \uAC00\uB2A5 \u2014 \uADF8\uB9BC \uC18D \uAE00\uC740 ocr: true / CLI --ocr \uB85C \uC77D\uC2B5\uB2C8\uB2E4)`, code: "SKIPPED_IMAGE" });
3130
3344
  }
3131
3345
  }
3132
- if (options?.removeHeaderFooter !== false && parsedPageCount >= 3) {
3133
- const removed = removeHeaderFooterBlocks(blocks, pageHeights, warnings, noteMarks);
3346
+ if (options?.removeHeaderFooter !== false && (parsedPageCount >= 3 || headerContext.length)) {
3347
+ const removed = removeHeaderFooterBlocks(blocks, pageHeights, warnings, noteMarks, false, headerContext);
3134
3348
  for (let ri = removed.length - 1; ri >= 0; ri--) {
3135
3349
  blocks.splice(removed[ri], 1);
3136
3350
  }
@@ -3178,6 +3392,10 @@ async function parsePdfDocument(buffer, options) {
3178
3392
  const outline = blocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
3179
3393
  sanitizeBlockControlChars(blocks);
3180
3394
  let outBlocks = splitSingleCellTables(blocks);
3395
+ if (options?.layoutTables !== "keep") {
3396
+ blocks.length = 0;
3397
+ for (const block of outBlocks) blocks.push(block);
3398
+ }
3181
3399
  outBlocks = inlineFootnotes(outBlocks, noteMarks);
3182
3400
  outBlocks = relocateEndnotes(outBlocks);
3183
3401
  if (options?.removeHeaderFooter !== false) outBlocks = outBlocks.filter((b) => {
@@ -3294,4 +3512,4 @@ export {
3294
3512
  parsePdfDocument,
3295
3513
  removeHeaderFooterBlocks
3296
3514
  };
3297
- //# sourceMappingURL=parser-M3T2EWUN.js.map
3515
+ //# sourceMappingURL=parser-GFDGAVLV.js.map