kordoc 3.8.2 → 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.
package/dist/mcp.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  parse,
11
11
  patchHwp,
12
12
  patchHwpx
13
- } from "./chunk-DP37KF2X.js";
13
+ } from "./chunk-B27QMVL7.js";
14
14
  import {
15
15
  detectFormat,
16
16
  detectZipFormat
@@ -21,7 +21,7 @@ import {
21
21
  blocksToMarkdown,
22
22
  sanitizeError,
23
23
  toArrayBuffer
24
- } from "./chunk-JHZUFBUV.js";
24
+ } from "./chunk-KIWKBRCJ.js";
25
25
  import "./chunk-MOL7MDBG.js";
26
26
 
27
27
  // src/mcp.ts
@@ -193,7 +193,7 @@ server.tool(
193
193
  break;
194
194
  case "pdf":
195
195
  try {
196
- const { extractPdfMetadataOnly } = await import("./parser-KNQDRLZQ.js");
196
+ const { extractPdfMetadataOnly } = await import("./parser-6GP535ZB.js");
197
197
  metadata = await extractPdfMetadataOnly(buffer);
198
198
  } catch {
199
199
  metadata = void 0;
@@ -7,7 +7,7 @@ import {
7
7
  blocksToMarkdown,
8
8
  safeMax,
9
9
  safeMin
10
- } from "./chunk-JHZUFBUV.js";
10
+ } from "./chunk-KIWKBRCJ.js";
11
11
  import {
12
12
  parsePageRange
13
13
  } from "./chunk-MOL7MDBG.js";
@@ -1263,7 +1263,106 @@ function detectClusterTables(items, pageNum) {
1263
1263
  }
1264
1264
  }
1265
1265
  }
1266
- return results;
1266
+ return results.filter((r) => !isTwoColumnProse(r));
1267
+ }
1268
+ function isTwoColumnProse(r) {
1269
+ const t = r.table;
1270
+ if (t.rows < 8) return false;
1271
+ const dense = [];
1272
+ for (let c = 0; c < t.cols; c++) {
1273
+ const filled = t.cells.filter((row) => row[c]?.text.trim()).length;
1274
+ if (filled / t.rows >= 0.3) dense.push(c);
1275
+ }
1276
+ if (dense.length !== 2) return false;
1277
+ for (const c of dense) {
1278
+ const lens = t.cells.map((row) => row[c]?.text.replace(/\s+/g, "").length ?? 0).filter((n) => n > 0);
1279
+ const avg = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
1280
+ if (avg < 12) return false;
1281
+ }
1282
+ return findTwoColumnProseCutX([...r.usedItems]) !== null;
1283
+ }
1284
+ function findTwoColumnProseCutX(items) {
1285
+ const lines = groupByBaseline(items);
1286
+ if (lines.length < 8) return null;
1287
+ let minX = Infinity;
1288
+ let maxX = -Infinity;
1289
+ for (const i of items) {
1290
+ if (i.x < minX) minX = i.x;
1291
+ if (i.x + i.w > maxX) maxX = i.x + i.w;
1292
+ }
1293
+ if (!Number.isFinite(maxX - minX)) return null;
1294
+ if (maxX - minX < 100) return null;
1295
+ const lo = minX + (maxX - minX) * 0.3;
1296
+ const hi = minX + (maxX - minX) * 0.7;
1297
+ const step = Math.max(2, (hi - lo) / 400);
1298
+ let cutX = 0;
1299
+ let bestCover = Infinity;
1300
+ for (let x = lo; x <= hi; x += step) {
1301
+ let cover = 0;
1302
+ for (const line of lines) {
1303
+ if (line.items.some((i) => i.x < x && i.x + i.w > x)) cover++;
1304
+ }
1305
+ if (cover < bestCover) {
1306
+ bestCover = cover;
1307
+ cutX = x;
1308
+ }
1309
+ }
1310
+ if (bestCover / lines.length > 0.15) return null;
1311
+ const left = [];
1312
+ const right = [];
1313
+ let twoSide = 0;
1314
+ for (const line of lines) {
1315
+ let hasL = false;
1316
+ let hasR = false;
1317
+ for (const i of line.items) {
1318
+ if (i.x + i.w <= cutX) {
1319
+ left.push(i);
1320
+ hasL = true;
1321
+ } else if (i.x >= cutX) {
1322
+ right.push(i);
1323
+ hasR = true;
1324
+ }
1325
+ }
1326
+ if (hasL && hasR) twoSide++;
1327
+ }
1328
+ if (twoSide / lines.length < 0.55) return null;
1329
+ if (left.length < 5 || right.length < 5) return null;
1330
+ const allText = items.map((i) => i.text).join("").replace(/\s+/g, "");
1331
+ const digits = (allText.match(/[\d,.%△—-]/g) || []).length;
1332
+ if (allText.length === 0 || digits / allText.length > 0.15) return null;
1333
+ const stats = [left, right].map((side) => {
1334
+ let sMinX = Infinity;
1335
+ let sMaxR = -Infinity;
1336
+ let fsSum = 0;
1337
+ const rowEnds = /* @__PURE__ */ new Map();
1338
+ const rowLens = /* @__PURE__ */ new Map();
1339
+ const rowFirst = /* @__PURE__ */ new Map();
1340
+ for (const i of side) {
1341
+ if (i.x < sMinX) sMinX = i.x;
1342
+ const rgt = i.x + i.w;
1343
+ if (rgt > sMaxR) sMaxR = rgt;
1344
+ fsSum += i.fontSize;
1345
+ const key = Math.round(i.y / 4);
1346
+ rowEnds.set(key, Math.max(rowEnds.get(key) ?? -Infinity, rgt));
1347
+ rowLens.set(key, (rowLens.get(key) ?? 0) + i.text.replace(/\s+/g, "").length);
1348
+ const f = rowFirst.get(key);
1349
+ if (!f || i.x < f.x) rowFirst.set(key, i);
1350
+ }
1351
+ const ends = [...rowEnds.values()].sort((a, b) => a - b);
1352
+ const p85 = ends[Math.floor(ends.length * 0.85)] ?? sMaxR;
1353
+ const fs = fsSum / side.length;
1354
+ const justified = ends.filter((e) => Math.abs(e - p85) <= fs).length / ends.length;
1355
+ const lens = [...rowLens.values()];
1356
+ const avgLen = lens.reduce((s, v) => s + v, 0) / (lens.length || 1);
1357
+ const markers = [...rowFirst.values()].filter((i) => /^[•▪◦‣∙·\-–—□■◇◆▶※*]/.test(i.text)).length;
1358
+ return { width: sMaxR - sMinX, justified, avgLen, markerRatio: markers / (rowFirst.size || 1) };
1359
+ });
1360
+ if (stats.some((s) => s.avgLen < 12)) return null;
1361
+ if (stats.some((s) => s.markerRatio > 0.1)) return null;
1362
+ const widthSym = Math.min(stats[0].width, stats[1].width) / Math.max(stats[0].width, stats[1].width);
1363
+ if (widthSym < 0.6) return null;
1364
+ if (Math.min(stats[0].justified, stats[1].justified) < 0.55) return null;
1365
+ return cutX;
1267
1366
  }
1268
1367
  function mergeEvenSpacedClusters(items) {
1269
1368
  const originMap = /* @__PURE__ */ new Map();
@@ -2460,7 +2559,7 @@ function extractPageBlocksWithLines(items, pageNum, opList, pageWidth, pageHeigh
2460
2559
  if (grids.length > 0) {
2461
2560
  return extractBlocksWithGrids(items, pageNum, grids, horizontals, verticals);
2462
2561
  }
2463
- return extractPageBlocksFallback(items, pageNum);
2562
+ return extractPageBlocksFallback(items, pageNum, true);
2464
2563
  }
2465
2564
  var STRIKE_MAX_THICKNESS = 2;
2466
2565
  var STRIKE_MAX_THICKNESS_RATIO = 0.25;
@@ -2705,7 +2804,53 @@ function mergeAdjacentTableBlocks(blocks) {
2705
2804
  }
2706
2805
  return result;
2707
2806
  }
2708
- function extractPageBlocksFallback(items, pageNum) {
2807
+ function splitTwoColumnProse(items, cutX) {
2808
+ const left = [];
2809
+ const right = [];
2810
+ const cross = [];
2811
+ for (const i of items) {
2812
+ if (i.x + i.w <= cutX) left.push(i);
2813
+ else if (i.x >= cutX) right.push(i);
2814
+ else cross.push(i);
2815
+ }
2816
+ if (cross.length === 0) {
2817
+ return [left, right].filter((g2) => g2.length > 0);
2818
+ }
2819
+ cross.sort((a, b) => b.y - a.y);
2820
+ const crossLines = [];
2821
+ for (const c of cross) {
2822
+ const last = crossLines[crossLines.length - 1];
2823
+ if (last && Math.abs(last[0].y - c.y) <= 3) last.push(c);
2824
+ else crossLines.push([c]);
2825
+ }
2826
+ const bandItem = (arr) => arr.filter((i) => {
2827
+ for (const cl of crossLines) {
2828
+ if (Math.abs(cl[0].y - i.y) <= 3) {
2829
+ cl.push(i);
2830
+ return false;
2831
+ }
2832
+ }
2833
+ return true;
2834
+ });
2835
+ const leftRest = bandItem(left);
2836
+ const rightRest = bandItem(right);
2837
+ const boundYs = crossLines.map((cl) => cl[0].y);
2838
+ const bandOf = (y) => {
2839
+ let k = 0;
2840
+ while (k < boundYs.length && y < boundYs[k]) k++;
2841
+ return k;
2842
+ };
2843
+ const groups = [];
2844
+ for (let k = 0; k <= crossLines.length; k++) {
2845
+ const L = leftRest.filter((i) => bandOf(i.y) === k);
2846
+ const R = rightRest.filter((i) => bandOf(i.y) === k);
2847
+ if (L.length > 0) groups.push(L);
2848
+ if (R.length > 0) groups.push(R);
2849
+ if (k < crossLines.length) groups.push(crossLines[k]);
2850
+ }
2851
+ return groups;
2852
+ }
2853
+ function extractPageBlocksFallback(items, pageNum, fullPage = false) {
2709
2854
  if (items.length === 0) return [];
2710
2855
  const blocks = [];
2711
2856
  const clusterItems = items.map((i) => ({
@@ -2746,8 +2891,9 @@ function extractPageBlocksFallback(items, pageNum) {
2746
2891
  return by - ay;
2747
2892
  });
2748
2893
  } else {
2894
+ const proseCutX = fullPage ? findTwoColumnProseCutX(items) : null;
2749
2895
  const allYLines = mergeSuperscriptLines(groupByY(items));
2750
- const columns = detectColumns(allYLines);
2896
+ const columns = proseCutX !== null ? null : detectColumns(allYLines);
2751
2897
  if (columns && columns.length >= 3) {
2752
2898
  const tableText = extractWithColumns(allYLines, columns);
2753
2899
  const bbox = computeBBox(items, pageNum);
@@ -2756,7 +2902,7 @@ function extractPageBlocksFallback(items, pageNum) {
2756
2902
  const allY = items.map((i) => i.y);
2757
2903
  const pageHeight = safeMax(allY) - safeMin(allY);
2758
2904
  const gapThreshold = Math.max(15, pageHeight * 0.03);
2759
- const orderedGroups = xyCutOrder(items, gapThreshold);
2905
+ const orderedGroups = proseCutX !== null ? splitTwoColumnProse(items, proseCutX) : xyCutOrder(items, gapThreshold);
2760
2906
  for (const group of orderedGroups) {
2761
2907
  if (group.length === 0) continue;
2762
2908
  const yLines = mergeSuperscriptLines(groupByY(group));
@@ -3211,4 +3357,4 @@ export {
3211
3357
  parsePdfDocument,
3212
3358
  removeHeaderFooterBlocks
3213
3359
  };
3214
- //# sourceMappingURL=parser-KNQDRLZQ.js.map
3360
+ //# sourceMappingURL=parser-6GP535ZB.js.map