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
@@ -5,6 +5,8 @@ import {
5
5
  CONT_PARTS,
6
6
  EMPTY_PARTS,
7
7
  FILLER_CELLS,
8
+ FRAME_READING_UNITS,
9
+ FRAME_TITLE_BLOCKS,
8
10
  IMAGE_CELLS,
9
11
  NO_EDGES,
10
12
  PART_COLXS,
@@ -15,6 +17,7 @@ import {
15
17
  TOC_BLOCKS,
16
18
  WrapLexicon,
17
19
  collapseEvenSpacing,
20
+ computeBBox,
18
21
  computeMedianFontSizeFromFreq,
19
22
  detectDocumentStyleHeadings,
20
23
  detectHeadings,
@@ -22,33 +25,39 @@ import {
22
25
  detectMarkerHeadings,
23
26
  detectPageLeadHeadings,
24
27
  detectRepeatedPageLabels,
28
+ detectRightArrowRegions,
25
29
  detectSiblingStyleHeadings,
26
30
  detectTableCaptions,
27
31
  detectTypographyHeadings,
32
+ dominantStyle,
28
33
  extractImageRegions,
29
34
  extractLines,
30
35
  extractPageBlocksWithLines,
31
36
  filterHiddenText,
37
+ groupByY,
32
38
  joinCellEdges,
33
39
  joinPageBreakWraps,
34
40
  latinSoftWrap,
41
+ mergeLineSimple,
35
42
  mergeStackedHeadingLines,
36
43
  normalizeItems,
44
+ recordFrameReadingUnit,
37
45
  refineDocumentStyleHeadings,
38
46
  removeHeaderFooterBlocks,
39
47
  removeSideTabs,
48
+ restoreImageBullets,
40
49
  startsNewItem,
41
50
  trimTrailingEmptyTableCols,
42
51
  wrapJoiner
43
- } from "./chunk-OGAYGUJF.js";
52
+ } from "./chunk-KUUSP6OS.js";
44
53
  import {
45
54
  ocrModelsCached
46
- } from "./chunk-NZM2SSI4.js";
47
- import "./chunk-4B2EXELH.js";
48
- import "./chunk-6OKBTY72.js";
55
+ } from "./chunk-Z2PPDQK2.js";
56
+ import "./chunk-HRJJDNRD.js";
57
+ import "./chunk-QVCHFCT2.js";
49
58
  import {
50
59
  blocksToPages
51
- } from "./chunk-GM7XIZF2.js";
60
+ } from "./chunk-4IBY5LTJ.js";
52
61
  import {
53
62
  encodePng
54
63
  } from "./chunk-7FCNOKOR.js";
@@ -58,7 +67,7 @@ import {
58
67
  escapeLiteralTags,
59
68
  stripScriptTags,
60
69
  unframeLayoutTables
61
- } from "./chunk-F5HING4Y.js";
70
+ } from "./chunk-TMJVD6FW.js";
62
71
  import {
63
72
  hasRequestedPagesAfter,
64
73
  parsePageRange
@@ -67,11 +76,11 @@ import {
67
76
  WINGDINGS,
68
77
  blocksToMarkdown,
69
78
  escapeLiteralDollar
70
- } from "./chunk-IA3UKDHA.js";
79
+ } from "./chunk-VTVK2JMI.js";
71
80
  import {
72
81
  KordocError,
73
82
  sanitizeHref
74
- } from "./chunk-OBILAVWC.js";
83
+ } from "./chunk-F5YVCJVF.js";
75
84
 
76
85
  // src/pdf/ocr-region-merge.ts
77
86
  function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
@@ -84,8 +93,10 @@ function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
84
93
  const overlapH = Math.max(0, Math.min(b.y + b.height, region.y2) - Math.max(b.y, region.y1));
85
94
  return overlapW * overlapH >= b.width * b.height * 0.8;
86
95
  });
96
+ const labels = candidates.filter((b) => b.type === "paragraph" && b.bbox.height <= 24 && (b.text?.match(/[\p{L}\p{N}]/gu)?.length ?? 0) >= 2);
97
+ const axisFragments = rotatedAxisFragments(candidates);
87
98
  const accepted = candidates.filter((b) => {
88
- if (b.type === "paragraph") return (b.text?.match(/[\p{L}\p{N}]/gu)?.length ?? 0) >= 2;
99
+ if (b.type === "paragraph") return (b.text?.match(/[\p{L}\p{N}]/gu)?.length ?? 0) >= 2 || !axisFragments.has(b) && supportedDiagramLabel(b, labels, region);
89
100
  const t = b.table;
90
101
  if (b.type !== "table" || !t) return false;
91
102
  if (t.rows === 1 && t.cols === 1) {
@@ -96,29 +107,89 @@ function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
96
107
  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);
97
108
  });
98
109
  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 ?? "")) : []);
99
- for (const block of selected) {
110
+ const hasOriginal = (block) => blocks.some((existing) => {
100
111
  const b = block.bbox;
101
- const hasOriginal = blocks.some((existing) => {
102
- if (existing.pageNumber !== page || !existing.bbox || existing.type === "image") return false;
103
- const e = existing.bbox;
104
- const x = Math.max(0, Math.min(e.x + e.width, b.x + b.width) - Math.max(e.x, b.x));
105
- const y = Math.max(0, Math.min(e.y + e.height, b.y + b.height) - Math.max(e.y, b.y));
106
- return x * y > b.width * b.height * 0.2;
107
- });
108
- if (hasOriginal) continue;
109
- const index = blocks.findIndex((existing) => {
110
- const e = existing.bbox;
111
- if (existing.pageNumber !== page || !e) return false;
112
- const beside = e.y < region.y2 && e.y + e.height > region.y1 && e.x >= region.x2 - 1;
113
- return e.y < b.y || beside;
114
- });
115
- const placed = block.type === "paragraph" ? { ...block, style: void 0 } : block;
116
- blocks.splice(index < 0 ? blocks.length : index, 0, placed);
117
- added++;
112
+ if (existing.pageNumber !== page || !existing.bbox || existing.type === "image") return false;
113
+ const e = existing.bbox;
114
+ const x = Math.max(0, Math.min(e.x + e.width, b.x + b.width) - Math.max(e.x, b.x));
115
+ const y = Math.max(0, Math.min(e.y + e.height, b.y + b.height) - Math.max(e.y, b.y));
116
+ return x * y > b.width * b.height * 0.2;
117
+ });
118
+ const selectedSet = new Set(selected), seen = /* @__PURE__ */ new Set();
119
+ for (const block of selected) {
120
+ if (seen.has(block)) continue;
121
+ const frame = FRAME_READING_UNITS.get(block);
122
+ const source = frame?.blocks.every((member) => selectedSet.has(member)) ? frame.blocks : [block];
123
+ source.forEach((member) => seen.add(member));
124
+ const available = source.filter((member) => !hasOriginal(member));
125
+ 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 }));
126
+ for (const unit of units) {
127
+ const b = unit.bbox;
128
+ const index = blocks.findIndex((existing) => {
129
+ const e = FRAME_READING_UNITS.get(existing)?.bbox ?? existing.bbox;
130
+ if (existing.pageNumber !== page || !e) return false;
131
+ const beside = e.y < region.y2 && e.y + e.height > region.y1 && e.x >= region.x2 - 1;
132
+ return e.y < b.y || beside;
133
+ });
134
+ const placed = unit.blocks.map((member) => member.type === "paragraph" ? { ...member, style: void 0 } : member);
135
+ if (unit.atomic) recordFrameReadingUnit(placed, unit.bbox);
136
+ blocks.splice(index < 0 ? blocks.length : index, 0, ...placed);
137
+ added += placed.length;
138
+ }
118
139
  }
119
140
  }
120
141
  return added;
121
142
  }
143
+ function supportedDiagramLabel(block, labels, region) {
144
+ const b = block.bbox, text = block.text?.trim() ?? "";
145
+ 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;
146
+ let above = false, below = false;
147
+ for (const label of labels) {
148
+ const a = label.bbox, em = Math.max(b.height, a.height);
149
+ if (b.x + b.width < a.x - em * 2 || b.x > a.x + a.width + em * 2) continue;
150
+ const upperGap = a.y - (b.y + b.height), lowerGap = b.y - (a.y + a.height);
151
+ if (upperGap >= 0 && upperGap <= em * 4) above = true;
152
+ if (lowerGap >= 0 && lowerGap <= em * 4) below = true;
153
+ }
154
+ return above && below;
155
+ }
156
+ function rotatedAxisFragments(candidates) {
157
+ const paragraphs = candidates.filter((b) => b.type === "paragraph" && b.bbox.height <= 24);
158
+ const axes = [];
159
+ for (const block of paragraphs) {
160
+ const b = block.bbox, text = block.text?.trim() ?? "";
161
+ if (!/^[\d\s.,%+−-]+$/u.test(text) || !/\d/u.test(text) || b.width > b.height * 6) continue;
162
+ 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);
163
+ if (axis) axis.push(block);
164
+ else axes.push([block]);
165
+ }
166
+ const fragments = /* @__PURE__ */ new Set();
167
+ const aligned = (a, b) => {
168
+ const x = a.bbox, y = b.bbox, tolerance = Math.max(x.height, y.height) * 0.5;
169
+ return Math.abs(x.x - y.x) <= tolerance || Math.abs(x.x + x.width - y.x - y.width) <= tolerance;
170
+ };
171
+ for (const axis of axes) {
172
+ if (axis.length < 3) continue;
173
+ const bottom = Math.min(...axis.map((a) => a.bbox.y)), top = Math.max(...axis.map((a) => a.bbox.y + a.bbox.height));
174
+ const em = Math.max(...axis.map((a) => a.bbox.height)), right = axis[0].bbox.x + axis[0].bbox.width;
175
+ if (top - bottom < em * 6) continue;
176
+ const left = paragraphs.filter((block) => {
177
+ const b = block.bbox, text = block.text?.trim() ?? "";
178
+ 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;
179
+ });
180
+ const stack = left.filter((a) => left.some((b) => {
181
+ if (a === b || !aligned(a, b)) return false;
182
+ const x = a.bbox, y = b.bbox, gap = Math.max(x.y, y.y) - Math.min(x.y + x.height, y.y + y.height);
183
+ return gap >= -Math.min(x.height, y.height) * 0.5 && gap <= Math.max(x.height, y.height);
184
+ }));
185
+ if (stack.length < 2) continue;
186
+ for (const block of paragraphs) {
187
+ const b = block.bbox;
188
+ 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);
189
+ }
190
+ }
191
+ return fragments;
192
+ }
122
193
  function rowParagraphs(block) {
123
194
  const t = block.table, b = block.bbox;
124
195
  const h = b.height / t.rows;
@@ -924,6 +995,17 @@ var CARRIED_MIN_COL_W = 4;
924
995
  var LABEL_ROOM = 1.5;
925
996
  var HANGING_MIN = 0.5;
926
997
  var HANGING_TOL = 1;
998
+ 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";
999
+ var ITEM_MARK = /^\s*(?:([가-힣])\.|(\d{1,3})[.)]|\(([가-힣\d]{1,3})\))(?=\s)/;
1000
+ function nextItemHead(prev, next) {
1001
+ const a = ITEM_MARK.exec(prev), b = ITEM_MARK.exec(next);
1002
+ if (!a || !b) return false;
1003
+ 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;
1004
+ if (a[1] && b[1]) return succ(a[1], b[1]);
1005
+ if (a[2] && b[2]) return succ(a[2], b[2]) && prev.trimStart()[a[2].length] === next.trimStart()[b[2].length];
1006
+ if (a[3] && b[3]) return succ(a[3], b[3]);
1007
+ return false;
1008
+ }
927
1009
  function continuesAcross(u, d, x1, x2) {
928
1010
  const U = CELL_LINES.get(u), D = CELL_LINES.get(d);
929
1011
  if (!U?.length || !D?.length) return false;
@@ -1055,6 +1137,8 @@ function mergeSplitRow(table, owner, first, colXs, textOnly = false, cut = NO_CU
1055
1137
  if (!carriedSplit) {
1056
1138
  const norm = (c) => flowText(c.text).replace(/\s+/g, "");
1057
1139
  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;
1140
+ const oneLine = (c) => CELL_LINES.get(c)?.length === 1;
1141
+ 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;
1058
1142
  const flows = ([u, d]) => continuesAcross(cell(u), cell(d), colXs[u.c], colXs[u.c + u.cs]) || clauseContinues(cell(u), cell(d));
1059
1143
  if (!(cut.open && !newCell)) {
1060
1144
  if (pairs.some((p) => p[1].rs > 1 && !flows(p))) return false;
@@ -1115,7 +1199,7 @@ function sameHeadShape(a, b) {
1115
1199
  let tall = false;
1116
1200
  for (let c = 0; c < a.length; c++) {
1117
1201
  if (a[c].colSpan !== b[c].colSpan || a[c].rowSpan !== b[c].rowSpan) return false;
1118
- if (a[c].rowSpan >= 2 && a[c].text.trim()) tall = true;
1202
+ if (a[c].rowSpan >= 2 && a[c].text.trim() && b[c].text.trim()) tall = true;
1119
1203
  }
1120
1204
  return tall;
1121
1205
  }
@@ -1152,9 +1236,10 @@ function mergeCrossPageTables(blocks, pageHeights, lex) {
1152
1236
  if (px && cx && !shiftedSame(px, cx, !CLIP_TABLES.has(prev.table) && !CLIP_TABLES.has(curr.table))) continue;
1153
1237
  if (!rowTextsEqual(prev.table.cells[0], curr.table.cells[0]) && sameHeadShape(prev.table.cells[0], curr.table.cells[0])) continue;
1154
1238
  let currCells = curr.table.cells;
1155
- if (currCells.length > 1 && prev.table.cells.length > 0 && rowTextsEqual(prev.table.cells[0], currCells[0])) {
1156
- currCells = currCells.slice(1);
1157
- }
1239
+ const headRows = repeatedHeaderRows(prev.table, curr.table);
1240
+ if (headRows < 0) continue;
1241
+ if (headRows) currCells = currCells.slice(headRows);
1242
+ if (currCells.length) continueRowSpans(prev.table.cells, currCells);
1158
1243
  if (currCells.length === 0) {
1159
1244
  blocks.splice(j, 1);
1160
1245
  continue;
@@ -1356,6 +1441,45 @@ function chainHead(blocks, i, pageHeights) {
1356
1441
  }
1357
1442
  return k;
1358
1443
  }
1444
+ var ROW_CONTINUATIONS = /* @__PURE__ */ new WeakMap();
1445
+ function continueRowSpans(prevCells, currCells) {
1446
+ const first = currCells[0];
1447
+ const last = prevCells.length;
1448
+ for (let c = 0; c < first.length; c++) {
1449
+ const cell = first[c];
1450
+ if (hasContent(cell) || (cell.rowSpan || 1) < 2) continue;
1451
+ let anchor;
1452
+ for (let r = last - 1; r >= 0 && !anchor; r--) {
1453
+ const a = prevCells[r]?.[c];
1454
+ if (a && r + (a.rowSpan || 1) === last && (a.colSpan || 1) === (cell.colSpan || 1) && (hasContent(a) || a.rowSpan >= 2)) anchor = a;
1455
+ }
1456
+ if (!anchor) continue;
1457
+ if (!hasContent(anchor)) {
1458
+ ROW_CONTINUATIONS.set(anchor, cell);
1459
+ continue;
1460
+ }
1461
+ for (let part = cell; part; ) {
1462
+ const next = ROW_CONTINUATIONS.get(part);
1463
+ anchor.rowSpan = (anchor.rowSpan || 1) + part.rowSpan;
1464
+ part.rowSpan = 1;
1465
+ part.colSpan = 1;
1466
+ ROW_CONTINUATIONS.delete(part);
1467
+ part = next;
1468
+ }
1469
+ }
1470
+ }
1471
+ function repeatedHeaderRows(prev, curr) {
1472
+ if (!rowTextsEqual(prev.cells[0], curr.cells[0])) return 0;
1473
+ const pa = anchorsOf(prev), ca = anchorsOf(curr);
1474
+ let depth = 1;
1475
+ for (let r = 0; r < depth && r < prev.rows; r++) {
1476
+ for (const a of pa) if (a.r === r) depth = Math.max(depth, r + a.rs);
1477
+ }
1478
+ if (depth >= curr.rows || depth > prev.rows) return -1;
1479
+ const p = pa.filter((a) => a.r < depth), d = ca.filter((a) => a.r < depth);
1480
+ const norm = (text) => flowText(text).replace(/\s+/g, "");
1481
+ 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;
1482
+ }
1359
1483
  function rowTextsEqual(a, b) {
1360
1484
  if (a.length !== b.length) return false;
1361
1485
  const norm = (t) => flowText(t).replace(/\s+/g, "");
@@ -1450,6 +1574,34 @@ function fillNestedContinuation(blocks, at) {
1450
1574
  blocks.splice(at, 1);
1451
1575
  }
1452
1576
 
1577
+ // src/pdf/selection-context.ts
1578
+ function selectionContextPages(selected, pageCount) {
1579
+ const out = /* @__PURE__ */ new Set();
1580
+ for (const page of selected) {
1581
+ for (let distance = 1; distance <= 4; distance++) {
1582
+ for (const neighbor of [page - distance, page + distance]) {
1583
+ if (neighbor < 1 || neighbor > pageCount || selected.has(neighbor)) continue;
1584
+ out.add(neighbor);
1585
+ }
1586
+ }
1587
+ }
1588
+ return [...out].sort((a, b) => a - b);
1589
+ }
1590
+ function marginContextBlocks(raw, page, view) {
1591
+ const [x1, y1, x2, y2] = view;
1592
+ const width = x2 - x1, height = y2 - y1;
1593
+ const items = filterHiddenText(normalizeItems(raw), width, height, x1, y1).visible;
1594
+ for (const item of items) {
1595
+ item.x -= x1;
1596
+ item.y -= y1;
1597
+ }
1598
+ return groupByY(items).flatMap((line) => {
1599
+ const bbox = computeBBox(line, page);
1600
+ if (bbox.y + bbox.height < height * 0.88 && bbox.y > height * 0.12) return [];
1601
+ return [{ type: "paragraph", text: mergeLineSimple(line), pageNumber: page, bbox, style: dominantStyle(line) }];
1602
+ });
1603
+ }
1604
+
1453
1605
  // src/pdf/symbol-fonts.ts
1454
1606
  var WINANSI_REVERSE = {
1455
1607
  8364: 128,
@@ -1757,6 +1909,9 @@ var NAMED = {
1757
1909
  quotedblright: "\u201D",
1758
1910
  quotesingle: "'",
1759
1911
  quotedbl: '"',
1912
+ bullet: "\u2022",
1913
+ openbullet: "\u25E6",
1914
+ whitebullet: "\u25E6",
1760
1915
  question: "?",
1761
1916
  exclam: "!",
1762
1917
  percent: "%",
@@ -1773,7 +1928,9 @@ function glyphNameText(name) {
1773
1928
  let out = "";
1774
1929
  for (const part of base.split("_")) {
1775
1930
  const uni = /^uni([0-9A-F]{4})$/.exec(part) ?? /^u([0-9A-F]{4,6})$/.exec(part);
1776
- const ch = /^[A-Za-z]$/.test(part) ? part : NAMED[part] ?? (uni ? String.fromCodePoint(parseInt(uni[1], 16)) : void 0);
1931
+ const code = uni ? parseInt(uni[1], 16) : void 0;
1932
+ if (code !== void 0 && (code > 1114111 || code >= 55296 && code <= 57343)) return void 0;
1933
+ const ch = /^[A-Za-z]$/.test(part) ? part : NAMED[part] ?? (code !== void 0 ? String.fromCodePoint(code) : void 0);
1777
1934
  if (ch === void 0) return void 0;
1778
1935
  out += ch;
1779
1936
  }
@@ -2459,6 +2616,35 @@ function demoteNonHeadingRoles(blocks, pageHeights, faceNames) {
2459
2616
  }
2460
2617
  }
2461
2618
  }
2619
+ const citedProse = /* @__PURE__ */ new Set();
2620
+ const numberedProse = /* @__PURE__ */ new Set();
2621
+ for (const page of byPage.values()) {
2622
+ 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) ?? ""));
2623
+ let chain = [];
2624
+ const finish = () => {
2625
+ if (chain.length < 3 || !chain.some((b) => (b.text?.length ?? 0) >= 40 && b.bbox.height >= b.style.fontSize * 2.4)) return;
2626
+ for (const b of chain) numberedProse.add(b);
2627
+ const first = chain[0], size = first.style.fontSize;
2628
+ 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);
2629
+ };
2630
+ for (const b of numbered) {
2631
+ const prev = chain.at(-1), size = b.style.fontSize;
2632
+ 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) {
2633
+ finish();
2634
+ chain = [];
2635
+ }
2636
+ chain.push(b);
2637
+ }
2638
+ finish();
2639
+ }
2640
+ for (let i = 0; i + 1 < blocks.length; i++) {
2641
+ const prose = blocks[i], reference = blocks[i + 1];
2642
+ const a = prose.bbox, b = reference.bbox, size = prose.style?.fontSize ?? 0;
2643
+ const source = reference.text?.replace(/<[^>]+>/g, "").trim() ?? "";
2644
+ 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;
2645
+ citedProse.add(prose);
2646
+ citedProse.add(reference);
2647
+ }
2462
2648
  for (let i = 0; i < blocks.length; i++) {
2463
2649
  const block = blocks[i];
2464
2650
  if (block.type !== "heading" || !block.text) continue;
@@ -2506,7 +2692,7 @@ function demoteNonHeadingRoles(blocks, pageHeights, faceNames) {
2506
2692
  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;
2507
2693
  const ocrFragment = block.style?.fontName === "ocr" && (/^[.,;:…·•-]/.test(text) || text.includes("\u2026") || (text.match(/\p{L}/gu)?.length ?? 0) < 2 || text.split(/\s+/).length > 7);
2508
2694
  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;
2509
- 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)"·"가)" 앞머리 번호는 빼고 센다
2695
+ 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)"·"가)" 앞머리 번호는 빼고 센다
2510
2696
  unbalancedClose(text.replace(/^\s*[\dA-Za-z가-힣ⅰ-ⅹ]{1,3}\)\s*/, "")) || isRunningHead(block, page, pageHeights.get(block.pageNumber ?? 0))) {
2511
2697
  block.type = "paragraph";
2512
2698
  block.level = void 0;
@@ -2547,6 +2733,11 @@ function splitSingleCellTables(blocks) {
2547
2733
  const out = [];
2548
2734
  for (const b of blocks) {
2549
2735
  const t = b.type === "table" ? b.table : void 0;
2736
+ const title = t && FRAME_TITLE_BLOCKS.get(t);
2737
+ if (title) {
2738
+ out.push({ ...title, text: `${t.cells[0][0].text.trim()} ${t.cells[0][2].text.trim()}` });
2739
+ continue;
2740
+ }
2550
2741
  const only = t && t.rows === 1 && t.cols === 1 && t.cells[0]?.[0]?.blocks?.length === 1 ? t.cells[0][0].blocks[0] : void 0;
2551
2742
  const squash = (s) => s.replace(/\s/g, "");
2552
2743
  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;
@@ -2556,12 +2747,16 @@ function splitSingleCellTables(blocks) {
2556
2747
  continue;
2557
2748
  }
2558
2749
  const cell = t && t.rows === 1 && t.cols === 1 ? t.cells[0]?.[0] : void 0;
2559
- if (!cell || cell.blocks?.some((x) => x.type === "table")) {
2750
+ if (!cell) {
2560
2751
  out.push(b);
2561
2752
  continue;
2562
2753
  }
2563
2754
  const lines = (cell.text ?? "").split(/\n/).map((l) => l.trim()).filter(Boolean);
2564
2755
  if (t?.caption?.trim()) out.push({ type: "paragraph", text: t.caption.trim(), pageNumber: b.pageNumber, bbox: b.bbox });
2756
+ if (cell.blocks?.length) {
2757
+ out.push(...splitSingleCellTables(cell.blocks));
2758
+ continue;
2759
+ }
2565
2760
  for (const text of lines) out.push({ type: "paragraph", text, pageNumber: b.pageNumber, bbox: b.bbox });
2566
2761
  }
2567
2762
  return out;
@@ -2686,7 +2881,7 @@ function mergeLinkRuns(markdown) {
2686
2881
 
2687
2882
  // src/pdf/formula-ocr.ts
2688
2883
  async function applyFormulaOcr(buffer, blocks, pageFilter, effectivePageCount, warnings, _onProgress) {
2689
- const formulaMod = await import("./formula-E3N7KDDG.js");
2884
+ const formulaMod = await import("./formula-7ZOZ5QJ6.js");
2690
2885
  const { FormulaPipeline, ensureFormulaModels } = formulaMod;
2691
2886
  await ensureFormulaModels((p) => {
2692
2887
  if (p.phase === "download" && p.total) {
@@ -2909,12 +3104,29 @@ async function parsePdfDocument(buffer, options) {
2909
3104
  const uncoveredImageRegions = /* @__PURE__ */ new Map();
2910
3105
  const largeImageRegions = /* @__PURE__ */ new Set();
2911
3106
  const imageState = createPdfImageState();
3107
+ const imageBulletShapes = /* @__PURE__ */ new Map();
3108
+ const imageArrowDirections = /* @__PURE__ */ new Map();
2912
3109
  const extractedImages = [];
2913
3110
  const pageImageBlocks = /* @__PURE__ */ new Map();
2914
3111
  const carry = {};
2915
3112
  const vectorPageOps = /* @__PURE__ */ new Map();
2916
3113
  const wrapLexicon = new WrapLexicon();
2917
3114
  const noteMarks = /* @__PURE__ */ new Map();
3115
+ const headerContext = [];
3116
+ if (pageFilter && options?.removeHeaderFooter !== false && pageFilter.size < effectivePageCount) {
3117
+ for (const number of selectionContextPages(pageFilter, effectivePageCount)) {
3118
+ let contextPage;
3119
+ try {
3120
+ contextPage = await doc.getPage(number);
3121
+ const content = await contextPage.getTextContent();
3122
+ pageHeights.set(number, contextPage.view[3] - contextPage.view[1]);
3123
+ headerContext.push(...marginContextBlocks(content.items, number, contextPage.view));
3124
+ } catch {
3125
+ } finally {
3126
+ contextPage?.cleanup();
3127
+ }
3128
+ }
3129
+ }
2918
3130
  let parsedPages = 0;
2919
3131
  for (let i = 1; i <= effectivePageCount; i++) {
2920
3132
  if (pageFilter && !pageFilter.has(i)) continue;
@@ -2968,6 +3180,7 @@ async function parsePdfDocument(buffer, options) {
2968
3180
  } : rawOps;
2969
3181
  remapSymbolFontItems(visible, (loadedName) => fontObj(loadedName)?.name);
2970
3182
  remapControlGlyphs(visible, differencesOf);
3183
+ await restoreImageBullets(visible, page, opList.fnArray, opList.argsArray, imageBulletShapes);
2971
3184
  const faces = /* @__PURE__ */ new Map();
2972
3185
  for (const it of visible) {
2973
3186
  if (!it.fontName) continue;
@@ -3014,7 +3227,8 @@ async function parsePdfDocument(buffer, options) {
3014
3227
  if (marks.length) noteMarks.set(i, { marks, seps: footnoteSeparators(extractLines(opList.fnArray, opList.argsArray).horizontals, pageW, pageH) });
3015
3228
  const stamp = marginStamp(visible);
3016
3229
  const flow = stamp.length ? visible.filter((it) => !stamp.includes(it)) : visible;
3017
- const pageBlocks = orderTwoUpPage(extractPageBlocksWithLines(flow, i, opList, pageW, pageH, void 0, options?.tables !== false, carry, wrapLexicon), pageW, pageH);
3230
+ const rightArrows = options?.tables !== false ? await detectRightArrowRegions(page, opList.fnArray, opList.argsArray, imageArrowDirections) : [];
3231
+ const pageBlocks = orderTwoUpPage(extractPageBlocksWithLines(flow, i, opList, pageW, pageH, void 0, options?.tables !== false, carry, wrapLexicon, rightArrows), pageW, pageH);
3018
3232
  if (stamp.length) pageBlocks.unshift({ type: "paragraph", text: [...stamp].sort((a, b) => a.y - b.y).map((it) => it.text).join(" "), pageNumber: i });
3019
3233
  for (const b of pageBlocks) blocks.push(b);
3020
3234
  try {
@@ -3070,7 +3284,7 @@ async function parsePdfDocument(buffer, options) {
3070
3284
  }
3071
3285
  if (targets.size > 0) {
3072
3286
  try {
3073
- const { runPdfOcr } = await import("./pdf-ocr-YEBFWU2K.js");
3287
+ const { runPdfOcr } = await import("./pdf-ocr-7IOOVR2I.js");
3074
3288
  const mode = typeof options?.ocr === "function" ? options.ocr : "builtin";
3075
3289
  const regionPages = new Map([...ocrRegions].filter(([p]) => options?.ocr !== "force" && !isImageBased && !pageQuality.find((q) => q.page === p)?.needsOcr));
3076
3290
  const ocrPageBlocks = await runPdfOcr(ocrBuffer, targets, mode, warnings, options?.onProgress, options?.tables !== false, vectorPageOps, regionPages);
@@ -3137,8 +3351,8 @@ async function parsePdfDocument(buffer, options) {
3137
3351
  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" });
3138
3352
  }
3139
3353
  }
3140
- if (options?.removeHeaderFooter !== false && parsedPageCount >= 3) {
3141
- const removed = removeHeaderFooterBlocks(blocks, pageHeights, warnings, noteMarks);
3354
+ if (options?.removeHeaderFooter !== false && (parsedPageCount >= 3 || headerContext.length)) {
3355
+ const removed = removeHeaderFooterBlocks(blocks, pageHeights, warnings, noteMarks, false, headerContext);
3142
3356
  for (let ri = removed.length - 1; ri >= 0; ri--) {
3143
3357
  blocks.splice(removed[ri], 1);
3144
3358
  }
@@ -3186,6 +3400,10 @@ async function parsePdfDocument(buffer, options) {
3186
3400
  const outline = blocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
3187
3401
  sanitizeBlockControlChars(blocks);
3188
3402
  let outBlocks = splitSingleCellTables(blocks);
3403
+ if (options?.layoutTables !== "keep") {
3404
+ blocks.length = 0;
3405
+ for (const block of outBlocks) blocks.push(block);
3406
+ }
3189
3407
  outBlocks = inlineFootnotes(outBlocks, noteMarks);
3190
3408
  outBlocks = relocateEndnotes(outBlocks);
3191
3409
  if (options?.removeHeaderFooter !== false) outBlocks = outBlocks.filter((b) => {
@@ -3302,4 +3520,4 @@ export {
3302
3520
  parsePdfDocument,
3303
3521
  removeHeaderFooterBlocks
3304
3522
  };
3305
- //# sourceMappingURL=parser-KB4BYQBZ.js.map
3523
+ //# sourceMappingURL=parser-SOWTUOMK.js.map