reamkit 1.29.0 → 1.31.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 +60 -24
- package/dist/esm/core/converter/project.js +3 -1
- package/dist/esm/core/crypto/offcrypto.js +1 -1
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +65 -0
- package/dist/esm/core/drawingml/shape-render.js +13 -1
- package/dist/esm/core/font/index.d.ts +2 -0
- package/dist/esm/core/font/ttf-build.d.ts +113 -0
- package/dist/esm/core/font/ttf-build.js +1224 -0
- package/dist/esm/core/font/ttf-subset.d.ts +19 -0
- package/dist/esm/core/font/ttf-subset.js +14 -1
- package/dist/esm/core/fonts/index.d.ts +1 -1
- package/dist/esm/core/fonts/provider.d.ts +17 -0
- package/dist/esm/core/fonts/provider.js +27 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +8 -0
- package/dist/esm/core/fonts/remote-fonts.js +108 -18
- package/dist/esm/core/ir/flow.d.ts +88 -1
- package/dist/esm/core/numbering/index.d.ts +1 -1
- package/dist/esm/core/numbering/state.d.ts +11 -1
- package/dist/esm/core/numbering/state.js +10 -1
- package/dist/esm/core/style-cascade/resolver.js +35 -4
- package/dist/esm/core/style-cascade/types.d.ts +19 -1
- package/dist/esm/core/style-cascade/types.js +3 -0
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/layout/page-doc.d.ts +10 -3
- package/dist/esm/layout/styled-layout.d.ts +48 -7
- package/dist/esm/layout/styled-layout.js +881 -119
- package/dist/esm/layout/turned-section.d.ts +38 -0
- package/dist/esm/layout/turned-section.js +193 -0
- package/dist/esm/pdf/styled-page-emitter.js +78 -2
- package/dist/esm/pdf-reader/annot-draw.js +93 -1
- package/dist/esm/pdf-reader/annots.d.ts +18 -0
- package/dist/esm/pdf-reader/annots.js +86 -9
- package/dist/esm/pdf-reader/cff-outline.d.ts +27 -0
- package/dist/esm/pdf-reader/cff-outline.js +169 -21
- package/dist/esm/pdf-reader/cmap.js +5 -2
- package/dist/esm/pdf-reader/content.d.ts +70 -4
- package/dist/esm/pdf-reader/content.js +172 -12
- package/dist/esm/pdf-reader/display.d.ts +36 -0
- package/dist/esm/pdf-reader/display.js +82 -1
- package/dist/esm/pdf-reader/document.js +5 -1
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +25 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +78 -9
- package/dist/esm/pdf-reader/encodings.d.ts +8 -0
- package/dist/esm/pdf-reader/encodings.js +25 -3
- package/dist/esm/pdf-reader/face-outlines.d.ts +78 -0
- package/dist/esm/pdf-reader/face-outlines.js +362 -0
- package/dist/esm/pdf-reader/figures.d.ts +52 -0
- package/dist/esm/pdf-reader/figures.js +433 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +224 -7
- package/dist/esm/pdf-reader/flow-build.js +545 -39
- package/dist/esm/pdf-reader/font.d.ts +27 -1
- package/dist/esm/pdf-reader/font.js +632 -63
- package/dist/esm/pdf-reader/glyf-outline.d.ts +33 -0
- package/dist/esm/pdf-reader/glyf-outline.js +148 -3
- package/dist/esm/pdf-reader/glyph-names.js +154 -1
- package/dist/esm/pdf-reader/glyph-shapes.d.ts +18 -0
- package/dist/esm/pdf-reader/glyph-shapes.js +57 -0
- package/dist/esm/pdf-reader/image-decode.js +70 -4
- package/dist/esm/pdf-reader/images.d.ts +5 -0
- package/dist/esm/pdf-reader/images.js +4 -2
- package/dist/esm/pdf-reader/jbig2.d.ts +40 -1
- package/dist/esm/pdf-reader/jbig2.js +78 -16
- package/dist/esm/pdf-reader/jpeg.d.ts +6 -3
- package/dist/esm/pdf-reader/jpeg.js +21 -1
- package/dist/esm/pdf-reader/layout.d.ts +119 -2
- package/dist/esm/pdf-reader/layout.js +2219 -184
- package/dist/esm/pdf-reader/lexer.d.ts +10 -0
- package/dist/esm/pdf-reader/lexer.js +17 -0
- package/dist/esm/pdf-reader/page-numbers.d.ts +53 -0
- package/dist/esm/pdf-reader/page-numbers.js +167 -0
- package/dist/esm/pdf-reader/pattern-tint.d.ts +11 -1
- package/dist/esm/pdf-reader/pattern-tint.js +21 -3
- package/dist/esm/pdf-reader/regions.d.ts +25 -0
- package/dist/esm/pdf-reader/regions.js +167 -0
- package/dist/esm/pdf-reader/shading.d.ts +58 -2
- package/dist/esm/pdf-reader/shading.js +181 -11
- package/dist/esm/pdf-reader/struct-tree.js +112 -8
- package/dist/esm/pdf-reader/tagged.js +207 -28
- package/dist/esm/pdf-reader/text-rules.js +1 -1
- package/dist/esm/pdf-reader/text.d.ts +6 -3
- package/dist/esm/pdf-reader/text.js +106 -22
- package/dist/esm/pdf-reader/type1-outline.d.ts +11 -0
- package/dist/esm/pdf-reader/type1-outline.js +63 -8
- package/dist/esm/pdf-reader/vector.d.ts +8 -2
- package/dist/esm/pdf-reader/vector.js +105 -6
- package/dist/esm/word/doc/doc-reader.js +6 -2
- package/dist/esm/word/doc/doc-text.d.ts +6 -0
- package/dist/esm/word/doc/doc-text.js +19 -1
- package/dist/esm/word/document-parser.d.ts +2 -2
- package/dist/esm/word/document-parser.js +11 -1
- package/dist/esm/word/docx-reader.js +5 -3
- package/dist/esm/word/docx-writer.js +341 -54
- package/dist/esm/word/drawing-parser.d.ts +5 -3
- package/dist/esm/word/drawing-parser.js +56 -10
- package/dist/esm/word/font-embed.d.ts +30 -0
- package/dist/esm/word/font-embed.js +173 -0
- package/dist/esm/word/font-table.d.ts +10 -0
- package/dist/esm/word/font-table.js +13 -1
- package/dist/esm/word/index.js +1 -1
- package/dist/esm/word/numbering-parser.d.ts +3 -1
- package/dist/esm/word/numbering-parser.js +2 -1
- package/dist/esm/word/paragraph-properties.d.ts +7 -6
- package/dist/esm/word/paragraph-properties.js +16 -2
- package/dist/esm/word/run-properties.js +26 -0
- package/package.json +12 -5
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { postScriptFsType } from "./cff-outline.js";
|
|
1
2
|
//#region src/pdf-reader/type1-outline.ts
|
|
2
3
|
/**
|
|
3
4
|
* Read an embedded Type 1 program.
|
|
@@ -31,7 +32,13 @@ function type1Font(program) {
|
|
|
31
32
|
return out;
|
|
32
33
|
},
|
|
33
34
|
has: (name) => parsed.charstrings.has(name),
|
|
34
|
-
|
|
35
|
+
advance: (name) => {
|
|
36
|
+
const charstring = parsed.charstrings.get(name);
|
|
37
|
+
const width = charstring ? statedWidth(charstring) : void 0;
|
|
38
|
+
return width === void 0 ? void 0 : width * parsed.scale * 1e3;
|
|
39
|
+
},
|
|
40
|
+
...parsed.encoding ? { encoding: parsed.encoding } : {},
|
|
41
|
+
...parsed.fsType !== void 0 ? { fsType: parsed.fsType } : {}
|
|
35
42
|
};
|
|
36
43
|
}
|
|
37
44
|
function parseType1(program) {
|
|
@@ -47,11 +54,13 @@ function parseType1(program) {
|
|
|
47
54
|
const charstrings = readCharstrings(plain, text, lenIV);
|
|
48
55
|
if (charstrings.size === 0) return void 0;
|
|
49
56
|
const encoding = readEncoding(clear);
|
|
57
|
+
const fsType = postScriptFsType(clear);
|
|
50
58
|
return {
|
|
51
59
|
charstrings,
|
|
52
60
|
subrs: readSubrs(plain, text, lenIV),
|
|
53
61
|
...encoding ? { encoding } : {},
|
|
54
|
-
scale: readMatrixScale(clear) ?? .001
|
|
62
|
+
scale: readMatrixScale(clear) ?? .001,
|
|
63
|
+
...fsType !== void 0 ? { fsType } : {}
|
|
55
64
|
};
|
|
56
65
|
}
|
|
57
66
|
/** The `eexec` key (§7), and the one every charstring is encrypted with (§6.2). */
|
|
@@ -211,6 +220,7 @@ function runGlyph(font, program, depth) {
|
|
|
211
220
|
let inFlex = false;
|
|
212
221
|
let x = 0;
|
|
213
222
|
let y = 0;
|
|
223
|
+
let sideBearing = 0;
|
|
214
224
|
let open = false;
|
|
215
225
|
let steps = 0;
|
|
216
226
|
const moveTo = () => {
|
|
@@ -255,6 +265,7 @@ function runGlyph(font, program, depth) {
|
|
|
255
265
|
case 13:
|
|
256
266
|
x = stack[0] ?? 0;
|
|
257
267
|
y = 0;
|
|
268
|
+
sideBearing = x;
|
|
258
269
|
stack.length = 0;
|
|
259
270
|
break;
|
|
260
271
|
case 9:
|
|
@@ -404,18 +415,25 @@ function runGlyph(font, program, depth) {
|
|
|
404
415
|
break;
|
|
405
416
|
}
|
|
406
417
|
if (op2 === 6) {
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
418
|
+
const [asb = 0, adx = 0, ady = 0, bchar = 0, achar = 0] = stack;
|
|
419
|
+
if (open) out.push({ op: "close" });
|
|
420
|
+
open = false;
|
|
421
|
+
const part = (charCode, dx, dy) => {
|
|
422
|
+
const name = STANDARD_ENCODING[charCode];
|
|
423
|
+
const charstring = name !== void 0 ? font.charstrings.get(name) : void 0;
|
|
424
|
+
if (!charstring || depth >= 2) return;
|
|
410
425
|
const drawn = runGlyph(font, charstring, depth + 1);
|
|
411
|
-
if (drawn) out.push(...drawn.map((seg) => unscale(seg, font.scale)));
|
|
412
|
-
}
|
|
426
|
+
if (drawn) out.push(...drawn.map((seg) => shift(unscale(seg, font.scale), dx, dy)));
|
|
427
|
+
};
|
|
428
|
+
part(bchar, 0, 0);
|
|
429
|
+
part(achar, adx + sideBearing - asb, ady);
|
|
413
430
|
stack.length = 0;
|
|
414
431
|
return false;
|
|
415
432
|
}
|
|
416
433
|
if (op2 === 7) {
|
|
417
434
|
x = stack[0] ?? 0;
|
|
418
435
|
y = stack[1] ?? 0;
|
|
436
|
+
sideBearing = x;
|
|
419
437
|
stack.length = 0;
|
|
420
438
|
break;
|
|
421
439
|
}
|
|
@@ -457,10 +475,47 @@ function scaleSeg(seg, k) {
|
|
|
457
475
|
y: seg.y * k
|
|
458
476
|
};
|
|
459
477
|
}
|
|
460
|
-
/**
|
|
478
|
+
/**
|
|
479
|
+
* §6.4 — the width a charstring states before it draws: the second operand of
|
|
480
|
+
* `hsbw` (`sbx wx hsbw`), or the third of `sbw` (`sbx sby wx wy sbw`).
|
|
481
|
+
*/
|
|
482
|
+
function statedWidth(code) {
|
|
483
|
+
const stack = [];
|
|
484
|
+
for (let i = 0; i < code.length && stack.length <= 4;) {
|
|
485
|
+
const b = code[i++];
|
|
486
|
+
if (b >= 32 && b <= 246) stack.push(b - 139);
|
|
487
|
+
else if (b >= 247 && b <= 250) stack.push((b - 247) * 256 + (code[i++] ?? 0) + 108);
|
|
488
|
+
else if (b >= 251 && b <= 254) stack.push(-(b - 251) * 256 - (code[i++] ?? 0) - 108);
|
|
489
|
+
else if (b === 255) {
|
|
490
|
+
stack.push(code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3] | 0);
|
|
491
|
+
i += 4;
|
|
492
|
+
} else if (b === 13) return stack[1];
|
|
493
|
+
else if (b === 12 && code[i] === 7) return stack[2];
|
|
494
|
+
else return void 0;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/** The parts of a `seac` come back already scaled; this puts them back in glyph space. */
|
|
461
498
|
function unscale(seg, k) {
|
|
462
499
|
return scaleSeg(seg, k === 0 ? 1 : 1 / k);
|
|
463
500
|
}
|
|
501
|
+
/** A segment moved by `(dx, dy)`: where a `seac` puts its accent. */
|
|
502
|
+
function shift(seg, dx, dy) {
|
|
503
|
+
if (seg.op === "close" || dx === 0 && dy === 0) return seg;
|
|
504
|
+
if (seg.op === "cubic") return {
|
|
505
|
+
op: "cubic",
|
|
506
|
+
x1: seg.x1 + dx,
|
|
507
|
+
y1: seg.y1 + dy,
|
|
508
|
+
x2: seg.x2 + dx,
|
|
509
|
+
y2: seg.y2 + dy,
|
|
510
|
+
x: seg.x + dx,
|
|
511
|
+
y: seg.y + dy
|
|
512
|
+
};
|
|
513
|
+
return {
|
|
514
|
+
op: seg.op,
|
|
515
|
+
x: seg.x + dx,
|
|
516
|
+
y: seg.y + dy
|
|
517
|
+
};
|
|
518
|
+
}
|
|
464
519
|
/** §C.1 — the names `seac` selects its two parts by, at the codes it states. */
|
|
465
520
|
var STANDARD_ENCODING = {
|
|
466
521
|
32: "space",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { PageGradient } from './shading.js';
|
|
1
2
|
import { PathSeg } from './content.js';
|
|
2
|
-
import { ShapeGradient } from '../core/vector.js';
|
|
3
3
|
import { Loss } from '../core/ir/index.js';
|
|
4
4
|
import { PdfFile, PdfPage } from './document.js';
|
|
5
5
|
/**
|
|
@@ -21,7 +21,7 @@ export interface PdfVector {
|
|
|
21
21
|
/** Present iff a qualifying solid fill survived (EP10). */
|
|
22
22
|
readonly fillHex?: string;
|
|
23
23
|
/** Present iff a shading-pattern fill survived (EP16c). */
|
|
24
|
-
readonly gradient?:
|
|
24
|
+
readonly gradient?: PageGradient;
|
|
25
25
|
/** §11.6.4.4 — how opaque the fill is, when the page asked for less than all. */
|
|
26
26
|
readonly alpha?: number;
|
|
27
27
|
/**
|
|
@@ -33,6 +33,12 @@ export interface PdfVector {
|
|
|
33
33
|
readonly strokeHex?: string;
|
|
34
34
|
/** Stroke width in page-space points (EP11). */
|
|
35
35
|
readonly lineWidth?: number;
|
|
36
|
+
/** §8.4.3.6 — the stroke's dash lengths in page-space points, where it is dashed. */
|
|
37
|
+
readonly dash?: ReadonlyArray<number>;
|
|
38
|
+
/** §8.4.3.3 — the stroke's cap, where it is not the butt cap. */
|
|
39
|
+
readonly cap?: 'round' | 'square';
|
|
40
|
+
/** §11.6.4.4 `/CA` — how opaque the stroke is, where less than all. */
|
|
41
|
+
readonly strokeAlpha?: number;
|
|
36
42
|
readonly minX: number;
|
|
37
43
|
readonly minY: number;
|
|
38
44
|
readonly maxX: number;
|
|
@@ -2,9 +2,10 @@ import { PDF_NULL, PdfName, PdfStream } from "../pdf/objects.js";
|
|
|
2
2
|
import { FEATURES } from "../core/ir/features.js";
|
|
3
3
|
import { buildAlphaMap, buildColorSpaceMap, buildShadingMap, gradientShading, shadingTypeOf } from "./shading.js";
|
|
4
4
|
import { IDENTITY, interpretContent, multiply } from "./content.js";
|
|
5
|
-
import { collectPageAppearances } from "./annots.js";
|
|
5
|
+
import { appearanceContent, collectPageAppearances } from "./annots.js";
|
|
6
6
|
import { hiddenProperties, hiddenXObject } from "./optional-content.js";
|
|
7
7
|
import { buildFonts } from "./text.js";
|
|
8
|
+
import { patternTint, tintedHex } from "./pattern-tint.js";
|
|
8
9
|
//#region src/pdf-reader/vector.ts
|
|
9
10
|
function paintedVectors(file, page) {
|
|
10
11
|
const out = [];
|
|
@@ -22,6 +23,31 @@ function paintedVectors(file, page) {
|
|
|
22
23
|
stateCache.set(resources, made);
|
|
23
24
|
return made;
|
|
24
25
|
};
|
|
26
|
+
const tints = /* @__PURE__ */ new Map();
|
|
27
|
+
const tinted = (resources, vector) => {
|
|
28
|
+
const name = vector.patternName;
|
|
29
|
+
if (name === void 0) return vector;
|
|
30
|
+
let known = tints.get(resources);
|
|
31
|
+
if (!known) tints.set(resources, known = /* @__PURE__ */ new Map());
|
|
32
|
+
const key = `${name}\u0000${vector.patternPaint ?? ""}`;
|
|
33
|
+
let hex = known.get(key);
|
|
34
|
+
if (!known.has(key)) {
|
|
35
|
+
let tint;
|
|
36
|
+
try {
|
|
37
|
+
tint = patternTint(file, resources, name, vector.patternPaint);
|
|
38
|
+
} catch {
|
|
39
|
+
tint = void 0;
|
|
40
|
+
}
|
|
41
|
+
hex = tint ? tintedHex(tint.colorHex, tint.coverage) : void 0;
|
|
42
|
+
known.set(key, hex);
|
|
43
|
+
}
|
|
44
|
+
if (hex === void 0) return vector;
|
|
45
|
+
const { patternName: _named, patternPaint: _paint, ...plain } = vector;
|
|
46
|
+
return {
|
|
47
|
+
...plain,
|
|
48
|
+
fillHex: hex
|
|
49
|
+
};
|
|
50
|
+
};
|
|
25
51
|
const walk = (resources, content, baseCtm, depth, prefix) => {
|
|
26
52
|
if (out.length >= MAX_VECTORS) return;
|
|
27
53
|
const xobjects = resources ? file.get(resources, "XObject") : PDF_NULL;
|
|
@@ -34,7 +60,7 @@ function paintedVectors(file, page) {
|
|
|
34
60
|
const found = dict instanceof Map ? file.resolve(dict.get(paint.name) ?? PDF_NULL) : PDF_NULL;
|
|
35
61
|
const sh = found instanceof PdfStream ? found.dict : found instanceof Map ? found : void 0;
|
|
36
62
|
if (sh && shadingTypeOf(file, sh) === 1) continue;
|
|
37
|
-
const gradient = sh ? gradientShading(file, sh) : void 0;
|
|
63
|
+
const gradient = sh ? gradientShading(file, sh, paint.ctm) : void 0;
|
|
38
64
|
if (paint.masked) {
|
|
39
65
|
bareShadings++;
|
|
40
66
|
continue;
|
|
@@ -74,7 +100,7 @@ function paintedVectors(file, page) {
|
|
|
74
100
|
if (out.length >= MAX_VECTORS) return;
|
|
75
101
|
if (event.vector) {
|
|
76
102
|
out.push({
|
|
77
|
-
...event.vector,
|
|
103
|
+
...tinted(resources, event.vector),
|
|
78
104
|
orderKey: [...prefix, event.order]
|
|
79
105
|
});
|
|
80
106
|
continue;
|
|
@@ -102,7 +128,7 @@ function paintedVectors(file, page) {
|
|
|
102
128
|
};
|
|
103
129
|
walk(page.resources, file.pageContent(page), IDENTITY, 0, []);
|
|
104
130
|
collectPageAppearances(file, page).forEach((appearance, index) => {
|
|
105
|
-
walk(appearance.resources ?? page.resources, file
|
|
131
|
+
walk(appearance.resources ?? page.resources, appearanceContent(file, appearance), appearance.ctm, 1, [Number.MAX_SAFE_INTEGER, index]);
|
|
106
132
|
});
|
|
107
133
|
return {
|
|
108
134
|
placements: out,
|
|
@@ -196,7 +222,10 @@ function collectPageVectors(file, page, occupied = []) {
|
|
|
196
222
|
...filled && v.darkens === true ? { darkens: true } : {},
|
|
197
223
|
...stroked ? {
|
|
198
224
|
strokeHex: v.strokeHex,
|
|
199
|
-
...v.lineWidth !== void 0 ? { lineWidth: v.lineWidth } : {}
|
|
225
|
+
...v.lineWidth !== void 0 ? { lineWidth: v.lineWidth } : {},
|
|
226
|
+
...v.dash !== void 0 ? { dash: v.dash } : {},
|
|
227
|
+
...v.cap !== void 0 ? { cap: v.cap } : {},
|
|
228
|
+
...v.strokeAlpha !== void 0 ? { strokeAlpha: v.strokeAlpha } : {}
|
|
200
229
|
} : {},
|
|
201
230
|
...b,
|
|
202
231
|
...v.glyph === true ? { glyph: true } : {},
|
|
@@ -237,15 +266,23 @@ function overlaps(a, b) {
|
|
|
237
266
|
* path intersection, and where the two merely overlap the answer is the smaller
|
|
238
267
|
* of them — bounded, never larger than the truth.
|
|
239
268
|
*
|
|
269
|
+
* A path is measured by where its curves reach, not where their handles stand,
|
|
270
|
+
* and one that reaches past its clip by no more than a sliver is inside it. An
|
|
271
|
+
* appearance's `/BBox` is drawn round the path it holds: comments.pdf signs its
|
|
272
|
+
* sixth page with a stamp of sixty-seven strokes that its box meets exactly,
|
|
273
|
+
* and a handle standing 0.03pt past the box made the signature a path round
|
|
274
|
+
* its clip — it came back a black bar the width of the text.
|
|
275
|
+
*
|
|
240
276
|
* @param v The painted path as the interpreter saw it.
|
|
241
277
|
* @returns The path to draw, or `undefined` when the clip leaves nothing.
|
|
242
278
|
*/
|
|
243
279
|
function clipped(v) {
|
|
244
280
|
const clip = v.clip;
|
|
245
281
|
if (!clip) return v;
|
|
246
|
-
const b =
|
|
282
|
+
const b = reachOf(v.segs);
|
|
247
283
|
if (!b) return v;
|
|
248
284
|
if (clip.minX >= b.maxX || clip.maxX <= b.minX || clip.minY >= b.maxY || clip.maxY <= b.minY) return;
|
|
285
|
+
if (b.minX >= clip.minX - SLIVER_PT && b.maxX <= clip.maxX + SLIVER_PT && b.minY >= clip.minY - SLIVER_PT && b.maxY <= clip.maxY + SLIVER_PT) return v;
|
|
249
286
|
const pathArea = Math.max(0, b.maxX - b.minX) * Math.max(0, b.maxY - b.minY);
|
|
250
287
|
if (Math.max(0, clip.maxX - clip.minX) * Math.max(0, clip.maxY - clip.minY) >= pathArea) return v;
|
|
251
288
|
return {
|
|
@@ -254,6 +291,68 @@ function clipped(v) {
|
|
|
254
291
|
segs: clip.segs
|
|
255
292
|
};
|
|
256
293
|
}
|
|
294
|
+
/** How far past its clip a path may reach and still be inside it: a box's rounding. */
|
|
295
|
+
var SLIVER_PT = .5;
|
|
296
|
+
/**
|
|
297
|
+
* The box a path's curves reach: its points, and the turns of its curves —
|
|
298
|
+
* a Bézier stays inside its handles, and rarely reaches them.
|
|
299
|
+
*
|
|
300
|
+
* @param segs The path.
|
|
301
|
+
*/
|
|
302
|
+
function reachOf(segs) {
|
|
303
|
+
let minX = Infinity;
|
|
304
|
+
let minY = Infinity;
|
|
305
|
+
let maxX = -Infinity;
|
|
306
|
+
let maxY = -Infinity;
|
|
307
|
+
const add = (x, y) => {
|
|
308
|
+
minX = Math.min(minX, x);
|
|
309
|
+
minY = Math.min(minY, y);
|
|
310
|
+
maxX = Math.max(maxX, x);
|
|
311
|
+
maxY = Math.max(maxY, y);
|
|
312
|
+
};
|
|
313
|
+
let [x, y] = [0, 0];
|
|
314
|
+
let [startX, startY] = [0, 0];
|
|
315
|
+
for (const s of segs) {
|
|
316
|
+
if (s.op === "close") {
|
|
317
|
+
[x, y] = [startX, startY];
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (s.op === "cubic") {
|
|
321
|
+
const [x0, y0] = [x, y];
|
|
322
|
+
for (const t of [...turnsOf(x0, s.x1, s.x2, s.x), ...turnsOf(y0, s.y1, s.y2, s.y)]) add(bezierAt(x0, s.x1, s.x2, s.x, t), bezierAt(y0, s.y1, s.y2, s.y, t));
|
|
323
|
+
}
|
|
324
|
+
add(s.x, s.y);
|
|
325
|
+
[x, y] = [s.x, s.y];
|
|
326
|
+
if (s.op === "move") [startX, startY] = [s.x, s.y];
|
|
327
|
+
}
|
|
328
|
+
return Number.isFinite(minX) ? {
|
|
329
|
+
minX,
|
|
330
|
+
minY,
|
|
331
|
+
maxX,
|
|
332
|
+
maxY
|
|
333
|
+
} : void 0;
|
|
334
|
+
}
|
|
335
|
+
/** Where, between its ends, one coordinate of a cubic Bézier turns back. */
|
|
336
|
+
function turnsOf(p0, p1, p2, p3) {
|
|
337
|
+
const a = p3 - 3 * p2 + 3 * p1 - p0;
|
|
338
|
+
const b = 2 * (p2 - 2 * p1 + p0);
|
|
339
|
+
const c = p1 - p0;
|
|
340
|
+
let roots = [];
|
|
341
|
+
if (Math.abs(a) < FLAT) {
|
|
342
|
+
if (Math.abs(b) >= FLAT) roots = [-c / b];
|
|
343
|
+
} else {
|
|
344
|
+
const d = b * b - 4 * a * c;
|
|
345
|
+
if (d >= 0) roots = [(-b + Math.sqrt(d)) / (2 * a), (-b - Math.sqrt(d)) / (2 * a)];
|
|
346
|
+
}
|
|
347
|
+
return roots.filter((t) => t > 0 && t < 1);
|
|
348
|
+
}
|
|
349
|
+
/** A coefficient this small is none: the curve's derivative is of lower degree. */
|
|
350
|
+
var FLAT = 1e-12;
|
|
351
|
+
/** One coordinate of a cubic Bézier at `t`. */
|
|
352
|
+
function bezierAt(p0, p1, p2, p3, t) {
|
|
353
|
+
const u = 1 - t;
|
|
354
|
+
return u * u * u * p0 + 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t * p3;
|
|
355
|
+
}
|
|
257
356
|
function bbox(segs) {
|
|
258
357
|
let minX = Infinity;
|
|
259
358
|
let minY = Infinity;
|
|
@@ -178,7 +178,8 @@ function readDoc(bytes) {
|
|
|
178
178
|
},
|
|
179
179
|
styles: EMPTY_STYLE_SHEET,
|
|
180
180
|
resources,
|
|
181
|
-
...headersFooters.size > 0 ? { headersFooters } : {}
|
|
181
|
+
...headersFooters.size > 0 ? { headersFooters } : {},
|
|
182
|
+
typesetBy: "word"
|
|
182
183
|
},
|
|
183
184
|
losses: [content.encrypted ? DOC_ENCRYPTED_LOSS : DOC_TEXT_LOSS]
|
|
184
185
|
};
|
|
@@ -406,7 +407,10 @@ function toParaProperties(p) {
|
|
|
406
407
|
...p.indentRightTwips !== void 0 ? { indentRight: pt(p.indentRightTwips / 20) } : {},
|
|
407
408
|
...p.indentFirstTwips !== void 0 ? { indentFirstLine: pt(p.indentFirstTwips / 20) } : {},
|
|
408
409
|
...p.spaceBeforeTwips !== void 0 ? { spacingBefore: pt(p.spaceBeforeTwips / 20) } : {},
|
|
409
|
-
...p.spaceAfterTwips !== void 0 ? { spacingAfter: pt(p.spaceAfterTwips / 20) } : {}
|
|
410
|
+
...p.spaceAfterTwips !== void 0 ? { spacingAfter: pt(p.spaceAfterTwips / 20) } : {},
|
|
411
|
+
...p.widowControl !== void 0 ? { widowControl: p.widowControl } : {},
|
|
412
|
+
...p.keepNext !== void 0 ? { keepNext: p.keepNext } : {},
|
|
413
|
+
...p.keepLines !== void 0 ? { keepLines: p.keepLines } : {}
|
|
410
414
|
};
|
|
411
415
|
}
|
|
412
416
|
function underlineStyle(kul) {
|
|
@@ -74,6 +74,12 @@ export interface DocParaProps {
|
|
|
74
74
|
readonly listIlfo?: number;
|
|
75
75
|
/** `sprmPIlvl` — list level (0–8). */
|
|
76
76
|
readonly listIlvl?: number;
|
|
77
|
+
/** `sprmPFWidowControl` — no first or last line left alone on a page. */
|
|
78
|
+
readonly widowControl?: boolean;
|
|
79
|
+
/** `sprmPFKeepFollow` — on the same page as the start of the next paragraph. */
|
|
80
|
+
readonly keepNext?: boolean;
|
|
81
|
+
/** `sprmPFKeep` — every line on one page. */
|
|
82
|
+
readonly keepLines?: boolean;
|
|
77
83
|
}
|
|
78
84
|
/** One maximal same-formatting run of text, or an embedded picture. */
|
|
79
85
|
export interface DocRun {
|
|
@@ -40,6 +40,9 @@ var SPRM_P_DYA_BEFORE = 42003;
|
|
|
40
40
|
var SPRM_P_DYA_AFTER = 42004;
|
|
41
41
|
var SPRM_P_F_IN_TABLE = 9238;
|
|
42
42
|
var SPRM_P_F_TTP = 9239;
|
|
43
|
+
var SPRM_P_F_WIDOW_CONTROL = 9265;
|
|
44
|
+
var SPRM_P_F_KEEP = 9221;
|
|
45
|
+
var SPRM_P_F_KEEP_FOLLOW = 9222;
|
|
43
46
|
var SPRM_T_DEF_TABLE = 54792;
|
|
44
47
|
var SPRM_T_DEF_TABLE_SHD = 54802;
|
|
45
48
|
var MAX_ROW_CELLS = 256;
|
|
@@ -433,6 +436,9 @@ function decodePapxGrpprl(d) {
|
|
|
433
436
|
let cellShadings;
|
|
434
437
|
let listIlfo;
|
|
435
438
|
let listIlvl;
|
|
439
|
+
let widowControl;
|
|
440
|
+
let keepNext;
|
|
441
|
+
let keepLines;
|
|
436
442
|
for (const s of sprms(d)) switch (s.sprm) {
|
|
437
443
|
case SPRM_P_JC:
|
|
438
444
|
jc = d[s.op];
|
|
@@ -458,6 +464,15 @@ function decodePapxGrpprl(d) {
|
|
|
458
464
|
case SPRM_P_F_TTP:
|
|
459
465
|
rowEnd = d[s.op] !== 0;
|
|
460
466
|
break;
|
|
467
|
+
case SPRM_P_F_WIDOW_CONTROL:
|
|
468
|
+
widowControl = d[s.op] !== 0;
|
|
469
|
+
break;
|
|
470
|
+
case SPRM_P_F_KEEP_FOLLOW:
|
|
471
|
+
keepNext = d[s.op] !== 0;
|
|
472
|
+
break;
|
|
473
|
+
case SPRM_P_F_KEEP:
|
|
474
|
+
keepLines = d[s.op] !== 0;
|
|
475
|
+
break;
|
|
461
476
|
case SPRM_T_DEF_TABLE: {
|
|
462
477
|
const cols = d[s.op] ?? 0;
|
|
463
478
|
const edges = [];
|
|
@@ -498,7 +513,10 @@ function decodePapxGrpprl(d) {
|
|
|
498
513
|
...cellDescriptors ? { cellDescriptors } : {},
|
|
499
514
|
...cellShadings ? { cellShadings } : {},
|
|
500
515
|
...listIlfo !== void 0 ? { listIlfo } : {},
|
|
501
|
-
...listIlvl !== void 0 ? { listIlvl } : {}
|
|
516
|
+
...listIlvl !== void 0 ? { listIlvl } : {},
|
|
517
|
+
...widowControl !== void 0 ? { widowControl } : {},
|
|
518
|
+
...keepNext !== void 0 ? { keepNext } : {},
|
|
519
|
+
...keepLines !== void 0 ? { keepLines } : {}
|
|
502
520
|
};
|
|
503
521
|
}
|
|
504
522
|
function* sprms(d) {
|
|
@@ -80,8 +80,8 @@ export interface ParseContext {
|
|
|
80
80
|
readonly openCommentRanges?: Set<string>;
|
|
81
81
|
/**
|
|
82
82
|
* §17.3.1.1/§17.3.1.3 — what `w:beforeAutospacing`/`w:afterAutospacing`
|
|
83
|
-
* resolve to
|
|
84
|
-
*
|
|
83
|
+
* resolve to: HTML's 14pt for a Word document, nothing (the default) where
|
|
84
|
+
* the caller gives none.
|
|
85
85
|
*/
|
|
86
86
|
readonly autoSpacingPt?: number;
|
|
87
87
|
}
|
|
@@ -9,6 +9,7 @@ import { parseRunProperties } from "./run-properties.js";
|
|
|
9
9
|
import { parseParagraphProperties } from "./paragraph-properties.js";
|
|
10
10
|
import { poElementToFlat } from "./po-to-flat.js";
|
|
11
11
|
import { parseBorders, parseTable } from "./table-parser.js";
|
|
12
|
+
import { FORMATS } from "./numbering-parser.js";
|
|
12
13
|
import { XMLParser } from "fast-xml-parser";
|
|
13
14
|
//#region src/word/document-parser.ts
|
|
14
15
|
var decoder = new TextDecoder("utf-8");
|
|
@@ -199,11 +200,13 @@ function parseSectPrNode(sectPr) {
|
|
|
199
200
|
let margins;
|
|
200
201
|
let titlePg = false;
|
|
201
202
|
let pageNumberStart;
|
|
203
|
+
let pageNumberFormat;
|
|
202
204
|
let lineNumbering;
|
|
203
205
|
let columns;
|
|
204
206
|
let sectionStart;
|
|
205
207
|
let pageBorders;
|
|
206
208
|
let gridLinePitchPt;
|
|
209
|
+
let textDirection;
|
|
207
210
|
const headers = [];
|
|
208
211
|
const footers = [];
|
|
209
212
|
for (const child of poChildren(sectPr)) if (poIs(child, "w:pgSz")) {
|
|
@@ -251,6 +254,8 @@ function parseSectPrNode(sectPr) {
|
|
|
251
254
|
} else if (poIs(child, "w:pgNumType")) {
|
|
252
255
|
const start = poIntAttr(child, "start");
|
|
253
256
|
if (start !== void 0) pageNumberStart = start;
|
|
257
|
+
const fmt = poAttr(child, "fmt");
|
|
258
|
+
if (fmt !== void 0 && FORMATS.has(fmt) && fmt !== "decimal") pageNumberFormat = fmt;
|
|
254
259
|
} else if (poIs(child, "w:cols")) columns = parseColumns(child);
|
|
255
260
|
else if (poIs(child, "w:pgBorders")) {
|
|
256
261
|
const borders = parseBorders(child);
|
|
@@ -265,6 +270,9 @@ function parseSectPrNode(sectPr) {
|
|
|
265
270
|
} else if (poIs(child, "w:type")) {
|
|
266
271
|
const val = poAttr(child, "val");
|
|
267
272
|
sectionStart = val === "continuous" || val === "oddPage" || val === "evenPage" ? val : "nextPage";
|
|
273
|
+
} else if (poIs(child, "w:textDirection")) {
|
|
274
|
+
const val = poAttr(child, "val");
|
|
275
|
+
if (val === "tbRl" || val === "btLr") textDirection = val;
|
|
268
276
|
}
|
|
269
277
|
return {
|
|
270
278
|
pageSize,
|
|
@@ -273,11 +281,13 @@ function parseSectPrNode(sectPr) {
|
|
|
273
281
|
footers,
|
|
274
282
|
...titlePg ? { titlePg: true } : {},
|
|
275
283
|
...pageNumberStart !== void 0 ? { pageNumberStart } : {},
|
|
284
|
+
...pageNumberFormat !== void 0 ? { pageNumberFormat } : {},
|
|
276
285
|
...lineNumbering ? { lineNumbering } : {},
|
|
277
286
|
...columns ? { columns } : {},
|
|
278
287
|
...sectionStart ? { sectionStart } : {},
|
|
279
288
|
...pageBorders ? { pageBorders } : {},
|
|
280
|
-
...gridLinePitchPt !== void 0 ? { gridLinePitchPt } : {}
|
|
289
|
+
...gridLinePitchPt !== void 0 ? { gridLinePitchPt } : {},
|
|
290
|
+
...textDirection ? { textDirection } : {}
|
|
281
291
|
};
|
|
282
292
|
}
|
|
283
293
|
function parseColumns(cols) {
|
|
@@ -15,10 +15,10 @@ import { OpcPackage } from "../core/opc/package.js";
|
|
|
15
15
|
import { parseCoreProperties } from "../core/opc/core-properties.js";
|
|
16
16
|
import "../core/opc/index.js";
|
|
17
17
|
import { parseXml } from "../pptx/pptx-reader.js";
|
|
18
|
+
import { EMPTY_NUMBERING, parseNumbering } from "./numbering-parser.js";
|
|
18
19
|
import { EMPTY_SECTION, applyAuthorIds, bodyIndexForBlock, newBlockCounter, parseBackgroundColor, parseBackgroundFill, parseCommentThreads, parseDocument, parseHeaderFooter, parseNotes, parsePeople, parseSections } from "./document-parser.js";
|
|
19
20
|
import { parseStyles } from "./styles-parser.js";
|
|
20
21
|
import { loadEmbeddedFonts } from "./font-table.js";
|
|
21
|
-
import { EMPTY_NUMBERING, parseNumbering } from "./numbering-parser.js";
|
|
22
22
|
import { EMPTY_SETTINGS, parseSettings } from "./settings-parser.js";
|
|
23
23
|
import "./index.js";
|
|
24
24
|
//#region src/word/docx-reader.ts
|
|
@@ -66,7 +66,7 @@ function readDocx(docx) {
|
|
|
66
66
|
const settings = settingsData ? parseSettings(settingsData) : EMPTY_SETTINGS;
|
|
67
67
|
const ctx = {
|
|
68
68
|
resolveColor,
|
|
69
|
-
|
|
69
|
+
autoSpacingPt: 14,
|
|
70
70
|
...themeLineWidths && themeLineWidths.length > 0 ? { themeLineWidths } : {},
|
|
71
71
|
...themeStyles ? { themeStyles } : {},
|
|
72
72
|
...themeFonts ? { themeFonts } : {},
|
|
@@ -142,7 +142,9 @@ function readDocx(docx) {
|
|
|
142
142
|
...settings.doNotExpandShiftReturn ? { doNotExpandShiftReturn: true } : {},
|
|
143
143
|
...settings.displayBackgroundShape && backgroundFill ? { pageBackgroundFill: backgroundFill } : {},
|
|
144
144
|
...settings.displayBackgroundShape && backgroundColorHex ? { pageBackgroundColorHex: backgroundColorHex } : {},
|
|
145
|
-
...settings.gutterAtTop ? { gutterAtTop: true } : {}
|
|
145
|
+
...settings.gutterAtTop ? { gutterAtTop: true } : {},
|
|
146
|
+
...settings.compatibilityMode !== void 0 ? { compatibilityMode: settings.compatibilityMode } : {},
|
|
147
|
+
typesetBy: "word"
|
|
146
148
|
},
|
|
147
149
|
losses
|
|
148
150
|
};
|