@pixerate/editor 0.24.0 → 0.26.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 +101 -1
- package/THIRD_PARTY_NOTICES.md +40 -0
- package/dist/agent/index.cjs +175 -11
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +18 -4
- package/dist/agent/index.d.ts +18 -4
- package/dist/agent/index.js +168 -4
- package/dist/agent/index.js.map +1 -1
- package/dist/{arrangeShortcuts-B8O3f8-P.d.cts → arrange-BICutYPk.d.cts} +243 -29
- package/dist/{arrangeShortcuts-sLlD2rSX.d.ts → arrange-BICutYPk.d.ts} +243 -29
- package/dist/builtins-CdPcLwwF.d.cts +176 -0
- package/dist/builtins-Chj6zv_O.d.ts +176 -0
- package/dist/canvas/index.cjs +8588 -1857
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +1847 -9
- package/dist/canvas/index.d.ts +1847 -9
- package/dist/canvas/index.js +8577 -1846
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-3CC7OPUQ.cjs +831 -0
- package/dist/chunk-3CC7OPUQ.cjs.map +1 -0
- package/dist/chunk-4BVP64JJ.cjs +1406 -0
- package/dist/chunk-4BVP64JJ.cjs.map +1 -0
- package/dist/chunk-BVP3TSLH.cjs +69 -0
- package/dist/chunk-BVP3TSLH.cjs.map +1 -0
- package/dist/{chunk-OLZJXL4R.cjs → chunk-CS6NZWWA.cjs} +59 -25
- package/dist/chunk-CS6NZWWA.cjs.map +1 -0
- package/dist/{chunk-MCSJFWAO.cjs → chunk-EWCOFSCQ.cjs} +685 -100
- package/dist/chunk-EWCOFSCQ.cjs.map +1 -0
- package/dist/chunk-HDYMLS3X.cjs +409 -0
- package/dist/chunk-HDYMLS3X.cjs.map +1 -0
- package/dist/chunk-HRMEDT2L.js +1406 -0
- package/dist/chunk-HRMEDT2L.js.map +1 -0
- package/dist/{chunk-D27YFC46.cjs → chunk-IFHKKVXH.cjs} +382 -63
- package/dist/chunk-IFHKKVXH.cjs.map +1 -0
- package/dist/{chunk-PGNZKFQS.js → chunk-JOIREKL7.js} +137 -58
- package/dist/chunk-JOIREKL7.js.map +1 -0
- package/dist/chunk-KRGXUQ2Y.js +1696 -0
- package/dist/chunk-KRGXUQ2Y.js.map +1 -0
- package/dist/{chunk-3LV6RRPH.js → chunk-MHEPLBFB.js} +2 -2
- package/dist/chunk-MR2764X2.js +831 -0
- package/dist/chunk-MR2764X2.js.map +1 -0
- package/dist/{chunk-XNORY7M6.cjs → chunk-NFVBT3UZ.cjs} +166 -87
- package/dist/chunk-NFVBT3UZ.cjs.map +1 -0
- package/dist/chunk-NQF32I6Z.cjs +6478 -0
- package/dist/chunk-NQF32I6Z.cjs.map +1 -0
- package/dist/chunk-O5RYH2PG.js +69 -0
- package/dist/chunk-O5RYH2PG.js.map +1 -0
- package/dist/{chunk-ITBSKI26.js → chunk-Q2OHWD2A.js} +1064 -360
- package/dist/chunk-Q2OHWD2A.js.map +1 -0
- package/dist/{chunk-FODNLX5N.js → chunk-QJSOZFCZ.js} +38 -4
- package/dist/chunk-QJSOZFCZ.js.map +1 -0
- package/dist/{chunk-SML64VJG.cjs → chunk-RRREAOVM.cjs} +4 -4
- package/dist/{chunk-SML64VJG.cjs.map → chunk-RRREAOVM.cjs.map} +1 -1
- package/dist/{chunk-5S3Z4PPF.js → chunk-SWE3NPOU.js} +347 -28
- package/dist/chunk-SWE3NPOU.js.map +1 -0
- package/dist/chunk-TXXNBDQX.cjs +1696 -0
- package/dist/chunk-TXXNBDQX.cjs.map +1 -0
- package/dist/chunk-UBCFIABU.js +409 -0
- package/dist/chunk-UBCFIABU.js.map +1 -0
- package/dist/chunk-X7HXL2SB.js +6478 -0
- package/dist/chunk-X7HXL2SB.js.map +1 -0
- package/dist/{chunk-SBCZ6RN5.cjs → chunk-YOMYSFJU.cjs} +1163 -459
- package/dist/chunk-YOMYSFJU.cjs.map +1 -0
- package/dist/{chunk-3CN2WD3X.js → chunk-ZRNHGAQT.js} +661 -76
- package/dist/chunk-ZRNHGAQT.js.map +1 -0
- package/dist/commands/index.cjs +425 -4
- package/dist/commands/index.cjs.map +1 -1
- package/dist/commands/index.d.cts +39 -77
- package/dist/commands/index.d.ts +39 -77
- package/dist/commands/index.js +424 -3
- package/dist/commands/index.js.map +1 -1
- package/dist/compare/index.cjs +3 -3
- package/dist/compare/index.d.cts +1 -1
- package/dist/compare/index.d.ts +1 -1
- package/dist/compare/index.js +2 -2
- package/dist/controller-CxXGOEmy.d.cts +2038 -0
- package/dist/controller-CxXGOEmy.d.ts +2038 -0
- package/dist/{documents-BQjzJNe2.d.ts → documents-CHT1U5Vs.d.ts} +10 -0
- package/dist/{documents-KRTPhvst.d.cts → documents-Gp7wb0Me.d.cts} +10 -0
- package/dist/export/index.cjs +36 -0
- package/dist/export/index.cjs.map +1 -0
- package/dist/export/index.d.cts +243 -0
- package/dist/export/index.d.ts +243 -0
- package/dist/export/index.js +36 -0
- package/dist/export/index.js.map +1 -0
- package/dist/extensions/index.cjs +101 -6
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +18 -5
- package/dist/extensions/index.d.ts +18 -5
- package/dist/extensions/index.js +101 -6
- package/dist/generation/index.cjs +1013 -69
- package/dist/generation/index.cjs.map +1 -1
- package/dist/generation/index.d.cts +474 -13
- package/dist/generation/index.d.ts +474 -13
- package/dist/generation/index.js +976 -32
- package/dist/generation/index.js.map +1 -1
- package/dist/image-editor/index.cjs +3385 -1275
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +693 -128
- package/dist/image-editor/index.d.ts +693 -128
- package/dist/image-editor/index.js +3325 -1215
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{index-fJrlkJCd.d.ts → index-B273Zllk.d.ts} +500 -7
- package/dist/{index-BhJBSm2d.d.cts → index-jcJwmBYt.d.cts} +500 -7
- package/dist/index.cjs +1603 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +154 -27
- package/dist/index.d.ts +154 -27
- package/dist/index.js +1584 -26
- package/dist/index.js.map +1 -1
- package/dist/mention-text-CDnCFd3c.d.cts +53 -0
- package/dist/mention-text-CDnCFd3c.d.ts +53 -0
- package/dist/model-C1zApQM8.d.cts +219 -0
- package/dist/model-C1zApQM8.d.ts +219 -0
- package/dist/persistence/index.d.cts +3 -120
- package/dist/persistence/index.d.ts +3 -120
- package/dist/registry-CED5C0lA.d.cts +204 -0
- package/dist/registry-CED5C0lA.d.ts +204 -0
- package/dist/{registry-GJI4gToU.d.cts → registry-CEgwXED1.d.cts} +12 -1
- package/dist/{registry-GJI4gToU.d.ts → registry-CEgwXED1.d.ts} +12 -1
- package/dist/{registry-D32LpIc4.d.cts → registry-D0GADKc7.d.cts} +1 -1
- package/dist/{registry-evKTP4ls.d.ts → registry-DhVUZioj.d.ts} +1 -1
- package/dist/serializers/index.cjs +12 -4
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.d.cts +41 -13
- package/dist/serializers/index.d.ts +41 -13
- package/dist/serializers/index.js +12 -4
- package/dist/spreadsheet/index.cjs +157 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +534 -11
- package/dist/spreadsheet/index.d.ts +534 -11
- package/dist/spreadsheet/index.js +157 -3
- package/dist/storage-BpFfspHm.d.cts +120 -0
- package/dist/storage-BpFfspHm.d.ts +120 -0
- package/dist/tokens/index.cjs +115 -0
- package/dist/tokens/index.cjs.map +1 -0
- package/dist/tokens/index.d.cts +212 -0
- package/dist/tokens/index.d.ts +212 -0
- package/dist/tokens/index.js +115 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/{track-changes-BK5sVf4_.d.cts → track-changes-D_VAPELi.d.cts} +95 -11
- package/dist/{track-changes-CDjCrwKe.d.ts → track-changes-Db_fGEvx.d.ts} +95 -11
- package/package.json +15 -1
- package/dist/chunk-3CN2WD3X.js.map +0 -1
- package/dist/chunk-5S3Z4PPF.js.map +0 -1
- package/dist/chunk-D27YFC46.cjs.map +0 -1
- package/dist/chunk-FODNLX5N.js.map +0 -1
- package/dist/chunk-ITBSKI26.js.map +0 -1
- package/dist/chunk-MA2F5KHF.cjs +0 -3223
- package/dist/chunk-MA2F5KHF.cjs.map +0 -1
- package/dist/chunk-MCSJFWAO.cjs.map +0 -1
- package/dist/chunk-OLZJXL4R.cjs.map +0 -1
- package/dist/chunk-PGNZKFQS.js.map +0 -1
- package/dist/chunk-SBCZ6RN5.cjs.map +0 -1
- package/dist/chunk-U5KWZU4X.js +0 -3223
- package/dist/chunk-U5KWZU4X.js.map +0 -1
- package/dist/chunk-XNORY7M6.cjs.map +0 -1
- package/dist/controller-BhLLAoi8.d.cts +0 -1000
- package/dist/controller-BhLLAoi8.d.ts +0 -1000
- package/dist/types-DX4Mh4SL.d.cts +0 -217
- package/dist/types-DX4Mh4SL.d.ts +0 -217
- /package/dist/{chunk-3LV6RRPH.js.map → chunk-MHEPLBFB.js.map} +0 -0
|
@@ -0,0 +1,1696 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var _chunk3CC7OPUQcjs = require('./chunk-3CC7OPUQ.cjs');
|
|
7
|
+
|
|
8
|
+
// src/export/images.ts
|
|
9
|
+
var DOCX_IMAGE_TYPES = {
|
|
10
|
+
"image/png": "png",
|
|
11
|
+
"image/jpeg": "jpeg",
|
|
12
|
+
"image/jpg": "jpeg",
|
|
13
|
+
"image/gif": "gif",
|
|
14
|
+
"image/bmp": "bmp",
|
|
15
|
+
"image/webp": "webp",
|
|
16
|
+
"image/tiff": "tiff"
|
|
17
|
+
};
|
|
18
|
+
var DOCX_IMAGE_CONTENT_TYPES = {
|
|
19
|
+
png: "image/png",
|
|
20
|
+
jpeg: "image/jpeg",
|
|
21
|
+
gif: "image/gif",
|
|
22
|
+
bmp: "image/bmp",
|
|
23
|
+
webp: "image/webp",
|
|
24
|
+
tiff: "image/tiff"
|
|
25
|
+
};
|
|
26
|
+
var MAX_DATA_URL = 64 * 1024 * 1024;
|
|
27
|
+
function decodeDataUrl(src) {
|
|
28
|
+
if (src.length > MAX_DATA_URL) return null;
|
|
29
|
+
const comma = src.indexOf(",");
|
|
30
|
+
if (comma === -1) return null;
|
|
31
|
+
const header = /^data:([a-z0-9.+-]+\/[a-z0-9.+-]+)((?:;[a-z0-9-]+=[^;,]*)*);base64$/i.exec(src.slice(0, comma));
|
|
32
|
+
if (!header) return null;
|
|
33
|
+
const payload = src.slice(comma + 1).replace(/\s+/g, "");
|
|
34
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(payload)) return null;
|
|
35
|
+
try {
|
|
36
|
+
const binary = atob(payload);
|
|
37
|
+
const bytes = new Uint8Array(binary.length);
|
|
38
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
39
|
+
return { mime: header[1].toLowerCase(), bytes };
|
|
40
|
+
} catch (e) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
var u16be = (b, i) => b[i] << 8 | b[i + 1];
|
|
45
|
+
var u16le = (b, i) => b[i] | b[i + 1] << 8;
|
|
46
|
+
var u32be = (b, i) => (b[i] << 24 | b[i + 1] << 16 | b[i + 2] << 8 | b[i + 3]) >>> 0;
|
|
47
|
+
var i32le = (b, i) => b[i] | b[i + 1] << 8 | b[i + 2] << 16 | b[i + 3] << 24;
|
|
48
|
+
function imagePixelSize(b) {
|
|
49
|
+
const ok = (width, height) => width > 0 && height > 0 && width < 1e6 && height < 1e6 ? { width, height } : null;
|
|
50
|
+
if (b.length >= 24 && b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71) {
|
|
51
|
+
return ok(u32be(b, 16), u32be(b, 20));
|
|
52
|
+
}
|
|
53
|
+
if (b.length >= 10 && b[0] === 71 && b[1] === 73 && b[2] === 70) return ok(u16le(b, 6), u16le(b, 8));
|
|
54
|
+
if (b.length >= 26 && b[0] === 66 && b[1] === 77) return ok(Math.abs(i32le(b, 18)), Math.abs(i32le(b, 22)));
|
|
55
|
+
if (b.length >= 30 && b[0] === 82 && b[1] === 73 && b[8] === 87 && b[9] === 69) {
|
|
56
|
+
const chunk = String.fromCharCode(b[12], b[13], b[14], b[15]);
|
|
57
|
+
if (chunk === "VP8 ") return ok(u16le(b, 26) & 16383, u16le(b, 28) & 16383);
|
|
58
|
+
if (chunk === "VP8L") {
|
|
59
|
+
const bits = b[21] | b[22] << 8 | b[23] << 16 | b[24] << 24;
|
|
60
|
+
return ok((bits & 16383) + 1, (bits >>> 14 & 16383) + 1);
|
|
61
|
+
}
|
|
62
|
+
if (chunk === "VP8X") return ok((b[24] | b[25] << 8 | b[26] << 16) + 1, (b[27] | b[28] << 8 | b[29] << 16) + 1);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
if (b.length >= 4 && b[0] === 255 && b[1] === 216) {
|
|
66
|
+
let i = 2;
|
|
67
|
+
while (i + 9 < b.length) {
|
|
68
|
+
if (b[i] !== 255) return null;
|
|
69
|
+
const marker = b[i + 1];
|
|
70
|
+
if (marker === 216 || marker === 1 || marker >= 208 && marker <= 215) {
|
|
71
|
+
i += 2;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const length = u16be(b, i + 2);
|
|
75
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) {
|
|
76
|
+
return ok(u16be(b, i + 7), u16be(b, i + 5));
|
|
77
|
+
}
|
|
78
|
+
if (length < 2) return null;
|
|
79
|
+
i += 2 + length;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
function pixelAttr(value) {
|
|
85
|
+
if (typeof value === "number") return Number.isFinite(value) && value > 0 ? value : void 0;
|
|
86
|
+
if (typeof value !== "string") return void 0;
|
|
87
|
+
const match = /^\s*(\d+(?:\.\d+)?)\s*(px)?\s*$/i.exec(value);
|
|
88
|
+
return match ? Number(match[1]) || void 0 : void 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/export/units.ts
|
|
92
|
+
var DOCX_BASE_FONT_PT = 11;
|
|
93
|
+
var MAX_LEN_PT = 1584;
|
|
94
|
+
var UNIT_PT = {
|
|
95
|
+
pt: 1,
|
|
96
|
+
px: 0.75,
|
|
97
|
+
in: 72,
|
|
98
|
+
cm: 72 / 2.54,
|
|
99
|
+
mm: 72 / 25.4,
|
|
100
|
+
pc: 12
|
|
101
|
+
};
|
|
102
|
+
function cssLengthToPt(value, basePt = DOCX_BASE_FONT_PT) {
|
|
103
|
+
if (typeof value === "number") return Number.isFinite(value) ? clampPt(value * UNIT_PT.px) : void 0;
|
|
104
|
+
if (typeof value !== "string") return void 0;
|
|
105
|
+
const match = /^\s*(-?\d+(?:\.\d+)?|-?\.\d+)\s*([a-z%]*)\s*$/i.exec(value);
|
|
106
|
+
if (!match) return void 0;
|
|
107
|
+
const n = Number(match[1]);
|
|
108
|
+
const unit = match[2].toLowerCase() || "px";
|
|
109
|
+
let pt;
|
|
110
|
+
if (unit === "em" || unit === "rem") pt = n * basePt;
|
|
111
|
+
else if (unit === "%") pt = n / 100 * basePt;
|
|
112
|
+
else if (unit in UNIT_PT) pt = n * UNIT_PT[unit];
|
|
113
|
+
return pt === void 0 || !Number.isFinite(pt) ? void 0 : clampPt(pt);
|
|
114
|
+
}
|
|
115
|
+
function clampPt(pt) {
|
|
116
|
+
return Math.max(-MAX_LEN_PT, Math.min(MAX_LEN_PT, pt));
|
|
117
|
+
}
|
|
118
|
+
var ptToTwips = (pt) => Math.round(pt * 20);
|
|
119
|
+
var ptToHalfPoints = (pt) => Math.max(1, Math.min(3276, Math.round(pt * 2)));
|
|
120
|
+
var pxToEmu = (px) => Math.round(px * 9525);
|
|
121
|
+
var pxToTwips = (px) => Math.round(px * 15);
|
|
122
|
+
var NAMED_COLORS = {
|
|
123
|
+
black: "000000",
|
|
124
|
+
white: "FFFFFF",
|
|
125
|
+
red: "FF0000",
|
|
126
|
+
green: "008000",
|
|
127
|
+
lime: "00FF00",
|
|
128
|
+
blue: "0000FF",
|
|
129
|
+
yellow: "FFFF00",
|
|
130
|
+
cyan: "00FFFF",
|
|
131
|
+
aqua: "00FFFF",
|
|
132
|
+
magenta: "FF00FF",
|
|
133
|
+
fuchsia: "FF00FF",
|
|
134
|
+
gray: "808080",
|
|
135
|
+
grey: "808080",
|
|
136
|
+
silver: "C0C0C0",
|
|
137
|
+
maroon: "800000",
|
|
138
|
+
navy: "000080",
|
|
139
|
+
olive: "808000",
|
|
140
|
+
purple: "800080",
|
|
141
|
+
teal: "008080",
|
|
142
|
+
orange: "FFA500",
|
|
143
|
+
pink: "FFC0CB"
|
|
144
|
+
};
|
|
145
|
+
function cssColorToHex(value) {
|
|
146
|
+
if (typeof value !== "string") return void 0;
|
|
147
|
+
const color = value.trim().toLowerCase();
|
|
148
|
+
if (color in NAMED_COLORS) return NAMED_COLORS[color];
|
|
149
|
+
let match = /^#([0-9a-f]{3,4})$/.exec(color);
|
|
150
|
+
if (match) return match[1].slice(0, 3).split("").map((c) => c + c).join("").toUpperCase();
|
|
151
|
+
match = /^#([0-9a-f]{6})(?:[0-9a-f]{2})?$/.exec(color);
|
|
152
|
+
if (match) return match[1].toUpperCase();
|
|
153
|
+
match = /^rgba?\(\s*(\d{1,3})\s*[, ]\s*(\d{1,3})\s*[, ]\s*(\d{1,3})\s*(?:[,/]\s*[\d.]+%?\s*)?\)$/.exec(color);
|
|
154
|
+
if (match) {
|
|
155
|
+
return match.slice(1, 4).map((n) => Math.min(255, Number(n)).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
156
|
+
}
|
|
157
|
+
return void 0;
|
|
158
|
+
}
|
|
159
|
+
var WORD_HIGHLIGHTS = {
|
|
160
|
+
FFFF00: "yellow",
|
|
161
|
+
"00FF00": "green",
|
|
162
|
+
"00FFFF": "cyan",
|
|
163
|
+
FF00FF: "magenta",
|
|
164
|
+
"0000FF": "blue",
|
|
165
|
+
FF0000: "red",
|
|
166
|
+
"000080": "darkBlue",
|
|
167
|
+
"008080": "darkCyan",
|
|
168
|
+
"008000": "darkGreen",
|
|
169
|
+
"800080": "darkMagenta",
|
|
170
|
+
"800000": "darkRed",
|
|
171
|
+
"808000": "darkYellow",
|
|
172
|
+
"808080": "darkGray",
|
|
173
|
+
C0C0C0: "lightGray",
|
|
174
|
+
"000000": "black",
|
|
175
|
+
FFFFFF: "white"
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/export/xml.ts
|
|
179
|
+
var INVALID_XML_CHARS = /[^\t\n\r --�\u{10000}-\u{10FFFF}]/gu;
|
|
180
|
+
function stripInvalidXmlChars(value) {
|
|
181
|
+
return value.replace(INVALID_XML_CHARS, "");
|
|
182
|
+
}
|
|
183
|
+
function escapeXmlText(value) {
|
|
184
|
+
return stripInvalidXmlChars(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
185
|
+
}
|
|
186
|
+
function escapeXmlAttr(value) {
|
|
187
|
+
return escapeXmlText(value).replace(/"/g, """).replace(/'/g, "'").replace(/\t/g, "	").replace(/\n/g, " ").replace(/\r/g, " ");
|
|
188
|
+
}
|
|
189
|
+
function attrs(values) {
|
|
190
|
+
if (!values) return "";
|
|
191
|
+
let out = "";
|
|
192
|
+
for (const [name, value] of Object.entries(values)) {
|
|
193
|
+
if (value === void 0 || value === null || value === false) continue;
|
|
194
|
+
out += ` ${name}="${escapeXmlAttr(String(value))}"`;
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
var XmlWriter = class {
|
|
199
|
+
|
|
200
|
+
/** `declaration: false` writes a fragment (e.g. one paragraph). */
|
|
201
|
+
constructor(declaration = true) {
|
|
202
|
+
this.parts = declaration ? ['<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n'] : [];
|
|
203
|
+
}
|
|
204
|
+
open(name, values) {
|
|
205
|
+
this.parts.push(`<${name}${attrs(values)}>`);
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
empty(name, values) {
|
|
209
|
+
this.parts.push(`<${name}${attrs(values)}/>`);
|
|
210
|
+
return this;
|
|
211
|
+
}
|
|
212
|
+
close(name) {
|
|
213
|
+
this.parts.push(`</${name}>`);
|
|
214
|
+
return this;
|
|
215
|
+
}
|
|
216
|
+
text(value) {
|
|
217
|
+
this.parts.push(escapeXmlText(value));
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
/** `<name attrs>text</name>`. */
|
|
221
|
+
leaf(name, values, text) {
|
|
222
|
+
return this.open(name, values).text(text).close(name);
|
|
223
|
+
}
|
|
224
|
+
/** `<name w:val="value"/>`. */
|
|
225
|
+
val(name, value) {
|
|
226
|
+
return this.empty(name, { "w:val": value });
|
|
227
|
+
}
|
|
228
|
+
/** Appends markup produced by another writer. */
|
|
229
|
+
raw(markup) {
|
|
230
|
+
this.parts.push(markup);
|
|
231
|
+
return this;
|
|
232
|
+
}
|
|
233
|
+
toString() {
|
|
234
|
+
return this.parts.join("");
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// src/export/zip-writer.ts
|
|
239
|
+
var encoder = new TextEncoder();
|
|
240
|
+
var MAX_SIZE = 4294967295;
|
|
241
|
+
async function readAll(readable) {
|
|
242
|
+
const reader = readable.getReader();
|
|
243
|
+
const chunks = [];
|
|
244
|
+
let length = 0;
|
|
245
|
+
for (; ; ) {
|
|
246
|
+
const { done, value } = await reader.read();
|
|
247
|
+
if (done) break;
|
|
248
|
+
chunks.push(value);
|
|
249
|
+
length += value.length;
|
|
250
|
+
}
|
|
251
|
+
const out = new Uint8Array(length);
|
|
252
|
+
let pos = 0;
|
|
253
|
+
for (const chunk of chunks) {
|
|
254
|
+
out.set(chunk, pos);
|
|
255
|
+
pos += chunk.length;
|
|
256
|
+
}
|
|
257
|
+
return out;
|
|
258
|
+
}
|
|
259
|
+
async function deflateRaw(data) {
|
|
260
|
+
const Stream = globalThis.CompressionStream;
|
|
261
|
+
if (typeof Stream !== "function") return null;
|
|
262
|
+
let stream;
|
|
263
|
+
try {
|
|
264
|
+
stream = new Stream("deflate-raw");
|
|
265
|
+
} catch (e2) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
const writer = stream.writable.getWriter();
|
|
269
|
+
const written = writer.write(data).then(() => writer.close()).catch(() => {
|
|
270
|
+
});
|
|
271
|
+
const out = await readAll(stream.readable);
|
|
272
|
+
await written;
|
|
273
|
+
return out;
|
|
274
|
+
}
|
|
275
|
+
function dosDateTime(date) {
|
|
276
|
+
const year = Math.min(Math.max(date.getUTCFullYear(), 1980), 2107);
|
|
277
|
+
return {
|
|
278
|
+
time: date.getUTCHours() << 11 | date.getUTCMinutes() << 5 | Math.floor(date.getUTCSeconds() / 2),
|
|
279
|
+
date: year - 1980 << 9 | date.getUTCMonth() + 1 << 5 | date.getUTCDate()
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
var ByteSink = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
|
|
283
|
+
__init() {this.chunks = []}
|
|
284
|
+
__init2() {this.length = 0}
|
|
285
|
+
bytes(data) {
|
|
286
|
+
this.chunks.push(data);
|
|
287
|
+
this.length += data.length;
|
|
288
|
+
}
|
|
289
|
+
header(fields) {
|
|
290
|
+
const size = fields.reduce((n, [, width]) => n + width, 0);
|
|
291
|
+
const buffer = new Uint8Array(size);
|
|
292
|
+
const view = new DataView(buffer.buffer);
|
|
293
|
+
let pos = 0;
|
|
294
|
+
for (const [value, width] of fields) {
|
|
295
|
+
if (width === 2) view.setUint16(pos, value, true);
|
|
296
|
+
else view.setUint32(pos, value >>> 0, true);
|
|
297
|
+
pos += width;
|
|
298
|
+
}
|
|
299
|
+
this.bytes(buffer);
|
|
300
|
+
}
|
|
301
|
+
toUint8Array() {
|
|
302
|
+
const out = new Uint8Array(this.length);
|
|
303
|
+
let pos = 0;
|
|
304
|
+
for (const chunk of this.chunks) {
|
|
305
|
+
out.set(chunk, pos);
|
|
306
|
+
pos += chunk.length;
|
|
307
|
+
}
|
|
308
|
+
return out;
|
|
309
|
+
}
|
|
310
|
+
}, _class);
|
|
311
|
+
async function writeZip(entries, options = {}) {
|
|
312
|
+
if (entries.length > 65535) throw new RangeError("Too many ZIP entries (no ZIP64 support).");
|
|
313
|
+
const { time, date } = dosDateTime(_nullishCoalesce(options.modified, () => ( new Date(Date.UTC(1980, 0, 1)))));
|
|
314
|
+
const out = new ByteSink();
|
|
315
|
+
const central = new ByteSink();
|
|
316
|
+
const seen = /* @__PURE__ */ new Set();
|
|
317
|
+
for (const entry of entries) {
|
|
318
|
+
const name = entry.name;
|
|
319
|
+
if (!name || name.startsWith("/") || name.includes("\\") || name.split("/").includes("..") || name.includes("\0")) {
|
|
320
|
+
throw new Error(`Unsafe ZIP entry name: ${JSON.stringify(name)}`);
|
|
321
|
+
}
|
|
322
|
+
if (seen.has(name)) throw new Error(`Duplicate ZIP entry name: ${JSON.stringify(name)}`);
|
|
323
|
+
seen.add(name);
|
|
324
|
+
const raw = typeof entry.data === "string" ? encoder.encode(entry.data) : entry.data;
|
|
325
|
+
const deflated = options.compression === "store" || raw.length === 0 ? null : await deflateRaw(raw);
|
|
326
|
+
const useDeflate = !!deflated && deflated.length < raw.length;
|
|
327
|
+
const body = useDeflate ? deflated : raw;
|
|
328
|
+
const method = useDeflate ? 8 : 0;
|
|
329
|
+
const nameBytes = encoder.encode(name);
|
|
330
|
+
const crc = _chunk3CC7OPUQcjs.zipCrc32.call(void 0, raw);
|
|
331
|
+
const offset = out.length;
|
|
332
|
+
if (body.length > MAX_SIZE || raw.length > MAX_SIZE || offset > MAX_SIZE) {
|
|
333
|
+
throw new RangeError("ZIP archive too large (no ZIP64 support).");
|
|
334
|
+
}
|
|
335
|
+
const flags = 2048;
|
|
336
|
+
out.header([
|
|
337
|
+
[67324752, 4],
|
|
338
|
+
[20, 2],
|
|
339
|
+
[flags, 2],
|
|
340
|
+
[method, 2],
|
|
341
|
+
[time, 2],
|
|
342
|
+
[date, 2],
|
|
343
|
+
[crc, 4],
|
|
344
|
+
[body.length, 4],
|
|
345
|
+
[raw.length, 4],
|
|
346
|
+
[nameBytes.length, 2],
|
|
347
|
+
[0, 2]
|
|
348
|
+
]);
|
|
349
|
+
out.bytes(nameBytes);
|
|
350
|
+
out.bytes(body);
|
|
351
|
+
central.header([
|
|
352
|
+
[33639248, 4],
|
|
353
|
+
[20, 2],
|
|
354
|
+
[20, 2],
|
|
355
|
+
[flags, 2],
|
|
356
|
+
[method, 2],
|
|
357
|
+
[time, 2],
|
|
358
|
+
[date, 2],
|
|
359
|
+
[crc, 4],
|
|
360
|
+
[body.length, 4],
|
|
361
|
+
[raw.length, 4],
|
|
362
|
+
[nameBytes.length, 2],
|
|
363
|
+
[0, 2],
|
|
364
|
+
[0, 2],
|
|
365
|
+
[0, 2],
|
|
366
|
+
[0, 2],
|
|
367
|
+
[0, 4],
|
|
368
|
+
[offset, 4]
|
|
369
|
+
]);
|
|
370
|
+
central.bytes(nameBytes);
|
|
371
|
+
}
|
|
372
|
+
const cdOffset = out.length;
|
|
373
|
+
const cd = central.toUint8Array();
|
|
374
|
+
out.bytes(cd);
|
|
375
|
+
out.header([
|
|
376
|
+
[101010256, 4],
|
|
377
|
+
[0, 2],
|
|
378
|
+
[0, 2],
|
|
379
|
+
[entries.length, 2],
|
|
380
|
+
[entries.length, 2],
|
|
381
|
+
[cd.length, 4],
|
|
382
|
+
[cdOffset, 4],
|
|
383
|
+
[0, 2]
|
|
384
|
+
]);
|
|
385
|
+
return out.toUint8Array();
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/export/docx.ts
|
|
389
|
+
var DOCX_EXPORT_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
390
|
+
var NS = {
|
|
391
|
+
w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
|
|
392
|
+
r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
|
|
393
|
+
wp: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
|
|
394
|
+
a: "http://schemas.openxmlformats.org/drawingml/2006/main",
|
|
395
|
+
pic: "http://schemas.openxmlformats.org/drawingml/2006/picture",
|
|
396
|
+
mc: "http://schemas.openxmlformats.org/markup-compatibility/2006",
|
|
397
|
+
w14: "http://schemas.microsoft.com/office/word/2010/wordml",
|
|
398
|
+
w15: "http://schemas.microsoft.com/office/word/2012/wordml"
|
|
399
|
+
};
|
|
400
|
+
var BODY_NS = {
|
|
401
|
+
"xmlns:w": NS.w,
|
|
402
|
+
"xmlns:r": NS.r,
|
|
403
|
+
"xmlns:wp": NS.wp,
|
|
404
|
+
"xmlns:a": NS.a,
|
|
405
|
+
"xmlns:pic": NS.pic,
|
|
406
|
+
"xmlns:mc": NS.mc,
|
|
407
|
+
"xmlns:w14": NS.w14,
|
|
408
|
+
"xmlns:w15": NS.w15,
|
|
409
|
+
"mc:Ignorable": "w14 w15"
|
|
410
|
+
};
|
|
411
|
+
var REL = {
|
|
412
|
+
officeDocument: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
|
|
413
|
+
core: "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
|
|
414
|
+
app: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
|
|
415
|
+
styles: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
|
|
416
|
+
numbering: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
|
|
417
|
+
settings: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
|
|
418
|
+
comments: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
|
|
419
|
+
commentsExtended: "http://schemas.microsoft.com/office/2011/relationships/commentsExtended",
|
|
420
|
+
people: "http://schemas.microsoft.com/office/2011/relationships/people",
|
|
421
|
+
image: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
|
422
|
+
hyperlink: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
|
423
|
+
};
|
|
424
|
+
var CT_WML = "application/vnd.openxmlformats-officedocument.wordprocessingml.";
|
|
425
|
+
var CONTENT_WIDTH_TWIPS = 9360;
|
|
426
|
+
var MAX_IMAGE_WIDTH_PX = 624;
|
|
427
|
+
var INDENT_STEP = 720;
|
|
428
|
+
var DOCX_ANONYMOUS_AUTHOR = "Author";
|
|
429
|
+
var ANONYMOUS_INITIALS = "A";
|
|
430
|
+
var MAX_DEPTH = 64;
|
|
431
|
+
var BULLETS = ["\u2022", "\u25E6", "\u25AA"];
|
|
432
|
+
var BULLET_FONTS = ["Symbol", "Courier New", "Wingdings"];
|
|
433
|
+
var TASK_UNCHECKED = "\u2610";
|
|
434
|
+
var TASK_CHECKED = "\u2612";
|
|
435
|
+
var FORMAT_MARKS = /* @__PURE__ */ new Set([
|
|
436
|
+
"bold",
|
|
437
|
+
"italic",
|
|
438
|
+
"underline",
|
|
439
|
+
"strike",
|
|
440
|
+
"subscript",
|
|
441
|
+
"superscript",
|
|
442
|
+
"code",
|
|
443
|
+
"textStyle",
|
|
444
|
+
"highlight",
|
|
445
|
+
"characterStyle"
|
|
446
|
+
]);
|
|
447
|
+
var STRUCTURAL_MARKS = /* @__PURE__ */ new Set(["link", "insertion", "deletion", "formatChange", "comment", "bookmark"]);
|
|
448
|
+
var isEditorLike = (value) => !!value && typeof value.getJSON === "function";
|
|
449
|
+
function threadsOf(source) {
|
|
450
|
+
if (!source) return [];
|
|
451
|
+
if (Array.isArray(source)) return [...source];
|
|
452
|
+
const value = source;
|
|
453
|
+
if (typeof value.toJSON === "function") return [..._nullishCoalesce(_optionalChain([value, 'access', _ => _.toJSON, 'call', _2 => _2(), 'optionalAccess', _3 => _3.threads]), () => ( []))];
|
|
454
|
+
if (typeof value.getSnapshot === "function") return [..._nullishCoalesce(_optionalChain([value, 'access', _4 => _4.getSnapshot, 'call', _5 => _5(), 'optionalAccess', _6 => _6.threads]), () => ( []))];
|
|
455
|
+
return Array.isArray(value.threads) ? [...value.threads] : [];
|
|
456
|
+
}
|
|
457
|
+
function stylesOf(source) {
|
|
458
|
+
if (!source) return { styles: _chunk3CC7OPUQcjs.DEFAULT_STYLES.map((s) => ({ ...s })), defaults: {} };
|
|
459
|
+
if (Array.isArray(source)) return { styles: [...source], defaults: {} };
|
|
460
|
+
const value = source;
|
|
461
|
+
const json = typeof value.toJSON === "function" ? value.toJSON() : value;
|
|
462
|
+
return { styles: [..._nullishCoalesce(json.styles, () => ( []))], defaults: _nullishCoalesce(json.defaults, () => ( {})) };
|
|
463
|
+
}
|
|
464
|
+
function authorOf(author) {
|
|
465
|
+
if (!author) return void 0;
|
|
466
|
+
return typeof author === "string" ? { id: author, name: author } : author;
|
|
467
|
+
}
|
|
468
|
+
function isoDate(ms) {
|
|
469
|
+
const n = typeof ms === "number" ? ms : Number(ms);
|
|
470
|
+
if (!Number.isFinite(n) || n <= 0) return void 0;
|
|
471
|
+
const date = new Date(n);
|
|
472
|
+
return Number.isNaN(date.getTime()) ? void 0 : date.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
473
|
+
}
|
|
474
|
+
function initialsOf(name) {
|
|
475
|
+
const letters = name.split(/\s+/).filter(Boolean).map((word) => _nullishCoalesce(Array.from(word)[0], () => ( ""))).join("").slice(0, 3).toUpperCase();
|
|
476
|
+
return letters || ANONYMOUS_INITIALS;
|
|
477
|
+
}
|
|
478
|
+
function fileStyleName(name) {
|
|
479
|
+
const heading = /^Heading ([1-9])$/.exec(name);
|
|
480
|
+
return heading ? `heading ${heading[1]}` : name;
|
|
481
|
+
}
|
|
482
|
+
var truncate = (value, max = 80) => value.length > max ? `${value.slice(0, max - 1)}\u2026` : value;
|
|
483
|
+
function runFormatOf(marks) {
|
|
484
|
+
const format = {};
|
|
485
|
+
for (const mark of _nullishCoalesce(marks, () => ( []))) {
|
|
486
|
+
const attrs2 = _nullishCoalesce(mark.attrs, () => ( {}));
|
|
487
|
+
switch (mark.type) {
|
|
488
|
+
case "bold":
|
|
489
|
+
format.bold = true;
|
|
490
|
+
break;
|
|
491
|
+
case "italic":
|
|
492
|
+
format.italic = true;
|
|
493
|
+
break;
|
|
494
|
+
case "underline":
|
|
495
|
+
format.underline = true;
|
|
496
|
+
break;
|
|
497
|
+
case "strike":
|
|
498
|
+
format.strike = true;
|
|
499
|
+
break;
|
|
500
|
+
case "subscript":
|
|
501
|
+
format.vertAlign = "subscript";
|
|
502
|
+
break;
|
|
503
|
+
case "superscript":
|
|
504
|
+
format.vertAlign = "superscript";
|
|
505
|
+
break;
|
|
506
|
+
case "code":
|
|
507
|
+
format.font = "Consolas";
|
|
508
|
+
break;
|
|
509
|
+
case "textStyle": {
|
|
510
|
+
const color = cssColorToHex(attrs2.color);
|
|
511
|
+
if (color) format.color = color;
|
|
512
|
+
const pt = cssLengthToPt(attrs2.fontSize);
|
|
513
|
+
if (pt !== void 0 && pt > 0) format.halfPoints = ptToHalfPoints(pt);
|
|
514
|
+
if (typeof attrs2.fontFamily === "string" && attrs2.fontFamily.trim()) {
|
|
515
|
+
format.font = attrs2.fontFamily.split(",")[0].trim().replace(/^["']|["']$/g, "");
|
|
516
|
+
}
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
case "highlight": {
|
|
520
|
+
const color = attrs2.color ? cssColorToHex(attrs2.color) : "FFFF00";
|
|
521
|
+
if (color && WORD_HIGHLIGHTS[color]) format.highlight = WORD_HIGHLIGHTS[color];
|
|
522
|
+
else if (color) format.shading = color;
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
case "characterStyle":
|
|
526
|
+
if (_chunk3CC7OPUQcjs.isValidStyleId.call(void 0, attrs2.styleId)) format.charStyle = attrs2.styleId;
|
|
527
|
+
break;
|
|
528
|
+
case "link":
|
|
529
|
+
format.charStyle ??= "Hyperlink";
|
|
530
|
+
break;
|
|
531
|
+
default:
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return format;
|
|
536
|
+
}
|
|
537
|
+
function writeRunProps(w, f) {
|
|
538
|
+
if (f.charStyle) w.val("w:rStyle", f.charStyle);
|
|
539
|
+
if (f.font) w.empty("w:rFonts", { "w:ascii": f.font, "w:hAnsi": f.font, "w:cs": f.font, "w:eastAsia": f.font });
|
|
540
|
+
if (f.bold) w.empty("w:b");
|
|
541
|
+
if (f.italic) w.empty("w:i");
|
|
542
|
+
if (f.strike) w.empty("w:strike");
|
|
543
|
+
if (f.color) w.val("w:color", f.color);
|
|
544
|
+
if (f.halfPoints) {
|
|
545
|
+
w.val("w:sz", f.halfPoints);
|
|
546
|
+
w.val("w:szCs", f.halfPoints);
|
|
547
|
+
}
|
|
548
|
+
if (f.highlight) w.val("w:highlight", f.highlight);
|
|
549
|
+
if (f.underline) w.val("w:u", "single");
|
|
550
|
+
if (f.shading) w.empty("w:shd", { "w:val": "clear", "w:color": "auto", "w:fill": f.shading });
|
|
551
|
+
if (f.vertAlign) w.val("w:vertAlign", f.vertAlign);
|
|
552
|
+
}
|
|
553
|
+
var hasRunProps = (f) => Object.values(f).some((v) => v !== void 0 && v !== false);
|
|
554
|
+
function characterFormatToRun(c) {
|
|
555
|
+
const f = {};
|
|
556
|
+
if (!c) return f;
|
|
557
|
+
if (c.fontFamily) f.font = c.fontFamily.split(",")[0].trim().replace(/^["']|["']$/g, "");
|
|
558
|
+
if (c.bold) f.bold = true;
|
|
559
|
+
if (c.italic) f.italic = true;
|
|
560
|
+
if (c.underline) f.underline = true;
|
|
561
|
+
if (c.strike) f.strike = true;
|
|
562
|
+
const color = cssColorToHex(c.color);
|
|
563
|
+
if (color) f.color = color;
|
|
564
|
+
const pt = cssLengthToPt(c.fontSize);
|
|
565
|
+
if (pt !== void 0 && pt > 0) f.halfPoints = ptToHalfPoints(pt);
|
|
566
|
+
const background = cssColorToHex(c.backgroundColor);
|
|
567
|
+
if (background) f.shading = background;
|
|
568
|
+
return f;
|
|
569
|
+
}
|
|
570
|
+
function writeParagraphFormat(w, p, outline) {
|
|
571
|
+
if (!p && outline === void 0) return;
|
|
572
|
+
const before = cssLengthToPt(_optionalChain([p, 'optionalAccess', _7 => _7.spaceBefore]));
|
|
573
|
+
const after = cssLengthToPt(_optionalChain([p, 'optionalAccess', _8 => _8.spaceAfter]));
|
|
574
|
+
const lineValue = _optionalChain([p, 'optionalAccess', _9 => _9.lineHeight]);
|
|
575
|
+
let line;
|
|
576
|
+
let lineRule;
|
|
577
|
+
if (typeof lineValue === "string" && /^\s*\d+(\.\d+)?\s*$/.test(lineValue)) {
|
|
578
|
+
line = Math.round(Number(lineValue) * 240);
|
|
579
|
+
lineRule = "auto";
|
|
580
|
+
} else if (lineValue) {
|
|
581
|
+
const pt = cssLengthToPt(lineValue);
|
|
582
|
+
if (pt !== void 0 && pt > 0) {
|
|
583
|
+
line = ptToTwips(pt);
|
|
584
|
+
lineRule = "atLeast";
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (before !== void 0 || after !== void 0 || line !== void 0) {
|
|
588
|
+
w.empty("w:spacing", {
|
|
589
|
+
"w:before": before !== void 0 ? Math.max(0, ptToTwips(before)) : void 0,
|
|
590
|
+
"w:after": after !== void 0 ? Math.max(0, ptToTwips(after)) : void 0,
|
|
591
|
+
"w:line": line,
|
|
592
|
+
"w:lineRule": lineRule
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
const left = cssLengthToPt(_optionalChain([p, 'optionalAccess', _10 => _10.indentLeft]));
|
|
596
|
+
const right = cssLengthToPt(_optionalChain([p, 'optionalAccess', _11 => _11.indentRight]));
|
|
597
|
+
const first = cssLengthToPt(_optionalChain([p, 'optionalAccess', _12 => _12.indentFirstLine]));
|
|
598
|
+
if (left !== void 0 || right !== void 0 || first !== void 0) {
|
|
599
|
+
w.empty("w:ind", {
|
|
600
|
+
"w:left": left !== void 0 ? ptToTwips(left) : void 0,
|
|
601
|
+
"w:right": right !== void 0 ? ptToTwips(right) : void 0,
|
|
602
|
+
"w:firstLine": first !== void 0 && first >= 0 ? ptToTwips(first) : void 0,
|
|
603
|
+
"w:hanging": first !== void 0 && first < 0 ? ptToTwips(-first) : void 0
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
const jc = alignment(_optionalChain([p, 'optionalAccess', _13 => _13.textAlign]));
|
|
607
|
+
if (jc) w.val("w:jc", jc);
|
|
608
|
+
if (outline !== void 0) w.val("w:outlineLvl", outline);
|
|
609
|
+
}
|
|
610
|
+
function alignment(value) {
|
|
611
|
+
switch (value) {
|
|
612
|
+
case "left":
|
|
613
|
+
return "left";
|
|
614
|
+
case "center":
|
|
615
|
+
return "center";
|
|
616
|
+
case "right":
|
|
617
|
+
return "right";
|
|
618
|
+
case "justify":
|
|
619
|
+
return "both";
|
|
620
|
+
default:
|
|
621
|
+
return void 0;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
var Relationships = (_class2 = class {constructor() { _class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this); }
|
|
625
|
+
__init3() {this.list = []}
|
|
626
|
+
__init4() {this.index = /* @__PURE__ */ new Map()}
|
|
627
|
+
add(type, target, external = false) {
|
|
628
|
+
const key = `${type}
|
|
629
|
+
${target}
|
|
630
|
+
${external}`;
|
|
631
|
+
const existing = this.index.get(key);
|
|
632
|
+
if (existing) return existing;
|
|
633
|
+
const id = `rId${this.list.length + 1}`;
|
|
634
|
+
this.list.push({ id, type, target, external });
|
|
635
|
+
this.index.set(key, id);
|
|
636
|
+
return id;
|
|
637
|
+
}
|
|
638
|
+
get size() {
|
|
639
|
+
return this.list.length;
|
|
640
|
+
}
|
|
641
|
+
xml() {
|
|
642
|
+
const w = new XmlWriter();
|
|
643
|
+
w.open("Relationships", { xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" });
|
|
644
|
+
for (const rel of this.list) {
|
|
645
|
+
w.empty("Relationship", {
|
|
646
|
+
Id: rel.id,
|
|
647
|
+
Type: rel.type,
|
|
648
|
+
Target: rel.target,
|
|
649
|
+
TargetMode: rel.external ? "External" : void 0
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
w.close("Relationships");
|
|
653
|
+
return w.toString();
|
|
654
|
+
}
|
|
655
|
+
}, _class2);
|
|
656
|
+
var DocxBuilder = (_class3 = class {
|
|
657
|
+
constructor(doc, options, threads, styles) {;_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);
|
|
658
|
+
this.doc = doc;
|
|
659
|
+
this.options = options;
|
|
660
|
+
this.threads = threads;
|
|
661
|
+
this.styles = styles;
|
|
662
|
+
this.anonymous = options.privacy === "strip-authors";
|
|
663
|
+
this.defaultAuthor = authorOf(options.author);
|
|
664
|
+
this.styleIds = new Set(styles.styles.filter((s) => _chunk3CC7OPUQcjs.isValidStyleId.call(void 0, s.id)).map((s) => s.id));
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
__init5() {this.report = {
|
|
671
|
+
dropped: [],
|
|
672
|
+
written: { paragraphs: 0, tables: 0, images: 0, comments: 0, replies: 0, trackedChanges: 0 }
|
|
673
|
+
}}
|
|
674
|
+
__init6() {this.rels = new Relationships()}
|
|
675
|
+
__init7() {this.media = []}
|
|
676
|
+
__init8() {this.mediaTypes = /* @__PURE__ */ new Set()}
|
|
677
|
+
__init9() {this.nums = []}
|
|
678
|
+
__init10() {this.revisionId = 0}
|
|
679
|
+
__init11() {this.docPrId = 0}
|
|
680
|
+
__init12() {this.paraIdCounter = 268435456}
|
|
681
|
+
__init13() {this.comments = /* @__PURE__ */ new Map()}
|
|
682
|
+
/** Thread id → JSON node carrying its last comment mark. */
|
|
683
|
+
__init14() {this.commentEnds = /* @__PURE__ */ new Map()}
|
|
684
|
+
/** JSON node → threads whose range ends after it (so ends are found in O(1) per node). */
|
|
685
|
+
__init15() {this.endsByNode = /* @__PURE__ */ new Map()}
|
|
686
|
+
__init16() {this.people = /* @__PURE__ */ new Map()}
|
|
687
|
+
|
|
688
|
+
__init17() {this.extraStyles = /* @__PURE__ */ new Set()}
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
drop(kind, name, reason) {
|
|
692
|
+
const issue = this.report.dropped.find((i) => i.kind === kind && i.name === name && i.reason === reason);
|
|
693
|
+
if (issue) issue.count++;
|
|
694
|
+
else this.report.dropped.push({ kind, name: truncate(name), reason, count: 1 });
|
|
695
|
+
}
|
|
696
|
+
// -- Authors and revisions ------------------------------------------------
|
|
697
|
+
authorName(name, id) {
|
|
698
|
+
if (this.anonymous) return DOCX_ANONYMOUS_AUTHOR;
|
|
699
|
+
const author = typeof name === "string" && name.trim() || typeof id === "string" && id.trim() || _optionalChain([this, 'access', _14 => _14.defaultAuthor, 'optionalAccess', _15 => _15.name]) || "Unknown";
|
|
700
|
+
const authorId = typeof id === "string" && id.trim() || _optionalChain([this, 'access', _16 => _16.defaultAuthor, 'optionalAccess', _17 => _17.id]);
|
|
701
|
+
if (authorId && authorId !== author && !this.people.has(author)) this.people.set(author, authorId);
|
|
702
|
+
return author;
|
|
703
|
+
}
|
|
704
|
+
changeAttrs(attrs2) {
|
|
705
|
+
return {
|
|
706
|
+
"w:id": ++this.revisionId,
|
|
707
|
+
"w:author": this.authorName(attrs2.authorName, attrs2.authorId),
|
|
708
|
+
"w:date": isoDate(attrs2.createdAt)
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
// -- Comments ---------------------------------------------------------------
|
|
712
|
+
prepareComments() {
|
|
713
|
+
const marked = /* @__PURE__ */ new Set();
|
|
714
|
+
const visit = (node, depth) => {
|
|
715
|
+
if (depth > MAX_DEPTH) return;
|
|
716
|
+
for (const mark of _nullishCoalesce(node.marks, () => ( []))) {
|
|
717
|
+
if (mark.type === "comment" && typeof _optionalChain([mark, 'access', _18 => _18.attrs, 'optionalAccess', _19 => _19.commentId]) === "string") {
|
|
718
|
+
marked.add(mark.attrs.commentId);
|
|
719
|
+
this.commentEnds.set(mark.attrs.commentId, node);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
_optionalChain([node, 'access', _20 => _20.content, 'optionalAccess', _21 => _21.forEach, 'call', _22 => _22((child) => visit(child, depth + 1))]);
|
|
723
|
+
};
|
|
724
|
+
visit(this.doc, 0);
|
|
725
|
+
let next = 0;
|
|
726
|
+
for (const thread of this.threads) {
|
|
727
|
+
if (!thread || typeof thread.id !== "string") continue;
|
|
728
|
+
if (!marked.has(thread.id)) {
|
|
729
|
+
this.drop("comment", thread.id, "comment text is not in the document");
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
if (!_optionalChain([thread, 'access', _23 => _23.body, 'optionalAccess', _24 => _24.trim, 'call', _25 => _25()])) {
|
|
733
|
+
this.drop("comment", thread.id, "draft comment without text");
|
|
734
|
+
this.commentEnds.delete(thread.id);
|
|
735
|
+
continue;
|
|
736
|
+
}
|
|
737
|
+
const replies = (_nullishCoalesce(thread.replies, () => ( []))).filter((reply) => reply && _optionalChain([reply, 'access', _26 => _26.body, 'optionalAccess', _27 => _27.trim, 'call', _28 => _28()]));
|
|
738
|
+
const ids = [next++, ...replies.map(() => next++)];
|
|
739
|
+
this.comments.set(thread.id, { thread: { ...thread, replies }, ids, started: false, ended: false });
|
|
740
|
+
}
|
|
741
|
+
for (const [threadId, node] of this.commentEnds) {
|
|
742
|
+
if (!this.comments.has(threadId)) continue;
|
|
743
|
+
const list = _nullishCoalesce(this.endsByNode.get(node), () => ( []));
|
|
744
|
+
list.push(threadId);
|
|
745
|
+
this.endsByNode.set(node, list);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
// -- Document ---------------------------------------------------------------
|
|
749
|
+
documentXml() {
|
|
750
|
+
this.prepareComments();
|
|
751
|
+
const body = new XmlWriter(false);
|
|
752
|
+
const blocks = this.doc.type === "doc" || !this.doc.type ? _nullishCoalesce(this.doc.content, () => ( [])) : [this.doc];
|
|
753
|
+
this.blocks(body, blocks, { depth: 0, quoteLevel: 0 });
|
|
754
|
+
if (!blocks.length || blocks[blocks.length - 1].type === "table") body.empty("w:p");
|
|
755
|
+
for (const [id, entry] of this.comments) if (entry.started && !entry.ended) this.endComment(body, id);
|
|
756
|
+
const w = new XmlWriter();
|
|
757
|
+
w.open("w:document", BODY_NS).open("w:body").raw(body.toString());
|
|
758
|
+
w.open("w:sectPr").empty("w:pgSz", { "w:w": 12240, "w:h": 15840 }).empty("w:pgMar", {
|
|
759
|
+
"w:top": 1440,
|
|
760
|
+
"w:right": 1440,
|
|
761
|
+
"w:bottom": 1440,
|
|
762
|
+
"w:left": 1440,
|
|
763
|
+
"w:header": 720,
|
|
764
|
+
"w:footer": 720,
|
|
765
|
+
"w:gutter": 0
|
|
766
|
+
}).close("w:sectPr");
|
|
767
|
+
w.close("w:body").close("w:document");
|
|
768
|
+
return w.toString();
|
|
769
|
+
}
|
|
770
|
+
blocks(w, nodes, ctx) {
|
|
771
|
+
if (ctx.depth > MAX_DEPTH) {
|
|
772
|
+
this.drop("node", "nesting", `content nested deeper than ${MAX_DEPTH} levels`);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
let first = true;
|
|
776
|
+
nodes.forEach((node, i) => {
|
|
777
|
+
const itemCtx = { ...ctx, depth: ctx.depth + 1, listItemFirst: ctx.list ? first : void 0 };
|
|
778
|
+
this.block(w, node, itemCtx);
|
|
779
|
+
if (node.type !== "bulletList" && node.type !== "orderedList" && node.type !== "taskList") first = false;
|
|
780
|
+
if (node.type === "table" && _optionalChain([nodes, 'access', _29 => _29[i + 1], 'optionalAccess', _30 => _30.type]) === "table") w.empty("w:p");
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
block(w, node, ctx) {
|
|
784
|
+
const type = _nullishCoalesce(node.type, () => ( ""));
|
|
785
|
+
switch (type) {
|
|
786
|
+
case "paragraph":
|
|
787
|
+
this.paragraph(w, node, ctx);
|
|
788
|
+
return;
|
|
789
|
+
case "heading":
|
|
790
|
+
this.paragraph(w, node, ctx, { heading: Math.max(1, Math.min(6, Number(_optionalChain([node, 'access', _31 => _31.attrs, 'optionalAccess', _32 => _32.level])) || 1)) });
|
|
791
|
+
return;
|
|
792
|
+
case "codeBlock":
|
|
793
|
+
this.paragraph(w, node, ctx, { code: true });
|
|
794
|
+
return;
|
|
795
|
+
case "blockquote":
|
|
796
|
+
this.blocks(w, _nullishCoalesce(node.content, () => ( [])), { ...ctx, quoteLevel: ctx.quoteLevel + 1 });
|
|
797
|
+
return;
|
|
798
|
+
case "bulletList":
|
|
799
|
+
case "orderedList":
|
|
800
|
+
case "taskList":
|
|
801
|
+
this.list(w, node, ctx);
|
|
802
|
+
return;
|
|
803
|
+
case "table":
|
|
804
|
+
this.table(w, node, ctx);
|
|
805
|
+
return;
|
|
806
|
+
case "horizontalRule":
|
|
807
|
+
w.open("w:p").open("w:pPr").open("w:pBdr");
|
|
808
|
+
w.empty("w:bottom", { "w:val": "single", "w:sz": 6, "w:space": 1, "w:color": "auto" });
|
|
809
|
+
w.close("w:pBdr").close("w:pPr").close("w:p");
|
|
810
|
+
this.report.written.paragraphs++;
|
|
811
|
+
return;
|
|
812
|
+
case "pageBreak":
|
|
813
|
+
w.open("w:p").open("w:r").empty("w:br", { "w:type": "page" }).close("w:r").close("w:p");
|
|
814
|
+
return;
|
|
815
|
+
case "image":
|
|
816
|
+
this.paragraph(w, { type: "paragraph", content: [node] }, ctx);
|
|
817
|
+
return;
|
|
818
|
+
default:
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
const content = _nullishCoalesce(node.content, () => ( []));
|
|
822
|
+
if (content.some((child) => child.type === "text" || isInlineType(child.type))) {
|
|
823
|
+
this.drop("node", type || "unknown", "written as a plain paragraph");
|
|
824
|
+
this.paragraph(w, { type: "paragraph", content }, ctx);
|
|
825
|
+
} else if (content.length) {
|
|
826
|
+
this.drop("node", type || "unknown", "container flattened");
|
|
827
|
+
this.blocks(w, content, ctx);
|
|
828
|
+
} else {
|
|
829
|
+
this.drop("node", type || "unknown", "unsupported node");
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
// -- Lists --------------------------------------------------------------------
|
|
833
|
+
list(w, node, ctx) {
|
|
834
|
+
const level = Math.min(8, ctx.list ? ctx.list.level + 1 : 0);
|
|
835
|
+
const abstractId = node.type === "orderedList" ? 2 : node.type === "taskList" ? 3 : 1;
|
|
836
|
+
const numId = this.nums.length + 1;
|
|
837
|
+
const start = node.type === "orderedList" ? Number(_nullishCoalesce(_optionalChain([node, 'access', _33 => _33.attrs, 'optionalAccess', _34 => _34.start]), () => ( 1))) : void 0;
|
|
838
|
+
this.nums.push({ numId, abstractId, level, start: start !== void 0 && start !== 1 && Number.isFinite(start) ? start : void 0 });
|
|
839
|
+
for (const item of _nullishCoalesce(node.content, () => ( []))) {
|
|
840
|
+
const task = item.type === "taskItem";
|
|
841
|
+
this.blocks(w, _nullishCoalesce(item.content, () => ( [])), {
|
|
842
|
+
...ctx,
|
|
843
|
+
list: { numId, level, task, checked: task ? !!_optionalChain([item, 'access', _35 => _35.attrs, 'optionalAccess', _36 => _36.checked]) : void 0 }
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
// -- Paragraphs -----------------------------------------------------------------
|
|
848
|
+
styleFor(node, ctx, opts) {
|
|
849
|
+
const own = _optionalChain([node, 'access', _37 => _37.attrs, 'optionalAccess', _38 => _38.styleId]);
|
|
850
|
+
if (own) {
|
|
851
|
+
if (_chunk3CC7OPUQcjs.isValidStyleId.call(void 0, own) && this.styleIds.has(own)) return own;
|
|
852
|
+
this.drop("style", String(own), "style is not in the registry");
|
|
853
|
+
}
|
|
854
|
+
if (opts.heading) return this.needStyle(`Heading${opts.heading}`);
|
|
855
|
+
if (opts.code) return this.needStyle("Code");
|
|
856
|
+
if (ctx.quoteLevel > 0) return this.needStyle("BlockText");
|
|
857
|
+
if (ctx.list) return this.needStyle("ListParagraph");
|
|
858
|
+
return void 0;
|
|
859
|
+
}
|
|
860
|
+
/** Uses a style the registry may not define (it is then written with defaults). */
|
|
861
|
+
needStyle(id) {
|
|
862
|
+
if (!this.styleIds.has(id)) this.extraStyles.add(id);
|
|
863
|
+
return id;
|
|
864
|
+
}
|
|
865
|
+
previousStyle(previous) {
|
|
866
|
+
if (!previous) return void 0;
|
|
867
|
+
const id = _optionalChain([previous, 'access', _39 => _39.attrs, 'optionalAccess', _40 => _40.styleId]);
|
|
868
|
+
if (_chunk3CC7OPUQcjs.isValidStyleId.call(void 0, id) && this.styleIds.has(id)) return id;
|
|
869
|
+
if (previous.type === "heading") return this.needStyle(`Heading${Math.max(1, Math.min(6, Number(_optionalChain([previous, 'access', _41 => _41.attrs, 'optionalAccess', _42 => _42.level])) || 1))}`);
|
|
870
|
+
if (previous.type === "codeBlock") return this.needStyle("Code");
|
|
871
|
+
return void 0;
|
|
872
|
+
}
|
|
873
|
+
paragraph(w, node, ctx, opts = {}) {
|
|
874
|
+
this.report.written.paragraphs++;
|
|
875
|
+
const style = this.styleFor(node, ctx, opts);
|
|
876
|
+
const change = _nullishCoalesce(_optionalChain([node, 'access', _43 => _43.attrs, 'optionalAccess', _44 => _44.blockChange]), () => ( null));
|
|
877
|
+
const operation = _optionalChain([change, 'optionalAccess', _45 => _45.operation]);
|
|
878
|
+
const list = ctx.list;
|
|
879
|
+
const numbered = list && ctx.listItemFirst;
|
|
880
|
+
const indent = ctx.quoteLevel * INDENT_STEP + (list && !numbered ? (list.level + 1) * INDENT_STEP : 0);
|
|
881
|
+
const jc = alignment(_optionalChain([node, 'access', _46 => _46.attrs, 'optionalAccess', _47 => _47.textAlign]));
|
|
882
|
+
w.open("w:p");
|
|
883
|
+
const ppr = new XmlWriter(false);
|
|
884
|
+
if (style) ppr.val("w:pStyle", style);
|
|
885
|
+
if (numbered) {
|
|
886
|
+
ppr.open("w:numPr").val("w:ilvl", list.level).val("w:numId", list.numId).close("w:numPr");
|
|
887
|
+
}
|
|
888
|
+
if (indent && !(ctx.quoteLevel > 0 && !list && ctx.quoteLevel === 1)) ppr.empty("w:ind", { "w:left": indent });
|
|
889
|
+
if (jc) ppr.val("w:jc", jc);
|
|
890
|
+
if (change && operation) {
|
|
891
|
+
ppr.open("w:rPr").empty(operation === "insert" ? "w:ins" : "w:del", this.changeAttrs(change)).close("w:rPr");
|
|
892
|
+
this.report.written.trackedChanges++;
|
|
893
|
+
} else if (_optionalChain([change, 'optionalAccess', _48 => _48.previous])) {
|
|
894
|
+
ppr.open("w:pPrChange", this.changeAttrs(change)).open("w:pPr");
|
|
895
|
+
const old = this.previousStyle(change.previous);
|
|
896
|
+
if (old) ppr.val("w:pStyle", old);
|
|
897
|
+
const oldJc = alignment(_optionalChain([change, 'access', _49 => _49.previous, 'access', _50 => _50.attrs, 'optionalAccess', _51 => _51.textAlign]));
|
|
898
|
+
if (oldJc) ppr.val("w:jc", oldJc);
|
|
899
|
+
ppr.close("w:pPr").close("w:pPrChange");
|
|
900
|
+
this.report.written.trackedChanges++;
|
|
901
|
+
}
|
|
902
|
+
const pprXml = ppr.toString();
|
|
903
|
+
if (pprXml) w.open("w:pPr").raw(pprXml).close("w:pPr");
|
|
904
|
+
if (_optionalChain([list, 'optionalAccess', _52 => _52.task]) && numbered) {
|
|
905
|
+
w.open("w:r").leaf("w:t", { "xml:space": "preserve" }, `${list.checked ? TASK_CHECKED : TASK_UNCHECKED} `).close("w:r");
|
|
906
|
+
}
|
|
907
|
+
const synthetic = change && operation ? { kind: operation === "insert" ? "ins" : "del", attrs: change } : void 0;
|
|
908
|
+
this.inline(w, this.pieces(_nullishCoalesce(node.content, () => ( [])), opts.code === true), synthetic);
|
|
909
|
+
w.close("w:p");
|
|
910
|
+
}
|
|
911
|
+
/** Flattens inline content into runs of text, tabs, breaks and images. */
|
|
912
|
+
pieces(nodes, code, out = [], depth = 0) {
|
|
913
|
+
if (depth > MAX_DEPTH) return out;
|
|
914
|
+
for (const node of nodes) {
|
|
915
|
+
const marks = _nullishCoalesce(node.marks, () => ( []));
|
|
916
|
+
switch (node.type) {
|
|
917
|
+
case "text": {
|
|
918
|
+
const text = _nullishCoalesce(node.text, () => ( ""));
|
|
919
|
+
const parts = text.split(/(\t|\r\n|\n|\r)/);
|
|
920
|
+
const pieces = [];
|
|
921
|
+
for (const part of parts) {
|
|
922
|
+
if (!part) continue;
|
|
923
|
+
if (part === " ") pieces.push({ kind: "tab", node, last: false, marks });
|
|
924
|
+
else if (part === "\n" || part === "\r\n" || part === "\r") pieces.push({ kind: "br", node, last: false, marks });
|
|
925
|
+
else pieces.push({ kind: "text", text: part, node, last: false, marks });
|
|
926
|
+
}
|
|
927
|
+
if (!pieces.length) pieces.push({ kind: "text", text: "", node, last: false, marks });
|
|
928
|
+
pieces[pieces.length - 1].last = true;
|
|
929
|
+
out.push(...pieces);
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
case "hardBreak":
|
|
933
|
+
out.push({ kind: "br", node, last: true, marks });
|
|
934
|
+
break;
|
|
935
|
+
case "image":
|
|
936
|
+
out.push({ kind: "image", node, last: true, marks });
|
|
937
|
+
break;
|
|
938
|
+
case "mention": {
|
|
939
|
+
const label = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _53 => _53.attrs, 'optionalAccess', _54 => _54.label]), () => ( _optionalChain([node, 'access', _55 => _55.attrs, 'optionalAccess', _56 => _56.id]))), () => ( ""));
|
|
940
|
+
out.push({ kind: "text", text: label ? `@${label}` : "", node, last: true, marks });
|
|
941
|
+
break;
|
|
942
|
+
}
|
|
943
|
+
default:
|
|
944
|
+
if (_optionalChain([node, 'access', _57 => _57.content, 'optionalAccess', _58 => _58.length])) {
|
|
945
|
+
this.pieces(node.content, code, out, depth + 1);
|
|
946
|
+
} else if (typeof _optionalChain([node, 'access', _59 => _59.attrs, 'optionalAccess', _60 => _60.label]) === "string" || typeof _optionalChain([node, 'access', _61 => _61.attrs, 'optionalAccess', _62 => _62.text]) === "string") {
|
|
947
|
+
this.drop("node", _nullishCoalesce(node.type, () => ( "unknown")), "written as text");
|
|
948
|
+
out.push({ kind: "text", text: String(_nullishCoalesce(node.attrs.label, () => ( node.attrs.text))), node, last: true, marks });
|
|
949
|
+
} else {
|
|
950
|
+
this.drop("node", _nullishCoalesce(node.type, () => ( "unknown")), "unsupported inline node");
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
return out;
|
|
955
|
+
}
|
|
956
|
+
revisionsOf(marks, synthetic) {
|
|
957
|
+
const out = [];
|
|
958
|
+
const ins = marks.find((m) => m.type === "insertion");
|
|
959
|
+
const del = marks.find((m) => m.type === "deletion");
|
|
960
|
+
if (ins) out.push({ kind: "ins", attrs: _nullishCoalesce(ins.attrs, () => ( {})), moveId: _optionalChain([ins, 'access', _63 => _63.attrs, 'optionalAccess', _64 => _64.moveId]) || void 0 });
|
|
961
|
+
if (del) out.push({ kind: "del", attrs: _nullishCoalesce(del.attrs, () => ( {})), moveId: _optionalChain([del, 'access', _65 => _65.attrs, 'optionalAccess', _66 => _66.moveId]) || void 0 });
|
|
962
|
+
if (!out.length && synthetic) out.push(synthetic);
|
|
963
|
+
return out;
|
|
964
|
+
}
|
|
965
|
+
linkOf(marks) {
|
|
966
|
+
const link = marks.find((m) => m.type === "link");
|
|
967
|
+
const href = typeof _optionalChain([link, 'optionalAccess', _67 => _67.attrs, 'optionalAccess', _68 => _68.href]) === "string" ? link.attrs.href.trim() : "";
|
|
968
|
+
if (!href) return void 0;
|
|
969
|
+
if (href.startsWith("#") || /^(https?|mailto|tel|ftp):/i.test(href) || !/^[a-z][a-z0-9+.-]*:/i.test(href)) return href;
|
|
970
|
+
this.drop("link", href, "unsafe URL scheme");
|
|
971
|
+
return void 0;
|
|
972
|
+
}
|
|
973
|
+
/** Writes pieces grouped into hyperlinks (outer) and tracked-change wrappers (inner). */
|
|
974
|
+
inline(w, pieces, synthetic) {
|
|
975
|
+
let openLink;
|
|
976
|
+
let openRevs = null;
|
|
977
|
+
const closeRevs = () => {
|
|
978
|
+
const open = openRevs;
|
|
979
|
+
if (!open) return;
|
|
980
|
+
for (const tag of [...open.tags].reverse()) w.close(tag);
|
|
981
|
+
for (const range of open.moveRanges) w.empty(range.tag, { "w:id": range.id });
|
|
982
|
+
openRevs = null;
|
|
983
|
+
};
|
|
984
|
+
const closeLink = () => {
|
|
985
|
+
closeRevs();
|
|
986
|
+
if (openLink !== void 0) w.close("w:hyperlink");
|
|
987
|
+
openLink = void 0;
|
|
988
|
+
};
|
|
989
|
+
for (const piece of pieces) {
|
|
990
|
+
const href = this.linkOf(piece.marks);
|
|
991
|
+
if (href !== openLink) {
|
|
992
|
+
closeLink();
|
|
993
|
+
if (href !== void 0) {
|
|
994
|
+
if (href.startsWith("#")) w.open("w:hyperlink", { "w:anchor": href.slice(1), "w:history": 1 });
|
|
995
|
+
else w.open("w:hyperlink", { "r:id": this.rels.add(REL.hyperlink, href, true), "w:history": 1 });
|
|
996
|
+
openLink = href;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
const revs = this.revisionsOf(piece.marks, synthetic);
|
|
1000
|
+
const key = revs.map((r) => `${r.kind}:${_nullishCoalesce(r.attrs.changeId, () => ( ""))}:${_nullishCoalesce(r.moveId, () => ( ""))}:${_nullishCoalesce(r.attrs.authorName, () => ( ""))}`).join("|");
|
|
1001
|
+
if (key !== (_nullishCoalesce(_optionalChain([openRevs, 'optionalAccess', _69 => _69.key]), () => ( "")))) {
|
|
1002
|
+
closeRevs();
|
|
1003
|
+
if (revs.length) {
|
|
1004
|
+
const state = { key, tags: [], moveRanges: [] };
|
|
1005
|
+
for (const rev of revs) {
|
|
1006
|
+
const attrs2 = this.changeAttrs(rev.attrs);
|
|
1007
|
+
this.report.written.trackedChanges++;
|
|
1008
|
+
if (rev.moveId) {
|
|
1009
|
+
const rangeTag = rev.kind === "ins" ? "w:moveToRange" : "w:moveFromRange";
|
|
1010
|
+
const rangeId = ++this.revisionId;
|
|
1011
|
+
w.empty(`${rangeTag}Start`, { "w:id": rangeId, "w:name": rev.moveId, "w:author": attrs2["w:author"], "w:date": attrs2["w:date"] });
|
|
1012
|
+
state.moveRanges.push({ tag: `${rangeTag}End`, id: rangeId });
|
|
1013
|
+
}
|
|
1014
|
+
const tag = rev.moveId ? rev.kind === "ins" ? "w:moveTo" : "w:moveFrom" : rev.kind === "ins" ? "w:ins" : "w:del";
|
|
1015
|
+
w.open(tag, attrs2);
|
|
1016
|
+
state.tags.push(tag);
|
|
1017
|
+
}
|
|
1018
|
+
openRevs = state;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
this.commentStarts(w, piece.marks);
|
|
1022
|
+
this.run(w, piece, revs);
|
|
1023
|
+
if (piece.last) this.commentEndsAfter(w, piece.node);
|
|
1024
|
+
}
|
|
1025
|
+
closeLink();
|
|
1026
|
+
}
|
|
1027
|
+
commentStarts(w, marks) {
|
|
1028
|
+
for (const mark of marks) {
|
|
1029
|
+
if (mark.type !== "comment") continue;
|
|
1030
|
+
const entry = this.comments.get(_optionalChain([mark, 'access', _70 => _70.attrs, 'optionalAccess', _71 => _71.commentId]));
|
|
1031
|
+
if (!entry || entry.started) continue;
|
|
1032
|
+
entry.started = true;
|
|
1033
|
+
for (const id of entry.ids) w.empty("w:commentRangeStart", { "w:id": id });
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
commentEndsAfter(w, node) {
|
|
1037
|
+
for (const threadId of _nullishCoalesce(this.endsByNode.get(node), () => ( []))) {
|
|
1038
|
+
const entry = this.comments.get(threadId);
|
|
1039
|
+
if (_optionalChain([entry, 'optionalAccess', _72 => _72.started]) && !entry.ended) this.endComment(w, threadId);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
endComment(w, threadId) {
|
|
1043
|
+
const entry = this.comments.get(threadId);
|
|
1044
|
+
entry.ended = true;
|
|
1045
|
+
for (const id of entry.ids) {
|
|
1046
|
+
w.empty("w:commentRangeEnd", { "w:id": id });
|
|
1047
|
+
w.open("w:r").open("w:rPr").val("w:rStyle", "CommentReference").close("w:rPr");
|
|
1048
|
+
w.empty("w:commentReference", { "w:id": id }).close("w:r");
|
|
1049
|
+
}
|
|
1050
|
+
this.needStyle("CommentReference");
|
|
1051
|
+
this.needStyle("CommentText");
|
|
1052
|
+
}
|
|
1053
|
+
run(w, piece, revs) {
|
|
1054
|
+
for (const mark of piece.marks) {
|
|
1055
|
+
if (!FORMAT_MARKS.has(mark.type) && !STRUCTURAL_MARKS.has(mark.type)) this.drop("mark", mark.type, "formatting not supported");
|
|
1056
|
+
if (mark.type === "characterStyle" && _optionalChain([mark, 'access', _73 => _73.attrs, 'optionalAccess', _74 => _74.styleId]) && !this.styleIds.has(mark.attrs.styleId)) {
|
|
1057
|
+
this.drop("style", String(mark.attrs.styleId), "character style is not in the registry");
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
if (piece.kind === "image") {
|
|
1061
|
+
const drawing = this.image(piece.node);
|
|
1062
|
+
if (!drawing) return;
|
|
1063
|
+
w.open("w:r");
|
|
1064
|
+
const format2 = runFormatOf(piece.marks);
|
|
1065
|
+
delete format2.charStyle;
|
|
1066
|
+
if (hasRunProps(format2)) {
|
|
1067
|
+
w.open("w:rPr");
|
|
1068
|
+
writeRunProps(w, format2);
|
|
1069
|
+
w.close("w:rPr");
|
|
1070
|
+
}
|
|
1071
|
+
w.raw(drawing).close("w:r");
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
const format = runFormatOf(piece.marks.filter((m) => m.type !== "characterStyle" || this.styleIds.has(_optionalChain([m, 'access', _75 => _75.attrs, 'optionalAccess', _76 => _76.styleId]))));
|
|
1075
|
+
if (format.charStyle === "Hyperlink") this.needStyle("Hyperlink");
|
|
1076
|
+
const formatChange = piece.marks.find((m) => m.type === "formatChange");
|
|
1077
|
+
w.open("w:r");
|
|
1078
|
+
if (hasRunProps(format) || formatChange) {
|
|
1079
|
+
w.open("w:rPr");
|
|
1080
|
+
writeRunProps(w, format);
|
|
1081
|
+
if (formatChange) {
|
|
1082
|
+
const attrs2 = _nullishCoalesce(formatChange.attrs, () => ( {}));
|
|
1083
|
+
w.open("w:rPrChange", this.changeAttrs(attrs2)).open("w:rPr");
|
|
1084
|
+
writeRunProps(w, runFormatOf(Array.isArray(attrs2.before) ? attrs2.before : []));
|
|
1085
|
+
w.close("w:rPr").close("w:rPrChange");
|
|
1086
|
+
this.report.written.trackedChanges++;
|
|
1087
|
+
}
|
|
1088
|
+
w.close("w:rPr");
|
|
1089
|
+
}
|
|
1090
|
+
const deleted = revs.some((r) => r.kind === "del" && !r.moveId);
|
|
1091
|
+
if (piece.kind === "tab") w.empty("w:tab");
|
|
1092
|
+
else if (piece.kind === "br") w.empty("w:br");
|
|
1093
|
+
else if (piece.text) w.leaf(deleted ? "w:delText" : "w:t", { "xml:space": "preserve" }, piece.text);
|
|
1094
|
+
w.close("w:r");
|
|
1095
|
+
}
|
|
1096
|
+
// -- Images -----------------------------------------------------------------
|
|
1097
|
+
image(node) {
|
|
1098
|
+
const src = typeof _optionalChain([node, 'access', _77 => _77.attrs, 'optionalAccess', _78 => _78.src]) === "string" ? node.attrs.src.trim() : "";
|
|
1099
|
+
const alt = typeof _optionalChain([node, 'access', _79 => _79.attrs, 'optionalAccess', _80 => _80.alt]) === "string" ? node.attrs.alt : "";
|
|
1100
|
+
const title = typeof _optionalChain([node, 'access', _81 => _81.attrs, 'optionalAccess', _82 => _82.title]) === "string" ? node.attrs.title : "";
|
|
1101
|
+
let relId;
|
|
1102
|
+
let natural = null;
|
|
1103
|
+
let linked = false;
|
|
1104
|
+
if (src.startsWith("data:")) {
|
|
1105
|
+
const decoded = decodeDataUrl(src);
|
|
1106
|
+
const ext = decoded ? DOCX_IMAGE_TYPES[decoded.mime] : void 0;
|
|
1107
|
+
if (!decoded || !ext) {
|
|
1108
|
+
this.drop("image", _nullishCoalesce(_optionalChain([decoded, 'optionalAccess', _83 => _83.mime]), () => ( "data URL")), "unsupported image type");
|
|
1109
|
+
return null;
|
|
1110
|
+
}
|
|
1111
|
+
const name = `image${this.media.length + 1}.${ext}`;
|
|
1112
|
+
this.media.push({ name, bytes: decoded.bytes });
|
|
1113
|
+
this.mediaTypes.add(ext);
|
|
1114
|
+
relId = this.rels.add(REL.image, `media/${name}`);
|
|
1115
|
+
natural = imagePixelSize(decoded.bytes);
|
|
1116
|
+
} else if (/^https?:\/\//i.test(src)) {
|
|
1117
|
+
if (this.options.remoteImages !== "link") {
|
|
1118
|
+
this.drop("image", src, 'remote image skipped (use remoteImages: "link")');
|
|
1119
|
+
return null;
|
|
1120
|
+
}
|
|
1121
|
+
relId = this.rels.add(REL.image, src, true);
|
|
1122
|
+
linked = true;
|
|
1123
|
+
} else {
|
|
1124
|
+
this.drop("image", src || "image", "image source is neither a data URL nor http(s)");
|
|
1125
|
+
return null;
|
|
1126
|
+
}
|
|
1127
|
+
let width = _nullishCoalesce(_nullishCoalesce(pixelAttr(_optionalChain([node, 'access', _84 => _84.attrs, 'optionalAccess', _85 => _85.width])), () => ( _optionalChain([natural, 'optionalAccess', _86 => _86.width]))), () => ( 400));
|
|
1128
|
+
let height = _nullishCoalesce(pixelAttr(_optionalChain([node, 'access', _87 => _87.attrs, 'optionalAccess', _88 => _88.height])), () => ( (natural ? natural.height * width / natural.width : 300)));
|
|
1129
|
+
if (width > MAX_IMAGE_WIDTH_PX) {
|
|
1130
|
+
height = height * MAX_IMAGE_WIDTH_PX / width;
|
|
1131
|
+
width = MAX_IMAGE_WIDTH_PX;
|
|
1132
|
+
}
|
|
1133
|
+
const cx = pxToEmu(width);
|
|
1134
|
+
const cy = pxToEmu(height);
|
|
1135
|
+
const id = ++this.docPrId;
|
|
1136
|
+
this.report.written.images++;
|
|
1137
|
+
const w = new XmlWriter(false);
|
|
1138
|
+
w.open("w:drawing").open("wp:inline", { distT: 0, distB: 0, distL: 0, distR: 0 });
|
|
1139
|
+
w.empty("wp:extent", { cx, cy }).empty("wp:effectExtent", { l: 0, t: 0, r: 0, b: 0 });
|
|
1140
|
+
w.empty("wp:docPr", { id, name: `Picture ${id}`, descr: alt || void 0, title: title || void 0 });
|
|
1141
|
+
w.open("wp:cNvGraphicFramePr").empty("a:graphicFrameLocks", { noChangeAspect: 1 }).close("wp:cNvGraphicFramePr");
|
|
1142
|
+
w.open("a:graphic").open("a:graphicData", { uri: "http://schemas.openxmlformats.org/drawingml/2006/picture" });
|
|
1143
|
+
w.open("pic:pic").open("pic:nvPicPr").empty("pic:cNvPr", { id: 0, name: `Picture ${id}`, descr: alt || void 0 });
|
|
1144
|
+
w.empty("pic:cNvPicPr").close("pic:nvPicPr");
|
|
1145
|
+
w.open("pic:blipFill").empty("a:blip", linked ? { "r:link": relId } : { "r:embed": relId });
|
|
1146
|
+
w.open("a:stretch").empty("a:fillRect").close("a:stretch").close("pic:blipFill");
|
|
1147
|
+
w.open("pic:spPr").open("a:xfrm").empty("a:off", { x: 0, y: 0 }).empty("a:ext", { cx, cy }).close("a:xfrm");
|
|
1148
|
+
w.open("a:prstGeom", { prst: "rect" }).empty("a:avLst").close("a:prstGeom").close("pic:spPr");
|
|
1149
|
+
w.close("pic:pic").close("a:graphicData").close("a:graphic").close("wp:inline").close("w:drawing");
|
|
1150
|
+
return w.toString();
|
|
1151
|
+
}
|
|
1152
|
+
// -- Tables -------------------------------------------------------------------
|
|
1153
|
+
table(w, node, ctx) {
|
|
1154
|
+
const rows = (_nullishCoalesce(node.content, () => ( []))).filter((row) => row.type === "tableRow" || _optionalChain([row, 'access', _89 => _89.content, 'optionalAccess', _90 => _90.length]));
|
|
1155
|
+
if (!rows.length) {
|
|
1156
|
+
this.drop("node", "table", "empty table");
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
const grid = rows.map(() => []);
|
|
1160
|
+
rows.forEach((row, r) => {
|
|
1161
|
+
let col = 0;
|
|
1162
|
+
for (const cell of _nullishCoalesce(row.content, () => ( []))) {
|
|
1163
|
+
while (grid[r][col]) col++;
|
|
1164
|
+
const colspan = Math.max(1, Math.min(63, Number(_optionalChain([cell, 'access', _91 => _91.attrs, 'optionalAccess', _92 => _92.colspan])) || 1));
|
|
1165
|
+
const rowspan = Math.max(1, Math.min(rows.length - r, Number(_optionalChain([cell, 'access', _93 => _93.attrs, 'optionalAccess', _94 => _94.rowspan])) || 1));
|
|
1166
|
+
for (let i = 0; i < rowspan; i++) {
|
|
1167
|
+
for (let j = 0; j < colspan; j++) {
|
|
1168
|
+
grid[r + i][col + j] = { cell, rowOffset: i, colOffset: j, colspan, rowspan };
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
col += colspan;
|
|
1172
|
+
}
|
|
1173
|
+
});
|
|
1174
|
+
const cols = Math.max(1, Math.min(63, ...grid.map((row) => row.length)));
|
|
1175
|
+
const widths = [];
|
|
1176
|
+
for (let c = 0; c < cols; c++) {
|
|
1177
|
+
const slot = grid[0][c];
|
|
1178
|
+
const colwidth = _optionalChain([slot, 'optionalAccess', _95 => _95.cell, 'access', _96 => _96.attrs, 'optionalAccess', _97 => _97.colwidth]);
|
|
1179
|
+
const px = Array.isArray(colwidth) ? Number(colwidth[slot.colOffset]) : NaN;
|
|
1180
|
+
widths.push(Number.isFinite(px) && px > 0 ? pxToTwips(px) : 0);
|
|
1181
|
+
}
|
|
1182
|
+
const known = widths.reduce((n, v) => n + v, 0);
|
|
1183
|
+
const unknown = widths.filter((v) => !v).length;
|
|
1184
|
+
const fill = unknown ? Math.max(360, Math.floor(Math.max(0, CONTENT_WIDTH_TWIPS - known) / unknown)) : 0;
|
|
1185
|
+
for (let c = 0; c < cols; c++) if (!widths[c]) widths[c] = fill;
|
|
1186
|
+
this.report.written.tables++;
|
|
1187
|
+
w.open("w:tbl").open("w:tblPr");
|
|
1188
|
+
w.empty("w:tblW", { "w:w": 0, "w:type": "auto" });
|
|
1189
|
+
w.open("w:tblBorders");
|
|
1190
|
+
for (const side of ["top", "left", "bottom", "right", "insideH", "insideV"]) {
|
|
1191
|
+
w.empty(`w:${side}`, { "w:val": "single", "w:sz": 4, "w:space": 0, "w:color": "auto" });
|
|
1192
|
+
}
|
|
1193
|
+
w.close("w:tblBorders");
|
|
1194
|
+
w.empty("w:tblLook", { "w:val": "04A0", "w:firstRow": 1, "w:lastRow": 0, "w:firstColumn": 1, "w:lastColumn": 0, "w:noHBand": 0, "w:noVBand": 1 });
|
|
1195
|
+
w.close("w:tblPr");
|
|
1196
|
+
w.open("w:tblGrid");
|
|
1197
|
+
widths.forEach((width) => w.empty("w:gridCol", { "w:w": width }));
|
|
1198
|
+
w.close("w:tblGrid");
|
|
1199
|
+
const cellCtx = { depth: ctx.depth + 1, quoteLevel: 0 };
|
|
1200
|
+
rows.forEach((row, r) => {
|
|
1201
|
+
w.open("w:tr");
|
|
1202
|
+
const cells = _nullishCoalesce(row.content, () => ( []));
|
|
1203
|
+
if (cells.length && cells.every((cell) => cell.type === "tableHeader")) {
|
|
1204
|
+
w.open("w:trPr").empty("w:tblHeader").close("w:trPr");
|
|
1205
|
+
}
|
|
1206
|
+
for (let c = 0; c < cols; c++) {
|
|
1207
|
+
const slot = grid[r][c];
|
|
1208
|
+
if (slot && slot.colOffset > 0) continue;
|
|
1209
|
+
const span = _nullishCoalesce(_optionalChain([slot, 'optionalAccess', _98 => _98.colspan]), () => ( 1));
|
|
1210
|
+
const width = widths.slice(c, c + span).reduce((n, v) => n + v, 0);
|
|
1211
|
+
w.open("w:tc").open("w:tcPr").empty("w:tcW", { "w:w": width, "w:type": "dxa" });
|
|
1212
|
+
if (span > 1) w.val("w:gridSpan", span);
|
|
1213
|
+
if (slot && slot.rowspan > 1) {
|
|
1214
|
+
if (slot.rowOffset === 0) w.val("w:vMerge", "restart");
|
|
1215
|
+
else w.empty("w:vMerge");
|
|
1216
|
+
}
|
|
1217
|
+
w.close("w:tcPr");
|
|
1218
|
+
const content = slot && slot.rowOffset === 0 ? _nullishCoalesce(slot.cell.content, () => ( [])) : [];
|
|
1219
|
+
if (content.length) this.blocks(w, content, cellCtx);
|
|
1220
|
+
const lastType = _optionalChain([content, 'access', _99 => _99[content.length - 1], 'optionalAccess', _100 => _100.type]);
|
|
1221
|
+
if (!content.length || lastType === "table") w.empty("w:p");
|
|
1222
|
+
w.close("w:tc");
|
|
1223
|
+
}
|
|
1224
|
+
w.close("w:tr");
|
|
1225
|
+
});
|
|
1226
|
+
w.close("w:tbl");
|
|
1227
|
+
}
|
|
1228
|
+
// -- Other parts --------------------------------------------------------------
|
|
1229
|
+
numberingXml() {
|
|
1230
|
+
if (!this.nums.length) return null;
|
|
1231
|
+
const w = new XmlWriter();
|
|
1232
|
+
w.open("w:numbering", BODY_NS);
|
|
1233
|
+
const abstract = (id, kind) => {
|
|
1234
|
+
w.open("w:abstractNum", { "w:abstractNumId": id }).val("w:multiLevelType", "hybridMultilevel");
|
|
1235
|
+
for (let level = 0; level < 9; level++) {
|
|
1236
|
+
w.open("w:lvl", { "w:ilvl": level }).val("w:start", 1);
|
|
1237
|
+
if (kind === "decimal") {
|
|
1238
|
+
const formats = ["decimal", "lowerLetter", "lowerRoman"];
|
|
1239
|
+
w.val("w:numFmt", formats[level % 3]).val("w:lvlText", `%${level + 1}.`);
|
|
1240
|
+
} else if (kind === "bullet") {
|
|
1241
|
+
w.val("w:numFmt", "bullet").val("w:lvlText", BULLETS[level % 3]);
|
|
1242
|
+
} else {
|
|
1243
|
+
w.val("w:numFmt", "none").val("w:lvlText", "");
|
|
1244
|
+
}
|
|
1245
|
+
w.val("w:lvlJc", "left");
|
|
1246
|
+
w.open("w:pPr").empty("w:ind", { "w:left": (level + 1) * INDENT_STEP, "w:hanging": kind === "task" ? 0 : 360 }).close("w:pPr");
|
|
1247
|
+
if (kind === "bullet") {
|
|
1248
|
+
const font = BULLET_FONTS[level % 3] === "Symbol" ? "Arial" : BULLET_FONTS[level % 3];
|
|
1249
|
+
w.open("w:rPr").empty("w:rFonts", { "w:ascii": font, "w:hAnsi": font, "w:hint": "default" }).close("w:rPr");
|
|
1250
|
+
}
|
|
1251
|
+
w.close("w:lvl");
|
|
1252
|
+
}
|
|
1253
|
+
w.close("w:abstractNum");
|
|
1254
|
+
};
|
|
1255
|
+
abstract(1, "bullet");
|
|
1256
|
+
abstract(2, "decimal");
|
|
1257
|
+
abstract(3, "task");
|
|
1258
|
+
for (const num of this.nums) {
|
|
1259
|
+
w.open("w:num", { "w:numId": num.numId }).val("w:abstractNumId", num.abstractId);
|
|
1260
|
+
if (num.start !== void 0) {
|
|
1261
|
+
w.open("w:lvlOverride", { "w:ilvl": num.level }).val("w:startOverride", num.start).close("w:lvlOverride");
|
|
1262
|
+
}
|
|
1263
|
+
w.close("w:num");
|
|
1264
|
+
}
|
|
1265
|
+
w.close("w:numbering");
|
|
1266
|
+
return w.toString();
|
|
1267
|
+
}
|
|
1268
|
+
stylesXml() {
|
|
1269
|
+
const w = new XmlWriter();
|
|
1270
|
+
w.open("w:styles", BODY_NS);
|
|
1271
|
+
const defaults = this.styles.defaults;
|
|
1272
|
+
const defaultRun = characterFormatToRun(defaults.character);
|
|
1273
|
+
w.open("w:docDefaults").open("w:rPrDefault").open("w:rPr");
|
|
1274
|
+
const font = _nullishCoalesce(defaultRun.font, () => ( "Calibri"));
|
|
1275
|
+
w.empty("w:rFonts", { "w:ascii": font, "w:hAnsi": font, "w:eastAsia": font, "w:cs": font });
|
|
1276
|
+
const size = _nullishCoalesce(defaultRun.halfPoints, () => ( 22));
|
|
1277
|
+
w.val("w:sz", size).val("w:szCs", size);
|
|
1278
|
+
w.val("w:lang", "en-US");
|
|
1279
|
+
w.close("w:rPr").close("w:rPrDefault");
|
|
1280
|
+
w.open("w:pPrDefault").open("w:pPr");
|
|
1281
|
+
if (defaults.paragraph && Object.keys(defaults.paragraph).length) writeParagraphFormat(w, defaults.paragraph);
|
|
1282
|
+
else w.empty("w:spacing", { "w:after": 160, "w:line": 259, "w:lineRule": "auto" });
|
|
1283
|
+
w.close("w:pPr").close("w:pPrDefault").close("w:docDefaults");
|
|
1284
|
+
const byId = new Map(this.styles.styles.filter((s) => _chunk3CC7OPUQcjs.isValidStyleId.call(void 0, s.id)).map((s) => [s.id, s]));
|
|
1285
|
+
const written = /* @__PURE__ */ new Set();
|
|
1286
|
+
const blockOf = (style) => {
|
|
1287
|
+
let current = style;
|
|
1288
|
+
for (let i = 0; current && i < 32; i++) {
|
|
1289
|
+
if (current.block) return current.block;
|
|
1290
|
+
current = current.basedOn ? byId.get(current.basedOn) : void 0;
|
|
1291
|
+
}
|
|
1292
|
+
return null;
|
|
1293
|
+
};
|
|
1294
|
+
const writeStyle = (style) => {
|
|
1295
|
+
if (written.has(style.id)) return;
|
|
1296
|
+
written.add(style.id);
|
|
1297
|
+
const isNormal = style.kind === "paragraph" && style.id === _chunk3CC7OPUQcjs.NORMAL_STYLE_ID;
|
|
1298
|
+
w.open("w:style", {
|
|
1299
|
+
"w:type": style.kind === "character" ? "character" : "paragraph",
|
|
1300
|
+
"w:default": isNormal ? 1 : void 0,
|
|
1301
|
+
"w:customStyle": style.builtin ? void 0 : 1,
|
|
1302
|
+
"w:styleId": style.id
|
|
1303
|
+
});
|
|
1304
|
+
w.val("w:name", fileStyleName(style.name || style.id));
|
|
1305
|
+
const base = style.basedOn && byId.has(style.basedOn) && byId.get(style.basedOn).kind === style.kind ? style.basedOn : void 0;
|
|
1306
|
+
if (base) w.val("w:basedOn", base);
|
|
1307
|
+
if (style.kind === "paragraph" && style.next && _optionalChain([byId, 'access', _101 => _101.get, 'call', _102 => _102(style.next), 'optionalAccess', _103 => _103.kind]) === "paragraph") w.val("w:next", style.next);
|
|
1308
|
+
if (style.linked && byId.has(style.linked)) w.val("w:link", style.linked);
|
|
1309
|
+
if (style.priority !== void 0 && Number.isFinite(style.priority)) w.val("w:uiPriority", Math.max(0, Math.round(style.priority)));
|
|
1310
|
+
if (style.hidden) w.empty("w:semiHidden").empty("w:unhideWhenUsed");
|
|
1311
|
+
if (style.quick) w.empty("w:qFormat");
|
|
1312
|
+
const block = style.kind === "paragraph" ? blockOf(style) : null;
|
|
1313
|
+
const ownBlock = style.kind === "paragraph" ? style.block : null;
|
|
1314
|
+
const outline = _optionalChain([ownBlock, 'optionalAccess', _104 => _104.type]) === "heading" ? Math.max(0, Math.min(8, (Number(_optionalChain([ownBlock, 'access', _105 => _105.attrs, 'optionalAccess', _106 => _106.level])) || 1) - 1)) : void 0;
|
|
1315
|
+
if (style.kind === "paragraph" && (style.paragraph || outline !== void 0)) {
|
|
1316
|
+
const p = new XmlWriter(false);
|
|
1317
|
+
writeParagraphFormat(p, style.paragraph, outline);
|
|
1318
|
+
const xml = p.toString();
|
|
1319
|
+
if (xml) w.open("w:pPr").raw(xml).close("w:pPr");
|
|
1320
|
+
}
|
|
1321
|
+
const run = characterFormatToRun(style.character);
|
|
1322
|
+
if (_optionalChain([block, 'optionalAccess', _107 => _107.type]) === "codeBlock" && !run.font) run.font = "Consolas";
|
|
1323
|
+
if (hasRunProps(run)) {
|
|
1324
|
+
w.open("w:rPr");
|
|
1325
|
+
writeRunProps(w, run);
|
|
1326
|
+
w.close("w:rPr");
|
|
1327
|
+
}
|
|
1328
|
+
w.close("w:style");
|
|
1329
|
+
};
|
|
1330
|
+
const visit = (style, depth = 0) => {
|
|
1331
|
+
if (depth > 32 || written.has(style.id)) return;
|
|
1332
|
+
const base = style.basedOn ? byId.get(style.basedOn) : void 0;
|
|
1333
|
+
if (base) visit(base, depth + 1);
|
|
1334
|
+
writeStyle(style);
|
|
1335
|
+
};
|
|
1336
|
+
byId.forEach((style) => visit(style));
|
|
1337
|
+
for (const id of this.extraStyles) {
|
|
1338
|
+
if (written.has(id)) continue;
|
|
1339
|
+
const extra = _nullishCoalesce(EXTRA_STYLES[id], () => ( { id, name: id, kind: "paragraph", basedOn: _chunk3CC7OPUQcjs.NORMAL_STYLE_ID }));
|
|
1340
|
+
byId.set(id, extra);
|
|
1341
|
+
writeStyle(extra);
|
|
1342
|
+
}
|
|
1343
|
+
w.close("w:styles");
|
|
1344
|
+
return w.toString();
|
|
1345
|
+
}
|
|
1346
|
+
settingsXml() {
|
|
1347
|
+
const w = new XmlWriter();
|
|
1348
|
+
w.open("w:settings", BODY_NS).empty("w:zoom", { "w:percent": 100 });
|
|
1349
|
+
if (this.anonymous) w.empty("w:removePersonalInformation");
|
|
1350
|
+
w.val("w:defaultTabStop", 720);
|
|
1351
|
+
w.val("w:characterSpacingControl", "doNotCompress");
|
|
1352
|
+
w.open("w:compat").empty("w:compatSetting", {
|
|
1353
|
+
"w:name": "compatibilityMode",
|
|
1354
|
+
"w:uri": "http://schemas.microsoft.com/office/word",
|
|
1355
|
+
"w:val": 15
|
|
1356
|
+
});
|
|
1357
|
+
w.close("w:compat").close("w:settings");
|
|
1358
|
+
return w.toString();
|
|
1359
|
+
}
|
|
1360
|
+
commentParts() {
|
|
1361
|
+
if (!this.comments.size) return null;
|
|
1362
|
+
const w = new XmlWriter();
|
|
1363
|
+
const ext = new XmlWriter();
|
|
1364
|
+
w.open("w:comments", BODY_NS);
|
|
1365
|
+
ext.open("w15:commentsEx", { "xmlns:w15": NS.w15, "xmlns:mc": NS.mc, "mc:Ignorable": "w15" });
|
|
1366
|
+
for (const entry of this.comments.values()) {
|
|
1367
|
+
if (!entry.started) continue;
|
|
1368
|
+
const { thread } = entry;
|
|
1369
|
+
const parentPara = this.comment(w, entry.ids[0], thread.author, thread.createdAt, thread.body);
|
|
1370
|
+
ext.empty("w15:commentEx", { "w15:paraId": parentPara, "w15:done": thread.resolved ? 1 : 0 });
|
|
1371
|
+
this.report.written.comments++;
|
|
1372
|
+
thread.replies.forEach((reply, i) => {
|
|
1373
|
+
const para = this.comment(w, entry.ids[i + 1], reply.author, reply.createdAt, reply.body);
|
|
1374
|
+
ext.empty("w15:commentEx", { "w15:paraId": para, "w15:paraIdParent": parentPara, "w15:done": thread.resolved ? 1 : 0 });
|
|
1375
|
+
this.report.written.replies++;
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
w.close("w:comments");
|
|
1379
|
+
ext.close("w15:commentsEx");
|
|
1380
|
+
return { comments: w.toString(), extended: ext.toString() };
|
|
1381
|
+
}
|
|
1382
|
+
comment(w, id, author, createdAt, body) {
|
|
1383
|
+
const name = this.authorName(_optionalChain([author, 'optionalAccess', _108 => _108.name]), _optionalChain([author, 'optionalAccess', _109 => _109.id]));
|
|
1384
|
+
w.open("w:comment", {
|
|
1385
|
+
"w:id": id,
|
|
1386
|
+
"w:author": name,
|
|
1387
|
+
"w:date": isoDate(createdAt),
|
|
1388
|
+
"w:initials": this.anonymous ? ANONYMOUS_INITIALS : initialsOf(name)
|
|
1389
|
+
});
|
|
1390
|
+
const lines = String(_nullishCoalesce(body, () => ( ""))).replace(/\r\n?/g, "\n").split("\n");
|
|
1391
|
+
let paraId = "";
|
|
1392
|
+
lines.forEach((line, i) => {
|
|
1393
|
+
const last = i === lines.length - 1;
|
|
1394
|
+
if (last) paraId = (this.paraIdCounter++).toString(16).toUpperCase().padStart(8, "0");
|
|
1395
|
+
w.open("w:p", last ? { "w14:paraId": paraId, "w14:textId": "77777777" } : void 0);
|
|
1396
|
+
w.open("w:pPr").val("w:pStyle", "CommentText").close("w:pPr");
|
|
1397
|
+
if (i === 0) {
|
|
1398
|
+
w.open("w:r").open("w:rPr").val("w:rStyle", "CommentReference").close("w:rPr").empty("w:annotationRef").close("w:r");
|
|
1399
|
+
}
|
|
1400
|
+
if (line) w.open("w:r").leaf("w:t", { "xml:space": "preserve" }, line).close("w:r");
|
|
1401
|
+
w.close("w:p");
|
|
1402
|
+
});
|
|
1403
|
+
w.close("w:comment");
|
|
1404
|
+
return paraId;
|
|
1405
|
+
}
|
|
1406
|
+
peopleXml() {
|
|
1407
|
+
if (this.anonymous || !this.people.size) return null;
|
|
1408
|
+
const w = new XmlWriter();
|
|
1409
|
+
w.open("w15:people", { "xmlns:w15": NS.w15, "xmlns:mc": NS.mc, "mc:Ignorable": "w15" });
|
|
1410
|
+
for (const [name, id] of this.people) {
|
|
1411
|
+
w.open("w15:person", { "w15:author": name });
|
|
1412
|
+
w.empty("w15:presenceInfo", { "w15:providerId": "None", "w15:userId": id });
|
|
1413
|
+
w.close("w15:person");
|
|
1414
|
+
}
|
|
1415
|
+
w.close("w15:people");
|
|
1416
|
+
return w.toString();
|
|
1417
|
+
}
|
|
1418
|
+
coreXml(now) {
|
|
1419
|
+
const w = new XmlWriter();
|
|
1420
|
+
w.open("cp:coreProperties", {
|
|
1421
|
+
"xmlns:cp": "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
|
|
1422
|
+
"xmlns:dc": "http://purl.org/dc/elements/1.1/",
|
|
1423
|
+
"xmlns:dcterms": "http://purl.org/dc/terms/",
|
|
1424
|
+
"xmlns:dcmitype": "http://purl.org/dc/dcmitype/",
|
|
1425
|
+
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance"
|
|
1426
|
+
});
|
|
1427
|
+
if (this.options.title) w.leaf("dc:title", void 0, this.options.title);
|
|
1428
|
+
const creator = this.anonymous ? void 0 : _optionalChain([this, 'access', _110 => _110.defaultAuthor, 'optionalAccess', _111 => _111.name]);
|
|
1429
|
+
if (creator) w.leaf("dc:creator", void 0, creator).leaf("cp:lastModifiedBy", void 0, creator);
|
|
1430
|
+
const date = _nullishCoalesce(isoDate(now.getTime()), () => ( "2026-01-01T00:00:00Z"));
|
|
1431
|
+
w.leaf("dcterms:created", { "xsi:type": "dcterms:W3CDTF" }, date);
|
|
1432
|
+
w.leaf("dcterms:modified", { "xsi:type": "dcterms:W3CDTF" }, date);
|
|
1433
|
+
w.close("cp:coreProperties");
|
|
1434
|
+
return w.toString();
|
|
1435
|
+
}
|
|
1436
|
+
/** Assembles every part; `[Content_Types].xml` first. */
|
|
1437
|
+
parts(now) {
|
|
1438
|
+
const document2 = this.documentXml();
|
|
1439
|
+
const parts = [];
|
|
1440
|
+
const overrides = [];
|
|
1441
|
+
const add = (name, data, contentType) => {
|
|
1442
|
+
parts.push({ name, data });
|
|
1443
|
+
overrides.push([`/${name}`, contentType]);
|
|
1444
|
+
};
|
|
1445
|
+
this.rels.add(REL.styles, "styles.xml");
|
|
1446
|
+
this.rels.add(REL.settings, "settings.xml");
|
|
1447
|
+
const numbering = this.numberingXml();
|
|
1448
|
+
if (numbering) this.rels.add(REL.numbering, "numbering.xml");
|
|
1449
|
+
const comments = this.commentParts();
|
|
1450
|
+
if (comments) {
|
|
1451
|
+
this.rels.add(REL.comments, "comments.xml");
|
|
1452
|
+
this.rels.add(REL.commentsExtended, "commentsExtended.xml");
|
|
1453
|
+
}
|
|
1454
|
+
const people = this.peopleXml();
|
|
1455
|
+
if (people) this.rels.add(REL.people, "people.xml");
|
|
1456
|
+
const styles = this.stylesXml();
|
|
1457
|
+
add("word/document.xml", document2, `${CT_WML}document.main+xml`);
|
|
1458
|
+
add("word/styles.xml", styles, `${CT_WML}styles+xml`);
|
|
1459
|
+
add("word/settings.xml", this.settingsXml(), `${CT_WML}settings+xml`);
|
|
1460
|
+
if (numbering) add("word/numbering.xml", numbering, `${CT_WML}numbering+xml`);
|
|
1461
|
+
if (comments) {
|
|
1462
|
+
add("word/comments.xml", comments.comments, `${CT_WML}comments+xml`);
|
|
1463
|
+
add("word/commentsExtended.xml", comments.extended, `${CT_WML}commentsExtended+xml`);
|
|
1464
|
+
}
|
|
1465
|
+
if (people) add("word/people.xml", people, `${CT_WML}people+xml`);
|
|
1466
|
+
parts.push({ name: "word/_rels/document.xml.rels", data: this.rels.xml() });
|
|
1467
|
+
for (const file of this.media) parts.push({ name: `word/media/${file.name}`, data: file.bytes });
|
|
1468
|
+
add("docProps/core.xml", this.coreXml(now), "application/vnd.openxmlformats-package.core-properties+xml");
|
|
1469
|
+
const app = new XmlWriter();
|
|
1470
|
+
app.open("Properties", { xmlns: "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" });
|
|
1471
|
+
app.leaf("Application", void 0, "@pixerate/editor").close("Properties");
|
|
1472
|
+
add("docProps/app.xml", app.toString(), "application/vnd.openxmlformats-officedocument.extended-properties+xml");
|
|
1473
|
+
const root = new Relationships();
|
|
1474
|
+
root.add(REL.officeDocument, "word/document.xml");
|
|
1475
|
+
root.add(REL.core, "docProps/core.xml");
|
|
1476
|
+
root.add(REL.app, "docProps/app.xml");
|
|
1477
|
+
const types = new XmlWriter();
|
|
1478
|
+
types.open("Types", { xmlns: "http://schemas.openxmlformats.org/package/2006/content-types" });
|
|
1479
|
+
types.empty("Default", { Extension: "rels", ContentType: "application/vnd.openxmlformats-package.relationships+xml" });
|
|
1480
|
+
types.empty("Default", { Extension: "xml", ContentType: "application/xml" });
|
|
1481
|
+
for (const ext of this.mediaTypes) types.empty("Default", { Extension: ext, ContentType: DOCX_IMAGE_CONTENT_TYPES[ext] });
|
|
1482
|
+
for (const [name, contentType] of overrides) types.empty("Override", { PartName: name, ContentType: contentType });
|
|
1483
|
+
types.close("Types");
|
|
1484
|
+
return [
|
|
1485
|
+
{ name: "[Content_Types].xml", data: types.toString() },
|
|
1486
|
+
{ name: "_rels/.rels", data: root.xml() },
|
|
1487
|
+
...parts
|
|
1488
|
+
];
|
|
1489
|
+
}
|
|
1490
|
+
}, _class3);
|
|
1491
|
+
var isInlineType = (type) => type === "hardBreak" || type === "image" || type === "mention" || type === "text";
|
|
1492
|
+
var EXTRA_STYLES = {
|
|
1493
|
+
BlockText: {
|
|
1494
|
+
id: "BlockText",
|
|
1495
|
+
name: "Block Text",
|
|
1496
|
+
kind: "paragraph",
|
|
1497
|
+
basedOn: _chunk3CC7OPUQcjs.NORMAL_STYLE_ID,
|
|
1498
|
+
paragraph: { indentLeft: "0.5in", indentRight: "0.5in" },
|
|
1499
|
+
character: { italic: true },
|
|
1500
|
+
priority: 99,
|
|
1501
|
+
builtin: true
|
|
1502
|
+
},
|
|
1503
|
+
ListParagraph: {
|
|
1504
|
+
id: "ListParagraph",
|
|
1505
|
+
name: "List Paragraph",
|
|
1506
|
+
kind: "paragraph",
|
|
1507
|
+
basedOn: _chunk3CC7OPUQcjs.NORMAL_STYLE_ID,
|
|
1508
|
+
paragraph: { indentLeft: "0.5in" },
|
|
1509
|
+
priority: 34,
|
|
1510
|
+
quick: true,
|
|
1511
|
+
builtin: true
|
|
1512
|
+
},
|
|
1513
|
+
Code: {
|
|
1514
|
+
id: "Code",
|
|
1515
|
+
name: "Code",
|
|
1516
|
+
kind: "paragraph",
|
|
1517
|
+
basedOn: _chunk3CC7OPUQcjs.NORMAL_STYLE_ID,
|
|
1518
|
+
block: { type: "codeBlock" },
|
|
1519
|
+
character: { fontFamily: "Consolas", fontSize: "10pt" },
|
|
1520
|
+
paragraph: { spaceAfter: "0pt", lineHeight: "1" },
|
|
1521
|
+
priority: 30
|
|
1522
|
+
},
|
|
1523
|
+
Hyperlink: {
|
|
1524
|
+
id: "Hyperlink",
|
|
1525
|
+
name: "Hyperlink",
|
|
1526
|
+
kind: "character",
|
|
1527
|
+
character: { color: "#0563C1", underline: true },
|
|
1528
|
+
priority: 99,
|
|
1529
|
+
hidden: true,
|
|
1530
|
+
builtin: true
|
|
1531
|
+
},
|
|
1532
|
+
CommentReference: {
|
|
1533
|
+
id: "CommentReference",
|
|
1534
|
+
name: "annotation reference",
|
|
1535
|
+
kind: "character",
|
|
1536
|
+
character: { fontSize: "8pt" },
|
|
1537
|
+
priority: 99,
|
|
1538
|
+
hidden: true,
|
|
1539
|
+
builtin: true
|
|
1540
|
+
},
|
|
1541
|
+
CommentText: {
|
|
1542
|
+
id: "CommentText",
|
|
1543
|
+
name: "annotation text",
|
|
1544
|
+
kind: "paragraph",
|
|
1545
|
+
basedOn: _chunk3CC7OPUQcjs.NORMAL_STYLE_ID,
|
|
1546
|
+
character: { fontSize: "10pt" },
|
|
1547
|
+
priority: 99,
|
|
1548
|
+
hidden: true,
|
|
1549
|
+
builtin: true
|
|
1550
|
+
}
|
|
1551
|
+
};
|
|
1552
|
+
for (let level = 1; level <= 6; level++) {
|
|
1553
|
+
EXTRA_STYLES[`Heading${level}`] = {
|
|
1554
|
+
id: `Heading${level}`,
|
|
1555
|
+
name: `Heading ${level}`,
|
|
1556
|
+
kind: "paragraph",
|
|
1557
|
+
basedOn: _chunk3CC7OPUQcjs.NORMAL_STYLE_ID,
|
|
1558
|
+
next: _chunk3CC7OPUQcjs.NORMAL_STYLE_ID,
|
|
1559
|
+
block: { type: "heading", attrs: { level } },
|
|
1560
|
+
character: { bold: true },
|
|
1561
|
+
priority: 9,
|
|
1562
|
+
quick: true,
|
|
1563
|
+
builtin: true
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1566
|
+
function resolveInput(input, options) {
|
|
1567
|
+
if (!isEditorLike(input)) return { doc: input, options };
|
|
1568
|
+
const storage = _nullishCoalesce(input.storage, () => ( {}));
|
|
1569
|
+
return {
|
|
1570
|
+
doc: input.getJSON(),
|
|
1571
|
+
options: {
|
|
1572
|
+
...options,
|
|
1573
|
+
comments: options.comments !== void 0 ? options.comments : _nullishCoalesce(_optionalChain([storage, 'access', _112 => _112.comment, 'optionalAccess', _113 => _113.store]), () => ( null)),
|
|
1574
|
+
styles: _nullishCoalesce(_nullishCoalesce(options.styles, () => ( _optionalChain([storage, 'access', _114 => _114.paragraphStyles, 'optionalAccess', _115 => _115.registry]))), () => ( void 0))
|
|
1575
|
+
}
|
|
1576
|
+
};
|
|
1577
|
+
}
|
|
1578
|
+
function createDocxParts(input, options = {}) {
|
|
1579
|
+
const resolved = resolveInput(input, options);
|
|
1580
|
+
const builder = new DocxBuilder(
|
|
1581
|
+
_nullishCoalesce(resolved.doc, () => ( { type: "doc", content: [] })),
|
|
1582
|
+
resolved.options,
|
|
1583
|
+
threadsOf(resolved.options.comments),
|
|
1584
|
+
stylesOf(resolved.options.styles)
|
|
1585
|
+
);
|
|
1586
|
+
const parts = builder.parts(_nullishCoalesce(_optionalChain([resolved, 'access', _116 => _116.options, 'access', _117 => _117.now, 'optionalCall', _118 => _118()]), () => ( /* @__PURE__ */ new Date())));
|
|
1587
|
+
return { parts, report: builder.report };
|
|
1588
|
+
}
|
|
1589
|
+
async function exportDocx(input, options = {}) {
|
|
1590
|
+
const { parts, report } = createDocxParts(input, options);
|
|
1591
|
+
const data = await writeZip(parts, { compression: options.compression });
|
|
1592
|
+
return { data, report };
|
|
1593
|
+
}
|
|
1594
|
+
async function exportDocxBlob(input, options = {}) {
|
|
1595
|
+
const { data, report } = await exportDocx(input, options);
|
|
1596
|
+
return { blob: new Blob([data], { type: DOCX_EXPORT_MIME_TYPE }), report };
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
// src/export/controller.ts
|
|
1600
|
+
function downloadBlob(blob, fileName) {
|
|
1601
|
+
if (typeof document === "undefined" || typeof URL === "undefined" || typeof URL.createObjectURL !== "function") {
|
|
1602
|
+
return false;
|
|
1603
|
+
}
|
|
1604
|
+
const url = URL.createObjectURL(blob);
|
|
1605
|
+
const link = document.createElement("a");
|
|
1606
|
+
link.href = url;
|
|
1607
|
+
link.download = fileName;
|
|
1608
|
+
link.rel = "noopener";
|
|
1609
|
+
link.style.display = "none";
|
|
1610
|
+
document.body.appendChild(link);
|
|
1611
|
+
link.click();
|
|
1612
|
+
link.remove();
|
|
1613
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
1614
|
+
return true;
|
|
1615
|
+
}
|
|
1616
|
+
function docxFileName(name) {
|
|
1617
|
+
const base = (_nullishCoalesce(name, () => ( ""))).replace(/[\u0000-\u001f\u007f<>:"/\\|?*]+/g, " ").replace(/\s+/g, " ").trim().replace(/\.docx$/i, "").slice(0, 120);
|
|
1618
|
+
return `${base || "document"}.docx`;
|
|
1619
|
+
}
|
|
1620
|
+
var DocxExportController = (_class4 = class {
|
|
1621
|
+
constructor(getSource, options = {}) {;_class4.prototype.__init18.call(this);_class4.prototype.__init19.call(this);_class4.prototype.__init20.call(this);_class4.prototype.__init21.call(this);_class4.prototype.__init22.call(this);
|
|
1622
|
+
this.getSource = getSource;
|
|
1623
|
+
this.options = options;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
__init18() {this.state = { isExporting: false, error: null, lastReport: null }}
|
|
1628
|
+
__init19() {this.listeners = /* @__PURE__ */ new Set()}
|
|
1629
|
+
__init20() {this.pending = 0}
|
|
1630
|
+
setOptions(options) {
|
|
1631
|
+
this.options = options;
|
|
1632
|
+
}
|
|
1633
|
+
__init21() {this.getState = () => this.state}
|
|
1634
|
+
__init22() {this.subscribe = (listener) => {
|
|
1635
|
+
this.listeners.add(listener);
|
|
1636
|
+
return () => {
|
|
1637
|
+
this.listeners.delete(listener);
|
|
1638
|
+
};
|
|
1639
|
+
}}
|
|
1640
|
+
setState(patch) {
|
|
1641
|
+
this.state = { ...this.state, ...patch };
|
|
1642
|
+
this.listeners.forEach((listener) => listener(this.state));
|
|
1643
|
+
}
|
|
1644
|
+
/** Builds the `.docx` without downloading it. Resolves with `null` when there is no editor or it fails. */
|
|
1645
|
+
async exportBlob() {
|
|
1646
|
+
const source = this.getSource();
|
|
1647
|
+
if (!source) return null;
|
|
1648
|
+
this.pending++;
|
|
1649
|
+
this.setState({ isExporting: true, error: null });
|
|
1650
|
+
try {
|
|
1651
|
+
const { fileName: _fileName, onExport: _onExport, onError: _onError, ...exportOptions } = this.options;
|
|
1652
|
+
const result = await exportDocxBlob(source, exportOptions);
|
|
1653
|
+
this.setState({ lastReport: result.report });
|
|
1654
|
+
_optionalChain([this, 'access', _119 => _119.options, 'access', _120 => _120.onExport, 'optionalCall', _121 => _121(result.report, result.blob)]);
|
|
1655
|
+
return result;
|
|
1656
|
+
} catch (error) {
|
|
1657
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1658
|
+
this.setState({ error: err });
|
|
1659
|
+
if (this.options.onError) this.options.onError(err);
|
|
1660
|
+
else console.error("[Editor] DOCX export failed:", err);
|
|
1661
|
+
return null;
|
|
1662
|
+
} finally {
|
|
1663
|
+
this.pending--;
|
|
1664
|
+
if (this.pending === 0) this.setState({ isExporting: false });
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
/** Exports and downloads the document. Resolves with the report, or `null`. */
|
|
1668
|
+
async download(fileName) {
|
|
1669
|
+
const result = await this.exportBlob();
|
|
1670
|
+
if (!result) return null;
|
|
1671
|
+
downloadBlob(result.blob, docxFileName(_nullishCoalesce(_nullishCoalesce(fileName, () => ( this.options.fileName)), () => ( this.options.title))));
|
|
1672
|
+
return result.report;
|
|
1673
|
+
}
|
|
1674
|
+
}, _class4);
|
|
1675
|
+
function createDocxExportController(getSource, options) {
|
|
1676
|
+
return new DocxExportController(getSource, options);
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
exports.stripInvalidXmlChars = stripInvalidXmlChars; exports.escapeXmlText = escapeXmlText; exports.escapeXmlAttr = escapeXmlAttr; exports.XmlWriter = XmlWriter; exports.deflateRaw = deflateRaw; exports.writeZip = writeZip; exports.DOCX_EXPORT_MIME_TYPE = DOCX_EXPORT_MIME_TYPE; exports.DOCX_ANONYMOUS_AUTHOR = DOCX_ANONYMOUS_AUTHOR; exports.createDocxParts = createDocxParts; exports.exportDocx = exportDocx; exports.exportDocxBlob = exportDocxBlob; exports.downloadBlob = downloadBlob; exports.docxFileName = docxFileName; exports.DocxExportController = DocxExportController; exports.createDocxExportController = createDocxExportController;
|
|
1696
|
+
//# sourceMappingURL=chunk-TXXNBDQX.cjs.map
|