documonster 0.16.0 → 0.16.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 +17 -14
- package/README_zh.md +20 -16
- package/dist/esm/modules/archive/zip/zip-archive.js +37 -7
- package/dist/esm/modules/excel/chart/chart-handle.js +4 -4
- package/dist/esm/modules/excel/chart/render/chart-renderer.js +6 -379
- package/dist/esm/modules/excel/chart/shared/shape-properties.js +32 -41
- package/dist/esm/modules/excel/core/workbook.browser.js +10 -4
- package/dist/esm/modules/excel/utils/guid.js +7 -29
- package/dist/esm/modules/stream/core/utils.js +1 -1
- package/dist/esm/modules/stream/node/factories.js +4 -2
- package/dist/esm/modules/word/core/internal-utils.js +8 -14
- package/dist/iife/documonster.archive.iife.min.js +4 -4
- package/dist/iife/documonster.csv.iife.min.js +8 -8
- package/dist/iife/documonster.draw.iife.min.js +2 -2
- package/dist/iife/documonster.excel.iife.min.js +46 -46
- package/dist/iife/documonster.formula.iife.min.js +3 -3
- package/dist/iife/documonster.markdown.iife.min.js +2 -2
- package/dist/iife/documonster.mermaid.iife.min.js +3 -3
- package/dist/iife/documonster.pdf.iife.min.js +28 -28
- package/dist/iife/documonster.stream.iife.min.js +2 -2
- package/dist/iife/documonster.word.iife.min.js +60 -60
- package/dist/iife/documonster.xml.iife.min.js +4 -4
- package/dist/types/modules/archive/zip/zip-archive.d.ts +22 -0
- package/dist/types/modules/excel/utils/guid.d.ts +0 -14
- package/dist/types/modules/word/core/internal-utils.d.ts +6 -0
- package/package.json +10 -10
|
@@ -401,26 +401,26 @@ function parsePatternFill(xml) {
|
|
|
401
401
|
return { pattern: { preset, foreground, background } };
|
|
402
402
|
}
|
|
403
403
|
/**
|
|
404
|
-
* Remove
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
* `<a:solidFill>` / `<a:noFill/>` / `<a:gradFill>` should not be
|
|
409
|
-
* harvested as the shape's fill.
|
|
404
|
+
* Remove `<tag …>…</tag>` (or self-closing `<tag …/>`) blocks from the input
|
|
405
|
+
* XML, returning the remainder. Used by {@link parseSpPr} to keep the line's
|
|
406
|
+
* own `<a:solidFill>` / `<a:noFill/>` / `<a:gradFill>` inside `<a:ln>` from
|
|
407
|
+
* being harvested as the shape's fill.
|
|
410
408
|
*
|
|
411
|
-
* Strips
|
|
412
|
-
*
|
|
413
|
-
* which failed on inputs like `<a:ln/>…<a:ln>…</a:ln>` — the paired
|
|
414
|
-
* block survived and its inner `<a:solidFill>` was then mistakenly
|
|
415
|
-
* parsed as the shape's fill.
|
|
409
|
+
* Strips up to eight occurrences in one pass, so a `<a:ln/>` ahead of
|
|
410
|
+
* `<a:ln>…</a:ln>` does not leave the paired block behind.
|
|
416
411
|
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
412
|
+
* The trailing slash is **captured** rather than excluded with a `(?<!/)`
|
|
413
|
+
* lookbehind, which Safari only supports from 16.4 and which threw
|
|
414
|
+
* `SyntaxError` here at first use, not at import.
|
|
415
|
+
*
|
|
416
|
+
* Not a general-purpose XML tool: no same-named nesting, and no `>` inside an
|
|
417
|
+
* attribute value. Sufficient for DrawingML spPr.
|
|
420
418
|
*/
|
|
421
419
|
function stripOuterElement(xml, tag) {
|
|
422
|
-
|
|
423
|
-
|
|
420
|
+
// `[^>]*?` is lazy so `(/?)` gets the chance to claim the slash of a
|
|
421
|
+
// self-closing tag; a greedy `[^>]*` would swallow it and report every
|
|
422
|
+
// `<tag …/>` as a paired open tag.
|
|
423
|
+
const tagRe = new RegExp(`<${tag}\\b[^>]*?(/?)>`);
|
|
424
424
|
const closeRe = new RegExp(`</${tag}>`);
|
|
425
425
|
let current = xml;
|
|
426
426
|
// Strip up to 8 occurrences. DrawingML spPr never has more than one
|
|
@@ -428,36 +428,27 @@ function stripOuterElement(xml, tag) {
|
|
|
428
428
|
// the ceiling guards against pathological input causing infinite
|
|
429
429
|
// loops without changing the happy path.
|
|
430
430
|
for (let i = 0; i < 8; i++) {
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
const selfCloseIndex = selfCloseMatch ? selfCloseMatch.index : Infinity;
|
|
434
|
-
const openIndex = openMatch ? openMatch.index : Infinity;
|
|
435
|
-
if (selfCloseIndex === Infinity && openIndex === Infinity) {
|
|
431
|
+
const match = tagRe.exec(current);
|
|
432
|
+
if (!match) {
|
|
436
433
|
break;
|
|
437
434
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
current.slice(selfCloseMatch.index + selfCloseMatch[0].length);
|
|
435
|
+
const matchEnd = match.index + match[0].length;
|
|
436
|
+
if (match[1] === "/") {
|
|
437
|
+
current = current.slice(0, match.index) + current.slice(matchEnd);
|
|
442
438
|
continue;
|
|
443
439
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
// input we don't understand.
|
|
453
|
-
break;
|
|
454
|
-
}
|
|
455
|
-
const closeStart = openEnd + closeMatch.index;
|
|
456
|
-
const closeEnd = closeStart + closeMatch[0].length;
|
|
457
|
-
current = current.slice(0, openMatch.index) + current.slice(closeEnd);
|
|
458
|
-
continue;
|
|
440
|
+
// Find the close tag that pairs with this open — start searching
|
|
441
|
+
// after the open's end to avoid capturing `</tag>` that belongs
|
|
442
|
+
// to a prior unrelated (e.g. self-closing lookalike) open.
|
|
443
|
+
const closeMatch = closeRe.exec(current.slice(matchEnd));
|
|
444
|
+
if (!closeMatch) {
|
|
445
|
+
// Malformed — stop stripping to avoid further mutation of
|
|
446
|
+
// input we don't understand.
|
|
447
|
+
break;
|
|
459
448
|
}
|
|
460
|
-
|
|
449
|
+
current =
|
|
450
|
+
current.slice(0, match.index) +
|
|
451
|
+
current.slice(matchEnd + closeMatch.index + closeMatch[0].length);
|
|
461
452
|
}
|
|
462
453
|
return current;
|
|
463
454
|
}
|
|
@@ -876,11 +876,17 @@ export function setWorkbookModel(wb, value) {
|
|
|
876
876
|
// workbook replaces any accumulated state from previous writes.
|
|
877
877
|
wb._writerExternalLinkCache = new Map();
|
|
878
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Deep-clone workbook-model data.
|
|
881
|
+
*
|
|
882
|
+
* `structuredClone` unguarded: it exists in every supported environment, and
|
|
883
|
+
* the `JSON.parse(JSON.stringify(...))` fallback this used to carry was a
|
|
884
|
+
* lossier second implementation, not a fallback — it strips a typed-array
|
|
885
|
+
* prototype, which the `Uint8Array` values on `ChartExModel.externalParts`
|
|
886
|
+
* need. `chart/chart-handle.ts` had already dropped the same fallback.
|
|
887
|
+
*/
|
|
879
888
|
function deepClone(value) {
|
|
880
|
-
|
|
881
|
-
return structuredClone(value);
|
|
882
|
-
}
|
|
883
|
-
return JSON.parse(JSON.stringify(value));
|
|
889
|
+
return structuredClone(value);
|
|
884
890
|
}
|
|
885
891
|
/**
|
|
886
892
|
* Deep-copy a {@link ChartEntry}, preserving every field that affects
|
|
@@ -1,35 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GUID helpers for OOXML.
|
|
3
3
|
*
|
|
4
|
-
* Office parts
|
|
5
|
-
*
|
|
6
|
-
* `
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `synthGuid()` returns an RFC-4122 version-4-compatible value suitable
|
|
10
|
-
* for those callers. We don't use `crypto.randomUUID()` directly because
|
|
11
|
-
* it isn't available in every supported runtime (older Node without
|
|
12
|
-
* `node:crypto` globals); `Math.random` is good enough for uniqueness
|
|
13
|
-
* within a single workbook, which is the only thing Office cares about.
|
|
4
|
+
* Office parts needing stable cross-reference ids (threaded comments, chart
|
|
5
|
+
* uniqueIds, slicer caches) use uppercase hex in 8-4-4-4-12 groups; callers add
|
|
6
|
+
* the braces. `synthGuid()` delegates to {@link uuidV4} and upper-cases it
|
|
7
|
+
* rather than rolling its own digits out of `Math.random()`, which skipped Web
|
|
8
|
+
* Crypto even where it exists and duplicated the version/variant masking.
|
|
14
9
|
*/
|
|
10
|
+
import { uuidV4 } from "../../../utils/uuid.js";
|
|
15
11
|
export function synthGuid() {
|
|
16
|
-
|
|
17
|
-
let out = "";
|
|
18
|
-
for (let i = 0; i < 32; i++) {
|
|
19
|
-
// Version 4: bit 48 (13th hex digit) is always '4'.
|
|
20
|
-
// Variant 10xx: bit 64 (17th hex digit) is one of 8, 9, A, B.
|
|
21
|
-
if (i === 12) {
|
|
22
|
-
out += "4";
|
|
23
|
-
}
|
|
24
|
-
else if (i === 16) {
|
|
25
|
-
out += hex[8 + Math.floor(Math.random() * 4)];
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
out += hex[Math.floor(Math.random() * 16)];
|
|
29
|
-
}
|
|
30
|
-
if (i === 7 || i === 11 || i === 15 || i === 19) {
|
|
31
|
-
out += "-";
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return out;
|
|
12
|
+
return uuidV4().toUpperCase();
|
|
35
13
|
}
|
|
@@ -42,7 +42,7 @@ export function promisify(fn) {
|
|
|
42
42
|
// =============================================================================
|
|
43
43
|
// High Water Mark
|
|
44
44
|
// =============================================================================
|
|
45
|
-
let _defaultHighWaterMark = 65536; // 64KB default (matches Node
|
|
45
|
+
let _defaultHighWaterMark = 65536; // 64KB default (matches Node's own on every supported line)
|
|
46
46
|
let _defaultHighWaterMarkObjectMode = 16; // 16 objects default
|
|
47
47
|
/**
|
|
48
48
|
* Get the default high water mark for streams
|
|
@@ -24,8 +24,10 @@ import { Writable } from "./writable.js";
|
|
|
24
24
|
/**
|
|
25
25
|
* Ensure the options include a highWaterMark so that native Node.js streams
|
|
26
26
|
* use the same default as the browser implementation (from common/utils.ts).
|
|
27
|
-
*
|
|
28
|
-
* the 64 KB
|
|
27
|
+
*
|
|
28
|
+
* Every supported Node line already defaults to the same 64 KB, so this is not
|
|
29
|
+
* a version workaround: it exists so `setDefaultHighWaterMark` is honoured on
|
|
30
|
+
* native streams too, which otherwise read Node's default rather than ours.
|
|
29
31
|
*/
|
|
30
32
|
function withDefaultHWM(options) {
|
|
31
33
|
if (options?.highWaterMark != null) {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* used throughout the word module. Consolidates previously duplicated
|
|
6
6
|
* implementations of base64, UUID, UTF-16LE encoding, and XML helpers.
|
|
7
7
|
*/
|
|
8
|
+
import { uuidV4 } from "../../../utils/uuid.js";
|
|
8
9
|
import { DocxError } from "../errors.js";
|
|
9
10
|
// =============================================================================
|
|
10
11
|
// Shared TextEncoder / TextDecoder singletons
|
|
@@ -62,25 +63,18 @@ export function base64ToBytes(s) {
|
|
|
62
63
|
// =============================================================================
|
|
63
64
|
// UUID v4 Generation
|
|
64
65
|
// =============================================================================
|
|
65
|
-
/**
|
|
66
|
-
* Generate a random UUID v4 string in the form "XXXXXXXX-XXXX-4XXX-YXXX-XXXXXXXXXXXX".
|
|
67
|
-
* Uses `crypto.getRandomValues` for cryptographic randomness.
|
|
68
|
-
*/
|
|
69
|
-
function generateUuid() {
|
|
70
|
-
const bytes = new Uint8Array(16);
|
|
71
|
-
crypto.getRandomValues(bytes);
|
|
72
|
-
// RFC 4122 v4 UUID: set version (4) and variant (10xx) bits
|
|
73
|
-
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
74
|
-
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
75
|
-
const hex = Array.from(bytes, b => b.toString(16).padStart(2, "0")).join("");
|
|
76
|
-
return `${hex.substring(0, 8)}-${hex.substring(8, 12)}-${hex.substring(12, 16)}-${hex.substring(16, 20)}-${hex.substring(20, 32)}`;
|
|
77
|
-
}
|
|
78
66
|
/**
|
|
79
67
|
* Generate a GUID in braced format: "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".
|
|
80
68
|
* Used by font obfuscation (w:fontKey) and building blocks.
|
|
69
|
+
*
|
|
70
|
+
* Delegates to {@link uuidV4} rather than assembling a third copy of the v4 bit
|
|
71
|
+
* masking here. These ids identify rather than protect — a `w:fontKey` is
|
|
72
|
+
* stored in the document in plain text — so a non-cryptographic tier is
|
|
73
|
+
* acceptable. Keys, salts and verifiers use {@link randomBytes}, which throws
|
|
74
|
+
* when Web Crypto is missing.
|
|
81
75
|
*/
|
|
82
76
|
export function generateGuid() {
|
|
83
|
-
return `{${
|
|
77
|
+
return `{${uuidV4()}}`;
|
|
84
78
|
}
|
|
85
79
|
// =============================================================================
|
|
86
80
|
// UTF-16LE Encoding
|