js.documents 14.5.0 → 14.6.1
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/README.md +27 -3
- package/dist/{composition-plan-Cofo9qPI.d.cts → composition-plan-D7mR0HWB.d.cts} +5 -0
- package/dist/{composition-plan-BgsXTscN.cjs → composition-plan-DJQgPvBj.cjs} +5 -3
- package/dist/{composition-plan-mRolIOZY.js → composition-plan-DMTkmk8n.js} +5 -3
- package/dist/{composition-plan-B1Nn2JCQ.d.ts → composition-plan-DPZq6NhK.d.ts} +5 -0
- package/dist/convert/composition-plan.cjs +1 -1
- package/dist/convert/composition-plan.d.cts +1 -1
- package/dist/convert/composition-plan.d.ts +1 -1
- package/dist/convert/composition-plan.js +1 -1
- package/dist/convert/composition-to-pdf.cjs +1 -1
- package/dist/convert/composition-to-pdf.d.cts +1 -1
- package/dist/convert/composition-to-pdf.d.ts +1 -1
- package/dist/convert/composition-to-pdf.js +1 -1
- package/dist/convert/composition.cjs +1 -1
- package/dist/convert/composition.d.cts +1 -1
- package/dist/convert/composition.d.ts +1 -1
- package/dist/convert/composition.js +1 -1
- package/dist/convert/from-pdf.cjs +14 -4
- package/dist/convert/from-pdf.d.cts +9 -0
- package/dist/convert/from-pdf.d.ts +9 -0
- package/dist/convert/from-pdf.js +14 -4
- package/dist/convert/local.cjs +1 -1
- package/dist/convert/local.js +1 -1
- package/dist/edit/pdf/editor.d.cts +1 -1
- package/dist/edit/pdf/editor.d.ts +1 -1
- package/dist/index.cjs +8 -2
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/layout/reading-order.cjs +202 -0
- package/dist/layout/reading-order.d.cts +40 -0
- package/dist/layout/reading-order.d.ts +40 -0
- package/dist/layout/reading-order.js +200 -0
- package/dist/layout/reconstruct-presentations-prod.cjs +1 -1
- package/dist/layout/reconstruct-presentations-prod.js +1 -1
- package/dist/layout/reconstruct-tables.cjs +1 -1
- package/dist/layout/reconstruct-tables.js +1 -1
- package/dist/layout/reconstruct.cjs +1 -1
- package/dist/layout/reconstruct.js +1 -1
- package/dist/{reconstruct-presentations-prod-CA4no_aw.cjs → reconstruct-presentations-prod-CsvGlvP2.cjs} +9 -5
- package/dist/{reconstruct-presentations-prod-CC8ct-5O.js → reconstruct-presentations-prod-D1KbGPxa.js} +9 -5
- package/package.json +2 -2
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { clusterIntoLines } from "./reconstruct-lines.js";
|
|
2
|
+
import { resolveStandardFont } from "pdf-codec/fonts";
|
|
3
|
+
import { afmWidthOfCode } from "pdf-codec/afm-widths";
|
|
4
|
+
//#region src/layout/reading-order.ts
|
|
5
|
+
const MIN_COLUMN_LINES = 3;
|
|
6
|
+
const MIN_PROSE_MEASURE_CHARS = 20;
|
|
7
|
+
const SPACE_CHAR_CODE = 32;
|
|
8
|
+
const AFM_UNITS_PER_EM = 1e3;
|
|
9
|
+
/**
|
|
10
|
+
* Splits a page's text items into reading-order flows at the column gutters the page's geometry states.
|
|
11
|
+
* @param items - The page's text items in content-stream order, after any table recovery has removed the text it claimed.
|
|
12
|
+
* @returns The flows in reading order, and a locator placing anything else among them. A page with no gutter yields one flow whose lines are `clusterIntoLines(items)`.
|
|
13
|
+
*/
|
|
14
|
+
function readingOrder(items) {
|
|
15
|
+
const bands = segment(items);
|
|
16
|
+
const regions = [];
|
|
17
|
+
collectRegions(bands, [], regions);
|
|
18
|
+
return {
|
|
19
|
+
regions,
|
|
20
|
+
locate: (xPt, yPt) => locate(bands, xPt, yPt)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Orders two placed blocks for reading: by reading-order path first, then top to bottom by y.
|
|
25
|
+
* @returns Negative when `a` is read first, positive when `b` is, zero when neither precedes the other.
|
|
26
|
+
*/
|
|
27
|
+
function compareReadingPosition(a, b) {
|
|
28
|
+
const length = Math.min(a.path.length, b.path.length);
|
|
29
|
+
for (let i = 0; i < length; i++) {
|
|
30
|
+
const difference = a.path[i] - b.path[i];
|
|
31
|
+
if (difference !== 0) return difference;
|
|
32
|
+
}
|
|
33
|
+
return a.path.length - b.path.length || b.yPt - a.yPt;
|
|
34
|
+
}
|
|
35
|
+
function segment(items) {
|
|
36
|
+
const lines = clusterIntoLines(items);
|
|
37
|
+
const split = findColumnSplit(lines);
|
|
38
|
+
if (split === void 0) return [flowBand(lines)];
|
|
39
|
+
const before = lines.slice(0, split.startLine);
|
|
40
|
+
const band = lines.slice(split.startLine, split.endLine);
|
|
41
|
+
const after = lines.slice(split.endLine);
|
|
42
|
+
return [
|
|
43
|
+
...before.length > 0 ? segment(itemsOf(before)) : [],
|
|
44
|
+
{
|
|
45
|
+
kind: "columns",
|
|
46
|
+
gutterXPt: (split.loPt + split.hiPt) / 2,
|
|
47
|
+
left: segment(split.left),
|
|
48
|
+
right: segment(split.right),
|
|
49
|
+
topPt: band[0].baselineY,
|
|
50
|
+
bottomPt: band.at(-1).baselineY
|
|
51
|
+
},
|
|
52
|
+
...after.length > 0 ? segment(itemsOf(after)) : []
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
function flowBand(lines) {
|
|
56
|
+
return {
|
|
57
|
+
kind: "flow",
|
|
58
|
+
lines,
|
|
59
|
+
topPt: lines[0]?.baselineY ?? Number.POSITIVE_INFINITY,
|
|
60
|
+
bottomPt: lines.at(-1)?.baselineY ?? Number.NEGATIVE_INFINITY
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function itemsOf(lines) {
|
|
64
|
+
return lines.flatMap((line) => line.items);
|
|
65
|
+
}
|
|
66
|
+
function collectRegions(bands, prefix, into) {
|
|
67
|
+
bands.forEach((band, index) => {
|
|
68
|
+
if (band.kind === "flow") into.push({
|
|
69
|
+
lines: band.lines,
|
|
70
|
+
path: [...prefix, index]
|
|
71
|
+
});
|
|
72
|
+
else {
|
|
73
|
+
collectRegions(band.left, [
|
|
74
|
+
...prefix,
|
|
75
|
+
index,
|
|
76
|
+
0
|
|
77
|
+
], into);
|
|
78
|
+
collectRegions(band.right, [
|
|
79
|
+
...prefix,
|
|
80
|
+
index,
|
|
81
|
+
1
|
|
82
|
+
], into);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function locate(bands, xPt, yPt) {
|
|
87
|
+
let index = bands.length - 1;
|
|
88
|
+
for (let i = 0; i + 1 < bands.length; i++) if (yPt >= (bands[i].bottomPt + bands[i + 1].topPt) / 2) {
|
|
89
|
+
index = i;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
const band = bands[index];
|
|
93
|
+
if (band.kind === "flow") return [index];
|
|
94
|
+
const side = xPt < band.gutterXPt ? 0 : 1;
|
|
95
|
+
return [
|
|
96
|
+
index,
|
|
97
|
+
side,
|
|
98
|
+
...locate(side === 0 ? band.left : band.right, xPt, yPt)
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
function findColumnSplit(lines) {
|
|
102
|
+
const items = itemsOf(lines);
|
|
103
|
+
if (lines.length < MIN_COLUMN_LINES || !items.every(isMeasurable)) return;
|
|
104
|
+
const runs = gutterRuns(lines, Math.min(...items.map(spaceAdvancePt))).sort((a, b) => b.endLine - b.startLine - (a.endLine - a.startLine) || b.hiPt - b.loPt - (a.hiPt - a.loPt) || a.startLine - b.startLine);
|
|
105
|
+
for (const run of runs) {
|
|
106
|
+
const runItems = itemsOf(lines.slice(run.startLine, run.endLine));
|
|
107
|
+
if (run.hiPt - run.loPt <= Math.max(...runItems.map(spaceAdvancePt))) continue;
|
|
108
|
+
const left = runItems.filter((item) => rightEdge(item) <= run.loPt);
|
|
109
|
+
const right = runItems.filter((item) => item.xPt >= run.hiPt);
|
|
110
|
+
if (isRunningProse(left, run.hiPt - run.loPt) && isRunningProse(right, run.hiPt - run.loPt)) return {
|
|
111
|
+
...run,
|
|
112
|
+
left,
|
|
113
|
+
right
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function isMeasurable(item) {
|
|
118
|
+
return item.widthPt !== void 0 && item.writingMode === void 0 && (item.rotationDeg ?? 0) === 0;
|
|
119
|
+
}
|
|
120
|
+
function rightEdge(item) {
|
|
121
|
+
return item.xPt + (item.widthPt ?? 0);
|
|
122
|
+
}
|
|
123
|
+
function spaceAdvancePt(item) {
|
|
124
|
+
const { standardName } = resolveStandardFont(item.font.family, item.font.weight === "bold", item.font.style === "italic");
|
|
125
|
+
const advance = afmWidthOfCode(standardName, SPACE_CHAR_CODE);
|
|
126
|
+
if (advance === void 0) throw new Error(`${standardName} has no AFM width for the space glyph`);
|
|
127
|
+
return advance / AFM_UNITS_PER_EM * item.sizePt;
|
|
128
|
+
}
|
|
129
|
+
function freeSpans(line) {
|
|
130
|
+
const sorted = [...line.items].sort((a, b) => a.xPt - b.xPt);
|
|
131
|
+
const spans = [];
|
|
132
|
+
let reachedPt = Number.NEGATIVE_INFINITY;
|
|
133
|
+
for (const item of sorted) {
|
|
134
|
+
if (item.xPt > reachedPt) spans.push({
|
|
135
|
+
loPt: reachedPt,
|
|
136
|
+
hiPt: item.xPt
|
|
137
|
+
});
|
|
138
|
+
reachedPt = Math.max(reachedPt, rightEdge(item));
|
|
139
|
+
}
|
|
140
|
+
spans.push({
|
|
141
|
+
loPt: reachedPt,
|
|
142
|
+
hiPt: Number.POSITIVE_INFINITY
|
|
143
|
+
});
|
|
144
|
+
return spans;
|
|
145
|
+
}
|
|
146
|
+
function gutterRuns(lines, minWidthPt) {
|
|
147
|
+
const runs = [];
|
|
148
|
+
let open = /* @__PURE__ */ new Map();
|
|
149
|
+
const record = (span, endLine) => {
|
|
150
|
+
if (Number.isFinite(span.loPt) && Number.isFinite(span.hiPt) && endLine - span.startLine >= MIN_COLUMN_LINES) runs.push({
|
|
151
|
+
...span,
|
|
152
|
+
endLine
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
lines.forEach((line, lineIndex) => {
|
|
156
|
+
const next = /* @__PURE__ */ new Map();
|
|
157
|
+
const keep = (loPt, hiPt, startLine) => {
|
|
158
|
+
if (hiPt - loPt <= minWidthPt) return;
|
|
159
|
+
const key = `${String(loPt)}|${String(hiPt)}`;
|
|
160
|
+
const existing = next.get(key);
|
|
161
|
+
if (existing === void 0 || startLine < existing.startLine) next.set(key, {
|
|
162
|
+
loPt,
|
|
163
|
+
hiPt,
|
|
164
|
+
startLine
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
const spans = freeSpans(line);
|
|
168
|
+
for (const strip of open.values()) for (const span of spans) keep(Math.max(strip.loPt, span.loPt), Math.min(strip.hiPt, span.hiPt), strip.startLine);
|
|
169
|
+
for (const span of spans) keep(span.loPt, span.hiPt, lineIndex);
|
|
170
|
+
for (const [key, strip] of open) if (next.get(key)?.startLine !== strip.startLine) record(strip, lineIndex);
|
|
171
|
+
open = next;
|
|
172
|
+
});
|
|
173
|
+
for (const strip of open.values()) record(strip, lines.length);
|
|
174
|
+
return runs;
|
|
175
|
+
}
|
|
176
|
+
function isRunningProse(items, gutterWidthPt) {
|
|
177
|
+
const lines = clusterIntoLines(items);
|
|
178
|
+
if (lines.length < MIN_COLUMN_LINES) return false;
|
|
179
|
+
const characters = items.reduce((sum, item) => sum + item.text.length, 0);
|
|
180
|
+
const advancePt = items.reduce((sum, item) => sum + (item.widthPt ?? 0), 0);
|
|
181
|
+
if (characters === 0 || advancePt === 0) return false;
|
|
182
|
+
const leftPt = Math.min(...items.map((item) => item.xPt));
|
|
183
|
+
const rightPt = Math.max(...items.map(rightEdge));
|
|
184
|
+
if ((rightPt - leftPt) / (advancePt / characters) < MIN_PROSE_MEASURE_CHARS) return false;
|
|
185
|
+
for (const line of lines) for (const span of freeSpans(line)) if (Number.isFinite(span.loPt) && Number.isFinite(span.hiPt) && span.hiPt - span.loPt >= gutterWidthPt) return false;
|
|
186
|
+
let wrapped = 0;
|
|
187
|
+
for (let i = 0; i + 1 < lines.length; i++) {
|
|
188
|
+
const lineRightPt = Math.max(...lines[i].items.map(rightEdge));
|
|
189
|
+
const nextFirst = lines[i + 1].items[0];
|
|
190
|
+
if (rightPt - lineRightPt < firstWordWidthPt(nextFirst) + spaceAdvancePt(nextFirst)) wrapped++;
|
|
191
|
+
}
|
|
192
|
+
return wrapped * 2 > lines.length - 1;
|
|
193
|
+
}
|
|
194
|
+
function firstWordWidthPt(item) {
|
|
195
|
+
const text = item.text.trimStart();
|
|
196
|
+
const firstWord = text.split(/\s/u)[0] ?? text;
|
|
197
|
+
return text.length === 0 ? 0 : (item.widthPt ?? 0) * firstWord.length / item.text.length;
|
|
198
|
+
}
|
|
199
|
+
//#endregion
|
|
200
|
+
export { compareReadingPosition, readingOrder };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_reconstruct_presentations_prod = require("../reconstruct-presentations-prod-
|
|
2
|
+
const require_reconstruct_presentations_prod = require("../reconstruct-presentations-prod-CsvGlvP2.cjs");
|
|
3
3
|
exports.layoutItemToVector = require_reconstruct_presentations_prod.layoutItemToVector;
|
|
4
4
|
exports.lineToParagraph = require_reconstruct_presentations_prod.lineToParagraph;
|
|
5
5
|
exports.reconstructDrawing = require_reconstruct_presentations_prod.reconstructDrawing;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as reconstructSheet, i as reconstructPresentation, n as lineToParagraph, o as recoverPageVectors, r as reconstructDrawing, s as splitLineByLargeGaps, t as layoutItemToVector } from "../reconstruct-presentations-prod-
|
|
1
|
+
import { a as reconstructSheet, i as reconstructPresentation, n as lineToParagraph, o as recoverPageVectors, r as reconstructDrawing, s as splitLineByLargeGaps, t as layoutItemToVector } from "../reconstruct-presentations-prod-D1KbGPxa.js";
|
|
2
2
|
export { layoutItemToVector, lineToParagraph, reconstructDrawing, reconstructPresentation, reconstructSheet, recoverPageVectors, splitLineByLargeGaps };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_reconstruct_presentations_prod = require("../reconstruct-presentations-prod-
|
|
2
|
+
const require_reconstruct_presentations_prod = require("../reconstruct-presentations-prod-CsvGlvP2.cjs");
|
|
3
3
|
exports.buildGridFromLattice = require_reconstruct_presentations_prod.buildGridFromLattice;
|
|
4
4
|
exports.buildGridFromTextClustering = require_reconstruct_presentations_prod.buildGridFromTextClustering;
|
|
5
5
|
exports.recoverTables = require_reconstruct_presentations_prod.recoverTables;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { b as recoverTables, v as buildGridFromLattice, y as buildGridFromTextClustering } from "../reconstruct-presentations-prod-
|
|
1
|
+
import { b as recoverTables, v as buildGridFromLattice, y as buildGridFromTextClustering } from "../reconstruct-presentations-prod-D1KbGPxa.js";
|
|
2
2
|
export { buildGridFromLattice, buildGridFromTextClustering, recoverTables };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_reconstruct_presentations_prod = require("../reconstruct-presentations-prod-
|
|
2
|
+
const require_reconstruct_presentations_prod = require("../reconstruct-presentations-prod-CsvGlvP2.cjs");
|
|
3
3
|
exports.CELL_TYPES = require_reconstruct_presentations_prod.CELL_TYPES;
|
|
4
4
|
exports.DEFAULT_COLUMN_WIDTH_FALLBACK_PT = require_reconstruct_presentations_prod.DEFAULT_COLUMN_WIDTH_FALLBACK_PT;
|
|
5
5
|
exports.NO_ITEMS = require_reconstruct_presentations_prod.NO_ITEMS;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as reconstructWordprocessing, c as CELL_TYPES, d as ROW_TYPES, f as TABLE_TYPES, g as reconstructSpreadsheet, h as nearestOfType, l as DEFAULT_COLUMN_WIDTH_FALLBACK_PT, m as indexStructure, p as ZERO_MARGINS, u as NO_ITEMS } from "../reconstruct-presentations-prod-
|
|
1
|
+
import { _ as reconstructWordprocessing, c as CELL_TYPES, d as ROW_TYPES, f as TABLE_TYPES, g as reconstructSpreadsheet, h as nearestOfType, l as DEFAULT_COLUMN_WIDTH_FALLBACK_PT, m as indexStructure, p as ZERO_MARGINS, u as NO_ITEMS } from "../reconstruct-presentations-prod-D1KbGPxa.js";
|
|
2
2
|
export { CELL_TYPES, DEFAULT_COLUMN_WIDTH_FALLBACK_PT, NO_ITEMS, ROW_TYPES, TABLE_TYPES, ZERO_MARGINS, indexStructure, nearestOfType, reconstructSpreadsheet, reconstructWordprocessing };
|
|
@@ -5,6 +5,7 @@ const require_layout_cell_typing = require("./layout/cell-typing.cjs");
|
|
|
5
5
|
const require_ports_abort = require("./ports/abort.cjs");
|
|
6
6
|
const require_layout_reconstruct_lines = require("./layout/reconstruct-lines.cjs");
|
|
7
7
|
const require_layout_lattice = require("./layout/lattice.cjs");
|
|
8
|
+
const require_layout_reading_order = require("./layout/reading-order.cjs");
|
|
8
9
|
let document_schema_js = require("document-schema.js");
|
|
9
10
|
let pdf_codec_layout = require("pdf-codec/layout");
|
|
10
11
|
//#region src/layout/reconstruct-tables.ts
|
|
@@ -519,19 +520,19 @@ function reconstructPageBlocks(page, pageIndex, images, headingLevels, form, str
|
|
|
519
520
|
}
|
|
520
521
|
const textItems = page.items.filter((i) => i.kind === "text" && !consumedText.has(i));
|
|
521
522
|
const imageItems = page.items.filter((i) => i.kind === "image");
|
|
522
|
-
const
|
|
523
|
-
const paragraphs = require_layout_reconstruct_lines.clusterIntoParagraphs(lines);
|
|
523
|
+
const order = require_layout_reading_order.readingOrder(textItems);
|
|
524
524
|
const recordDivisions = (block, items) => {
|
|
525
525
|
if (structure !== void 0) divisionByBlock.set(block, divisionChainOf(items, structure));
|
|
526
526
|
};
|
|
527
527
|
const positioned = [];
|
|
528
|
-
for (const paragraph of
|
|
528
|
+
for (const { lines, path } of order.regions) for (const paragraph of require_layout_reconstruct_lines.clusterIntoParagraphs(lines)) {
|
|
529
529
|
const paragraphItems = paragraph.lines.flatMap((line) => line.items);
|
|
530
530
|
const structural = structure === void 0 ? void 0 : structureHeadingLevel(paragraphItems, structure);
|
|
531
531
|
const headingLevel = structural !== void 0 ? structural.level : headingLevelOf(paragraph, headingLevels);
|
|
532
532
|
const block = require_layout_reconstruct_lines.paragraphToContentParagraph(paragraph, pageIndex, headingLevel);
|
|
533
533
|
recordDivisions(block, paragraphItems);
|
|
534
534
|
positioned.push({
|
|
535
|
+
path,
|
|
535
536
|
yPt: paragraph.lines[0].baselineY,
|
|
536
537
|
block
|
|
537
538
|
});
|
|
@@ -554,6 +555,7 @@ function reconstructPageBlocks(page, pageIndex, images, headingLevels, form, str
|
|
|
554
555
|
});
|
|
555
556
|
recordDivisions(block, [img]);
|
|
556
557
|
positioned.push({
|
|
558
|
+
path: order.locate(img.xPt + img.widthPt / 2, img.yPt),
|
|
557
559
|
yPt: img.yPt,
|
|
558
560
|
block
|
|
559
561
|
});
|
|
@@ -562,6 +564,7 @@ function reconstructPageBlocks(page, pageIndex, images, headingLevels, form, str
|
|
|
562
564
|
for (const recovered of recoveredTables) {
|
|
563
565
|
recordDivisions(recovered.table, [...recovered.consumedText]);
|
|
564
566
|
positioned.push({
|
|
567
|
+
path: order.locate(recovered.frame.xPt + recovered.frame.widthPt / 2, recovered.topYPt),
|
|
565
568
|
yPt: recovered.topYPt,
|
|
566
569
|
block: recovered.table
|
|
567
570
|
});
|
|
@@ -571,11 +574,12 @@ function reconstructPageBlocks(page, pageIndex, images, headingLevels, form, str
|
|
|
571
574
|
const vectorItems = page.items.filter((item) => !claimedItems.has(item) && layoutItemToVector(item, page.heightPt) !== void 0);
|
|
572
575
|
recordDivisions(recoveredVectors.block, vectorItems);
|
|
573
576
|
positioned.push({
|
|
577
|
+
path: order.locate(Number.NEGATIVE_INFINITY, recoveredVectors.topYPt),
|
|
574
578
|
yPt: recoveredVectors.topYPt,
|
|
575
579
|
block: recoveredVectors.block
|
|
576
580
|
});
|
|
577
581
|
}
|
|
578
|
-
positioned.sort(
|
|
582
|
+
positioned.sort(require_layout_reading_order.compareReadingPosition);
|
|
579
583
|
const blocks = positioned.map((p) => p.block);
|
|
580
584
|
reconcileLinks(blocks, page, pageIndex);
|
|
581
585
|
appendAnnotationConstructs(blocks, page, pageIndex);
|
|
@@ -772,7 +776,7 @@ function reconstructSlide(page, pageIndex, images, structure) {
|
|
|
772
776
|
}
|
|
773
777
|
const textItems = page.items.filter((i) => i.kind === "text" && !consumedText.has(i));
|
|
774
778
|
const imageItems = page.items.filter((i) => i.kind === "image");
|
|
775
|
-
const textShapes =
|
|
779
|
+
const textShapes = require_layout_reading_order.readingOrder(textItems).regions.flatMap((region) => clusterIntoBlocks(region.lines)).map((block) => blockToShape(block, page.heightPt, pageIndex));
|
|
776
780
|
const imageShapes = [];
|
|
777
781
|
for (const img of imageItems) {
|
|
778
782
|
const shape = imageToShape(img, page.heightPt, pageIndex, images);
|
|
@@ -5,6 +5,7 @@ import { inferCellValue } from "./layout/cell-typing.js";
|
|
|
5
5
|
import { throwIfAborted } from "./ports/abort.js";
|
|
6
6
|
import { HALF_POINT_BUCKET_PT, bucketCounts, clusterIntoLines, clusterIntoParagraphs, estimateModalLineSpacing, fontSizesClose, gapExceeds, lineBox, modeOf, paragraphToContentParagraph, pushRunsForLine, textBoxOfItem, textItemToContentRun, textItemVerticalExtent } from "./layout/reconstruct-lines.js";
|
|
7
7
|
import { detectGridLattice, findColumnIndex, findRowIndex } from "./layout/lattice.js";
|
|
8
|
+
import { compareReadingPosition, readingOrder } from "./layout/reading-order.js";
|
|
8
9
|
import { denseTableRows } from "document-schema.js";
|
|
9
10
|
import { sourcePageIndex } from "pdf-codec/layout";
|
|
10
11
|
//#region src/layout/reconstruct-tables.ts
|
|
@@ -519,19 +520,19 @@ function reconstructPageBlocks(page, pageIndex, images, headingLevels, form, str
|
|
|
519
520
|
}
|
|
520
521
|
const textItems = page.items.filter((i) => i.kind === "text" && !consumedText.has(i));
|
|
521
522
|
const imageItems = page.items.filter((i) => i.kind === "image");
|
|
522
|
-
const
|
|
523
|
-
const paragraphs = clusterIntoParagraphs(lines);
|
|
523
|
+
const order = readingOrder(textItems);
|
|
524
524
|
const recordDivisions = (block, items) => {
|
|
525
525
|
if (structure !== void 0) divisionByBlock.set(block, divisionChainOf(items, structure));
|
|
526
526
|
};
|
|
527
527
|
const positioned = [];
|
|
528
|
-
for (const paragraph of
|
|
528
|
+
for (const { lines, path } of order.regions) for (const paragraph of clusterIntoParagraphs(lines)) {
|
|
529
529
|
const paragraphItems = paragraph.lines.flatMap((line) => line.items);
|
|
530
530
|
const structural = structure === void 0 ? void 0 : structureHeadingLevel(paragraphItems, structure);
|
|
531
531
|
const headingLevel = structural !== void 0 ? structural.level : headingLevelOf(paragraph, headingLevels);
|
|
532
532
|
const block = paragraphToContentParagraph(paragraph, pageIndex, headingLevel);
|
|
533
533
|
recordDivisions(block, paragraphItems);
|
|
534
534
|
positioned.push({
|
|
535
|
+
path,
|
|
535
536
|
yPt: paragraph.lines[0].baselineY,
|
|
536
537
|
block
|
|
537
538
|
});
|
|
@@ -554,6 +555,7 @@ function reconstructPageBlocks(page, pageIndex, images, headingLevels, form, str
|
|
|
554
555
|
});
|
|
555
556
|
recordDivisions(block, [img]);
|
|
556
557
|
positioned.push({
|
|
558
|
+
path: order.locate(img.xPt + img.widthPt / 2, img.yPt),
|
|
557
559
|
yPt: img.yPt,
|
|
558
560
|
block
|
|
559
561
|
});
|
|
@@ -562,6 +564,7 @@ function reconstructPageBlocks(page, pageIndex, images, headingLevels, form, str
|
|
|
562
564
|
for (const recovered of recoveredTables) {
|
|
563
565
|
recordDivisions(recovered.table, [...recovered.consumedText]);
|
|
564
566
|
positioned.push({
|
|
567
|
+
path: order.locate(recovered.frame.xPt + recovered.frame.widthPt / 2, recovered.topYPt),
|
|
565
568
|
yPt: recovered.topYPt,
|
|
566
569
|
block: recovered.table
|
|
567
570
|
});
|
|
@@ -571,11 +574,12 @@ function reconstructPageBlocks(page, pageIndex, images, headingLevels, form, str
|
|
|
571
574
|
const vectorItems = page.items.filter((item) => !claimedItems.has(item) && layoutItemToVector(item, page.heightPt) !== void 0);
|
|
572
575
|
recordDivisions(recoveredVectors.block, vectorItems);
|
|
573
576
|
positioned.push({
|
|
577
|
+
path: order.locate(Number.NEGATIVE_INFINITY, recoveredVectors.topYPt),
|
|
574
578
|
yPt: recoveredVectors.topYPt,
|
|
575
579
|
block: recoveredVectors.block
|
|
576
580
|
});
|
|
577
581
|
}
|
|
578
|
-
positioned.sort(
|
|
582
|
+
positioned.sort(compareReadingPosition);
|
|
579
583
|
const blocks = positioned.map((p) => p.block);
|
|
580
584
|
reconcileLinks(blocks, page, pageIndex);
|
|
581
585
|
appendAnnotationConstructs(blocks, page, pageIndex);
|
|
@@ -772,7 +776,7 @@ function reconstructSlide(page, pageIndex, images, structure) {
|
|
|
772
776
|
}
|
|
773
777
|
const textItems = page.items.filter((i) => i.kind === "text" && !consumedText.has(i));
|
|
774
778
|
const imageItems = page.items.filter((i) => i.kind === "image");
|
|
775
|
-
const textShapes =
|
|
779
|
+
const textShapes = readingOrder(textItems).regions.flatMap((region) => clusterIntoBlocks(region.lines)).map((block) => blockToShape(block, page.heightPt, pageIndex));
|
|
776
780
|
const imageShapes = [];
|
|
777
781
|
for (const img of imageItems) {
|
|
778
782
|
const shape = imageToShape(img, page.heightPt, pageIndex, images);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js.documents",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.6.1",
|
|
4
4
|
"description": "Converts between docx, pptx, odt, odp, ods, odg, xlsx, csv, svg, markdown, rtf, doc, xls, ppt and PDF through one shared, Zod-typed content schema (wpd read-only), plus read+write editors for OOXML and OpenDocument. Worker-isomorphic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"markdown-codec": "11.1.16",
|
|
87
87
|
"odf.js": "11.2.2",
|
|
88
88
|
"ooxml.js": "12.2.32",
|
|
89
|
-
"pdf-codec": "5.
|
|
89
|
+
"pdf-codec": "5.5.0",
|
|
90
90
|
"ppt-codec": "2.2.23",
|
|
91
91
|
"rtf-codec": "8.1.24",
|
|
92
92
|
"temml": "0.13.4",
|