kordoc 4.15.7 → 4.16.0

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 (149) hide show
  1. package/README.md +22 -10
  2. package/dist/{-H6WNRHK6.js → -VQNLLLPE.js} +11 -11
  3. package/dist/{chunk-YFHV4QP3.js → chunk-3JWMDL3S.js} +5 -4
  4. package/dist/chunk-3JWMDL3S.js.map +1 -0
  5. package/dist/{chunk-WMLGS5QL.js → chunk-43FKGDDO.js} +200 -105
  6. package/dist/chunk-43FKGDDO.js.map +1 -0
  7. package/dist/{chunk-O5SDUPB2.js → chunk-46DZF3RK.js} +2 -2
  8. package/dist/{chunk-C572DIHX.js → chunk-476OYHGZ.js} +13 -6
  9. package/dist/{chunk-C572DIHX.js.map → chunk-476OYHGZ.js.map} +1 -1
  10. package/dist/{chunk-UGSRP7E2.js → chunk-6LMKQM7I.js} +3 -3
  11. package/dist/{chunk-IHCQ4IE7.js → chunk-A3QDRMVD.js} +2 -2
  12. package/dist/{chunk-ZXAH4AFS.cjs → chunk-B5NEGP65.cjs} +18 -71
  13. package/dist/chunk-B5NEGP65.cjs.map +1 -0
  14. package/dist/{chunk-TRB6OYMU.js → chunk-C75WE52C.js} +2 -2
  15. package/dist/{chunk-S7PEBTU3.js → chunk-CB5XDCSL.js} +134 -46
  16. package/dist/chunk-CB5XDCSL.js.map +1 -0
  17. package/dist/{chunk-OE6XLTMC.cjs → chunk-DRY3L5KQ.cjs} +9 -8
  18. package/dist/chunk-DRY3L5KQ.cjs.map +1 -0
  19. package/dist/{chunk-AWXXLLIG.js → chunk-DYENR3PX.js} +2 -2
  20. package/dist/{chunk-WQWXQVOQ.js → chunk-GOQBON77.js} +4 -2
  21. package/dist/{chunk-F5FHYJKJ.js.map → chunk-GOQBON77.js.map} +1 -1
  22. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  23. package/dist/{chunk-R45AG5K6.cjs → chunk-H6KMTYYZ.cjs} +3 -3
  24. package/dist/chunk-H6KMTYYZ.cjs.map +1 -0
  25. package/dist/{chunk-X3PBLSV5.js → chunk-HIVK5V27.js} +274 -98
  26. package/dist/chunk-HIVK5V27.js.map +1 -0
  27. package/dist/chunk-J55UQC5H.cjs.map +1 -1
  28. package/dist/{chunk-6ULM2YCN.js → chunk-JB5X5NNL.js} +7 -7
  29. package/dist/chunk-JB5X5NNL.js.map +1 -0
  30. package/dist/{chunk-4ANWGSUT.cjs → chunk-MH6MAL64.cjs} +320 -144
  31. package/dist/chunk-MH6MAL64.cjs.map +1 -0
  32. package/dist/{chunk-KJSD2WNF.js → chunk-N6TPODYL.js} +15 -2
  33. package/dist/chunk-N6TPODYL.js.map +1 -0
  34. package/dist/{chunk-NZMPU24H.js → chunk-NNYF2AGC.js} +5 -4
  35. package/dist/chunk-NNYF2AGC.js.map +1 -0
  36. package/dist/{chunk-J6ZU7AIR.cjs → chunk-NWODPYBD.cjs} +5 -3
  37. package/dist/chunk-NWODPYBD.cjs.map +1 -0
  38. package/dist/{chunk-L5MDTA6T.js → chunk-PIMB2YNO.js} +2 -2
  39. package/dist/{chunk-ZWPRA2SE.js → chunk-PQRP4NSF.js} +2 -2
  40. package/dist/{chunk-W2UTB3RG.js → chunk-QJERJZJ6.js} +1 -1
  41. package/dist/{chunk-YNJLZVEO.cjs.map → chunk-QJERJZJ6.js.map} +1 -1
  42. package/dist/{chunk-F5FHYJKJ.js → chunk-RC4C7Q33.js} +4 -2
  43. package/dist/{chunk-WQWXQVOQ.js.map → chunk-RC4C7Q33.js.map} +1 -1
  44. package/dist/{chunk-WHZUJH2O.js → chunk-TGD7UFHD.js} +5 -4
  45. package/dist/{chunk-WHZUJH2O.js.map → chunk-TGD7UFHD.js.map} +1 -1
  46. package/dist/{chunk-ORMMGTNK.js → chunk-UDX7TSOC.js} +2 -2
  47. package/dist/{chunk-NVG2GQNA.js → chunk-UQ6TZDW6.js} +1 -1
  48. package/dist/chunk-UQ6TZDW6.js.map +1 -0
  49. package/dist/{chunk-ZYJY44BT.js → chunk-XHOZB2WP.js} +16 -66
  50. package/dist/chunk-XHOZB2WP.js.map +1 -0
  51. package/dist/{chunk-YNJLZVEO.cjs → chunk-ZY5K3LPM.cjs} +1 -1
  52. package/dist/chunk-ZY5K3LPM.cjs.map +1 -0
  53. package/dist/chunks-JD25E5PM.js +10 -0
  54. package/dist/cli.js +35 -33
  55. package/dist/cli.js.map +1 -1
  56. package/dist/{formula-CUSB5R3P.js → formula-5775PTP2.js} +4 -4
  57. package/dist/{formula-UKLCJINT.js → formula-FNQYHMIY.js} +3 -3
  58. package/dist/{formula-YJIUNSWW.cjs → formula-VEFKYXPB.cjs} +9 -9
  59. package/dist/formula-VEFKYXPB.cjs.map +1 -0
  60. package/dist/{image-ocr-BMCOWLLB.cjs → image-ocr-6JZR734G.cjs} +17 -15
  61. package/dist/image-ocr-6JZR734G.cjs.map +1 -0
  62. package/dist/{image-ocr-OEEGTGDU.js → image-ocr-PYZU4TO7.js} +14 -9
  63. package/dist/image-ocr-PYZU4TO7.js.map +1 -0
  64. package/dist/{image-ocr-S5OLK6WH.js → image-ocr-YA2MQBRP.js} +9 -11
  65. package/dist/image-ocr-YA2MQBRP.js.map +1 -0
  66. package/dist/index.cjs +726 -630
  67. package/dist/index.cjs.map +1 -1
  68. package/dist/index.d.cts +3 -0
  69. package/dist/index.d.ts +3 -0
  70. package/dist/index.js +152 -56
  71. package/dist/index.js.map +1 -1
  72. package/dist/mcp.js +60 -49
  73. package/dist/mcp.js.map +1 -1
  74. package/dist/{model-bundle-A6QPDJZ3.js → model-bundle-O6J7ORVC.js} +5 -5
  75. package/dist/{models-GAP4U6WU.js → models-YMOKZGCI.js} +7 -5
  76. package/dist/page-range-QHHFTL7X.cjs.map +1 -1
  77. package/dist/{parser-MRTO7R2Y.js → parser-3B6I2XL7.js} +344 -23
  78. package/dist/parser-3B6I2XL7.js.map +1 -0
  79. package/dist/{parser-BCN3SZZC.js → parser-PXATL5DM.js} +340 -22
  80. package/dist/parser-PXATL5DM.js.map +1 -0
  81. package/dist/{parser-DZMXH4V5.cjs → parser-YAQV7FBO.cjs} +454 -136
  82. package/dist/parser-YAQV7FBO.cjs.map +1 -0
  83. package/dist/pdf-ocr-2TTO5PX2.js +15 -0
  84. package/dist/pdf-ocr-T2JXQATA.cjs +16 -0
  85. package/dist/pdf-ocr-T2JXQATA.cjs.map +1 -0
  86. package/dist/pdf-ocr-WF2NQA6X.js +18 -0
  87. package/dist/{profile-io-XAZ2MDXD.js → profile-io-ZTV2MKRT.js} +3 -3
  88. package/dist/{rasterize-2YKKVEIR.js → rasterize-MMUZ537K.js} +3 -3
  89. package/dist/{redact-doc-XPV546P6.js → redact-doc-S42XGV5D.js} +11 -11
  90. package/dist/{render-ASDQSRPX.js → render-WCWPZKJ7.js} +7 -7
  91. package/dist/seal-WHK4GOHR.js +10 -0
  92. package/dist/{setup-M3MH2DHU.js → setup-D35LKZCH.js} +3 -3
  93. package/dist/visual-WL4TDE5B.js +20 -0
  94. package/dist/{watch-3DB2LMAP.js → watch-AX64CIMN.js} +41 -19
  95. package/dist/watch-AX64CIMN.js.map +1 -0
  96. package/package.json +1 -1
  97. package/dist/chunk-4ANWGSUT.cjs.map +0 -1
  98. package/dist/chunk-6ULM2YCN.js.map +0 -1
  99. package/dist/chunk-J6ZU7AIR.cjs.map +0 -1
  100. package/dist/chunk-KJSD2WNF.js.map +0 -1
  101. package/dist/chunk-NVG2GQNA.js.map +0 -1
  102. package/dist/chunk-NZMPU24H.js.map +0 -1
  103. package/dist/chunk-OE6XLTMC.cjs.map +0 -1
  104. package/dist/chunk-R45AG5K6.cjs.map +0 -1
  105. package/dist/chunk-S7PEBTU3.js.map +0 -1
  106. package/dist/chunk-W2UTB3RG.js.map +0 -1
  107. package/dist/chunk-WMLGS5QL.js.map +0 -1
  108. package/dist/chunk-X3PBLSV5.js.map +0 -1
  109. package/dist/chunk-YFHV4QP3.js.map +0 -1
  110. package/dist/chunk-ZXAH4AFS.cjs.map +0 -1
  111. package/dist/chunk-ZYJY44BT.js.map +0 -1
  112. package/dist/chunks-PPHEGDUD.js +0 -10
  113. package/dist/formula-YJIUNSWW.cjs.map +0 -1
  114. package/dist/image-ocr-BMCOWLLB.cjs.map +0 -1
  115. package/dist/image-ocr-OEEGTGDU.js.map +0 -1
  116. package/dist/image-ocr-S5OLK6WH.js.map +0 -1
  117. package/dist/parser-BCN3SZZC.js.map +0 -1
  118. package/dist/parser-DZMXH4V5.cjs.map +0 -1
  119. package/dist/parser-MRTO7R2Y.js.map +0 -1
  120. package/dist/pdf-ocr-4V7U52JI.js +0 -18
  121. package/dist/pdf-ocr-A3Q4YMCG.js +0 -15
  122. package/dist/pdf-ocr-CZDODSMI.cjs +0 -16
  123. package/dist/pdf-ocr-CZDODSMI.cjs.map +0 -1
  124. package/dist/seal-3XWSKD6C.js +0 -10
  125. package/dist/visual-Z6BCNJMU.js +0 -20
  126. package/dist/watch-3DB2LMAP.js.map +0 -1
  127. /package/dist/{-H6WNRHK6.js.map → -VQNLLLPE.js.map} +0 -0
  128. /package/dist/{chunk-O5SDUPB2.js.map → chunk-46DZF3RK.js.map} +0 -0
  129. /package/dist/{chunk-UGSRP7E2.js.map → chunk-6LMKQM7I.js.map} +0 -0
  130. /package/dist/{chunk-IHCQ4IE7.js.map → chunk-A3QDRMVD.js.map} +0 -0
  131. /package/dist/{chunk-TRB6OYMU.js.map → chunk-C75WE52C.js.map} +0 -0
  132. /package/dist/{chunk-AWXXLLIG.js.map → chunk-DYENR3PX.js.map} +0 -0
  133. /package/dist/{chunk-L5MDTA6T.js.map → chunk-PIMB2YNO.js.map} +0 -0
  134. /package/dist/{chunk-ZWPRA2SE.js.map → chunk-PQRP4NSF.js.map} +0 -0
  135. /package/dist/{chunk-ORMMGTNK.js.map → chunk-UDX7TSOC.js.map} +0 -0
  136. /package/dist/{chunks-PPHEGDUD.js.map → chunks-JD25E5PM.js.map} +0 -0
  137. /package/dist/{formula-CUSB5R3P.js.map → formula-5775PTP2.js.map} +0 -0
  138. /package/dist/{formula-UKLCJINT.js.map → formula-FNQYHMIY.js.map} +0 -0
  139. /package/dist/{model-bundle-A6QPDJZ3.js.map → model-bundle-O6J7ORVC.js.map} +0 -0
  140. /package/dist/{models-GAP4U6WU.js.map → models-YMOKZGCI.js.map} +0 -0
  141. /package/dist/{pdf-ocr-4V7U52JI.js.map → pdf-ocr-2TTO5PX2.js.map} +0 -0
  142. /package/dist/{pdf-ocr-A3Q4YMCG.js.map → pdf-ocr-WF2NQA6X.js.map} +0 -0
  143. /package/dist/{profile-io-XAZ2MDXD.js.map → profile-io-ZTV2MKRT.js.map} +0 -0
  144. /package/dist/{rasterize-2YKKVEIR.js.map → rasterize-MMUZ537K.js.map} +0 -0
  145. /package/dist/{redact-doc-XPV546P6.js.map → redact-doc-S42XGV5D.js.map} +0 -0
  146. /package/dist/{render-ASDQSRPX.js.map → render-WCWPZKJ7.js.map} +0 -0
  147. /package/dist/{seal-3XWSKD6C.js.map → seal-WHK4GOHR.js.map} +0 -0
  148. /package/dist/{setup-M3MH2DHU.js.map → setup-D35LKZCH.js.map} +0 -0
  149. /package/dist/{visual-Z6BCNJMU.js.map → visual-WL4TDE5B.js.map} +0 -0
@@ -3,76 +3,14 @@ import {
3
3
  HEADING_RATIO_H1,
4
4
  HEADING_RATIO_H2,
5
5
  HEADING_RATIO_H3
6
- } from "./chunk-NVG2GQNA.js";
6
+ } from "./chunk-UQ6TZDW6.js";
7
7
  import {
8
8
  safeMax,
9
9
  safeMin
10
- } from "./chunk-F5FHYJKJ.js";
11
-
12
- // src/pdf/image-regions.ts
13
- import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
14
- function multiplyTransform(m, t) {
15
- return [
16
- m[0] * t[0] + m[2] * t[1],
17
- m[1] * t[0] + m[3] * t[1],
18
- m[0] * t[2] + m[2] * t[3],
19
- m[1] * t[2] + m[3] * t[3],
20
- m[0] * t[4] + m[2] * t[5] + m[4],
21
- m[1] * t[4] + m[3] * t[5] + m[5]
22
- ];
23
- }
24
- function extractImageRegions(fnArray, argsArray) {
25
- const regions = [];
26
- let ctm = [1, 0, 0, 1, 0, 0];
27
- const stack = [];
28
- for (let i = 0; i < fnArray.length; i++) {
29
- const op = fnArray[i];
30
- switch (op) {
31
- case OPS.save:
32
- stack.push(ctm);
33
- break;
34
- case OPS.restore:
35
- ctm = stack.pop() || [1, 0, 0, 1, 0, 0];
36
- break;
37
- case OPS.transform: {
38
- const t = argsArray[i];
39
- if (Array.isArray(t) && t.length >= 6) ctm = multiplyTransform(ctm, t);
40
- break;
41
- }
42
- // Form XObject 는 /Matrix 공간에서 그린다 — pdfjs 인자 [matrix, bbox], End 에서 복원 (line-extract.ts 와 같음)
43
- case OPS.paintFormXObjectBegin: {
44
- stack.push(ctm);
45
- const m = argsArray[i]?.[0];
46
- if (Array.isArray(m) && m.length >= 6) ctm = multiplyTransform(ctm, m);
47
- break;
48
- }
49
- case OPS.paintFormXObjectEnd:
50
- ctm = stack.pop() || [1, 0, 0, 1, 0, 0];
51
- break;
52
- case OPS.paintImageXObject:
53
- case OPS.paintInlineImageXObject:
54
- case OPS.paintImageMaskXObject:
55
- case OPS.paintImageXObjectRepeat: {
56
- const corners = [[0, 0], [1, 0], [0, 1], [1, 1]];
57
- let x1 = Infinity, y1 = Infinity, x2 = -Infinity, y2 = -Infinity;
58
- for (const [u, v] of corners) {
59
- const x = ctm[0] * u + ctm[2] * v + ctm[4];
60
- const y = ctm[1] * u + ctm[3] * v + ctm[5];
61
- if (x < x1) x1 = x;
62
- if (x > x2) x2 = x;
63
- if (y < y1) y1 = y;
64
- if (y > y2) y2 = y;
65
- }
66
- if (x2 - x1 > 0 && y2 - y1 > 0) regions.push({ x1, y1, x2, y2 });
67
- break;
68
- }
69
- }
70
- }
71
- return regions;
72
- }
10
+ } from "./chunk-RC4C7Q33.js";
73
11
 
74
12
  // src/pdf/line-extract.ts
75
- import { OPS as OPS2 } from "pdfjs-dist/legacy/build/pdf.mjs";
13
+ import { OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
76
14
  var ORIENTATION_TOL = 2;
77
15
  var MIN_LINE_LENGTH = 15;
78
16
  var MAX_LINE_WIDTH = 5;
@@ -185,20 +123,20 @@ function extractLines(fnArray, argsArray) {
185
123
  const op = fnArray[i];
186
124
  const args = argsArray[i];
187
125
  switch (op) {
188
- case OPS2.setLineWidth:
126
+ case OPS.setLineWidth:
189
127
  lineWidth = args[0] || 1;
190
128
  break;
191
- case OPS2.save:
129
+ case OPS.save:
192
130
  ctmStack.push(ctm.slice());
193
131
  colorStack.push(fillColor);
194
132
  alphaStack.push([fillAlpha, strokeAlpha]);
195
133
  break;
196
- case OPS2.restore:
134
+ case OPS.restore:
197
135
  ctm = ctmStack.pop() ?? [1, 0, 0, 1, 0, 0];
198
136
  fillColor = colorStack.pop() ?? 0;
199
137
  [fillAlpha, strokeAlpha] = alphaStack.pop() ?? [1, 1];
200
138
  break;
201
- case OPS2.setGState: {
139
+ case OPS.setGState: {
202
140
  const entries = args[0];
203
141
  if (!Array.isArray(entries)) break;
204
142
  for (const e of entries) {
@@ -208,15 +146,15 @@ function extractLines(fnArray, argsArray) {
208
146
  }
209
147
  break;
210
148
  }
211
- case OPS2.setFillRGBColor: {
149
+ case OPS.setFillRGBColor: {
212
150
  const c = args;
213
151
  fillColor = c[0] << 16 | c[1] << 8 | c[2];
214
152
  break;
215
153
  }
216
- case OPS2.transform:
217
- case OPS2.paintFormXObjectBegin: {
154
+ case OPS.transform:
155
+ case OPS.paintFormXObjectBegin: {
218
156
  let t = args;
219
- if (op === OPS2.paintFormXObjectBegin) {
157
+ if (op === OPS.paintFormXObjectBegin) {
220
158
  ctmStack.push(ctm.slice());
221
159
  colorStack.push(fillColor);
222
160
  alphaStack.push([fillAlpha, strokeAlpha]);
@@ -234,41 +172,41 @@ function extractLines(fnArray, argsArray) {
234
172
  ];
235
173
  break;
236
174
  }
237
- case OPS2.paintFormXObjectEnd:
175
+ case OPS.paintFormXObjectEnd:
238
176
  ctm = ctmStack.pop() ?? [1, 0, 0, 1, 0, 0];
239
177
  fillColor = colorStack.pop() ?? 0;
240
178
  [fillAlpha, strokeAlpha] = alphaStack.pop() ?? [1, 1];
241
179
  break;
242
- case OPS2.constructPath: {
180
+ case OPS.constructPath: {
243
181
  const arg0 = args[0];
244
182
  if (Array.isArray(arg0)) {
245
183
  const subOps = arg0;
246
184
  const coords = args[1];
247
185
  let ci = 0;
248
186
  for (const subOp of subOps) {
249
- if (subOp === OPS2.moveTo) {
187
+ if (subOp === OPS.moveTo) {
250
188
  curX = coords[ci++];
251
189
  curY = coords[ci++];
252
190
  pathStartX = curX;
253
191
  pathStartY = curY;
254
- } else if (subOp === OPS2.lineTo) {
192
+ } else if (subOp === OPS.lineTo) {
255
193
  const x2 = coords[ci++], y2 = coords[ci++];
256
194
  pushSeg(curX, curY, x2, y2);
257
195
  curX = x2;
258
196
  curY = y2;
259
- } else if (subOp === OPS2.rectangle) {
197
+ } else if (subOp === OPS.rectangle) {
260
198
  const rx = coords[ci++], ry = coords[ci++];
261
199
  const rw = coords[ci++], rh = coords[ci++];
262
200
  pushRectangle(rx, ry, rw, rh);
263
- } else if (subOp === OPS2.closePath) {
201
+ } else if (subOp === OPS.closePath) {
264
202
  if (curX !== pathStartX || curY !== pathStartY) {
265
203
  pushSeg(curX, curY, pathStartX, pathStartY);
266
204
  }
267
205
  curX = pathStartX;
268
206
  curY = pathStartY;
269
- } else if (subOp === OPS2.curveTo) {
207
+ } else if (subOp === OPS.curveTo) {
270
208
  ci += 6;
271
- } else if (subOp === OPS2.curveTo2 || subOp === OPS2.curveTo3) {
209
+ } else if (subOp === OPS.curveTo2 || subOp === OPS.curveTo3) {
272
210
  ci += 4;
273
211
  }
274
212
  }
@@ -306,37 +244,37 @@ function extractLines(fnArray, argsArray) {
306
244
  }
307
245
  }
308
246
  }
309
- if (afterOp === OPS2.stroke || afterOp === OPS2.closeStroke) {
247
+ if (afterOp === OPS.stroke || afterOp === OPS.closeStroke) {
310
248
  flushPath(true);
311
- } else if (afterOp === OPS2.fill || afterOp === OPS2.eoFill) {
249
+ } else if (afterOp === OPS.fill || afterOp === OPS.eoFill) {
312
250
  flushPath(true, true);
313
- } else if (afterOp === OPS2.fillStroke || afterOp === OPS2.eoFillStroke || afterOp === OPS2.closeFillStroke || afterOp === OPS2.closeEOFillStroke) {
251
+ } else if (afterOp === OPS.fillStroke || afterOp === OPS.eoFillStroke || afterOp === OPS.closeFillStroke || afterOp === OPS.closeEOFillStroke) {
314
252
  flushPath(true, false, true);
315
- } else if (afterOp === OPS2.endPath) {
253
+ } else if (afterOp === OPS.endPath) {
316
254
  flushPath(false);
317
255
  }
318
256
  }
319
257
  break;
320
258
  }
321
- case OPS2.stroke:
322
- case OPS2.closeStroke:
259
+ case OPS.stroke:
260
+ case OPS.closeStroke:
323
261
  flushPath(true);
324
262
  break;
325
- case OPS2.fill:
326
- case OPS2.eoFill:
263
+ case OPS.fill:
264
+ case OPS.eoFill:
327
265
  flushPath(true, true);
328
266
  break;
329
- case OPS2.fillStroke:
330
- case OPS2.eoFillStroke:
331
- case OPS2.closeFillStroke:
332
- case OPS2.closeEOFillStroke:
267
+ case OPS.fillStroke:
268
+ case OPS.eoFillStroke:
269
+ case OPS.closeFillStroke:
270
+ case OPS.closeEOFillStroke:
333
271
  flushPath(true, false, true);
334
272
  break;
335
- case OPS2.endPath:
273
+ case OPS.endPath:
336
274
  flushPath(false);
337
275
  break;
338
- case OPS2.clip:
339
- case OPS2.eoClip:
276
+ case OPS.clip:
277
+ case OPS.eoClip:
340
278
  pendingClip = true;
341
279
  break;
342
280
  }
@@ -672,6 +610,68 @@ function filterPageBorderLines(horizontals, verticals, pageWidth, pageHeight) {
672
610
  };
673
611
  }
674
612
 
613
+ // src/pdf/image-regions.ts
614
+ import { OPS as OPS2 } from "pdfjs-dist/legacy/build/pdf.mjs";
615
+ function multiplyTransform(m, t) {
616
+ return [
617
+ m[0] * t[0] + m[2] * t[1],
618
+ m[1] * t[0] + m[3] * t[1],
619
+ m[0] * t[2] + m[2] * t[3],
620
+ m[1] * t[2] + m[3] * t[3],
621
+ m[0] * t[4] + m[2] * t[5] + m[4],
622
+ m[1] * t[4] + m[3] * t[5] + m[5]
623
+ ];
624
+ }
625
+ function extractImageRegions(fnArray, argsArray) {
626
+ const regions = [];
627
+ let ctm = [1, 0, 0, 1, 0, 0];
628
+ const stack = [];
629
+ for (let i = 0; i < fnArray.length; i++) {
630
+ const op = fnArray[i];
631
+ switch (op) {
632
+ case OPS2.save:
633
+ stack.push(ctm);
634
+ break;
635
+ case OPS2.restore:
636
+ ctm = stack.pop() || [1, 0, 0, 1, 0, 0];
637
+ break;
638
+ case OPS2.transform: {
639
+ const t = argsArray[i];
640
+ if (Array.isArray(t) && t.length >= 6) ctm = multiplyTransform(ctm, t);
641
+ break;
642
+ }
643
+ // Form XObject 는 /Matrix 공간에서 그린다 — pdfjs 인자 [matrix, bbox], End 에서 복원 (line-extract.ts 와 같음)
644
+ case OPS2.paintFormXObjectBegin: {
645
+ stack.push(ctm);
646
+ const m = argsArray[i]?.[0];
647
+ if (Array.isArray(m) && m.length >= 6) ctm = multiplyTransform(ctm, m);
648
+ break;
649
+ }
650
+ case OPS2.paintFormXObjectEnd:
651
+ ctm = stack.pop() || [1, 0, 0, 1, 0, 0];
652
+ break;
653
+ case OPS2.paintImageXObject:
654
+ case OPS2.paintInlineImageXObject:
655
+ case OPS2.paintImageMaskXObject:
656
+ case OPS2.paintImageXObjectRepeat: {
657
+ const corners = [[0, 0], [1, 0], [0, 1], [1, 1]];
658
+ let x1 = Infinity, y1 = Infinity, x2 = -Infinity, y2 = -Infinity;
659
+ for (const [u, v] of corners) {
660
+ const x = ctm[0] * u + ctm[2] * v + ctm[4];
661
+ const y = ctm[1] * u + ctm[3] * v + ctm[5];
662
+ if (x < x1) x1 = x;
663
+ if (x > x2) x2 = x;
664
+ if (y < y1) y1 = y;
665
+ if (y > y2) y2 = y;
666
+ }
667
+ if (x2 - x1 > 0 && y2 - y1 > 0) regions.push({ x1, y1, x2, y2 });
668
+ break;
669
+ }
670
+ }
671
+ }
672
+ return regions;
673
+ }
674
+
675
675
  // src/pdf/vertical-bridge.ts
676
676
  var BRIDGE_X_TOL = 1.5;
677
677
  var BRIDGE_MIN_GAP = 5;
@@ -1917,6 +1917,7 @@ var hasBatchim = (c) => {
1917
1917
  const k = c.charCodeAt(0) - 44032;
1918
1918
  return k >= 0 && k < 11172 && k % 28 !== 0;
1919
1919
  };
1920
+ var CJK = /[\u3000-\u303F\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\uFF00-\uFFEF]/;
1920
1921
  var CLOSE_TAIL = /[’”」』)\]〉》>]+$/;
1921
1922
  var TAIL = "[.,)\u300D\u300F\u2019\u201D]*";
1922
1923
  var PARTICLE = new RegExp(`^(?:\uB2E4\\.|\uC758|\uC5D0|\uC5D0\uC11C|\uC5D0\uB294|\uC5D0\uAC8C|\uC5D0\uB3C4|\uC5D0\uC11C\uB294|\uAE4C\uC9C0|\uBD80\uD130|\uCC98\uB7FC|\uB9C8\uB2E4|\uB9CC|\uB3C4|\uB4E4|\uB4E4\uC774|\uB4E4\uC758|\uB4E4\uC740|\uB4E4\uC744|\uB4E4\uC5D0\uAC8C|\uC11C\uB294|\uC11C\uB3C4|\uB77C\uACE0|\uB77C\uBA70|\uC740|\uB294|\uC744|\uB97C|\uC73C\uB85C|\uB85C|\uC73C\uB85C\uC11C|\uB85C\uC11C|\uC73C\uB85C\uC368|\uB85C\uC368)${TAIL}$`);
@@ -1966,6 +1967,7 @@ function wrapJoiner(prevText, nextText, lex) {
1966
1967
  const prev = prevText.replace(MARKUP, "").trimEnd(), next = nextText.replace(MARKUP, "").trimStart();
1967
1968
  const a = prev[prev.length - 1], b = next[0];
1968
1969
  if (!a || !b || /[,;:!?]/.test(a) || DATE_DAY_END.test(prev) && b !== "(") return " ";
1970
+ if (CJK.test(a) && CJK.test(b) && !/[가-힣ㄱ-ㅎㅏ-ㅣ]/.test(prev + next)) return "";
1969
1971
  let s = prev.length;
1970
1972
  while (s > 0 && !/\s/.test(prev[s - 1])) s--;
1971
1973
  const left = prev.slice(s), right = next.match(/^\S+/)[0];
@@ -2007,6 +2009,7 @@ function joinPageBreakWraps(blocks, lex) {
2007
2009
  blocks.splice(i, 1);
2008
2010
  }
2009
2011
  }
2012
+ var HANGING = /[,。、:;!?)」』】〕》〉.]\s*$/;
2010
2013
  var BODY_FULL_TOL = 0.25;
2011
2014
  var BODY_MIN_WIDTH_EM = 12;
2012
2015
  var BODY_MAX_PITCH_EM = 2;
@@ -2015,12 +2018,15 @@ var BODY_MAX_PITCH_ABS_EM = 3.5;
2015
2018
  function bodyLineJoins(lines, lex) {
2016
2019
  let right = -Infinity;
2017
2020
  for (const l of lines) if (l.right > right) right = l.right;
2021
+ let inner = -Infinity;
2022
+ for (const l of lines) if (!HANGING.test(l.text) && l.right > inner) inner = l.right;
2023
+ 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;
2018
2024
  const pitch = (k) => lines[k].y - lines[k + 1].y;
2019
2025
  const sameSize = (k) => Math.abs(lines[k + 1].fontSize - lines[k].fontSize) <= 0.15 * lines[k].fontSize;
2020
2026
  let p1 = Infinity, p2 = Infinity, i1 = -1;
2021
2027
  for (let k = 0; k + 1 < lines.length; k++) {
2022
2028
  const p = pitch(k);
2023
- if (p <= 0 || !sameSize(k)) continue;
2029
+ if (p <= 0 || !sameSize(k) || Math.min(lines[k].right - lines[k].left, lines[k + 1].right - lines[k + 1].left) < 3 * lines[k].fontSize) continue;
2024
2030
  if (p < p1) {
2025
2031
  p2 = p1;
2026
2032
  p1 = p;
@@ -2033,7 +2039,7 @@ function bodyLineJoins(lines, lex) {
2033
2039
  const fs = a.fontSize;
2034
2040
  const others = i === i1 ? p2 : p1;
2035
2041
  const maxPitch = Number.isFinite(others) ? Math.min(BODY_MAX_PITCH_ABS_EM * fs, Math.max(BODY_MAX_PITCH_EM * fs, others * BODY_PITCH_REL)) : BODY_MAX_PITCH_EM * fs;
2036
- const wraps = fs > 0 && right - a.right < BODY_FULL_TOL * fs && a.right - a.left >= BODY_MIN_WIDTH_EM * fs && a.y - b.y > 0 && a.y - b.y < maxPitch && Math.abs(b.fontSize - fs) <= 0.15 * fs && !startsNewItem(a.text, b.text);
2042
+ const wraps = fs > 0 && full(a) && a.right - a.left >= BODY_MIN_WIDTH_EM * fs && a.y - b.y > 0 && a.y - b.y < maxPitch && Math.abs(b.fontSize - fs) <= 0.15 * fs && !startsNewItem(a.text, b.text);
2037
2043
  out.push(wraps ? wrapJoiner(a.text, b.text, lex) : "\n");
2038
2044
  }
2039
2045
  return out;
@@ -2143,6 +2149,7 @@ function cellTextToString(items, wrap) {
2143
2149
  const textLines = merged.map((line) => {
2144
2150
  const s = sortLineByX(line);
2145
2151
  if (s.length === 1) return s[0].text;
2152
+ if (s.length === 2 && /^[가-힣]$/.test(s[0].text) && /^[가-힣]$/.test(s[1].text) && !!wrap?.lex && (wrap.lex.isWord(s[0].text + s[1].text) || wrap.lex.evidence(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;
2146
2153
  const evenSpaced = detectEvenSpacedItems(s);
2147
2154
  let result = s[0].text;
2148
2155
  for (let j = 1; j < s.length; j++) {
@@ -2152,7 +2159,9 @@ function cellTextToString(items, wrap) {
2152
2159
  }
2153
2160
  const gap = s[j].x - (s[j - 1].x + s[j - 1].w);
2154
2161
  const avgFs = (s[j].fontSize + s[j - 1].fontSize) / 2;
2155
- if (s[j].hasSpaceBefore && gap >= avgFs * 0.05) {
2162
+ if (isCjkLatinAutospace(s[j - 1].text, s[j].text, gap, avgFs)) {
2163
+ result += s[j].text;
2164
+ } else if (s[j].hasSpaceBefore && gap >= avgFs * 0.05) {
2156
2165
  result += " " + s[j].text;
2157
2166
  } else if (gap > spaceGapThreshold(avgFs)) {
2158
2167
  result += " " + s[j].text;
@@ -2445,6 +2454,12 @@ function sortLineByX(items) {
2445
2454
  }
2446
2455
  return items;
2447
2456
  }
2457
+ function isCjkLatinAutospace(prevText, nextText, gap, fontSize) {
2458
+ if (!(gap < fontSize * 0.3)) return false;
2459
+ const a = prevText.slice(-1), b = nextText[0] ?? "";
2460
+ const cjk = /[\u3040-\u30ff\u3400-\u9fff\uf900-\ufaff]/, latin = /[A-Za-z0-9]/;
2461
+ return cjk.test(a) && latin.test(b) || latin.test(a) && cjk.test(b);
2462
+ }
2448
2463
  function filterHiddenText(items, pageWidth, pageHeight, originX = 0, originY = 0) {
2449
2464
  let hiddenCount = 0;
2450
2465
  const visible = [];
@@ -2520,10 +2535,14 @@ function normalizeItems(rawItems) {
2520
2535
  const scaleX = Math.hypot(i.transform[0], i.transform[1]);
2521
2536
  const scaleY = Math.hypot(i.transform[2], i.transform[3]);
2522
2537
  const fontSize = Math.round(Math.max(scaleY, scaleX));
2523
- const w = Math.round(i.width);
2538
+ let w = Math.round(i.width);
2524
2539
  const h = Math.round(i.height);
2540
+ if (/[^\u0000]\u0000+$/.test(i.str)) {
2541
+ w = Math.max(1, Math.round(i.width - Math.round(Math.max(Math.hypot(i.transform[2], i.transform[3]), Math.hypot(i.transform[0], i.transform[1]))) * 0.3));
2542
+ spacePositions.push({ x: x + w, y });
2543
+ }
2525
2544
  const isHidden = fontSize === 0 || i.width === 0 && i.str.trim().length > 0;
2526
- let text = i.str.trim();
2545
+ let text = i.str.trim().replace(/[\u2F00-\u2FD5]/g, (c) => c.normalize("NFKC"));
2527
2546
  if (/^[\d\s\-().·,☎]+$/.test(text) && /\d/.test(text) && / /.test(text)) {
2528
2547
  text = text.replace(/ /g, "");
2529
2548
  }
@@ -2744,6 +2763,10 @@ function mergeLineSimple(items) {
2744
2763
  result += sorted[i].text;
2745
2764
  continue;
2746
2765
  }
2766
+ if (isCjkLatinAutospace(sorted[i - 1].text, sorted[i].text, gap, avgFs)) {
2767
+ result += sorted[i].text;
2768
+ continue;
2769
+ }
2747
2770
  if (sorted[i].hasSpaceBefore && gap >= avgFs * 0.05) {
2748
2771
  result += " ";
2749
2772
  result += sorted[i].text;
@@ -3518,16 +3541,23 @@ function removeHeaderFooterBlocks(blocks, pageHeights, warnings) {
3518
3541
  if (entries.length === 0) continue;
3519
3542
  const patternCount = /* @__PURE__ */ new Map();
3520
3543
  const patternPages = /* @__PURE__ */ new Map();
3544
+ const patternNumbers = /* @__PURE__ */ new Map();
3521
3545
  for (const e of entries) {
3522
3546
  const norm = e.text.replace(/\d+/g, "#");
3523
3547
  patternCount.set(norm, (patternCount.get(norm) || 0) + 1);
3548
+ const nums = patternNumbers.get(norm) || /* @__PURE__ */ new Set();
3549
+ nums.add((e.text.match(/\d+/g) ?? []).join(","));
3550
+ patternNumbers.set(norm, nums);
3524
3551
  const pages = patternPages.get(norm) || /* @__PURE__ */ new Set();
3525
3552
  pages.add(e.page);
3526
3553
  patternPages.set(norm, pages);
3527
3554
  }
3528
3555
  const repeatedPatterns = /* @__PURE__ */ new Set();
3529
3556
  for (const [p, count] of patternCount) {
3530
- if (count >= MIN_REPEAT && (patternPages.get(p)?.size ?? 0) >= MIN_REPEAT) {
3557
+ const pages = [...patternPages.get(p) ?? []];
3558
+ const span = pages.length ? Math.max(...pages) - Math.min(...pages) + 1 : 0;
3559
+ const pageNumbered = (patternNumbers.get(p)?.size ?? 0) > 1;
3560
+ if (count >= MIN_REPEAT && pages.length >= MIN_REPEAT && (pages.length >= span * 0.4 || pageNumbered)) {
3531
3561
  repeatedPatterns.add(p);
3532
3562
  }
3533
3563
  }
@@ -3732,6 +3762,12 @@ function isFormulaTable(table) {
3732
3762
  const math = texts.filter((text) => /^[a-z]{1,2}$/.test(text) || /[=∂∑∫∣Γ∇√∞]/.test(text)).length;
3733
3763
  return math >= texts.length * 0.6;
3734
3764
  }
3765
+ function isExamLayoutTable(table) {
3766
+ const texts = table.cells.flat().map((cell) => cell.text.trim()).filter(Boolean);
3767
+ if (texts.length < 3 || !texts.some((text) => /[①-⑤]|문\d+)/.test(text))) return false;
3768
+ const layout = texts.filter((text) => /\$|[①-⑤]|문\d+)/.test(text) || !/[\p{L}\p{N}]/u.test(text)).length;
3769
+ return layout >= texts.length * 0.6;
3770
+ }
3735
3771
 
3736
3772
  // src/pdf/cluster-detector.ts
3737
3773
  var Y_TOL = 3;
@@ -4501,7 +4537,7 @@ function joinCellItems(items) {
4501
4537
  for (let i = 1; i < line.length; i++) {
4502
4538
  const gap = line[i].x - (line[i - 1].x + line[i - 1].w);
4503
4539
  const fs = (line[i].fontSize + line[i - 1].fontSize) / 2;
4504
- s += (line[i].hasSpaceBefore && gap >= fs * 0.05 || gap > spaceGapThreshold(fs) ? " " : "") + line[i].text;
4540
+ s += (!isCjkLatinAutospace(line[i - 1].text, line[i].text, gap, fs) && (line[i].hasSpaceBefore && gap >= fs * 0.05 || gap > spaceGapThreshold(fs)) ? " " : "") + line[i].text;
4505
4541
  }
4506
4542
  return s;
4507
4543
  }).join(" ");
@@ -4764,6 +4800,27 @@ function splitEdgeSpannedColumns(items, gapThreshold, depth) {
4764
4800
  ];
4765
4801
  }
4766
4802
 
4803
+ // src/pdf/blank-fills.ts
4804
+ var FILL_EDGE_GAP = 6;
4805
+ var FILL_MAX_THICKNESS = 2;
4806
+ function fillBlanks(items, horizontals, verticals = []) {
4807
+ const widened = /* @__PURE__ */ new Map();
4808
+ const used = /* @__PURE__ */ new Set();
4809
+ for (const h of horizontals) {
4810
+ if (h.lineWidth > FILL_MAX_THICKNESS || Math.abs(h.y1 - h.y2) > 1) continue;
4811
+ const x1 = Math.min(h.x1, h.x2), x2 = Math.max(h.x1, h.x2);
4812
+ const row = items.filter((i) => i.y >= h.y1 && i.y - h.y1 <= Math.max(3, i.fontSize * 0.5));
4813
+ const left = row.find((i) => i.x + i.w <= x1 + 1 && x1 - (i.x + i.w) <= FILL_EDGE_GAP);
4814
+ const right = row.find((i) => i.x >= x2 - 1 && i.x - x2 <= FILL_EDGE_GAP);
4815
+ if (!left || !right || widened.has(left) || row.some((i) => i.x < x2 && i.x + i.w > x1) || x2 - x1 < 2 * left.fontSize) continue;
4816
+ if (verticals.some((v) => (Math.abs(v.x1 - x1) <= 3 || Math.abs(v.x1 - x2) <= 3) && Math.min(v.y1, v.y2) - 3 <= h.y1 && Math.max(v.y1, v.y2) + 3 >= h.y1)) continue;
4817
+ widened.set(left, { ...left, text: left.text.trimEnd() + " ", w: x2 - left.x });
4818
+ used.add(h);
4819
+ }
4820
+ if (!used.size) return { items, horizontals };
4821
+ return { items: items.map((i) => widened.get(i) ?? i), horizontals: horizontals.filter((h) => !used.has(h)) };
4822
+ }
4823
+
4767
4824
  // src/pdf/two-column.ts
4768
4825
  var GUTTER_SCAN_LO = 0.3;
4769
4826
  var GUTTER_SCAN_HI = 0.7;
@@ -5368,6 +5425,23 @@ function headerLineAbove(free, colXs, top) {
5368
5425
  return cols;
5369
5426
  }
5370
5427
 
5428
+ // src/pdf/page-frame.ts
5429
+ function isPageFrameGrid(grid, cells, pageWidth, pageHeight, items = []) {
5430
+ const b = grid.bbox;
5431
+ if (grid.cells || b.x2 - b.x1 < pageWidth * 0.85 || b.y2 - b.y1 < pageHeight * 0.75) return false;
5432
+ const pageArea = pageWidth * pageHeight;
5433
+ const area = (c) => (c.bbox.x2 - c.bbox.x1) * (c.bbox.y2 - c.bbox.y1);
5434
+ const big = cells.filter((c) => area(c) >= pageArea * 0.15);
5435
+ if (big.reduce((s, c) => s + area(c), 0) < pageArea * 0.5) return false;
5436
+ const inner = grid.colXs.slice(1, -1);
5437
+ const inBig = items.filter((it) => big.some((c) => {
5438
+ const cx = it.x + it.w / 2, cy = it.y + it.h / 2;
5439
+ return cx > c.bbox.x1 && cx < c.bbox.x2 && cy > c.bbox.y1 && cy < c.bbox.y2;
5440
+ }));
5441
+ const crossing = inBig.filter((it) => inner.some((x) => x > it.x + 1 && x < it.x + it.w - 1)).length;
5442
+ return inner.length === 0 || crossing >= 1 && crossing >= inBig.length * 0.01;
5443
+ }
5444
+
5371
5445
  // src/pdf/open-table-ends.ts
5372
5446
  var ALIGN_TOL = 3;
5373
5447
  var MIN_RULES = 3;
@@ -6032,6 +6106,9 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
6032
6106
  for (const line of streamLines(items)) lex.addLine(mergeLineSimple(line));
6033
6107
  const extracted = extractLines(opList.fnArray, opList.argsArray);
6034
6108
  let { horizontals, verticals } = extracted;
6109
+ const filled = fillBlanks(items, horizontals, verticals);
6110
+ items = filled.items;
6111
+ horizontals = filled.horizontals;
6035
6112
  const prevPage = carry?.page === pageNum - 1 ? carry.clip : void 0;
6036
6113
  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 };
6037
6114
  if (carry) {
@@ -6243,6 +6320,7 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
6243
6320
  const holdsNested = !grid.cells && pendingNested.some((p) => p.contained && p.parent.x1 >= grid.bbox.x1 - FRAME_RECT_TOL && p.parent.x2 <= grid.bbox.x2 + FRAME_RECT_TOL && p.parent.y1 >= grid.bbox.y1 - FRAME_RECT_TOL && p.parent.y2 <= grid.bbox.y2 + FRAME_RECT_TOL);
6244
6321
  if (!grid.cells && !holdsNested && numGridRows === 1 && numGridCols >= 2) continue;
6245
6322
  if (!grid.cells && !holdsNested && numGridCols === 1 && numGridRows >= 2 && (numGridRows < 5 || gridW > pageWidth * 0.7)) continue;
6323
+ if (!holdsNested && isPageFrameGrid(grid, extractCells(grid, horizontals, verticals), pageWidth, pageHeight, items)) continue;
6246
6324
  const tableItems = [];
6247
6325
  const pad = 3;
6248
6326
  for (const item of items) {
@@ -6336,6 +6414,18 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
6336
6414
  finalRows++;
6337
6415
  for (const item of unitLine) usedItems.add(item);
6338
6416
  }
6417
+ const filledCells = finalGrid.flat().filter((c) => c.text.trim()).length;
6418
+ if (!rebuiltUsed && filledCells * 2 >= finalGrid.flat().length && !/^\s*\(\s*단위\s*[::]/.test(finalGrid[0]?.[0]?.text ?? "")) {
6419
+ 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);
6420
+ const line = above.filter((it) => Math.abs(it.y - Math.min(...above.map((a) => a.y))) <= 1).sort((a, b) => a.x - b.x);
6421
+ const text = line.map((it) => it.text).join("");
6422
+ const inset = line.length ? grid.bbox.x2 - (line[line.length - 1].x + line[line.length - 1].w) : 0;
6423
+ if (line.length && /^\s*\(\s*단위\s*[::]/.test(text) && inset >= 4.6 && inset <= 5.6) {
6424
+ finalGrid.unshift(Array.from({ length: numCols }, (_, c) => ({ text: c === 0 ? cleanCellText(text) : "", colSpan: c === 0 ? numCols : 1, rowSpan: 1 })));
6425
+ finalRows++;
6426
+ for (const item of line) usedItems.add(item);
6427
+ }
6428
+ }
6339
6429
  let semanticOneColumn = false;
6340
6430
  if (!grid.cells && numCols === 1 && numGridRows >= 2) {
6341
6431
  const populatedRows = finalGrid.filter((row) => row[0]?.text.trim());
@@ -6463,7 +6553,10 @@ function extractBlocksWithGrids(items, pageNum, pageWidth, pageHeight, grids, ho
6463
6553
  hasSpaceBefore: i.hasSpaceBefore
6464
6554
  }));
6465
6555
  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;
6466
- const clusterResults = proseColumns ? [] : detectClusterTables(clusterItems, pageNum);
6556
+ const clusterResults = (proseColumns ? [] : detectClusterTables(clusterItems, pageNum)).filter((cr) => {
6557
+ const b = cr.bbox;
6558
+ return !blocks.some((x) => x.type === "paragraph" && x.bbox && (x.text?.match(/\p{L}/gu)?.length ?? 0) >= 10 && Math.min(x.bbox.x + x.bbox.width, b.x + b.width) - Math.max(x.bbox.x, b.x) >= 0.8 * b.width && x.bbox.y >= b.y - 2 && x.bbox.y + x.bbox.height <= b.y + b.height + 2);
6559
+ });
6467
6560
  if (clusterResults.length > 0) {
6468
6561
  const ciToIdx = /* @__PURE__ */ new Map();
6469
6562
  for (let ci = 0; ci < clusterItems.length; ci++) ciToIdx.set(clusterItems[ci], ci);
@@ -6627,6 +6720,7 @@ function clusterTableBlock(cr, source, pageNum, horizontals = []) {
6627
6720
  if (!ruled && isTableOfContents(cr.table)) return tocBlock(cr.table, pageNum, cr.bbox, dominantStyle(source));
6628
6721
  if (isChartTable(cr.table)) return chartBlock(source, pageNum, cr.bbox);
6629
6722
  if (isFormulaTable(cr.table)) return chartBlock(source, pageNum, cr.bbox);
6723
+ if (isExamLayoutTable(cr.table)) return { ...chartBlock(source, pageNum, cr.bbox), text: groupByY(source).map((line) => mergeLineSimple(line).trim()).filter(Boolean).join("\n") };
6630
6724
  return { type: "table", table: cr.table, pageNumber: pageNum, bbox: cr.bbox };
6631
6725
  }
6632
6726
  function chartBlock(source, pageNum, bbox) {
@@ -6849,6 +6943,7 @@ function extractPageBlocksFallback(items, pageNum, fullPage = false, detectTable
6849
6943
  }
6850
6944
 
6851
6945
  export {
6946
+ extractLines,
6852
6947
  extractImageRegions,
6853
6948
  filterHiddenText,
6854
6949
  collapseEvenSpacing,
@@ -6881,4 +6976,4 @@ export {
6881
6976
  trimTrailingEmptyTableCols,
6882
6977
  extractPageBlocksWithLines
6883
6978
  };
6884
- //# sourceMappingURL=chunk-WMLGS5QL.js.map
6979
+ //# sourceMappingURL=chunk-43FKGDDO.js.map