reamkit 1.33.1 → 1.34.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 +13 -10
- package/dist/esm/core/converter/facade.js +1 -0
- package/dist/esm/core/converter/ream.d.ts +6 -6
- package/dist/esm/core/converter/ream.js +11 -5
- package/dist/esm/core/crypto/index.js +1 -2
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +15 -0
- package/dist/esm/core/drawingml/text-warp.d.ts +34 -0
- package/dist/esm/core/drawingml/text-warp.js +49 -1
- package/dist/esm/core/font/index.d.ts +1 -1
- package/dist/esm/core/font/index.js +8 -0
- package/dist/esm/core/font/indic-shaper.d.ts +47 -0
- package/dist/esm/core/font/indic-shaper.js +1146 -0
- package/dist/esm/core/font/indic-table.d.ts +12 -0
- package/dist/esm/core/font/indic-table.js +463 -0
- package/dist/esm/core/font/measure.d.ts +45 -4
- package/dist/esm/core/font/measure.js +253 -14
- package/dist/esm/core/font/opentype-lookups.d.ts +214 -0
- package/dist/esm/core/font/opentype-lookups.js +1112 -0
- package/dist/esm/core/fonts/families.d.ts +4 -0
- package/dist/esm/core/fonts/families.js +43 -12
- package/dist/esm/core/fonts/provider.js +1 -0
- package/dist/esm/core/fonts/remote-fonts.d.ts +4 -2
- package/dist/esm/core/fonts/remote-fonts.js +36 -0
- package/dist/esm/core/fonts/scripts.d.ts +19 -0
- package/dist/esm/core/fonts/scripts.js +96 -1
- package/dist/esm/core/numbering/apply.js +12 -8
- package/dist/esm/core/style-cascade/index.d.ts +1 -1
- package/dist/esm/core/style-cascade/index.js +2 -2
- package/dist/esm/core/style-cascade/resolver.d.ts +9 -0
- package/dist/esm/core/style-cascade/resolver.js +31 -3
- package/dist/esm/core/style-cascade/table.js +3 -8
- package/dist/esm/excel/xlsx-to-pdf.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/layout/line-paint.d.ts +5 -4
- package/dist/esm/layout/line-paint.js +6 -5
- package/dist/esm/layout/page-doc.d.ts +26 -0
- package/dist/esm/layout/styled-layout.d.ts +8 -1
- package/dist/esm/layout/styled-layout.js +459 -112
- package/dist/esm/layout/undrawn.d.ts +18 -0
- package/dist/esm/layout/undrawn.js +59 -0
- package/dist/esm/pdf/cid-font.d.ts +5 -0
- package/dist/esm/pdf/cid-font.js +8 -2
- package/dist/esm/pdf/styled-page-emitter.js +117 -28
- package/dist/esm/pdf/text-page-renderer.js +1 -0
- package/dist/esm/pdf-reader/content.d.ts +1 -1
- package/dist/esm/pdf-reader/content.js +48 -13
- package/dist/esm/pdf-reader/embedded-fonts.js +1 -0
- package/dist/esm/pdf-reader/encodings.d.ts +9 -0
- package/dist/esm/pdf-reader/encodings.js +66 -1
- package/dist/esm/pdf-reader/face-outlines.js +1 -0
- package/dist/esm/pdf-reader/text.d.ts +10 -0
- package/dist/esm/pdf-reader/text.js +25 -3
- package/dist/esm/pdf-reader/vector.js +2 -2
- package/dist/esm/pptx/embedded-fonts.js +1 -0
- package/dist/esm/pptx/slide-parser.js +22 -7
- package/dist/esm/pptx/sp-helpers.d.ts +3 -2
- package/dist/esm/pptx/sp-helpers.js +9 -4
- package/dist/esm/svg/svg-text.js +30 -7
- package/dist/esm/word/doc/doc-reader.js +148 -57
- package/dist/esm/word/doc/doc-text.d.ts +80 -11
- package/dist/esm/word/doc/doc-text.js +438 -75
- package/dist/esm/word/document-parser.js +48 -28
- package/dist/esm/word/docx-to-pdf.d.ts +5 -5
- package/dist/esm/word/docx-to-pdf.js +9 -7
- package/dist/esm/word/docx-writer.js +3 -5
- package/dist/esm/word/font-embed.js +1 -0
- package/dist/esm/word/font-table.js +1 -0
- package/dist/esm/word/numbering-parser.js +3 -0
- package/dist/esm/word/paragraph-properties.js +2 -2
- package/dist/esm/word/run-properties.js +2 -2
- package/dist/esm/word/xml-helpers.d.ts +18 -0
- package/dist/esm/word/xml-helpers.js +48 -1
- package/package.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { PDF_NULL, PdfName, PdfStream } from "../pdf/objects.js";
|
|
1
|
+
import { PDF_NULL, PdfHexString, PdfName, PdfStream } from "../pdf/objects.js";
|
|
2
|
+
import { pdfTextString } from "./encodings.js";
|
|
2
3
|
import { buildColorSpaceMap, buildShadingMap } from "./shading.js";
|
|
3
4
|
import { IDENTITY, interpretContent, multiply } from "./content.js";
|
|
4
5
|
import { textMarkupOf } from "./annot-draw.js";
|
|
@@ -275,8 +276,29 @@ function spacesOf(file, resources) {
|
|
|
275
276
|
spaceCache.set(resources, made);
|
|
276
277
|
return made;
|
|
277
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* §14.9.4 — the replacement text of each property list the page's
|
|
281
|
+
* `/Properties` names: the content says `/Span /P1 BDC` and the `/ActualText`
|
|
282
|
+
* is in the resources, not in the stream.
|
|
283
|
+
*
|
|
284
|
+
* @param file The owning file.
|
|
285
|
+
* @param resources The resource dictionary in force.
|
|
286
|
+
* @returns Name → the text, for the lists that hold one.
|
|
287
|
+
*/
|
|
288
|
+
function actualTextsOf(file, resources) {
|
|
289
|
+
const out = /* @__PURE__ */ new Map();
|
|
290
|
+
const props = resources ? file.get(resources, "Properties") : void 0;
|
|
291
|
+
if (!(props instanceof Map)) return out;
|
|
292
|
+
for (const [name, value] of props) {
|
|
293
|
+
const list = file.resolve(value);
|
|
294
|
+
const text = list instanceof Map ? file.get(list, "ActualText") : void 0;
|
|
295
|
+
if (text instanceof PdfHexString) out.set(name, pdfTextString(text.bytes));
|
|
296
|
+
else if (typeof text === "string") out.set(name, pdfTextString(Uint8Array.from(text, (c) => c.charCodeAt(0) & 255)));
|
|
297
|
+
}
|
|
298
|
+
return out;
|
|
299
|
+
}
|
|
278
300
|
function collectRuns(file, resources, content, baseCtm, depth, visiting, out, shown) {
|
|
279
|
-
const result = interpretContent(content, buildFonts(file, resources), baseCtm, shadingsOf(file, resources), void 0, spacesOf(file, resources), hiddenProperties(file, resources));
|
|
301
|
+
const result = interpretContent(content, buildFonts(file, resources), baseCtm, shadingsOf(file, resources), void 0, spacesOf(file, resources), hiddenProperties(file, resources), actualTextsOf(file, resources));
|
|
280
302
|
out.push(...result.texts.map((r) => withPatternColour(file, resources, r, visiting)));
|
|
281
303
|
if (shown) addShown(shown, result.shown);
|
|
282
304
|
if (depth >= MAX_FORM_DEPTH) return;
|
|
@@ -411,4 +433,4 @@ function inRect(x, y, r) {
|
|
|
411
433
|
return x >= r[0] - 1 && x <= r[2] + 1 && y >= r[1] - 2 && y <= r[3] + 2;
|
|
412
434
|
}
|
|
413
435
|
//#endregion
|
|
414
|
-
export { buildFonts, extractPageText };
|
|
436
|
+
export { actualTextsOf, buildFonts, extractPageText };
|
|
@@ -4,7 +4,7 @@ import { buildAlphaMap, buildColorSpaceMap, buildShadingMap, gradientShading, sh
|
|
|
4
4
|
import { IDENTITY, interpretContent, multiply } from "./content.js";
|
|
5
5
|
import { appearanceContent, collectPageAppearances } from "./annots.js";
|
|
6
6
|
import { hiddenProperties, hiddenXObject } from "./optional-content.js";
|
|
7
|
-
import { buildFonts } from "./text.js";
|
|
7
|
+
import { actualTextsOf, buildFonts } from "./text.js";
|
|
8
8
|
import { patternTint, tintedHex } from "./pattern-tint.js";
|
|
9
9
|
//#region src/pdf-reader/vector.ts
|
|
10
10
|
function paintedVectors(file, page) {
|
|
@@ -53,7 +53,7 @@ function paintedVectors(file, page) {
|
|
|
53
53
|
const xobjects = resources ? file.get(resources, "XObject") : PDF_NULL;
|
|
54
54
|
const xobjDict = xobjects instanceof Map ? xobjects : void 0;
|
|
55
55
|
const maps = mapsOf(resources);
|
|
56
|
-
const result = interpretContent(content, buildFonts(file, resources), baseCtm, maps.shadings, maps.alphas, maps.spaces, hiddenProperties(file, resources));
|
|
56
|
+
const result = interpretContent(content, buildFonts(file, resources), baseCtm, maps.shadings, maps.alphas, maps.spaces, hiddenProperties(file, resources), actualTextsOf(file, resources));
|
|
57
57
|
for (const paint of result.shadings) {
|
|
58
58
|
if (out.length >= MAX_VECTORS) break;
|
|
59
59
|
const dict = resources ? file.get(resources, "Shading") : PDF_NULL;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FontRegistry } from "../core/font/font-registry.js";
|
|
2
|
+
import "../core/font/index.js";
|
|
2
3
|
import { poAttr, poChildren, poIs } from "../core/po-helpers.js";
|
|
3
4
|
//#region src/pptx/embedded-fonts.ts
|
|
4
5
|
var REL_FONT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font";
|
|
@@ -40,7 +40,7 @@ function parseSlideShapes(container, ctx = {}, transform = IDENTITY_TRANSFORM, s
|
|
|
40
40
|
const out = [];
|
|
41
41
|
for (const child of poChildren(container)) {
|
|
42
42
|
if (skipPlaceholders && isPlaceholder(child)) continue;
|
|
43
|
-
if (poIs(child, "p:sp")) {
|
|
43
|
+
if (poIs(child, "p:sp") || poIs(child, "p:cxnSp")) {
|
|
44
44
|
const shape = parseSp(child, ctx, transform);
|
|
45
45
|
if (shape) out.push({
|
|
46
46
|
kind: "shape",
|
|
@@ -89,6 +89,15 @@ function pictureAsShape(pic) {
|
|
|
89
89
|
const nv = poChildren(pic).find((c) => poIs(c, "p:nvPicPr"));
|
|
90
90
|
return { "p:sp": [...nv ? [{ "p:nvSpPr": poChildren(nv) }] : [], { "p:spPr": [{ "a:blipFill": poChildren(blipFill) }, ...poChildren(spPr)] }] };
|
|
91
91
|
}
|
|
92
|
+
/** Whether a shape properties node has an `a:ln` that states its own fill. */
|
|
93
|
+
function statesLineFill(spPr) {
|
|
94
|
+
const ln = poChildren(spPr).find((c) => poIs(c, "a:ln"));
|
|
95
|
+
return ln !== void 0 && poChildren(ln).some((c) => poIs(c, "a:noFill") || poIs(c, "a:solidFill") || poIs(c, "a:gradFill") || poIs(c, "a:pattFill"));
|
|
96
|
+
}
|
|
97
|
+
/** A line's stated properties, ready to spread over the ones it inherits. */
|
|
98
|
+
function definedProps(line) {
|
|
99
|
+
return Object.fromEntries(Object.entries(line).filter(([, v]) => v !== void 0));
|
|
100
|
+
}
|
|
92
101
|
/**
|
|
93
102
|
* Whether a shape is a placeholder — `p:ph` in its OWN non-visual properties.
|
|
94
103
|
* Read as "anywhere below", a group holding one would take the whole group
|
|
@@ -169,12 +178,18 @@ function parseSp(sp, ctx, transform) {
|
|
|
169
178
|
const styled = withStatedDirection(resolved, spPr);
|
|
170
179
|
const lineFrom = from((n) => poChildren(n).some((c) => poIs(c, "a:ln")));
|
|
171
180
|
let line = lineFrom ? parseLine(lineFrom, colors) : void 0;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
181
|
+
const fromStyle = style ? styleRefLine(style, colors, ctx.themeLineWidths) : void 0;
|
|
182
|
+
if (fromStyle) line = line ? {
|
|
183
|
+
...fromStyle,
|
|
184
|
+
...definedProps(line)
|
|
185
|
+
} : fromStyle;
|
|
186
|
+
else if (line && lineFrom && !statesLineFill(lineFrom)) {
|
|
187
|
+
const lentLine = protos.find(statesLineFill);
|
|
188
|
+
const lentProps = lentLine ? parseLine(lentLine, colors) : void 0;
|
|
189
|
+
line = lentProps ? {
|
|
190
|
+
...lentProps,
|
|
191
|
+
...definedProps(line)
|
|
192
|
+
} : void 0;
|
|
178
193
|
}
|
|
179
194
|
const shadowFrom = from((n) => poChildren(n).some((c) => poIs(c, "a:effectLst")));
|
|
180
195
|
const shadow = shadowFrom ? parseShadow(shadowFrom, colors) : void 0;
|
|
@@ -31,8 +31,9 @@ export declare function parsePh(sp: PoNode): PlaceholderRef | undefined;
|
|
|
31
31
|
/**
|
|
32
32
|
* An xfrm node (`a:off` + `a:ext` children) → the EMU box. Works for both
|
|
33
33
|
* `a:xfrm` (in `p:spPr`) and `p:xfrm` (on a `p:graphicFrame`), whose children are
|
|
34
|
-
* identical. Returns `undefined` for a missing or
|
|
35
|
-
*
|
|
34
|
+
* identical. Returns `undefined` for a missing or negative extent, or one that is
|
|
35
|
+
* empty both ways. A single zero is a real box: a horizontal line has `cy="0"` and
|
|
36
|
+
* a vertical one `cx="0"`.
|
|
36
37
|
*/
|
|
37
38
|
export declare function boxFromXfrm(xfrm: PoNode | undefined): ShapeBoxEmu | undefined;
|
|
38
39
|
/**
|
|
@@ -34,8 +34,9 @@ function parsePh(sp) {
|
|
|
34
34
|
/**
|
|
35
35
|
* An xfrm node (`a:off` + `a:ext` children) → the EMU box. Works for both
|
|
36
36
|
* `a:xfrm` (in `p:spPr`) and `p:xfrm` (on a `p:graphicFrame`), whose children are
|
|
37
|
-
* identical. Returns `undefined` for a missing or
|
|
38
|
-
*
|
|
37
|
+
* identical. Returns `undefined` for a missing or negative extent, or one that is
|
|
38
|
+
* empty both ways. A single zero is a real box: a horizontal line has `cy="0"` and
|
|
39
|
+
* a vertical one `cx="0"`.
|
|
39
40
|
*/
|
|
40
41
|
function boxFromXfrm(xfrm) {
|
|
41
42
|
if (!xfrm) return void 0;
|
|
@@ -43,7 +44,8 @@ function boxFromXfrm(xfrm) {
|
|
|
43
44
|
const ext = poChildren(xfrm).find((c) => poIs(c, "a:ext"));
|
|
44
45
|
const cx = ext ? poIntAttr(ext, "cx") : void 0;
|
|
45
46
|
const cy = ext ? poIntAttr(ext, "cy") : void 0;
|
|
46
|
-
if (cx === void 0 || cy === void 0 || cx
|
|
47
|
+
if (cx === void 0 || cy === void 0 || cx < 0 || cy < 0) return void 0;
|
|
48
|
+
if (cx === 0 && cy === 0) return void 0;
|
|
47
49
|
return {
|
|
48
50
|
x: (off ? poIntAttr(off, "x") : void 0) ?? 0,
|
|
49
51
|
y: (off ? poIntAttr(off, "y") : void 0) ?? 0,
|
|
@@ -83,7 +85,10 @@ function rPrToRunProps(rPr, colors, themeFonts) {
|
|
|
83
85
|
...u !== void 0 ? { underline: u === "none" ? "none" : "single" } : {},
|
|
84
86
|
...sz !== void 0 ? { fontSizePt: pt(sz / 100) } : {},
|
|
85
87
|
...colorHex ? { colorHex } : {},
|
|
86
|
-
...typeface ? { fontFamily: {
|
|
88
|
+
...typeface ? { fontFamily: {
|
|
89
|
+
ascii: typeface,
|
|
90
|
+
hAnsi: typeface
|
|
91
|
+
} } : {},
|
|
87
92
|
...capsOf(poAttr(rPr, "cap"))
|
|
88
93
|
};
|
|
89
94
|
}
|
package/dist/esm/svg/svg-text.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { svgPathData } from "../core/vector.js";
|
|
2
2
|
import { reverseByCodePoint } from "../core/bidi/index.js";
|
|
3
3
|
import { FAUX_ITALIC_SHEAR, computeJustifyExtra, lineVisualOrder } from "../layout/line-paint.js";
|
|
4
|
-
import { warpGlyphMatrix } from "../core/drawingml/text-warp.js";
|
|
4
|
+
import { warpGlyphMatrix, warpGlyphRun } from "../core/drawingml/text-warp.js";
|
|
5
5
|
import { sanitizeHref } from "../core/links.js";
|
|
6
6
|
import { cffOutlineSource, openTypeCff } from "../pdf-reader/cff-outline.js";
|
|
7
7
|
import { outlineSource } from "../pdf-reader/glyf-outline.js";
|
|
@@ -128,10 +128,16 @@ function emitTextToken(out, tok, x, baseline, ctx) {
|
|
|
128
128
|
const scale = (tok.synthetic?.widthScale ?? 1) * (tok.resolvedRun.widthScale ?? 1);
|
|
129
129
|
const slant = tok.synthetic?.italic === true ? FAUX_ITALIC_SHEAR : 0;
|
|
130
130
|
const rise = tok.risePt ?? 0;
|
|
131
|
-
const
|
|
131
|
+
const reversed = tok.bidiLevel % 2 === 1;
|
|
132
|
+
const text = reversed ? reverseByCodePoint(tok.text) : tok.text;
|
|
132
133
|
const run = tok.font.measure.glyphRun(text);
|
|
133
134
|
const upem = tok.font.parsed.unitsPerEm;
|
|
134
135
|
const spacingEm = (tok.resolvedRun.letterSpacingPt ?? 0) / (size * scale);
|
|
136
|
+
const outline = tok.resolvedRun.textOutline;
|
|
137
|
+
const strokeWidth = outline !== void 0 ? outline.widthPt : tok.synthetic?.bold === true ? size * .03 : 0;
|
|
138
|
+
const colours = reversed ? tok.charColorsHex?.slice().reverse() : tok.charColorsHex;
|
|
139
|
+
const sources = colours ? tok.font.measure.glyphSources(text) : void 0;
|
|
140
|
+
const paint = (hex) => hex === void 0 || hex === tok.resolvedRun.colorHex ? "" : ` fill="#${hex}"${strokeWidth > 0 && outline === void 0 ? ` stroke="#${hex}"` : ""}`;
|
|
135
141
|
const uses = [];
|
|
136
142
|
let pen = 0;
|
|
137
143
|
for (let g = 0; g < run.gids.length; g++) {
|
|
@@ -140,12 +146,16 @@ function emitTextToken(out, tok, x, baseline, ctx) {
|
|
|
140
146
|
emitAsText(out, tok, x, baseline);
|
|
141
147
|
return;
|
|
142
148
|
}
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
const gx = pen + (run.xOffsets?.[g] ?? 0) / upem;
|
|
150
|
+
const gy = (run.yOffsets?.[g] ?? 0) / upem;
|
|
151
|
+
if (id !== null) {
|
|
152
|
+
const fill = paint(sources ? colours?.[sources[g]] : void 0);
|
|
153
|
+
uses.push(`<use href="#${id}"${gx !== 0 ? ` x="${fmtEm(gx)}"` : ""}${gy !== 0 ? ` y="${fmtEm(gy)}"` : ""}${fill}/>`);
|
|
154
|
+
}
|
|
155
|
+
const spaced = run.clusterEnds ? run.clusterEnds[g] === true : true;
|
|
156
|
+
pen += (run.advances[g] ?? 0) / upem + (spaced ? spacingEm : 0);
|
|
145
157
|
}
|
|
146
158
|
if (uses.length === 0) return;
|
|
147
|
-
const outline = tok.resolvedRun.textOutline;
|
|
148
|
-
const strokeWidth = outline !== void 0 ? outline.widthPt : tok.synthetic?.bold === true ? size * .03 : 0;
|
|
149
159
|
const stroke = strokeWidth > 0 ? ` stroke="#${outline?.colorHex ?? tok.resolvedRun.colorHex}" stroke-width="${fmtEm(strokeWidth / size)}"` : "";
|
|
150
160
|
const group = `<g transform="matrix(${fmt(size * scale)} 0 ${fmt(slant * size)} ${fmt(-size)} ${fmt(x)} ${fmt(baseline - rise)})" fill="#${tok.resolvedRun.colorHex}"${stroke}>${uses.join("")}</g>`;
|
|
151
161
|
const href = tok.href !== void 0 ? sanitizeHref(tok.href) : void 0;
|
|
@@ -282,6 +292,19 @@ function emitWarped(out, item, ctx) {
|
|
|
282
292
|
continue;
|
|
283
293
|
}
|
|
284
294
|
const size = tok.fontSizePt;
|
|
295
|
+
const group = (m, uses, hex = tok.resolvedRun.colorHex) => `<g transform="matrix(${fmt(m[0] * size)} ${fmt(m[1] * size)} ${fmt(m[2] * size)} ${fmt(m[3] * size)} ${fmt(m[4])} ${fmt(m[5])})" fill="#${hex}">${uses}</g>`;
|
|
296
|
+
if (tok.font.measure.clustered(tok.text)) {
|
|
297
|
+
const glyphs = warpGlyphRun(warp, tok.font.measure.glyphRun(tok.text), cursor, tok.widthPt, size / tok.font.parsed.unitsPerEm, item.baselineY);
|
|
298
|
+
const colours = tok.charColorsHex;
|
|
299
|
+
const sources = colours ? tok.font.measure.glyphSources(tok.text) : void 0;
|
|
300
|
+
for (const g of glyphs) {
|
|
301
|
+
const id = ctx.glyphs.use(tok.font, g.gid);
|
|
302
|
+
const hex = sources ? colours?.[sources[g.index]] : void 0;
|
|
303
|
+
if (id) out.push(group(g.matrix, `<use href="#${id}"/>`, hex));
|
|
304
|
+
}
|
|
305
|
+
cursor += tok.widthPt;
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
285
308
|
const chars = [...tok.text];
|
|
286
309
|
const raw = chars.map((c) => tok.font.measure.textWidthPt(c, size));
|
|
287
310
|
const total = raw.reduce((a, b) => a + b, 0);
|
|
@@ -301,7 +324,7 @@ function emitWarped(out, item, ctx) {
|
|
|
301
324
|
pen += (run.advances[g] ?? 0) / upem;
|
|
302
325
|
}
|
|
303
326
|
if (uses.length === 0) continue;
|
|
304
|
-
out.push(
|
|
327
|
+
out.push(group(m, uses.join("")));
|
|
305
328
|
}
|
|
306
329
|
}
|
|
307
330
|
}
|
|
@@ -27,6 +27,11 @@ var TABLE_BORDERS = {
|
|
|
27
27
|
insideH: TABLE_BORDER,
|
|
28
28
|
insideV: TABLE_BORDER
|
|
29
29
|
};
|
|
30
|
+
var LVL_FOLLOW = [
|
|
31
|
+
" ",
|
|
32
|
+
" ",
|
|
33
|
+
""
|
|
34
|
+
];
|
|
30
35
|
function createListMarkers(tables) {
|
|
31
36
|
const counters = /* @__PURE__ */ new Map();
|
|
32
37
|
const resolve = (ilfo, ilvl) => {
|
|
@@ -43,7 +48,8 @@ function createListMarkers(tables) {
|
|
|
43
48
|
const r = resolve(ilfo, ilvl);
|
|
44
49
|
if (!r) return void 0;
|
|
45
50
|
const { lsid, lvl } = r;
|
|
46
|
-
|
|
51
|
+
const follow = LVL_FOLLOW[lvl.follow] ?? " ";
|
|
52
|
+
if (lvl.nfc === 23 || lvl.nfc === 255 || !lvl.xst.some((cu) => cu <= 8)) return lvl.xst.map((cu) => String.fromCharCode(cu)).join("") + follow;
|
|
47
53
|
const col = counters.get(lsid) ?? [];
|
|
48
54
|
col[ilvl] = (col[ilvl] ?? lvl.iStartAt - 1) + 1;
|
|
49
55
|
for (let l = ilvl + 1; l < col.length; l++) col[l] = void 0;
|
|
@@ -53,7 +59,7 @@ function createListMarkers(tables) {
|
|
|
53
59
|
const other = resolve(ilfo, cu);
|
|
54
60
|
out += formatListNumber(other?.lvl.nfc ?? 0, col[cu] ?? other?.lvl.iStartAt ?? 1);
|
|
55
61
|
} else out += String.fromCharCode(cu);
|
|
56
|
-
return out;
|
|
62
|
+
return out + follow;
|
|
57
63
|
} };
|
|
58
64
|
}
|
|
59
65
|
function formatListNumber(nfc, n) {
|
|
@@ -128,54 +134,79 @@ var DOC_ENCRYPTED_LOSS = {
|
|
|
128
134
|
function readDoc(bytes) {
|
|
129
135
|
const content = extractDocContent(bytes);
|
|
130
136
|
const resources = new ResourceStore();
|
|
131
|
-
const body = buildBody(content, resources);
|
|
137
|
+
const { body, sectionEnds } = buildBody(content, resources);
|
|
132
138
|
const headersFooters = /* @__PURE__ */ new Map();
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
const bandIds = /* @__PURE__ */ new Map();
|
|
140
|
+
const bands = (index) => {
|
|
141
|
+
const headers = [];
|
|
142
|
+
const footers = [];
|
|
143
|
+
const hf = content.headerFooters?.[index];
|
|
144
|
+
const add = (story, kind, type) => {
|
|
145
|
+
if (!story) return;
|
|
146
|
+
let id = bandIds.get(story);
|
|
147
|
+
if (id === void 0) {
|
|
148
|
+
id = `${kind}-${type}-${index}`;
|
|
149
|
+
bandIds.set(story, id);
|
|
150
|
+
headersFooters.set(id, resolveBodyStyles(story.flatMap((p) => mapParagraph(p, resources)), EMPTY_STYLE_SHEET));
|
|
151
|
+
}
|
|
152
|
+
(kind === "header" ? headers : footers).push({
|
|
153
|
+
type,
|
|
154
|
+
relationshipId: id
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
add(hf?.defaultHeader, "header", "default");
|
|
158
|
+
add(hf?.firstHeader, "header", "first");
|
|
159
|
+
add(hf?.evenHeader, "header", "even");
|
|
160
|
+
add(hf?.defaultFooter, "footer", "default");
|
|
161
|
+
add(hf?.firstFooter, "footer", "first");
|
|
162
|
+
add(hf?.evenFooter, "footer", "even");
|
|
163
|
+
return {
|
|
164
|
+
headers,
|
|
165
|
+
footers
|
|
166
|
+
};
|
|
144
167
|
};
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
const sectionProperties = (sec, index) => {
|
|
169
|
+
const ps = sec?.pageSize;
|
|
170
|
+
const sectionStart = sec?.bkc !== void 0 ? sectionStartOf(sec.bkc) : void 0;
|
|
171
|
+
const pageNumberFormat = sec?.pageNumberNfc !== void 0 ? pageNumberFormatOf(sec.pageNumberNfc) : void 0;
|
|
172
|
+
return {
|
|
173
|
+
pageSize: ps ? {
|
|
174
|
+
width: pt(ps.widthPt),
|
|
175
|
+
height: pt(ps.heightPt),
|
|
176
|
+
orientation: ps.widthPt > ps.heightPt ? "landscape" : "portrait"
|
|
177
|
+
} : {
|
|
178
|
+
width: pt(612),
|
|
179
|
+
height: pt(792)
|
|
180
|
+
},
|
|
181
|
+
margins: toMargins(sec?.margins),
|
|
182
|
+
...bands(index),
|
|
183
|
+
...sec?.titlePage ? { titlePg: true } : {},
|
|
184
|
+
...content.facingPages ? { evenAndOddHeaders: true } : {},
|
|
185
|
+
...sectionStart ? { sectionStart } : {},
|
|
186
|
+
...sec?.pageNumberStart !== void 0 ? { pageNumberStart: sec.pageNumberStart } : {},
|
|
187
|
+
...pageNumberFormat ? { pageNumberFormat } : {}
|
|
188
|
+
};
|
|
162
189
|
};
|
|
190
|
+
const docSections = content.sections ?? [];
|
|
191
|
+
const sections = [];
|
|
192
|
+
for (const end of sectionEnds) {
|
|
193
|
+
const last = sections[sections.length - 1]?.endIndex ?? 0;
|
|
194
|
+
if (end.endIndex <= last || end.endIndex >= body.length) continue;
|
|
195
|
+
sections.push({
|
|
196
|
+
properties: sectionProperties(docSections[end.section], end.section),
|
|
197
|
+
endIndex: end.endIndex
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
if (sections.length > 0) sections.push({
|
|
201
|
+
properties: sectionProperties(docSections[docSections.length - 1], docSections.length - 1),
|
|
202
|
+
endIndex: body.length
|
|
203
|
+
});
|
|
163
204
|
return {
|
|
164
205
|
doc: {
|
|
165
206
|
kind: "flow",
|
|
166
207
|
body: resolveBodyStyles(body, EMPTY_STYLE_SHEET),
|
|
167
|
-
sections
|
|
168
|
-
section:
|
|
169
|
-
pageSize,
|
|
170
|
-
margins: {
|
|
171
|
-
top: pt(72),
|
|
172
|
-
right: pt(72),
|
|
173
|
-
bottom: pt(72),
|
|
174
|
-
left: pt(72)
|
|
175
|
-
},
|
|
176
|
-
headers,
|
|
177
|
-
footers
|
|
178
|
-
},
|
|
208
|
+
sections,
|
|
209
|
+
section: sectionProperties(docSections[0], 0),
|
|
179
210
|
styles: EMPTY_STYLE_SHEET,
|
|
180
211
|
resources,
|
|
181
212
|
...headersFooters.size > 0 ? { headersFooters } : {},
|
|
@@ -186,12 +217,16 @@ function readDoc(bytes) {
|
|
|
186
217
|
}
|
|
187
218
|
function buildBody(content, resources) {
|
|
188
219
|
const markers = createListMarkers(content.listTables);
|
|
189
|
-
const
|
|
220
|
+
const sectionEnds = [];
|
|
221
|
+
const body = groupTables(content.paragraphs, resources, markers, sectionEnds);
|
|
190
222
|
while (body.length > 1 && isEmptyParagraph(body[body.length - 1])) body.pop();
|
|
191
223
|
if (body.length === 0) body.push(emptyParagraph());
|
|
192
|
-
return
|
|
224
|
+
return {
|
|
225
|
+
body,
|
|
226
|
+
sectionEnds
|
|
227
|
+
};
|
|
193
228
|
}
|
|
194
|
-
function groupTables(paras, resources, markers) {
|
|
229
|
+
function groupTables(paras, resources, markers, sectionEnds) {
|
|
195
230
|
const out = [];
|
|
196
231
|
let i = 0;
|
|
197
232
|
while (i < paras.length) if (paras[i].props.inTable) {
|
|
@@ -201,7 +236,14 @@ function groupTables(paras, resources, markers) {
|
|
|
201
236
|
kind: "table",
|
|
202
237
|
table: buildTable(group, resources, markers)
|
|
203
238
|
});
|
|
204
|
-
} else
|
|
239
|
+
} else {
|
|
240
|
+
const p = paras[i++];
|
|
241
|
+
out.push(...mapParagraph(p, resources, markers));
|
|
242
|
+
if (p.sectionEnd !== void 0) sectionEnds.push({
|
|
243
|
+
section: p.sectionEnd,
|
|
244
|
+
endIndex: out.length
|
|
245
|
+
});
|
|
246
|
+
}
|
|
205
247
|
return out;
|
|
206
248
|
}
|
|
207
249
|
function buildTable(group, resources, markers) {
|
|
@@ -331,16 +373,24 @@ function mapParagraph(p, resources, markers) {
|
|
|
331
373
|
const textRuns = p.runs.filter((r) => r.picture === void 0);
|
|
332
374
|
const ilvl = p.props.listIlvl ?? 0;
|
|
333
375
|
const isList = (p.props.listIlfo ?? 0) > 0;
|
|
334
|
-
if (textRuns.some((r) => r.text.length > 0) || isList) {
|
|
376
|
+
if (textRuns.some((r) => r.text.length > 0 || r.pageBreak || r.field) || isList) {
|
|
335
377
|
const runs = textRuns.map((r) => ({
|
|
336
378
|
text: r.text,
|
|
337
|
-
properties: toRunProperties(r.props)
|
|
379
|
+
properties: toRunProperties(r.props),
|
|
380
|
+
...r.pageBreak ? { pageBreak: true } : {},
|
|
381
|
+
...r.columnBreak ? { columnBreak: true } : {},
|
|
382
|
+
...r.field ? { field: r.field } : {}
|
|
338
383
|
}));
|
|
384
|
+
const last = textRuns[textRuns.length - 1];
|
|
385
|
+
if (last?.pageBreak || last?.columnBreak) runs.push({
|
|
386
|
+
text: ZERO_WIDTH_SPACE,
|
|
387
|
+
properties: p.mark ? toRunProperties(p.mark) : {}
|
|
388
|
+
});
|
|
339
389
|
let properties = toParaProperties(p.props);
|
|
340
390
|
if (isList) {
|
|
341
|
-
const marker = markers?.marker(p.props.listIlfo, ilvl) ?? LIST_BULLETS[ilvl % LIST_BULLETS.length]
|
|
391
|
+
const marker = markers?.marker(p.props.listIlfo, ilvl) ?? `${LIST_BULLETS[ilvl % LIST_BULLETS.length]} `;
|
|
342
392
|
runs.unshift({
|
|
343
|
-
text:
|
|
393
|
+
text: marker,
|
|
344
394
|
properties: {}
|
|
345
395
|
});
|
|
346
396
|
properties = {
|
|
@@ -360,7 +410,7 @@ function mapParagraph(p, resources, markers) {
|
|
|
360
410
|
});
|
|
361
411
|
}
|
|
362
412
|
for (const r of p.runs) if (r.picture) out.push(imageBlock(r.picture, resources, toParaProperties(p.props)));
|
|
363
|
-
if (out.length === 0) out.push(emptyParagraph());
|
|
413
|
+
if (out.length === 0) out.push(emptyParagraph(toParaProperties(p.props), p.mark));
|
|
364
414
|
return out;
|
|
365
415
|
}
|
|
366
416
|
function imageBlock(pic, resources, paragraphProperties) {
|
|
@@ -374,14 +424,14 @@ function imageBlock(pic, resources, paragraphProperties) {
|
|
|
374
424
|
}
|
|
375
425
|
};
|
|
376
426
|
}
|
|
377
|
-
function emptyParagraph() {
|
|
427
|
+
function emptyParagraph(properties = {}, mark = void 0) {
|
|
378
428
|
return {
|
|
379
429
|
kind: "paragraph",
|
|
380
430
|
paragraph: {
|
|
381
|
-
properties
|
|
431
|
+
properties,
|
|
382
432
|
runs: [{
|
|
383
433
|
text: ZERO_WIDTH_SPACE,
|
|
384
|
-
properties: {}
|
|
434
|
+
properties: mark ? toRunProperties(mark) : {}
|
|
385
435
|
}]
|
|
386
436
|
}
|
|
387
437
|
};
|
|
@@ -392,13 +442,24 @@ function isEmptyParagraph(el) {
|
|
|
392
442
|
function toRunProperties(p) {
|
|
393
443
|
const underline = p.underlineKul ? underlineStyle(p.underlineKul) : void 0;
|
|
394
444
|
const size = p.sizeHalfPts && p.sizeHalfPts > 0 ? pt(p.sizeHalfPts / 2) : void 0;
|
|
445
|
+
const fontFamily = toFontFamily(p);
|
|
395
446
|
return {
|
|
396
447
|
...p.bold ? { bold: true } : {},
|
|
397
448
|
...p.italic ? { italic: true } : {},
|
|
398
449
|
...underline ? { underline } : {},
|
|
399
|
-
...size ? { fontSizePt: size } : {}
|
|
450
|
+
...size ? { fontSizePt: size } : {},
|
|
451
|
+
...fontFamily ? { fontFamily } : {}
|
|
400
452
|
};
|
|
401
453
|
}
|
|
454
|
+
function toFontFamily(p) {
|
|
455
|
+
const fonts = {
|
|
456
|
+
...p.fontAscii ? { ascii: p.fontAscii } : {},
|
|
457
|
+
...p.fontOther ? { hAnsi: p.fontOther } : {},
|
|
458
|
+
...p.fontEastAsia ? { eastAsia: p.fontEastAsia } : {},
|
|
459
|
+
...p.fontBi ? { cs: p.fontBi } : {}
|
|
460
|
+
};
|
|
461
|
+
return Object.keys(fonts).length > 0 ? fonts : void 0;
|
|
462
|
+
}
|
|
402
463
|
function toParaProperties(p) {
|
|
403
464
|
const alignment = p.jc !== void 0 ? alignmentFromJc(p.jc) : void 0;
|
|
404
465
|
return {
|
|
@@ -410,7 +471,8 @@ function toParaProperties(p) {
|
|
|
410
471
|
...p.spaceAfterTwips !== void 0 ? { spacingAfter: pt(p.spaceAfterTwips / 20) } : {},
|
|
411
472
|
...p.widowControl !== void 0 ? { widowControl: p.widowControl } : {},
|
|
412
473
|
...p.keepNext !== void 0 ? { keepNext: p.keepNext } : {},
|
|
413
|
-
...p.keepLines !== void 0 ? { keepLines: p.keepLines } : {}
|
|
474
|
+
...p.keepLines !== void 0 ? { keepLines: p.keepLines } : {},
|
|
475
|
+
...p.pageBreakBefore !== void 0 ? { pageBreakBefore: p.pageBreakBefore } : {}
|
|
414
476
|
};
|
|
415
477
|
}
|
|
416
478
|
function underlineStyle(kul) {
|
|
@@ -422,6 +484,35 @@ function underlineStyle(kul) {
|
|
|
422
484
|
default: return "single";
|
|
423
485
|
}
|
|
424
486
|
}
|
|
487
|
+
function toMargins(m) {
|
|
488
|
+
const side = (twips) => twipsToPt(twips ?? 1440);
|
|
489
|
+
return {
|
|
490
|
+
top: side(m?.topTwips),
|
|
491
|
+
right: side(m?.rightTwips),
|
|
492
|
+
bottom: side(m?.bottomTwips),
|
|
493
|
+
left: side(m?.leftTwips),
|
|
494
|
+
...m?.headerTwips !== void 0 ? { header: twipsToPt(m.headerTwips) } : {},
|
|
495
|
+
...m?.footerTwips !== void 0 ? { footer: twipsToPt(m.footerTwips) } : {},
|
|
496
|
+
...m?.gutterTwips ? { gutter: twipsToPt(m.gutterTwips) } : {}
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
function sectionStartOf(bkc) {
|
|
500
|
+
switch (bkc) {
|
|
501
|
+
case 0: return "continuous";
|
|
502
|
+
case 3: return "evenPage";
|
|
503
|
+
case 4: return "oddPage";
|
|
504
|
+
default: return "nextPage";
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
function pageNumberFormatOf(nfc) {
|
|
508
|
+
switch (nfc) {
|
|
509
|
+
case 1: return "upperRoman";
|
|
510
|
+
case 2: return "lowerRoman";
|
|
511
|
+
case 3: return "upperLetter";
|
|
512
|
+
case 4: return "lowerLetter";
|
|
513
|
+
default: return;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
425
516
|
function alignmentFromJc(jc) {
|
|
426
517
|
switch (jc) {
|
|
427
518
|
case 1: return "center";
|