kordoc 4.24.6 → 4.24.8

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 (128) hide show
  1. package/README.md +7 -7
  2. package/dist/{-7J7Y3XPH.js → -TLCDUU22.js} +11 -11
  3. package/dist/{chunk-TZVVK5MI.js → chunk-5MQG3GJI.js} +2 -2
  4. package/dist/{chunk-JIU7E7Z6.cjs → chunk-73MRAQXA.cjs} +1098 -209
  5. package/dist/chunk-73MRAQXA.cjs.map +1 -0
  6. package/dist/{chunk-ISTIOEIL.cjs → chunk-7F35EPMM.cjs} +3 -3
  7. package/dist/{chunk-ISTIOEIL.cjs.map → chunk-7F35EPMM.cjs.map} +1 -1
  8. package/dist/{chunk-GI5LWQ3S.js → chunk-7JUF6G6Z.js} +2 -2
  9. package/dist/{chunk-BBKRJE57.js → chunk-7XPTKW76.js} +2 -2
  10. package/dist/{chunk-XM2Y4DB5.js → chunk-BJABLQMB.js} +2 -2
  11. package/dist/{chunk-2JDVPQ33.cjs → chunk-C3BOYTY5.cjs} +2 -2
  12. package/dist/{chunk-2JDVPQ33.cjs.map → chunk-C3BOYTY5.cjs.map} +1 -1
  13. package/dist/{chunk-EVBSSU3N.js → chunk-CB57N2MG.js} +2 -2
  14. package/dist/{chunk-WNOWRBM4.js → chunk-D3EHIHYN.js} +2 -2
  15. package/dist/{chunk-GYX26HZR.js → chunk-DPB6ZVQ5.js} +927 -38
  16. package/dist/chunk-DPB6ZVQ5.js.map +1 -0
  17. package/dist/{chunk-DFRQD254.js → chunk-F7UWIMUA.js} +2 -2
  18. package/dist/{chunk-BKTEGPEO.js → chunk-FSWJC5RR.js} +3 -3
  19. package/dist/{chunk-W75FRCAP.js → chunk-IT5XO3UG.js} +926 -37
  20. package/dist/chunk-IT5XO3UG.js.map +1 -0
  21. package/dist/{chunk-HAMIOQYO.js → chunk-J7MFKS73.js} +2 -2
  22. package/dist/{chunk-435ECXNG.cjs → chunk-JM7PZM6E.cjs} +3 -3
  23. package/dist/{chunk-435ECXNG.cjs.map → chunk-JM7PZM6E.cjs.map} +1 -1
  24. package/dist/{chunk-G343MTBX.js → chunk-K2FGQ5D5.js} +43 -15
  25. package/dist/chunk-K2FGQ5D5.js.map +1 -0
  26. package/dist/{chunk-BZW2WS44.js → chunk-KA6JZZIW.js} +83 -716
  27. package/dist/chunk-KA6JZZIW.js.map +1 -0
  28. package/dist/{chunk-RMUDX5Q2.js → chunk-N2XN6GAQ.js} +2 -2
  29. package/dist/{chunk-XVTGFK2F.js → chunk-NE6G6LCP.js} +2 -2
  30. package/dist/{chunk-AM5ALISV.cjs → chunk-NW2CKOFL.cjs} +6 -6
  31. package/dist/{chunk-AM5ALISV.cjs.map → chunk-NW2CKOFL.cjs.map} +1 -1
  32. package/dist/{chunk-5RZBLPVP.js → chunk-OUJIV2AM.js} +4 -4
  33. package/dist/chunk-OUJIV2AM.js.map +1 -0
  34. package/dist/{chunk-VMRH6UVA.js → chunk-RCDRTQ37.js} +2 -2
  35. package/dist/{chunk-KR4UKOX2.js → chunk-RCT5MO53.js} +6 -6
  36. package/dist/{chunk-3ZLS54V4.js → chunk-TDB27K2Z.js} +2 -2
  37. package/dist/{chunk-EBJWBGWF.js → chunk-TTUAJYTC.js} +83 -716
  38. package/dist/chunk-TTUAJYTC.js.map +1 -0
  39. package/dist/{chunk-5XBZJ3O4.js → chunk-WTSID6AI.js} +2 -2
  40. package/dist/{chunk-PKCOOSDT.js → chunk-XOUZC7MX.js} +2 -2
  41. package/dist/{chunk-TLJJF3J6.js → chunk-Z5DT55TW.js} +3 -3
  42. package/dist/{chunk-J4XCQNVH.cjs → chunk-ZJYNTA5R.cjs} +141 -774
  43. package/dist/chunk-ZJYNTA5R.cjs.map +1 -0
  44. package/dist/chunks-S2GGFN6W.js +10 -0
  45. package/dist/cli.js +30 -30
  46. package/dist/{formula-DKNZKJ5Z.js → formula-DZMBNPWT.js} +4 -4
  47. package/dist/{formula-T7D5JIZR.js → formula-PNMQ5JFJ.js} +3 -3
  48. package/dist/{formula-D7LBREWP.cjs → formula-ZLNSVWS6.cjs} +9 -9
  49. package/dist/{formula-D7LBREWP.cjs.map → formula-ZLNSVWS6.cjs.map} +1 -1
  50. package/dist/{image-ocr-5POXVGN2.js → image-ocr-BPH25SFW.js} +9 -9
  51. package/dist/{image-ocr-7NCSIZGA.js → image-ocr-P5Q6YXTO.js} +6 -6
  52. package/dist/{image-ocr-N3I3MUKF.cjs → image-ocr-YUXCVOOP.cjs} +17 -17
  53. package/dist/{image-ocr-N3I3MUKF.cjs.map → image-ocr-YUXCVOOP.cjs.map} +1 -1
  54. package/dist/index.cjs +729 -701
  55. package/dist/index.cjs.map +1 -1
  56. package/dist/index.js +38 -10
  57. package/dist/index.js.map +1 -1
  58. package/dist/mcp.js +23 -23
  59. package/dist/{model-bundle-XT7G2IJU.js → model-bundle-XAM6JFZV.js} +5 -5
  60. package/dist/{models-AB2VO45L.js → models-6Q5ULSTP.js} +5 -5
  61. package/dist/{parse-worker-v2-YSSAUPWU.js → parse-worker-v2-ONX5QLJZ.js} +12 -12
  62. package/dist/{parser-KGDUPSA7.js → parser-54R7ENH6.js} +9 -9
  63. package/dist/{parser-ES3I54QL.js → parser-JHXN4S6L.js} +12 -12
  64. package/dist/{parser-AGDY3ZOA.cjs → parser-Z352BN56.cjs} +159 -159
  65. package/dist/{parser-AGDY3ZOA.cjs.map → parser-Z352BN56.cjs.map} +1 -1
  66. package/dist/{pdf-ocr-53WUTX6H.js → pdf-ocr-FQ4LAXM6.js} +9 -9
  67. package/dist/{pdf-ocr-7QSP7JLG.js → pdf-ocr-LFVER7IE.js} +6 -6
  68. package/dist/pdf-ocr-SMFFJYTD.cjs +31 -0
  69. package/dist/{pdf-ocr-X6OAHK46.cjs.map → pdf-ocr-SMFFJYTD.cjs.map} +1 -1
  70. package/dist/{profile-io-GGEJ3MZW.js → profile-io-YW5QWKBB.js} +3 -3
  71. package/dist/{rasterize-YXICEI5S.js → rasterize-T4S3NMQ7.js} +3 -3
  72. package/dist/{redact-doc-OYXBNTWI.js → redact-doc-CAVBR5XO.js} +11 -11
  73. package/dist/{render-4PBNDLK2.js → render-ZW52ZX6R.js} +7 -7
  74. package/dist/seal-TQ3RLVVT.js +10 -0
  75. package/dist/{setup-WHTMPK74.js → setup-7UGSJPJP.js} +3 -3
  76. package/dist/visual-6GXHKPCJ.js +21 -0
  77. package/dist/{watch-P6UWW52D.js → watch-M4A7B5WS.js} +12 -12
  78. package/package.json +4 -4
  79. package/dist/chunk-5RZBLPVP.js.map +0 -1
  80. package/dist/chunk-BZW2WS44.js.map +0 -1
  81. package/dist/chunk-EBJWBGWF.js.map +0 -1
  82. package/dist/chunk-G343MTBX.js.map +0 -1
  83. package/dist/chunk-GYX26HZR.js.map +0 -1
  84. package/dist/chunk-J4XCQNVH.cjs.map +0 -1
  85. package/dist/chunk-JIU7E7Z6.cjs.map +0 -1
  86. package/dist/chunk-W75FRCAP.js.map +0 -1
  87. package/dist/chunks-3MWJ7HOZ.js +0 -10
  88. package/dist/pdf-ocr-X6OAHK46.cjs +0 -31
  89. package/dist/seal-KJYAU23C.js +0 -10
  90. package/dist/visual-PHKJTSFR.js +0 -21
  91. /package/dist/{-7J7Y3XPH.js.map → -TLCDUU22.js.map} +0 -0
  92. /package/dist/{chunk-TZVVK5MI.js.map → chunk-5MQG3GJI.js.map} +0 -0
  93. /package/dist/{chunk-GI5LWQ3S.js.map → chunk-7JUF6G6Z.js.map} +0 -0
  94. /package/dist/{chunk-BBKRJE57.js.map → chunk-7XPTKW76.js.map} +0 -0
  95. /package/dist/{chunk-XM2Y4DB5.js.map → chunk-BJABLQMB.js.map} +0 -0
  96. /package/dist/{chunk-EVBSSU3N.js.map → chunk-CB57N2MG.js.map} +0 -0
  97. /package/dist/{chunk-WNOWRBM4.js.map → chunk-D3EHIHYN.js.map} +0 -0
  98. /package/dist/{chunk-DFRQD254.js.map → chunk-F7UWIMUA.js.map} +0 -0
  99. /package/dist/{chunk-BKTEGPEO.js.map → chunk-FSWJC5RR.js.map} +0 -0
  100. /package/dist/{chunk-HAMIOQYO.js.map → chunk-J7MFKS73.js.map} +0 -0
  101. /package/dist/{chunk-RMUDX5Q2.js.map → chunk-N2XN6GAQ.js.map} +0 -0
  102. /package/dist/{chunk-XVTGFK2F.js.map → chunk-NE6G6LCP.js.map} +0 -0
  103. /package/dist/{chunk-VMRH6UVA.js.map → chunk-RCDRTQ37.js.map} +0 -0
  104. /package/dist/{chunk-KR4UKOX2.js.map → chunk-RCT5MO53.js.map} +0 -0
  105. /package/dist/{chunk-3ZLS54V4.js.map → chunk-TDB27K2Z.js.map} +0 -0
  106. /package/dist/{chunk-5XBZJ3O4.js.map → chunk-WTSID6AI.js.map} +0 -0
  107. /package/dist/{chunk-PKCOOSDT.js.map → chunk-XOUZC7MX.js.map} +0 -0
  108. /package/dist/{chunk-TLJJF3J6.js.map → chunk-Z5DT55TW.js.map} +0 -0
  109. /package/dist/{chunks-3MWJ7HOZ.js.map → chunks-S2GGFN6W.js.map} +0 -0
  110. /package/dist/{formula-DKNZKJ5Z.js.map → formula-DZMBNPWT.js.map} +0 -0
  111. /package/dist/{formula-T7D5JIZR.js.map → formula-PNMQ5JFJ.js.map} +0 -0
  112. /package/dist/{image-ocr-5POXVGN2.js.map → image-ocr-BPH25SFW.js.map} +0 -0
  113. /package/dist/{image-ocr-7NCSIZGA.js.map → image-ocr-P5Q6YXTO.js.map} +0 -0
  114. /package/dist/{model-bundle-XT7G2IJU.js.map → model-bundle-XAM6JFZV.js.map} +0 -0
  115. /package/dist/{models-AB2VO45L.js.map → models-6Q5ULSTP.js.map} +0 -0
  116. /package/dist/{parse-worker-v2-YSSAUPWU.js.map → parse-worker-v2-ONX5QLJZ.js.map} +0 -0
  117. /package/dist/{parser-KGDUPSA7.js.map → parser-54R7ENH6.js.map} +0 -0
  118. /package/dist/{parser-ES3I54QL.js.map → parser-JHXN4S6L.js.map} +0 -0
  119. /package/dist/{pdf-ocr-53WUTX6H.js.map → pdf-ocr-FQ4LAXM6.js.map} +0 -0
  120. /package/dist/{pdf-ocr-7QSP7JLG.js.map → pdf-ocr-LFVER7IE.js.map} +0 -0
  121. /package/dist/{profile-io-GGEJ3MZW.js.map → profile-io-YW5QWKBB.js.map} +0 -0
  122. /package/dist/{rasterize-YXICEI5S.js.map → rasterize-T4S3NMQ7.js.map} +0 -0
  123. /package/dist/{redact-doc-OYXBNTWI.js.map → redact-doc-CAVBR5XO.js.map} +0 -0
  124. /package/dist/{render-4PBNDLK2.js.map → render-ZW52ZX6R.js.map} +0 -0
  125. /package/dist/{seal-KJYAU23C.js.map → seal-TQ3RLVVT.js.map} +0 -0
  126. /package/dist/{setup-WHTMPK74.js.map → setup-7UGSJPJP.js.map} +0 -0
  127. /package/dist/{visual-PHKJTSFR.js.map → visual-6GXHKPCJ.js.map} +0 -0
  128. /package/dist/{watch-P6UWW52D.js.map → watch-M4A7B5WS.js.map} +0 -0
@@ -5,15 +5,15 @@
5
5
 
6
6
 
7
7
 
8
- var _chunkAM5ALISVcjs = require('./chunk-AM5ALISV.cjs');
8
+ var _chunkNW2CKOFLcjs = require('./chunk-NW2CKOFL.cjs');
9
9
 
10
10
 
11
11
 
12
- var _chunk435ECXNGcjs = require('./chunk-435ECXNG.cjs');
12
+ var _chunkJM7PZM6Ecjs = require('./chunk-JM7PZM6E.cjs');
13
13
 
14
14
 
15
15
 
16
- var _chunk2JDVPQ33cjs = require('./chunk-2JDVPQ33.cjs');
16
+ var _chunkC3BOYTY5cjs = require('./chunk-C3BOYTY5.cjs');
17
17
 
18
18
  // src/ocr/models.ts
19
19
  var _path = require('path');
@@ -57,7 +57,7 @@ var OCR_REC_DICT = {
57
57
  sizeMb: 1
58
58
  };
59
59
  function getOcrModelsDir() {
60
- return _chunk435ECXNGcjs.getModelsDir.call(void 0, "ppocr");
60
+ return _chunkJM7PZM6Ecjs.getModelsDir.call(void 0, "ppocr");
61
61
  }
62
62
  var DEFAULT_OCR_MODELS = Object.freeze({
63
63
  det: { spec: OCR_DET_MODEL },
@@ -99,7 +99,7 @@ async function ensureOcrModelsFor(sel, onProgress) {
99
99
  if (!stamp || verifiedInProcess.get(path) !== stamp) todo.push(s.spec);
100
100
  }
101
101
  if (!todo.length) return;
102
- await _chunk435ECXNGcjs.ensureModelsIn.call(void 0, dir, todo, onProgress);
102
+ await _chunkJM7PZM6Ecjs.ensureModelsIn.call(void 0, dir, todo, onProgress);
103
103
  for (const spec of todo) {
104
104
  const path = _path.join.call(void 0, dir, spec.filename), stamp = await fileStamp(path);
105
105
  if (stamp) verifiedInProcess.set(path, stamp);
@@ -146,6 +146,773 @@ function ocrModelPath(spec) {
146
146
  return _path.join.call(void 0, getOcrModelsDir(), spec.filename);
147
147
  }
148
148
 
149
+ // src/ocr/line-split.ts
150
+ function grayCrop(rgba, pageW, box) {
151
+ const out = new Uint8Array(box.w * box.h);
152
+ for (let y = 0; y < box.h; y++) {
153
+ let si = ((box.y + y) * pageW + box.x) * 4;
154
+ let di = y * box.w;
155
+ for (let x = 0; x < box.w; x++, si += 4, di++) {
156
+ out[di] = rgba[si] * 77 + rgba[si + 1] * 150 + rgba[si + 2] * 29 >> 8;
157
+ }
158
+ }
159
+ return out;
160
+ }
161
+ function inkStats(gray) {
162
+ const hist = new Uint32Array(256);
163
+ for (let i = 0; i < gray.length; i++) hist[gray[i]]++;
164
+ const total = gray.length;
165
+ let sumAll = 0;
166
+ for (let v = 0; v < 256; v++) sumAll += v * hist[v];
167
+ let wB = 0, sumB = 0, best = -1, thr = 127;
168
+ for (let t = 0; t < 256; t++) {
169
+ wB += hist[t];
170
+ if (wB === 0) continue;
171
+ const wF = total - wB;
172
+ if (wF === 0) break;
173
+ sumB += t * hist[t];
174
+ const mB = sumB / wB;
175
+ const mF = (sumAll - sumB) / wF;
176
+ const between = wB * wF * (mB - mF) * (mB - mF);
177
+ if (between > best) {
178
+ best = between;
179
+ thr = t;
180
+ }
181
+ }
182
+ let nDark = 0, sDark = 0;
183
+ for (let v = 0; v <= thr; v++) {
184
+ nDark += hist[v];
185
+ sDark += v * hist[v];
186
+ }
187
+ const nLight = total - nDark;
188
+ const sLight = sumAll - sDark;
189
+ if (nDark === 0 || nLight === 0) return { threshold: thr, darkInk: true, contrast: 0, inkRatio: 0 };
190
+ const darkInk = nDark <= nLight;
191
+ return {
192
+ threshold: thr,
193
+ darkInk,
194
+ contrast: sLight / nLight - sDark / nDark,
195
+ inkRatio: (darkInk ? nDark : nLight) / total
196
+ };
197
+ }
198
+ function splitRowBands(gray, w, h, ink, minBandRatio) {
199
+ const isInk = (v) => ink.darkInk ? v <= ink.threshold : v > ink.threshold;
200
+ const colInk = new Uint32Array(w);
201
+ for (let y = 0; y < h; y++) {
202
+ const off = y * w;
203
+ for (let x = 0; x < w; x++) if (isInk(gray[off + x])) colInk[x]++;
204
+ }
205
+ const ruleCol = new Uint8Array(w);
206
+ let liveW = 0;
207
+ for (let x = 0; x < w; x++) {
208
+ if (colInk[x] >= h * 0.85) ruleCol[x] = 1;
209
+ else liveW++;
210
+ }
211
+ const rowInk = new Uint32Array(h);
212
+ for (let y = 0; y < h; y++) {
213
+ let n = 0;
214
+ const off = y * w;
215
+ for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[off + x])) n++;
216
+ rowInk[y] = n >= liveW * 0.85 ? 0 : n;
217
+ }
218
+ const blank = Math.max(1, Math.floor(w * 0.02));
219
+ let bands = [];
220
+ let start = -1;
221
+ for (let y = 0; y <= h; y++) {
222
+ const on = y < h && rowInk[y] > blank;
223
+ if (on && start < 0) start = y;
224
+ else if (!on && start >= 0) {
225
+ bands.push([start, y]);
226
+ start = -1;
227
+ }
228
+ }
229
+ const inkCols = (y0, y1) => {
230
+ let x0 = w, x1 = -1;
231
+ for (let y = y0; y < y1; y++) {
232
+ const off = y * w;
233
+ for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[off + x])) {
234
+ if (x < x0) x0 = x;
235
+ if (x > x1) x1 = x;
236
+ }
237
+ }
238
+ return x1 >= x0 ? [x0, x1 + 1] : [0, w];
239
+ };
240
+ if (bands.length <= 1) return [{ y0: _nullishCoalesce(_optionalChain([bands, 'access', _7 => _7[0], 'optionalAccess', _8 => _8[0]]), () => ( 0)), y1: _nullishCoalesce(_optionalChain([bands, 'access', _9 => _9[0], 'optionalAccess', _10 => _10[1]]), () => ( h)), x0: 0, x1: w }];
241
+ const widths = bands.map(([y0, y1]) => {
242
+ const [a, b] = inkCols(y0, y1);
243
+ return b - a;
244
+ }).sort((a, b) => a - b);
245
+ const charSize = widths[widths.length >> 1];
246
+ const minBand = Math.max(3, minBandRatio * charSize);
247
+ for (let i = 0; i + 1 < bands.length; ) {
248
+ const gap = bands[i + 1][0] - bands[i][1];
249
+ if (gap <= Math.max(2, charSize * 0.15) && bands[i + 1][1] - bands[i][0] <= charSize * 1.3) {
250
+ bands.splice(i, 2, [bands[i][0], bands[i + 1][1]]);
251
+ } else i++;
252
+ }
253
+ while (bands.length > 1 && bands[0][0] <= 1 && bands[0][1] - bands[0][0] < minBand) bands.shift();
254
+ while (bands.length > 1 && bands[bands.length - 1][1] >= h - 1 && bands[bands.length - 1][1] - bands[bands.length - 1][0] < minBand) bands.pop();
255
+ for (; ; ) {
256
+ let idx = -1, minH = Infinity;
257
+ for (let i = 0; i < bands.length; i++) {
258
+ const bh = bands[i][1] - bands[i][0];
259
+ if (bh < minBand && bh < minH) {
260
+ minH = bh;
261
+ idx = i;
262
+ }
263
+ }
264
+ if (idx < 0 || bands.length === 1) break;
265
+ const gapPrev = idx > 0 ? bands[idx][0] - bands[idx - 1][1] : Infinity;
266
+ const gapNext = idx < bands.length - 1 ? bands[idx + 1][0] - bands[idx][1] : Infinity;
267
+ const j = gapPrev <= gapNext ? idx - 1 : idx + 1;
268
+ const a = Math.min(idx, j), b = Math.max(idx, j);
269
+ bands = [...bands.slice(0, a), [bands[a][0], bands[b][1]], ...bands.slice(b + 1)];
270
+ }
271
+ if (bands.length === 1) return [{ y0: bands[0][0], y1: bands[0][1], x0: 0, x1: w }];
272
+ return bands.map(([y0, y1]) => {
273
+ const [x0, x1] = inkCols(y0, y1);
274
+ return { y0, y1, x0, x1 };
275
+ });
276
+ }
277
+ function components(gray, w, h, ink) {
278
+ const isInk = (v) => ink.darkInk ? v <= ink.threshold : v > ink.threshold;
279
+ const comps = [];
280
+ const label = new Int32Array(w * h);
281
+ const stack = [];
282
+ for (let p0 = 0; p0 < w * h; p0++) {
283
+ if (label[p0] || !isInk(gray[p0])) continue;
284
+ const c = { x0: w, x1: 0, y0: h, y1: 0, id: comps.length + 1 };
285
+ label[p0] = c.id;
286
+ stack.push(p0);
287
+ while (stack.length) {
288
+ const p = stack.pop();
289
+ const x = p % w, y = p / w | 0;
290
+ if (x < c.x0) c.x0 = x;
291
+ if (x + 1 > c.x1) c.x1 = x + 1;
292
+ if (y < c.y0) c.y0 = y;
293
+ if (y + 1 > c.y1) c.y1 = y + 1;
294
+ for (let dy = -1; dy <= 1; dy++) for (let dx = -1; dx <= 1; dx++) {
295
+ const nx = x + dx, ny = y + dy;
296
+ if (nx < 0 || ny < 0 || nx >= w || ny >= h) continue;
297
+ const q = ny * w + nx;
298
+ if (!label[q] && isInk(gray[q])) {
299
+ label[q] = c.id;
300
+ stack.push(q);
301
+ }
302
+ }
303
+ }
304
+ if (c.y1 - c.y0 < h * 0.85 && c.x1 - c.x0 < w * 0.85) comps.push(c);
305
+ }
306
+ return { comps, label };
307
+ }
308
+ function leadingTriangle(gray, w, h, ink) {
309
+ const { comps, label } = components(gray, w, h, ink);
310
+ let charH = 0;
311
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
312
+ const first = comps.filter((c) => c.y1 - c.y0 >= charH * 0.4).sort((a, b) => a.x0 - b.x0)[0];
313
+ if (!first || charH < 8) return null;
314
+ const cw = first.x1 - first.x0, ch = first.y1 - first.y0;
315
+ if (cw < ch * 0.8 || cw > ch * 1.8) return null;
316
+ const rowSpan = (y) => {
317
+ let n = 0, lo = -1, hi = -1, runs = 0, prev = false;
318
+ for (let x = first.x0; x < first.x1; x++) {
319
+ const on = label[y * w + x] === first.id;
320
+ if (on) {
321
+ n++;
322
+ if (lo < 0) lo = x - first.x0;
323
+ hi = x - first.x0;
324
+ if (!prev) runs++;
325
+ }
326
+ prev = on;
327
+ }
328
+ return { n, lo, hi, runs };
329
+ };
330
+ const base = Math.max(rowSpan(first.y1 - 1).n, rowSpan(first.y1 - 2).n);
331
+ if (base < cw * 0.7) return null;
332
+ for (let y = first.y0; y < first.y0 + Math.max(1, Math.round(ch * 0.2)); y++) {
333
+ const r = rowSpan(y);
334
+ if (r.n === 0) continue;
335
+ if (r.hi - r.lo + 1 > cw * 0.4 || (r.lo + r.hi) / 2 < cw * 0.25 || (r.lo + r.hi) / 2 > cw * 0.75) return null;
336
+ }
337
+ const mid = rowSpan(first.y0 + Math.round(ch * 0.6));
338
+ if (mid.lo < 0 || mid.lo > cw * 0.3 || mid.hi < cw * 0.7) return null;
339
+ return mid.runs >= 2 ? "\u25B3" : "\u25B2";
340
+ }
341
+ function leaderRuns(gray, w, h, ink, minDots) {
342
+ const comps = components(gray, w, h, ink).comps.sort((a, b) => a.x0 - b.x0);
343
+ const blobs = [];
344
+ for (const c of comps) {
345
+ const last = blobs[blobs.length - 1];
346
+ if (last && c.x0 < last.x1) {
347
+ last.x1 = Math.max(last.x1, c.x1);
348
+ last.y0 = Math.min(last.y0, c.y0);
349
+ last.y1 = Math.max(last.y1, c.y1);
350
+ } else blobs.push({ x0: c.x0, x1: c.x1, y0: c.y0, y1: c.y1 });
351
+ }
352
+ let charH = 0;
353
+ for (const b of blobs) charH = Math.max(charH, b.y1 - b.y0);
354
+ if (charH < 8) return [];
355
+ const small = (c) => c.x1 - c.x0 <= charH * 0.3 && c.y1 - c.y0 <= charH * 0.3;
356
+ let bandTop = h, bandBot = 0;
357
+ for (const c of comps) if (!small(c)) {
358
+ bandTop = Math.min(bandTop, c.y0);
359
+ bandBot = Math.max(bandBot, c.y1);
360
+ }
361
+ const cy = (c) => (c.y0 + c.y1) / 2;
362
+ const isDot = (b) => small(b) && cy(b) >= bandTop && cy(b) <= bandBot;
363
+ const runs = [];
364
+ for (let i = 0; i < blobs.length; ) {
365
+ if (!isDot(blobs[i])) {
366
+ i++;
367
+ continue;
368
+ }
369
+ let j = i;
370
+ while (j + 1 < blobs.length && isDot(blobs[j + 1]) && blobs[j + 1].x0 - blobs[j].x1 <= charH && Math.abs(cy(blobs[j + 1]) - cy(blobs[i])) <= charH * 0.2) j++;
371
+ const x0 = blobs[i].x0, x1 = blobs[j].x1, y = cy(blobs[i]);
372
+ const onLine = comps.some((c) => !small(c) && c.y0 <= y && c.y1 >= y && (c.x1 <= x0 + 2 && c.x1 >= x0 - 2 * charH || c.x0 >= x1 - 2 && c.x0 <= x1 + 2 * charH));
373
+ const run = blobs.slice(i, j + 1).filter((b) => b.x0 > 0 && b.x1 < w);
374
+ const spread = (xs) => {
375
+ const v = [...xs].sort((a, b) => a - b).slice(xs.length >= 5 ? 1 : 0, xs.length >= 5 ? -1 : void 0);
376
+ return v[v.length - 1] / Math.max(1, v[0]);
377
+ };
378
+ const even = run.length >= 2 && spread(run.map((b) => b.x1 - b.x0)) <= 2.5 && spread(run.map((b) => b.y1 - b.y0)) <= 2.5 && spread(run.slice(1).map((b, k) => b.x0 - run[k].x0)) <= 1.8;
379
+ if (j - i + 1 >= minDots && onLine && even) runs.push([x0, x1]);
380
+ i = j + 1;
381
+ }
382
+ return runs;
383
+ }
384
+ function inkBounds(gray, w, h, ink) {
385
+ const isInk = (v) => ink.darkInk ? v <= ink.threshold : v > ink.threshold;
386
+ const colInk = new Uint32Array(w);
387
+ const rowInk = new Uint32Array(h);
388
+ for (let y = 0; y < h; y++) {
389
+ const off = y * w;
390
+ for (let x = 0; x < w; x++) if (isInk(gray[off + x])) {
391
+ colInk[x]++;
392
+ rowInk[y]++;
393
+ }
394
+ }
395
+ const ruleCol = new Uint8Array(w), ruleRow = new Uint8Array(h);
396
+ for (let x = 0; x < w; x++) if (colInk[x] >= h * 0.85) ruleCol[x] = 1;
397
+ for (let y = 0; y < h; y++) if (rowInk[y] >= w * 0.85) ruleRow[y] = 1;
398
+ let x0 = w, x1 = -1, y0 = h, y1 = -1;
399
+ for (let y = 0; y < h; y++) {
400
+ if (ruleRow[y]) continue;
401
+ const off = y * w;
402
+ for (let x = 0; x < w; x++) {
403
+ if (ruleCol[x] || !isInk(gray[off + x])) continue;
404
+ if (x < x0) x0 = x;
405
+ if (x > x1) x1 = x;
406
+ if (y < y0) y0 = y;
407
+ if (y > y1) y1 = y;
408
+ }
409
+ }
410
+ if (x1 < x0 || y1 < y0) return { x0: 0, y0: 0, x1: w, y1: h };
411
+ return { x0, y0, x1: x1 + 1, y1: y1 + 1 };
412
+ }
413
+ function bracketFeatures(gray, w, h, ink, cx) {
414
+ const { comps, label } = components(gray, w, h, ink);
415
+ let charH = 0;
416
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
417
+ if (charH < 8) return null;
418
+ const tol = Math.max(2, charH * 0.3);
419
+ let best = null, bestD = Infinity;
420
+ for (const c of comps) {
421
+ if (c.y1 - c.y0 < charH * 0.3 || c.x1 < cx - tol || c.x0 > cx + tol) continue;
422
+ const d = Math.abs((c.x0 + c.x1) / 2 - cx);
423
+ if (d < bestD) {
424
+ bestD = d;
425
+ best = c;
426
+ }
427
+ }
428
+ if (!best) return null;
429
+ const b = best;
430
+ const cw = b.x1 - b.x0, ch = b.y1 - b.y0;
431
+ if (cw < 3 || ch < 8) return null;
432
+ const spans = [];
433
+ for (let y = b.y0; y < b.y1; y++) {
434
+ let n = 0;
435
+ for (let x = b.x0; x < b.x1; x++) if (label[y * w + x] === b.id) n++;
436
+ spans.push(n);
437
+ }
438
+ const band = Math.max(1, Math.round(ch * 0.15));
439
+ const top = Math.max(...spans.slice(0, band)) / cw, bottom = Math.max(...spans.slice(ch - band)) / cw;
440
+ const midRows = spans.slice(Math.floor(ch * 0.3), Math.ceil(ch * 0.7)).sort((p, q) => p - q);
441
+ const stroke = _nullishCoalesce(midRows[midRows.length >> 1], () => ( 0));
442
+ const taper = spans.filter((n) => n > stroke && n < cw).length / ch;
443
+ const fill = spans.reduce((a, n) => a + n, 0) / (cw * ch);
444
+ return { top, bottom, taper, fill, cw, ch, charH };
445
+ }
446
+ function romanStems(gray, w, h, ink, prevX, nextX) {
447
+ const { comps, label } = components(gray, w, h, ink);
448
+ let charH = 0;
449
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
450
+ if (charH < 10) return null;
451
+ const x0 = prevX + charH * 0.35, x1 = nextX - charH * 0.35;
452
+ const sel = comps.filter((c) => c.y1 - c.y0 >= charH * 0.6 && (c.x0 + c.x1) / 2 >= x0 && (c.x0 + c.x1) / 2 < x1);
453
+ if (!sel.length) return null;
454
+ const ids = new Set(sel.map((c) => c.id));
455
+ const ux0 = Math.min(...sel.map((c) => c.x0)), ux1 = Math.max(...sel.map((c) => c.x1));
456
+ const uy0 = Math.min(...sel.map((c) => c.y0)), uy1 = Math.max(...sel.map((c) => c.y1));
457
+ const uh = uy1 - uy0;
458
+ const counts = /* @__PURE__ */ new Map();
459
+ let rows = 0;
460
+ for (let y = uy0 + Math.floor(uh * 0.25); y < uy1 - Math.floor(uh * 0.25); y++) {
461
+ let runs = 0, len = 0, thick = false;
462
+ for (let x = ux0; x <= ux1; x++) {
463
+ const on = x < ux1 && ids.has(label[y * w + x]);
464
+ if (on) len++;
465
+ else if (len) {
466
+ runs++;
467
+ if (len > uh * 0.35) thick = true;
468
+ len = 0;
469
+ }
470
+ }
471
+ rows++;
472
+ if (!thick) counts.set(runs, (_nullishCoalesce(counts.get(runs), () => ( 0))) + 1);
473
+ }
474
+ const [n, k] = _nullishCoalesce([...counts].sort((a, b) => b[1] - a[1])[0], () => ( [0, 0]));
475
+ return n >= 1 && n <= 3 && k >= rows * 0.7 ? n : null;
476
+ }
477
+ function circledAt(gray, w, h, ink, xs) {
478
+ const { comps } = components(gray, w, h, ink);
479
+ let charH = 0;
480
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
481
+ const rings = charH < 10 ? [] : comps.filter((r) => {
482
+ const rw = r.x1 - r.x0, rh = r.y1 - r.y0;
483
+ return rh >= charH * 0.55 && rw >= rh * 0.8 && rw <= rh * 1.25 && comps.some((d) => d !== r && d.x0 > r.x0 && d.x1 < r.x1 && d.y0 > r.y0 && d.y1 < r.y1 && d.y1 - d.y0 >= rh * 0.35);
484
+ });
485
+ return xs.map((x) => rings.some((r) => x >= r.x0 && x <= r.x1));
486
+ }
487
+ function quoteHead(gray, w, h, ink, cx) {
488
+ const { comps, label } = components(gray, w, h, ink);
489
+ let charH = 0;
490
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
491
+ if (charH < 10) return null;
492
+ const tall = comps.filter((c) => c.y1 - c.y0 >= charH * 0.6);
493
+ if (!tall.length) return null;
494
+ const mid = (Math.min(...tall.map((c) => c.y0)) + Math.max(...tall.map((c) => c.y1))) / 2;
495
+ let best = null, bestD = charH * 0.4;
496
+ for (const c of comps) {
497
+ const ch = c.y1 - c.y0, d = Math.abs((c.x0 + c.x1) / 2 - cx);
498
+ if (ch < charH * 0.12 || ch > charH * 0.5 || (c.y0 + c.y1) / 2 > mid || d > bestD) continue;
499
+ bestD = d;
500
+ best = c;
501
+ }
502
+ if (!best) return null;
503
+ let n = 0, sy = 0;
504
+ for (let y = best.y0; y < best.y1; y++) for (let x = best.x0; x < best.x1; x++) if (label[y * w + x] === best.id) {
505
+ n++;
506
+ sy += y;
507
+ }
508
+ return n ? (sy / n - best.y0) / (best.y1 - best.y0) : null;
509
+ }
510
+ function edgeTrim(gray, w, h, ink) {
511
+ const isInk = (v) => ink.darkInk ? v <= ink.threshold : v > ink.threshold;
512
+ const colInk = new Uint32Array(w);
513
+ for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) if (isInk(gray[y * w + x])) colInk[x]++;
514
+ const ruleCol = new Uint8Array(w);
515
+ let liveW = 0;
516
+ for (let x = 0; x < w; x++) {
517
+ if (colInk[x] >= h * 0.85) ruleCol[x] = 1;
518
+ else liveW++;
519
+ }
520
+ const blank = Math.max(1, Math.floor(w * 0.02));
521
+ const bands = [];
522
+ let start = -1;
523
+ for (let y = 0; y <= h; y++) {
524
+ let n = 0;
525
+ if (y < h) {
526
+ for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[y * w + x])) n++;
527
+ }
528
+ const on = y < h && n > blank && n < liveW * 0.85;
529
+ if (on && start < 0) start = y;
530
+ else if (!on && start >= 0) {
531
+ bands.push([start, y]);
532
+ start = -1;
533
+ }
534
+ }
535
+ let y0 = 0, y1 = h;
536
+ if (bands.length >= 2 && h >= 24) {
537
+ const mh = Math.max(...bands.map(([a, b]) => b - a));
538
+ const [top, next] = [bands[0], bands[1]], [bot, prev] = [bands[bands.length - 1], bands[bands.length - 2]];
539
+ if (top[0] <= 1 && top[1] - top[0] < mh * 0.45) y0 = top[1] + next[0] >> 1;
540
+ if (bot[1] >= h - 1 && bot[1] - bot[0] < mh * 0.45) y1 = bot[0] + prev[1] + 1 >> 1;
541
+ if (y0 > 0 || y1 < h) {
542
+ let runs = 0, len = 0;
543
+ for (let x = 0; x <= w; x++) {
544
+ let on = false;
545
+ if (x < w && !ruleCol[x]) for (let y = y0; y < y1 && !on; y++) on = isInk(gray[y * w + x]);
546
+ if (on) len++;
547
+ else {
548
+ if (len >= (y1 - y0) * 0.3) runs++;
549
+ len = 0;
550
+ }
551
+ }
552
+ if (runs < 2) {
553
+ y0 = 0;
554
+ y1 = h;
555
+ }
556
+ }
557
+ }
558
+ const textCol = (x) => {
559
+ for (let y = y0; y < y1; y++) if (isInk(gray[y * w + x])) return true;
560
+ return false;
561
+ };
562
+ const border = (x) => colInk[x] >= h * 0.95;
563
+ const gap = Math.max(2, Math.round(h * 0.1));
564
+ const clearFrom = (x, dir) => {
565
+ for (let k = 0; k < gap; k++) {
566
+ const c = x + dir * k;
567
+ if (c < 0 || c >= w || textCol(c)) return false;
568
+ }
569
+ return true;
570
+ };
571
+ let x0 = 0, x1 = w;
572
+ for (let x = 0; x < w * 0.2; x++) {
573
+ if (border(x)) {
574
+ let e = x;
575
+ while (e + 1 < w && border(e + 1)) e++;
576
+ if (clearFrom(e + 1, 1)) x0 = e + 1;
577
+ break;
578
+ }
579
+ if (textCol(x)) break;
580
+ }
581
+ for (let x = w - 1; x >= w * 0.8; x--) {
582
+ if (border(x)) {
583
+ let e = x;
584
+ while (e - 1 >= 0 && border(e - 1)) e--;
585
+ if (clearFrom(e - 1, -1)) x1 = e;
586
+ break;
587
+ }
588
+ if (textCol(x)) break;
589
+ }
590
+ return y0 > 0 || y1 < h || x0 > 0 || x1 < w ? { x0, x1, y0, y1 } : null;
591
+ }
592
+ function tallInkCount(gray, w, h, ink) {
593
+ const { comps } = components(gray, w, h, ink);
594
+ let charH = 0;
595
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
596
+ const tall = comps.filter((c) => c.y1 - c.y0 >= charH * 0.5).sort((a, b) => a.x0 - b.x0);
597
+ let n = 0, end = -1;
598
+ for (const c of tall) {
599
+ if (c.x0 >= end) n++;
600
+ end = Math.max(end, c.x1);
601
+ }
602
+ return n;
603
+ }
604
+ function gapGlyphs(gray, w, h, ink) {
605
+ const { comps, label } = components(gray, w, h, ink);
606
+ let charH = 0;
607
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
608
+ if (charH < 10) return { glyphs: [], bandH: 0 };
609
+ const tall = comps.filter((c) => c.y1 - c.y0 >= charH * 0.6);
610
+ const bandT = Math.min(...tall.map((c) => c.y0)), bandB = Math.max(...tall.map((c) => c.y1)), bh = bandB - bandT;
611
+ const inBand = (c) => c.y1 > bandT && c.y0 < bandB;
612
+ const out = [];
613
+ for (const c of comps) {
614
+ if (!inBand(c)) continue;
615
+ const cw = c.x1 - c.x0, ch = c.y1 - c.y0;
616
+ if (ch >= bh * 0.9 && cw <= bh * 0.15) continue;
617
+ const others = comps.filter((o) => o !== c && inBand(o) && !(o.x0 >= c.x0 && o.x1 <= c.x1 && o.y0 >= c.y0 && o.y1 <= c.y1));
618
+ const apart = !others.some((o) => o.x0 < c.x1 + 1 && o.x1 > c.x0 - 1);
619
+ const abut = !apart && ch >= bh * 0.3 && ch <= bh * 0.65 && !others.some((o) => o.x0 < c.x1 && o.x1 > c.x0);
620
+ const nearlyApart = !others.some((o) => Math.min(o.x1, c.x1) - Math.max(o.x0, c.x0) > 2);
621
+ const spans = [], runs = [];
622
+ let n = 0;
623
+ for (let y = c.y0; y < c.y1; y++) {
624
+ let s = 0, r = 0, prev = false;
625
+ for (let x = c.x0; x < c.x1; x++) {
626
+ const on = label[y * w + x] === c.id;
627
+ if (on) {
628
+ s++;
629
+ if (!prev) r++;
630
+ }
631
+ prev = on;
632
+ }
633
+ spans.push(s);
634
+ runs.push(r);
635
+ n += s;
636
+ }
637
+ const fill = n / (cw * ch), cy = ((c.y0 + c.y1) / 2 - bandT) / bh;
638
+ const band = Math.max(1, Math.round(ch * 0.15));
639
+ const top = Math.max(...spans.slice(0, band)) / cw, bottom = Math.max(...spans.slice(ch - band)) / cw;
640
+ let mark = null;
641
+ const speck = Math.max(3, bh * 0.08);
642
+ const dot = ch <= bh * 0.25 && cw <= bh * 0.25 && ch >= speck && cw >= speck && cw >= ch * 0.6 && cw <= ch * 1.6;
643
+ const small = ch <= bh * 0.25 && cw <= bh * 0.25 && ch >= 2 && cw >= 2 && cw >= ch * 0.6 && cw <= ch * 1.6 && fill >= 0.6 && cy >= 0.3 && cy <= 0.7;
644
+ if (!apart && !abut && !(nearlyApart && ch >= bh * 0.6)) {
645
+ if (small) out.push({ x0: c.x0, x1: c.x1, mark: "\xB7" });
646
+ continue;
647
+ }
648
+ const bracket = () => {
649
+ const stem = (from, to) => {
650
+ let sx = 0, k = 0;
651
+ for (let y = from; y < to; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) {
652
+ sx += x - c.x0;
653
+ k++;
654
+ }
655
+ return k ? sx / k / cw : 0.5;
656
+ };
657
+ if (c.y0 <= bandT + bh * 0.15 && top >= 0.7 && bottom <= 0.5 && stem(c.y0 + band, c.y1) <= 0.35) return "\u300C";
658
+ if (c.y1 >= bandB - bh * 0.15 && bottom >= 0.7 && top <= 0.5 && stem(c.y0, c.y1 - band) >= 0.65) return "\u300D";
659
+ return null;
660
+ };
661
+ if (!apart && !abut) {
662
+ } else if (abut) {
663
+ if (fill < 0.5) mark = bracket();
664
+ } else if (dot && fill >= 0.6 && cy >= 0.3 && cy <= 0.7) mark = "\xB7";
665
+ else if (small) mark = "\xB7";
666
+ else if (dot && fill >= 0.6 && cy >= 0.75 && cw >= ch * 0.8) mark = ".";
667
+ else if (ch <= bh * 0.4 && ch >= speck && cw >= ch * 0.75 && cw <= ch * 1.3 && fill < 0.6 && runs[ch >> 1] === 2 && cy >= 0.6) mark = "\u3002";
668
+ else if (ch <= bh * 0.15 && cw >= ch * 2 && cw <= bh * 0.8 && fill >= 0.7 && cy >= 0.35 && cy <= 0.75) mark = "-";
669
+ else if (ch >= bh * 0.5 && cw >= ch * 0.9 && cw <= ch * 1.4 && fill >= 0.4 && runs.every((r) => r <= 1) && top <= 0.4 && bottom >= 0.8) mark = "\u25B2";
670
+ else if (ch >= bh * 0.3 && ch <= bh * 0.65 && fill < 0.5) mark = bracket();
671
+ else if (ch >= charH * 0.6 && cw >= ch * 0.8 && cw <= ch * 1.25 && fill < 0.5 && top >= 0.8 && bottom >= 0.8 && runs[ch >> 1] === 2) mark = ch <= charH * 0.92 ? "\u25A1" : "\u25A1\0";
672
+ if (!mark && ch >= bh * 0.6 && cw >= ch * 0.25 && cw <= ch * 0.7 && fill <= 0.4 && runs.every((r) => r <= 1)) {
673
+ const mx = (y) => {
674
+ let sx = 0, k = 0;
675
+ for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) {
676
+ sx += x;
677
+ k++;
678
+ }
679
+ return k ? sx / k : NaN;
680
+ };
681
+ if (mx(c.y0 + band) - mx(c.y1 - 1 - band) >= cw * 0.5) mark = "/";
682
+ }
683
+ if (mark) out.push({ x0: c.x0, x1: c.x1, mark });
684
+ }
685
+ return { glyphs: out, bandH: bh };
686
+ }
687
+ function ringBullet(gray, w, h, ink, cx) {
688
+ const { comps, label } = components(gray, w, h, ink);
689
+ let charH = 0;
690
+ for (const c2 of comps) charH = Math.max(charH, c2.y1 - c2.y0);
691
+ if (charH < 10) return null;
692
+ const tall = comps.filter((c2) => c2.y1 - c2.y0 >= charH * 0.6);
693
+ const bandT = Math.min(...tall.map((c2) => c2.y0)), bh = Math.max(...tall.map((c2) => c2.y1)) - bandT;
694
+ let best = null, bestD = bh * 0.6;
695
+ for (const c2 of comps) {
696
+ const d = Math.abs((c2.x0 + c2.x1) / 2 - cx);
697
+ if (c2.y1 - c2.y0 >= bh * 0.3 && d < bestD) {
698
+ bestD = d;
699
+ best = c2;
700
+ }
701
+ }
702
+ if (!best) return null;
703
+ const c = best, cw = c.x1 - c.x0, ch = c.y1 - c.y0;
704
+ if (cw < ch * 0.85 || cw > ch * 1.2) return null;
705
+ const runs = (xs, at) => {
706
+ let n2 = 0, len = 0, mx2 = 0, mn = Infinity;
707
+ for (const k of [...xs, -1]) {
708
+ if (k >= 0 && at(k)) {
709
+ if (!len) n2++;
710
+ len++;
711
+ mx2 = Math.max(mx2, len);
712
+ } else {
713
+ if (len) mn = Math.min(mn, len);
714
+ len = 0;
715
+ }
716
+ }
717
+ return { n: n2, mx: mx2, mn };
718
+ };
719
+ const my = c.y0 + c.y1 >> 1, mx = c.x0 + c.x1 >> 1;
720
+ const row = runs(Array.from({ length: cw }, (_, k) => c.x0 + k), (x) => label[my * w + x] === c.id);
721
+ const col = runs(Array.from({ length: ch }, (_, k) => c.y0 + k), (y) => label[y * w + mx] === c.id);
722
+ if (row.n !== 2 || col.n !== 2) return null;
723
+ let n = 0;
724
+ for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++;
725
+ const fill = n / (cw * ch), rel = ch / bh;
726
+ if (rel >= 0.62 && (fill <= 0.23 ? row.mx <= cw * 0.1 : fill <= 0.33 && row.mn <= cw * 0.08)) return "\u25CB";
727
+ if (rel <= 0.58 && fill >= 0.24) return "\u3147";
728
+ if (rel >= 0.6 && rel <= 0.8 && fill >= 0.3 && ((c.y0 + c.y1) / 2 - bandT) / bh >= 0.55) return "o";
729
+ return null;
730
+ }
731
+ function dashRatio(gray, w, h, ink, cx) {
732
+ const { comps } = components(gray, w, h, ink);
733
+ let charH = 0;
734
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
735
+ if (charH < 10) return null;
736
+ const tall = comps.filter((c) => c.y1 - c.y0 >= charH * 0.6);
737
+ const bh = Math.max(...tall.map((c) => c.y1)) - Math.min(...tall.map((c) => c.y0));
738
+ const dash = comps.filter((c) => c.y1 - c.y0 <= bh * 0.25 && c.x1 - c.x0 >= (c.y1 - c.y0) * 2 && Math.abs((c.x0 + c.x1) / 2 - cx) <= bh * 0.6).sort((a, b) => Math.abs((a.x0 + a.x1) / 2 - cx) - Math.abs((b.x0 + b.x1) / 2 - cx))[0];
739
+ return dash ? (dash.x1 - dash.x0) / bh : null;
740
+ }
741
+ function discAt(gray, w, h, ink, cx) {
742
+ const { comps, label } = components(gray, w, h, ink);
743
+ let charH = 0;
744
+ for (const c2 of comps) charH = Math.max(charH, c2.y1 - c2.y0);
745
+ if (charH < 10) return false;
746
+ const tall = comps.filter((c2) => c2.y1 - c2.y0 >= charH * 0.6);
747
+ const bh = Math.max(...tall.map((c2) => c2.y1)) - Math.min(...tall.map((c2) => c2.y0));
748
+ const c = comps.filter((o) => Math.abs((o.x0 + o.x1) / 2 - cx) <= bh * 0.4).sort((a, b) => Math.abs((a.x0 + a.x1) / 2 - cx) - Math.abs((b.x0 + b.x1) / 2 - cx))[0];
749
+ if (!c) return false;
750
+ const cw = c.x1 - c.x0, ch = c.y1 - c.y0;
751
+ if (ch < bh * 0.45 || ch > bh * 1.05 || cw < ch * 0.8 || cw > ch * 1.25) return false;
752
+ let n = 0;
753
+ for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++;
754
+ const fill = n / (cw * ch);
755
+ return fill >= 0.65 && fill <= 0.9;
756
+ }
757
+ function serifOne(gray, w, h, ink, cx) {
758
+ const { comps, label } = components(gray, w, h, ink);
759
+ let charH = 0;
760
+ for (const c2 of comps) charH = Math.max(charH, c2.y1 - c2.y0);
761
+ if (charH < 10) return false;
762
+ const c = comps.filter((o) => o.x0 - 3 <= cx && o.x1 + 3 >= cx && o.y1 - o.y0 >= charH * 0.6).sort((a, b) => b.y1 - b.y0 - (a.y1 - a.y0))[0];
763
+ if (!c) return false;
764
+ const ch = c.y1 - c.y0;
765
+ const span2 = (a, b) => {
766
+ let mn = Infinity, mx = -1;
767
+ for (let y = c.y0 + Math.floor(ch * a); y < c.y0 + Math.ceil(ch * b); y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) {
768
+ mn = Math.min(mn, x);
769
+ mx = Math.max(mx, x);
770
+ }
771
+ return [mn, mx];
772
+ };
773
+ const [m0, m1] = span2(0.4, 0.6), [t0, t1] = span2(0, 0.2), [b0, b1] = span2(0.8, 1);
774
+ const sw = m1 - m0 + 1;
775
+ const even = (l, r) => l >= sw * 0.4 && r >= sw * 0.4 && Math.abs(l - r) <= Math.max(l, r) * 0.35;
776
+ return sw >= 2 && sw <= ch * 0.3 && even(m0 - t0, t1 - m1) && even(m0 - b0, b1 - m1);
777
+ }
778
+ function starRun(gray, w, h, ink, cx) {
779
+ const { comps, label } = components(gray, w, h, ink);
780
+ let charH = 0;
781
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
782
+ if (charH < 10) return 0;
783
+ const tall = comps.filter((c) => c.y1 - c.y0 >= charH * 0.6);
784
+ const bandT = Math.min(...tall.map((c) => c.y0)), bh = Math.max(...tall.map((c) => c.y1)) - bandT;
785
+ const star = (c) => {
786
+ const cw = c.x1 - c.x0, ch = c.y1 - c.y0;
787
+ if (ch < bh * 0.2 || ch > bh * 0.5 || cw < ch * 0.7 || cw > ch * 1.4 || ((c.y0 + c.y1) / 2 - bandT) / bh > 0.55) return false;
788
+ let n = 0;
789
+ for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++;
790
+ const fill = n / (cw * ch);
791
+ return fill >= 0.25 && fill <= 0.65;
792
+ };
793
+ const stars = comps.filter(star).sort((a, b) => a.x0 - b.x0);
794
+ const k = stars.findIndex((c) => cx >= c.x0 - (c.x1 - c.x0) && cx <= c.x1 + (c.x1 - c.x0));
795
+ if (k < 0) return 0;
796
+ let lo = k, hi = k;
797
+ while (lo > 0 && stars[lo].x0 - stars[lo - 1].x1 <= stars[lo].x1 - stars[lo].x0) lo--;
798
+ while (hi + 1 < stars.length && stars[hi + 1].x0 - stars[hi].x1 <= stars[hi].x1 - stars[hi].x0) hi++;
799
+ return hi - lo + 1;
800
+ }
801
+ var BRACKET_TAPER = 0.16;
802
+ var BRACKET_SOLID = 0.4;
803
+ var BRACKET_WIDE = 0.265;
804
+ var BRACKET_LENS = 0.35;
805
+ function bracketShape(f, close) {
806
+ const [near2, far] = close ? [f.bottom, f.top] : [f.top, f.bottom];
807
+ const paren = close ? ")" : "(";
808
+ if (near2 >= 0.7 && far <= 0.5) return f.taper < BRACKET_TAPER ? close ? "\u300D" : "\u300C" : paren;
809
+ if (near2 >= 0.7 && far >= 0.7 && f.taper >= BRACKET_TAPER) {
810
+ return f.fill >= BRACKET_SOLID && (f.cw >= f.ch * BRACKET_WIDE || f.taper >= BRACKET_LENS) ? close ? "\u3011" : "\u3010" : paren;
811
+ }
812
+ return null;
813
+ }
814
+ function leadingBullet(gray, w, h, ink, firstX) {
815
+ const { comps, label } = components(gray, w, h, ink);
816
+ let charH = 0;
817
+ for (const c of comps) charH = Math.max(charH, c.y1 - c.y0);
818
+ if (charH < 10) return null;
819
+ const cand = comps.filter((c) => c.y1 - c.y0 >= charH * 0.15).sort((a, b) => a.x0 - b.x0);
820
+ const first = cand[0];
821
+ if (!first) return null;
822
+ const cl = cand.filter((c) => c.x0 < first.x1 && c.x1 > first.x0);
823
+ const x0 = Math.min(...cl.map((c) => c.x0)), x1 = Math.max(...cl.map((c) => c.x1)), y0 = Math.min(...cl.map((c) => c.y0)), y1 = Math.max(...cl.map((c) => c.y1));
824
+ const cw = x1 - x0, ch = y1 - y0;
825
+ if (cw < ch * 0.8 || cw > ch * 1.25) return null;
826
+ const next = cand.find((c) => c.x0 >= x1);
827
+ if (next && next.x0 - x1 < ch * 0.3) return null;
828
+ let inkN = 0;
829
+ for (let y = y0; y < y1; y++) for (let x = x0; x < x1; x++) if (cl.some((c) => label[y * w + x] === c.id)) inkN++;
830
+ const fill = inkN / (cw * ch);
831
+ const rel = ch / charH;
832
+ const ring = (c) => {
833
+ const a = c.x1 - c.x0, b = c.y1 - c.y0;
834
+ return a >= b * 0.75 && a <= b * 1.33;
835
+ };
836
+ const nested = cl.length >= 2 && cl.some((a) => cl.some((b) => a !== b && b.x0 > a.x0 && b.x1 < a.x1 && b.y0 > a.y0 && b.y1 < a.y1 && ring(b) && Math.abs(b.x0 + b.x1 - (a.x0 + a.x1)) <= (a.x1 - a.x0) * 0.2 && Math.abs(b.y0 + b.y1 - (a.y0 + a.y1)) <= (a.y1 - a.y0) * 0.2));
837
+ const span2 = (y) => {
838
+ let n = 0;
839
+ for (let x = x0; x < x1; x++) if (cl.some((c) => label[y * w + x] === c.id)) n++;
840
+ return n;
841
+ };
842
+ const band = Math.max(1, Math.round(ch * 0.15));
843
+ const edgeFull = (from, dir) => {
844
+ let m = 0;
845
+ for (let k = 0; k < band; k++) m = Math.max(m, span2(from + dir * k));
846
+ return m >= cw * 0.8;
847
+ };
848
+ let midRuns = 0;
849
+ {
850
+ let prev = false;
851
+ const my = y0 + (ch >> 1);
852
+ for (let x = x0; x < x1; x++) {
853
+ const on = cl.some((c) => label[my * w + x] === c.id);
854
+ if (on && !prev) midRuns++;
855
+ prev = on;
856
+ }
857
+ }
858
+ const hollowSquare = cl.length === 1 && fill < 0.5 && midRuns === 2 && edgeFull(y0, 1) && edgeFull(y1 - 1, -1);
859
+ let mark = null;
860
+ if (hollowSquare && rel >= 0.6 && rel <= 0.92) mark = "\u25A1";
861
+ else if (nested && fill < 0.45 && rel >= 0.6) mark = "\u25CE";
862
+ else if (cl.length === 1 && fill >= 0.9 && rel >= 0.28 && rel <= 0.6) mark = "\u25AA";
863
+ else if (cl.length === 1 && fill >= 0.65 && fill <= 0.88 && rel >= 0.5 && rel <= 0.8) mark = "\u25CF";
864
+ if (!mark) return null;
865
+ return { mark, covers: firstX <= x1 + ch * 0.3 };
866
+ }
867
+
868
+ // src/ocr/text-gaps.ts
869
+ var evidence = /* @__PURE__ */ new WeakMap();
870
+ var NO_GAPS = [];
871
+ function rememberOcrTextGaps(item, gaps) {
872
+ if (gaps.length) evidence.set(item, { text: item.text, gaps });
873
+ }
874
+ function ocrTextGaps(item) {
875
+ const saved = evidence.get(item);
876
+ return _optionalChain([saved, 'optionalAccess', _11 => _11.text]) === item.text ? saved.gaps : NO_GAPS;
877
+ }
878
+ function copyOcrTextGaps(source, target, scale = 1, offsetX = 0) {
879
+ const gaps = ocrTextGaps(source);
880
+ if (!gaps.length || source.text !== target.text) return;
881
+ rememberOcrTextGaps(target, scale === 1 && offsetX === 0 ? gaps : gaps.map((g) => ({ ...g, left: g.left * scale + offsetX, right: g.right * scale + offsetX })));
882
+ }
883
+ function findOcrTextGaps(rgba, pageW, box, read, text, steps, stepPx) {
884
+ if (read.replace(/\s/g, "") !== text.replace(/\s/g, "") || [...read].length !== steps.length) return [];
885
+ const visible = [...read].flatMap((c, i) => /\s/.test(c) ? [] : [(steps[i] + 0.5) * stepPx]);
886
+ if (visible.length < 2) return [];
887
+ const gray = grayCrop(rgba, pageW, box), ink = inkStats(gray);
888
+ if (!ink.darkInk || ink.contrast < 35) return [];
889
+ const counts = new Uint32Array(box.w);
890
+ for (let y = 0; y < box.h; y++) for (let x = 0; x < box.w; x++) if (gray[y * box.w + x] <= ink.threshold) counts[x]++;
891
+ const out = [];
892
+ let offset = 0, index = 0;
893
+ for (const c of text) {
894
+ if (!/\s/.test(c)) {
895
+ if (index > 0) {
896
+ const from = Math.max(0, Math.floor(visible[index - 1]) + 1), end = Math.min(box.w, Math.ceil(visible[index]));
897
+ let start = from, left = from, right = from;
898
+ for (let x = from; x <= end; x++) {
899
+ if (x === end || counts[x] > Math.max(1, Math.floor(box.h * 0.03))) {
900
+ if (x - start > right - left) {
901
+ left = start;
902
+ right = x;
903
+ }
904
+ start = x + 1;
905
+ }
906
+ }
907
+ if (right - left >= Math.max(3, box.h * 0.25)) out.push({ at: offset, left: box.x + left, right: box.x + right });
908
+ }
909
+ index++;
910
+ }
911
+ offset += c.length;
912
+ }
913
+ return out;
914
+ }
915
+
149
916
  // src/pdf/line-extract.ts
150
917
  var _pdfmjs = require('pdfjs-dist/legacy/build/pdf.mjs');
151
918
  var ORIENTATION_TOL = 2;
@@ -369,7 +1136,7 @@ function extractLines(fnArray, argsArray) {
369
1136
  } else {
370
1137
  const afterOp = arg0;
371
1138
  const dataArr = args[1];
372
- const pathData = _optionalChain([dataArr, 'optionalAccess', _7 => _7[0]]);
1139
+ const pathData = _optionalChain([dataArr, 'optionalAccess', _12 => _12[0]]);
373
1140
  if (pathData && typeof pathData === "object") {
374
1141
  const len = Object.keys(pathData).length;
375
1142
  let di = 0;
@@ -747,7 +1514,7 @@ function mergeParallelLines(lines, dir, nonRules) {
747
1514
  const overlap2 = Math.min(prevEnd, currEnd) - Math.max(prevStart, currStart);
748
1515
  const minLen = Math.min(prevEnd - prevStart, currEnd - currStart);
749
1516
  if (overlap2 > minLen * 0.3) {
750
- if (_optionalChain([nonRules, 'optionalAccess', _8 => _8.has, 'call', _9 => _9(prev)]) && !nonRules.has(curr)) nonRules.delete(prev);
1517
+ if (_optionalChain([nonRules, 'optionalAccess', _13 => _13.has, 'call', _14 => _14(prev)]) && !nonRules.has(curr)) nonRules.delete(prev);
751
1518
  if (dir === "h") {
752
1519
  prev.x1 = Math.min(prev.x1, curr.x1);
753
1520
  prev.x2 = Math.max(prev.x2, curr.x2);
@@ -815,8 +1582,8 @@ function extractImageRegions(fnArray, argsArray, respectClip = false) {
815
1582
  break;
816
1583
  case _pdfmjs.OPS.restore: {
817
1584
  const state = stack.pop();
818
- ctm = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _10 => _10.ctm]), () => ( [1, 0, 0, 1, 0, 0]));
819
- clip = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _11 => _11.clip]), () => ( null));
1585
+ ctm = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _15 => _15.ctm]), () => ( [1, 0, 0, 1, 0, 0]));
1586
+ clip = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _16 => _16.clip]), () => ( null));
820
1587
  break;
821
1588
  }
822
1589
  case _pdfmjs.OPS.transform: {
@@ -827,19 +1594,19 @@ function extractImageRegions(fnArray, argsArray, respectClip = false) {
827
1594
  // Form XObject 는 /Matrix 공간에서 그린다 — pdfjs 인자 [matrix, bbox], End 에서 복원 (line-extract.ts 와 같음)
828
1595
  case _pdfmjs.OPS.paintFormXObjectBegin: {
829
1596
  stack.push({ ctm, clip });
830
- const m = _optionalChain([argsArray, 'access', _12 => _12[i], 'optionalAccess', _13 => _13[0]]);
1597
+ const m = _optionalChain([argsArray, 'access', _17 => _17[i], 'optionalAccess', _18 => _18[0]]);
831
1598
  if (Array.isArray(m) && m.length >= 6) ctm = multiplyTransform(ctm, m);
832
1599
  break;
833
1600
  }
834
1601
  case _pdfmjs.OPS.paintFormXObjectEnd: {
835
1602
  const state = stack.pop();
836
- ctm = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _14 => _14.ctm]), () => ( [1, 0, 0, 1, 0, 0]));
837
- clip = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _15 => _15.clip]), () => ( null));
1603
+ ctm = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _19 => _19.ctm]), () => ( [1, 0, 0, 1, 0, 0]));
1604
+ clip = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _20 => _20.clip]), () => ( null));
838
1605
  break;
839
1606
  }
840
1607
  case _pdfmjs.OPS.constructPath: {
841
1608
  const [ops, coords] = argsArray[i];
842
- pathRect = pathRect === void 0 && _optionalChain([ops, 'optionalAccess', _16 => _16.length]) === 1 && ops[0] === _pdfmjs.OPS.rectangle && _optionalChain([coords, 'optionalAccess', _17 => _17.length]) >= 4 ? transformedRect(ctm, coords[0], coords[1], coords[2], coords[3]) : null;
1609
+ pathRect = pathRect === void 0 && _optionalChain([ops, 'optionalAccess', _21 => _21.length]) === 1 && ops[0] === _pdfmjs.OPS.rectangle && _optionalChain([coords, 'optionalAccess', _22 => _22.length]) >= 4 ? transformedRect(ctm, coords[0], coords[1], coords[2], coords[3]) : null;
843
1610
  break;
844
1611
  }
845
1612
  case _pdfmjs.OPS.clip:
@@ -992,7 +1759,7 @@ function hasShadedRowBands(host, clips, fills, verticals, horizontals) {
992
1759
  if (!host.colXs.slice(1, -1).every((x) => verticals.some((v) => !v.fromFill && near2(v.x1, x) && v.y1 <= host.bbox.y1 + tol && v.y2 >= host.bbox.y2 - tol))) return false;
993
1760
  const covered = /* @__PURE__ */ new Set();
994
1761
  for (const band of bands) {
995
- if (band.clipParent || !_optionalChain([band, 'access', _18 => _18.cells, 'optionalAccess', _19 => _19.length]) || band.colXs.length !== host.colXs.length || !band.colXs.every((x, i) => near2(x, host.colXs[i]))) return false;
1762
+ if (band.clipParent || !_optionalChain([band, 'access', _23 => _23.cells, 'optionalAccess', _24 => _24.length]) || band.colXs.length !== host.colXs.length || !band.colXs.every((x, i) => near2(x, host.colXs[i]))) return false;
996
1763
  const start = host.rowYs.findIndex((y) => near2(y, band.rowYs[0]));
997
1764
  if (start < 0 || !band.rowYs.every((y, i) => near2(y, host.rowYs[start + i]))) return false;
998
1765
  if (!band.rowYs.every((y) => horizontals.some((h) => !h.fromFill && near2(h.y1, y) && h.x1 <= host.bbox.x1 + tol && h.x2 >= host.bbox.x2 - tol))) return false;
@@ -1094,7 +1861,7 @@ function mergeVertices(vertices) {
1094
1861
  const candidates = [];
1095
1862
  for (let dx = -1; dx <= 1; dx++) {
1096
1863
  for (let dy = -1; dy <= 1; dy++) {
1097
- const arr = _optionalChain([buckets, 'access', _20 => _20.get, 'call', _21 => _21(cx + dx), 'optionalAccess', _22 => _22.get, 'call', _23 => _23(cy + dy)]);
1864
+ const arr = _optionalChain([buckets, 'access', _25 => _25.get, 'call', _26 => _26(cx + dx), 'optionalAccess', _27 => _27.get, 'call', _28 => _28(cy + dy)]);
1098
1865
  if (!arr) continue;
1099
1866
  for (const j of arr) {
1100
1867
  if (j > i && !used[j]) candidates.push(j);
@@ -1221,7 +1988,7 @@ function dropShadingClipGrids(clipGrids, lineGrids, fillRects, verticals = [], h
1221
1988
  const area = (b) => Math.max(0, b.x2 - b.x1) * Math.max(0, b.y2 - b.y1);
1222
1989
  const inter = (a, b) => area({ x1: Math.max(a.x1, b.x1), y1: Math.max(a.y1, b.y1), x2: Math.min(a.x2, b.x2), y2: Math.min(a.y2, b.y2) });
1223
1990
  return clipGrids.filter((c) => {
1224
- if (!_optionalChain([c, 'access', _24 => _24.cells, 'optionalAccess', _25 => _25.length]) || c.clipParent) return true;
1991
+ if (!_optionalChain([c, 'access', _29 => _29.cells, 'optionalAccess', _30 => _30.length]) || c.clipParent) return true;
1225
1992
  const sourceCells = c.cells.filter((cell) => !cell.filler);
1226
1993
  if (sourceCells.length === 0) return true;
1227
1994
  const shaded = sourceCells.every((cell) => fillRects.some((f) => near2(f.x1, cell.bbox.x1) && near2(f.x2, cell.bbox.x2) && near2(f.y1, cell.bbox.y1) && near2(f.y2, cell.bbox.y2)));
@@ -1231,7 +1998,7 @@ function dropShadingClipGrids(clipGrids, lineGrids, fillRects, verticals = [], h
1231
1998
  const host = lineGrids.find((l) => (
1232
1999
  // Inferred filler cells carry no boundary evidence. Replace their frame only
1233
2000
  // with a finer ruled grid of the same extent, never a larger surrounding form.
1234
- (!c.cells.some((cell) => cell.filler) || near2(c.bbox.x1, l.bbox.x1) && near2(c.bbox.x2, l.bbox.x2) && near2(c.bbox.y1, l.bbox.y1) && near2(c.bbox.y2, l.bbox.y2) && l.rowYs.length > c.rowYs.length && sourceCells.every((cell) => [cell.bbox.y1, cell.bbox.y2].every((y) => l.rowYs.some((ly) => near2(y, ly))))) && c.bbox.x1 >= l.bbox.x1 - SHADE_CLIP_TOL && c.bbox.x2 <= l.bbox.x2 + SHADE_CLIP_TOL && c.bbox.y1 >= l.bbox.y1 - SHADE_CLIP_TOL && c.bbox.y2 <= l.bbox.y2 + SHADE_CLIP_TOL && c.colXs.every((x) => l.colXs.some((lx) => near2(lx, x))) && (clipGrids.reduce((s, o) => s + (_optionalChain([o, 'access', _26 => _26.cells, 'optionalAccess', _27 => _27.some, 'call', _28 => _28((cell) => cell.filler)]) ? o.cells.filter((cell) => !cell.filler).reduce((a, cell) => a + inter(cell.bbox, l.bbox), 0) : inter(o.bbox, l.bbox)), 0) <= area(l.bbox) * SHADE_CLIP_MAX_AREA || l.rowYs.length === c.rowYs.length + 1 && c.rowYs.every((y, i) => near2(y, l.rowYs[i])) && l.colXs.length === c.colXs.length && c.colXs.every((x, i) => near2(x, l.colXs[i])) && !clipGrids.some((o) => o !== c && inter(o.bbox, l.bbox) > 0) || hasShadedRowBands(l, clipGrids, fillRects, verticals, horizontals))
2001
+ (!c.cells.some((cell) => cell.filler) || near2(c.bbox.x1, l.bbox.x1) && near2(c.bbox.x2, l.bbox.x2) && near2(c.bbox.y1, l.bbox.y1) && near2(c.bbox.y2, l.bbox.y2) && l.rowYs.length > c.rowYs.length && sourceCells.every((cell) => [cell.bbox.y1, cell.bbox.y2].every((y) => l.rowYs.some((ly) => near2(y, ly))))) && c.bbox.x1 >= l.bbox.x1 - SHADE_CLIP_TOL && c.bbox.x2 <= l.bbox.x2 + SHADE_CLIP_TOL && c.bbox.y1 >= l.bbox.y1 - SHADE_CLIP_TOL && c.bbox.y2 <= l.bbox.y2 + SHADE_CLIP_TOL && c.colXs.every((x) => l.colXs.some((lx) => near2(lx, x))) && (clipGrids.reduce((s, o) => s + (_optionalChain([o, 'access', _31 => _31.cells, 'optionalAccess', _32 => _32.some, 'call', _33 => _33((cell) => cell.filler)]) ? o.cells.filter((cell) => !cell.filler).reduce((a, cell) => a + inter(cell.bbox, l.bbox), 0) : inter(o.bbox, l.bbox)), 0) <= area(l.bbox) * SHADE_CLIP_MAX_AREA || l.rowYs.length === c.rowYs.length + 1 && c.rowYs.every((y, i) => near2(y, l.rowYs[i])) && l.colXs.length === c.colXs.length && c.colXs.every((x, i) => near2(x, l.colXs[i])) && !clipGrids.some((o) => o !== c && inter(o.bbox, l.bbox) > 0) || hasShadedRowBands(l, clipGrids, fillRects, verticals, horizontals))
1235
2002
  ));
1236
2003
  return !host;
1237
2004
  });
@@ -1246,7 +2013,17 @@ function dropHeadBandClipGrids(clipGrids, lineGrids) {
1246
2013
  if (clipGrids.length === 0 || lineGrids.length === 0) return clipGrids;
1247
2014
  const near2 = (a, b) => Math.abs(a - b) <= SHADE_CLIP_TOL;
1248
2015
  const overlaps = (a, b) => Math.min(a.x2, b.x2) > Math.max(a.x1, b.x1) && Math.min(a.y2, b.y2) > Math.max(a.y1, b.y1);
1249
- return clipGrids.filter((c) => c.clipParent || !_optionalChain([c, 'access', _29 => _29.cells, 'optionalAccess', _30 => _30.length]) || !lineGrids.some((l) => l.rowYs.length > c.rowYs.length && l.colXs.length === c.colXs.length && c.colXs.every((x, k) => near2(x, l.colXs[k])) && c.rowYs.every((y, k) => near2(y, l.rowYs[k])) && !clipGrids.some((o) => o !== c && overlaps(o.bbox, l.bbox))));
2016
+ const kept = clipGrids.filter((c) => c.clipParent || !_optionalChain([c, 'access', _34 => _34.cells, 'optionalAccess', _35 => _35.length]) || !lineGrids.some((l) => l.rowYs.length > c.rowYs.length && l.colXs.length === c.colXs.length && c.colXs.every((x, k) => near2(x, l.colXs[k])) && c.rowYs.every((y, k) => near2(y, l.rowYs[k])) && !clipGrids.some((o) => o !== c && overlaps(o.bbox, l.bbox))));
2017
+ return kept.filter((c) => !lineGrids.some((l) => headBandTiles(kept, l, near2, overlaps).includes(c)));
2018
+ }
2019
+ function headBandTiles(clips, l, near2, overlaps) {
2020
+ const onRow = (y) => l.rowYs.some((r) => near2(r, y));
2021
+ const band = clips.filter((c) => !c.clipParent && _optionalChain([c, 'access', _36 => _36.cells, 'optionalAccess', _37 => _37.length]) && near2(c.bbox.y2, l.bbox.y2) && c.bbox.y1 > l.bbox.y1 + SHADE_CLIP_TOL && c.bbox.x1 >= l.bbox.x1 - SHADE_CLIP_TOL && c.bbox.x2 <= l.bbox.x2 + SHADE_CLIP_TOL && c.rowYs.every(onRow)).sort((a, b) => a.bbox.x1 - b.bbox.x1);
2022
+ if (band.length < 2 || !near2(band[0].bbox.x1, l.bbox.x1) || !near2(band[band.length - 1].bbox.x2, l.bbox.x2)) return [];
2023
+ if (band.some((c, k) => k > 0 && c.bbox.x1 > band[k - 1].bbox.x2 + SHADE_CLIP_TOL)) return [];
2024
+ const bottom = Math.min(...band.map((c) => c.bbox.y1));
2025
+ const body = { ...l.bbox, y2: bottom };
2026
+ return clips.some((o) => !band.includes(o) && overlaps(o.bbox, body)) ? [] : band;
1250
2027
  }
1251
2028
  function enforceMinWidth(colXs, minWidth, narrowRuns = true) {
1252
2029
  if (colXs.length <= 2) return colXs;
@@ -1597,7 +2374,7 @@ function buildClipCellGrids(rects, strokedH, strokedV, pageWidth, pageHeight, te
1597
2374
  for (let dx = -1; dx <= 1 && !duplicate; dx++) {
1598
2375
  const ys2 = buckets.get(bx + dx);
1599
2376
  for (let dy = -1; dy <= 1 && !duplicate; dy++) {
1600
- duplicate = _nullishCoalesce(_optionalChain([ys2, 'optionalAccess', _31 => _31.get, 'call', _32 => _32(by + dy), 'optionalAccess', _33 => _33.some, 'call', _34 => _34((c) => sameRect(c, r))]), () => ( false));
2377
+ duplicate = _nullishCoalesce(_optionalChain([ys2, 'optionalAccess', _38 => _38.get, 'call', _39 => _39(by + dy), 'optionalAccess', _40 => _40.some, 'call', _41 => _41((c) => sameRect(c, r))]), () => ( false));
1601
2378
  }
1602
2379
  }
1603
2380
  if (duplicate) continue;
@@ -1745,7 +2522,7 @@ function buildClipCellGrids(rects, strokedH, strokedV, pageWidth, pageHeight, te
1745
2522
  else groups.set(r, [i]);
1746
2523
  }
1747
2524
  const containers = cells.filter((_, i) => isContainer[i]);
1748
- const groupSize = (i) => _nullishCoalesce(_optionalChain([groups, 'access', _35 => _35.get, 'call', _36 => _36(find(i)), 'optionalAccess', _37 => _37.length]), () => ( 0));
2525
+ const groupSize = (i) => _nullishCoalesce(_optionalChain([groups, 'access', _42 => _42.get, 'call', _43 => _43(find(i)), 'optionalAccess', _44 => _44.length]), () => ( 0));
1749
2526
  const isGridMember = (i) => groupSize(i) >= CLIP_MIN_GROUP;
1750
2527
  const framed = (r) => edgeStroked(strokedH, "h", r.y1, r.x1, r.x2) && edgeStroked(strokedH, "h", r.y2, r.x1, r.x2) && edgeStroked(strokedV, "v", r.x1, r.y1, r.y2) && edgeStroked(strokedV, "v", r.x2, r.y1, r.y2);
1751
2528
  const titledFrame = (r) => r.y1 >= pageHeight * TITLED_FRAME_MIN_TOP && r.x2 - r.x1 >= pageWidth * TITLED_FRAME_MIN_WIDTH && textPoints.some((p) => p.y < r.y1 && p.y > pageHeight * HEADER_BAND && p.x >= r.x1 - CLIP_EDGE_TOL && p.x <= r.x2 + CLIP_EDGE_TOL) && textPoints.some((p) => p.x > r.x1 && p.x < r.x2 && p.y > r.y1 && p.y < r.y2);
@@ -2126,8 +2903,8 @@ function childRules(r, grid) {
2126
2903
  }
2127
2904
  function recordClipCellEdges(grids, horizontals, verticals, nonRules) {
2128
2905
  if (!grids.some((g) => g.cells)) return;
2129
- const h = rules(_optionalChain([nonRules, 'optionalAccess', _38 => _38.size]) ? horizontals.filter((l) => !nonRules.has(l)) : horizontals, "h");
2130
- const v = rules(_optionalChain([nonRules, 'optionalAccess', _39 => _39.size]) ? verticals.filter((l) => !nonRules.has(l)) : verticals, "v");
2906
+ const h = rules(_optionalChain([nonRules, 'optionalAccess', _45 => _45.size]) ? horizontals.filter((l) => !nonRules.has(l)) : horizontals, "h");
2907
+ const v = rules(_optionalChain([nonRules, 'optionalAccess', _46 => _46.size]) ? verticals.filter((l) => !nonRules.has(l)) : verticals, "v");
2131
2908
  for (const g of grids) {
2132
2909
  if (!g.cells) continue;
2133
2910
  const ownH = childRules(h, g), ownV = childRules(v, g);
@@ -2143,9 +2920,9 @@ function recordOpenEndCellEdges(grid, cells, horizontals) {
2143
2920
  const end = horizontals.find((l) => OPEN_END_RULES.has(l) && Math.abs(l.y1 - b.y1) <= EDGE_NEAR2 && Math.abs(l.x1 - b.x1) <= EDGE_NEAR2 && Math.abs(l.x2 - b.x2) <= EDGE_NEAR2);
2144
2921
  const raw = end && OPEN_END_RULES.get(end);
2145
2922
  if (!raw) return;
2146
- const hs = raw.horizontals.filter((l) => !_optionalChain([raw, 'access', _40 => _40.nonRules, 'optionalAccess', _41 => _41.has, 'call', _42 => _42(l)]));
2923
+ const hs = raw.horizontals.filter((l) => !_optionalChain([raw, 'access', _47 => _47.nonRules, 'optionalAccess', _48 => _48.has, 'call', _49 => _49(l)]));
2147
2924
  if (hs.some((l) => Math.abs(l.y1 - b.y1) <= EDGE_NEAR2 && Math.min(l.x2, b.x2) - Math.max(l.x1, b.x1) > TIP_MAX)) return;
2148
- const h = rules(hs, "h"), v = rules(raw.verticals.filter((l) => !_optionalChain([raw, 'access', _43 => _43.nonRules, 'optionalAccess', _44 => _44.has, 'call', _45 => _45(l)])), "v");
2925
+ const h = rules(hs, "h"), v = rules(raw.verticals.filter((l) => !_optionalChain([raw, 'access', _50 => _50.nonRules, 'optionalAccess', _51 => _51.has, 'call', _52 => _52(l)])), "v");
2149
2926
  const edges = cells.map((c) => edgesOf(c.bbox, h, v));
2150
2927
  const last = grid.rowYs.length - 2;
2151
2928
  if (!cells.every((c, i) => {
@@ -2156,16 +2933,16 @@ function recordOpenEndCellEdges(grid, cells, horizontals) {
2156
2933
  }
2157
2934
  function takeClipCellEdges(from, to) {
2158
2935
  const e = CLIP_CELL_EDGES.get(from);
2159
- if (e) _chunkAM5ALISVcjs.CELL_EDGES.set(to, e);
2936
+ if (e) _chunkNW2CKOFLcjs.CELL_EDGES.set(to, e);
2160
2937
  }
2161
2938
  function hasOpenCellSeam(a, b) {
2162
- const u = _chunkAM5ALISVcjs.CELL_EDGES.get(a), d = _chunkAM5ALISVcjs.CELL_EDGES.get(b);
2939
+ const u = _chunkNW2CKOFLcjs.CELL_EDGES.get(a), d = _chunkNW2CKOFLcjs.CELL_EDGES.get(b);
2163
2940
  return !!u && !!d && u.t && !u.b && !d.t && d.b && u.l && u.r && d.l && d.r;
2164
2941
  }
2165
2942
  function joinCellEdges(a, b) {
2166
- const u = _chunkAM5ALISVcjs.CELL_EDGES.get(a), d = _chunkAM5ALISVcjs.CELL_EDGES.get(b);
2943
+ const u = _chunkNW2CKOFLcjs.CELL_EDGES.get(a), d = _chunkNW2CKOFLcjs.CELL_EDGES.get(b);
2167
2944
  if (!u || !d) return;
2168
- _chunkAM5ALISVcjs.CELL_EDGES.set(a, { t: u.t, b: d.b, l: u.l || d.l, r: u.r || d.r });
2945
+ _chunkNW2CKOFLcjs.CELL_EDGES.set(a, { t: u.t, b: d.b, l: u.l || d.l, r: u.r || d.r });
2169
2946
  }
2170
2947
 
2171
2948
  // src/pdf/cell-extract.ts
@@ -2341,7 +3118,7 @@ function tagScripts(text, lines) {
2341
3118
  const [s, e, kind] = marks[m];
2342
3119
  out = out.slice(0, s) + `<${kind}>` + out.slice(s, e) + `</${kind}>` + out.slice(e);
2343
3120
  }
2344
- return _chunkAM5ALISVcjs.tidyScriptTags.call(void 0, out);
3121
+ return _chunkNW2CKOFLcjs.tidyScriptTags.call(void 0, out);
2345
3122
  }
2346
3123
 
2347
3124
  // src/pdf/line-wrap.ts
@@ -2377,12 +3154,12 @@ var WrapLexicon = (_class = class {constructor() { _class.prototype.__init.call(
2377
3154
  const t = toks[i], n = t.length;
2378
3155
  if (i > 0 && i < toks.length - 1) {
2379
3156
  bump(this.words, t);
2380
- const run = _nullishCoalesce(_optionalChain([t, 'access', _46 => _46.match, 'call', _47 => _47(/^[가-힣]+/), 'optionalAccess', _48 => _48[0]]), () => ( ""));
3157
+ const run = _nullishCoalesce(_optionalChain([t, 'access', _53 => _53.match, 'call', _54 => _54(/^[가-힣]+/), 'optionalAccess', _55 => _55[0]]), () => ( ""));
2381
3158
  for (let j = 2; j <= Math.min(run.length, 6); j++) this.heads.add(run.slice(0, j));
2382
3159
  }
2383
3160
  if (i + 1 < toks.length) {
2384
3161
  this.pairs.add(t + " " + toks[i + 1]);
2385
- const tail = _optionalChain([t, 'access', _49 => _49.match, 'call', _50 => _50(/[가-힣]+$/), 'optionalAccess', _51 => _51[0]]);
3162
+ const tail = _optionalChain([t, 'access', _56 => _56.match, 'call', _57 => _57(/[가-힣]+$/), 'optionalAccess', _58 => _58[0]]);
2386
3163
  if (tail) this.spacedHeads.add(tail + " " + toks[i + 1].charAt(0));
2387
3164
  }
2388
3165
  for (let a = 0; a + 1 < n; a++) {
@@ -2419,14 +3196,14 @@ var WrapLexicon = (_class = class {constructor() { _class.prototype.__init.call(
2419
3196
  const n = left.length;
2420
3197
  if (n < 2 || right.length < 2) return null;
2421
3198
  const k1 = pairKey(left.charCodeAt(n - 2), left.charCodeAt(n - 1)), k2 = pairKey(right.charCodeAt(0), right.charCodeAt(1));
2422
- return decideCounts(_nullishCoalesce(_optionalChain([this, 'access', _52 => _52.joined2, 'access', _53 => _53.get, 'call', _54 => _54(k1), 'optionalAccess', _55 => _55.get, 'call', _56 => _56(k2)]), () => ( 0)), _nullishCoalesce(_optionalChain([this, 'access', _57 => _57.spaced2, 'access', _58 => _58.get, 'call', _59 => _59(k1), 'optionalAccess', _60 => _60.get, 'call', _61 => _61(k2)]), () => ( 0)));
3199
+ return decideCounts(_nullishCoalesce(_optionalChain([this, 'access', _59 => _59.joined2, 'access', _60 => _60.get, 'call', _61 => _61(k1), 'optionalAccess', _62 => _62.get, 'call', _63 => _63(k2)]), () => ( 0)), _nullishCoalesce(_optionalChain([this, 'access', _64 => _64.spaced2, 'access', _65 => _65.get, 'call', _66 => _66(k1), 'optionalAccess', _67 => _67.get, 'call', _68 => _68(k2)]), () => ( 0)));
2423
3200
  }
2424
3201
  /** 꺾인 자리 증거: "" 붙음 · " " 띄움 · null 모름 (두 글자 증거가 갈리거나 없으면 한 글자) */
2425
3202
  evidence(left, right) {
2426
3203
  const n = left.length;
2427
3204
  if (n >= 2 && right.length >= 2) {
2428
3205
  const k1 = pairKey(left.charCodeAt(n - 2), left.charCodeAt(n - 1)), k2 = pairKey(right.charCodeAt(0), right.charCodeAt(1));
2429
- const v = decideCounts(_nullishCoalesce(_optionalChain([this, 'access', _62 => _62.joined2, 'access', _63 => _63.get, 'call', _64 => _64(k1), 'optionalAccess', _65 => _65.get, 'call', _66 => _66(k2)]), () => ( 0)), _nullishCoalesce(_optionalChain([this, 'access', _67 => _67.spaced2, 'access', _68 => _68.get, 'call', _69 => _69(k1), 'optionalAccess', _70 => _70.get, 'call', _71 => _71(k2)]), () => ( 0)));
3206
+ const v = decideCounts(_nullishCoalesce(_optionalChain([this, 'access', _69 => _69.joined2, 'access', _70 => _70.get, 'call', _71 => _71(k1), 'optionalAccess', _72 => _72.get, 'call', _73 => _73(k2)]), () => ( 0)), _nullishCoalesce(_optionalChain([this, 'access', _74 => _74.spaced2, 'access', _75 => _75.get, 'call', _76 => _76(k1), 'optionalAccess', _77 => _77.get, 'call', _78 => _78(k2)]), () => ( 0)));
2430
3207
  if (v !== null) return v;
2431
3208
  }
2432
3209
  if (n && right.length) {
@@ -2501,11 +3278,11 @@ function wrapJoiner(prevText, nextText, lex, heads = true) {
2501
3278
  if (particleContinues(left, right)) return "";
2502
3279
  if (endsAsWord(left)) return " ";
2503
3280
  if (/[A-Za-z]-$/.test(left) && /^[A-Za-z]/.test(right) && !/[가-힣]/.test(prev + next)) {
2504
- return _optionalChain([lex, 'optionalAccess', _72 => _72.joinedWord, 'call', _73 => _73(left, right.replace(/[.,;:!?)]*$/, ""))]) ? "" : " ";
3281
+ return _optionalChain([lex, 'optionalAccess', _79 => _79.joinedWord, 'call', _80 => _80(left, right.replace(/[.,;:!?)]*$/, ""))]) ? "" : " ";
2505
3282
  }
2506
3283
  if (/[·ㆍ‧-]/.test(a) && !/[·ㆍ‧…]{2}$/.test(prev) && /[가-힣A-Za-z0-9]/.test(b)) return "";
2507
3284
  if (/[A-Za-z]/.test(a) && /[A-Za-z]/.test(b) || /\d/.test(a) && /\d/.test(b)) return " ";
2508
- const ev = _optionalChain([lex, 'optionalAccess', _74 => _74.evidence, 'call', _75 => _75(left, right)]);
3285
+ const ev = _optionalChain([lex, 'optionalAccess', _81 => _81.evidence, 'call', _82 => _82(left, right)]);
2509
3286
  if (ev != null) return ev;
2510
3287
  if (lex && /[가-힣A-Za-z0-9]$/.test(left) && /^[가-힣A-Za-z0-9]/.test(right) && lex.joinedWord(left, right.replace(/[.,)」』’”;:]+$/, ""))) return "";
2511
3288
  if (/\d$/.test(left) && COUNTER.test(right)) return "";
@@ -2513,7 +3290,7 @@ function wrapJoiner(prevText, nextText, lex, heads = true) {
2513
3290
  const r1 = right.replace(/[.,)」』’”]+$/, "");
2514
3291
  if (lex && /[가-힣]$/.test(left) && /^[가-힣]$/.test(r1) && !STANDALONE_SYLLABLE.test(r1) && !lex.isWord(r1) && !lex.isWord(right)) return "";
2515
3292
  if (lex && heads) {
2516
- const tail = _optionalChain([left, 'access', _76 => _76.match, 'call', _77 => _77(/[가-힣]+$/), 'optionalAccess', _78 => _78[0]]), run = _optionalChain([right, 'access', _79 => _79.match, 'call', _80 => _80(/^[가-힣]+/), 'optionalAccess', _81 => _81[0]]);
3293
+ const tail = _optionalChain([left, 'access', _83 => _83.match, 'call', _84 => _84(/[가-힣]+$/), 'optionalAccess', _85 => _85[0]]), run = _optionalChain([right, 'access', _86 => _86.match, 'call', _87 => _87(/^[가-힣]+/), 'optionalAccess', _88 => _88[0]]);
2517
3294
  if (tail && run && !STANDALONE_SYLLABLE.test(tail) && lex.startsWord(tail + run.slice(0, 2)) && !lex.spacedHead(tail, run[0])) return "";
2518
3295
  if (/[가-힣]{2}$/.test(left) && /^\([^()\s]*\)/.test(right) && !endsAsWord(left) && !/(?:함|음|됨|임|다)$/.test(left) && !BARE_UNIT_PAREN.test(right) && !/^\(\d/.test(right)) return "";
2519
3296
  }
@@ -2548,14 +3325,14 @@ function joinPageBreakWraps(blocks, lex) {
2548
3325
  if (a.type !== "paragraph" && a.type !== "list" || b.type !== "paragraph") continue;
2549
3326
  const last = a.bbox && PARA_LAST_LINE.get(a.bbox), fs = last ? last.fontSize : 0;
2550
3327
  if (!last || fs <= 0 || (_nullishCoalesce(pageRight.get(a.pageNumber), () => ( Infinity))) - last.right >= BODY_FULL_TOL * fs) continue;
2551
- if (last.width < BODY_MIN_WIDTH_EM * fs || Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _82 => _82.style, 'optionalAccess', _83 => _83.fontSize]), () => ( 0))) - fs) > 0.15 * fs) continue;
3328
+ if (last.width < BODY_MIN_WIDTH_EM * fs || Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _89 => _89.style, 'optionalAccess', _90 => _90.fontSize]), () => ( 0))) - fs) > 0.15 * fs) continue;
2552
3329
  const bt = b.text.replace(MARKUP, "");
2553
3330
  if (startsNewItem(a.text, b.text) || PAGE_REF_TAIL.test(a.text) || PAGE_ITEM_HEAD.test(bt)) continue;
2554
3331
  if (PAGE_HEAD_MARK.test(bt) && !(/^[\u25a0-\u25ff]/.test(bt) && a.text.includes(bt[0]))) continue;
2555
3332
  const firstLeft = b.bbox && PARA_FIRST_LEFT.get(b.bbox);
2556
3333
  const indented = firstLeft === void 0 || firstLeft - (_nullishCoalesce(pageLeft.get(b.pageNumber), () => ( firstLeft))) >= 0.3 * fs;
2557
3334
  if (indented && SENTENCE_END.test(a.text.replace(MARKUP, "").trimEnd())) continue;
2558
- if (Math.round(_nullishCoalesce(_optionalChain([b, 'access', _84 => _84.style, 'optionalAccess', _85 => _85.fontSize]), () => ( 0))) !== Math.round(fs) && titleLike(b.text)) continue;
3335
+ if (Math.round(_nullishCoalesce(_optionalChain([b, 'access', _91 => _91.style, 'optionalAccess', _92 => _92.fontSize]), () => ( 0))) !== Math.round(fs) && titleLike(b.text)) continue;
2559
3336
  if (/\t/.test(a.text.slice(a.text.lastIndexOf("\n") + 1).replace(/^\S{1,8}\t/, "")) && titleLike(bt.trim().split("\n")[0])) continue;
2560
3337
  const joined = wrapJoiner(a.text, b.text, lex);
2561
3338
  const head = a.text, joiner = joined === "" && last.spaceAfter ? " " : joined;
@@ -2604,7 +3381,7 @@ function bodyLineJoins(lines, lex) {
2604
3381
  for (const l of lines) if (!HANGING.test(l.text) && l.right > inner) inner = l.right;
2605
3382
  const full = (l) => right - l.right < BODY_FULL_TOL * l.fontSize || right - inner <= 1.2 * l.fontSize && inner - l.right < BODY_FULL_TOL * l.fontSize;
2606
3383
  const nextWordNoRoom = (a, b) => {
2607
- const w = _optionalChain([b, 'access', _86 => _86.text, 'access', _87 => _87.trim, 'call', _88 => _88(), 'access', _89 => _89.match, 'call', _90 => _90(/^\S+/), 'optionalAccess', _91 => _91[0]]);
3384
+ const w = _optionalChain([b, 'access', _93 => _93.text, 'access', _94 => _94.trim, 'call', _95 => _95(), 'access', _96 => _96.match, 'call', _97 => _97(/^\S+/), 'optionalAccess', _98 => _98[0]]);
2608
3385
  const n = [...b.text.trim()].length;
2609
3386
  if (!w || n === 0) return false;
2610
3387
  const em = (b.right - b.left) / n;
@@ -2800,7 +3577,7 @@ function cellTextToString(items, wrap) {
2800
3577
  const merged = mergeSuperscriptRows(lines).map((line) => sortLineByX(line));
2801
3578
  const textLines = merged.map((s) => {
2802
3579
  if (s.length === 1) return s[0].text;
2803
- if (s.length === 2 && /^[가-힣]$/.test(s[0].text) && /^[가-힣]$/.test(s[1].text) && !!_optionalChain([wrap, 'optionalAccess', _92 => _92.lex]) && (wrap.lex.isWord(s[0].text + s[1].text) || wrap.lex.evidence(s[0].text, s[1].text) === "" || REGION_LABELS.has(s[0].text + s[1].text)) && s[1].x - (s[0].x + s[0].w) >= Math.max(s[0].fontSize, s[1].fontSize) * 1.5 && s[1].x + s[1].w - s[0].x >= wrap.box.x2 - wrap.box.x1 - Math.max(s[0].fontSize, s[1].fontSize) * 2) return s[0].text + s[1].text;
3580
+ if (s.length === 2 && /^[가-힣]$/.test(s[0].text) && /^[가-힣]$/.test(s[1].text) && !!_optionalChain([wrap, 'optionalAccess', _99 => _99.lex]) && (wrap.lex.isWord(s[0].text + s[1].text) || wrap.lex.evidence(s[0].text, s[1].text) === "" || REGION_LABELS.has(s[0].text + s[1].text)) && s[1].x - (s[0].x + s[0].w) >= Math.max(s[0].fontSize, s[1].fontSize) * 1.5 && s[1].x + s[1].w - s[0].x >= wrap.box.x2 - wrap.box.x1 - Math.max(s[0].fontSize, s[1].fontSize) * 2) return s[0].text + s[1].text;
2804
3581
  const evenSpaced = detectEvenSpacedItems(s, true);
2805
3582
  let result = s[0].text;
2806
3583
  for (let j = 1; j < s.length; j++) {
@@ -2946,12 +3723,12 @@ function markEvenRun(items, visible, result, start, end) {
2946
3723
  }
2947
3724
  function mergeCellTextLines(textLines, wrap) {
2948
3725
  if (textLines.length <= 1) return textLines[0] || "";
2949
- const numberWrapped = (k) => !!_optionalChain([wrap, 'optionalAccess', _93 => _93.wraps, 'access', _94 => _94[k]]) && (_nullishCoalesce(_optionalChain([wrap, 'access', _95 => _95.wide, 'optionalAccess', _96 => _96[k]]), () => ( true)));
3726
+ const numberWrapped = (k) => !!_optionalChain([wrap, 'optionalAccess', _100 => _100.wraps, 'access', _101 => _101[k]]) && (_nullishCoalesce(_optionalChain([wrap, 'access', _102 => _102.wide, 'optionalAccess', _103 => _103[k]]), () => ( true)));
2950
3727
  const merged = [textLines[0]];
2951
3728
  for (let i = 1; i < textLines.length; i++) {
2952
3729
  const prev = merged[merged.length - 1];
2953
3730
  const curr = textLines[i];
2954
- if (wrap ? wrap.wraps[i - 1] && !_optionalChain([wrap, 'access', _97 => _97.spaced, 'optionalAccess', _98 => _98[i - 1]]) && !startsNewItem(prev, curr) && wrapJoiner(prev, curr, wrap.lex, false) === "" : /[가-힣]$/.test(prev) && /^[가-힣]+$/.test(curr) && curr.length <= 8 && !curr.includes(" ")) {
3731
+ if (wrap ? wrap.wraps[i - 1] && !_optionalChain([wrap, 'access', _104 => _104.spaced, 'optionalAccess', _105 => _105[i - 1]]) && !startsNewItem(prev, curr) && wrapJoiner(prev, curr, wrap.lex, false) === "" : /[가-힣]$/.test(prev) && /^[가-힣]+$/.test(curr) && curr.length <= 8 && !curr.includes(" ")) {
2955
3732
  merged[merged.length - 1] = prev + curr;
2956
3733
  } else if (curr.trim().length <= 3 && /^[)\]%}]/.test(curr.trim())) {
2957
3734
  merged[merged.length - 1] = prev + curr.trim();
@@ -3046,7 +3823,7 @@ function normalizeUndersegmentedTable(originalCells, colXs, items, rowYs) {
3046
3823
  if (numRows > MAX_UNDERSEGMENTED_ROWS || numCols < MIN_UNDERSEGMENTED_COLUMNS) return null;
3047
3824
  if (items.length === 0) return null;
3048
3825
  if (numRows >= 3) {
3049
- if (_optionalChain([rowYs, 'optionalAccess', _99 => _99.length]) !== numRows + 1) return null;
3826
+ if (_optionalChain([rowYs, 'optionalAccess', _106 => _106.length]) !== numRows + 1) return null;
3050
3827
  const rebuilt2 = [];
3051
3828
  let expanded = 0;
3052
3829
  for (let r = 0; r < numRows; r++) {
@@ -3140,7 +3917,7 @@ function sortLineByX(items) {
3140
3917
  e++;
3141
3918
  }
3142
3919
  const run = items.slice(s, e), seqs = run.map((i) => i.seq);
3143
- const ok = !wide ? !run.some((i) => _optionalChain([i, 'access', _100 => _100.text, 'optionalAccess', _101 => _101.startsWith, 'call', _102 => _102("$")])) : Math.max(...seqs) - Math.min(...seqs) <= 2 * (e - s - 1) && run.every((i) => Math.abs((_nullishCoalesce(i.fontSize, () => ( 0))) - (_nullishCoalesce(run[0].fontSize, () => ( 0)))) <= 0.5);
3920
+ const ok = !wide ? !run.some((i) => _optionalChain([i, 'access', _107 => _107.text, 'optionalAccess', _108 => _108.startsWith, 'call', _109 => _109("$")])) : Math.max(...seqs) - Math.min(...seqs) <= 2 * (e - s - 1) && run.every((i) => Math.abs((_nullishCoalesce(i.fontSize, () => ( 0))) - (_nullishCoalesce(run[0].fontSize, () => ( 0)))) <= 0.5);
3144
3921
  if (e - s > 1 && seqs.every((q) => q !== void 0) && ok) {
3145
3922
  run.sort((a, b) => a.seq - b.seq);
3146
3923
  for (let k = 0; k < run.length; k++) items[s + k] = run[k];
@@ -3209,7 +3986,7 @@ function dominantStyle(items) {
3209
3986
  let maxCount = 0, dominantSize = 0;
3210
3987
  for (const i of items) {
3211
3988
  if (i.fontSize <= 0) continue;
3212
- const count = (freq.get(i.fontSize) || 0) + Math.max(1, _nullishCoalesce(_optionalChain([i, 'access', _103 => _103.text, 'access', _104 => _104.match, 'call', _105 => _105(/[\p{L}\p{N}]/gu), 'optionalAccess', _106 => _106.length]), () => ( 0)));
3989
+ const count = (freq.get(i.fontSize) || 0) + Math.max(1, _nullishCoalesce(_optionalChain([i, 'access', _110 => _110.text, 'access', _111 => _111.match, 'call', _112 => _112(/[\p{L}\p{N}]/gu), 'optionalAccess', _113 => _113.length]), () => ( 0)));
3213
3990
  freq.set(i.fontSize, count);
3214
3991
  if (count > maxCount) {
3215
3992
  maxCount = count;
@@ -3217,7 +3994,7 @@ function dominantStyle(items) {
3217
3994
  }
3218
3995
  }
3219
3996
  if (dominantSize === 0) return void 0;
3220
- const fontName = _optionalChain([items, 'access', _107 => _107.find, 'call', _108 => _108((i) => i.fontSize === dominantSize), 'optionalAccess', _109 => _109.fontName]) || void 0;
3997
+ const fontName = _optionalChain([items, 'access', _114 => _114.find, 'call', _115 => _115((i) => i.fontSize === dominantSize), 'optionalAccess', _116 => _116.fontName]) || void 0;
3221
3998
  return fontName ? { fontSize: dominantSize, fontName } : { fontSize: dominantSize };
3222
3999
  }
3223
4000
  function normalizeItems(rawItems) {
@@ -3362,7 +4139,7 @@ function splitAroundOverlays(c, overlays) {
3362
4139
  const ov = overlays.filter((o) => {
3363
4140
  for (let at = c.text.indexOf(o.text); at >= 0; at = c.text.indexOf(o.text, at + 1)) {
3364
4141
  const prefix = c.text.slice(0, at);
3365
- const est = c.x + glyphUnits(prefix.replace(/\s+/g, "")) * a0 + (_nullishCoalesce(_optionalChain([prefix, 'access', _110 => _110.match, 'call', _111 => _111(/\s+/g), 'optionalAccess', _112 => _112.length]), () => ( 0))) * ws;
4142
+ const est = c.x + glyphUnits(prefix.replace(/\s+/g, "")) * a0 + (_nullishCoalesce(_optionalChain([prefix, 'access', _117 => _117.match, 'call', _118 => _118(/\s+/g), 'optionalAccess', _119 => _119.length]), () => ( 0))) * ws;
3366
4143
  if (Math.abs(est - o.x) <= OVERLAY_DUP_EM * fs) return false;
3367
4144
  }
3368
4145
  return true;
@@ -3487,7 +4264,7 @@ function mergeSuperscriptLines(lines) {
3487
4264
  return result;
3488
4265
  }
3489
4266
  function mergeLineSimple(items) {
3490
- if (items.length <= 1) return _optionalChain([items, 'access', _113 => _113[0], 'optionalAccess', _114 => _114.text]) || "";
4267
+ if (items.length <= 1) return _optionalChain([items, 'access', _120 => _120[0], 'optionalAccess', _121 => _121.text]) || "";
3491
4268
  const sorted = sortLineByX([...items]);
3492
4269
  const isEvenSpaced = detectEvenSpacedItems(sorted);
3493
4270
  let result = sorted[0].text;
@@ -3575,7 +4352,7 @@ function isProseTable(table) {
3575
4352
  if (!(long > 0 && long >= total * 0.5 && longRows >= rows * 0.4)) return false;
3576
4353
  for (let c = 0; c < table.cols; c++) {
3577
4354
  const filled = table.cells.map((row) => row[c]).filter((cell) => cell && cell.colSpan < table.cols && cell.text.trim()).map((cell) => cell.text.trim());
3578
- if (filled.length >= 3 && filled.length >= rows * 0.6 && filled.every((text) => text.length <= 30 && (_nullishCoalesce(_optionalChain([text, 'access', _115 => _115.match, 'call', _116 => _116(/\p{L}/gu), 'optionalAccess', _117 => _117.length]), () => ( 0))) >= 2)) return false;
4355
+ if (filled.length >= 3 && filled.length >= rows * 0.6 && filled.every((text) => text.length <= 30 && (_nullishCoalesce(_optionalChain([text, 'access', _122 => _122.match, 'call', _123 => _123(/\p{L}/gu), 'optionalAccess', _124 => _124.length]), () => ( 0))) >= 2)) return false;
3579
4356
  }
3580
4357
  return true;
3581
4358
  }
@@ -3604,7 +4381,7 @@ var TICK = /^-?[\d,]+(?:\.\d+)?%?$/;
3604
4381
  var QUANTITY = /^[-−–]?[\d,]*\.?\d+%?$/;
3605
4382
  var quantity = (token) => Number(token.replace(/^[−–]/, "-").replace(/[,%]/g, ""));
3606
4383
  function isValueAxisColumn(table, c) {
3607
- const lines = table.cells.flatMap((row) => (_nullishCoalesce(_optionalChain([row, 'access', _118 => _118[c], 'optionalAccess', _119 => _119.text]), () => ( ""))).split("\n").map((line) => line.trim().split(/\s+/)));
4384
+ const lines = table.cells.flatMap((row) => (_nullishCoalesce(_optionalChain([row, 'access', _125 => _125[c], 'optionalAccess', _126 => _126.text]), () => ( ""))).split("\n").map((line) => line.trim().split(/\s+/)));
3608
4385
  const others = table.cells.flatMap((row) => row.filter((_, k) => k !== c).map((cell) => cell.text.trim().split(/\s+/))).filter((tokens) => tokens.every((token) => QUANTITY.test(token))).flat().map(quantity).filter((v) => !(Number.isInteger(v) && v >= 1900 && v <= 2100));
3609
4386
  for (const ticks of [lines.flat().filter((t) => TICK.test(t)).map(quantity), lines.map((tokens) => tokens[0]).filter((t) => TICK.test(t)).map(quantity)]) {
3610
4387
  const run = fallingRun(ticks);
@@ -3636,7 +4413,7 @@ function isChartTable(table, ocr = false) {
3636
4413
  const numeric = texts.filter((text) => NUMERIC_CELL.test(text)).length;
3637
4414
  if (numeric < texts.length * 0.5) return false;
3638
4415
  for (let c = 0; c < table.cols; c++) {
3639
- if (!ocr ? isValueAxisColumn(table, c) : hasValueAxis(table.cells.flatMap((row) => (_nullishCoalesce(_optionalChain([row, 'access', _120 => _120[c], 'optionalAccess', _121 => _121.text]), () => ( ""))).split(/\s+/)).filter((t) => TICK.test(t)).map((t) => Number(t.replace(/[,%]/g, ""))))) return true;
4416
+ if (!ocr ? isValueAxisColumn(table, c) : hasValueAxis(table.cells.flatMap((row) => (_nullishCoalesce(_optionalChain([row, 'access', _127 => _127[c], 'optionalAccess', _128 => _128.text]), () => ( ""))).split(/\s+/)).filter((t) => TICK.test(t)).map((t) => Number(t.replace(/[,%]/g, ""))))) return true;
3640
4417
  }
3641
4418
  const values = texts.filter((text) => text.split(/\s+/).every((token) => QUANTITY.test(token))).length;
3642
4419
  const cells = table.rows * table.cols;
@@ -3689,7 +4466,7 @@ function clusterCellLines(items) {
3689
4466
  }
3690
4467
  var WRAP_INDENT_MAX = 3;
3691
4468
  function joinClusterCellLines(lines, box, lex) {
3692
- let out = _nullishCoalesce(_optionalChain([lines, 'access', _122 => _122[0], 'optionalAccess', _123 => _123.text]), () => ( ""));
4469
+ let out = _nullishCoalesce(_optionalChain([lines, 'access', _129 => _129[0], 'optionalAccess', _130 => _130.text]), () => ( ""));
3693
4470
  for (let i = 1; i < lines.length; i++) {
3694
4471
  const a = lines[i - 1], b = lines[i];
3695
4472
  const join2 = !a.spaceAfter && cellLineWraps(box, box.x1, a.right, a.fontSize, b.firstCharW) && a.left - box.x1 <= WRAP_INDENT_MAX * a.fontSize && b.left - box.x1 <= WRAP_INDENT_MAX * b.fontSize && /<\/u>$/.test(a.text) === /^<u>/.test(b.text) && !startsNewItem(out, b.text) && wrapJoiner(out, b.text, lex, false) === "";
@@ -3698,6 +4475,59 @@ function joinClusterCellLines(lines, box, lex) {
3698
4475
  return out;
3699
4476
  }
3700
4477
 
4478
+ // src/pdf/ocr-column-cuts.ts
4479
+ var OCR_NUMERIC_CELL = /^[+-]?\d+(?:[,.]\d+)*%?$/;
4480
+ var OCR_GROUPED_NUMBER = /^[+-]?\d{1,3}(?:\s+\d{3})+(?:[.,]\d+)?%?$/;
4481
+ function supportedOcrColumnCuts(rows) {
4482
+ const cuts = /* @__PURE__ */ new Map();
4483
+ for (const head of _nullishCoalesce(rows[0], () => ( []))) {
4484
+ if (head.items.length !== 1 || head.items[0].fontName !== "ocr") continue;
4485
+ const candidates = [];
4486
+ for (const gap of ocrTextGaps(head.items[0])) {
4487
+ const text = head.items[0].text;
4488
+ if (!/\p{L}/u.test(text.slice(0, gap.at)) || !/\p{L}/u.test(text.slice(gap.at))) continue;
4489
+ const intervals = [];
4490
+ for (const row of rows.slice(1)) {
4491
+ const cell = row.find((c) => c.col === head.col);
4492
+ if (!cell || cell.items.some((it) => it.fontName !== "ocr")) continue;
4493
+ let interval;
4494
+ if (cell.items.length === 1) {
4495
+ const it = cell.items[0];
4496
+ interval = ocrTextGaps(it).find((g) => isOcrNumericSplit(it.text, g.at));
4497
+ } else if (isOcrNumericPair(cell.items)) {
4498
+ const [a, b] = [...cell.items].sort((a2, b2) => a2.x - b2.x);
4499
+ interval = { left: a.x + a.w / 2, right: b.x + b.w / 2 };
4500
+ }
4501
+ if (interval) {
4502
+ const left = Math.max(gap.left, interval.left), right = Math.min(gap.right, interval.right);
4503
+ if (right > left) intervals.push({ left, right });
4504
+ }
4505
+ }
4506
+ const events = intervals.flatMap((i) => [{ x: i.left, delta: 1 }, { x: i.right, delta: -1 }]).sort((a, b) => a.x - b.x);
4507
+ let active = 0, bestCount = 1, bestWidth = 0, cut;
4508
+ for (let i = 0; i < events.length; ) {
4509
+ const x = events[i].x;
4510
+ while (i < events.length && events[i].x === x) active += events[i++].delta;
4511
+ const width = i < events.length ? events[i].x - x : 0;
4512
+ if (active >= 2 && width > 0 && (active > bestCount || active === bestCount && width > bestWidth)) {
4513
+ bestCount = active;
4514
+ bestWidth = width;
4515
+ cut = x + width / 2;
4516
+ }
4517
+ }
4518
+ if (cut !== void 0) candidates.push(cut);
4519
+ }
4520
+ if (candidates.length === 1) cuts.set(head.col, candidates[0]);
4521
+ }
4522
+ return cuts;
4523
+ }
4524
+ function isOcrNumericPair(items) {
4525
+ return items.length === 2 && items.every((it) => it.fontName === "ocr" && OCR_NUMERIC_CELL.test(it.text.trim())) && !OCR_GROUPED_NUMBER.test([...items].sort((a, b) => a.x - b.x).map((it) => it.text.trim()).join(" "));
4526
+ }
4527
+ function isOcrNumericSplit(text, at) {
4528
+ return !OCR_GROUPED_NUMBER.test(text.trim()) && /\s/.test((_nullishCoalesce(text[at - 1], () => ( ""))) + (_nullishCoalesce(text[at], () => ( "")))) && OCR_NUMERIC_CELL.test(text.slice(0, at).trim()) && OCR_NUMERIC_CELL.test(text.slice(at).trim());
4529
+ }
4530
+
3701
4531
  // src/pdf/cluster-detector.ts
3702
4532
  var Y_TOL = 3;
3703
4533
  var COL_CLUSTER_TOL = 15;
@@ -3908,7 +4738,7 @@ function detectAlignedTwoColumnTables(rows, pageNum) {
3908
4738
  continue;
3909
4739
  }
3910
4740
  const top = rows[i - 1];
3911
- const title = _optionalChain([top, 'optionalAccess', _124 => _124.items, 'access', _125 => _125.length]) === 1 && Math.abs(top.items[0].x - first[0].x) <= 5 && top.items[0].text.length <= 65 && top.y - first[0].y <= Math.max(24, first[0].fontSize * 2.8) ? top : void 0;
4741
+ const title = _optionalChain([top, 'optionalAccess', _131 => _131.items, 'access', _132 => _132.length]) === 1 && Math.abs(top.items[0].x - first[0].x) <= 5 && top.items[0].text.length <= 65 && top.y - first[0].y <= Math.max(24, first[0].fontSize * 2.8) ? top : void 0;
3912
4742
  const tableRows = title ? [title, ...body] : body;
3913
4743
  const cells = tableRows.map((row, idx) => {
3914
4744
  if (title && idx === 0) return [{ text: row.items[0].text, colSpan: 2, rowSpan: 1 }, { text: "", colSpan: 1, rowSpan: 1 }];
@@ -3964,12 +4794,12 @@ function isTwoColumnProse(r) {
3964
4794
  if (t.rows < 8) return false;
3965
4795
  const dense = [];
3966
4796
  for (let c = 0; c < t.cols; c++) {
3967
- const filled = t.cells.filter((row) => _optionalChain([row, 'access', _126 => _126[c], 'optionalAccess', _127 => _127.text, 'access', _128 => _128.trim, 'call', _129 => _129()])).length;
4797
+ const filled = t.cells.filter((row) => _optionalChain([row, 'access', _133 => _133[c], 'optionalAccess', _134 => _134.text, 'access', _135 => _135.trim, 'call', _136 => _136()])).length;
3968
4798
  if (filled / t.rows >= 0.3) dense.push(c);
3969
4799
  }
3970
4800
  if (dense.length !== 2) return false;
3971
4801
  for (const c of dense) {
3972
- const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access', _130 => _130[c], 'optionalAccess', _131 => _131.text, 'access', _132 => _132.replace, 'call', _133 => _133(/\s+/g, ""), 'access', _134 => _134.length]), () => ( 0))).filter((n) => n > 0);
4802
+ const lens = t.cells.map((row) => _nullishCoalesce(_optionalChain([row, 'access', _137 => _137[c], 'optionalAccess', _138 => _138.text, 'access', _139 => _139.replace, 'call', _140 => _140(/\s+/g, ""), 'access', _141 => _141.length]), () => ( 0))).filter((n) => n > 0);
3973
4803
  const avg = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
3974
4804
  if (avg < 12) return false;
3975
4805
  }
@@ -4396,7 +5226,7 @@ function assignRowItems(items, columns, numCols, headerFace) {
4396
5226
  const runs = [];
4397
5227
  for (const it of sorted) {
4398
5228
  const last = runs[runs.length - 1];
4399
- const prev = _optionalChain([last, 'optionalAccess', _135 => _135[last.length - 1]]);
5229
+ const prev = _optionalChain([last, 'optionalAccess', _142 => _142[last.length - 1]]);
4400
5230
  if (prev && it.x - (prev.x + prev.w) <= Math.max(0.5, it.fontSize * 0.05) && !it.hasSpaceBefore) last.push(it);
4401
5231
  else runs.push([it]);
4402
5232
  }
@@ -4462,17 +5292,21 @@ function assignRowItems(items, columns, numCols, headerFace) {
4462
5292
  return result;
4463
5293
  }
4464
5294
  function buildClusterTable(rows, columns, pageNum, lex) {
4465
- const numCols = columns.length;
4466
5295
  const numRows = rows.length;
4467
- if (numRows < MIN_ROWS || numCols < MIN_COLS) return null;
5296
+ if (numRows < MIN_ROWS || columns.length < MIN_COLS) return null;
5297
+ const headFaces = new Set(_optionalChain([rows, 'access', _143 => _143[0], 'optionalAccess', _144 => _144.items, 'access', _145 => _145.map, 'call', _146 => _146((i) => i.fontName)]));
5298
+ const headerFace = headFaces.size === 1 && rows.slice(1).every((row) => row.items.every((i) => !headFaces.has(i.fontName))) ? [...headFaces][0] : void 0;
5299
+ const assigned = rows.map((row, r) => assignRowItems(row.items, columns, columns.length, r === 0 ? headerFace : void 0));
5300
+ const cuts = supportedOcrColumnCuts(assigned);
5301
+ const starts = columns.map((_, c) => c + [...cuts.keys()].filter((k) => k < c).length);
5302
+ const numCols = columns.length + cuts.size;
4468
5303
  const cells = Array.from(
4469
5304
  { length: numRows },
4470
5305
  () => Array.from({ length: numCols }, () => ({ text: "", colSpan: 1, rowSpan: 1 }))
4471
5306
  );
4472
5307
  const usedItems = /* @__PURE__ */ new Set();
4473
5308
  const lines = cells.map((row) => row.map(() => []));
4474
- const headFaces = new Set(_optionalChain([rows, 'access', _136 => _136[0], 'optionalAccess', _137 => _137.items, 'access', _138 => _138.map, 'call', _139 => _139((i) => i.fontName)]));
4475
- const headerFace = headFaces.size === 1 && rows.slice(1).every((row) => row.items.every((i) => !headFaces.has(i.fontName))) ? [...headFaces][0] : void 0;
5309
+ const origins = /* @__PURE__ */ new Map();
4476
5310
  for (let r = 0; r < numRows; r++) {
4477
5311
  const row = rows[r];
4478
5312
  if (row.items.length === 1 && numCols > 1) {
@@ -4480,15 +5314,39 @@ function buildClusterTable(rows, columns, pageNum, lex) {
4480
5314
  usedItems.add(row.items[0]);
4481
5315
  continue;
4482
5316
  }
4483
- const assignments = assignRowItems(row.items, columns, numCols, r === 0 ? headerFace : void 0);
4484
- for (const { col, items } of assignments) {
5317
+ const assignments = assigned[r].flatMap(({ col, items }) => {
5318
+ const target = starts[col], cut = cuts.get(col);
5319
+ if (cut === void 0) return [{ col: target, items, span: 1 }];
5320
+ const gapAt = (it) => ocrTextGaps(it).find((g) => g.left < cut && g.right > cut && (r === 0 || isOcrNumericSplit(it.text, g.at)));
5321
+ const groupedNumber = OCR_GROUPED_NUMBER.test([...items].sort((a, b) => a.x - b.x).map((it) => it.text.trim()).join(" "));
5322
+ if (groupedNumber || !isOcrNumericPair(items) && items.some((it) => it.x < cut && it.x + it.w > cut && !gapAt(it))) return [{ col: target, items, span: 2 }];
5323
+ const parts = [[], []];
5324
+ for (const it of items) {
5325
+ const g = gapAt(it);
5326
+ if (!g) {
5327
+ parts[it.x + it.w / 2 < cut ? 0 : 1].push(it);
5328
+ continue;
5329
+ }
5330
+ const fragments = [
5331
+ { ...it, text: it.text.slice(0, g.at).trimEnd(), w: g.left - it.x },
5332
+ { ...it, text: it.text.slice(g.at).trimStart(), x: g.right, w: it.x + it.w - g.right }
5333
+ ];
5334
+ fragments.forEach((fragment, side) => {
5335
+ origins.set(fragment, it);
5336
+ parts[side].push(fragment);
5337
+ });
5338
+ }
5339
+ return parts.flatMap((part, side) => part.length ? [{ col: target + side, items: part, span: 1 }] : []);
5340
+ });
5341
+ for (const { col, items, span: span2 } of assignments) {
5342
+ cells[r][col].colSpan = span2;
4485
5343
  const cell = lines[r][col];
4486
5344
  if (cell.length) cell[cell.length - 1].spaceAfter = true;
4487
5345
  cell.push(...clusterCellLines(items));
4488
- for (const item of items) usedItems.add(item);
5346
+ for (const item of items) usedItems.add(_nullishCoalesce(origins.get(item), () => ( item)));
4489
5347
  }
4490
5348
  }
4491
- const boxes = columns.map((_, c) => {
5349
+ const boxes = Array.from({ length: numCols }, (_, c) => {
4492
5350
  const col = lines.flatMap((row) => row[c]);
4493
5351
  return { x1: Math.min(...col.map((l) => l.left)), x2: Math.max(...col.map((l) => l.right)) };
4494
5352
  });
@@ -4507,11 +5365,11 @@ function buildClusterTable(rows, columns, pageNum, lex) {
4507
5365
  const nonEmptyCols = cells[r].filter((c) => c.text.trim()).length;
4508
5366
  if (nonEmptyCols !== 1) continue;
4509
5367
  if (cells[r][0].text.trim() !== "") continue;
4510
- const contentText = _optionalChain([cells, 'access', _140 => _140[r], 'access', _141 => _141.find, 'call', _142 => _142((c) => c.text.trim()), 'optionalAccess', _143 => _143.text, 'access', _144 => _144.trim, 'call', _145 => _145()]) || "";
5368
+ const contentText = _optionalChain([cells, 'access', _147 => _147[r], 'access', _148 => _148.find, 'call', _149 => _149((c) => c.text.trim()), 'optionalAccess', _150 => _150.text, 'access', _151 => _151.trim, 'call', _152 => _152()]) || "";
4511
5369
  if (/^[○●▶\-·]/.test(contentText)) continue;
4512
5370
  for (let pr = r - 1; pr >= 0; pr--) {
4513
5371
  if (cells[pr].some((c) => c.text.trim())) {
4514
- if (cells[pr][0].colSpan > 1) break;
5372
+ if (cells[pr].some((c) => c.colSpan > 1)) break;
4515
5373
  for (let c = 0; c < numCols; c++) {
4516
5374
  if (!cells[r][c].text.trim()) continue;
4517
5375
  lines[pr][c].push(...lines[r][c]);
@@ -4740,7 +5598,7 @@ function stackedTableBands(items) {
4740
5598
  const caption = (start, end) => lines.slice(start, end).some((line) => /^Table\s+\d+\s*[:.]/i.test(mergeLineSimple(line).trim()));
4741
5599
  while (runs.length > 0 && !caption(runs[runs.length - 1].end, lines.length)) runs.pop();
4742
5600
  if (runs.length < 2) return null;
4743
- if (runs.some((run, i) => !caption(run.end, _nullishCoalesce(_optionalChain([runs, 'access', _146 => _146[i + 1], 'optionalAccess', _147 => _147.start]), () => ( lines.length))))) return null;
5601
+ if (runs.some((run, i) => !caption(run.end, _nullishCoalesce(_optionalChain([runs, 'access', _153 => _153[i + 1], 'optionalAccess', _154 => _154.start]), () => ( lines.length))))) return null;
4744
5602
  const tables = runs.map((run) => lines.slice(run.start, run.end).flat());
4745
5603
  const between = runs.slice(0, -1).map((run, i) => lines.slice(run.end, runs[i + 1].start).flat());
4746
5604
  const tail = lines.slice(runs[runs.length - 1].end);
@@ -5008,7 +5866,7 @@ function splitTrailingColumnRegion(items) {
5008
5866
  }
5009
5867
  function panelBlocks(items, panel, pageNum) {
5010
5868
  const lines = groupByY([...items].sort((a, b) => b.y - a.y || a.x - b.x));
5011
- const faceOf = (line) => _nullishCoalesce(_optionalChain([dominantStyle, 'call', _148 => _148(line), 'optionalAccess', _149 => _149.fontName]), () => ( ""));
5869
+ const faceOf = (line) => _nullishCoalesce(_optionalChain([dominantStyle, 'call', _155 => _155(line), 'optionalAccess', _156 => _156.fontName]), () => ( ""));
5012
5870
  const runs = [];
5013
5871
  for (const line of lines) {
5014
5872
  const last = runs[runs.length - 1];
@@ -5190,7 +6048,7 @@ function validWrapBands(items, bands) {
5190
6048
  }
5191
6049
  function inheritedWrapBands(items) {
5192
6050
  const source = XY_WRAP_ITEMS.get(items[0]);
5193
- const present = _optionalChain([source, 'optionalAccess', _150 => _150.length]) === items.length ? new Set(items) : null;
6051
+ const present = _optionalChain([source, 'optionalAccess', _157 => _157.length]) === items.length ? new Set(items) : null;
5194
6052
  const sameLeaf = present && source.every((item) => present.has(item));
5195
6053
  return sameLeaf ? validWrapBands(items, _nullishCoalesce(XY_WRAP_BANDS.get(items[0]), () => ( []))) : [];
5196
6054
  }
@@ -5229,7 +6087,7 @@ function wrappedLineBands(items, inherited) {
5229
6087
  left: box.x,
5230
6088
  right: box.x + box.width,
5231
6089
  y: row.reduce((n, i) => n + i.y, 0) / row.length,
5232
- fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call', _151 => _151(row), 'optionalAccess', _152 => _152.fontSize]), () => ( 0)),
6090
+ fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call', _158 => _158(row), 'optionalAccess', _159 => _159.fontSize]), () => ( 0)),
5233
6091
  sources: row.map((item) => ({ item, state: { ...item } }))
5234
6092
  };
5235
6093
  });
@@ -5365,10 +6223,10 @@ function pushLineParagraphs(out, yLines, pageNum, lex) {
5365
6223
  const lines = attachDropCaps(yLines).map((items) => ({ items, text: mergeLineSimple(items) })).filter((l) => l.text.trim());
5366
6224
  const geo = lines.map((l) => {
5367
6225
  const b = computeBBox(l.items, pageNum);
5368
- return { text: l.text, left: b.x, right: b.x + b.width, y: l.items.reduce((s, i) => s + i.y, 0) / l.items.length, fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call', _153 => _153(l.items), 'optionalAccess', _154 => _154.fontSize]), () => ( 0)) };
6226
+ return { text: l.text, left: b.x, right: b.x + b.width, y: l.items.reduce((s, i) => s + i.y, 0) / l.items.length, fontSize: _nullishCoalesce(_optionalChain([dominantStyle, 'call', _160 => _160(l.items), 'optionalAccess', _161 => _161.fontSize]), () => ( 0)) };
5369
6227
  });
5370
6228
  const joins = bodyLineJoins(geo, lex);
5371
- const first = _optionalChain([lines, 'access', _155 => _155[0], 'optionalAccess', _156 => _156.items, 'access', _157 => _157[0]]);
6229
+ const first = _optionalChain([lines, 'access', _162 => _162[0], 'optionalAccess', _163 => _163.items, 'access', _164 => _164[0]]);
5372
6230
  const bands = first ? _nullishCoalesce(XY_WRAP_BANDS.get(first), () => ( [])) : [];
5373
6231
  const hasBand = (top, bottom) => {
5374
6232
  let lo = 0, hi = bands.length;
@@ -5445,15 +6303,15 @@ function computeMedianFontSizeFromFreq(freq) {
5445
6303
  function detectHeadings(blocks, medianFontSize) {
5446
6304
  for (let bi = 0; bi < blocks.length; bi++) {
5447
6305
  const block = blocks[bi];
5448
- if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _158 => _158.style, 'optionalAccess', _159 => _159.fontSize])) continue;
6306
+ if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _165 => _165.style, 'optionalAccess', _166 => _166.fontSize])) continue;
5449
6307
  const text = block.text.trim();
5450
6308
  if (text.length === 0 || text.length > 200) continue;
5451
6309
  if (/^\d+$/.test(text) && !isChapterNumber(block, blocks[bi + 1], medianFontSize)) continue;
5452
6310
  const ratio = block.style.fontSize / medianFontSize;
5453
6311
  let level = 0;
5454
- if (ratio >= _chunkAM5ALISVcjs.HEADING_RATIO_H1) level = 1;
5455
- else if (ratio >= _chunkAM5ALISVcjs.HEADING_RATIO_H2) level = 2;
5456
- else if (ratio >= _chunkAM5ALISVcjs.HEADING_RATIO_H3) level = 3;
6312
+ if (ratio >= _chunkNW2CKOFLcjs.HEADING_RATIO_H1) level = 1;
6313
+ else if (ratio >= _chunkNW2CKOFLcjs.HEADING_RATIO_H2) level = 2;
6314
+ else if (ratio >= _chunkNW2CKOFLcjs.HEADING_RATIO_H3) level = 3;
5457
6315
  if (level > 0) {
5458
6316
  block.type = "heading";
5459
6317
  block.level = level;
@@ -5462,21 +6320,21 @@ function detectHeadings(blocks, medianFontSize) {
5462
6320
  }
5463
6321
  }
5464
6322
  function isChapterNumber(block, next, medianFontSize) {
5465
- const size = _nullishCoalesce(_optionalChain([block, 'access', _160 => _160.style, 'optionalAccess', _161 => _161.fontSize]), () => ( 0));
5466
- const nextSize = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _162 => _162.style, 'optionalAccess', _163 => _163.fontSize]), () => ( 0));
5467
- const text = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _164 => _164.text, 'optionalAccess', _165 => _165.trim, 'call', _166 => _166()]), () => ( ""));
5468
- const a = block.bbox, b = _optionalChain([next, 'optionalAccess', _167 => _167.bbox]);
5469
- return /^\d{1,2}$/.test(_nullishCoalesce(_optionalChain([block, 'access', _168 => _168.text, 'optionalAccess', _169 => _169.trim, 'call', _170 => _170()]), () => ( ""))) && size >= medianFontSize * 2.5 && !!next && (next.type === "paragraph" || next.type === "heading") && next.pageNumber === block.pageNumber && nextSize >= medianFontSize * _chunkAM5ALISVcjs.HEADING_RATIO_H1 && text.length > 0 && text.length <= 80 && !/^[\d\s.]+$/.test(text) && !!a && !!b && a.y > b.y && a.y - (b.y + b.height) <= size * 2;
6323
+ const size = _nullishCoalesce(_optionalChain([block, 'access', _167 => _167.style, 'optionalAccess', _168 => _168.fontSize]), () => ( 0));
6324
+ const nextSize = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _169 => _169.style, 'optionalAccess', _170 => _170.fontSize]), () => ( 0));
6325
+ const text = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _171 => _171.text, 'optionalAccess', _172 => _172.trim, 'call', _173 => _173()]), () => ( ""));
6326
+ const a = block.bbox, b = _optionalChain([next, 'optionalAccess', _174 => _174.bbox]);
6327
+ return /^\d{1,2}$/.test(_nullishCoalesce(_optionalChain([block, 'access', _175 => _175.text, 'optionalAccess', _176 => _176.trim, 'call', _177 => _177()]), () => ( ""))) && size >= medianFontSize * 2.5 && !!next && (next.type === "paragraph" || next.type === "heading") && next.pageNumber === block.pageNumber && nextSize >= medianFontSize * _chunkNW2CKOFLcjs.HEADING_RATIO_H1 && text.length > 0 && text.length <= 80 && !/^[\d\s.]+$/.test(text) && !!a && !!b && a.y > b.y && a.y - (b.y + b.height) <= size * 2;
5470
6328
  }
5471
6329
  function mergeStackedHeadingLines(blocks, medianFontSize) {
5472
6330
  for (let i = 0; i < blocks.length - 1; ) {
5473
6331
  const a = blocks[i], b = blocks[i + 1];
5474
6332
  const ab = a.bbox, bb = b.bbox;
5475
- const af = _nullishCoalesce(_optionalChain([a, 'access', _171 => _171.style, 'optionalAccess', _172 => _172.fontSize]), () => ( 0)), bf = _nullishCoalesce(_optionalChain([b, 'access', _173 => _173.style, 'optionalAccess', _174 => _174.fontSize]), () => ( 0));
6333
+ const af = _nullishCoalesce(_optionalChain([a, 'access', _178 => _178.style, 'optionalAccess', _179 => _179.fontSize]), () => ( 0)), bf = _nullishCoalesce(_optionalChain([b, 'access', _180 => _180.style, 'optionalAccess', _181 => _181.fontSize]), () => ( 0));
5476
6334
  const gap = ab && bb ? ab.y - (bb.y + bb.height) : Infinity;
5477
- const centered = ab && bb && _optionalChain([a, 'access', _175 => _175.style, 'optionalAccess', _176 => _176.fontName]) === _optionalChain([b, 'access', _177 => _177.style, 'optionalAccess', _178 => _178.fontName]) && Math.abs(ab.x + ab.width / 2 - (bb.x + bb.width / 2)) <= Math.max(5, af * 0.5);
6335
+ const centered = ab && bb && _optionalChain([a, 'access', _182 => _182.style, 'optionalAccess', _183 => _183.fontName]) === _optionalChain([b, 'access', _184 => _184.style, 'optionalAccess', _185 => _185.fontName]) && Math.abs(ab.x + ab.width / 2 - (bb.x + bb.width / 2)) <= Math.max(5, af * 0.5);
5478
6336
  const sameAnchor = ab && bb && Math.abs(ab.x - bb.x) <= 5;
5479
- const wrapped = sameAnchor && _optionalChain([a, 'access', _179 => _179.style, 'optionalAccess', _180 => _180.fontName]) === _optionalChain([b, 'access', _181 => _181.style, 'optionalAccess', _182 => _182.fontName]) && af === bf && ab.width >= bb.width * 0.95 && (_nullishCoalesce(_optionalChain([a, 'access', _183 => _183.text, 'optionalAccess', _184 => _184.trim, 'call', _185 => _185(), 'access', _186 => _186.split, 'call', _187 => _187(/\s+/), 'access', _188 => _188.length]), () => ( 0))) >= 3;
6337
+ const wrapped = sameAnchor && _optionalChain([a, 'access', _186 => _186.style, 'optionalAccess', _187 => _187.fontName]) === _optionalChain([b, 'access', _188 => _188.style, 'optionalAccess', _189 => _189.fontName]) && af === bf && ab.width >= bb.width * 0.95 && (_nullishCoalesce(_optionalChain([a, 'access', _190 => _190.text, 'optionalAccess', _191 => _191.trim, 'call', _192 => _192(), 'access', _193 => _193.split, 'call', _194 => _194(/\s+/), 'access', _195 => _195.length]), () => ( 0))) >= 3;
5480
6338
  const displayStack = centered && gap <= Math.min(af, bf) * 0.3 && Math.max(af, bf) <= Math.min(af, bf) * 1.45;
5481
6339
  if (a.type !== "heading" || b.type !== "heading" || !a.text || !b.text || /^\d+$/.test(a.text.trim()) || !ab || !bb || ab.page !== bb.page || !(sameAnchor && af >= medianFontSize * 2 && bf >= medianFontSize * 2) && !wrapped && !(centered && af >= medianFontSize * 1.25 && bf >= medianFontSize * 1.25) || Math.abs(af - bf) > Math.max(af, bf) * 0.15 && !displayStack || gap < -2 || gap > Math.max(af, bf) * 0.45 || a.text.length > (centered ? 120 : 50) || b.text.length > (centered ? 120 : 50)) {
5482
6340
  i++;
@@ -5505,25 +6363,25 @@ function detectTypographyHeadings(blocks) {
5505
6363
  if (page.some((block) => block.type === "heading")) continue;
5506
6364
  const faceWeight = /* @__PURE__ */ new Map();
5507
6365
  for (const block of page) {
5508
- if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _189 => _189.style, 'optionalAccess', _190 => _190.fontName])) continue;
6366
+ if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _196 => _196.style, 'optionalAccess', _197 => _197.fontName])) continue;
5509
6367
  const faces = FACE_CHARS.get(block);
5510
6368
  if (faces) for (const [face, n] of faces) faceWeight.set(face, (_nullishCoalesce(faceWeight.get(face), () => ( 0))) + n);
5511
6369
  else faceWeight.set(block.style.fontName, (_nullishCoalesce(faceWeight.get(block.style.fontName), () => ( 0))) + block.text.length);
5512
6370
  }
5513
- const bodyFace = _optionalChain([[...faceWeight], 'access', _191 => _191.sort, 'call', _192 => _192((a, b) => b[1] - a[1]), 'access', _193 => _193[0], 'optionalAccess', _194 => _194[0]]);
6371
+ const bodyFace = _optionalChain([[...faceWeight], 'access', _198 => _198.sort, 'call', _199 => _199((a, b) => b[1] - a[1]), 'access', _200 => _200[0], 'optionalAccess', _201 => _201[0]]);
5514
6372
  if (!bodyFace || (_nullishCoalesce(faceWeight.get(bodyFace), () => ( 0))) < 250) continue;
5515
6373
  const sizeWeight = /* @__PURE__ */ new Map();
5516
6374
  for (const block of page) {
5517
- if (block.type !== "paragraph" || !_optionalChain([block, 'access', _195 => _195.style, 'optionalAccess', _196 => _196.fontSize])) continue;
6375
+ if (block.type !== "paragraph" || !_optionalChain([block, 'access', _202 => _202.style, 'optionalAccess', _203 => _203.fontSize])) continue;
5518
6376
  const faces = FACE_CHARS.get(block);
5519
- const chars = faces ? _nullishCoalesce(faces.get(bodyFace), () => ( 0)) : block.style.fontName === bodyFace ? _nullishCoalesce(_optionalChain([block, 'access', _197 => _197.text, 'optionalAccess', _198 => _198.length]), () => ( 0)) : 0;
6377
+ const chars = faces ? _nullishCoalesce(faces.get(bodyFace), () => ( 0)) : block.style.fontName === bodyFace ? _nullishCoalesce(_optionalChain([block, 'access', _204 => _204.text, 'optionalAccess', _205 => _205.length]), () => ( 0)) : 0;
5520
6378
  if (chars) sizeWeight.set(block.style.fontSize, (_nullishCoalesce(sizeWeight.get(block.style.fontSize), () => ( 0))) + chars);
5521
6379
  }
5522
- const bodySize = _nullishCoalesce(_optionalChain([[...sizeWeight], 'access', _199 => _199.sort, 'call', _200 => _200((a, b) => b[1] - a[1]), 'access', _201 => _201[0], 'optionalAccess', _202 => _202[0]]), () => ( 0));
6380
+ const bodySize = _nullishCoalesce(_optionalChain([[...sizeWeight], 'access', _206 => _206.sort, 'call', _207 => _207((a, b) => b[1] - a[1]), 'access', _208 => _208[0], 'optionalAccess', _209 => _209[0]]), () => ( 0));
5523
6381
  for (let i = 0; i < page.length; i++) {
5524
6382
  const block = page[i];
5525
6383
  const { text, bbox, style } = block;
5526
- if (block.type !== "paragraph" || !text || !bbox || !_optionalChain([style, 'optionalAccess', _203 => _203.fontName]) || !style.fontSize) continue;
6384
+ if (block.type !== "paragraph" || !text || !bbox || !_optionalChain([style, 'optionalAccess', _210 => _210.fontName]) || !style.fontSize) continue;
5527
6385
  const title = text.trim();
5528
6386
  const numbered = /^\d+(?:\.\d+)*\.?\s+[A-Z가-힣]/.test(title);
5529
6387
  const faces = FACE_CHARS.get(block);
@@ -5553,16 +6411,16 @@ function detectDocumentStyleHeadings(blocks) {
5553
6411
  for (const page of byPage.values()) {
5554
6412
  const faceChars = /* @__PURE__ */ new Map();
5555
6413
  for (const block of page) {
5556
- if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _204 => _204.style, 'optionalAccess', _205 => _205.fontName])) continue;
6414
+ if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _211 => _211.style, 'optionalAccess', _212 => _212.fontName])) continue;
5557
6415
  faceChars.set(block.style.fontName, (_nullishCoalesce(faceChars.get(block.style.fontName), () => ( 0))) + block.text.length);
5558
6416
  }
5559
- const bodyFace = _optionalChain([[...faceChars], 'access', _206 => _206.sort, 'call', _207 => _207((a, b) => b[1] - a[1]), 'access', _208 => _208[0], 'optionalAccess', _209 => _209[0]]);
6417
+ const bodyFace = _optionalChain([[...faceChars], 'access', _213 => _213.sort, 'call', _214 => _214((a, b) => b[1] - a[1]), 'access', _215 => _215[0], 'optionalAccess', _216 => _216[0]]);
5560
6418
  if (!bodyFace || (_nullishCoalesce(faceChars.get(bodyFace), () => ( 0))) < 100) continue;
5561
- const labels = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _210 => _210.style, 'optionalAccess', _211 => _211.fontName]) && b.style.fontName !== bodyFace && b.text.trim().length >= 3 && b.text.trim().length <= 40);
6419
+ const labels = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _217 => _217.style, 'optionalAccess', _218 => _218.fontName]) && b.style.fontName !== bodyFace && b.text.trim().length >= 3 && b.text.trim().length <= 40);
5562
6420
  for (const label of labels) {
5563
- const peers = labels.filter((b) => _optionalChain([b, 'access', _212 => _212.style, 'optionalAccess', _213 => _213.fontName]) === _optionalChain([label, 'access', _214 => _214.style, 'optionalAccess', _215 => _215.fontName]) && Math.abs(b.bbox.y - label.bbox.y) <= 3 && Math.abs(b.bbox.x - label.bbox.x) >= 60);
6421
+ const peers = labels.filter((b) => _optionalChain([b, 'access', _219 => _219.style, 'optionalAccess', _220 => _220.fontName]) === _optionalChain([label, 'access', _221 => _221.style, 'optionalAccess', _222 => _222.fontName]) && Math.abs(b.bbox.y - label.bbox.y) <= 3 && Math.abs(b.bbox.x - label.bbox.x) >= 60);
5564
6422
  if (peers.length < 2) continue;
5565
- const value = page.find((b) => b.type === "paragraph" && b.bbox && _optionalChain([b, 'access', _216 => _216.style, 'optionalAccess', _217 => _217.fontName]) !== _optionalChain([label, 'access', _218 => _218.style, 'optionalAccess', _219 => _219.fontName]) && b.bbox.x >= label.bbox.x - 5 && b.bbox.x <= label.bbox.x + 20 && b.bbox.y < label.bbox.y && label.bbox.y - (b.bbox.y + b.bbox.height) <= 60);
6423
+ const value = page.find((b) => b.type === "paragraph" && b.bbox && _optionalChain([b, 'access', _223 => _223.style, 'optionalAccess', _224 => _224.fontName]) !== _optionalChain([label, 'access', _225 => _225.style, 'optionalAccess', _226 => _226.fontName]) && b.bbox.x >= label.bbox.x - 5 && b.bbox.x <= label.bbox.x + 20 && b.bbox.y < label.bbox.y && label.bbox.y - (b.bbox.y + b.bbox.height) <= 60);
5566
6424
  if (value) {
5567
6425
  label.type = "heading";
5568
6426
  label.level = 2;
@@ -5571,7 +6429,7 @@ function detectDocumentStyleHeadings(blocks) {
5571
6429
  const first = page.find((b) => b.type !== "image" && b.type !== "separator");
5572
6430
  const second = page[page.indexOf(first) + 1];
5573
6431
  const third = page[page.indexOf(first) + 2];
5574
- if (!first || !second || !third || first.type !== "list" && first.type !== "paragraph" || second.type !== "paragraph" || !first.text || !second.text || !first.bbox || !second.bbox || !_optionalChain([first, 'access', _220 => _220.style, 'optionalAccess', _221 => _221.fontName]) || !_optionalChain([second, 'access', _222 => _222.style, 'optionalAccess', _223 => _223.fontName]) || !/^\d+(?:\.\d+)*\.\s+/.test(first.text.trim()) || first.style.fontName === bodyFace || second.style.fontName === bodyFace || first.text.length + second.text.length > 140 || Math.abs(first.bbox.x - second.bbox.x) > 30 || first.bbox.y - (second.bbox.y + second.bbox.height) > (_nullishCoalesce(first.style.fontSize, () => ( 0))) * 1.5 || _optionalChain([third, 'access', _224 => _224.style, 'optionalAccess', _225 => _225.fontName]) !== bodyFace) continue;
6432
+ if (!first || !second || !third || first.type !== "list" && first.type !== "paragraph" || second.type !== "paragraph" || !first.text || !second.text || !first.bbox || !second.bbox || !_optionalChain([first, 'access', _227 => _227.style, 'optionalAccess', _228 => _228.fontName]) || !_optionalChain([second, 'access', _229 => _229.style, 'optionalAccess', _230 => _230.fontName]) || !/^\d+(?:\.\d+)*\.\s+/.test(first.text.trim()) || first.style.fontName === bodyFace || second.style.fontName === bodyFace || first.text.length + second.text.length > 140 || Math.abs(first.bbox.x - second.bbox.x) > 30 || first.bbox.y - (second.bbox.y + second.bbox.height) > (_nullishCoalesce(first.style.fontSize, () => ( 0))) * 1.5 || _optionalChain([third, 'access', _231 => _231.style, 'optionalAccess', _232 => _232.fontName]) !== bodyFace) continue;
5575
6433
  first.type = "heading";
5576
6434
  first.level = 1;
5577
6435
  first.text = `${first.text.trim()} ${second.text.trim()}`;
@@ -5595,18 +6453,18 @@ function detectSiblingStyleHeadings(blocks) {
5595
6453
  for (const page of byPage.values()) {
5596
6454
  const bodyChars = /* @__PURE__ */ new Map();
5597
6455
  for (const block of page) {
5598
- if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _226 => _226.style, 'optionalAccess', _227 => _227.fontName])) continue;
6456
+ if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _233 => _233.style, 'optionalAccess', _234 => _234.fontName])) continue;
5599
6457
  const face = block.style.fontName;
5600
6458
  bodyChars.set(face, (_nullishCoalesce(bodyChars.get(face), () => ( 0))) + block.text.length);
5601
6459
  }
5602
- const bodyFace = _optionalChain([[...bodyChars], 'access', _228 => _228.sort, 'call', _229 => _229((a, b) => b[1] - a[1]), 'access', _230 => _230[0], 'optionalAccess', _231 => _231[0]]);
5603
- const anchors = page.filter((b) => b.type === "heading" && b.text && _optionalChain([b, 'access', _232 => _232.style, 'optionalAccess', _233 => _233.fontName]) && b.style.fontName !== bodyFace);
6460
+ const bodyFace = _optionalChain([[...bodyChars], 'access', _235 => _235.sort, 'call', _236 => _236((a, b) => b[1] - a[1]), 'access', _237 => _237[0], 'optionalAccess', _238 => _238[0]]);
6461
+ const anchors = page.filter((b) => b.type === "heading" && b.text && _optionalChain([b, 'access', _239 => _239.style, 'optionalAccess', _240 => _240.fontName]) && b.style.fontName !== bodyFace);
5604
6462
  for (const anchor of anchors) {
5605
6463
  const numbered = /^([A-Z])\.\d+\s+/.exec(anchor.text.trim());
5606
6464
  const lettered = /^([A-Z])\s+/.exec(anchor.text.trim());
5607
- const peers = anchors.filter((b) => _optionalChain([b, 'access', _234 => _234.style, 'optionalAccess', _235 => _235.fontName]) === _optionalChain([anchor, 'access', _236 => _236.style, 'optionalAccess', _237 => _237.fontName]) && Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _238 => _238.style, 'optionalAccess', _239 => _239.fontSize]), () => ( 0))) - (_nullishCoalesce(_optionalChain([anchor, 'access', _240 => _240.style, 'optionalAccess', _241 => _241.fontSize]), () => ( 0)))) < 0.5);
6465
+ const peers = anchors.filter((b) => _optionalChain([b, 'access', _241 => _241.style, 'optionalAccess', _242 => _242.fontName]) === _optionalChain([anchor, 'access', _243 => _243.style, 'optionalAccess', _244 => _244.fontName]) && Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _245 => _245.style, 'optionalAccess', _246 => _246.fontSize]), () => ( 0))) - (_nullishCoalesce(_optionalChain([anchor, 'access', _247 => _247.style, 'optionalAccess', _248 => _248.fontSize]), () => ( 0)))) < 0.5);
5608
6466
  if (peers.length < 2 && !numbered && !lettered) continue;
5609
- const candidates = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _242 => _242.style, 'optionalAccess', _243 => _243.fontName]) === _optionalChain([anchor, 'access', _244 => _244.style, 'optionalAccess', _245 => _245.fontName]) && Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _246 => _246.style, 'optionalAccess', _247 => _247.fontSize]), () => ( 0))) - (_nullishCoalesce(_optionalChain([anchor, 'access', _248 => _248.style, 'optionalAccess', _249 => _249.fontSize]), () => ( 0)))) < 0.5 && b.text.trim().length >= 3 && b.text.trim().length <= 80 && b.bbox.height <= (_nullishCoalesce(_optionalChain([b, 'access', _250 => _250.style, 'optionalAccess', _251 => _251.fontSize]), () => ( 0))) * 1.6 && /^[A-Z]/.test(b.text.trim()) && !/[.!?:;,]$/.test(b.text.trim()) && !/^(?:Table|Figure|Fig\.?|Appendix)\s+\d/i.test(b.text.trim()));
6467
+ const candidates = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _249 => _249.style, 'optionalAccess', _250 => _250.fontName]) === _optionalChain([anchor, 'access', _251 => _251.style, 'optionalAccess', _252 => _252.fontName]) && Math.abs((_nullishCoalesce(_optionalChain([b, 'access', _253 => _253.style, 'optionalAccess', _254 => _254.fontSize]), () => ( 0))) - (_nullishCoalesce(_optionalChain([anchor, 'access', _255 => _255.style, 'optionalAccess', _256 => _256.fontSize]), () => ( 0)))) < 0.5 && b.text.trim().length >= 3 && b.text.trim().length <= 80 && b.bbox.height <= (_nullishCoalesce(_optionalChain([b, 'access', _257 => _257.style, 'optionalAccess', _258 => _258.fontSize]), () => ( 0))) * 1.6 && /^[A-Z]/.test(b.text.trim()) && !/[.!?:;,]$/.test(b.text.trim()) && !/^(?:Table|Figure|Fig\.?|Appendix)\s+\d/i.test(b.text.trim()));
5610
6468
  const siblings = candidates.filter((b) => numbered ? new RegExp(`^${numbered[1]}\\.\\d+\\s+`).test(b.text.trim()) : lettered ? /^[A-Z]\s+/.test(b.text.trim()) && Math.abs(anchor.bbox.x - b.bbox.x) < 8 : peers.some((h) => h.bbox && Math.abs(h.bbox.x - b.bbox.x) < 8));
5611
6469
  if (siblings.length < (numbered || lettered ? 1 : 2)) continue;
5612
6470
  for (const sibling of siblings) {
@@ -5625,13 +6483,13 @@ function detectRepeatedPageLabels(blocks) {
5625
6483
  }
5626
6484
  for (const page of byPage.values()) {
5627
6485
  const bodyChars = /* @__PURE__ */ new Map();
5628
- for (const b of page) if (b.type === "paragraph" && b.text && _optionalChain([b, 'access', _252 => _252.style, 'optionalAccess', _253 => _253.fontName])) {
6486
+ for (const b of page) if (b.type === "paragraph" && b.text && _optionalChain([b, 'access', _259 => _259.style, 'optionalAccess', _260 => _260.fontName])) {
5629
6487
  const faces = FACE_CHARS.get(b);
5630
6488
  if (faces) for (const [face, n] of faces) bodyChars.set(face, (_nullishCoalesce(bodyChars.get(face), () => ( 0))) + n);
5631
6489
  else bodyChars.set(b.style.fontName, (_nullishCoalesce(bodyChars.get(b.style.fontName), () => ( 0))) + b.text.length);
5632
6490
  }
5633
- const bodyFace = _optionalChain([[...bodyChars], 'access', _254 => _254.sort, 'call', _255 => _255((a, b) => b[1] - a[1]), 'access', _256 => _256[0], 'optionalAccess', _257 => _257[0]]);
5634
- const candidates = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _258 => _258.style, 'optionalAccess', _259 => _259.fontName]) && b.style.fontName !== bodyFace && b.bbox.height <= (_nullishCoalesce(b.style.fontSize, () => ( 0))) * 1.6 && b.text.trim().length >= 5 && b.text.trim().length <= 80);
6491
+ const bodyFace = _optionalChain([[...bodyChars], 'access', _261 => _261.sort, 'call', _262 => _262((a, b) => b[1] - a[1]), 'access', _263 => _263[0], 'optionalAccess', _264 => _264[0]]);
6492
+ const candidates = page.filter((b) => b.type === "paragraph" && b.text && b.bbox && _optionalChain([b, 'access', _265 => _265.style, 'optionalAccess', _266 => _266.fontName]) && b.style.fontName !== bodyFace && b.bbox.height <= (_nullishCoalesce(b.style.fontSize, () => ( 0))) * 1.6 && b.text.trim().length >= 5 && b.text.trim().length <= 80);
5635
6493
  const groups = /* @__PURE__ */ new Map();
5636
6494
  for (const b of candidates) {
5637
6495
  const key = `${b.style.fontName}:${b.style.fontSize}`;
@@ -5667,19 +6525,19 @@ function detectPageLeadHeadings(blocks) {
5667
6525
  for (const page of byPage.values()) {
5668
6526
  const content = page.filter((b) => b.type !== "image" && b.type !== "separator" && !(b.type === "paragraph" && !b.style));
5669
6527
  const [first, second, third] = content;
5670
- if (!_optionalChain([first, 'optionalAccess', _260 => _260.bbox]) || !first.text || !_optionalChain([first, 'access', _261 => _261.style, 'optionalAccess', _262 => _262.fontSize]) || !second) continue;
6528
+ if (!_optionalChain([first, 'optionalAccess', _267 => _267.bbox]) || !first.text || !_optionalChain([first, 'access', _268 => _268.style, 'optionalAccess', _269 => _269.fontSize]) || !second) continue;
5671
6529
  const firstText = first.text.trim();
5672
6530
  const captionLike = /^(?:Figure|Fig\.?|Table|표|그림)\s*\d/i;
5673
6531
  const hasImage = page.some((b) => b.type === "image");
5674
- const firstIsTitle = first.type === "paragraph" && firstText.length >= 5 && firstText.length <= 80 && first.bbox.height <= first.style.fontSize * 1.6 && (/^(?:CONTENTS|Table of Contents)$/i.test(firstText) || hasImage && /^[A-Z]/.test(firstText) && !captionLike.test(firstText) && second.type === "paragraph" && /^[A-Z]/.test(_nullishCoalesce(_optionalChain([second, 'access', _263 => _263.text, 'optionalAccess', _264 => _264.trim, 'call', _265 => _265()]), () => ( ""))) && (_nullishCoalesce(_optionalChain([second, 'access', _266 => _266.text, 'optionalAccess', _267 => _267.length]), () => ( 0))) >= 100 && second.bbox && first.bbox.y - (second.bbox.y + second.bbox.height) >= first.style.fontSize);
6532
+ const firstIsTitle = first.type === "paragraph" && firstText.length >= 5 && firstText.length <= 80 && first.bbox.height <= first.style.fontSize * 1.6 && (/^(?:CONTENTS|Table of Contents)$/i.test(firstText) || hasImage && /^[A-Z]/.test(firstText) && !captionLike.test(firstText) && second.type === "paragraph" && /^[A-Z]/.test(_nullishCoalesce(_optionalChain([second, 'access', _270 => _270.text, 'optionalAccess', _271 => _271.trim, 'call', _272 => _272()]), () => ( ""))) && (_nullishCoalesce(_optionalChain([second, 'access', _273 => _273.text, 'optionalAccess', _274 => _274.length]), () => ( 0))) >= 100 && second.bbox && first.bbox.y - (second.bbox.y + second.bbox.height) >= first.style.fontSize);
5675
6533
  const firstAboveProse = first.type === "paragraph" && firstText.length >= 5 && firstText.length <= 80 && first.bbox.height <= first.style.fontSize * 2 && second.type === "paragraph" && second.bbox && second.bbox.height >= first.style.fontSize * 4 && Math.abs(first.bbox.x - second.bbox.x) <= first.style.fontSize * 2 && first.bbox.y - (second.bbox.y + second.bbox.height) >= first.style.fontSize * 2 && !captionLike.test(firstText) && !/^(?:doi:|https?:|www\.)/i.test(firstText);
5676
- const firstIsSection = first.type === "list" && /^\d+\.\s+[A-Z][A-Z\s]{12,}$/.test(firstText) && second.type === "paragraph" && (_nullishCoalesce(_optionalChain([second, 'access', _268 => _268.text, 'optionalAccess', _269 => _269.length]), () => ( 0))) >= 100;
6534
+ const firstIsSection = first.type === "list" && /^\d+\.\s+[A-Z][A-Z\s]{12,}$/.test(firstText) && second.type === "paragraph" && (_nullishCoalesce(_optionalChain([second, 'access', _275 => _275.text, 'optionalAccess', _276 => _276.length]), () => ( 0))) >= 100;
5677
6535
  if (firstIsTitle || firstAboveProse || firstIsSection) {
5678
6536
  first.type = "heading";
5679
6537
  first.level = 1;
5680
6538
  }
5681
- if (first.type !== "heading" || captionLike.test(firstText) || second.type !== "paragraph" || !second.text || !second.bbox || !_optionalChain([second, 'access', _270 => _270.style, 'optionalAccess', _271 => _271.fontName]) || !second.style.fontSize || !_optionalChain([third, 'optionalAccess', _272 => _272.text]) || !third.bbox || second.text.trim().length < 5 || second.text.trim().length > 80 || captionLike.test(second.text.trim()) || /^(?:doi:|https?:)/i.test(second.text.trim()) || second.bbox.height > second.style.fontSize * 1.6 || Math.abs(second.bbox.x - third.bbox.x) > 30) continue;
5682
- const distinctFace = _optionalChain([third, 'access', _273 => _273.style, 'optionalAccess', _274 => _274.fontName]) !== second.style.fontName;
6539
+ if (first.type !== "heading" || captionLike.test(firstText) || second.type !== "paragraph" || !second.text || !second.bbox || !_optionalChain([second, 'access', _277 => _277.style, 'optionalAccess', _278 => _278.fontName]) || !second.style.fontSize || !_optionalChain([third, 'optionalAccess', _279 => _279.text]) || !third.bbox || second.text.trim().length < 5 || second.text.trim().length > 80 || captionLike.test(second.text.trim()) || /^(?:doi:|https?:)/i.test(second.text.trim()) || second.bbox.height > second.style.fontSize * 1.6 || Math.abs(second.bbox.x - third.bbox.x) > 30) continue;
6540
+ const distinctFace = _optionalChain([third, 'access', _280 => _280.style, 'optionalAccess', _281 => _281.fontName]) !== second.style.fontName;
5683
6541
  const namedContents = /^Table of Contents$/i.test(second.text.trim());
5684
6542
  if (distinctFace && third.text.length >= 60 || namedContents) {
5685
6543
  second.type = "heading";
@@ -5690,24 +6548,24 @@ function detectPageLeadHeadings(blocks) {
5690
6548
  function refineDocumentStyleHeadings(blocks) {
5691
6549
  const faceChars = /* @__PURE__ */ new Map();
5692
6550
  for (const block of blocks) {
5693
- if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _275 => _275.style, 'optionalAccess', _276 => _276.fontName])) continue;
6551
+ if (block.type !== "paragraph" || !block.text || !_optionalChain([block, 'access', _282 => _282.style, 'optionalAccess', _283 => _283.fontName])) continue;
5694
6552
  faceChars.set(block.style.fontName, (_nullishCoalesce(faceChars.get(block.style.fontName), () => ( 0))) + block.text.length);
5695
6553
  }
5696
6554
  const [bodyFace, bodyChars] = _nullishCoalesce([...faceChars].sort((a, b) => b[1] - a[1])[0], () => ( []));
5697
6555
  if (!bodyFace || !bodyChars || bodyChars < 300) return;
5698
6556
  for (let i = 0; i < blocks.length; i++) {
5699
6557
  const block = blocks[i];
5700
- const text = _nullishCoalesce(_optionalChain([block, 'access', _277 => _277.text, 'optionalAccess', _278 => _278.trim, 'call', _279 => _279()]), () => ( ""));
6558
+ const text = _nullishCoalesce(_optionalChain([block, 'access', _284 => _284.text, 'optionalAccess', _285 => _285.trim, 'call', _286 => _286()]), () => ( ""));
5701
6559
  if (block.type === "heading" && /(?:https?:\/\/|www\.|^arxiv:|^doi:)/i.test(text)) {
5702
6560
  block.type = "paragraph";
5703
6561
  block.level = void 0;
5704
6562
  continue;
5705
6563
  }
5706
6564
  const box = block.bbox, style = block.style;
5707
- if (block.type !== "paragraph" || !box || !_optionalChain([style, 'optionalAccess', _280 => _280.fontName]) || !style.fontSize || style.fontName === bodyFace || (_nullishCoalesce(faceChars.get(style.fontName), () => ( 0))) > bodyChars * 0.25 || text.length < 3 || text.length > 70 || text.includes("\n") || box.height > style.fontSize * 1.6 || /^(?:table|figure|fig\.?|source|doi:|arxiv:|https?:|www\.|[•●○▪▫⮚*∗†])/i.test(text) || /(?:https?:\/\/|www\.|@|[=¼≪þ])/i.test(text) || /^definition\s+\d+[.:]?\s+.*\b(?:is|are|means)\b/i.test(text) || /^[\d\s.,:%+\-–]+$/.test(text)) continue;
6565
+ if (block.type !== "paragraph" || !box || !_optionalChain([style, 'optionalAccess', _287 => _287.fontName]) || !style.fontSize || style.fontName === bodyFace || (_nullishCoalesce(faceChars.get(style.fontName), () => ( 0))) > bodyChars * 0.25 || text.length < 3 || text.length > 70 || text.includes("\n") || box.height > style.fontSize * 1.6 || /^(?:table|figure|fig\.?|source|doi:|arxiv:|https?:|www\.|[•●○▪▫⮚*∗†])/i.test(text) || /(?:https?:\/\/|www\.|@|[=¼≪þ])/i.test(text) || /^definition\s+\d+[.:]?\s+.*\b(?:is|are|means)\b/i.test(text) || /^[\d\s.,:%+\-–]+$/.test(text)) continue;
5708
6566
  const previous = blocks[i - 1], next = blocks[i + 1];
5709
- const pb = _optionalChain([previous, 'optionalAccess', _281 => _281.bbox]), nb = _optionalChain([next, 'optionalAccess', _282 => _282.bbox]);
5710
- if (!pb || !nb || previous.pageNumber !== block.pageNumber || next.pageNumber !== block.pageNumber || previous.type !== "paragraph" && previous.type !== "heading" || next.type !== "paragraph" || _optionalChain([next, 'access', _283 => _283.style, 'optionalAccess', _284 => _284.fontName]) !== bodyFace || !next.text || next.text.length < 40 || style.fontSize < (_nullishCoalesce(next.style.fontSize, () => ( 0))) * 0.95 || pb.y - (box.y + box.height) < style.fontSize * 0.5 || box.y - (nb.y + nb.height) < 0 || box.y - (nb.y + nb.height) > style.fontSize * 2 || box.x + box.width / 2 < nb.x - 10 || box.x + box.width / 2 > nb.x + nb.width + 10) continue;
6567
+ const pb = _optionalChain([previous, 'optionalAccess', _288 => _288.bbox]), nb = _optionalChain([next, 'optionalAccess', _289 => _289.bbox]);
6568
+ if (!pb || !nb || previous.pageNumber !== block.pageNumber || next.pageNumber !== block.pageNumber || previous.type !== "paragraph" && previous.type !== "heading" || next.type !== "paragraph" || _optionalChain([next, 'access', _290 => _290.style, 'optionalAccess', _291 => _291.fontName]) !== bodyFace || !next.text || next.text.length < 40 || style.fontSize < (_nullishCoalesce(next.style.fontSize, () => ( 0))) * 0.95 || pb.y - (box.y + box.height) < style.fontSize * 0.5 || box.y - (nb.y + nb.height) < 0 || box.y - (nb.y + nb.height) > style.fontSize * 2 || box.x + box.width / 2 < nb.x - 10 || box.x + box.width / 2 > nb.x + nb.width + 10) continue;
5711
6569
  block.type = "heading";
5712
6570
  block.level = 2;
5713
6571
  }
@@ -5757,7 +6615,7 @@ function detectMarkerHeadings(blocks) {
5757
6615
  block.level = 4;
5758
6616
  continue;
5759
6617
  }
5760
- if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access', _285 => _285.style, 'optionalAccess', _286 => _286.fontSize])) {
6618
+ if (/^[가-힣]{2,6}$/.test(text) && _optionalChain([block, 'access', _292 => _292.style, 'optionalAccess', _293 => _293.fontSize])) {
5761
6619
  const prev = blocks[i - 1];
5762
6620
  const next = blocks[i + 1];
5763
6621
  const prevIsStructural = !prev || prev.type === "table" || prev.type === "heading" || prev.type === "separator";
@@ -5798,7 +6656,7 @@ function detectTableCaptions(blocks) {
5798
6656
  block.table.caption = blocks[i - 1].text.trim();
5799
6657
  blocks.splice(i - 1, 1);
5800
6658
  i--;
5801
- } else if (isCaptionCandidate(blocks[i + 1], block) && _optionalChain([blocks, 'access', _287 => _287[i + 2], 'optionalAccess', _288 => _288.type]) !== "table") {
6659
+ } else if (isCaptionCandidate(blocks[i + 1], block) && _optionalChain([blocks, 'access', _294 => _294[i + 2], 'optionalAccess', _295 => _295.type]) !== "table") {
5802
6660
  const cap = blocks[i + 1].bbox, tbl = block.bbox;
5803
6661
  block.table.caption = blocks[i + 1].text.trim();
5804
6662
  if (cap && tbl && cap.y + cap.height <= tbl.y + 1) block.table.captionBelow = true;
@@ -6036,7 +6894,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
6036
6894
  const bottomEntries = [];
6037
6895
  for (let bi = 0; bi < blocks.length; bi++) {
6038
6896
  const b = blocks[bi];
6039
- const text = !tables ? _optionalChain([b, 'access', _289 => _289.text, 'optionalAccess', _290 => _290.trim, 'call', _291 => _291()]) : b.type === "table" && b.table ? b.table.cells.flat().map((c) => c.text.trim()).filter(Boolean).join(" | ") : void 0;
6897
+ const text = !tables ? _optionalChain([b, 'access', _296 => _296.text, 'optionalAccess', _297 => _297.trim, 'call', _298 => _298()]) : b.type === "table" && b.table ? b.table.cells.flat().map((c) => c.text.trim()).filter(Boolean).join(" | ") : void 0;
6040
6898
  if (!b.bbox || !b.pageNumber || !text) continue;
6041
6899
  const ph = pageHeights.get(b.bbox.page) || pageHeights.get(b.pageNumber);
6042
6900
  if (!ph) continue;
@@ -6069,7 +6927,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
6069
6927
  for (const [p, count] of patternCount) {
6070
6928
  const pages = [..._nullishCoalesce(patternPages.get(p), () => ( []))];
6071
6929
  const span2 = pages.length ? Math.max(...pages) - Math.min(...pages) + 1 : 0;
6072
- const varying = !tables && (_nullishCoalesce(_optionalChain([patternNumbers, 'access', _292 => _292.get, 'call', _293 => _293(p), 'optionalAccess', _294 => _294.size]), () => ( 0))) > 1;
6930
+ const varying = !tables && (_nullishCoalesce(_optionalChain([patternNumbers, 'access', _299 => _299.get, 'call', _300 => _300(p), 'optionalAccess', _301 => _301.size]), () => ( 0))) > 1;
6073
6931
  const occ = _nullishCoalesce(patternOcc.get(p), () => ( []));
6074
6932
  const dense = pages.length >= span2 * 0.4;
6075
6933
  const loose = looseVaryingNumber(occ, entries === topEntries) && (entries === bottomEntries || dense || tracksPages(occ));
@@ -6081,8 +6939,8 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
6081
6939
  for (const e of entries) {
6082
6940
  const norm = e.text.replace(/\d+/g, "#");
6083
6941
  if (!repeatedPatterns.has(norm)) continue;
6084
- const noteMark = _optionalChain([e, 'access', _295 => _295.text, 'access', _296 => _296.match, 'call', _297 => _297(/^\d{1,3}\)/), 'optionalAccess', _298 => _298[0]]);
6085
- if (noteMark && _optionalChain([notes, 'optionalAccess', _299 => _299.get, 'call', _300 => _300(e.page), 'optionalAccess', _301 => _301.marks, 'access', _302 => _302.some, 'call', _303 => _303((m) => m.mark === noteMark)])) continue;
6942
+ const noteMark = _optionalChain([e, 'access', _302 => _302.text, 'access', _303 => _303.match, 'call', _304 => _304(/^\d{1,3}\)/), 'optionalAccess', _305 => _305[0]]);
6943
+ if (noteMark && _optionalChain([notes, 'optionalAccess', _306 => _306.get, 'call', _307 => _307(e.page), 'optionalAccess', _308 => _308.marks, 'access', _309 => _309.some, 'call', _310 => _310((m) => m.mark === noteMark)])) continue;
6086
6944
  const cand = blocks[e.blockIdx];
6087
6945
  const cb = cand.bbox;
6088
6946
  const tableNote = /^(?:주\s*(?:\d+\s*[).:]|[::])|(?:자료|출처)\s*[::]|\*\s+\S)/.test(e.text.replace(/ \| /g, " ")) && blocks.some((o) => {
@@ -6096,7 +6954,7 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings, notes, tables =
6096
6954
  if (bi === e.blockIdx) continue;
6097
6955
  const o = blocks[bi];
6098
6956
  if (!o.bbox || o.bbox.page !== cb.page) continue;
6099
- const oNorm = _optionalChain([o, 'access', _304 => _304.text, 'optionalAccess', _305 => _305.trim, 'call', _306 => _306(), 'access', _307 => _307.replace, 'call', _308 => _308(/\d+/g, "#")]);
6957
+ const oNorm = _optionalChain([o, 'access', _311 => _311.text, 'optionalAccess', _312 => _312.trim, 'call', _313 => _313(), 'access', _314 => _314.replace, 'call', _315 => _315(/\d+/g, "#")]);
6100
6958
  if (oNorm && repeatedPatterns.has(oNorm)) continue;
6101
6959
  const overlap2 = Math.min(cb.y + cb.height, o.bbox.y + o.bbox.height) - Math.max(cb.y, o.bbox.y);
6102
6960
  if (overlap2 >= cb.height * 0.5) {
@@ -6224,7 +7082,7 @@ function recordRowRules(table, cells, bbox, hs) {
6224
7082
  function markImageCell(cell) {
6225
7083
  IMAGE_CELLS.add(cell);
6226
7084
  }
6227
- var emptyCell = (cell) => !cell || !_optionalChain([cell, 'access', _309 => _309.text, 'optionalAccess', _310 => _310.trim, 'call', _311 => _311()]) && !_optionalChain([cell, 'access', _312 => _312.blocks, 'optionalAccess', _313 => _313.length]) && !IMAGE_CELLS.has(cell);
7085
+ var emptyCell = (cell) => !cell || !_optionalChain([cell, 'access', _316 => _316.text, 'optionalAccess', _317 => _317.trim, 'call', _318 => _318()]) && !_optionalChain([cell, 'access', _319 => _319.blocks, 'optionalAccess', _320 => _320.length]) && !IMAGE_CELLS.has(cell);
6228
7086
  function trimTable(table) {
6229
7087
  let cols = table.cols;
6230
7088
  while (cols > 0 && table.cells.every((row) => emptyCell(row[cols - 1]))) cols--;
@@ -6240,7 +7098,7 @@ function trimTable(table) {
6240
7098
  function trimTrailingEmptyTableCols(blocks) {
6241
7099
  for (const b of blocks) {
6242
7100
  if (b.type !== "table" || !b.table) continue;
6243
- for (const row of b.table.cells) for (const cell of row) if (_optionalChain([cell, 'access', _314 => _314.blocks, 'optionalAccess', _315 => _315.length])) trimTrailingEmptyTableCols(cell.blocks);
7101
+ for (const row of b.table.cells) for (const cell of row) if (_optionalChain([cell, 'access', _321 => _321.blocks, 'optionalAccess', _322 => _322.length])) trimTrailingEmptyTableCols(cell.blocks);
6244
7102
  trimTable(b.table);
6245
7103
  }
6246
7104
  }
@@ -6260,7 +7118,7 @@ function mergeSliverColumns(grid, colXs, maxWidth) {
6260
7118
  }
6261
7119
  const ok = owner.every((row) => {
6262
7120
  const o = row[c];
6263
- return !!o && (o.colSpan > 1 || !o.text.trim() && !_optionalChain([o, 'access', _316 => _316.blocks, 'optionalAccess', _317 => _317.length]));
7121
+ return !!o && (o.colSpan > 1 || !o.text.trim() && !_optionalChain([o, 'access', _323 => _323.blocks, 'optionalAccess', _324 => _324.length]));
6264
7122
  });
6265
7123
  if (!ok) continue;
6266
7124
  const spanning = /* @__PURE__ */ new Set();
@@ -6287,7 +7145,7 @@ var multiply = (m, t) => [
6287
7145
  m[1] * t[4] + m[3] * t[5] + m[5]
6288
7146
  ];
6289
7147
  function hollowCircle(image) {
6290
- if (!_optionalChain([image, 'optionalAccess', _318 => _318.data]) || image.width < 16 || image.width > 128 || image.height < 16 || image.height > 128 || Math.abs(image.width - image.height) > Math.min(image.width, image.height) * 0.1) return false;
7148
+ if (!_optionalChain([image, 'optionalAccess', _325 => _325.data]) || image.width < 16 || image.width > 128 || image.height < 16 || image.height > 128 || Math.abs(image.width - image.height) > Math.min(image.width, image.height) * 0.1) return false;
6291
7149
  const stride = image.kind === _pdfmjs.ImageKind.RGB_24BPP ? 3 : image.kind === _pdfmjs.ImageKind.RGBA_32BPP ? 4 : 0;
6292
7150
  const { width, height, data } = image;
6293
7151
  if (!stride || data.length < width * height * stride) return false;
@@ -6352,9 +7210,9 @@ function smallVisibleImagePaints(fnArray, argsArray) {
6352
7210
  const op = fnArray[i], args = argsArray[i];
6353
7211
  if (op === _pdfmjs.OPS.save || op === _pdfmjs.OPS.paintFormXObjectBegin) {
6354
7212
  stack.push({ ctm, alpha, clip, unknownClip });
6355
- const matrix = op === _pdfmjs.OPS.paintFormXObjectBegin ? _optionalChain([args, 'optionalAccess', _319 => _319[0]]) : void 0;
7213
+ const matrix = op === _pdfmjs.OPS.paintFormXObjectBegin ? _optionalChain([args, 'optionalAccess', _326 => _326[0]]) : void 0;
6356
7214
  if (Array.isArray(matrix) && matrix.length >= 6) ctm = multiply(ctm, matrix);
6357
- const bounds = op === _pdfmjs.OPS.paintFormXObjectBegin ? _optionalChain([args, 'optionalAccess', _320 => _320[1]]) : void 0;
7215
+ const bounds = op === _pdfmjs.OPS.paintFormXObjectBegin ? _optionalChain([args, 'optionalAccess', _327 => _327[1]]) : void 0;
6358
7216
  if (Array.isArray(bounds) && bounds.length === 4) {
6359
7217
  const box = rectangle(bounds[0], bounds[1], bounds[2] - bounds[0], bounds[3] - bounds[1]);
6360
7218
  if (box && ctm[1] === 0 && ctm[2] === 0) intersectClip(box);
@@ -6362,17 +7220,17 @@ function smallVisibleImagePaints(fnArray, argsArray) {
6362
7220
  }
6363
7221
  } else if (op === _pdfmjs.OPS.restore || op === _pdfmjs.OPS.paintFormXObjectEnd) {
6364
7222
  const state = stack.pop();
6365
- ctm = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _321 => _321.ctm]), () => ( [1, 0, 0, 1, 0, 0]));
6366
- alpha = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _322 => _322.alpha]), () => ( 1));
6367
- clip = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _323 => _323.clip]), () => ( null));
6368
- unknownClip = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _324 => _324.unknownClip]), () => ( false));
7223
+ ctm = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _328 => _328.ctm]), () => ( [1, 0, 0, 1, 0, 0]));
7224
+ alpha = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _329 => _329.alpha]), () => ( 1));
7225
+ clip = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _330 => _330.clip]), () => ( null));
7226
+ unknownClip = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _331 => _331.unknownClip]), () => ( false));
6369
7227
  } else if (op === _pdfmjs.OPS.setGState) {
6370
- for (const [key, value] of _nullishCoalesce(_optionalChain([args, 'optionalAccess', _325 => _325[0]]), () => ( []))) {
7228
+ for (const [key, value] of _nullishCoalesce(_optionalChain([args, 'optionalAccess', _332 => _332[0]]), () => ( []))) {
6371
7229
  if (key === "ca") alpha = typeof value === "number" ? value : 0;
6372
7230
  }
6373
7231
  } else if (op === _pdfmjs.OPS.constructPath) {
6374
7232
  const [operations, coordinates] = args;
6375
- pathRect = pathRect === void 0 && _optionalChain([operations, 'optionalAccess', _326 => _326.length]) === 1 && operations[0] === _pdfmjs.OPS.rectangle && _optionalChain([coordinates, 'optionalAccess', _327 => _327.length]) >= 4 && ctm[1] === 0 && ctm[2] === 0 ? rectangle(coordinates[0], coordinates[1], coordinates[2], coordinates[3]) : null;
7233
+ pathRect = pathRect === void 0 && _optionalChain([operations, 'optionalAccess', _333 => _333.length]) === 1 && operations[0] === _pdfmjs.OPS.rectangle && _optionalChain([coordinates, 'optionalAccess', _334 => _334.length]) >= 4 && ctm[1] === 0 && ctm[2] === 0 ? rectangle(coordinates[0], coordinates[1], coordinates[2], coordinates[3]) : null;
6376
7234
  } else if (op === _pdfmjs.OPS.clip || op === _pdfmjs.OPS.eoClip) pendingClip = true;
6377
7235
  else if ([
6378
7236
  _pdfmjs.OPS.endPath,
@@ -6392,7 +7250,7 @@ function smallVisibleImagePaints(fnArray, argsArray) {
6392
7250
  pendingClip = false;
6393
7251
  pathRect = void 0;
6394
7252
  } else if (op === _pdfmjs.OPS.transform && Array.isArray(args) && args.length >= 6) ctm = multiply(ctm, args);
6395
- else if (op === _pdfmjs.OPS.paintImageXObject && typeof _optionalChain([args, 'optionalAccess', _328 => _328[0]]) === "string") {
7253
+ else if (op === _pdfmjs.OPS.paintImageXObject && typeof _optionalChain([args, 'optionalAccess', _335 => _335[0]]) === "string") {
6396
7254
  if (typeof args[1] !== "number" || typeof args[2] !== "number" || args[1] < 16 || args[1] > 128 || args[2] < 16 || args[2] > 128) continue;
6397
7255
  const box = extractImageRegions([_pdfmjs.OPS.transform, _pdfmjs.OPS.paintImageXObject], [ctm, args])[0];
6398
7256
  if (!box || ctm[1] !== 0 || ctm[2] !== 0 || alpha < 0.99 || unknownClip || clip && (box.x1 + (box.x2 - box.x1) * 0.03 < clip.x1 || box.y1 + (box.y2 - box.y1) * 0.03 < clip.y1 || box.x2 - (box.x2 - box.x1) * 0.03 > clip.x2 || box.y2 - (box.y2 - box.y1) * 0.03 > clip.y2)) continue;
@@ -6411,14 +7269,14 @@ async function restoreImageBullets(items, page, fnArray, argsArray, shapes = /*
6411
7269
  const line = items.filter((item) => !item.isHidden && item.fontSize > 0 && item.x >= box.x2 && item.x - box.x2 <= item.fontSize * 0.7 && Math.abs(item.y + item.h / 2 - (box.y1 + box.y2) / 2) <= item.fontSize * 0.4 && height >= item.fontSize * 0.5 && height <= item.fontSize * 1.2).sort((a, b) => a.x - b.x)[0];
6412
7270
  if (!line || /^[○●•◦□■∙]/.test(line.text.trim()) || !/\p{L}/u.test(line.text)) continue;
6413
7271
  const row = items.filter((item) => Math.abs(item.y - line.y) <= 2 && item.x >= line.x);
6414
- if (row.reduce((n, item) => n + (_nullishCoalesce(_optionalChain([item, 'access', _329 => _329.text, 'access', _330 => _330.match, 'call', _331 => _331(/\p{L}/gu), 'optionalAccess', _332 => _332.length]), () => ( 0))), 0) < 12 || items.some((item) => item !== line && Math.abs(item.y - line.y) <= 2 && item.x < line.x)) continue;
7272
+ if (row.reduce((n, item) => n + (_nullishCoalesce(_optionalChain([item, 'access', _336 => _336.text, 'access', _337 => _337.match, 'call', _338 => _338(/\p{L}/gu), 'optionalAccess', _339 => _339.length]), () => ( 0))), 0) < 12 || items.some((item) => item !== line && Math.abs(item.y - line.y) <= 2 && item.x < line.x)) continue;
6415
7273
  candidates.push({ id, x: box.x1, width, line });
6416
7274
  }
6417
7275
  let restored = 0;
6418
7276
  const used = /* @__PURE__ */ new Set();
6419
7277
  for (const candidate of candidates) {
6420
7278
  const same = candidates.filter((other) => other.id === candidate.id && other.line !== candidate.line && Math.abs(other.line.x - candidate.line.x) <= 1 && Math.abs(other.x - candidate.x) <= 1 && Math.abs(other.width - candidate.width) <= 1 && other.line.fontSize === candidate.line.fontSize && Math.abs(other.line.y - candidate.line.y) >= candidate.line.fontSize * 2);
6421
- const numbered = items.filter((item) => !item.isHidden && /^[①-⑮]\s*/.test(item.text.trim()) && item.fontName === candidate.line.fontName && item.fontSize === candidate.line.fontSize && Math.abs(item.x - candidate.x) <= 1 && (_nullishCoalesce(_optionalChain([item, 'access', _333 => _333.text, 'access', _334 => _334.match, 'call', _335 => _335(/\p{L}/gu), 'optionalAccess', _336 => _336.length]), () => ( 0))) >= 12).sort((a, b) => b.y - a.y);
7279
+ const numbered = items.filter((item) => !item.isHidden && /^[①-⑮]\s*/.test(item.text.trim()) && item.fontName === candidate.line.fontName && item.fontSize === candidate.line.fontSize && Math.abs(item.x - candidate.x) <= 1 && (_nullishCoalesce(_optionalChain([item, 'access', _340 => _340.text, 'access', _341 => _341.match, 'call', _342 => _342(/\p{L}/gu), 'optionalAccess', _343 => _343.length]), () => ( 0))) >= 12).sort((a, b) => b.y - a.y);
6422
7280
  const numberedList = numbered.some((item, index) => index > 0 && item.text.trim().charCodeAt(0) === numbered[index - 1].text.trim().charCodeAt(0) + 1);
6423
7281
  if (!same.length && !numberedList || used.has(candidate.line)) continue;
6424
7282
  if (!shapes.has(candidate.id)) shapes.set(candidate.id, hollowCircle(await resolveImagePixels(page, candidate.id)));
@@ -6484,7 +7342,7 @@ function groupFlowBoxUnits(blocks, grids, hs, vs, images) {
6484
7342
  return units;
6485
7343
  }
6486
7344
  function arrowDirection(image) {
6487
- if (!_optionalChain([image, 'optionalAccess', _337 => _337.data]) || image.width < 16 || image.width > 128 || image.height < 16 || image.height > 128) return 0;
7345
+ if (!_optionalChain([image, 'optionalAccess', _344 => _344.data]) || image.width < 16 || image.width > 128 || image.height < 16 || image.height > 128) return 0;
6488
7346
  const { width, height, data } = image;
6489
7347
  const stride = image.kind === _pdfmjs.ImageKind.RGB_24BPP ? 3 : image.kind === _pdfmjs.ImageKind.RGBA_32BPP ? 4 : 0;
6490
7348
  if (!stride || data.length < width * height * stride) return 0;
@@ -6552,7 +7410,7 @@ function isSideTabTable(box, table, others, pageWidth, pageHeight) {
6552
7410
  function removeSideTabs(blocks, pageWidths) {
6553
7411
  const edges = /* @__PURE__ */ new Map();
6554
7412
  for (const b of blocks) {
6555
- if (!b.bbox || b.pageNumber === void 0 || [..._nullishCoalesce(_optionalChain([b, 'access', _338 => _338.text, 'optionalAccess', _339 => _339.trim, 'call', _340 => _340()]), () => ( ""))].length <= MAX_CHARS) continue;
7413
+ if (!b.bbox || b.pageNumber === void 0 || [..._nullishCoalesce(_optionalChain([b, 'access', _345 => _345.text, 'optionalAccess', _346 => _346.trim, 'call', _347 => _347()]), () => ( ""))].length <= MAX_CHARS) continue;
6556
7414
  const e = _nullishCoalesce(edges.get(b.pageNumber), () => ( { lefts: [], rights: [] }));
6557
7415
  e.lefts.push(b.bbox.x);
6558
7416
  e.rights.push(b.bbox.x + b.bbox.width);
@@ -6568,7 +7426,7 @@ function removeSideTabs(blocks, pageWidths) {
6568
7426
  const fallback = all.length ? { left: q(all.map((e) => e.left), 0.5), right: q(all.map((e) => e.right), 0.5) } : void 0;
6569
7427
  const key = (b) => {
6570
7428
  const w = b.pageNumber !== void 0 ? pageWidths.get(b.pageNumber) : void 0;
6571
- const text = _optionalChain([b, 'access', _341 => _341.text, 'optionalAccess', _342 => _342.trim, 'call', _343 => _343()]);
7429
+ const text = _optionalChain([b, 'access', _348 => _348.text, 'optionalAccess', _349 => _349.trim, 'call', _350 => _350()]);
6572
7430
  const area = _nullishCoalesce((b.pageNumber !== void 0 ? body.get(b.pageNumber) : void 0), () => ( fallback));
6573
7431
  if (b.type === "table") {
6574
7432
  if (!w || !b.bbox || !b.table || !SIDE_TAB_TABLES.has(b.table)) return null;
@@ -7004,16 +7862,16 @@ function isProseSpread(items) {
7004
7862
  for (let i = 1; i < sorted.length; i++) {
7005
7863
  gaps.push(sorted[i].x - (sorted[i - 1].x + sorted[i - 1].w));
7006
7864
  }
7007
- const maxGap = _chunk2JDVPQ33cjs.safeMax.call(void 0, gaps);
7865
+ const maxGap = _chunkC3BOYTY5cjs.safeMax.call(void 0, gaps);
7008
7866
  const avgLen = items.reduce((s, i) => s + i.text.length, 0) / items.length;
7009
7867
  if (items.length >= 4 && maxGap < 40 && avgLen < 5) return true;
7010
- const minGap = _chunk2JDVPQ33cjs.safeMin.call(void 0, gaps);
7868
+ const minGap = _chunkC3BOYTY5cjs.safeMin.call(void 0, gaps);
7011
7869
  return minGap > 0 && maxGap - minGap <= Math.max(2, maxGap * 0.15) && (items.filter((i) => /^\P{L}*\p{Ll}/u.test(i.text)).length * 2 >= items.length || items.some((i) => /\p{L}[,.;:]["”’)]?$/u.test(i.text)));
7012
7870
  }
7013
7871
  function detectColumns(yLines) {
7014
7872
  const allItems = yLines.flat();
7015
7873
  if (allItems.length === 0) return null;
7016
- const pageWidth = _chunk2JDVPQ33cjs.safeMax.call(void 0, allItems.map((i) => i.x + i.w)) - _chunk2JDVPQ33cjs.safeMin.call(void 0, allItems.map((i) => i.x));
7874
+ const pageWidth = _chunkC3BOYTY5cjs.safeMax.call(void 0, allItems.map((i) => i.x + i.w)) - _chunkC3BOYTY5cjs.safeMin.call(void 0, allItems.map((i) => i.x));
7017
7875
  if (pageWidth < 100) return null;
7018
7876
  let bigoLineIdx = -1;
7019
7877
  for (let i = 0; i < yLines.length; i++) {
@@ -7238,7 +8096,7 @@ var UNDER_BOX_PAIR_MAX_EM = 2.2;
7238
8096
  var UNDER_BOX_PAIR_OVERLAP = 0.8;
7239
8097
  function markUnderlineItems(items, horizontals, verticals, nonRules) {
7240
8098
  const underlines = [];
7241
- if (_optionalChain([nonRules, 'optionalAccess', _344 => _344.size])) horizontals = horizontals.filter((line) => !nonRules.has(line));
8099
+ if (_optionalChain([nonRules, 'optionalAccess', _351 => _351.size])) horizontals = horizontals.filter((line) => !nonRules.has(line));
7242
8100
  if (items.length === 0 || horizontals.length === 0) return underlines;
7243
8101
  const tightOwners = /* @__PURE__ */ new Map();
7244
8102
  const tightlyOwned = (line) => {
@@ -7344,7 +8202,7 @@ function hasBoxTopPair(line, maxH, horizontals, cellItems) {
7344
8202
  if (ow <= 0) continue;
7345
8203
  const overlap2 = Math.min(line.x2, o.x2) - Math.max(line.x1, o.x1);
7346
8204
  if (overlap2 / Math.max(w, ow) < UNDER_BOX_PAIR_OVERLAP) continue;
7347
- const covered = _nullishCoalesce(_optionalChain([cellItems, 'optionalAccess', _345 => _345.reduce, 'call', _346 => _346((sum, item) => {
8205
+ const covered = _nullishCoalesce(_optionalChain([cellItems, 'optionalAccess', _352 => _352.reduce, 'call', _353 => _353((sum, item) => {
7348
8206
  const below = item.y - o.y1;
7349
8207
  if (below < 0.5 || below > 3 || !item.text.trim()) return sum;
7350
8208
  return sum + Math.max(0, Math.min(o.x2, item.x + item.w) - Math.max(o.x1, item.x));
@@ -7411,13 +8269,13 @@ function partTex(group) {
7411
8269
  const base = Math.min(...g.filter((i) => i.fontSize >= size * SCRIPT_SIZE_RATIO).map((i) => i.y));
7412
8270
  let s = "", run = "";
7413
8271
  const flush = () => {
7414
- if (run) s += _chunkAM5ALISVcjs.toTex.call(void 0, run);
8272
+ if (run) s += _chunkNW2CKOFLcjs.toTex.call(void 0, run);
7415
8273
  run = "";
7416
8274
  };
7417
8275
  g.forEach((it, k) => {
7418
8276
  if (it.fontSize < size * SCRIPT_SIZE_RATIO && it.y - base >= size * SCRIPT_RISE_EM) {
7419
8277
  flush();
7420
- s += `^{${_chunkAM5ALISVcjs.toTex.call(void 0, it.text)}}`;
8278
+ s += `^{${_chunkNW2CKOFLcjs.toTex.call(void 0, it.text)}}`;
7421
8279
  return;
7422
8280
  }
7423
8281
  if (k && it.x - (g[k - 1].x + g[k - 1].w) > spaceGapThreshold(it.fontSize)) run += " ";
@@ -7589,12 +8447,12 @@ function rebuildUnitLine(items, grid) {
7589
8447
  function prependUnitRow(cells, cols, line, usedItems) {
7590
8448
  const text = cleanCellText(line.map((item) => item.text).join(""));
7591
8449
  cells.unshift(Array.from({ length: cols }, (_, c) => ({ text: c === 0 ? text : "", colSpan: c === 0 ? cols : 1, rowSpan: 1 })));
7592
- for (const cell of cells[0]) _chunkAM5ALISVcjs.CELL_EDGES.set(cell, NO_EDGES);
8450
+ for (const cell of cells[0]) _chunkNW2CKOFLcjs.CELL_EDGES.set(cell, NO_EDGES);
7593
8451
  for (const item of line) usedItems.add(item);
7594
8452
  }
7595
8453
  function attachUnitRow(items, grid, cells, cols, usedItems) {
7596
8454
  const all = cells.flat();
7597
- if (all.filter((c) => c.text.trim()).length * 2 < all.length || UNIT.test(_nullishCoalesce(_optionalChain([cells, 'access', _347 => _347[0], 'optionalAccess', _348 => _348[0], 'optionalAccess', _349 => _349.text]), () => ( "")))) return false;
8455
+ if (all.filter((c) => c.text.trim()).length * 2 < all.length || UNIT.test(_nullishCoalesce(_optionalChain([cells, 'access', _354 => _354[0], 'optionalAccess', _355 => _355[0], 'optionalAccess', _356 => _356.text]), () => ( "")))) return false;
7598
8456
  const above = items.filter((it) => !usedItems.has(it) && it.y >= grid.bbox.y2 && it.y - grid.bbox.y2 <= 8 && it.x >= grid.bbox.x1 - 3 && it.x + it.w <= grid.bbox.x2 + 3);
7599
8457
  let nearest = Infinity;
7600
8458
  for (const it of above) nearest = Math.min(nearest, it.y);
@@ -7629,7 +8487,7 @@ function closeShadedTableEdges(clipGrids, horizontals, verticals, fillRects) {
7629
8487
  let hs = horizontals, vs = verticals;
7630
8488
  const restored = [];
7631
8489
  for (const grid of clipGrids) {
7632
- if (grid.clipParent || grid.rowYs.length !== 2 || grid.colXs.length < 3 || !_optionalChain([grid, 'access', _350 => _350.cells, 'optionalAccess', _351 => _351.length]) || grid.cells.some((c) => c.filler || c.rowSpan !== 1 || c.colSpan !== 1)) continue;
8490
+ if (grid.clipParent || grid.rowYs.length !== 2 || grid.colXs.length < 3 || !_optionalChain([grid, 'access', _357 => _357.cells, 'optionalAccess', _358 => _358.length]) || grid.cells.some((c) => c.filler || c.rowSpan !== 1 || c.colSpan !== 1)) continue;
7633
8491
  const { x1, x2, y1: mid, y2: top } = grid.bbox;
7634
8492
  if (!grid.cells.every((c) => fillRects.some((f) => near2(f.x1, c.bbox.x1) && near2(f.x2, c.bbox.x2) && near2(f.y1, c.bbox.y1) && near2(f.y2, c.bbox.y2)))) continue;
7635
8493
  const topRule = hs.find((h) => near2(h.y1, top) && near2(h.x1, x1) && near2(h.x2, x2));
@@ -8093,7 +8951,7 @@ function takeFrameSpanningText(items, cutX, pageNum, lex) {
8093
8951
  const rows = groupByY([...items].sort((a, b) => b.y - a.y || a.x - b.x)).map((line) => {
8094
8952
  const runs = [];
8095
8953
  for (const item of [...line].sort((a, b) => a.x - b.x)) {
8096
- const run = runs[runs.length - 1], prev = _optionalChain([run, 'optionalAccess', _352 => _352[run.length - 1]]);
8954
+ const run = runs[runs.length - 1], prev = _optionalChain([run, 'optionalAccess', _359 => _359[run.length - 1]]);
8097
8955
  if (prev && item.x - (prev.x + prev.w) <= Math.max(prev.fontSize, item.fontSize) * 0.6) run.push(item);
8098
8956
  else runs.push([item]);
8099
8957
  }
@@ -8137,7 +8995,7 @@ function groupFrameParagraphUnits(units, frames) {
8137
8995
  for (const unit of units) for (const block of unit) source.set(block, unit);
8138
8996
  const members = /* @__PURE__ */ new Map(), emitted = /* @__PURE__ */ new Set();
8139
8997
  for (const frame of frames) {
8140
- if (frame.length < 2 || frame.some((block) => block.type !== "paragraph" || _optionalChain([source, 'access', _353 => _353.get, 'call', _354 => _354(block), 'optionalAccess', _355 => _355.length]) !== 1)) continue;
8998
+ if (frame.length < 2 || frame.some((block) => block.type !== "paragraph" || _optionalChain([source, 'access', _360 => _360.get, 'call', _361 => _361(block), 'optionalAccess', _362 => _362.length]) !== 1)) continue;
8141
8999
  for (const block of frame) members.set(block, frame);
8142
9000
  }
8143
9001
  const out = [];
@@ -8150,7 +9008,7 @@ function groupFrameParagraphUnits(units, frames) {
8150
9008
  }
8151
9009
  }
8152
9010
  for (const unit of out) {
8153
- if (unit.length < 2 || _optionalChain([FRAME_READING_UNITS, 'access', _356 => _356.get, 'call', _357 => _357(unit[0]), 'optionalAccess', _358 => _358.blocks]) === unit) continue;
9011
+ if (unit.length < 2 || _optionalChain([FRAME_READING_UNITS, 'access', _363 => _363.get, 'call', _364 => _364(unit[0]), 'optionalAccess', _365 => _365.blocks]) === unit) continue;
8154
9012
  const bs = unit.map((b) => b.bbox).filter((b) => !!b);
8155
9013
  if (bs.length !== unit.length) continue;
8156
9014
  const x = Math.min(...bs.map((b) => b.x)), y = Math.min(...bs.map((b) => b.y));
@@ -8167,14 +9025,14 @@ function groupFrameParagraphUnits(units, frames) {
8167
9025
  function recordFrameTitle(table, source, pageNum) {
8168
9026
  if (!CLIP_TABLES.has(table) || table.rows !== 1 || table.cols !== 3 || source.length < 2) return;
8169
9027
  const cells = table.cells[0];
8170
- if (cells.length !== 3 || cells.some((c) => c.colSpan !== 1 || c.rowSpan !== 1 || _optionalChain([c, 'access', _359 => _359.blocks, 'optionalAccess', _360 => _360.length]) || c.text.includes("\n"))) return;
9028
+ if (cells.length !== 3 || cells.some((c) => c.colSpan !== 1 || c.rowSpan !== 1 || _optionalChain([c, 'access', _366 => _366.blocks, 'optionalAccess', _367 => _367.length]) || c.text.includes("\n"))) return;
8171
9029
  const [label, spacer, title] = cells;
8172
9030
  if (!/^(?:붙임|별첨|첨부|부록)\s*\d{1,3}$/.test(label.text.trim()) || spacer.text.trim() || !title.text.trim()) return;
8173
9031
  if (cells.some((c) => {
8174
- const e = _chunkAM5ALISVcjs.CELL_EDGES.get(c);
9032
+ const e = _chunkNW2CKOFLcjs.CELL_EDGES.get(c);
8175
9033
  return !e || e.t || e.b || e.l || e.r;
8176
9034
  })) return;
8177
- const xs = TABLE_COLXS.get(table), style = dominantStyle(source), fs = _nullishCoalesce(_optionalChain([style, 'optionalAccess', _361 => _361.fontSize]), () => ( 0));
9035
+ const xs = TABLE_COLXS.get(table), style = dominantStyle(source), fs = _nullishCoalesce(_optionalChain([style, 'optionalAccess', _368 => _368.fontSize]), () => ( 0));
8178
9036
  if (!xs || xs.length !== 4 || fs <= 0) return;
8179
9037
  const width = xs[3] - xs[0], gap = xs[2] - xs[1];
8180
9038
  if (width < fs * 12 || gap <= 0 || gap > fs * 1.5 || xs[1] - xs[0] > width * 0.25 || xs[3] - xs[2] < width * 0.6) return;
@@ -8232,7 +9090,7 @@ function extendNestedShadedHeaders(clipGrids, lineGrids, horizontals, verticals,
8232
9090
  const extended = [];
8233
9091
  for (let i = 0; i < clipGrids.length; i++) {
8234
9092
  const c = clipGrids[i], parent = c.clipParent;
8235
- if (!parent || c.rowYs.length !== 2 || c.colXs.length < 3 || !_optionalChain([c, 'access', _362 => _362.cells, 'optionalAccess', _363 => _363.length]) || c.cells.some((cell) => cell.filler || cell.rowSpan !== 1 || cell.colSpan !== 1)) continue;
9093
+ if (!parent || c.rowYs.length !== 2 || c.colXs.length < 3 || !_optionalChain([c, 'access', _369 => _369.cells, 'optionalAccess', _370 => _370.length]) || c.cells.some((cell) => cell.filler || cell.rowSpan !== 1 || cell.colSpan !== 1)) continue;
8236
9094
  if (!clipGrids.some((g) => g.rowYs.length === 2 && g.colXs.length === 2 && near2(g.bbox.x1, parent.x1) && near2(g.bbox.x2, parent.x2) && near2(g.bbox.y1, parent.y1) && near2(g.bbox.y2, parent.y2))) continue;
8237
9095
  if (!c.cells.every((cell) => fills.some((f) => near2(f.x1, cell.bbox.x1) && near2(f.x2, cell.bbox.x2) && near2(f.y1, cell.bbox.y1) && near2(f.y2, cell.bbox.y2)))) continue;
8238
9096
  const host = lineGrids.find((l) => l.rowYs.length > 2 && l.colXs.length === c.colXs.length && c.colXs.every((x, k) => near2(x, l.colXs[k])) && c.rowYs.every((y, k) => near2(y, l.rowYs[k])) && contains4(parent, l.bbox) && l.rowYs.every((y) => horizontals.some((h) => near2(h.y1, y) && near2(h.x1, l.bbox.x1) && near2(h.x2, l.bbox.x2))) && l.colXs.every((x) => verticals.some((v) => near2(v.x1, x) && v.y1 <= l.bbox.y1 + 1.5 && v.y2 >= l.bbox.y2 - 1.5)) && !clipGrids.some((o) => o !== c && !contains4(o.bbox, l.bbox) && Math.min(o.bbox.x2, l.bbox.x2) > Math.max(o.bbox.x1, l.bbox.x1) && Math.min(o.bbox.y2, l.bbox.y2) > Math.max(o.bbox.y1, l.bbox.y1)));
@@ -8255,7 +9113,7 @@ function attachSideTabBlocks(tab, body, pageNum) {
8255
9113
  bbox: computeBBox(items, pageNum),
8256
9114
  style: dominantStyle(items)
8257
9115
  });
8258
- const prefix = ordered.filter((g) => !_optionalChain([caps, 'optionalAccess', _364 => _364.has, 'call', _365 => _365(g)])).map((g) => ({
9116
+ const prefix = ordered.filter((g) => !_optionalChain([caps, 'optionalAccess', _371 => _371.has, 'call', _372 => _372(g)])).map((g) => ({
8259
9117
  type: "paragraph",
8260
9118
  text: g.text.trim(),
8261
9119
  pageNumber: pageNum,
@@ -8264,7 +9122,7 @@ function attachSideTabBlocks(tab, body, pageNum) {
8264
9122
  }));
8265
9123
  const groups = /* @__PURE__ */ new Map();
8266
9124
  for (const g of ordered) {
8267
- const cap = _optionalChain([caps, 'optionalAccess', _366 => _366.get, 'call', _367 => _367(g)]);
9125
+ const cap = _optionalChain([caps, 'optionalAccess', _373 => _373.get, 'call', _374 => _374(g)]);
8268
9126
  if (cap) groups.set(cap, [..._nullishCoalesce(groups.get(cap), () => ( [])), g]);
8269
9127
  }
8270
9128
  for (const [cap, glyphs] of groups) {
@@ -8298,7 +9156,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
8298
9156
  const filled = fillBlanks(items, horizontals, verticals);
8299
9157
  items = filled.items;
8300
9158
  horizontals = filled.horizontals;
8301
- const prevPage = _optionalChain([carry, 'optionalAccess', _368 => _368.page]) === pageNum - 1 ? carry.clip : void 0;
9159
+ const prevPage = _optionalChain([carry, 'optionalAccess', _375 => _375.page]) === pageNum - 1 ? carry.clip : void 0;
8302
9160
  const clipResult = detectTables ? buildClipCellGrids(extracted.clipRects, horizontals, verticals, pageWidth, pageHeight, items.map((it) => ({ x: it.x + it.w / 2, y: it.y + it.h / 2 })), extracted.fillRects, prevPage) : { grids: [], containers: [], page: void 0 };
8303
9161
  if (carry) {
8304
9162
  carry.page = pageNum;
@@ -8555,14 +9413,14 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
8555
9413
  if (!assignedItems.has(textItems[ti])) usedItems.delete(owners[ti]);
8556
9414
  }
8557
9415
  }
8558
- if (unitLine.length > 0 && rebuiltUsed && !/^\s*\(\s*단위\s*[::]/.test(_nullishCoalesce(_optionalChain([finalGrid, 'access', _369 => _369[0], 'optionalAccess', _370 => _370[0], 'optionalAccess', _371 => _371.text]), () => ( "")))) {
9416
+ if (unitLine.length > 0 && rebuiltUsed && !/^\s*\(\s*단위\s*[::]/.test(_nullishCoalesce(_optionalChain([finalGrid, 'access', _376 => _376[0], 'optionalAccess', _377 => _377[0], 'optionalAccess', _378 => _378.text]), () => ( "")))) {
8559
9417
  prependUnitRow(finalGrid, numCols, unitLine, usedItems);
8560
9418
  finalRows++;
8561
9419
  }
8562
9420
  if (!rebuiltUsed && attachUnitRow(items, grid, finalGrid, numCols, usedItems)) finalRows++;
8563
9421
  let semanticOneColumn = false;
8564
9422
  if (!grid.cells && !nestedAttached && numCols === 1 && numGridRows >= 2) {
8565
- const populatedRows = finalGrid.filter((row) => _optionalChain([row, 'access', _372 => _372[0], 'optionalAccess', _373 => _373.text, 'access', _374 => _374.trim, 'call', _375 => _375()]));
9423
+ const populatedRows = finalGrid.filter((row) => _optionalChain([row, 'access', _379 => _379[0], 'optionalAccess', _380 => _380.text, 'access', _381 => _381.trim, 'call', _382 => _382()]));
8566
9424
  if (populatedRows.length >= 4) {
8567
9425
  const fontSizes = tableItems.map((item) => item.fontSize).filter((size) => size > 0).sort((a, b) => a - b);
8568
9426
  const medianFont = _nullishCoalesce(fontSizes[Math.floor(fontSizes.length / 2)], () => ( 0));
@@ -8658,7 +9516,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
8658
9516
  height: grid.bbox.y2 - grid.bbox.y1
8659
9517
  };
8660
9518
  if (numRows === 1 && numCols === 1 && gridW < pageWidth * 0.35) {
8661
- const prose = _nullishCoalesce(_optionalChain([finalGrid, 'access', _376 => _376[0], 'optionalAccess', _377 => _377[0], 'optionalAccess', _378 => _378.text]), () => ( ""));
9519
+ const prose = _nullishCoalesce(_optionalChain([finalGrid, 'access', _383 => _383[0], 'optionalAccess', _384 => _384[0], 'optionalAccess', _385 => _385.text]), () => ( ""));
8662
9520
  const besideLines = (side) => new Set(side.map((it) => Math.round(it.y / 3))).size;
8663
9521
  const rightLines = items.filter((it) => it.x >= grid.bbox.x2 + 3 && it.y >= grid.bbox.y1 && it.y <= grid.bbox.y2);
8664
9522
  const leftLines = items.filter((it) => it.x + it.w <= grid.bbox.x1 - 3 && it.y >= grid.bbox.y1 && it.y <= grid.bbox.y2);
@@ -8677,8 +9535,8 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
8677
9535
  }
8678
9536
  }
8679
9537
  if (!grid.cells && !nestedAttached && shouldDemoteTable(irTable)) {
8680
- const paragraphs = numRows === 1 && numCols === 1 ? _optionalChain([irTable, 'access', _379 => _379.cells, 'access', _380 => _380[0], 'optionalAccess', _381 => _381[0], 'optionalAccess', _382 => _382.blocks]) : void 0;
8681
- if (_optionalChain([paragraphs, 'optionalAccess', _383 => _383.length])) {
9538
+ const paragraphs = numRows === 1 && numCols === 1 ? _optionalChain([irTable, 'access', _386 => _386.cells, 'access', _387 => _387[0], 'optionalAccess', _388 => _388[0], 'optionalAccess', _389 => _389.blocks]) : void 0;
9539
+ if (_optionalChain([paragraphs, 'optionalAccess', _390 => _390.length])) {
8682
9540
  blocks.push(...paragraphs);
8683
9541
  frameParagraphUnits.push(paragraphs);
8684
9542
  recordFrameReadingUnit(paragraphs, tableBbox);
@@ -8705,23 +9563,27 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
8705
9563
  let panels = null;
8706
9564
  if (remaining.length > 0) {
8707
9565
  remaining.sort((a, b) => b.y - a.y || a.x - b.x);
8708
- const clusterItems = remaining.map((i) => ({
8709
- text: i.text,
8710
- x: i.x,
8711
- y: i.y,
8712
- w: i.w,
8713
- h: i.h,
8714
- fontSize: i.fontSize,
8715
- fontName: i.fontName,
8716
- hasSpaceBefore: i.hasSpaceBefore,
8717
- syntheticSpace: i.syntheticSpace,
8718
- spaceAfter: i.spaceAfter
8719
- }));
9566
+ const clusterItems = remaining.map((i) => {
9567
+ const item = {
9568
+ text: i.text,
9569
+ x: i.x,
9570
+ y: i.y,
9571
+ w: i.w,
9572
+ h: i.h,
9573
+ fontSize: i.fontSize,
9574
+ fontName: i.fontName,
9575
+ hasSpaceBefore: i.hasSpaceBefore,
9576
+ syntheticSpace: i.syntheticSpace,
9577
+ spaceAfter: i.spaceAfter
9578
+ };
9579
+ copyOcrTextGaps(i, item);
9580
+ return item;
9581
+ });
8720
9582
  const proseColumns = findTwoColumnProseCutX(clusterItems) !== null || detectPersistentColumnGutter(remaining.map((i) => ({ x: i.x, y: i.y, w: i.w, h: i.h > 0 ? i.h : i.fontSize }))) !== null;
8721
9583
  const clusterResults = (proseColumns ? [] : detectClusterTables(clusterItems, pageNum, void 0, lex)).filter((cr) => {
8722
9584
  const b = cr.bbox;
8723
9585
  const overlapX = (x) => Math.min(x.x + x.width, b.x + b.width) - Math.max(x.x, b.x);
8724
- return !blocks.some((x) => x.bbox && x.bbox.y >= b.y - 2 && x.bbox.y + x.bbox.height <= b.y + b.height + 2 && (x.type === "paragraph" ? (_nullishCoalesce(_optionalChain([x, 'access', _384 => _384.text, 'optionalAccess', _385 => _385.match, 'call', _386 => _386(/\p{L}/gu), 'optionalAccess', _387 => _387.length]), () => ( 0))) >= 10 && overlapX(x.bbox) >= 0.8 * b.width : x.type === "table" && !ocrPage && _optionalChain([x, 'access', _388 => _388.table, 'optionalAccess', _389 => _389.cols]) === cr.table.cols && overlapX(x.bbox) >= 0.5 * Math.min(x.bbox.width, b.width)));
9586
+ return !blocks.some((x) => x.bbox && x.bbox.y >= b.y - 2 && x.bbox.y + x.bbox.height <= b.y + b.height + 2 && (x.type === "paragraph" ? (_nullishCoalesce(_optionalChain([x, 'access', _391 => _391.text, 'optionalAccess', _392 => _392.match, 'call', _393 => _393(/\p{L}/gu), 'optionalAccess', _394 => _394.length]), () => ( 0))) >= 10 && overlapX(x.bbox) >= 0.8 * b.width : x.type === "table" && !ocrPage && _optionalChain([x, 'access', _395 => _395.table, 'optionalAccess', _396 => _396.cols]) === cr.table.cols && overlapX(x.bbox) >= 0.5 * Math.min(x.bbox.width, b.width)));
8725
9587
  });
8726
9588
  if (clusterResults.length > 0) {
8727
9589
  const ciToIdx = /* @__PURE__ */ new Map();
@@ -8758,7 +9620,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
8758
9620
  groupSizes.push(1);
8759
9621
  }
8760
9622
  const allY = remaining.map((i) => i.y);
8761
- const pageH = _chunk2JDVPQ33cjs.safeMax.call(void 0, allY) - _chunk2JDVPQ33cjs.safeMin.call(void 0, allY);
9623
+ const pageH = _chunkC3BOYTY5cjs.safeMax.call(void 0, allY) - _chunkC3BOYTY5cjs.safeMin.call(void 0, allY);
8762
9624
  const gapThreshold = Math.max(15, pageH * 0.03);
8763
9625
  const sides = frameColumnTextBands(remaining, spanning, gx);
8764
9626
  const textBlocks = [];
@@ -8774,7 +9636,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
8774
9636
  finalTextBlocks.push(...detectListBlocks(textBlocks));
8775
9637
  } else {
8776
9638
  const allY = remaining.map((i) => i.y);
8777
- const pageH = _chunk2JDVPQ33cjs.safeMax.call(void 0, allY) - _chunk2JDVPQ33cjs.safeMin.call(void 0, allY);
9639
+ const pageH = _chunkC3BOYTY5cjs.safeMax.call(void 0, allY) - _chunkC3BOYTY5cjs.safeMin.call(void 0, allY);
8778
9640
  const gapThreshold = Math.max(15, pageH * 0.03);
8779
9641
  const groups = xyCutOrder(remaining, gapThreshold);
8780
9642
  const textBlocks = [];
@@ -9032,18 +9894,22 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
9032
9894
  if (cards) return cards.flatMap((group) => extractPageBlocksFallback(group, pageNum, false, detectTables, lex));
9033
9895
  }
9034
9896
  const blocks = [];
9035
- const clusterItems = items.map((i) => ({
9036
- text: i.text,
9037
- x: i.x,
9038
- y: i.y,
9039
- w: i.w,
9040
- h: i.h,
9041
- fontSize: i.fontSize,
9042
- fontName: i.fontName,
9043
- hasSpaceBefore: i.hasSpaceBefore,
9044
- syntheticSpace: i.syntheticSpace,
9045
- spaceAfter: i.spaceAfter
9046
- }));
9897
+ const clusterItems = items.map((i) => {
9898
+ const item = {
9899
+ text: i.text,
9900
+ x: i.x,
9901
+ y: i.y,
9902
+ w: i.w,
9903
+ h: i.h,
9904
+ fontSize: i.fontSize,
9905
+ fontName: i.fontName,
9906
+ hasSpaceBefore: i.hasSpaceBefore,
9907
+ syntheticSpace: i.syntheticSpace,
9908
+ spaceAfter: i.spaceAfter
9909
+ };
9910
+ copyOcrTextGaps(i, item);
9911
+ return item;
9912
+ });
9047
9913
  const textRects = items.map((i) => ({ x: i.x, y: i.y, w: i.w, h: i.h > 0 ? i.h : i.fontSize }));
9048
9914
  const imagePanels = fullPage ? splitImagePanels(items, figures) : null;
9049
9915
  if (imagePanels) return imagePanels.flatMap((group) => extractPageBlocksFallback(group, pageNum, false, detectTables, lex));
@@ -9102,7 +9968,7 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
9102
9968
  blocks.push(...columnTextToBlocks(tableText, pageNum, bbox, dominantStyle(items)));
9103
9969
  } else {
9104
9970
  const allY = items.map((i) => i.y);
9105
- const pageHeight = _chunk2JDVPQ33cjs.safeMax.call(void 0, allY) - _chunk2JDVPQ33cjs.safeMin.call(void 0, allY);
9971
+ const pageHeight = _chunkC3BOYTY5cjs.safeMax.call(void 0, allY) - _chunkC3BOYTY5cjs.safeMin.call(void 0, allY);
9106
9972
  const gapThreshold = Math.max(15, pageHeight * 0.03);
9107
9973
  const orderedGroups = proseCutX !== null ? splitTwoColumnProse(items, proseCutX) : xyCutOrder(items, gapThreshold, 0, void 0, minGap);
9108
9974
  for (const group of orderedGroups) {
@@ -9134,19 +10000,19 @@ function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
9134
10000
  const overlapH = Math.max(0, Math.min(b.y + b.height, region.y2) - Math.max(b.y, region.y1));
9135
10001
  return overlapW * overlapH >= b.width * b.height * 0.8;
9136
10002
  });
9137
- const labels = candidates.filter((b) => b.type === "paragraph" && b.bbox.height <= 24 && (_nullishCoalesce(_optionalChain([b, 'access', _390 => _390.text, 'optionalAccess', _391 => _391.match, 'call', _392 => _392(/[\p{L}\p{N}]/gu), 'optionalAccess', _393 => _393.length]), () => ( 0))) >= 2);
10003
+ const labels = candidates.filter((b) => b.type === "paragraph" && b.bbox.height <= 24 && (_nullishCoalesce(_optionalChain([b, 'access', _397 => _397.text, 'optionalAccess', _398 => _398.match, 'call', _399 => _399(/[\p{L}\p{N}]/gu), 'optionalAccess', _400 => _400.length]), () => ( 0))) >= 2);
9138
10004
  const axisFragments = rotatedAxisFragments(candidates);
9139
10005
  const accepted = candidates.filter((b) => {
9140
- if (b.type === "paragraph") return (_nullishCoalesce(_optionalChain([b, 'access', _394 => _394.text, 'optionalAccess', _395 => _395.match, 'call', _396 => _396(/[\p{L}\p{N}]/gu), 'optionalAccess', _397 => _397.length]), () => ( 0))) >= 2 || !axisFragments.has(b) && (supportedDiagramLabel(b, labels, region) || axisTick(b, candidates));
10006
+ if (b.type === "paragraph") return (_nullishCoalesce(_optionalChain([b, 'access', _401 => _401.text, 'optionalAccess', _402 => _402.match, 'call', _403 => _403(/[\p{L}\p{N}]/gu), 'optionalAccess', _404 => _404.length]), () => ( 0))) >= 2 || !axisFragments.has(b) && (supportedDiagramLabel(b, labels, region) || axisTick(b, candidates));
9141
10007
  const t = b.table;
9142
10008
  if (b.type !== "table" || !t || UNRULED_REGION_TABLES.has(b)) return false;
9143
10009
  const lone = t.cells.filter((row) => row.filter((c) => c.text.trim()).length === 1 && row.some((c) => c.colSpan === t.cols)).length;
9144
10010
  if (t.rows >= 2 && lone * 2 >= t.rows) return false;
9145
10011
  if (t.rows === 1 && t.cols === 1) {
9146
- const text = _nullishCoalesce(_optionalChain([t, 'access', _398 => _398.cells, 'access', _399 => _399[0], 'optionalAccess', _400 => _400[0], 'optionalAccess', _401 => _401.text]), () => ( ""));
9147
- return (_nullishCoalesce(_optionalChain([text, 'access', _402 => _402.match, 'call', _403 => _403(/\n/g), 'optionalAccess', _404 => _404.length]), () => ( 0))) >= 5 && (_nullishCoalesce(_optionalChain([text, 'access', _405 => _405.match, 'call', _406 => _406(/\d/g), 'optionalAccess', _407 => _407.length]), () => ( 0))) >= text.length * 0.25;
10012
+ const text = _nullishCoalesce(_optionalChain([t, 'access', _405 => _405.cells, 'access', _406 => _406[0], 'optionalAccess', _407 => _407[0], 'optionalAccess', _408 => _408.text]), () => ( ""));
10013
+ return (_nullishCoalesce(_optionalChain([text, 'access', _409 => _409.match, 'call', _410 => _410(/\n/g), 'optionalAccess', _411 => _411.length]), () => ( 0))) >= 5 && (_nullishCoalesce(_optionalChain([text, 'access', _412 => _412.match, 'call', _413 => _413(/\d/g), 'optionalAccess', _414 => _414.length]), () => ( 0))) >= text.length * 0.25;
9148
10014
  }
9149
- const headerLabels = _nullishCoalesce(_optionalChain([t, 'access', _408 => _408.cells, 'access', _409 => _409[0], 'optionalAccess', _410 => _410.filter, 'call', _411 => _411((c) => c.text.replace(/[^A-Za-z가-힣]/g, "").length >= 2), 'access', _412 => _412.length]), () => ( 0));
10015
+ const headerLabels = _nullishCoalesce(_optionalChain([t, 'access', _415 => _415.cells, 'access', _416 => _416[0], 'optionalAccess', _417 => _417.filter, 'call', _418 => _418((c) => c.text.replace(/[^A-Za-z가-힣]/g, "").length >= 2), 'access', _419 => _419.length]), () => ( 0));
9150
10016
  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);
9151
10017
  });
9152
10018
  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(_nullishCoalesce(p.text, () => ( "")))) : []);
@@ -9163,14 +10029,14 @@ function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
9163
10029
  for (const block of selected) {
9164
10030
  if (seen2.has(block)) continue;
9165
10031
  const frame = FRAME_READING_UNITS.get(block);
9166
- const source = _optionalChain([frame, 'optionalAccess', _413 => _413.blocks, 'access', _414 => _414.every, 'call', _415 => _415((member) => selectedSet.has(member))]) ? frame.blocks : [block];
10032
+ const source = _optionalChain([frame, 'optionalAccess', _420 => _420.blocks, 'access', _421 => _421.every, 'call', _422 => _422((member) => selectedSet.has(member))]) ? frame.blocks : [block];
9167
10033
  source.forEach((member) => seen2.add(member));
9168
10034
  const available = source.filter((member) => !hasOriginal(member));
9169
10035
  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 }));
9170
10036
  for (const unit of units) {
9171
10037
  const b = unit.bbox;
9172
10038
  const index = blocks.findIndex((existing) => {
9173
- const e = _nullishCoalesce(_optionalChain([FRAME_READING_UNITS, 'access', _416 => _416.get, 'call', _417 => _417(existing), 'optionalAccess', _418 => _418.bbox]), () => ( existing.bbox));
10039
+ const e = _nullishCoalesce(_optionalChain([FRAME_READING_UNITS, 'access', _423 => _423.get, 'call', _424 => _424(existing), 'optionalAccess', _425 => _425.bbox]), () => ( existing.bbox));
9174
10040
  if (existing.pageNumber !== page || !e) return false;
9175
10041
  const beside = e.y < region.y2 && e.y + e.height > region.y1 && e.x >= region.x2 - 1;
9176
10042
  if (placedHere.has(existing) && Math.abs(e.y + e.height / 2 - b.y - b.height / 2) <= Math.min(e.height, b.height) * 0.25) return e.x > b.x;
@@ -9188,16 +10054,16 @@ function mergeOcrImageRegions(blocks, page, regions, ocrBlocks) {
9188
10054
  }
9189
10055
  function axisTick(block, candidates) {
9190
10056
  const b = block.bbox;
9191
- if (!/^\d$/u.test(_nullishCoalesce(_optionalChain([block, 'access', _419 => _419.text, 'optionalAccess', _420 => _420.trim, 'call', _421 => _421()]), () => ( "")))) return false;
9192
- const numeric = candidates.filter((o) => o !== block && o.type === "paragraph" && o.bbox && /^[\d\s.,%+−-]+$/u.test(_nullishCoalesce(_optionalChain([o, 'access', _422 => _422.text, 'optionalAccess', _423 => _423.trim, 'call', _424 => _424()]), () => ( ""))) && /\d/u.test(_nullishCoalesce(o.text, () => ( ""))) && Math.max(o.bbox.height, b.height) <= Math.min(o.bbox.height, b.height) * 2);
10057
+ if (!/^\d$/u.test(_nullishCoalesce(_optionalChain([block, 'access', _426 => _426.text, 'optionalAccess', _427 => _427.trim, 'call', _428 => _428()]), () => ( "")))) return false;
10058
+ const numeric = candidates.filter((o) => o !== block && o.type === "paragraph" && o.bbox && /^[\d\s.,%+−-]+$/u.test(_nullishCoalesce(_optionalChain([o, 'access', _429 => _429.text, 'optionalAccess', _430 => _430.trim, 'call', _431 => _431()]), () => ( ""))) && /\d/u.test(_nullishCoalesce(o.text, () => ( ""))) && Math.max(o.bbox.height, b.height) <= Math.min(o.bbox.height, b.height) * 2);
9193
10059
  const cy = b.y + b.height / 2, right = b.x + b.width;
9194
10060
  const row = numeric.filter((o) => Math.abs(o.bbox.y + o.bbox.height / 2 - cy) <= Math.min(o.bbox.height, b.height) * 0.35);
9195
10061
  const column = numeric.filter((o) => Math.abs(o.bbox.x + o.bbox.width - right) <= Math.max(o.bbox.height, b.height) * 0.5);
9196
10062
  return row.length >= 2 || column.length >= 2;
9197
10063
  }
9198
10064
  function supportedDiagramLabel(block, labels, region) {
9199
- const b = block.bbox, text = _nullishCoalesce(_optionalChain([block, 'access', _425 => _425.text, 'optionalAccess', _426 => _426.trim, 'call', _427 => _427()]), () => ( ""));
9200
- 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(_nullishCoalesce(l.text, () => ( "")))) || labels.filter((l) => !/\p{L}/u.test(_nullishCoalesce(l.text, () => ( ""))) && (_nullishCoalesce(_optionalChain([l, 'access', _428 => _428.text, 'optionalAccess', _429 => _429.match, 'call', _430 => _430(/\p{N}/gu), 'optionalAccess', _431 => _431.length]), () => ( 0))) >= 2).length < 2) return false;
10065
+ const b = block.bbox, text = _nullishCoalesce(_optionalChain([block, 'access', _432 => _432.text, 'optionalAccess', _433 => _433.trim, 'call', _434 => _434()]), () => ( ""));
10066
+ 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(_nullishCoalesce(l.text, () => ( "")))) || labels.filter((l) => !/\p{L}/u.test(_nullishCoalesce(l.text, () => ( ""))) && (_nullishCoalesce(_optionalChain([l, 'access', _435 => _435.text, 'optionalAccess', _436 => _436.match, 'call', _437 => _437(/\p{N}/gu), 'optionalAccess', _438 => _438.length]), () => ( 0))) >= 2).length < 2) return false;
9201
10067
  let above = false, below = false;
9202
10068
  for (const label of labels) {
9203
10069
  const a = label.bbox, em = Math.max(b.height, a.height);
@@ -9212,7 +10078,7 @@ function rotatedAxisFragments(candidates) {
9212
10078
  const paragraphs = candidates.filter((b) => b.type === "paragraph" && b.bbox.height <= 24);
9213
10079
  const axes = [];
9214
10080
  for (const block of paragraphs) {
9215
- const b = block.bbox, text = _nullishCoalesce(_optionalChain([block, 'access', _432 => _432.text, 'optionalAccess', _433 => _433.trim, 'call', _434 => _434()]), () => ( ""));
10081
+ const b = block.bbox, text = _nullishCoalesce(_optionalChain([block, 'access', _439 => _439.text, 'optionalAccess', _440 => _440.trim, 'call', _441 => _441()]), () => ( ""));
9216
10082
  if (!/^[\d\s.,%+−-]+$/u.test(text) || !/\d/u.test(text) || b.width > b.height * 6) continue;
9217
10083
  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);
9218
10084
  if (axis) axis.push(block);
@@ -9229,8 +10095,8 @@ function rotatedAxisFragments(candidates) {
9229
10095
  const em = Math.max(...axis.map((a) => a.bbox.height)), right = axis[0].bbox.x + axis[0].bbox.width;
9230
10096
  if (top - bottom < em * 6) continue;
9231
10097
  const left = paragraphs.filter((block) => {
9232
- const b = block.bbox, text = _nullishCoalesce(_optionalChain([block, 'access', _435 => _435.text, 'optionalAccess', _436 => _436.trim, 'call', _437 => _437()]), () => ( ""));
9233
- return /\p{Script=Latin}/u.test(text) && (_nullishCoalesce(_optionalChain([text, 'access', _438 => _438.match, 'call', _439 => _439(/[\p{L}\p{N}]/gu), 'optionalAccess', _440 => _440.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;
10098
+ const b = block.bbox, text = _nullishCoalesce(_optionalChain([block, 'access', _442 => _442.text, 'optionalAccess', _443 => _443.trim, 'call', _444 => _444()]), () => ( ""));
10099
+ return /\p{Script=Latin}/u.test(text) && (_nullishCoalesce(_optionalChain([text, 'access', _445 => _445.match, 'call', _446 => _446(/[\p{L}\p{N}]/gu), 'optionalAccess', _447 => _447.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;
9234
10100
  });
9235
10101
  const stack = left.filter((a) => left.some((b) => {
9236
10102
  if (a === b || !aligned(a, b)) return false;
@@ -9240,7 +10106,7 @@ function rotatedAxisFragments(candidates) {
9240
10106
  if (stack.length < 2) continue;
9241
10107
  for (const block of paragraphs) {
9242
10108
  const b = block.bbox;
9243
- 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(_nullishCoalesce(_optionalChain([block, 'access', _441 => _441.text, 'optionalAccess', _442 => _442.trim, 'call', _443 => _443()]), () => ( ""))) && stack.some((s) => aligned(s, block))) fragments.add(block);
10109
+ 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(_nullishCoalesce(_optionalChain([block, 'access', _448 => _448.text, 'optionalAccess', _449 => _449.trim, 'call', _450 => _450()]), () => ( ""))) && stack.some((s) => aligned(s, block))) fragments.add(block);
9244
10110
  }
9245
10111
  }
9246
10112
  return fragments;
@@ -9317,5 +10183,28 @@ function rowParagraphs(block) {
9317
10183
 
9318
10184
 
9319
10185
 
9320
- exports.DEFAULT_OCR_MODELS = DEFAULT_OCR_MODELS; exports.resolveOcrModels = resolveOcrModels; exports.ocrSelectionKey = ocrSelectionKey; exports.ocrSourcePath = ocrSourcePath; exports.ensureOcrModelsFor = ensureOcrModelsFor; exports.ocrModelsCached = ocrModelsCached; exports.parseCharacterDict = parseCharacterDict; exports.extractLines = extractLines; exports.extractImageRegions = extractImageRegions; exports.NO_EDGES = NO_EDGES; exports.hasOpenCellSeam = hasOpenCellSeam; exports.joinCellEdges = joinCellEdges; exports.filterHiddenText = filterHiddenText; exports.collapseEvenSpacing = collapseEvenSpacing; exports.computeBBox = computeBBox; exports.dominantStyle = dominantStyle; exports.normalizeItems = normalizeItems; exports.groupByY = groupByY; exports.mergeLineSimple = mergeLineSimple; exports.WrapLexicon = WrapLexicon; exports.startsNewItem = startsNewItem; exports.wrapJoiner = wrapJoiner; exports.joinPageBreakWraps = joinPageBreakWraps; exports.splitPageBreakWraps = splitPageBreakWraps; exports.latinSoftWrap = latinSoftWrap; exports.TOC_BLOCKS = TOC_BLOCKS; exports.computeMedianFontSizeFromFreq = computeMedianFontSizeFromFreq; exports.detectHeadings = detectHeadings; exports.mergeStackedHeadingLines = mergeStackedHeadingLines; exports.detectTypographyHeadings = detectTypographyHeadings; exports.detectDocumentStyleHeadings = detectDocumentStyleHeadings; exports.detectSiblingStyleHeadings = detectSiblingStyleHeadings; exports.detectRepeatedPageLabels = detectRepeatedPageLabels; exports.detectPageLeadHeadings = detectPageLeadHeadings; exports.refineDocumentStyleHeadings = refineDocumentStyleHeadings; exports.detectMarkerHeadings = detectMarkerHeadings; exports.detectTableCaptions = detectTableCaptions; exports.detectKoreanListBlocks = detectKoreanListBlocks; exports.removeHeaderFooterBlocks = removeHeaderFooterBlocks; exports.runningLinePatterns = runningLinePatterns; exports.stripAbsorbedRunningLines = stripAbsorbedRunningLines; exports.CLIP_TABLES = CLIP_TABLES; exports.FRAME_TITLE_BLOCKS = FRAME_TITLE_BLOCKS; exports.TABLE_COLXS = TABLE_COLXS; exports.TABLE_ROWYS = TABLE_ROWYS; exports.TABLE_TAIL = TABLE_TAIL; exports.PART_COLXS = PART_COLXS; exports.EMPTY_PARTS = EMPTY_PARTS; exports.IMAGE_CELLS = IMAGE_CELLS; exports.FILLER_CELLS = FILLER_CELLS; exports.CONT_PARTS = CONT_PARTS; exports.CELL_LINES = CELL_LINES; exports.ROW_RULES = ROW_RULES; exports.trimTrailingEmptyTableCols = trimTrailingEmptyTableCols; exports.restoreImageBullets = restoreImageBullets; exports.detectRightArrowRegions = detectRightArrowRegions; exports.removeSideTabs = removeSideTabs; exports.extractPageBlocksWithLines = extractPageBlocksWithLines; exports.UNRULED_REGION_TABLES = UNRULED_REGION_TABLES; exports.mergeOcrImageRegions = mergeOcrImageRegions;
9321
- //# sourceMappingURL=chunk-JIU7E7Z6.cjs.map
10186
+
10187
+
10188
+
10189
+
10190
+
10191
+
10192
+
10193
+
10194
+
10195
+
10196
+
10197
+
10198
+
10199
+
10200
+
10201
+
10202
+
10203
+
10204
+
10205
+
10206
+
10207
+
10208
+
10209
+ exports.DEFAULT_OCR_MODELS = DEFAULT_OCR_MODELS; exports.resolveOcrModels = resolveOcrModels; exports.ocrSelectionKey = ocrSelectionKey; exports.ocrSourcePath = ocrSourcePath; exports.ensureOcrModelsFor = ensureOcrModelsFor; exports.ocrModelsCached = ocrModelsCached; exports.parseCharacterDict = parseCharacterDict; exports.grayCrop = grayCrop; exports.inkStats = inkStats; exports.splitRowBands = splitRowBands; exports.leadingTriangle = leadingTriangle; exports.leaderRuns = leaderRuns; exports.inkBounds = inkBounds; exports.bracketFeatures = bracketFeatures; exports.romanStems = romanStems; exports.circledAt = circledAt; exports.quoteHead = quoteHead; exports.edgeTrim = edgeTrim; exports.tallInkCount = tallInkCount; exports.gapGlyphs = gapGlyphs; exports.ringBullet = ringBullet; exports.dashRatio = dashRatio; exports.discAt = discAt; exports.serifOne = serifOne; exports.starRun = starRun; exports.bracketShape = bracketShape; exports.leadingBullet = leadingBullet; exports.rememberOcrTextGaps = rememberOcrTextGaps; exports.copyOcrTextGaps = copyOcrTextGaps; exports.findOcrTextGaps = findOcrTextGaps; exports.extractLines = extractLines; exports.extractImageRegions = extractImageRegions; exports.NO_EDGES = NO_EDGES; exports.hasOpenCellSeam = hasOpenCellSeam; exports.joinCellEdges = joinCellEdges; exports.filterHiddenText = filterHiddenText; exports.collapseEvenSpacing = collapseEvenSpacing; exports.computeBBox = computeBBox; exports.dominantStyle = dominantStyle; exports.normalizeItems = normalizeItems; exports.groupByY = groupByY; exports.mergeLineSimple = mergeLineSimple; exports.WrapLexicon = WrapLexicon; exports.startsNewItem = startsNewItem; exports.wrapJoiner = wrapJoiner; exports.joinPageBreakWraps = joinPageBreakWraps; exports.splitPageBreakWraps = splitPageBreakWraps; exports.latinSoftWrap = latinSoftWrap; exports.TOC_BLOCKS = TOC_BLOCKS; exports.computeMedianFontSizeFromFreq = computeMedianFontSizeFromFreq; exports.detectHeadings = detectHeadings; exports.mergeStackedHeadingLines = mergeStackedHeadingLines; exports.detectTypographyHeadings = detectTypographyHeadings; exports.detectDocumentStyleHeadings = detectDocumentStyleHeadings; exports.detectSiblingStyleHeadings = detectSiblingStyleHeadings; exports.detectRepeatedPageLabels = detectRepeatedPageLabels; exports.detectPageLeadHeadings = detectPageLeadHeadings; exports.refineDocumentStyleHeadings = refineDocumentStyleHeadings; exports.detectMarkerHeadings = detectMarkerHeadings; exports.detectTableCaptions = detectTableCaptions; exports.detectKoreanListBlocks = detectKoreanListBlocks; exports.removeHeaderFooterBlocks = removeHeaderFooterBlocks; exports.runningLinePatterns = runningLinePatterns; exports.stripAbsorbedRunningLines = stripAbsorbedRunningLines; exports.CLIP_TABLES = CLIP_TABLES; exports.FRAME_TITLE_BLOCKS = FRAME_TITLE_BLOCKS; exports.TABLE_COLXS = TABLE_COLXS; exports.TABLE_ROWYS = TABLE_ROWYS; exports.TABLE_TAIL = TABLE_TAIL; exports.PART_COLXS = PART_COLXS; exports.EMPTY_PARTS = EMPTY_PARTS; exports.IMAGE_CELLS = IMAGE_CELLS; exports.FILLER_CELLS = FILLER_CELLS; exports.CONT_PARTS = CONT_PARTS; exports.CELL_LINES = CELL_LINES; exports.ROW_RULES = ROW_RULES; exports.trimTrailingEmptyTableCols = trimTrailingEmptyTableCols; exports.restoreImageBullets = restoreImageBullets; exports.detectRightArrowRegions = detectRightArrowRegions; exports.removeSideTabs = removeSideTabs; exports.extractPageBlocksWithLines = extractPageBlocksWithLines; exports.UNRULED_REGION_TABLES = UNRULED_REGION_TABLES; exports.mergeOcrImageRegions = mergeOcrImageRegions;
10210
+ //# sourceMappingURL=chunk-73MRAQXA.cjs.map