kordoc 3.8.1 → 3.8.3

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 (32) hide show
  1. package/README.md +12 -0
  2. package/dist/{-LD4BZDDJ.js → -F5IXBLQQ.js} +3 -3
  3. package/dist/{chunk-PELBIL4K.js → chunk-7J73IGMK.js} +2 -2
  4. package/dist/{chunk-KT2BCHXI.js → chunk-B27QMVL7.js} +872 -825
  5. package/dist/chunk-B27QMVL7.js.map +1 -0
  6. package/dist/{chunk-IFYJFWD2.js → chunk-KIWKBRCJ.js} +2 -2
  7. package/dist/{chunk-LFCS3UVG.cjs → chunk-XL6O3VAY.cjs} +2 -2
  8. package/dist/{chunk-LFCS3UVG.cjs.map → chunk-XL6O3VAY.cjs.map} +1 -1
  9. package/dist/cli.js +4 -4
  10. package/dist/index.cjs +1065 -1018
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +17 -8
  13. package/dist/index.d.ts +17 -8
  14. package/dist/index.js +871 -824
  15. package/dist/index.js.map +1 -1
  16. package/dist/mcp.js +3 -3
  17. package/dist/{parser-FFEBMLSH.js → parser-6GP535ZB.js} +211 -25
  18. package/dist/parser-6GP535ZB.js.map +1 -0
  19. package/dist/{parser-XEDROIM7.js → parser-TM3AS25T.js} +211 -25
  20. package/dist/parser-TM3AS25T.js.map +1 -0
  21. package/dist/{parser-IXK5V7YG.cjs → parser-WWKYMRGJ.cjs} +240 -52
  22. package/dist/parser-WWKYMRGJ.cjs.map +1 -0
  23. package/dist/{watch-MAWCDNFI.js → watch-HETTZ7BO.js} +3 -3
  24. package/package.json +2 -1
  25. package/dist/chunk-KT2BCHXI.js.map +0 -1
  26. package/dist/parser-FFEBMLSH.js.map +0 -1
  27. package/dist/parser-IXK5V7YG.cjs.map +0 -1
  28. package/dist/parser-XEDROIM7.js.map +0 -1
  29. /package/dist/{-LD4BZDDJ.js.map → -F5IXBLQQ.js.map} +0 -0
  30. /package/dist/{chunk-PELBIL4K.js.map → chunk-7J73IGMK.js.map} +0 -0
  31. /package/dist/{chunk-IFYJFWD2.js.map → chunk-KIWKBRCJ.js.map} +0 -0
  32. /package/dist/{watch-MAWCDNFI.js.map → watch-HETTZ7BO.js.map} +0 -0
@@ -6,7 +6,7 @@ import {
6
6
  blocksToMarkdown,
7
7
  safeMax,
8
8
  safeMin
9
- } from "./chunk-PELBIL4K.js";
9
+ } from "./chunk-7J73IGMK.js";
10
10
  import {
11
11
  parsePageRange
12
12
  } from "./chunk-GE43BE46.js";
@@ -20,21 +20,30 @@ function extractLines(fnArray, argsArray) {
20
20
  const horizontals = [];
21
21
  const verticals = [];
22
22
  let lineWidth = 1;
23
+ let ctm = [1, 0, 0, 1, 0, 0];
24
+ const ctmStack = [];
25
+ const applyCtm = (x, y) => [ctm[0] * x + ctm[2] * y + ctm[4], ctm[1] * x + ctm[3] * y + ctm[5]];
26
+ const ctmScale = () => (Math.hypot(ctm[0], ctm[1]) + Math.hypot(ctm[2], ctm[3])) / 2;
23
27
  let currentPath = [];
24
28
  let pathStartX = 0, pathStartY = 0;
25
29
  let curX = 0, curY = 0;
26
- function pushRectangle(path, rx, ry, rw, rh) {
27
- if (Math.abs(rh) < ORIENTATION_TOL * 2) {
28
- path.push({ x1: rx, y1: ry + rh / 2, x2: rx + rw, y2: ry + rh / 2 });
29
- } else if (Math.abs(rw) < ORIENTATION_TOL * 2) {
30
- path.push({ x1: rx + rw / 2, y1: ry, x2: rx + rw / 2, y2: ry + rh });
30
+ function pushSeg(x1, y1, x2, y2) {
31
+ const [tx1, ty1] = applyCtm(x1, y1);
32
+ const [tx2, ty2] = applyCtm(x2, y2);
33
+ currentPath.push({ x1: tx1, y1: ty1, x2: tx2, y2: ty2 });
34
+ }
35
+ function pushRectangle(rx, ry, rw, rh) {
36
+ const effH = Math.abs(rh) * Math.hypot(ctm[2], ctm[3]);
37
+ const effW = Math.abs(rw) * Math.hypot(ctm[0], ctm[1]);
38
+ if (effH < ORIENTATION_TOL * 2) {
39
+ pushSeg(rx, ry + rh / 2, rx + rw, ry + rh / 2);
40
+ } else if (effW < ORIENTATION_TOL * 2) {
41
+ pushSeg(rx + rw / 2, ry, rx + rw / 2, ry + rh);
31
42
  } else {
32
- path.push(
33
- { x1: rx, y1: ry, x2: rx + rw, y2: ry },
34
- { x1: rx + rw, y1: ry, x2: rx + rw, y2: ry + rh },
35
- { x1: rx + rw, y1: ry + rh, x2: rx, y2: ry + rh },
36
- { x1: rx, y1: ry + rh, x2: rx, y2: ry }
37
- );
43
+ pushSeg(rx, ry, rx + rw, ry);
44
+ pushSeg(rx + rw, ry, rx + rw, ry + rh);
45
+ pushSeg(rx + rw, ry + rh, rx, ry + rh);
46
+ pushSeg(rx, ry + rh, rx, ry);
38
47
  }
39
48
  }
40
49
  function flushPath(isStroke) {
@@ -42,8 +51,9 @@ function extractLines(fnArray, argsArray) {
42
51
  currentPath = [];
43
52
  return;
44
53
  }
54
+ const effWidth = lineWidth * ctmScale();
45
55
  for (const seg of currentPath) {
46
- classifyAndAdd(seg, lineWidth, horizontals, verticals);
56
+ classifyAndAdd(seg, effWidth, horizontals, verticals);
47
57
  }
48
58
  currentPath = [];
49
59
  }
@@ -54,6 +64,24 @@ function extractLines(fnArray, argsArray) {
54
64
  case OPS.setLineWidth:
55
65
  lineWidth = args[0] || 1;
56
66
  break;
67
+ case OPS.save:
68
+ ctmStack.push(ctm.slice());
69
+ break;
70
+ case OPS.restore:
71
+ ctm = ctmStack.pop() ?? [1, 0, 0, 1, 0, 0];
72
+ break;
73
+ case OPS.transform: {
74
+ const t = args;
75
+ ctm = [
76
+ ctm[0] * t[0] + ctm[2] * t[1],
77
+ ctm[1] * t[0] + ctm[3] * t[1],
78
+ ctm[0] * t[2] + ctm[2] * t[3],
79
+ ctm[1] * t[2] + ctm[3] * t[3],
80
+ ctm[0] * t[4] + ctm[2] * t[5] + ctm[4],
81
+ ctm[1] * t[4] + ctm[3] * t[5] + ctm[5]
82
+ ];
83
+ break;
84
+ }
57
85
  case OPS.constructPath: {
58
86
  const arg0 = args[0];
59
87
  if (Array.isArray(arg0)) {
@@ -68,16 +96,16 @@ function extractLines(fnArray, argsArray) {
68
96
  pathStartY = curY;
69
97
  } else if (subOp === OPS.lineTo) {
70
98
  const x2 = coords[ci++], y2 = coords[ci++];
71
- currentPath.push({ x1: curX, y1: curY, x2, y2 });
99
+ pushSeg(curX, curY, x2, y2);
72
100
  curX = x2;
73
101
  curY = y2;
74
102
  } else if (subOp === OPS.rectangle) {
75
103
  const rx = coords[ci++], ry = coords[ci++];
76
104
  const rw = coords[ci++], rh = coords[ci++];
77
- pushRectangle(currentPath, rx, ry, rw, rh);
105
+ pushRectangle(rx, ry, rw, rh);
78
106
  } else if (subOp === OPS.closePath) {
79
107
  if (curX !== pathStartX || curY !== pathStartY) {
80
- currentPath.push({ x1: curX, y1: curY, x2: pathStartX, y2: pathStartY });
108
+ pushSeg(curX, curY, pathStartX, pathStartY);
81
109
  }
82
110
  curX = pathStartX;
83
111
  curY = pathStartY;
@@ -103,7 +131,7 @@ function extractLines(fnArray, argsArray) {
103
131
  pathStartY = curY;
104
132
  } else if (drawOp === 1 /* lineTo */) {
105
133
  const x2 = pathData[di++], y2 = pathData[di++];
106
- currentPath.push({ x1: curX, y1: curY, x2, y2 });
134
+ pushSeg(curX, curY, x2, y2);
107
135
  curX = x2;
108
136
  curY = y2;
109
137
  } else if (drawOp === 2 /* curveTo */) {
@@ -112,7 +140,7 @@ function extractLines(fnArray, argsArray) {
112
140
  di += 4;
113
141
  } else if (drawOp === 4 /* closePath */) {
114
142
  if (curX !== pathStartX || curY !== pathStartY) {
115
- currentPath.push({ x1: curX, y1: curY, x2: pathStartX, y2: pathStartY });
143
+ pushSeg(curX, curY, pathStartX, pathStartY);
116
144
  }
117
145
  curX = pathStartX;
118
146
  curY = pathStartY;
@@ -1234,7 +1262,106 @@ function detectClusterTables(items, pageNum) {
1234
1262
  }
1235
1263
  }
1236
1264
  }
1237
- return results;
1265
+ return results.filter((r) => !isTwoColumnProse(r));
1266
+ }
1267
+ function isTwoColumnProse(r) {
1268
+ const t = r.table;
1269
+ if (t.rows < 8) return false;
1270
+ const dense = [];
1271
+ for (let c = 0; c < t.cols; c++) {
1272
+ const filled = t.cells.filter((row) => row[c]?.text.trim()).length;
1273
+ if (filled / t.rows >= 0.3) dense.push(c);
1274
+ }
1275
+ if (dense.length !== 2) return false;
1276
+ for (const c of dense) {
1277
+ const lens = t.cells.map((row) => row[c]?.text.replace(/\s+/g, "").length ?? 0).filter((n) => n > 0);
1278
+ const avg = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
1279
+ if (avg < 12) return false;
1280
+ }
1281
+ return findTwoColumnProseCutX([...r.usedItems]) !== null;
1282
+ }
1283
+ function findTwoColumnProseCutX(items) {
1284
+ const lines = groupByBaseline(items);
1285
+ if (lines.length < 8) return null;
1286
+ let minX = Infinity;
1287
+ let maxX = -Infinity;
1288
+ for (const i of items) {
1289
+ if (i.x < minX) minX = i.x;
1290
+ if (i.x + i.w > maxX) maxX = i.x + i.w;
1291
+ }
1292
+ if (!Number.isFinite(maxX - minX)) return null;
1293
+ if (maxX - minX < 100) return null;
1294
+ const lo = minX + (maxX - minX) * 0.3;
1295
+ const hi = minX + (maxX - minX) * 0.7;
1296
+ const step = Math.max(2, (hi - lo) / 400);
1297
+ let cutX = 0;
1298
+ let bestCover = Infinity;
1299
+ for (let x = lo; x <= hi; x += step) {
1300
+ let cover = 0;
1301
+ for (const line of lines) {
1302
+ if (line.items.some((i) => i.x < x && i.x + i.w > x)) cover++;
1303
+ }
1304
+ if (cover < bestCover) {
1305
+ bestCover = cover;
1306
+ cutX = x;
1307
+ }
1308
+ }
1309
+ if (bestCover / lines.length > 0.15) return null;
1310
+ const left = [];
1311
+ const right = [];
1312
+ let twoSide = 0;
1313
+ for (const line of lines) {
1314
+ let hasL = false;
1315
+ let hasR = false;
1316
+ for (const i of line.items) {
1317
+ if (i.x + i.w <= cutX) {
1318
+ left.push(i);
1319
+ hasL = true;
1320
+ } else if (i.x >= cutX) {
1321
+ right.push(i);
1322
+ hasR = true;
1323
+ }
1324
+ }
1325
+ if (hasL && hasR) twoSide++;
1326
+ }
1327
+ if (twoSide / lines.length < 0.55) return null;
1328
+ if (left.length < 5 || right.length < 5) return null;
1329
+ const allText = items.map((i) => i.text).join("").replace(/\s+/g, "");
1330
+ const digits = (allText.match(/[\d,.%△—-]/g) || []).length;
1331
+ if (allText.length === 0 || digits / allText.length > 0.15) return null;
1332
+ const stats = [left, right].map((side) => {
1333
+ let sMinX = Infinity;
1334
+ let sMaxR = -Infinity;
1335
+ let fsSum = 0;
1336
+ const rowEnds = /* @__PURE__ */ new Map();
1337
+ const rowLens = /* @__PURE__ */ new Map();
1338
+ const rowFirst = /* @__PURE__ */ new Map();
1339
+ for (const i of side) {
1340
+ if (i.x < sMinX) sMinX = i.x;
1341
+ const rgt = i.x + i.w;
1342
+ if (rgt > sMaxR) sMaxR = rgt;
1343
+ fsSum += i.fontSize;
1344
+ const key = Math.round(i.y / 4);
1345
+ rowEnds.set(key, Math.max(rowEnds.get(key) ?? -Infinity, rgt));
1346
+ rowLens.set(key, (rowLens.get(key) ?? 0) + i.text.replace(/\s+/g, "").length);
1347
+ const f = rowFirst.get(key);
1348
+ if (!f || i.x < f.x) rowFirst.set(key, i);
1349
+ }
1350
+ const ends = [...rowEnds.values()].sort((a, b) => a - b);
1351
+ const p85 = ends[Math.floor(ends.length * 0.85)] ?? sMaxR;
1352
+ const fs = fsSum / side.length;
1353
+ const justified = ends.filter((e) => Math.abs(e - p85) <= fs).length / ends.length;
1354
+ const lens = [...rowLens.values()];
1355
+ const avgLen = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
1356
+ const markers = [...rowFirst.values()].filter((i) => /^[•▪◦‣∙·\-–—□■◇◆▶※*]/.test(i.text)).length;
1357
+ return { width: sMaxR - sMinX, justified, avgLen, markerRatio: markers / (rowFirst.size || 1) };
1358
+ });
1359
+ if (stats.some((s) => s.avgLen < 12)) return null;
1360
+ if (stats.some((s) => s.markerRatio > 0.1)) return null;
1361
+ const widthSym = Math.min(stats[0].width, stats[1].width) / Math.max(stats[0].width, stats[1].width);
1362
+ if (widthSym < 0.6) return null;
1363
+ if (Math.min(stats[0].justified, stats[1].justified) < 0.55) return null;
1364
+ return cutX;
1238
1365
  }
1239
1366
  function mergeEvenSpacedClusters(items) {
1240
1367
  const originMap = /* @__PURE__ */ new Map();
@@ -2431,7 +2558,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
2431
2558
  if (grids.length > 0) {
2432
2559
  return extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals);
2433
2560
  }
2434
- return extractPageBlocksFallback(items, pageNum);
2561
+ return extractPageBlocksFallback(items, pageNum, true);
2435
2562
  }
2436
2563
  var STRIKE_MAX_THICKNESS = 2;
2437
2564
  var STRIKE_MAX_THICKNESS_RATIO = 0.25;
@@ -2676,7 +2803,53 @@ function mergeAdjacentTableBlocks(blocks) {
2676
2803
  }
2677
2804
  return result;
2678
2805
  }
2679
- function extractPageBlocksFallback(items, pageNum) {
2806
+ function splitTwoColumnProse(items, cutX) {
2807
+ const left = [];
2808
+ const right = [];
2809
+ const cross = [];
2810
+ for (const i of items) {
2811
+ if (i.x + i.w <= cutX) left.push(i);
2812
+ else if (i.x >= cutX) right.push(i);
2813
+ else cross.push(i);
2814
+ }
2815
+ if (cross.length === 0) {
2816
+ return [left, right].filter((g2) => g2.length > 0);
2817
+ }
2818
+ cross.sort((a, b) => b.y - a.y);
2819
+ const crossLines = [];
2820
+ for (const c of cross) {
2821
+ const last = crossLines[crossLines.length - 1];
2822
+ if (last && Math.abs(last[0].y - c.y) <= 3) last.push(c);
2823
+ else crossLines.push([c]);
2824
+ }
2825
+ const bandItem = (arr) => arr.filter((i) => {
2826
+ for (const cl of crossLines) {
2827
+ if (Math.abs(cl[0].y - i.y) <= 3) {
2828
+ cl.push(i);
2829
+ return false;
2830
+ }
2831
+ }
2832
+ return true;
2833
+ });
2834
+ const leftRest = bandItem(left);
2835
+ const rightRest = bandItem(right);
2836
+ const boundYs = crossLines.map((cl) => cl[0].y);
2837
+ const bandOf = (y) => {
2838
+ let k = 0;
2839
+ while (k < boundYs.length && y < boundYs[k]) k++;
2840
+ return k;
2841
+ };
2842
+ const groups = [];
2843
+ for (let k = 0; k <= crossLines.length; k++) {
2844
+ const L = leftRest.filter((i) => bandOf(i.y) === k);
2845
+ const R = rightRest.filter((i) => bandOf(i.y) === k);
2846
+ if (L.length > 0) groups.push(L);
2847
+ if (R.length > 0) groups.push(R);
2848
+ if (k < crossLines.length) groups.push(crossLines[k]);
2849
+ }
2850
+ return groups;
2851
+ }
2852
+ function extractPageBlocksFallback(items, pageNum, fullPage = false) {
2680
2853
  if (items.length === 0) return [];
2681
2854
  const blocks = [];
2682
2855
  const clusterItems = items.map((i) => ({
@@ -2717,8 +2890,9 @@ function extractPageBlocksFallback(items, pageNum) {
2717
2890
  return by - ay;
2718
2891
  });
2719
2892
  } else {
2893
+ const proseCutX = fullPage ? findTwoColumnProseCutX(items) : null;
2720
2894
  const allYLines = mergeSuperscriptLines(groupByY(items));
2721
- const columns = detectColumns(allYLines);
2895
+ const columns = proseCutX !== null ? null : detectColumns(allYLines);
2722
2896
  if (columns && columns.length >= 3) {
2723
2897
  const tableText = extractWithColumns(allYLines, columns);
2724
2898
  const bbox = computeBBox(items, pageNum);
@@ -2727,7 +2901,7 @@ function extractPageBlocksFallback(items, pageNum) {
2727
2901
  const allY = items.map((i) => i.y);
2728
2902
  const pageHeight = safeMax(allY) - safeMin(allY);
2729
2903
  const gapThreshold = Math.max(15, pageHeight * 0.03);
2730
- const orderedGroups = xyCutOrder(items, gapThreshold);
2904
+ const orderedGroups = proseCutX !== null ? splitTwoColumnProse(items, proseCutX) : xyCutOrder(items, gapThreshold);
2731
2905
  for (const group of orderedGroups) {
2732
2906
  if (group.length === 0) continue;
2733
2907
  const yLines = mergeSuperscriptLines(groupByY(group));
@@ -2948,16 +3122,28 @@ g.pdfjsWorker = pdfjsWorker;
2948
3122
 
2949
3123
  // src/pdf/parser.ts
2950
3124
  import { getDocument, GlobalWorkerOptions } from "pdfjs-dist/legacy/build/pdf.mjs";
3125
+ import { createRequire } from "module";
3126
+ import { dirname, join } from "path";
2951
3127
  GlobalWorkerOptions.workerSrc = "";
2952
3128
  var MAX_PAGES = 5e3;
2953
3129
  var MAX_TOTAL_TEXT = 100 * 1024 * 1024;
2954
3130
  var PDF_LOAD_TIMEOUT_MS = 3e4;
3131
+ var pdfjsAssets = {};
3132
+ try {
3133
+ const _require = createRequire(import.meta.url);
3134
+ const pkgDir = dirname(_require.resolve("pdfjs-dist/package.json"));
3135
+ pdfjsAssets.cMapUrl = join(pkgDir, "cmaps") + "/";
3136
+ pdfjsAssets.cMapPacked = true;
3137
+ pdfjsAssets.standardFontDataUrl = join(pkgDir, "standard_fonts") + "/";
3138
+ } catch {
3139
+ }
2955
3140
  async function loadPdfWithTimeout(buffer) {
2956
3141
  const loadingTask = getDocument({
2957
3142
  data: new Uint8Array(buffer),
2958
3143
  useSystemFonts: true,
2959
3144
  disableFontFace: true,
2960
- isEvalSupported: false
3145
+ isEvalSupported: false,
3146
+ ...pdfjsAssets
2961
3147
  });
2962
3148
  let timer;
2963
3149
  try {
@@ -3170,4 +3356,4 @@ export {
3170
3356
  parsePdfDocument,
3171
3357
  removeHeaderFooterBlocks
3172
3358
  };
3173
- //# sourceMappingURL=parser-XEDROIM7.js.map
3359
+ //# sourceMappingURL=parser-TM3AS25T.js.map