documents.js 1.33.4 → 1.34.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 +1 -0
- package/dist/index.cjs +624 -727
- package/dist/index.d.cts +13 -645
- package/dist/index.d.ts +13 -645
- package/dist/index.js +607 -780
- package/package.json +5 -2
package/dist/index.cjs
CHANGED
|
@@ -1,238 +1,32 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let ooxml_js = require("ooxml.js");
|
|
3
|
+
let document_content_model = require("document-content-model");
|
|
3
4
|
let zod = require("zod");
|
|
4
5
|
let fflate = require("fflate");
|
|
5
|
-
//#region src/model/geometry.ts
|
|
6
|
-
function flipY(box, containerHeightPt) {
|
|
7
|
-
return {
|
|
8
|
-
xPt: box.xPt,
|
|
9
|
-
yPt: containerHeightPt - box.yPt - box.heightPt,
|
|
10
|
-
widthPt: box.widthPt,
|
|
11
|
-
heightPt: box.heightPt
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
//#endregion
|
|
15
|
-
//#region src/model/style.ts
|
|
16
|
-
const LayoutFontSchema = zod.z.object({
|
|
17
|
-
family: zod.z.string(),
|
|
18
|
-
weight: zod.z.enum(["normal", "bold"]),
|
|
19
|
-
style: zod.z.enum(["normal", "italic"])
|
|
20
|
-
});
|
|
21
|
-
const DEFAULT_LAYOUT_FONT = {
|
|
22
|
-
family: "Helvetica",
|
|
23
|
-
weight: "normal",
|
|
24
|
-
style: "normal"
|
|
25
|
-
};
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/model/layout.ts
|
|
28
|
-
const LAYOUT_FORMAT_VERSION = 1;
|
|
29
|
-
const LayoutTextSchema = zod.z.object({
|
|
30
|
-
kind: zod.z.literal("text"),
|
|
31
|
-
text: zod.z.string(),
|
|
32
|
-
xPt: zod.z.number(),
|
|
33
|
-
yPt: zod.z.number(),
|
|
34
|
-
font: LayoutFontSchema,
|
|
35
|
-
sizePt: zod.z.number().positive(),
|
|
36
|
-
color: ooxml_js.ColorSchema,
|
|
37
|
-
widthPt: zod.z.number().nonnegative().optional(),
|
|
38
|
-
rotationDeg: zod.z.number().optional(),
|
|
39
|
-
underline: zod.z.boolean().optional()
|
|
40
|
-
});
|
|
41
|
-
const LayoutImageSchema = zod.z.object({
|
|
42
|
-
kind: zod.z.literal("image"),
|
|
43
|
-
imageId: zod.z.string(),
|
|
44
|
-
xPt: zod.z.number(),
|
|
45
|
-
yPt: zod.z.number(),
|
|
46
|
-
widthPt: zod.z.number().positive(),
|
|
47
|
-
heightPt: zod.z.number().positive(),
|
|
48
|
-
rotationDeg: zod.z.number().optional()
|
|
49
|
-
});
|
|
50
|
-
const LayoutRectSchema = zod.z.object({
|
|
51
|
-
kind: zod.z.literal("rect"),
|
|
52
|
-
xPt: zod.z.number(),
|
|
53
|
-
yPt: zod.z.number(),
|
|
54
|
-
widthPt: zod.z.number().nonnegative(),
|
|
55
|
-
heightPt: zod.z.number().nonnegative(),
|
|
56
|
-
fill: ooxml_js.ColorSchema.optional(),
|
|
57
|
-
stroke: zod.z.object({
|
|
58
|
-
color: ooxml_js.ColorSchema,
|
|
59
|
-
widthPt: zod.z.number().positive()
|
|
60
|
-
}).optional()
|
|
61
|
-
});
|
|
62
|
-
const LayoutLineSchema = zod.z.object({
|
|
63
|
-
kind: zod.z.literal("line"),
|
|
64
|
-
x1Pt: zod.z.number(),
|
|
65
|
-
y1Pt: zod.z.number(),
|
|
66
|
-
x2Pt: zod.z.number(),
|
|
67
|
-
y2Pt: zod.z.number(),
|
|
68
|
-
color: ooxml_js.ColorSchema,
|
|
69
|
-
widthPt: zod.z.number().positive()
|
|
70
|
-
});
|
|
71
|
-
const LayoutEllipseSchema = zod.z.object({
|
|
72
|
-
kind: zod.z.literal("ellipse"),
|
|
73
|
-
xPt: zod.z.number(),
|
|
74
|
-
yPt: zod.z.number(),
|
|
75
|
-
widthPt: zod.z.number().positive(),
|
|
76
|
-
heightPt: zod.z.number().positive(),
|
|
77
|
-
fill: ooxml_js.ColorSchema.optional(),
|
|
78
|
-
stroke: zod.z.object({
|
|
79
|
-
color: ooxml_js.ColorSchema,
|
|
80
|
-
widthPt: zod.z.number().positive()
|
|
81
|
-
}).optional()
|
|
82
|
-
});
|
|
83
|
-
const LayoutLinkSchema = zod.z.object({
|
|
84
|
-
kind: zod.z.literal("link"),
|
|
85
|
-
uri: zod.z.string(),
|
|
86
|
-
xPt: zod.z.number(),
|
|
87
|
-
yPt: zod.z.number(),
|
|
88
|
-
widthPt: zod.z.number().nonnegative(),
|
|
89
|
-
heightPt: zod.z.number().nonnegative()
|
|
90
|
-
});
|
|
91
|
-
const LayoutItemSchema = zod.z.discriminatedUnion("kind", [
|
|
92
|
-
LayoutTextSchema,
|
|
93
|
-
LayoutImageSchema,
|
|
94
|
-
LayoutRectSchema,
|
|
95
|
-
LayoutLineSchema,
|
|
96
|
-
LayoutEllipseSchema,
|
|
97
|
-
LayoutLinkSchema
|
|
98
|
-
]);
|
|
99
|
-
const LayoutPageSchema = zod.z.object({
|
|
100
|
-
widthPt: zod.z.number().positive(),
|
|
101
|
-
heightPt: zod.z.number().positive(),
|
|
102
|
-
items: zod.z.array(LayoutItemSchema)
|
|
103
|
-
});
|
|
104
|
-
const LayoutImageAssetSchema = zod.z.object({
|
|
105
|
-
format: zod.z.enum(["png", "jpeg"]),
|
|
106
|
-
base64: zod.z.string(),
|
|
107
|
-
widthPx: zod.z.number().int().positive(),
|
|
108
|
-
heightPx: zod.z.number().int().positive()
|
|
109
|
-
});
|
|
110
|
-
const LayoutMetadataSchema = zod.z.object({
|
|
111
|
-
title: zod.z.string().optional(),
|
|
112
|
-
author: zod.z.string().optional(),
|
|
113
|
-
subject: zod.z.string().optional(),
|
|
114
|
-
keywords: zod.z.array(zod.z.string()).optional(),
|
|
115
|
-
creator: zod.z.string().optional(),
|
|
116
|
-
producer: zod.z.string().optional(),
|
|
117
|
-
createdIso: zod.z.string().optional(),
|
|
118
|
-
modifiedIso: zod.z.string().optional()
|
|
119
|
-
});
|
|
120
|
-
const LayoutDocumentSchema = zod.z.object({
|
|
121
|
-
formatVersion: zod.z.literal(1),
|
|
122
|
-
metadata: LayoutMetadataSchema,
|
|
123
|
-
pages: zod.z.array(LayoutPageSchema),
|
|
124
|
-
images: zod.z.record(zod.z.string(), LayoutImageAssetSchema)
|
|
125
|
-
});
|
|
126
|
-
//#endregion
|
|
127
6
|
//#region src/model/content.ts
|
|
128
7
|
const CONTENT_FORMAT_VERSION = 1;
|
|
129
|
-
const ContentRunSchema = zod.z.object({
|
|
130
|
-
text: zod.z.string(),
|
|
131
|
-
bold: zod.z.boolean().optional(),
|
|
132
|
-
italic: zod.z.boolean().optional(),
|
|
133
|
-
underline: zod.z.boolean().optional(),
|
|
134
|
-
strike: zod.z.boolean().optional(),
|
|
135
|
-
fontFamily: zod.z.string().optional(),
|
|
136
|
-
sizePt: zod.z.number().positive().optional(),
|
|
137
|
-
color: ooxml_js.ColorSchema.optional(),
|
|
138
|
-
hyperlink: zod.z.string().optional()
|
|
139
|
-
});
|
|
140
|
-
const ContentListMembershipSchema = zod.z.object({
|
|
141
|
-
numId: zod.z.string(),
|
|
142
|
-
level: zod.z.number().int().nonnegative()
|
|
143
|
-
});
|
|
144
|
-
const ContentParagraphSchema = zod.z.object({
|
|
145
|
-
kind: zod.z.literal("paragraph"),
|
|
146
|
-
runs: zod.z.array(ContentRunSchema),
|
|
147
|
-
styleId: zod.z.string().optional(),
|
|
148
|
-
alignment: ooxml_js.AlignmentSchema.optional(),
|
|
149
|
-
list: ContentListMembershipSchema.optional(),
|
|
150
|
-
spacingBeforePt: zod.z.number().optional(),
|
|
151
|
-
spacingAfterPt: zod.z.number().optional(),
|
|
152
|
-
lineSpacing: zod.z.number().positive().optional(),
|
|
153
|
-
indentLeftPt: zod.z.number().optional(),
|
|
154
|
-
indentFirstLinePt: zod.z.number().optional()
|
|
155
|
-
});
|
|
156
|
-
const ContentImageBlockSchema = zod.z.object({
|
|
157
|
-
kind: zod.z.literal("image"),
|
|
158
|
-
format: zod.z.enum(["png", "jpeg"]),
|
|
159
|
-
base64: zod.z.string(),
|
|
160
|
-
widthPt: zod.z.number().positive(),
|
|
161
|
-
heightPt: zod.z.number().positive(),
|
|
162
|
-
altText: zod.z.string().optional()
|
|
163
|
-
});
|
|
164
|
-
const ContentPageBreakSchema = zod.z.object({ kind: zod.z.literal("pageBreak") });
|
|
165
|
-
function isRecord(value) {
|
|
166
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
167
|
-
}
|
|
168
|
-
function isContentRun(value) {
|
|
169
|
-
return isRecord(value) && typeof value.text === "string";
|
|
170
|
-
}
|
|
171
|
-
function isContentTableCell(value) {
|
|
172
|
-
return isRecord(value) && Array.isArray(value.blocks) && value.blocks.every(isContentBlock);
|
|
173
|
-
}
|
|
174
|
-
function isContentTableRow(value) {
|
|
175
|
-
return isRecord(value) && Array.isArray(value.cells) && value.cells.every(isContentTableCell) && (value.heightPt === void 0 || typeof value.heightPt === "number");
|
|
176
|
-
}
|
|
177
|
-
function isContentBlock(value) {
|
|
178
|
-
if (!isRecord(value)) return false;
|
|
179
|
-
const kind = value.kind;
|
|
180
|
-
if (kind === "paragraph") return Array.isArray(value.runs) && value.runs.every(isContentRun);
|
|
181
|
-
if (kind === "image") return (value.format === "png" || value.format === "jpeg") && typeof value.base64 === "string" && typeof value.widthPt === "number" && typeof value.heightPt === "number";
|
|
182
|
-
if (kind === "pageBreak") return true;
|
|
183
|
-
if (kind === "table") return Array.isArray(value.rows) && value.rows.every(isContentTableRow) && Array.isArray(value.columnWidthsPt) && value.columnWidthsPt.every((w) => typeof w === "number");
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
const ContentBlockSchema = zod.z.custom(isContentBlock);
|
|
187
|
-
const ContentTableCellSchema = zod.z.object({
|
|
188
|
-
blocks: zod.z.array(ContentBlockSchema),
|
|
189
|
-
colSpan: zod.z.number().int().positive().optional(),
|
|
190
|
-
rowSpan: zod.z.number().int().positive().optional(),
|
|
191
|
-
background: ooxml_js.ColorSchema.optional()
|
|
192
|
-
});
|
|
193
|
-
const ContentTableRowSchema = zod.z.object({
|
|
194
|
-
cells: zod.z.array(ContentTableCellSchema),
|
|
195
|
-
heightPt: zod.z.number().positive().optional()
|
|
196
|
-
});
|
|
197
|
-
const ContentTableSchema = zod.z.object({
|
|
198
|
-
kind: zod.z.literal("table"),
|
|
199
|
-
rows: zod.z.array(ContentTableRowSchema),
|
|
200
|
-
columnWidthsPt: zod.z.array(zod.z.number().positive())
|
|
201
|
-
});
|
|
202
|
-
const ContentSectionSchema = zod.z.object({
|
|
203
|
-
pageSize: ooxml_js.PageSizeSchema,
|
|
204
|
-
margins: ooxml_js.MarginsSchema,
|
|
205
|
-
blocks: zod.z.array(ContentBlockSchema)
|
|
206
|
-
});
|
|
207
|
-
const ContentShapeSchema = zod.z.object({
|
|
208
|
-
name: zod.z.string().optional(),
|
|
209
|
-
frame: ooxml_js.BoxSchema,
|
|
210
|
-
rotationDeg: zod.z.number().optional(),
|
|
211
|
-
insetLeftPt: zod.z.number().nonnegative(),
|
|
212
|
-
insetTopPt: zod.z.number().nonnegative(),
|
|
213
|
-
insetRightPt: zod.z.number().nonnegative(),
|
|
214
|
-
insetBottomPt: zod.z.number().nonnegative(),
|
|
215
|
-
fontScale: zod.z.number().positive().optional(),
|
|
216
|
-
lineSpacingReduction: zod.z.number().nonnegative().optional(),
|
|
217
|
-
blocks: zod.z.array(ContentBlockSchema)
|
|
218
|
-
});
|
|
219
|
-
const ContentSlideSchema = zod.z.object({
|
|
220
|
-
size: ooxml_js.PageSizeSchema,
|
|
221
|
-
shapes: zod.z.array(ContentShapeSchema),
|
|
222
|
-
notes: zod.z.string()
|
|
223
|
-
});
|
|
224
8
|
const ContentDocumentSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
225
9
|
kind: zod.z.literal("wordprocessing"),
|
|
226
10
|
formatVersion: zod.z.literal(1),
|
|
227
|
-
metadata: LayoutMetadataSchema,
|
|
228
|
-
sections: zod.z.array(ContentSectionSchema)
|
|
11
|
+
metadata: document_content_model.LayoutMetadataSchema,
|
|
12
|
+
sections: zod.z.array(document_content_model.ContentSectionSchema)
|
|
229
13
|
}), zod.z.object({
|
|
230
14
|
kind: zod.z.literal("presentation"),
|
|
231
15
|
formatVersion: zod.z.literal(1),
|
|
232
|
-
metadata: LayoutMetadataSchema,
|
|
233
|
-
slides: zod.z.array(ContentSlideSchema)
|
|
16
|
+
metadata: document_content_model.LayoutMetadataSchema,
|
|
17
|
+
slides: zod.z.array(document_content_model.ContentSlideSchema)
|
|
234
18
|
})]);
|
|
235
19
|
//#endregion
|
|
20
|
+
//#region src/model/geometry.ts
|
|
21
|
+
function flipY(box, containerHeightPt) {
|
|
22
|
+
return {
|
|
23
|
+
xPt: box.xPt,
|
|
24
|
+
yPt: containerHeightPt - box.yPt - box.heightPt,
|
|
25
|
+
widthPt: box.widthPt,
|
|
26
|
+
heightPt: box.heightPt
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
236
30
|
//#region src/model/bytes.ts
|
|
237
31
|
const ZIP_LOCAL_FILE_HEADER = [
|
|
238
32
|
80,
|
|
@@ -652,10 +446,10 @@ function getColor(rPr) {
|
|
|
652
446
|
if (color === void 0) return;
|
|
653
447
|
const val = (0, ooxml_js.attr)(color, "w:val");
|
|
654
448
|
if (val === void 0 || val.toLowerCase() === "auto") return;
|
|
655
|
-
return (0,
|
|
449
|
+
return (0, document_content_model.rgbHexToColor)(val);
|
|
656
450
|
}
|
|
657
451
|
function setColor(rPr, color) {
|
|
658
|
-
setAttr(getOrCreateChildElement(rPr, "w:color", RPR_ORDER, () => el("w:color")), "w:val", (0,
|
|
452
|
+
setAttr(getOrCreateChildElement(rPr, "w:color", RPR_ORDER, () => el("w:color")), "w:val", (0, document_content_model.colorToRgbHex)(color));
|
|
659
453
|
}
|
|
660
454
|
function getStyleId(propsElement, tag) {
|
|
661
455
|
if (propsElement === void 0) return;
|
|
@@ -808,7 +602,7 @@ function buildRun(init = {}) {
|
|
|
808
602
|
const half = String(Math.round(init.sizePt * 2));
|
|
809
603
|
rPrChildren.push(el("w:sz", { "w:val": half }), el("w:szCs", { "w:val": half }));
|
|
810
604
|
}
|
|
811
|
-
if (init.color !== void 0) rPrChildren.push(el("w:color", { "w:val": (0,
|
|
605
|
+
if (init.color !== void 0) rPrChildren.push(el("w:color", { "w:val": (0, document_content_model.colorToRgbHex)(init.color) }));
|
|
812
606
|
const run = el("w:r");
|
|
813
607
|
if (rPrChildren.length > 0 || init.underline === true) {
|
|
814
608
|
const rPr = el("w:rPr");
|
|
@@ -5504,8 +5298,8 @@ function interpretContentStream(bytes, resources, context) {
|
|
|
5504
5298
|
const items = [];
|
|
5505
5299
|
runContentStream(bytes, resources, {
|
|
5506
5300
|
ctm: IDENTITY_MATRIX,
|
|
5507
|
-
fillColor:
|
|
5508
|
-
strokeColor:
|
|
5301
|
+
fillColor: document_content_model.COLOR_BLACK,
|
|
5302
|
+
strokeColor: document_content_model.COLOR_BLACK
|
|
5509
5303
|
}, context, items, 0);
|
|
5510
5304
|
return items;
|
|
5511
5305
|
}
|
|
@@ -5793,411 +5587,83 @@ function runContentStream(bytes, resources, initialState, context, items, depth)
|
|
|
5793
5587
|
}
|
|
5794
5588
|
}
|
|
5795
5589
|
//#endregion
|
|
5796
|
-
//#region src/
|
|
5797
|
-
const
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5590
|
+
//#region src/image/png-decode.ts
|
|
5591
|
+
const PNG_SIGNATURE = [
|
|
5592
|
+
137,
|
|
5593
|
+
80,
|
|
5594
|
+
78,
|
|
5595
|
+
71,
|
|
5596
|
+
13,
|
|
5597
|
+
10,
|
|
5598
|
+
26,
|
|
5599
|
+
10
|
|
5600
|
+
];
|
|
5601
|
+
function requireDataView(bytes) {
|
|
5602
|
+
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
5808
5603
|
}
|
|
5809
|
-
function
|
|
5810
|
-
const
|
|
5811
|
-
const
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
}
|
|
5604
|
+
function readChunks(bytes, onWarning) {
|
|
5605
|
+
const chunks = [];
|
|
5606
|
+
const view = requireDataView(bytes);
|
|
5607
|
+
let offset = PNG_SIGNATURE.length;
|
|
5608
|
+
while (offset + 8 <= bytes.length) {
|
|
5609
|
+
const length = view.getUint32(offset);
|
|
5610
|
+
const typeBytes = bytes.subarray(offset + 4, offset + 8);
|
|
5611
|
+
const type = new TextDecoder("latin1").decode(typeBytes);
|
|
5612
|
+
const dataStart = offset + 8;
|
|
5613
|
+
const dataEnd = dataStart + length;
|
|
5614
|
+
if (dataEnd + 4 > bytes.length) throw new Error(`PNG chunk '${type}' declares a length that runs past the end of the file`);
|
|
5615
|
+
const data = bytes.subarray(dataStart, dataEnd);
|
|
5616
|
+
if (onWarning !== void 0) {
|
|
5617
|
+
if (view.getUint32(dataEnd) !== crc32(concatBytes([typeBytes, data]))) onWarning(`PNG chunk '${type}' failed its CRC32 check`);
|
|
5618
|
+
}
|
|
5619
|
+
chunks.push({
|
|
5620
|
+
type,
|
|
5621
|
+
data
|
|
5622
|
+
});
|
|
5623
|
+
offset = dataEnd + 4;
|
|
5624
|
+
if (type === "IEND") break;
|
|
5625
|
+
}
|
|
5626
|
+
return chunks;
|
|
5831
5627
|
}
|
|
5832
|
-
function
|
|
5833
|
-
const
|
|
5834
|
-
if (arr === void 0) return {
|
|
5835
|
-
llx: 0,
|
|
5836
|
-
lly: 0,
|
|
5837
|
-
urx: DEFAULT_PAGE_WIDTH_PT,
|
|
5838
|
-
ury: DEFAULT_PAGE_HEIGHT_PT
|
|
5839
|
-
};
|
|
5840
|
-
const a = asNumber(arr[0]) ?? 0;
|
|
5841
|
-
const b = asNumber(arr[1]) ?? 0;
|
|
5842
|
-
const c = asNumber(arr[2]) ?? DEFAULT_PAGE_WIDTH_PT;
|
|
5843
|
-
const d = asNumber(arr[3]) ?? DEFAULT_PAGE_HEIGHT_PT;
|
|
5628
|
+
function parseIhdr(data) {
|
|
5629
|
+
const view = requireDataView(data);
|
|
5844
5630
|
return {
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5631
|
+
width: view.getUint32(0),
|
|
5632
|
+
height: view.getUint32(4),
|
|
5633
|
+
bitDepth: data[8],
|
|
5634
|
+
colorType: data[9],
|
|
5635
|
+
interlace: data[12]
|
|
5849
5636
|
};
|
|
5850
5637
|
}
|
|
5851
|
-
function
|
|
5852
|
-
if (
|
|
5853
|
-
|
|
5854
|
-
|
|
5638
|
+
function channelsForColorType(colorType) {
|
|
5639
|
+
if (colorType === 0) return 1;
|
|
5640
|
+
if (colorType === 2) return 3;
|
|
5641
|
+
if (colorType === 3) return 1;
|
|
5642
|
+
if (colorType === 4) return 2;
|
|
5643
|
+
if (colorType === 6) return 4;
|
|
5644
|
+
throw new Error(`unsupported PNG colour type: ${colorType}`);
|
|
5855
5645
|
}
|
|
5856
|
-
function
|
|
5857
|
-
|
|
5858
|
-
matrix: [
|
|
5859
|
-
0,
|
|
5860
|
-
-1,
|
|
5861
|
-
1,
|
|
5862
|
-
0,
|
|
5863
|
-
0,
|
|
5864
|
-
w
|
|
5865
|
-
],
|
|
5866
|
-
widthPt: h,
|
|
5867
|
-
heightPt: w
|
|
5868
|
-
};
|
|
5869
|
-
if (rotation === 180) return {
|
|
5870
|
-
matrix: [
|
|
5871
|
-
-1,
|
|
5872
|
-
0,
|
|
5873
|
-
0,
|
|
5874
|
-
-1,
|
|
5875
|
-
w,
|
|
5876
|
-
h
|
|
5877
|
-
],
|
|
5878
|
-
widthPt: w,
|
|
5879
|
-
heightPt: h
|
|
5880
|
-
};
|
|
5881
|
-
if (rotation === 270) return {
|
|
5882
|
-
matrix: [
|
|
5883
|
-
0,
|
|
5884
|
-
1,
|
|
5885
|
-
-1,
|
|
5886
|
-
0,
|
|
5887
|
-
h,
|
|
5888
|
-
0
|
|
5889
|
-
],
|
|
5890
|
-
widthPt: h,
|
|
5891
|
-
heightPt: w
|
|
5892
|
-
};
|
|
5893
|
-
return {
|
|
5894
|
-
matrix: [
|
|
5895
|
-
1,
|
|
5896
|
-
0,
|
|
5897
|
-
0,
|
|
5898
|
-
1,
|
|
5899
|
-
0,
|
|
5900
|
-
0
|
|
5901
|
-
],
|
|
5902
|
-
widthPt: w,
|
|
5903
|
-
heightPt: h
|
|
5904
|
-
};
|
|
5646
|
+
function filterBpp(bitDepth, channels) {
|
|
5647
|
+
return Math.max(1, Math.ceil(bitDepth * channels / 8));
|
|
5905
5648
|
}
|
|
5906
|
-
function
|
|
5907
|
-
const
|
|
5908
|
-
|
|
5909
|
-
if (
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5649
|
+
function unpackRow(rowBytes, width, channels, bitDepth) {
|
|
5650
|
+
const sampleCount = width * channels;
|
|
5651
|
+
const samples = new Array(sampleCount);
|
|
5652
|
+
if (bitDepth === 8) for (let i = 0; i < sampleCount; i++) samples[i] = rowBytes[i];
|
|
5653
|
+
else if (bitDepth === 16) for (let i = 0; i < sampleCount; i++) samples[i] = rowBytes[i * 2];
|
|
5654
|
+
else {
|
|
5655
|
+
const mask = (1 << bitDepth) - 1;
|
|
5656
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
5657
|
+
const bitOffset = i * bitDepth;
|
|
5658
|
+
const byteIndex = bitOffset >> 3;
|
|
5659
|
+
const shift = 8 - bitDepth - (bitOffset & 7);
|
|
5660
|
+
samples[i] = rowBytes[byteIndex] >> shift & mask;
|
|
5914
5661
|
}
|
|
5915
|
-
return concatBytes(chunks);
|
|
5916
5662
|
}
|
|
5917
|
-
return
|
|
5663
|
+
return samples;
|
|
5918
5664
|
}
|
|
5919
|
-
function
|
|
5920
|
-
|
|
5921
|
-
const mediaBox = readMediaBox(page);
|
|
5922
|
-
const rotationResult = pageRotationTransform(normalizeRotation(asNumber(dictGet(page, "Rotate"))), mediaBox.urx - mediaBox.llx, mediaBox.ury - mediaBox.lly);
|
|
5923
|
-
const pageMatrix = multiplyMatrices(translationMatrix(-mediaBox.llx, -mediaBox.lly), rotationResult.matrix);
|
|
5924
|
-
const items = [];
|
|
5925
|
-
if (resources !== void 0) {
|
|
5926
|
-
const extracted = interpretContentStream(readPageContentBytes(page, resolver, sink), resources, {
|
|
5927
|
-
fontMetrics: fontResolver.metrics,
|
|
5928
|
-
resolver,
|
|
5929
|
-
sink
|
|
5930
|
-
});
|
|
5931
|
-
for (const item of extracted) {
|
|
5932
|
-
const converted = convertExtractedItem(item, pageMatrix, fontResolver, images, imageIdCache, resolver, sink);
|
|
5933
|
-
if (converted !== void 0) items.push(converted);
|
|
5934
|
-
}
|
|
5935
|
-
} else sink({
|
|
5936
|
-
code: "pdf/object-missing-value",
|
|
5937
|
-
severity: "warning",
|
|
5938
|
-
message: "page has no /Resources dict; its content stream cannot be interpreted"
|
|
5939
|
-
});
|
|
5940
|
-
items.push(...readLinkAnnotations(page, pageMatrix, resolver));
|
|
5941
|
-
return {
|
|
5942
|
-
widthPt: rotationResult.widthPt,
|
|
5943
|
-
heightPt: rotationResult.heightPt,
|
|
5944
|
-
items
|
|
5945
|
-
};
|
|
5946
|
-
}
|
|
5947
|
-
function convertExtractedItem(item, pageMatrix, fontResolver, images, imageIdCache, resolver, sink) {
|
|
5948
|
-
if (item.kind === "text") return convertText(item, pageMatrix, fontResolver);
|
|
5949
|
-
if (item.kind === "rect") return convertRect(item, pageMatrix);
|
|
5950
|
-
if (item.kind === "image") return convertImage(item, pageMatrix, images, imageIdCache, resolver, sink);
|
|
5951
|
-
return convertInlineImage(item, pageMatrix, images, resolver, sink);
|
|
5952
|
-
}
|
|
5953
|
-
function convertText(item, pageMatrix, fontResolver) {
|
|
5954
|
-
const font = fontResolver.resolve(item.fontResourceName, item.resources);
|
|
5955
|
-
const text = font?.decodeToUnicode(item.codes) ?? "";
|
|
5956
|
-
if (text.length === 0) return;
|
|
5957
|
-
const startTrm = multiplyMatrices(item.startMatrix, pageMatrix);
|
|
5958
|
-
const endTrm = multiplyMatrices(item.endMatrix, pageMatrix);
|
|
5959
|
-
const widthPt = Math.hypot(endTrm[4] - startTrm[4], endTrm[5] - startTrm[5]);
|
|
5960
|
-
const sizePt = matrixScaleX(startTrm);
|
|
5961
|
-
const rotationDeg = matrixRotationDegrees(startTrm);
|
|
5962
|
-
const layoutFont = {
|
|
5963
|
-
family: font?.family ?? "Helvetica",
|
|
5964
|
-
weight: font?.bold === true ? "bold" : "normal",
|
|
5965
|
-
style: font?.italic === true ? "italic" : "normal"
|
|
5966
|
-
};
|
|
5967
|
-
return {
|
|
5968
|
-
kind: "text",
|
|
5969
|
-
text,
|
|
5970
|
-
xPt: startTrm[4],
|
|
5971
|
-
yPt: startTrm[5],
|
|
5972
|
-
font: layoutFont,
|
|
5973
|
-
sizePt: sizePt > 0 ? sizePt : item.sizePt,
|
|
5974
|
-
color: item.color,
|
|
5975
|
-
widthPt,
|
|
5976
|
-
rotationDeg: rotationDeg !== 0 ? rotationDeg : void 0
|
|
5977
|
-
};
|
|
5978
|
-
}
|
|
5979
|
-
function convertRect(item, pageMatrix) {
|
|
5980
|
-
const p1 = applyMatrix(pageMatrix, {
|
|
5981
|
-
x: item.xPt,
|
|
5982
|
-
y: item.yPt
|
|
5983
|
-
});
|
|
5984
|
-
const p2 = applyMatrix(pageMatrix, {
|
|
5985
|
-
x: item.xPt + item.widthPt,
|
|
5986
|
-
y: item.yPt + item.heightPt
|
|
5987
|
-
});
|
|
5988
|
-
return {
|
|
5989
|
-
kind: "rect",
|
|
5990
|
-
xPt: Math.min(p1.x, p2.x),
|
|
5991
|
-
yPt: Math.min(p1.y, p2.y),
|
|
5992
|
-
widthPt: Math.abs(p2.x - p1.x),
|
|
5993
|
-
heightPt: Math.abs(p2.y - p1.y),
|
|
5994
|
-
fill: item.color
|
|
5995
|
-
};
|
|
5996
|
-
}
|
|
5997
|
-
function imagePlacementFrom(matrix) {
|
|
5998
|
-
const rotationDeg = matrixRotationDegrees(matrix);
|
|
5999
|
-
return {
|
|
6000
|
-
xPt: matrix[4],
|
|
6001
|
-
yPt: matrix[5],
|
|
6002
|
-
widthPt: matrixScaleX(matrix),
|
|
6003
|
-
heightPt: matrixScaleY(matrix),
|
|
6004
|
-
rotationDeg: rotationDeg !== 0 ? rotationDeg : void 0
|
|
6005
|
-
};
|
|
6006
|
-
}
|
|
6007
|
-
function registerExtractedImage(format, bytes, widthPx, heightPx, images) {
|
|
6008
|
-
const imageId = `img${crc32(bytes).toString(16)}`;
|
|
6009
|
-
if (!(imageId in images)) images[imageId] = {
|
|
6010
|
-
format,
|
|
6011
|
-
base64: (0, ooxml_js.bytesToBase64)(bytes),
|
|
6012
|
-
widthPx,
|
|
6013
|
-
heightPx
|
|
6014
|
-
};
|
|
6015
|
-
return imageId;
|
|
6016
|
-
}
|
|
6017
|
-
function resolveCachedImageId(dict, raw, images, cache, resolver, sink) {
|
|
6018
|
-
if (cache.has(dict)) return cache.get(dict) ?? void 0;
|
|
6019
|
-
const decoded = readImageXObject(dict, raw, resolver, sink);
|
|
6020
|
-
if (decoded === void 0) {
|
|
6021
|
-
cache.set(dict, null);
|
|
6022
|
-
return;
|
|
6023
|
-
}
|
|
6024
|
-
const imageId = registerExtractedImage(decoded.format, decoded.bytes, decoded.widthPx, decoded.heightPx, images);
|
|
6025
|
-
cache.set(dict, imageId);
|
|
6026
|
-
return imageId;
|
|
6027
|
-
}
|
|
6028
|
-
function convertImage(item, pageMatrix, images, cache, resolver, sink) {
|
|
6029
|
-
const xobjects = resolver.resolveDict(dictGet(item.resources, "XObject"));
|
|
6030
|
-
const xobj = xobjects !== void 0 ? resolver.resolve(dictGet(xobjects, item.resourceName)) : void 0;
|
|
6031
|
-
if (xobj?.kind !== "stream") return;
|
|
6032
|
-
const imageId = resolveCachedImageId(xobj.dict, xobj.raw, images, cache, resolver, sink);
|
|
6033
|
-
if (imageId === void 0) return;
|
|
6034
|
-
return {
|
|
6035
|
-
kind: "image",
|
|
6036
|
-
imageId,
|
|
6037
|
-
...imagePlacementFrom(multiplyMatrices(item.matrix, pageMatrix))
|
|
6038
|
-
};
|
|
6039
|
-
}
|
|
6040
|
-
function convertInlineImage(item, pageMatrix, images, resolver, sink) {
|
|
6041
|
-
const decoded = readImageXObject(item.dict, item.data, resolver, sink);
|
|
6042
|
-
if (decoded === void 0) return;
|
|
6043
|
-
return {
|
|
6044
|
-
kind: "image",
|
|
6045
|
-
imageId: registerExtractedImage(decoded.format, decoded.bytes, decoded.widthPx, decoded.heightPx, images),
|
|
6046
|
-
...imagePlacementFrom(multiplyMatrices(item.matrix, pageMatrix))
|
|
6047
|
-
};
|
|
6048
|
-
}
|
|
6049
|
-
function readLinkAnnotations(page, pageMatrix, resolver) {
|
|
6050
|
-
const annotsArr = asArray(dictGet(page, "Annots"));
|
|
6051
|
-
if (annotsArr === void 0) return [];
|
|
6052
|
-
const links = [];
|
|
6053
|
-
for (const annotRef of annotsArr) {
|
|
6054
|
-
const annot = resolver.resolveDict(annotRef);
|
|
6055
|
-
if (annot === void 0 || asName(dictGet(annot, "Subtype")) !== "Link") continue;
|
|
6056
|
-
const uri = readLinkUri(annot, resolver);
|
|
6057
|
-
const rectArr = asArray(dictGet(annot, "Rect"));
|
|
6058
|
-
if (uri === void 0 || rectArr === void 0) continue;
|
|
6059
|
-
const x1 = asNumber(rectArr[0]) ?? 0;
|
|
6060
|
-
const y1 = asNumber(rectArr[1]) ?? 0;
|
|
6061
|
-
const x2 = asNumber(rectArr[2]) ?? 0;
|
|
6062
|
-
const y2 = asNumber(rectArr[3]) ?? 0;
|
|
6063
|
-
const p1 = applyMatrix(pageMatrix, {
|
|
6064
|
-
x: Math.min(x1, x2),
|
|
6065
|
-
y: Math.min(y1, y2)
|
|
6066
|
-
});
|
|
6067
|
-
const p2 = applyMatrix(pageMatrix, {
|
|
6068
|
-
x: Math.max(x1, x2),
|
|
6069
|
-
y: Math.max(y1, y2)
|
|
6070
|
-
});
|
|
6071
|
-
links.push({
|
|
6072
|
-
kind: "link",
|
|
6073
|
-
uri,
|
|
6074
|
-
xPt: Math.min(p1.x, p2.x),
|
|
6075
|
-
yPt: Math.min(p1.y, p2.y),
|
|
6076
|
-
widthPt: Math.abs(p2.x - p1.x),
|
|
6077
|
-
heightPt: Math.abs(p2.y - p1.y)
|
|
6078
|
-
});
|
|
6079
|
-
}
|
|
6080
|
-
return links;
|
|
6081
|
-
}
|
|
6082
|
-
function readLinkUri(annot, resolver) {
|
|
6083
|
-
const action = resolver.resolveDict(dictGet(annot, "A"));
|
|
6084
|
-
if (action === void 0 || asName(dictGet(action, "S")) !== "URI") return;
|
|
6085
|
-
const uriObj = dictGet(action, "URI");
|
|
6086
|
-
return uriObj?.kind === "string" ? decodePdfString(uriObj.bytes) : void 0;
|
|
6087
|
-
}
|
|
6088
|
-
function decodePdfString(bytes) {
|
|
6089
|
-
if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255) {
|
|
6090
|
-
let out = "";
|
|
6091
|
-
for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) << 8 | (bytes[i + 1] ?? 0));
|
|
6092
|
-
return out;
|
|
6093
|
-
}
|
|
6094
|
-
return Array.from(bytes, (b) => String.fromCharCode(b)).join("");
|
|
6095
|
-
}
|
|
6096
|
-
const PDF_DATE_PATTERN = /^D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?([+\-Z])?(\d{2})?'?(\d{2})?'?$/;
|
|
6097
|
-
function parsePdfDate(raw) {
|
|
6098
|
-
if (raw === void 0) return;
|
|
6099
|
-
const match = PDF_DATE_PATTERN.exec(raw);
|
|
6100
|
-
if (match === null) return;
|
|
6101
|
-
const [, year, month = "01", day = "01", hour = "00", minute = "00", second = "00", tzSign, tzHour = "00", tzMinute = "00"] = match;
|
|
6102
|
-
return `${year}-${month}-${day}T${hour}:${minute}:${second}${tzSign === void 0 || tzSign === "Z" ? "Z" : `${tzSign}${tzHour}:${tzMinute}`}`;
|
|
6103
|
-
}
|
|
6104
|
-
function readMetadata(trailer, resolver) {
|
|
6105
|
-
const info = resolver.resolveDict(dictGet(trailer, "Info"));
|
|
6106
|
-
if (info === void 0) return {};
|
|
6107
|
-
const stringField = (key) => {
|
|
6108
|
-
const obj = dictGet(info, key);
|
|
6109
|
-
return obj?.kind === "string" ? decodePdfString(obj.bytes) : void 0;
|
|
6110
|
-
};
|
|
6111
|
-
const keywords = stringField("Keywords")?.split(",").map((k) => k.trim()).filter((k) => k.length > 0);
|
|
6112
|
-
return {
|
|
6113
|
-
title: stringField("Title"),
|
|
6114
|
-
author: stringField("Author"),
|
|
6115
|
-
subject: stringField("Subject"),
|
|
6116
|
-
keywords: keywords !== void 0 && keywords.length > 0 ? keywords : void 0,
|
|
6117
|
-
creator: stringField("Creator"),
|
|
6118
|
-
producer: stringField("Producer"),
|
|
6119
|
-
createdIso: parsePdfDate(stringField("CreationDate")),
|
|
6120
|
-
modifiedIso: parsePdfDate(stringField("ModDate"))
|
|
6121
|
-
};
|
|
6122
|
-
}
|
|
6123
|
-
//#endregion
|
|
6124
|
-
//#region src/image/png-decode.ts
|
|
6125
|
-
const PNG_SIGNATURE = [
|
|
6126
|
-
137,
|
|
6127
|
-
80,
|
|
6128
|
-
78,
|
|
6129
|
-
71,
|
|
6130
|
-
13,
|
|
6131
|
-
10,
|
|
6132
|
-
26,
|
|
6133
|
-
10
|
|
6134
|
-
];
|
|
6135
|
-
function requireDataView(bytes) {
|
|
6136
|
-
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
6137
|
-
}
|
|
6138
|
-
function readChunks(bytes, onWarning) {
|
|
6139
|
-
const chunks = [];
|
|
6140
|
-
const view = requireDataView(bytes);
|
|
6141
|
-
let offset = PNG_SIGNATURE.length;
|
|
6142
|
-
while (offset + 8 <= bytes.length) {
|
|
6143
|
-
const length = view.getUint32(offset);
|
|
6144
|
-
const typeBytes = bytes.subarray(offset + 4, offset + 8);
|
|
6145
|
-
const type = new TextDecoder("latin1").decode(typeBytes);
|
|
6146
|
-
const dataStart = offset + 8;
|
|
6147
|
-
const dataEnd = dataStart + length;
|
|
6148
|
-
if (dataEnd + 4 > bytes.length) throw new Error(`PNG chunk '${type}' declares a length that runs past the end of the file`);
|
|
6149
|
-
const data = bytes.subarray(dataStart, dataEnd);
|
|
6150
|
-
if (onWarning !== void 0) {
|
|
6151
|
-
if (view.getUint32(dataEnd) !== crc32(concatBytes([typeBytes, data]))) onWarning(`PNG chunk '${type}' failed its CRC32 check`);
|
|
6152
|
-
}
|
|
6153
|
-
chunks.push({
|
|
6154
|
-
type,
|
|
6155
|
-
data
|
|
6156
|
-
});
|
|
6157
|
-
offset = dataEnd + 4;
|
|
6158
|
-
if (type === "IEND") break;
|
|
6159
|
-
}
|
|
6160
|
-
return chunks;
|
|
6161
|
-
}
|
|
6162
|
-
function parseIhdr(data) {
|
|
6163
|
-
const view = requireDataView(data);
|
|
6164
|
-
return {
|
|
6165
|
-
width: view.getUint32(0),
|
|
6166
|
-
height: view.getUint32(4),
|
|
6167
|
-
bitDepth: data[8],
|
|
6168
|
-
colorType: data[9],
|
|
6169
|
-
interlace: data[12]
|
|
6170
|
-
};
|
|
6171
|
-
}
|
|
6172
|
-
function channelsForColorType(colorType) {
|
|
6173
|
-
if (colorType === 0) return 1;
|
|
6174
|
-
if (colorType === 2) return 3;
|
|
6175
|
-
if (colorType === 3) return 1;
|
|
6176
|
-
if (colorType === 4) return 2;
|
|
6177
|
-
if (colorType === 6) return 4;
|
|
6178
|
-
throw new Error(`unsupported PNG colour type: ${colorType}`);
|
|
6179
|
-
}
|
|
6180
|
-
function filterBpp(bitDepth, channels) {
|
|
6181
|
-
return Math.max(1, Math.ceil(bitDepth * channels / 8));
|
|
6182
|
-
}
|
|
6183
|
-
function unpackRow(rowBytes, width, channels, bitDepth) {
|
|
6184
|
-
const sampleCount = width * channels;
|
|
6185
|
-
const samples = new Array(sampleCount);
|
|
6186
|
-
if (bitDepth === 8) for (let i = 0; i < sampleCount; i++) samples[i] = rowBytes[i];
|
|
6187
|
-
else if (bitDepth === 16) for (let i = 0; i < sampleCount; i++) samples[i] = rowBytes[i * 2];
|
|
6188
|
-
else {
|
|
6189
|
-
const mask = (1 << bitDepth) - 1;
|
|
6190
|
-
for (let i = 0; i < sampleCount; i++) {
|
|
6191
|
-
const bitOffset = i * bitDepth;
|
|
6192
|
-
const byteIndex = bitOffset >> 3;
|
|
6193
|
-
const shift = 8 - bitDepth - (bitOffset & 7);
|
|
6194
|
-
samples[i] = rowBytes[byteIndex] >> shift & mask;
|
|
6195
|
-
}
|
|
6196
|
-
}
|
|
6197
|
-
return samples;
|
|
6198
|
-
}
|
|
6199
|
-
function readTrnsGrayValue(trns) {
|
|
6200
|
-
return requireDataView(trns).getUint16(0);
|
|
5665
|
+
function readTrnsGrayValue(trns) {
|
|
5666
|
+
return requireDataView(trns).getUint16(0);
|
|
6201
5667
|
}
|
|
6202
5668
|
function readTrnsRgbKey(trns) {
|
|
6203
5669
|
const view = requireDataView(trns);
|
|
@@ -6675,8 +6141,25 @@ function buildLinkAnnotDict(link) {
|
|
|
6675
6141
|
function isLinkItem(item) {
|
|
6676
6142
|
return item.kind === "link";
|
|
6677
6143
|
}
|
|
6678
|
-
|
|
6679
|
-
|
|
6144
|
+
const NOTES_ANNOTATION_HIDDEN_FLAG = 2;
|
|
6145
|
+
const NOTES_ANNOTATION_AUTHOR = "documents.js:notes";
|
|
6146
|
+
function buildNotesAnnotDict(notes) {
|
|
6147
|
+
return pdfDict({
|
|
6148
|
+
Type: pdfName("Annot"),
|
|
6149
|
+
Subtype: pdfName("Text"),
|
|
6150
|
+
Rect: pdfArray([
|
|
6151
|
+
0,
|
|
6152
|
+
0,
|
|
6153
|
+
0,
|
|
6154
|
+
0
|
|
6155
|
+
].map((n) => pdfNum(n))),
|
|
6156
|
+
Contents: textToPdfString(notes),
|
|
6157
|
+
T: textToPdfString(NOTES_ANNOTATION_AUTHOR),
|
|
6158
|
+
F: pdfNum(NOTES_ANNOTATION_HIDDEN_FLAG)
|
|
6159
|
+
});
|
|
6160
|
+
}
|
|
6161
|
+
function xrefEntry(offset, generation, inUse) {
|
|
6162
|
+
return `${offset.toString().padStart(10, "0")} ${generation.toString().padStart(5, "0")} ${inUse ? "n" : "f"} \n`;
|
|
6680
6163
|
}
|
|
6681
6164
|
function writePdf(doc, options = {}) {
|
|
6682
6165
|
const compress = options.compress ?? true;
|
|
@@ -6761,90 +6244,433 @@ function writePdf(doc, options = {}) {
|
|
|
6761
6244
|
value: pdfStream(alloc.prepared.dict, alloc.prepared.raw)
|
|
6762
6245
|
});
|
|
6763
6246
|
}
|
|
6764
|
-
const resourceEntries = /* @__PURE__ */ new Map();
|
|
6765
|
-
if (fontAllocs.size > 0) resourceEntries.set("Font", pdfDict(new Map([...fontAllocs.values()].map((alloc) => [alloc.resourceName, pdfRef(alloc.fontNum, 0)]))));
|
|
6766
|
-
if (imageAllocs.size > 0) resourceEntries.set("XObject", pdfDict(new Map([...imageAllocs.values()].map((alloc) => [alloc.resourceName, pdfRef(alloc.imageNum, 0)]))));
|
|
6767
|
-
const resourcesDict = pdfDict(resourceEntries);
|
|
6768
|
-
const context = {
|
|
6769
|
-
measurer,
|
|
6770
|
-
resolveFont: (font) => {
|
|
6771
|
-
const standardName = resolveStandardFont(font.family, font.weight === "bold", font.style === "italic").standardName;
|
|
6772
|
-
const alloc = fontAllocs.get(standardName);
|
|
6773
|
-
if (alloc === void 0) throw new Error(`font "${standardName}" was not pre-allocated -- this is a writePdf internal invariant violation`);
|
|
6774
|
-
return {
|
|
6775
|
-
resourceName: alloc.resourceName,
|
|
6776
|
-
standardName
|
|
6777
|
-
};
|
|
6778
|
-
},
|
|
6779
|
-
resolveImage: (imageId) => {
|
|
6780
|
-
const alloc = imageAllocs.get(imageId);
|
|
6781
|
-
if (alloc === void 0) throw new Error(`image "${imageId}" was not pre-allocated -- this is a writePdf internal invariant violation`);
|
|
6782
|
-
return { resourceName: alloc.resourceName };
|
|
6783
|
-
}
|
|
6247
|
+
const resourceEntries = /* @__PURE__ */ new Map();
|
|
6248
|
+
if (fontAllocs.size > 0) resourceEntries.set("Font", pdfDict(new Map([...fontAllocs.values()].map((alloc) => [alloc.resourceName, pdfRef(alloc.fontNum, 0)]))));
|
|
6249
|
+
if (imageAllocs.size > 0) resourceEntries.set("XObject", pdfDict(new Map([...imageAllocs.values()].map((alloc) => [alloc.resourceName, pdfRef(alloc.imageNum, 0)]))));
|
|
6250
|
+
const resourcesDict = pdfDict(resourceEntries);
|
|
6251
|
+
const context = {
|
|
6252
|
+
measurer,
|
|
6253
|
+
resolveFont: (font) => {
|
|
6254
|
+
const standardName = resolveStandardFont(font.family, font.weight === "bold", font.style === "italic").standardName;
|
|
6255
|
+
const alloc = fontAllocs.get(standardName);
|
|
6256
|
+
if (alloc === void 0) throw new Error(`font "${standardName}" was not pre-allocated -- this is a writePdf internal invariant violation`);
|
|
6257
|
+
return {
|
|
6258
|
+
resourceName: alloc.resourceName,
|
|
6259
|
+
standardName
|
|
6260
|
+
};
|
|
6261
|
+
},
|
|
6262
|
+
resolveImage: (imageId) => {
|
|
6263
|
+
const alloc = imageAllocs.get(imageId);
|
|
6264
|
+
if (alloc === void 0) throw new Error(`image "${imageId}" was not pre-allocated -- this is a writePdf internal invariant violation`);
|
|
6265
|
+
return { resourceName: alloc.resourceName };
|
|
6266
|
+
}
|
|
6267
|
+
};
|
|
6268
|
+
doc.pages.forEach((page, pageIndex) => {
|
|
6269
|
+
throwIfAborted(options.signal);
|
|
6270
|
+
const { pageNum, contentsNum } = pageAllocs[pageIndex];
|
|
6271
|
+
const { bytes: contentBytes, substitutions } = writeContentStream(page.items, context);
|
|
6272
|
+
for (const substitution of substitutions) options.onSubstitution?.(substitution, { pageIndex });
|
|
6273
|
+
const finalContentBytes = compress ? deflate(contentBytes) : contentBytes;
|
|
6274
|
+
const contentsDict = pdfDict(compress ? { Filter: pdfName("FlateDecode") } : {});
|
|
6275
|
+
objects.push({
|
|
6276
|
+
num: contentsNum,
|
|
6277
|
+
value: pdfStream(contentsDict, finalContentBytes)
|
|
6278
|
+
});
|
|
6279
|
+
const annots = page.items.filter(isLinkItem).map((link) => buildLinkAnnotDict(link));
|
|
6280
|
+
if (page.notes !== void 0 && page.notes.length > 0) annots.push(buildNotesAnnotDict(page.notes));
|
|
6281
|
+
const pageEntries = /* @__PURE__ */ new Map([
|
|
6282
|
+
["Type", pdfName("Page")],
|
|
6283
|
+
["Parent", pdfRef(pagesNum, 0)],
|
|
6284
|
+
["MediaBox", pdfArray([
|
|
6285
|
+
0,
|
|
6286
|
+
0,
|
|
6287
|
+
page.widthPt,
|
|
6288
|
+
page.heightPt
|
|
6289
|
+
].map((n) => pdfNum(n)))],
|
|
6290
|
+
["Resources", resourcesDict],
|
|
6291
|
+
["Contents", pdfRef(contentsNum, 0)]
|
|
6292
|
+
]);
|
|
6293
|
+
if (annots.length > 0) pageEntries.set("Annots", pdfArray(annots));
|
|
6294
|
+
objects.push({
|
|
6295
|
+
num: pageNum,
|
|
6296
|
+
value: pdfDict(pageEntries)
|
|
6297
|
+
});
|
|
6298
|
+
});
|
|
6299
|
+
const writer = new ByteWriter();
|
|
6300
|
+
writer.writeAscii("%PDF-1.7\n");
|
|
6301
|
+
const offsets = /* @__PURE__ */ new Map();
|
|
6302
|
+
for (const { num, value } of objects) {
|
|
6303
|
+
offsets.set(num, writer.length);
|
|
6304
|
+
writer.writeAscii(`${num} 0 obj\n`);
|
|
6305
|
+
writeObject(writer, value);
|
|
6306
|
+
writer.writeAscii("\nendobj\n");
|
|
6307
|
+
}
|
|
6308
|
+
const maxObjNum = nextObjNum - 1;
|
|
6309
|
+
const xrefOffset = writer.length;
|
|
6310
|
+
writer.writeAscii("xref\n");
|
|
6311
|
+
writer.writeAscii(`0 ${maxObjNum + 1}\n`);
|
|
6312
|
+
writer.writeAscii(xrefEntry(0, 65535, false));
|
|
6313
|
+
for (let num = 1; num <= maxObjNum; num++) {
|
|
6314
|
+
const offset = offsets.get(num);
|
|
6315
|
+
if (offset === void 0) throw new Error(`object ${num} was allocated but never written -- this is a writePdf internal invariant violation`);
|
|
6316
|
+
writer.writeAscii(xrefEntry(offset, 0, true));
|
|
6317
|
+
}
|
|
6318
|
+
writer.writeAscii("trailer\n");
|
|
6319
|
+
writeObject(writer, pdfDict({
|
|
6320
|
+
Size: pdfNum(maxObjNum + 1),
|
|
6321
|
+
Root: pdfRef(catalogNum, 0),
|
|
6322
|
+
Info: pdfRef(infoNum, 0)
|
|
6323
|
+
}));
|
|
6324
|
+
writer.writeAscii("\nstartxref\n");
|
|
6325
|
+
writer.writeAscii(`${xrefOffset}\n`);
|
|
6326
|
+
writer.writeAscii("%%EOF");
|
|
6327
|
+
return writer.toBytes();
|
|
6328
|
+
}
|
|
6329
|
+
//#endregion
|
|
6330
|
+
//#region src/pdf/read.ts
|
|
6331
|
+
const PDF_HEADER_BYTES = new TextEncoder().encode("%PDF-");
|
|
6332
|
+
const HEADER_SEARCH_WINDOW = 1024;
|
|
6333
|
+
const DEFAULT_PAGE_WIDTH_PT = 612;
|
|
6334
|
+
const DEFAULT_PAGE_HEIGHT_PT = 792;
|
|
6335
|
+
function hasPdfHeader(bytes) {
|
|
6336
|
+
const window = bytes.subarray(0, Math.min(HEADER_SEARCH_WINDOW, bytes.length));
|
|
6337
|
+
outer: for (let i = 0; i <= window.length - PDF_HEADER_BYTES.length; i++) {
|
|
6338
|
+
for (let j = 0; j < PDF_HEADER_BYTES.length; j++) if (window[i + j] !== PDF_HEADER_BYTES[j]) continue outer;
|
|
6339
|
+
return true;
|
|
6340
|
+
}
|
|
6341
|
+
return false;
|
|
6342
|
+
}
|
|
6343
|
+
function readPdf(bytes, options) {
|
|
6344
|
+
const sink = options?.sink ?? NOOP_DIAGNOSTIC_SINK;
|
|
6345
|
+
const signal = options?.signal;
|
|
6346
|
+
if (!hasPdfHeader(bytes)) throw new PdfParseError("pdf/no-header", "no \"%PDF-\" header found within the first bytes of the file; this does not look like a PDF at all");
|
|
6347
|
+
const doc = openPdfDocument(bytes, sink);
|
|
6348
|
+
const resolver = doc;
|
|
6349
|
+
const fontResolver = createFontResolver({
|
|
6350
|
+
resolver,
|
|
6351
|
+
sink
|
|
6352
|
+
});
|
|
6353
|
+
const images = {};
|
|
6354
|
+
const imageIdCache = /* @__PURE__ */ new Map();
|
|
6355
|
+
const pages = doc.pages().map((pageDict) => {
|
|
6356
|
+
throwIfAborted(signal);
|
|
6357
|
+
return readPage(pageDict, resolver, fontResolver, images, imageIdCache, sink);
|
|
6358
|
+
});
|
|
6359
|
+
return {
|
|
6360
|
+
formatVersion: document_content_model.LAYOUT_FORMAT_VERSION,
|
|
6361
|
+
metadata: readMetadata(doc.trailer, resolver),
|
|
6362
|
+
pages,
|
|
6363
|
+
images
|
|
6364
|
+
};
|
|
6365
|
+
}
|
|
6366
|
+
function readMediaBox(page) {
|
|
6367
|
+
const arr = asArray(dictGet(page, "MediaBox"));
|
|
6368
|
+
if (arr === void 0) return {
|
|
6369
|
+
llx: 0,
|
|
6370
|
+
lly: 0,
|
|
6371
|
+
urx: DEFAULT_PAGE_WIDTH_PT,
|
|
6372
|
+
ury: DEFAULT_PAGE_HEIGHT_PT
|
|
6373
|
+
};
|
|
6374
|
+
const a = asNumber(arr[0]) ?? 0;
|
|
6375
|
+
const b = asNumber(arr[1]) ?? 0;
|
|
6376
|
+
const c = asNumber(arr[2]) ?? DEFAULT_PAGE_WIDTH_PT;
|
|
6377
|
+
const d = asNumber(arr[3]) ?? DEFAULT_PAGE_HEIGHT_PT;
|
|
6378
|
+
return {
|
|
6379
|
+
llx: Math.min(a, c),
|
|
6380
|
+
lly: Math.min(b, d),
|
|
6381
|
+
urx: Math.max(a, c),
|
|
6382
|
+
ury: Math.max(b, d)
|
|
6383
|
+
};
|
|
6384
|
+
}
|
|
6385
|
+
function normalizeRotation(rotate) {
|
|
6386
|
+
if (rotate === void 0) return 0;
|
|
6387
|
+
const normalized = (Math.round(rotate / 90) * 90 % 360 + 360) % 360;
|
|
6388
|
+
return normalized === 90 || normalized === 180 || normalized === 270 ? normalized : 0;
|
|
6389
|
+
}
|
|
6390
|
+
function pageRotationTransform(rotation, w, h) {
|
|
6391
|
+
if (rotation === 90) return {
|
|
6392
|
+
matrix: [
|
|
6393
|
+
0,
|
|
6394
|
+
-1,
|
|
6395
|
+
1,
|
|
6396
|
+
0,
|
|
6397
|
+
0,
|
|
6398
|
+
w
|
|
6399
|
+
],
|
|
6400
|
+
widthPt: h,
|
|
6401
|
+
heightPt: w
|
|
6402
|
+
};
|
|
6403
|
+
if (rotation === 180) return {
|
|
6404
|
+
matrix: [
|
|
6405
|
+
-1,
|
|
6406
|
+
0,
|
|
6407
|
+
0,
|
|
6408
|
+
-1,
|
|
6409
|
+
w,
|
|
6410
|
+
h
|
|
6411
|
+
],
|
|
6412
|
+
widthPt: w,
|
|
6413
|
+
heightPt: h
|
|
6414
|
+
};
|
|
6415
|
+
if (rotation === 270) return {
|
|
6416
|
+
matrix: [
|
|
6417
|
+
0,
|
|
6418
|
+
1,
|
|
6419
|
+
-1,
|
|
6420
|
+
0,
|
|
6421
|
+
h,
|
|
6422
|
+
0
|
|
6423
|
+
],
|
|
6424
|
+
widthPt: h,
|
|
6425
|
+
heightPt: w
|
|
6426
|
+
};
|
|
6427
|
+
return {
|
|
6428
|
+
matrix: [
|
|
6429
|
+
1,
|
|
6430
|
+
0,
|
|
6431
|
+
0,
|
|
6432
|
+
1,
|
|
6433
|
+
0,
|
|
6434
|
+
0
|
|
6435
|
+
],
|
|
6436
|
+
widthPt: w,
|
|
6437
|
+
heightPt: h
|
|
6438
|
+
};
|
|
6439
|
+
}
|
|
6440
|
+
function readPageContentBytes(page, resolver, sink) {
|
|
6441
|
+
const contentsObj = resolver.resolve(dictGet(page, "Contents"));
|
|
6442
|
+
if (contentsObj?.kind === "stream") return decodeStream(contentsObj.raw, contentsObj.dict, sink).bytes;
|
|
6443
|
+
if (contentsObj?.kind === "array") {
|
|
6444
|
+
const chunks = [];
|
|
6445
|
+
for (const item of contentsObj.items) {
|
|
6446
|
+
const streamObj = resolver.resolve(item);
|
|
6447
|
+
if (streamObj?.kind === "stream") chunks.push(decodeStream(streamObj.raw, streamObj.dict, sink).bytes, new Uint8Array([10]));
|
|
6448
|
+
}
|
|
6449
|
+
return concatBytes(chunks);
|
|
6450
|
+
}
|
|
6451
|
+
return /* @__PURE__ */ new Uint8Array(0);
|
|
6452
|
+
}
|
|
6453
|
+
function readPage(page, resolver, fontResolver, images, imageIdCache, sink) {
|
|
6454
|
+
const resources = resolver.resolveDict(dictGet(page, "Resources"));
|
|
6455
|
+
const mediaBox = readMediaBox(page);
|
|
6456
|
+
const rotationResult = pageRotationTransform(normalizeRotation(asNumber(dictGet(page, "Rotate"))), mediaBox.urx - mediaBox.llx, mediaBox.ury - mediaBox.lly);
|
|
6457
|
+
const pageMatrix = multiplyMatrices(translationMatrix(-mediaBox.llx, -mediaBox.lly), rotationResult.matrix);
|
|
6458
|
+
const items = [];
|
|
6459
|
+
if (resources !== void 0) {
|
|
6460
|
+
const extracted = interpretContentStream(readPageContentBytes(page, resolver, sink), resources, {
|
|
6461
|
+
fontMetrics: fontResolver.metrics,
|
|
6462
|
+
resolver,
|
|
6463
|
+
sink
|
|
6464
|
+
});
|
|
6465
|
+
for (const item of extracted) {
|
|
6466
|
+
const converted = convertExtractedItem(item, pageMatrix, fontResolver, images, imageIdCache, resolver, sink);
|
|
6467
|
+
if (converted !== void 0) items.push(converted);
|
|
6468
|
+
}
|
|
6469
|
+
} else sink({
|
|
6470
|
+
code: "pdf/object-missing-value",
|
|
6471
|
+
severity: "warning",
|
|
6472
|
+
message: "page has no /Resources dict; its content stream cannot be interpreted"
|
|
6473
|
+
});
|
|
6474
|
+
items.push(...readLinkAnnotations(page, pageMatrix, resolver));
|
|
6475
|
+
const notes = readPageNotes(page, resolver);
|
|
6476
|
+
return {
|
|
6477
|
+
widthPt: rotationResult.widthPt,
|
|
6478
|
+
heightPt: rotationResult.heightPt,
|
|
6479
|
+
items,
|
|
6480
|
+
...notes !== void 0 ? { notes } : {}
|
|
6481
|
+
};
|
|
6482
|
+
}
|
|
6483
|
+
function convertExtractedItem(item, pageMatrix, fontResolver, images, imageIdCache, resolver, sink) {
|
|
6484
|
+
if (item.kind === "text") return convertText(item, pageMatrix, fontResolver);
|
|
6485
|
+
if (item.kind === "rect") return convertRect(item, pageMatrix);
|
|
6486
|
+
if (item.kind === "image") return convertImage(item, pageMatrix, images, imageIdCache, resolver, sink);
|
|
6487
|
+
return convertInlineImage(item, pageMatrix, images, resolver, sink);
|
|
6488
|
+
}
|
|
6489
|
+
function convertText(item, pageMatrix, fontResolver) {
|
|
6490
|
+
const font = fontResolver.resolve(item.fontResourceName, item.resources);
|
|
6491
|
+
const text = font?.decodeToUnicode(item.codes) ?? "";
|
|
6492
|
+
if (text.length === 0) return;
|
|
6493
|
+
const startTrm = multiplyMatrices(item.startMatrix, pageMatrix);
|
|
6494
|
+
const endTrm = multiplyMatrices(item.endMatrix, pageMatrix);
|
|
6495
|
+
const widthPt = Math.hypot(endTrm[4] - startTrm[4], endTrm[5] - startTrm[5]);
|
|
6496
|
+
const sizePt = matrixScaleX(startTrm);
|
|
6497
|
+
const rotationDeg = matrixRotationDegrees(startTrm);
|
|
6498
|
+
const layoutFont = {
|
|
6499
|
+
family: font?.family ?? "Helvetica",
|
|
6500
|
+
weight: font?.bold === true ? "bold" : "normal",
|
|
6501
|
+
style: font?.italic === true ? "italic" : "normal"
|
|
6502
|
+
};
|
|
6503
|
+
return {
|
|
6504
|
+
kind: "text",
|
|
6505
|
+
text,
|
|
6506
|
+
xPt: startTrm[4],
|
|
6507
|
+
yPt: startTrm[5],
|
|
6508
|
+
font: layoutFont,
|
|
6509
|
+
sizePt: sizePt > 0 ? sizePt : item.sizePt,
|
|
6510
|
+
color: item.color,
|
|
6511
|
+
widthPt,
|
|
6512
|
+
rotationDeg: rotationDeg !== 0 ? rotationDeg : void 0
|
|
6513
|
+
};
|
|
6514
|
+
}
|
|
6515
|
+
function convertRect(item, pageMatrix) {
|
|
6516
|
+
const p1 = applyMatrix(pageMatrix, {
|
|
6517
|
+
x: item.xPt,
|
|
6518
|
+
y: item.yPt
|
|
6519
|
+
});
|
|
6520
|
+
const p2 = applyMatrix(pageMatrix, {
|
|
6521
|
+
x: item.xPt + item.widthPt,
|
|
6522
|
+
y: item.yPt + item.heightPt
|
|
6523
|
+
});
|
|
6524
|
+
return {
|
|
6525
|
+
kind: "rect",
|
|
6526
|
+
xPt: Math.min(p1.x, p2.x),
|
|
6527
|
+
yPt: Math.min(p1.y, p2.y),
|
|
6528
|
+
widthPt: Math.abs(p2.x - p1.x),
|
|
6529
|
+
heightPt: Math.abs(p2.y - p1.y),
|
|
6530
|
+
fill: item.color
|
|
6531
|
+
};
|
|
6532
|
+
}
|
|
6533
|
+
function imagePlacementFrom(matrix) {
|
|
6534
|
+
const rotationDeg = matrixRotationDegrees(matrix);
|
|
6535
|
+
return {
|
|
6536
|
+
xPt: matrix[4],
|
|
6537
|
+
yPt: matrix[5],
|
|
6538
|
+
widthPt: matrixScaleX(matrix),
|
|
6539
|
+
heightPt: matrixScaleY(matrix),
|
|
6540
|
+
rotationDeg: rotationDeg !== 0 ? rotationDeg : void 0
|
|
6541
|
+
};
|
|
6542
|
+
}
|
|
6543
|
+
function registerExtractedImage(format, bytes, widthPx, heightPx, images) {
|
|
6544
|
+
const imageId = `img${crc32(bytes).toString(16)}`;
|
|
6545
|
+
if (!(imageId in images)) images[imageId] = {
|
|
6546
|
+
format,
|
|
6547
|
+
base64: (0, ooxml_js.bytesToBase64)(bytes),
|
|
6548
|
+
widthPx,
|
|
6549
|
+
heightPx
|
|
6550
|
+
};
|
|
6551
|
+
return imageId;
|
|
6552
|
+
}
|
|
6553
|
+
function resolveCachedImageId(dict, raw, images, cache, resolver, sink) {
|
|
6554
|
+
if (cache.has(dict)) return cache.get(dict) ?? void 0;
|
|
6555
|
+
const decoded = readImageXObject(dict, raw, resolver, sink);
|
|
6556
|
+
if (decoded === void 0) {
|
|
6557
|
+
cache.set(dict, null);
|
|
6558
|
+
return;
|
|
6559
|
+
}
|
|
6560
|
+
const imageId = registerExtractedImage(decoded.format, decoded.bytes, decoded.widthPx, decoded.heightPx, images);
|
|
6561
|
+
cache.set(dict, imageId);
|
|
6562
|
+
return imageId;
|
|
6563
|
+
}
|
|
6564
|
+
function convertImage(item, pageMatrix, images, cache, resolver, sink) {
|
|
6565
|
+
const xobjects = resolver.resolveDict(dictGet(item.resources, "XObject"));
|
|
6566
|
+
const xobj = xobjects !== void 0 ? resolver.resolve(dictGet(xobjects, item.resourceName)) : void 0;
|
|
6567
|
+
if (xobj?.kind !== "stream") return;
|
|
6568
|
+
const imageId = resolveCachedImageId(xobj.dict, xobj.raw, images, cache, resolver, sink);
|
|
6569
|
+
if (imageId === void 0) return;
|
|
6570
|
+
return {
|
|
6571
|
+
kind: "image",
|
|
6572
|
+
imageId,
|
|
6573
|
+
...imagePlacementFrom(multiplyMatrices(item.matrix, pageMatrix))
|
|
6784
6574
|
};
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6575
|
+
}
|
|
6576
|
+
function convertInlineImage(item, pageMatrix, images, resolver, sink) {
|
|
6577
|
+
const decoded = readImageXObject(item.dict, item.data, resolver, sink);
|
|
6578
|
+
if (decoded === void 0) return;
|
|
6579
|
+
return {
|
|
6580
|
+
kind: "image",
|
|
6581
|
+
imageId: registerExtractedImage(decoded.format, decoded.bytes, decoded.widthPx, decoded.heightPx, images),
|
|
6582
|
+
...imagePlacementFrom(multiplyMatrices(item.matrix, pageMatrix))
|
|
6583
|
+
};
|
|
6584
|
+
}
|
|
6585
|
+
function readLinkAnnotations(page, pageMatrix, resolver) {
|
|
6586
|
+
const annotsArr = asArray(dictGet(page, "Annots"));
|
|
6587
|
+
if (annotsArr === void 0) return [];
|
|
6588
|
+
const links = [];
|
|
6589
|
+
for (const annotRef of annotsArr) {
|
|
6590
|
+
const annot = resolver.resolveDict(annotRef);
|
|
6591
|
+
if (annot === void 0 || asName(dictGet(annot, "Subtype")) !== "Link") continue;
|
|
6592
|
+
const uri = readLinkUri(annot, resolver);
|
|
6593
|
+
const rectArr = asArray(dictGet(annot, "Rect"));
|
|
6594
|
+
if (uri === void 0 || rectArr === void 0) continue;
|
|
6595
|
+
const x1 = asNumber(rectArr[0]) ?? 0;
|
|
6596
|
+
const y1 = asNumber(rectArr[1]) ?? 0;
|
|
6597
|
+
const x2 = asNumber(rectArr[2]) ?? 0;
|
|
6598
|
+
const y2 = asNumber(rectArr[3]) ?? 0;
|
|
6599
|
+
const p1 = applyMatrix(pageMatrix, {
|
|
6600
|
+
x: Math.min(x1, x2),
|
|
6601
|
+
y: Math.min(y1, y2)
|
|
6795
6602
|
});
|
|
6796
|
-
const
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
["Contents", pdfRef(contentsNum, 0)]
|
|
6808
|
-
]);
|
|
6809
|
-
if (annots.length > 0) pageEntries.set("Annots", pdfArray(annots));
|
|
6810
|
-
objects.push({
|
|
6811
|
-
num: pageNum,
|
|
6812
|
-
value: pdfDict(pageEntries)
|
|
6603
|
+
const p2 = applyMatrix(pageMatrix, {
|
|
6604
|
+
x: Math.max(x1, x2),
|
|
6605
|
+
y: Math.max(y1, y2)
|
|
6606
|
+
});
|
|
6607
|
+
links.push({
|
|
6608
|
+
kind: "link",
|
|
6609
|
+
uri,
|
|
6610
|
+
xPt: Math.min(p1.x, p2.x),
|
|
6611
|
+
yPt: Math.min(p1.y, p2.y),
|
|
6612
|
+
widthPt: Math.abs(p2.x - p1.x),
|
|
6613
|
+
heightPt: Math.abs(p2.y - p1.y)
|
|
6813
6614
|
});
|
|
6814
|
-
});
|
|
6815
|
-
const writer = new ByteWriter();
|
|
6816
|
-
writer.writeAscii("%PDF-1.7\n");
|
|
6817
|
-
const offsets = /* @__PURE__ */ new Map();
|
|
6818
|
-
for (const { num, value } of objects) {
|
|
6819
|
-
offsets.set(num, writer.length);
|
|
6820
|
-
writer.writeAscii(`${num} 0 obj\n`);
|
|
6821
|
-
writeObject(writer, value);
|
|
6822
|
-
writer.writeAscii("\nendobj\n");
|
|
6823
6615
|
}
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6616
|
+
return links;
|
|
6617
|
+
}
|
|
6618
|
+
function readLinkUri(annot, resolver) {
|
|
6619
|
+
const action = resolver.resolveDict(dictGet(annot, "A"));
|
|
6620
|
+
if (action === void 0 || asName(dictGet(action, "S")) !== "URI") return;
|
|
6621
|
+
const uriObj = dictGet(action, "URI");
|
|
6622
|
+
return uriObj?.kind === "string" ? decodePdfString(uriObj.bytes) : void 0;
|
|
6623
|
+
}
|
|
6624
|
+
function readPageNotes(page, resolver) {
|
|
6625
|
+
const annotsArr = asArray(dictGet(page, "Annots"));
|
|
6626
|
+
if (annotsArr === void 0) return;
|
|
6627
|
+
for (const annotRef of annotsArr) {
|
|
6628
|
+
const annot = resolver.resolveDict(annotRef);
|
|
6629
|
+
if (annot === void 0 || asName(dictGet(annot, "Subtype")) !== "Text") continue;
|
|
6630
|
+
const titleObj = dictGet(annot, "T");
|
|
6631
|
+
if ((titleObj?.kind === "string" ? decodePdfString(titleObj.bytes) : void 0) !== "documents.js:notes") continue;
|
|
6632
|
+
const contentsObj = dictGet(annot, "Contents");
|
|
6633
|
+
if (contentsObj?.kind === "string") return decodePdfString(contentsObj.bytes);
|
|
6833
6634
|
}
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6635
|
+
}
|
|
6636
|
+
function decodePdfString(bytes) {
|
|
6637
|
+
if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255) {
|
|
6638
|
+
let out = "";
|
|
6639
|
+
for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode((bytes[i] ?? 0) << 8 | (bytes[i + 1] ?? 0));
|
|
6640
|
+
return out;
|
|
6641
|
+
}
|
|
6642
|
+
return Array.from(bytes, (b) => String.fromCharCode(b)).join("");
|
|
6643
|
+
}
|
|
6644
|
+
const PDF_DATE_PATTERN = /^D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?([+\-Z])?(\d{2})?'?(\d{2})?'?$/;
|
|
6645
|
+
function parsePdfDate(raw) {
|
|
6646
|
+
if (raw === void 0) return;
|
|
6647
|
+
const match = PDF_DATE_PATTERN.exec(raw);
|
|
6648
|
+
if (match === null) return;
|
|
6649
|
+
const [, year, month = "01", day = "01", hour = "00", minute = "00", second = "00", tzSign, tzHour = "00", tzMinute = "00"] = match;
|
|
6650
|
+
return `${year}-${month}-${day}T${hour}:${minute}:${second}${tzSign === void 0 || tzSign === "Z" ? "Z" : `${tzSign}${tzHour}:${tzMinute}`}`;
|
|
6651
|
+
}
|
|
6652
|
+
function readMetadata(trailer, resolver) {
|
|
6653
|
+
const info = resolver.resolveDict(dictGet(trailer, "Info"));
|
|
6654
|
+
if (info === void 0) return {};
|
|
6655
|
+
const stringField = (key) => {
|
|
6656
|
+
const obj = dictGet(info, key);
|
|
6657
|
+
return obj?.kind === "string" ? decodePdfString(obj.bytes) : void 0;
|
|
6658
|
+
};
|
|
6659
|
+
const keywords = stringField("Keywords")?.split(",").map((k) => k.trim()).filter((k) => k.length > 0);
|
|
6660
|
+
return {
|
|
6661
|
+
title: stringField("Title"),
|
|
6662
|
+
author: stringField("Author"),
|
|
6663
|
+
subject: stringField("Subject"),
|
|
6664
|
+
keywords: keywords !== void 0 && keywords.length > 0 ? keywords : void 0,
|
|
6665
|
+
creator: stringField("Creator"),
|
|
6666
|
+
producer: stringField("Producer"),
|
|
6667
|
+
createdIso: parsePdfDate(stringField("CreationDate")),
|
|
6668
|
+
modifiedIso: parsePdfDate(stringField("ModDate"))
|
|
6669
|
+
};
|
|
6844
6670
|
}
|
|
6845
6671
|
//#endregion
|
|
6846
6672
|
//#region src/pdf/codec.ts
|
|
6847
|
-
const pdfCodec = zod.z.codec(PdfBytesSchema, LayoutDocumentSchema, {
|
|
6673
|
+
const pdfCodec = zod.z.codec(PdfBytesSchema, document_content_model.LayoutDocumentSchema, {
|
|
6848
6674
|
decode: (bytes) => readPdf(bytes),
|
|
6849
6675
|
encode: (doc) => writePdf(doc)
|
|
6850
6676
|
});
|
|
@@ -7085,7 +6911,7 @@ function wrapRunsToWidth(runs, measurer, maxWidthPt, options = {}) {
|
|
|
7085
6911
|
const FALLBACK_ROW_HEIGHT_PT = 20;
|
|
7086
6912
|
function runFont(run) {
|
|
7087
6913
|
return {
|
|
7088
|
-
family: run.fontFamily ?? DEFAULT_LAYOUT_FONT.family,
|
|
6914
|
+
family: run.fontFamily ?? document_content_model.DEFAULT_LAYOUT_FONT.family,
|
|
7089
6915
|
weight: run.bold === true ? "bold" : "normal",
|
|
7090
6916
|
style: run.italic === true ? "italic" : "normal"
|
|
7091
6917
|
};
|
|
@@ -7095,7 +6921,7 @@ function toStyledRuns(runs, fontScale = 1) {
|
|
|
7095
6921
|
text: run.text,
|
|
7096
6922
|
font: runFont(run),
|
|
7097
6923
|
sizePt: (run.sizePt ?? 18) * fontScale,
|
|
7098
|
-
color: run.color ??
|
|
6924
|
+
color: run.color ?? document_content_model.COLOR_BLACK,
|
|
7099
6925
|
underline: run.underline,
|
|
7100
6926
|
hyperlink: run.hyperlink
|
|
7101
6927
|
}));
|
|
@@ -7104,9 +6930,9 @@ function effectiveStyledRuns(runs, fontScale = 1) {
|
|
|
7104
6930
|
const styled = toStyledRuns(runs, fontScale);
|
|
7105
6931
|
return styled.length > 0 ? styled : [{
|
|
7106
6932
|
text: "",
|
|
7107
|
-
font: DEFAULT_LAYOUT_FONT,
|
|
6933
|
+
font: document_content_model.DEFAULT_LAYOUT_FONT,
|
|
7108
6934
|
sizePt: 18 * fontScale,
|
|
7109
|
-
color:
|
|
6935
|
+
color: document_content_model.COLOR_BLACK
|
|
7110
6936
|
}];
|
|
7111
6937
|
}
|
|
7112
6938
|
function lineNaturalHeightPt(line, measurer, fallback) {
|
|
@@ -7329,7 +7155,7 @@ function convertWordprocessingToLayout(doc, options) {
|
|
|
7329
7155
|
const pages = [];
|
|
7330
7156
|
for (const section of doc.sections) paginateSection(section, options.measurer, images, pages);
|
|
7331
7157
|
return {
|
|
7332
|
-
formatVersion:
|
|
7158
|
+
formatVersion: document_content_model.LAYOUT_FORMAT_VERSION,
|
|
7333
7159
|
metadata: doc.metadata,
|
|
7334
7160
|
pages,
|
|
7335
7161
|
images
|
|
@@ -7472,14 +7298,15 @@ function convertSlide(slide, measurer, images) {
|
|
|
7472
7298
|
return {
|
|
7473
7299
|
widthPt: slide.size.widthPt,
|
|
7474
7300
|
heightPt: slide.size.heightPt,
|
|
7475
|
-
items
|
|
7301
|
+
items,
|
|
7302
|
+
...slide.notes.length > 0 ? { notes: slide.notes } : {}
|
|
7476
7303
|
};
|
|
7477
7304
|
}
|
|
7478
7305
|
function convertPresentationToLayout(doc, options) {
|
|
7479
7306
|
const images = {};
|
|
7480
7307
|
const pages = doc.slides.map((slide) => convertSlide(slide, options.measurer, images));
|
|
7481
7308
|
return {
|
|
7482
|
-
formatVersion:
|
|
7309
|
+
formatVersion: document_content_model.LAYOUT_FORMAT_VERSION,
|
|
7483
7310
|
metadata: doc.metadata,
|
|
7484
7311
|
pages,
|
|
7485
7312
|
images
|
|
@@ -7710,7 +7537,7 @@ function reconstructSlide(page, images) {
|
|
|
7710
7537
|
heightPt: page.heightPt
|
|
7711
7538
|
},
|
|
7712
7539
|
shapes: [...imageShapes, ...textShapes],
|
|
7713
|
-
notes: ""
|
|
7540
|
+
notes: page.notes ?? ""
|
|
7714
7541
|
};
|
|
7715
7542
|
}
|
|
7716
7543
|
function splitLineByLargeGaps(line) {
|
|
@@ -7983,7 +7810,7 @@ Object.defineProperty(exports, "BinaryPartSchema", {
|
|
|
7983
7810
|
Object.defineProperty(exports, "COLOR_BLACK", {
|
|
7984
7811
|
enumerable: true,
|
|
7985
7812
|
get: function() {
|
|
7986
|
-
return
|
|
7813
|
+
return document_content_model.COLOR_BLACK;
|
|
7987
7814
|
}
|
|
7988
7815
|
});
|
|
7989
7816
|
exports.CONTENT_FORMAT_VERSION = CONTENT_FORMAT_VERSION;
|
|
@@ -8011,19 +7838,79 @@ Object.defineProperty(exports, "CompactXmlNodeSchema", {
|
|
|
8011
7838
|
return ooxml_js.CompactXmlNodeSchema;
|
|
8012
7839
|
}
|
|
8013
7840
|
});
|
|
8014
|
-
exports
|
|
7841
|
+
Object.defineProperty(exports, "ContentBlockSchema", {
|
|
7842
|
+
enumerable: true,
|
|
7843
|
+
get: function() {
|
|
7844
|
+
return document_content_model.ContentBlockSchema;
|
|
7845
|
+
}
|
|
7846
|
+
});
|
|
8015
7847
|
exports.ContentDocumentSchema = ContentDocumentSchema;
|
|
8016
|
-
exports
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
exports
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
7848
|
+
Object.defineProperty(exports, "ContentImageBlockSchema", {
|
|
7849
|
+
enumerable: true,
|
|
7850
|
+
get: function() {
|
|
7851
|
+
return document_content_model.ContentImageBlockSchema;
|
|
7852
|
+
}
|
|
7853
|
+
});
|
|
7854
|
+
Object.defineProperty(exports, "ContentPageBreakSchema", {
|
|
7855
|
+
enumerable: true,
|
|
7856
|
+
get: function() {
|
|
7857
|
+
return document_content_model.ContentPageBreakSchema;
|
|
7858
|
+
}
|
|
7859
|
+
});
|
|
7860
|
+
Object.defineProperty(exports, "ContentParagraphSchema", {
|
|
7861
|
+
enumerable: true,
|
|
7862
|
+
get: function() {
|
|
7863
|
+
return document_content_model.ContentParagraphSchema;
|
|
7864
|
+
}
|
|
7865
|
+
});
|
|
7866
|
+
Object.defineProperty(exports, "ContentRunSchema", {
|
|
7867
|
+
enumerable: true,
|
|
7868
|
+
get: function() {
|
|
7869
|
+
return document_content_model.ContentRunSchema;
|
|
7870
|
+
}
|
|
7871
|
+
});
|
|
7872
|
+
Object.defineProperty(exports, "ContentSectionSchema", {
|
|
7873
|
+
enumerable: true,
|
|
7874
|
+
get: function() {
|
|
7875
|
+
return document_content_model.ContentSectionSchema;
|
|
7876
|
+
}
|
|
7877
|
+
});
|
|
7878
|
+
Object.defineProperty(exports, "ContentShapeSchema", {
|
|
7879
|
+
enumerable: true,
|
|
7880
|
+
get: function() {
|
|
7881
|
+
return document_content_model.ContentShapeSchema;
|
|
7882
|
+
}
|
|
7883
|
+
});
|
|
7884
|
+
Object.defineProperty(exports, "ContentSlideSchema", {
|
|
7885
|
+
enumerable: true,
|
|
7886
|
+
get: function() {
|
|
7887
|
+
return document_content_model.ContentSlideSchema;
|
|
7888
|
+
}
|
|
7889
|
+
});
|
|
7890
|
+
Object.defineProperty(exports, "ContentTableCellSchema", {
|
|
7891
|
+
enumerable: true,
|
|
7892
|
+
get: function() {
|
|
7893
|
+
return document_content_model.ContentTableCellSchema;
|
|
7894
|
+
}
|
|
7895
|
+
});
|
|
7896
|
+
Object.defineProperty(exports, "ContentTableRowSchema", {
|
|
7897
|
+
enumerable: true,
|
|
7898
|
+
get: function() {
|
|
7899
|
+
return document_content_model.ContentTableRowSchema;
|
|
7900
|
+
}
|
|
7901
|
+
});
|
|
7902
|
+
Object.defineProperty(exports, "ContentTableSchema", {
|
|
7903
|
+
enumerable: true,
|
|
7904
|
+
get: function() {
|
|
7905
|
+
return document_content_model.ContentTableSchema;
|
|
7906
|
+
}
|
|
7907
|
+
});
|
|
7908
|
+
Object.defineProperty(exports, "DEFAULT_LAYOUT_FONT", {
|
|
7909
|
+
enumerable: true,
|
|
7910
|
+
get: function() {
|
|
7911
|
+
return document_content_model.DEFAULT_LAYOUT_FONT;
|
|
7912
|
+
}
|
|
7913
|
+
});
|
|
8027
7914
|
Object.defineProperty(exports, "DefinedNameSchema", {
|
|
8028
7915
|
enumerable: true,
|
|
8029
7916
|
get: function() {
|
|
@@ -8037,18 +7924,23 @@ exports.DocxRun = DocxRun;
|
|
|
8037
7924
|
exports.DocxTable = DocxTable;
|
|
8038
7925
|
exports.DocxTableCell = DocxTableCell;
|
|
8039
7926
|
exports.DocxTableRow = DocxTableRow;
|
|
8040
|
-
exports
|
|
7927
|
+
Object.defineProperty(exports, "LAYOUT_FORMAT_VERSION", {
|
|
7928
|
+
enumerable: true,
|
|
7929
|
+
get: function() {
|
|
7930
|
+
return document_content_model.LAYOUT_FORMAT_VERSION;
|
|
7931
|
+
}
|
|
7932
|
+
});
|
|
8041
7933
|
exports.NOOP_DIAGNOSTIC_SINK = NOOP_DIAGNOSTIC_SINK;
|
|
8042
7934
|
Object.defineProperty(exports, "PAGE_SIZE_A4", {
|
|
8043
7935
|
enumerable: true,
|
|
8044
7936
|
get: function() {
|
|
8045
|
-
return
|
|
7937
|
+
return document_content_model.PAGE_SIZE_A4;
|
|
8046
7938
|
}
|
|
8047
7939
|
});
|
|
8048
7940
|
Object.defineProperty(exports, "PAGE_SIZE_LETTER", {
|
|
8049
7941
|
enumerable: true,
|
|
8050
7942
|
get: function() {
|
|
8051
|
-
return
|
|
7943
|
+
return document_content_model.PAGE_SIZE_LETTER;
|
|
8052
7944
|
}
|
|
8053
7945
|
});
|
|
8054
7946
|
Object.defineProperty(exports, "PackageSchema", {
|
|
@@ -8073,13 +7965,13 @@ exports.PptxSlide = PptxSlide;
|
|
|
8073
7965
|
Object.defineProperty(exports, "SLIDE_SIZE_STANDARD", {
|
|
8074
7966
|
enumerable: true,
|
|
8075
7967
|
get: function() {
|
|
8076
|
-
return
|
|
7968
|
+
return document_content_model.SLIDE_SIZE_STANDARD;
|
|
8077
7969
|
}
|
|
8078
7970
|
});
|
|
8079
7971
|
Object.defineProperty(exports, "SLIDE_SIZE_WIDESCREEN", {
|
|
8080
7972
|
enumerable: true,
|
|
8081
7973
|
get: function() {
|
|
8082
|
-
return
|
|
7974
|
+
return document_content_model.SLIDE_SIZE_WIDESCREEN;
|
|
8083
7975
|
}
|
|
8084
7976
|
});
|
|
8085
7977
|
Object.defineProperty(exports, "XmlCdataSchema", {
|
|
@@ -8231,7 +8123,12 @@ Object.defineProperty(exports, "isCompactXmlNode", {
|
|
|
8231
8123
|
return ooxml_js.isCompactXmlNode;
|
|
8232
8124
|
}
|
|
8233
8125
|
});
|
|
8234
|
-
exports
|
|
8126
|
+
Object.defineProperty(exports, "isContentBlock", {
|
|
8127
|
+
enumerable: true,
|
|
8128
|
+
get: function() {
|
|
8129
|
+
return document_content_model.isContentBlock;
|
|
8130
|
+
}
|
|
8131
|
+
});
|
|
8235
8132
|
Object.defineProperty(exports, "isXmlNode", {
|
|
8236
8133
|
enumerable: true,
|
|
8237
8134
|
get: function() {
|
|
@@ -8277,7 +8174,7 @@ Object.defineProperty(exports, "resolveRelationships", {
|
|
|
8277
8174
|
Object.defineProperty(exports, "rgbHexToColor", {
|
|
8278
8175
|
enumerable: true,
|
|
8279
8176
|
get: function() {
|
|
8280
|
-
return
|
|
8177
|
+
return document_content_model.rgbHexToColor;
|
|
8281
8178
|
}
|
|
8282
8179
|
});
|
|
8283
8180
|
Object.defineProperty(exports, "rootElement", {
|