js.documents 7.20.34 → 7.20.36
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/layout/reconstruct.cjs +17 -11
- package/dist/layout/reconstruct.js +17 -11
- package/package.json +2 -2
|
@@ -7,6 +7,7 @@ const require_ports_abort = require("../ports/abort.cjs");
|
|
|
7
7
|
const require_layout_lattice = require("./lattice.cjs");
|
|
8
8
|
let pdf_codec_fonts = require("pdf-codec/fonts");
|
|
9
9
|
let pdf_codec_afm_widths = require("pdf-codec/afm-widths");
|
|
10
|
+
let pdf_codec_text_group = require("pdf-codec/text-group");
|
|
10
11
|
//#region src/layout/reconstruct.ts
|
|
11
12
|
const ZERO_MARGINS = {
|
|
12
13
|
topPt: 0,
|
|
@@ -15,6 +16,9 @@ const ZERO_MARGINS = {
|
|
|
15
16
|
leftPt: 0
|
|
16
17
|
};
|
|
17
18
|
const LINE_BASELINE_TOLERANCE_FACTOR = .5;
|
|
19
|
+
function sharesBaseline(anchor, item) {
|
|
20
|
+
return (0, pdf_codec_text_group.runsShareBaseline)(anchor, item, { baselineToleranceEm: LINE_BASELINE_TOLERANCE_FACTOR });
|
|
21
|
+
}
|
|
18
22
|
const DUPLICATE_PAINT_BUCKET_PT = .1;
|
|
19
23
|
function duplicatePaintKey(item) {
|
|
20
24
|
const xBucket = Math.round(item.xPt / DUPLICATE_PAINT_BUCKET_PT);
|
|
@@ -50,10 +54,9 @@ const REDRAW_PASS_SIMILARITY_THRESHOLD = .6;
|
|
|
50
54
|
function groupByBaselineInDocumentOrder(items) {
|
|
51
55
|
const groups = [];
|
|
52
56
|
for (const item of items) {
|
|
53
|
-
const
|
|
54
|
-
const group = groups.find((g) => Math.abs(g.baselineY - item.yPt) <= tolerance);
|
|
57
|
+
const group = groups.find((g) => sharesBaseline(g.anchor, item));
|
|
55
58
|
if (group === void 0) groups.push({
|
|
56
|
-
|
|
59
|
+
anchor: item,
|
|
57
60
|
items: [item]
|
|
58
61
|
});
|
|
59
62
|
else group.items.push(item);
|
|
@@ -126,11 +129,11 @@ function clusterIntoLines(items) {
|
|
|
126
129
|
const sorted = [...dropDuplicatePaints(dropFuzzyRedrawnPasses(items))].sort((a, b) => b.yPt - a.yPt || a.xPt - b.xPt);
|
|
127
130
|
const working = [];
|
|
128
131
|
for (const item of sorted) {
|
|
129
|
-
const
|
|
130
|
-
const line = working.find((l) => Math.abs(l.baselineY - item.yPt) <= tolerance);
|
|
132
|
+
const line = working.find((l) => sharesBaseline(l.anchor, item));
|
|
131
133
|
if (line === void 0) working.push({
|
|
132
134
|
items: [item],
|
|
133
|
-
baselineY: item.yPt
|
|
135
|
+
baselineY: item.yPt,
|
|
136
|
+
anchor: item
|
|
134
137
|
});
|
|
135
138
|
else line.items.push(item);
|
|
136
139
|
}
|
|
@@ -160,6 +163,10 @@ function textItemToContentRun(item) {
|
|
|
160
163
|
};
|
|
161
164
|
}
|
|
162
165
|
const MIN_WORD_GAP_PT = .5;
|
|
166
|
+
function gapExceeds(previous, next, thresholdPt) {
|
|
167
|
+
const gap = (0, pdf_codec_text_group.runGapPt)(previous, next);
|
|
168
|
+
return gap !== void 0 && gap > thresholdPt;
|
|
169
|
+
}
|
|
163
170
|
function textBoxOfItem(item, pageIndex) {
|
|
164
171
|
const { ascentPt, descentPt } = textItemVerticalExtent(item);
|
|
165
172
|
return {
|
|
@@ -194,9 +201,8 @@ function pushRunsForLine(runs, line, pageIndex) {
|
|
|
194
201
|
line.items.forEach((item, itemIndex) => {
|
|
195
202
|
if (itemIndex > 0) {
|
|
196
203
|
const prevItem = line.items[itemIndex - 1];
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
else if (gap > MIN_WORD_GAP_PT) runs[runs.length - 1].text += " ";
|
|
204
|
+
if (gapExceeds(prevItem, item, LARGE_GAP_EM_MULTIPLIER * item.sizePt)) runs.push({ text: " " });
|
|
205
|
+
else if (gapExceeds(prevItem, item, MIN_WORD_GAP_PT)) runs[runs.length - 1].text += " ";
|
|
200
206
|
}
|
|
201
207
|
const run = textItemToContentRun(item);
|
|
202
208
|
require_layout_shared.stampFrame(run, pageIndex, textBoxOfItem(item, pageIndex));
|
|
@@ -720,7 +726,7 @@ function splitLineByLargeGaps(line) {
|
|
|
720
726
|
line.items.forEach((item, i) => {
|
|
721
727
|
if (i > 0) {
|
|
722
728
|
const prev = line.items[i - 1];
|
|
723
|
-
if (
|
|
729
|
+
if (gapExceeds(prev, item, LARGE_GAP_EM_MULTIPLIER * item.sizePt)) {
|
|
724
730
|
segments.push({
|
|
725
731
|
items: current,
|
|
726
732
|
baselineY: line.baselineY
|
|
@@ -1340,7 +1346,7 @@ function joinCellText(items) {
|
|
|
1340
1346
|
sorted.forEach((item, i) => {
|
|
1341
1347
|
if (i > 0) {
|
|
1342
1348
|
const prev = sorted[i - 1];
|
|
1343
|
-
if (
|
|
1349
|
+
if (gapExceeds(prev, item, MIN_WORD_GAP_PT)) text += " ";
|
|
1344
1350
|
}
|
|
1345
1351
|
text += item.text;
|
|
1346
1352
|
});
|
|
@@ -6,6 +6,7 @@ import { throwIfAborted } from "../ports/abort.js";
|
|
|
6
6
|
import { detectGridLattice, findColumnIndex, findRowIndex } from "./lattice.js";
|
|
7
7
|
import { resolveStandardFont } from "pdf-codec/fonts";
|
|
8
8
|
import { STANDARD_METRICS } from "pdf-codec/afm-widths";
|
|
9
|
+
import { runGapPt, runsShareBaseline } from "pdf-codec/text-group";
|
|
9
10
|
//#region src/layout/reconstruct.ts
|
|
10
11
|
const ZERO_MARGINS = {
|
|
11
12
|
topPt: 0,
|
|
@@ -14,6 +15,9 @@ const ZERO_MARGINS = {
|
|
|
14
15
|
leftPt: 0
|
|
15
16
|
};
|
|
16
17
|
const LINE_BASELINE_TOLERANCE_FACTOR = .5;
|
|
18
|
+
function sharesBaseline(anchor, item) {
|
|
19
|
+
return runsShareBaseline(anchor, item, { baselineToleranceEm: LINE_BASELINE_TOLERANCE_FACTOR });
|
|
20
|
+
}
|
|
17
21
|
const DUPLICATE_PAINT_BUCKET_PT = .1;
|
|
18
22
|
function duplicatePaintKey(item) {
|
|
19
23
|
const xBucket = Math.round(item.xPt / DUPLICATE_PAINT_BUCKET_PT);
|
|
@@ -49,10 +53,9 @@ const REDRAW_PASS_SIMILARITY_THRESHOLD = .6;
|
|
|
49
53
|
function groupByBaselineInDocumentOrder(items) {
|
|
50
54
|
const groups = [];
|
|
51
55
|
for (const item of items) {
|
|
52
|
-
const
|
|
53
|
-
const group = groups.find((g) => Math.abs(g.baselineY - item.yPt) <= tolerance);
|
|
56
|
+
const group = groups.find((g) => sharesBaseline(g.anchor, item));
|
|
54
57
|
if (group === void 0) groups.push({
|
|
55
|
-
|
|
58
|
+
anchor: item,
|
|
56
59
|
items: [item]
|
|
57
60
|
});
|
|
58
61
|
else group.items.push(item);
|
|
@@ -125,11 +128,11 @@ function clusterIntoLines(items) {
|
|
|
125
128
|
const sorted = [...dropDuplicatePaints(dropFuzzyRedrawnPasses(items))].sort((a, b) => b.yPt - a.yPt || a.xPt - b.xPt);
|
|
126
129
|
const working = [];
|
|
127
130
|
for (const item of sorted) {
|
|
128
|
-
const
|
|
129
|
-
const line = working.find((l) => Math.abs(l.baselineY - item.yPt) <= tolerance);
|
|
131
|
+
const line = working.find((l) => sharesBaseline(l.anchor, item));
|
|
130
132
|
if (line === void 0) working.push({
|
|
131
133
|
items: [item],
|
|
132
|
-
baselineY: item.yPt
|
|
134
|
+
baselineY: item.yPt,
|
|
135
|
+
anchor: item
|
|
133
136
|
});
|
|
134
137
|
else line.items.push(item);
|
|
135
138
|
}
|
|
@@ -159,6 +162,10 @@ function textItemToContentRun(item) {
|
|
|
159
162
|
};
|
|
160
163
|
}
|
|
161
164
|
const MIN_WORD_GAP_PT = .5;
|
|
165
|
+
function gapExceeds(previous, next, thresholdPt) {
|
|
166
|
+
const gap = runGapPt(previous, next);
|
|
167
|
+
return gap !== void 0 && gap > thresholdPt;
|
|
168
|
+
}
|
|
162
169
|
function textBoxOfItem(item, pageIndex) {
|
|
163
170
|
const { ascentPt, descentPt } = textItemVerticalExtent(item);
|
|
164
171
|
return {
|
|
@@ -193,9 +200,8 @@ function pushRunsForLine(runs, line, pageIndex) {
|
|
|
193
200
|
line.items.forEach((item, itemIndex) => {
|
|
194
201
|
if (itemIndex > 0) {
|
|
195
202
|
const prevItem = line.items[itemIndex - 1];
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
else if (gap > MIN_WORD_GAP_PT) runs[runs.length - 1].text += " ";
|
|
203
|
+
if (gapExceeds(prevItem, item, LARGE_GAP_EM_MULTIPLIER * item.sizePt)) runs.push({ text: " " });
|
|
204
|
+
else if (gapExceeds(prevItem, item, MIN_WORD_GAP_PT)) runs[runs.length - 1].text += " ";
|
|
199
205
|
}
|
|
200
206
|
const run = textItemToContentRun(item);
|
|
201
207
|
stampFrame(run, pageIndex, textBoxOfItem(item, pageIndex));
|
|
@@ -719,7 +725,7 @@ function splitLineByLargeGaps(line) {
|
|
|
719
725
|
line.items.forEach((item, i) => {
|
|
720
726
|
if (i > 0) {
|
|
721
727
|
const prev = line.items[i - 1];
|
|
722
|
-
if (
|
|
728
|
+
if (gapExceeds(prev, item, LARGE_GAP_EM_MULTIPLIER * item.sizePt)) {
|
|
723
729
|
segments.push({
|
|
724
730
|
items: current,
|
|
725
731
|
baselineY: line.baselineY
|
|
@@ -1339,7 +1345,7 @@ function joinCellText(items) {
|
|
|
1339
1345
|
sorted.forEach((item, i) => {
|
|
1340
1346
|
if (i > 0) {
|
|
1341
1347
|
const prev = sorted[i - 1];
|
|
1342
|
-
if (
|
|
1348
|
+
if (gapExceeds(prev, item, MIN_WORD_GAP_PT)) text += " ";
|
|
1343
1349
|
}
|
|
1344
1350
|
text += item.text;
|
|
1345
1351
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js.documents",
|
|
3
|
-
"version": "7.20.
|
|
3
|
+
"version": "7.20.36",
|
|
4
4
|
"description": "Bidirectional docx/pptx <-> PDF conversion and a read+write editable OOXML document model, built on ooxml.js and Zod 4 codecs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"markdown-codec": "7.0.1",
|
|
87
87
|
"odf.js": "8.0.1",
|
|
88
88
|
"ooxml.js": "9.1.2",
|
|
89
|
-
"pdf-codec": "5.0
|
|
89
|
+
"pdf-codec": "5.2.0",
|
|
90
90
|
"ppt-codec": "2.0.1",
|
|
91
91
|
"rtf-codec": "5.0.1",
|
|
92
92
|
"temml": "0.13.4",
|