documents.js 1.102.2 → 2.0.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.
- package/README.md +8 -5
- package/dist/convert/composition.cjs +15 -4
- package/dist/convert/composition.js +15 -4
- package/dist/convert/convert.cjs +6 -3
- package/dist/convert/convert.js +6 -3
- package/dist/convert/from-package.cjs +179 -2
- package/dist/convert/from-package.d.cts +3 -2
- package/dist/convert/from-package.d.ts +3 -2
- package/dist/convert/from-package.js +179 -3
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/layout/drawing.cjs +71 -9
- package/dist/layout/drawing.d.cts +8 -3
- package/dist/layout/drawing.d.ts +8 -3
- package/dist/layout/drawing.js +71 -10
- package/dist/layout/engine.cjs +55 -43
- package/dist/layout/engine.d.cts +2 -1
- package/dist/layout/engine.d.ts +2 -1
- package/dist/layout/engine.js +57 -45
- package/dist/layout/reconstruct.cjs +259 -104
- package/dist/layout/reconstruct.js +259 -104
- package/dist/layout/shared.cjs +47 -2
- package/dist/layout/shared.d.cts +15 -4
- package/dist/layout/shared.d.ts +15 -4
- package/dist/layout/shared.js +44 -4
- package/dist/layout/sheets.cjs +18 -13
- package/dist/layout/sheets.d.cts +4 -2
- package/dist/layout/sheets.d.ts +4 -2
- package/dist/layout/sheets.js +20 -16
- package/dist/layout/slides.cjs +35 -31
- package/dist/layout/slides.d.cts +3 -2
- package/dist/layout/slides.d.ts +3 -2
- package/dist/layout/slides.js +37 -33
- package/dist/layout/text-layout.cjs +2 -1
- package/dist/layout/text-layout.d.cts +14 -3
- package/dist/layout/text-layout.d.ts +14 -3
- package/dist/layout/text-layout.js +2 -1
- package/package.json +5 -5
package/dist/layout/slides.js
CHANGED
|
@@ -2,8 +2,8 @@ import { flipY, rotatePointAboutCenter } from "../model/geometry.js";
|
|
|
2
2
|
import { formulaOfBlock } from "../model/formula.js";
|
|
3
3
|
import { layoutFormula } from "../mathml/layout.js";
|
|
4
4
|
import { wrapRunsToWidth } from "./text-layout.js";
|
|
5
|
-
import { alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, justifyLineGapsPt, lineNaturalHeightPt, registerImage, sumColumnWidthsPt } from "./shared.js";
|
|
6
|
-
import { COLOR_BLACK
|
|
5
|
+
import { alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, justifyLineGapsPt, layoutDocumentOf, lineNaturalHeightPt, packagePagesOf, registerImage, stampFragmentFrame, stampFrame, sumColumnWidthsPt } from "./shared.js";
|
|
6
|
+
import { COLOR_BLACK } from "document-schema.js";
|
|
7
7
|
//#region src/layout/slides.ts
|
|
8
8
|
function shapePlacement(flippedFrame, rotationDeg) {
|
|
9
9
|
if (rotationDeg === void 0 || rotationDeg === 0) return {
|
|
@@ -20,7 +20,7 @@ function shapePlacement(flippedFrame, rotationDeg) {
|
|
|
20
20
|
layoutRotationDeg: ccwDeg
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
-
function layoutParagraph(paragraph, contentLeftXDown, contentWidthPt, startYDown, slideHeightPt, placement, fontScale, spacingScale, measurer, out) {
|
|
23
|
+
function layoutParagraph(paragraph, contentLeftXDown, contentWidthPt, startYDown, slideHeightPt, pageIndex, placement, fontScale, spacingScale, measurer, out) {
|
|
24
24
|
let cursorYDown = startYDown + (paragraph.spacingBeforePt ?? 0);
|
|
25
25
|
const effectiveRuns = effectiveStyledRuns(paragraph.runs, fontScale);
|
|
26
26
|
const fallbackRun = effectiveRuns[0];
|
|
@@ -52,6 +52,7 @@ function layoutParagraph(paragraph, contentLeftXDown, contentWidthPt, startYDown
|
|
|
52
52
|
sourcePath: fragment.sourcePath
|
|
53
53
|
};
|
|
54
54
|
out.push(textItem);
|
|
55
|
+
stampFragmentFrame(paragraph.runs, fragment, pageIndex, textItem, measurer, line);
|
|
55
56
|
if (fragment.hyperlink !== void 0) {
|
|
56
57
|
const fragmentWidthPt = measurer.widthOfTextAtSize(fragment.text, fragment.font, fragment.sizePt);
|
|
57
58
|
const linkBottomLeft = placement.place({
|
|
@@ -75,7 +76,7 @@ function layoutParagraph(paragraph, contentLeftXDown, contentWidthPt, startYDown
|
|
|
75
76
|
cursorYDown += paragraph.spacingAfterPt ?? 0;
|
|
76
77
|
return cursorYDown;
|
|
77
78
|
}
|
|
78
|
-
function layoutTable(table, contentLeftXDown, contentWidthPt, startYDown, slideHeightPt, placement, measurer, out) {
|
|
79
|
+
function layoutTable(table, contentLeftXDown, contentWidthPt, startYDown, slideHeightPt, pageIndex, placement, measurer, out) {
|
|
79
80
|
let cursorYDown = startYDown;
|
|
80
81
|
const gridWidthPt = table.columnWidthsPt.reduce((sum, w) => sum + w, 0);
|
|
81
82
|
const scale = gridWidthPt > 0 ? contentWidthPt / gridWidthPt : 1;
|
|
@@ -86,25 +87,24 @@ function layoutTable(table, contentLeftXDown, contentWidthPt, startYDown, slideH
|
|
|
86
87
|
for (const cell of row.cells) {
|
|
87
88
|
const span = cell.colSpan ?? 1;
|
|
88
89
|
const cellWidthPt = sumColumnWidthsPt(table.columnWidthsPt, colIndex, span) * scale;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
90
|
+
const cellFrame = flipY({
|
|
91
|
+
xPt: cellXDown,
|
|
92
|
+
yPt: cursorYDown,
|
|
93
|
+
widthPt: cellWidthPt,
|
|
94
|
+
heightPt: rowHeightPt
|
|
95
|
+
}, slideHeightPt);
|
|
96
|
+
if (placement.layoutRotationDeg === void 0) stampFrame(cell, pageIndex, cellFrame);
|
|
97
|
+
if (cell.background !== void 0 && placement.layoutRotationDeg === void 0) out.push({
|
|
98
|
+
kind: "rect",
|
|
99
|
+
xPt: cellFrame.xPt,
|
|
100
|
+
yPt: cellFrame.yPt,
|
|
101
|
+
widthPt: cellFrame.widthPt,
|
|
102
|
+
heightPt: cellFrame.heightPt,
|
|
103
|
+
fill: cell.background,
|
|
104
|
+
sourcePath: table.sourcePath
|
|
105
|
+
});
|
|
106
106
|
let cellCursorYDown = cursorYDown;
|
|
107
|
-
for (const block of cell.blocks) if (block.kind === "paragraph") cellCursorYDown = layoutParagraph(block, cellXDown, cellWidthPt, cellCursorYDown, slideHeightPt, placement, 1, 1, measurer, out);
|
|
107
|
+
for (const block of cell.blocks) if (block.kind === "paragraph") cellCursorYDown = layoutParagraph(block, cellXDown, cellWidthPt, cellCursorYDown, slideHeightPt, pageIndex, placement, 1, 1, measurer, out);
|
|
108
108
|
cellXDown += cellWidthPt;
|
|
109
109
|
colIndex += span;
|
|
110
110
|
}
|
|
@@ -128,16 +128,18 @@ function layoutShapeFormula(block, flippedFrame, formulaContext) {
|
|
|
128
128
|
yPt: flippedFrame.yPt,
|
|
129
129
|
box
|
|
130
130
|
});
|
|
131
|
+
stampFrame(block, formulaContext.pageIndex, flippedFrame);
|
|
131
132
|
}
|
|
132
|
-
function convertShape(shape, slideHeightPt, measurer, images, out, formulaContext) {
|
|
133
|
+
function convertShape(shape, slideHeightPt, pageIndex, measurer, images, out, formulaContext) {
|
|
133
134
|
const flippedFrame = flipY(shape.frame, slideHeightPt);
|
|
135
|
+
stampFrame(shape, pageIndex, flippedFrame);
|
|
134
136
|
const placement = shapePlacement(flippedFrame, shape.rotationDeg);
|
|
135
137
|
const contentLeftXDown = shape.frame.xPt + shape.insetLeftPt;
|
|
136
138
|
const contentWidthPt = Math.max(0, shape.frame.widthPt - shape.insetLeftPt - shape.insetRightPt);
|
|
137
139
|
const fontScale = shape.fontScale ?? 1;
|
|
138
140
|
const spacingScale = 1 - (shape.lineSpacingReduction ?? 0);
|
|
139
141
|
let cursorYDown = shape.frame.yPt + shape.insetTopPt;
|
|
140
|
-
for (const block of shape.blocks) if (block.kind === "paragraph") cursorYDown = layoutParagraph(block, contentLeftXDown, contentWidthPt, cursorYDown, slideHeightPt, placement, fontScale, spacingScale, measurer, out);
|
|
142
|
+
for (const block of shape.blocks) if (block.kind === "paragraph") cursorYDown = layoutParagraph(block, contentLeftXDown, contentWidthPt, cursorYDown, slideHeightPt, pageIndex, placement, fontScale, spacingScale, measurer, out);
|
|
141
143
|
else if (block.kind === "image") {
|
|
142
144
|
const imageId = registerImage(block, images);
|
|
143
145
|
const placed = placement.place({
|
|
@@ -155,7 +157,13 @@ function convertShape(shape, slideHeightPt, measurer, images, out, formulaContex
|
|
|
155
157
|
sourcePath: block.sourcePath
|
|
156
158
|
};
|
|
157
159
|
out.push(imageItem);
|
|
158
|
-
|
|
160
|
+
stampFrame(block, pageIndex, {
|
|
161
|
+
xPt: placed.x,
|
|
162
|
+
yPt: placed.y,
|
|
163
|
+
widthPt: imageItem.widthPt,
|
|
164
|
+
heightPt: imageItem.heightPt
|
|
165
|
+
});
|
|
166
|
+
} else if (block.kind === "table") cursorYDown = layoutTable(block, contentLeftXDown, contentWidthPt, cursorYDown, slideHeightPt, pageIndex, placement, measurer, out);
|
|
159
167
|
else if (block.kind === "embeddedObject" && block.objectKind === "formula" && formulaContext !== void 0) layoutShapeFormula(block, flippedFrame, formulaContext);
|
|
160
168
|
}
|
|
161
169
|
function convertSlide(slide, slideIndex, measurer, images, positioned, mathMetricsAt) {
|
|
@@ -165,7 +173,7 @@ function convertSlide(slide, slideIndex, measurer, images, positioned, mathMetri
|
|
|
165
173
|
positioned,
|
|
166
174
|
mathMetricsAt
|
|
167
175
|
};
|
|
168
|
-
for (const shape of slide.shapes) convertShape(shape, slide.size.heightPt, measurer, images, items, formulaContext);
|
|
176
|
+
for (const shape of slide.shapes) convertShape(shape, slide.size.heightPt, slideIndex, measurer, images, items, formulaContext);
|
|
169
177
|
return {
|
|
170
178
|
widthPt: slide.size.widthPt,
|
|
171
179
|
heightPt: slide.size.heightPt,
|
|
@@ -178,13 +186,9 @@ function convertPresentationToLayout(doc, options) {
|
|
|
178
186
|
const formulas = [];
|
|
179
187
|
const pages = doc.slides.map((slide, slideIndex) => convertSlide(slide, slideIndex, options.measurer, images, formulas, options.mathMetricsAt));
|
|
180
188
|
return {
|
|
181
|
-
document:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
pages,
|
|
185
|
-
images
|
|
186
|
-
},
|
|
187
|
-
formulas
|
|
189
|
+
document: layoutDocumentOf(doc.metadata, pages, images),
|
|
190
|
+
formulas,
|
|
191
|
+
pages: packagePagesOf(pages)
|
|
188
192
|
};
|
|
189
193
|
}
|
|
190
194
|
//#endregion
|
|
@@ -38,7 +38,8 @@ function atomizeRuns(runs, measurer) {
|
|
|
38
38
|
color: run.color,
|
|
39
39
|
underline: run.underline,
|
|
40
40
|
hyperlink: run.hyperlink,
|
|
41
|
-
sourcePath: run.sourcePath
|
|
41
|
+
sourcePath: run.sourcePath,
|
|
42
|
+
runIndex: run.runIndex
|
|
42
43
|
});
|
|
43
44
|
wordWidth += measurer.widthOfTextAtSize(token, run.font, run.sizePt);
|
|
44
45
|
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import { StyledRun, TextMeasurer, WrapOptions, WrappedLine } from "document-schema.js";
|
|
1
|
+
import { StyledFragment, StyledRun, TextMeasurer, WrapOptions, WrappedLine } from "document-schema.js";
|
|
2
2
|
//#region src/layout/text-layout.d.ts
|
|
3
|
-
|
|
3
|
+
interface SourcedRun extends StyledRun {
|
|
4
|
+
readonly runIndex?: number;
|
|
5
|
+
}
|
|
6
|
+
interface SourcedFragment extends StyledFragment {
|
|
7
|
+
readonly runIndex?: number;
|
|
8
|
+
}
|
|
9
|
+
interface SourcedWrappedLine extends Omit<WrappedLine, 'fragments'> {
|
|
10
|
+
readonly fragments: readonly (SourcedFragment & {
|
|
11
|
+
readonly xOffsetPt: number;
|
|
12
|
+
})[];
|
|
13
|
+
}
|
|
14
|
+
declare function wrapRunsToWidth(runs: readonly SourcedRun[], measurer: TextMeasurer, maxWidthPt: number, options?: WrapOptions): SourcedWrappedLine[];
|
|
4
15
|
//#endregion
|
|
5
|
-
export { wrapRunsToWidth };
|
|
16
|
+
export { SourcedFragment, SourcedRun, SourcedWrappedLine, wrapRunsToWidth };
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import { StyledRun, TextMeasurer, WrapOptions, WrappedLine } from "document-schema.js";
|
|
1
|
+
import { StyledFragment, StyledRun, TextMeasurer, WrapOptions, WrappedLine } from "document-schema.js";
|
|
2
2
|
//#region src/layout/text-layout.d.ts
|
|
3
|
-
|
|
3
|
+
interface SourcedRun extends StyledRun {
|
|
4
|
+
readonly runIndex?: number;
|
|
5
|
+
}
|
|
6
|
+
interface SourcedFragment extends StyledFragment {
|
|
7
|
+
readonly runIndex?: number;
|
|
8
|
+
}
|
|
9
|
+
interface SourcedWrappedLine extends Omit<WrappedLine, 'fragments'> {
|
|
10
|
+
readonly fragments: readonly (SourcedFragment & {
|
|
11
|
+
readonly xOffsetPt: number;
|
|
12
|
+
})[];
|
|
13
|
+
}
|
|
14
|
+
declare function wrapRunsToWidth(runs: readonly SourcedRun[], measurer: TextMeasurer, maxWidthPt: number, options?: WrapOptions): SourcedWrappedLine[];
|
|
4
15
|
//#endregion
|
|
5
|
-
export { wrapRunsToWidth };
|
|
16
|
+
export { SourcedFragment, SourcedRun, SourcedWrappedLine, wrapRunsToWidth };
|
|
@@ -37,7 +37,8 @@ function atomizeRuns(runs, measurer) {
|
|
|
37
37
|
color: run.color,
|
|
38
38
|
underline: run.underline,
|
|
39
39
|
hyperlink: run.hyperlink,
|
|
40
|
-
sourcePath: run.sourcePath
|
|
40
|
+
sourcePath: run.sourcePath,
|
|
41
|
+
runIndex: run.runIndex
|
|
41
42
|
});
|
|
42
43
|
wordWidth += measurer.widthOfTextAtSize(token, run.font, run.sizePt);
|
|
43
44
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "documents.js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
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": {
|
|
@@ -84,11 +84,11 @@
|
|
|
84
84
|
"packageManager": "pnpm@11.6.0",
|
|
85
85
|
"dependencies": {
|
|
86
86
|
"byte-codec": "^1.1.9",
|
|
87
|
-
"document-schema.js": "^2.
|
|
87
|
+
"document-schema.js": "^3.2.0",
|
|
88
88
|
"fflate": "^0.8.3",
|
|
89
|
-
"markdown-codec": "^
|
|
90
|
-
"odf.js": "^
|
|
91
|
-
"ooxml.js": "^2.
|
|
89
|
+
"markdown-codec": "^2.0.0",
|
|
90
|
+
"odf.js": "^3.0.1",
|
|
91
|
+
"ooxml.js": "^2.16.0",
|
|
92
92
|
"pdf-codec": "^2.2.35",
|
|
93
93
|
"zod": "^4.4.3"
|
|
94
94
|
},
|