@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
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
compareDocuments
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QJSOZFCZ.js";
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_STYLES,
|
|
6
|
+
NORMAL_STYLE_ID,
|
|
7
|
+
createStyleRegistry,
|
|
8
|
+
isValidStyleId,
|
|
9
|
+
readZip
|
|
10
|
+
} from "./chunk-MR2764X2.js";
|
|
4
11
|
import {
|
|
5
12
|
INSTRUCTION_REGEX,
|
|
6
13
|
TEMPLATE_REGEX,
|
|
@@ -16,20 +23,29 @@ import {
|
|
|
16
23
|
rtfToPlainText,
|
|
17
24
|
sanitizeImportedHtml,
|
|
18
25
|
serializeRichClipboardPayload
|
|
19
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-MHEPLBFB.js";
|
|
27
|
+
import {
|
|
28
|
+
MAX_TABLE_COLUMNS,
|
|
29
|
+
MAX_TABLE_ROWS,
|
|
30
|
+
TABLE_ACTIONS,
|
|
31
|
+
createTableExtensions,
|
|
32
|
+
getTableActionState,
|
|
33
|
+
getTableState,
|
|
34
|
+
runTableAction
|
|
35
|
+
} from "./chunk-UBCFIABU.js";
|
|
20
36
|
import {
|
|
21
37
|
escapeHtml,
|
|
22
38
|
htmlToPlainText,
|
|
23
39
|
markdownToTipTapHtml,
|
|
24
40
|
plainTextToSlice
|
|
25
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-JOIREKL7.js";
|
|
26
42
|
import {
|
|
27
43
|
CommentStore,
|
|
28
44
|
TRACK_CHANGES_SKIP_META,
|
|
29
45
|
TrackChanges,
|
|
30
46
|
createReviewId,
|
|
31
47
|
trackChangesPluginKey
|
|
32
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-SWE3NPOU.js";
|
|
33
49
|
|
|
34
50
|
// src/extensions/gradient-text.ts
|
|
35
51
|
import { Mark } from "@tiptap/core";
|
|
@@ -601,10 +617,47 @@ var Mention = BaseMention.extend({
|
|
|
601
617
|
if (!attributes.color) return {};
|
|
602
618
|
return { "data-color": attributes.color };
|
|
603
619
|
}
|
|
620
|
+
},
|
|
621
|
+
// Role of an asset mention (`reference`, `style`, `start_frame`, …). The
|
|
622
|
+
// node attribute is `assetRole` so entities that already carry a `role`
|
|
623
|
+
// (e.g. a user's job title) passed as suggestion props do not set it.
|
|
624
|
+
assetRole: {
|
|
625
|
+
default: null,
|
|
626
|
+
parseHTML: (element) => {
|
|
627
|
+
const role = element.getAttribute("data-role");
|
|
628
|
+
return role && MENTION_ROLE_PATTERN.test(role) ? role : null;
|
|
629
|
+
},
|
|
630
|
+
renderHTML: (attributes) => {
|
|
631
|
+
if (!attributes.assetRole) return {};
|
|
632
|
+
return { "data-role": attributes.assetRole };
|
|
633
|
+
}
|
|
604
634
|
}
|
|
605
635
|
};
|
|
606
636
|
}
|
|
607
637
|
});
|
|
638
|
+
var MENTION_ROLE_PATTERN = /^[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9])?$/;
|
|
639
|
+
function getMentionNodes(editor) {
|
|
640
|
+
const result = [];
|
|
641
|
+
editor.state.doc.descendants((node, pos) => {
|
|
642
|
+
if (node.type?.name !== "mention") return;
|
|
643
|
+
result.push({
|
|
644
|
+
pos,
|
|
645
|
+
id: node.attrs.id ?? "",
|
|
646
|
+
label: node.attrs.label ?? "",
|
|
647
|
+
...node.attrs.type ? { type: node.attrs.type } : {},
|
|
648
|
+
...node.attrs.assetRole ? { role: node.attrs.assetRole } : {}
|
|
649
|
+
});
|
|
650
|
+
});
|
|
651
|
+
return result;
|
|
652
|
+
}
|
|
653
|
+
function setMentionRoleAt(editor, pos, role) {
|
|
654
|
+
const node = editor?.state?.doc?.nodeAt(pos);
|
|
655
|
+
if (!node || node.type.name !== "mention") return false;
|
|
656
|
+
if (role !== null && !MENTION_ROLE_PATTERN.test(role)) return false;
|
|
657
|
+
const tr = editor.state.tr.setNodeMarkup(pos, void 0, { ...node.attrs, assetRole: role });
|
|
658
|
+
editor.view.dispatch(tr);
|
|
659
|
+
return true;
|
|
660
|
+
}
|
|
608
661
|
function createMentionExtension(options = {}) {
|
|
609
662
|
const { HTMLAttributes = {}, ...rest } = options;
|
|
610
663
|
return Mention.configure({
|
|
@@ -2249,7 +2302,13 @@ var ImportAdapterRegistry = class {
|
|
|
2249
2302
|
{ fileName }
|
|
2250
2303
|
);
|
|
2251
2304
|
}
|
|
2252
|
-
const context = createImportContext(input, {
|
|
2305
|
+
const context = createImportContext(input, {
|
|
2306
|
+
fileName,
|
|
2307
|
+
mimeType,
|
|
2308
|
+
target: adapter.target,
|
|
2309
|
+
registry: this,
|
|
2310
|
+
options: options.adapterOptions?.[adapter.id]
|
|
2311
|
+
});
|
|
2253
2312
|
try {
|
|
2254
2313
|
const result = await adapter.import(input, context);
|
|
2255
2314
|
return { adapterId: adapter.id, target: adapter.target, fileName, mimeType, result };
|
|
@@ -2267,319 +2326,6 @@ var ImportAdapterRegistry = class {
|
|
|
2267
2326
|
}
|
|
2268
2327
|
};
|
|
2269
2328
|
|
|
2270
|
-
// src/import/zip.ts
|
|
2271
|
-
var ZipError = class extends Error {
|
|
2272
|
-
code;
|
|
2273
|
-
entryName;
|
|
2274
|
-
constructor(code, message, details = {}) {
|
|
2275
|
-
super(message, details.cause !== void 0 ? { cause: details.cause } : void 0);
|
|
2276
|
-
this.name = "ZipError";
|
|
2277
|
-
this.code = code;
|
|
2278
|
-
this.entryName = details.entryName;
|
|
2279
|
-
}
|
|
2280
|
-
};
|
|
2281
|
-
var DEFAULT_ZIP_MAX_ENTRIES = 1e4;
|
|
2282
|
-
var DEFAULT_ZIP_MAX_TOTAL_SIZE = 256 * 1024 * 1024;
|
|
2283
|
-
var SIG_EOCD = 101010256;
|
|
2284
|
-
var SIG_ZIP64_EOCD = 101075792;
|
|
2285
|
-
var SIG_ZIP64_LOCATOR = 117853008;
|
|
2286
|
-
var SIG_CENTRAL = 33639248;
|
|
2287
|
-
var SIG_LOCAL = 67324752;
|
|
2288
|
-
var EOCD_SIZE = 22;
|
|
2289
|
-
var MAX_COMMENT = 65535;
|
|
2290
|
-
var crcTable = null;
|
|
2291
|
-
function zipCrc32(data) {
|
|
2292
|
-
if (!crcTable) {
|
|
2293
|
-
crcTable = new Uint32Array(256);
|
|
2294
|
-
for (let n = 0; n < 256; n++) {
|
|
2295
|
-
let c = n;
|
|
2296
|
-
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
2297
|
-
crcTable[n] = c >>> 0;
|
|
2298
|
-
}
|
|
2299
|
-
}
|
|
2300
|
-
let crc = 4294967295;
|
|
2301
|
-
for (let i = 0; i < data.length; i++) crc = crcTable[(crc ^ data[i]) & 255] ^ crc >>> 8;
|
|
2302
|
-
return (crc ^ 4294967295) >>> 0;
|
|
2303
|
-
}
|
|
2304
|
-
function toBytes(data) {
|
|
2305
|
-
if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
2306
|
-
return new Uint8Array(data);
|
|
2307
|
-
}
|
|
2308
|
-
function isUnsafeZipPath(name) {
|
|
2309
|
-
if (!name || name.includes("\0")) return true;
|
|
2310
|
-
const normalized = name.replace(/\\/g, "/");
|
|
2311
|
-
if (normalized.startsWith("/") || /^[a-zA-Z]:/.test(normalized)) return true;
|
|
2312
|
-
return normalized.split("/").some((segment) => segment === "..");
|
|
2313
|
-
}
|
|
2314
|
-
var utf8 = new TextDecoder("utf-8");
|
|
2315
|
-
var CP437_HIGH = "\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";
|
|
2316
|
-
function decodeName(bytes, isUtf8) {
|
|
2317
|
-
if (isUtf8 || bytes.every((b) => b < 128)) return utf8.decode(bytes);
|
|
2318
|
-
let out = "";
|
|
2319
|
-
for (const b of bytes) out += b < 128 ? String.fromCharCode(b) : CP437_HIGH[b - 128];
|
|
2320
|
-
return out;
|
|
2321
|
-
}
|
|
2322
|
-
var ZipArchive = class {
|
|
2323
|
-
constructor(bytes, entries, maxTotalSize) {
|
|
2324
|
-
this.bytes = bytes;
|
|
2325
|
-
this.maxTotalSize = maxTotalSize;
|
|
2326
|
-
this.entries = entries;
|
|
2327
|
-
entries.forEach((entry) => {
|
|
2328
|
-
if (!this.byName.has(entry.name)) this.byName.set(entry.name, entry);
|
|
2329
|
-
});
|
|
2330
|
-
}
|
|
2331
|
-
bytes;
|
|
2332
|
-
maxTotalSize;
|
|
2333
|
-
/** Entries in central-directory order. */
|
|
2334
|
-
entries;
|
|
2335
|
-
byName = /* @__PURE__ */ new Map();
|
|
2336
|
-
extracted = 0;
|
|
2337
|
-
/** Looks up an entry by exact name (a leading `/` is ignored). */
|
|
2338
|
-
get(name) {
|
|
2339
|
-
return this.byName.get(name.replace(/^\/+/, ""));
|
|
2340
|
-
}
|
|
2341
|
-
has(name) {
|
|
2342
|
-
return !!this.get(name);
|
|
2343
|
-
}
|
|
2344
|
-
/** Uncompressed bytes extracted so far (counted against `maxTotalSize`). */
|
|
2345
|
-
get extractedSize() {
|
|
2346
|
-
return this.extracted;
|
|
2347
|
-
}
|
|
2348
|
-
/** Extracts an entry's data, verifying its size and CRC-32. */
|
|
2349
|
-
async read(entryOrName) {
|
|
2350
|
-
const entry = typeof entryOrName === "string" ? this.get(entryOrName) : entryOrName;
|
|
2351
|
-
if (!entry) {
|
|
2352
|
-
throw new ZipError("entry_not_found", `ZIP entry "${String(entryOrName)}" not found.`, {
|
|
2353
|
-
entryName: String(entryOrName)
|
|
2354
|
-
});
|
|
2355
|
-
}
|
|
2356
|
-
const name = entry.name;
|
|
2357
|
-
if (entry.encrypted) {
|
|
2358
|
-
throw new ZipError("encrypted", `ZIP entry "${name}" is encrypted; encrypted archives are not supported.`, {
|
|
2359
|
-
entryName: name
|
|
2360
|
-
});
|
|
2361
|
-
}
|
|
2362
|
-
if (entry.isDirectory) return new Uint8Array(0);
|
|
2363
|
-
const remaining = this.maxTotalSize - this.extracted;
|
|
2364
|
-
if (entry.size > remaining) {
|
|
2365
|
-
throw new ZipError(
|
|
2366
|
-
"too_large",
|
|
2367
|
-
`Extracting "${name}" (${entry.size} bytes) would exceed the ${this.maxTotalSize}-byte limit.`,
|
|
2368
|
-
{ entryName: name }
|
|
2369
|
-
);
|
|
2370
|
-
}
|
|
2371
|
-
const { bytes } = this;
|
|
2372
|
-
const offset = entry.localHeaderOffset;
|
|
2373
|
-
if (offset + 30 > bytes.length || readU32(bytes, offset) !== SIG_LOCAL) {
|
|
2374
|
-
throw new ZipError("corrupt_entry", `ZIP entry "${name}" has no valid local header.`, { entryName: name });
|
|
2375
|
-
}
|
|
2376
|
-
const dataStart = offset + 30 + readU16(bytes, offset + 26) + readU16(bytes, offset + 28);
|
|
2377
|
-
const dataEnd = dataStart + entry.compressedSize;
|
|
2378
|
-
if (dataEnd > bytes.length) {
|
|
2379
|
-
throw new ZipError("corrupt_entry", `ZIP entry "${name}" is truncated.`, { entryName: name });
|
|
2380
|
-
}
|
|
2381
|
-
const raw = bytes.subarray(dataStart, dataEnd);
|
|
2382
|
-
let data;
|
|
2383
|
-
if (entry.method === 0) {
|
|
2384
|
-
if (entry.compressedSize !== entry.size) {
|
|
2385
|
-
throw new ZipError("corrupt_entry", `Stored ZIP entry "${name}" has inconsistent sizes.`, { entryName: name });
|
|
2386
|
-
}
|
|
2387
|
-
data = raw.slice();
|
|
2388
|
-
} else if (entry.method === 8) {
|
|
2389
|
-
data = await inflateRaw(raw, entry.size, name);
|
|
2390
|
-
} else {
|
|
2391
|
-
throw new ZipError(
|
|
2392
|
-
"unsupported_feature",
|
|
2393
|
-
`ZIP entry "${name}" uses unsupported compression method ${entry.method}; only stored and deflate are supported.`,
|
|
2394
|
-
{ entryName: name }
|
|
2395
|
-
);
|
|
2396
|
-
}
|
|
2397
|
-
if (data.length !== entry.size) {
|
|
2398
|
-
throw new ZipError("corrupt_entry", `ZIP entry "${name}" size does not match the directory.`, { entryName: name });
|
|
2399
|
-
}
|
|
2400
|
-
this.extracted += data.length;
|
|
2401
|
-
if (zipCrc32(data) !== entry.crc32) {
|
|
2402
|
-
throw new ZipError("corrupt_entry", `ZIP entry "${name}" failed its CRC-32 check.`, { entryName: name });
|
|
2403
|
-
}
|
|
2404
|
-
return data;
|
|
2405
|
-
}
|
|
2406
|
-
/** Extracts an entry and decodes it as UTF-8 (a leading BOM is removed). */
|
|
2407
|
-
async readText(entryOrName) {
|
|
2408
|
-
const text = utf8.decode(await this.read(entryOrName));
|
|
2409
|
-
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
2410
|
-
}
|
|
2411
|
-
};
|
|
2412
|
-
function readU16(bytes, offset) {
|
|
2413
|
-
return bytes[offset] | bytes[offset + 1] << 8;
|
|
2414
|
-
}
|
|
2415
|
-
function readU32(bytes, offset) {
|
|
2416
|
-
return (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16 | bytes[offset + 3] << 24) >>> 0;
|
|
2417
|
-
}
|
|
2418
|
-
function readU64(bytes, offset) {
|
|
2419
|
-
const value = readU32(bytes, offset) + readU32(bytes, offset + 4) * 4294967296;
|
|
2420
|
-
if (!Number.isSafeInteger(value)) {
|
|
2421
|
-
throw new ZipError("unsupported_feature", "ZIP64 value exceeds the supported range.");
|
|
2422
|
-
}
|
|
2423
|
-
return value;
|
|
2424
|
-
}
|
|
2425
|
-
async function inflateRaw(raw, limit, entryName) {
|
|
2426
|
-
const Stream = globalThis.DecompressionStream;
|
|
2427
|
-
if (typeof Stream !== "function") {
|
|
2428
|
-
throw new ZipError(
|
|
2429
|
-
"unsupported_environment",
|
|
2430
|
-
"Inflating ZIP entries needs DecompressionStream (modern browsers, Node 18+).",
|
|
2431
|
-
{ entryName }
|
|
2432
|
-
);
|
|
2433
|
-
}
|
|
2434
|
-
const stream = new Stream("deflate-raw");
|
|
2435
|
-
const writer = stream.writable.getWriter();
|
|
2436
|
-
const reader = stream.readable.getReader();
|
|
2437
|
-
const CHUNK = 64 * 1024;
|
|
2438
|
-
const feeding = (async () => {
|
|
2439
|
-
for (let i = 0; i < raw.length; i += CHUNK) await writer.write(raw.subarray(i, i + CHUNK));
|
|
2440
|
-
await writer.close();
|
|
2441
|
-
})();
|
|
2442
|
-
feeding.catch(() => {
|
|
2443
|
-
});
|
|
2444
|
-
const chunks = [];
|
|
2445
|
-
let total = 0;
|
|
2446
|
-
try {
|
|
2447
|
-
for (; ; ) {
|
|
2448
|
-
const { done, value } = await reader.read();
|
|
2449
|
-
if (done) break;
|
|
2450
|
-
total += value.length;
|
|
2451
|
-
if (total > limit) {
|
|
2452
|
-
throw new ZipError(
|
|
2453
|
-
"corrupt_entry",
|
|
2454
|
-
`ZIP entry "${entryName}" inflates beyond its declared size of ${limit} bytes.`,
|
|
2455
|
-
{ entryName }
|
|
2456
|
-
);
|
|
2457
|
-
}
|
|
2458
|
-
chunks.push(value);
|
|
2459
|
-
}
|
|
2460
|
-
} catch (error) {
|
|
2461
|
-
reader.cancel().catch(() => {
|
|
2462
|
-
});
|
|
2463
|
-
writer.abort().catch(() => {
|
|
2464
|
-
});
|
|
2465
|
-
if (error instanceof ZipError) throw error;
|
|
2466
|
-
throw new ZipError("corrupt_entry", `ZIP entry "${entryName}" has an invalid deflate stream.`, {
|
|
2467
|
-
entryName,
|
|
2468
|
-
cause: error
|
|
2469
|
-
});
|
|
2470
|
-
}
|
|
2471
|
-
await feeding.catch(() => {
|
|
2472
|
-
});
|
|
2473
|
-
const out = new Uint8Array(total);
|
|
2474
|
-
let pos = 0;
|
|
2475
|
-
for (const chunk of chunks) {
|
|
2476
|
-
out.set(chunk, pos);
|
|
2477
|
-
pos += chunk.length;
|
|
2478
|
-
}
|
|
2479
|
-
return out;
|
|
2480
|
-
}
|
|
2481
|
-
function findEndOfCentralDirectory(bytes) {
|
|
2482
|
-
const min = Math.max(0, bytes.length - EOCD_SIZE - MAX_COMMENT);
|
|
2483
|
-
for (let i = bytes.length - EOCD_SIZE; i >= min; i--) {
|
|
2484
|
-
if (readU32(bytes, i) === SIG_EOCD && i + EOCD_SIZE + readU16(bytes, i + 20) <= bytes.length) return i;
|
|
2485
|
-
}
|
|
2486
|
-
return -1;
|
|
2487
|
-
}
|
|
2488
|
-
async function readZip(data, options = {}) {
|
|
2489
|
-
const bytes = toBytes(data);
|
|
2490
|
-
const maxEntries = options.maxEntries ?? DEFAULT_ZIP_MAX_ENTRIES;
|
|
2491
|
-
const maxTotalSize = options.maxTotalSize ?? DEFAULT_ZIP_MAX_TOTAL_SIZE;
|
|
2492
|
-
const eocd = findEndOfCentralDirectory(bytes);
|
|
2493
|
-
if (eocd < 0) throw new ZipError("invalid_archive", "Not a ZIP archive (no end of central directory record).");
|
|
2494
|
-
let diskNumber = readU16(bytes, eocd + 4);
|
|
2495
|
-
let cdDisk = readU16(bytes, eocd + 6);
|
|
2496
|
-
let count = readU16(bytes, eocd + 10);
|
|
2497
|
-
let cdSize = readU32(bytes, eocd + 12);
|
|
2498
|
-
let cdOffset = readU32(bytes, eocd + 16);
|
|
2499
|
-
if (count === 65535 || cdSize === 4294967295 || cdOffset === 4294967295) {
|
|
2500
|
-
const locator = eocd - 20;
|
|
2501
|
-
if (locator < 0 || readU32(bytes, locator) !== SIG_ZIP64_LOCATOR) {
|
|
2502
|
-
throw new ZipError("invalid_archive", "ZIP64 archive is missing its end of central directory locator.");
|
|
2503
|
-
}
|
|
2504
|
-
const record = readU64(bytes, locator + 8);
|
|
2505
|
-
if (record + 56 > bytes.length || readU32(bytes, record) !== SIG_ZIP64_EOCD) {
|
|
2506
|
-
throw new ZipError("invalid_archive", "ZIP64 end of central directory record not found.");
|
|
2507
|
-
}
|
|
2508
|
-
diskNumber = readU32(bytes, record + 16);
|
|
2509
|
-
cdDisk = readU32(bytes, record + 20);
|
|
2510
|
-
count = readU64(bytes, record + 32);
|
|
2511
|
-
cdSize = readU64(bytes, record + 40);
|
|
2512
|
-
cdOffset = readU64(bytes, record + 48);
|
|
2513
|
-
}
|
|
2514
|
-
if (diskNumber !== 0 || cdDisk !== 0) {
|
|
2515
|
-
throw new ZipError("unsupported_feature", "Multi-disk (spanned) ZIP archives are not supported.");
|
|
2516
|
-
}
|
|
2517
|
-
if (count > maxEntries) {
|
|
2518
|
-
throw new ZipError("too_many_entries", `ZIP archive has ${count} entries; the limit is ${maxEntries}.`);
|
|
2519
|
-
}
|
|
2520
|
-
if (cdOffset + cdSize > bytes.length) {
|
|
2521
|
-
throw new ZipError("invalid_archive", "ZIP central directory lies outside the file.");
|
|
2522
|
-
}
|
|
2523
|
-
const entries = [];
|
|
2524
|
-
let p = cdOffset;
|
|
2525
|
-
for (let i = 0; i < count; i++) {
|
|
2526
|
-
if (p + 46 > bytes.length || readU32(bytes, p) !== SIG_CENTRAL) {
|
|
2527
|
-
throw new ZipError("invalid_archive", "ZIP central directory is corrupt.");
|
|
2528
|
-
}
|
|
2529
|
-
const flags = readU16(bytes, p + 8);
|
|
2530
|
-
const method = readU16(bytes, p + 10);
|
|
2531
|
-
const crc32 = readU32(bytes, p + 16);
|
|
2532
|
-
let compressedSize = readU32(bytes, p + 20);
|
|
2533
|
-
let size = readU32(bytes, p + 24);
|
|
2534
|
-
const nameLength = readU16(bytes, p + 28);
|
|
2535
|
-
const extraLength = readU16(bytes, p + 30);
|
|
2536
|
-
const commentLength = readU16(bytes, p + 32);
|
|
2537
|
-
let localHeaderOffset = readU32(bytes, p + 42);
|
|
2538
|
-
const nameStart = p + 46;
|
|
2539
|
-
const extraStart = nameStart + nameLength;
|
|
2540
|
-
const next = extraStart + extraLength + commentLength;
|
|
2541
|
-
if (next > bytes.length) throw new ZipError("invalid_archive", "ZIP central directory is truncated.");
|
|
2542
|
-
for (let e = extraStart; e + 4 <= extraStart + extraLength; ) {
|
|
2543
|
-
const id = readU16(bytes, e);
|
|
2544
|
-
const len = readU16(bytes, e + 2);
|
|
2545
|
-
if (id === 1) {
|
|
2546
|
-
let f = e + 4;
|
|
2547
|
-
const end = f + len;
|
|
2548
|
-
if (size === 4294967295 && f + 8 <= end) {
|
|
2549
|
-
size = readU64(bytes, f);
|
|
2550
|
-
f += 8;
|
|
2551
|
-
}
|
|
2552
|
-
if (compressedSize === 4294967295 && f + 8 <= end) {
|
|
2553
|
-
compressedSize = readU64(bytes, f);
|
|
2554
|
-
f += 8;
|
|
2555
|
-
}
|
|
2556
|
-
if (localHeaderOffset === 4294967295 && f + 8 <= end) localHeaderOffset = readU64(bytes, f);
|
|
2557
|
-
}
|
|
2558
|
-
e += 4 + len;
|
|
2559
|
-
}
|
|
2560
|
-
const rawName = decodeName(bytes.subarray(nameStart, extraStart), (flags & 2048) !== 0);
|
|
2561
|
-
const name = rawName.replace(/\\/g, "/");
|
|
2562
|
-
p = next;
|
|
2563
|
-
if (isUnsafeZipPath(rawName)) {
|
|
2564
|
-
if (options.unsafePaths === "skip") continue;
|
|
2565
|
-
throw new ZipError("unsafe_path", `ZIP entry name "${rawName}" is absolute or escapes the archive root.`, {
|
|
2566
|
-
entryName: rawName
|
|
2567
|
-
});
|
|
2568
|
-
}
|
|
2569
|
-
entries.push({
|
|
2570
|
-
name,
|
|
2571
|
-
isDirectory: name.endsWith("/"),
|
|
2572
|
-
encrypted: (flags & 1) !== 0,
|
|
2573
|
-
method,
|
|
2574
|
-
compressedSize,
|
|
2575
|
-
size,
|
|
2576
|
-
crc32,
|
|
2577
|
-
localHeaderOffset
|
|
2578
|
-
});
|
|
2579
|
-
}
|
|
2580
|
-
return new ZipArchive(bytes, entries, maxTotalSize);
|
|
2581
|
-
}
|
|
2582
|
-
|
|
2583
2329
|
// src/import/docx.ts
|
|
2584
2330
|
var DOCX_MIME_TYPES = [
|
|
2585
2331
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
@@ -2587,6 +2333,8 @@ var DOCX_MIME_TYPES = [
|
|
|
2587
2333
|
"application/vnd.ms-word.document.macroenabled.12"
|
|
2588
2334
|
];
|
|
2589
2335
|
var DEFAULT_DOCX_MAX_IMAGE_SIZE = 10 * 1024 * 1024;
|
|
2336
|
+
var MAX_COMMENTS = 5e3;
|
|
2337
|
+
var MAX_PARENT_CHAIN = 64;
|
|
2590
2338
|
var W_NAMESPACES = /* @__PURE__ */ new Set([
|
|
2591
2339
|
"http://schemas.openxmlformats.org/wordprocessingml/2006/main",
|
|
2592
2340
|
"http://purl.oclc.org/ooxml/wordprocessingml/main"
|
|
@@ -2599,6 +2347,7 @@ var IMAGE_MIME_TYPES = {
|
|
|
2599
2347
|
gif: "image/gif",
|
|
2600
2348
|
webp: "image/webp"
|
|
2601
2349
|
};
|
|
2350
|
+
var TASK_GLYPHS = { "\u2610": false, "\u2612": true, "\u2611": true };
|
|
2602
2351
|
function isW(node, localName) {
|
|
2603
2352
|
if (!node || node.nodeType !== 1) return false;
|
|
2604
2353
|
const el = node;
|
|
@@ -2735,6 +2484,65 @@ function readNumPr(pPr) {
|
|
|
2735
2484
|
if (numId === void 0) return void 0;
|
|
2736
2485
|
return { numId, ilvl: Number(attr(wChild(numPr, "ilvl"), "val") ?? 0) || 0 };
|
|
2737
2486
|
}
|
|
2487
|
+
function twipsToCss(value) {
|
|
2488
|
+
const n = Number(value);
|
|
2489
|
+
return value !== void 0 && value !== "" && Number.isFinite(n) ? `${Math.round(n / 20 * 100) / 100}pt` : void 0;
|
|
2490
|
+
}
|
|
2491
|
+
var ALIGNMENTS = {
|
|
2492
|
+
left: "left",
|
|
2493
|
+
start: "left",
|
|
2494
|
+
center: "center",
|
|
2495
|
+
right: "right",
|
|
2496
|
+
end: "right",
|
|
2497
|
+
both: "justify",
|
|
2498
|
+
distribute: "justify"
|
|
2499
|
+
};
|
|
2500
|
+
function readParagraphFormat(pPr) {
|
|
2501
|
+
const format = {};
|
|
2502
|
+
if (!pPr) return format;
|
|
2503
|
+
const jc = attr(wChild(pPr, "jc"), "val");
|
|
2504
|
+
if (jc && ALIGNMENTS[jc]) format.textAlign = ALIGNMENTS[jc];
|
|
2505
|
+
const spacing = wChild(pPr, "spacing");
|
|
2506
|
+
const before = twipsToCss(attr(spacing, "before"));
|
|
2507
|
+
const after = twipsToCss(attr(spacing, "after"));
|
|
2508
|
+
if (before) format.spaceBefore = before;
|
|
2509
|
+
if (after) format.spaceAfter = after;
|
|
2510
|
+
const line = Number(attr(spacing, "line"));
|
|
2511
|
+
if (Number.isFinite(line) && line > 0) {
|
|
2512
|
+
const rule = attr(spacing, "lineRule") ?? "auto";
|
|
2513
|
+
format.lineHeight = rule === "auto" ? String(Math.round(line / 240 * 100) / 100) : twipsToCss(String(line));
|
|
2514
|
+
}
|
|
2515
|
+
const ind = wChild(pPr, "ind");
|
|
2516
|
+
const left = twipsToCss(attr(ind, "left") ?? attr(ind, "start"));
|
|
2517
|
+
const right = twipsToCss(attr(ind, "right") ?? attr(ind, "end"));
|
|
2518
|
+
const first = attr(ind, "firstLine");
|
|
2519
|
+
const hanging = attr(ind, "hanging");
|
|
2520
|
+
if (left) format.indentLeft = left;
|
|
2521
|
+
if (right) format.indentRight = right;
|
|
2522
|
+
if (first !== void 0) format.indentFirstLine = twipsToCss(first);
|
|
2523
|
+
else if (hanging !== void 0 && Number.isFinite(Number(hanging))) format.indentFirstLine = twipsToCss(String(-Number(hanging)));
|
|
2524
|
+
return format;
|
|
2525
|
+
}
|
|
2526
|
+
function readCharacterFormat(rPr) {
|
|
2527
|
+
const format = {};
|
|
2528
|
+
if (!rPr) return format;
|
|
2529
|
+
const f = readFormat(rPr);
|
|
2530
|
+
if (f.b !== void 0) format.bold = f.b;
|
|
2531
|
+
if (f.i !== void 0) format.italic = f.i;
|
|
2532
|
+
if (f.u !== void 0) format.underline = f.u;
|
|
2533
|
+
if (f.s !== void 0) format.strike = f.s;
|
|
2534
|
+
const fonts = wChild(rPr, "rFonts");
|
|
2535
|
+
const font = attr(fonts, "ascii") ?? attr(fonts, "hAnsi");
|
|
2536
|
+
if (font && /^[\w .-]{1,64}$/.test(font)) format.fontFamily = font;
|
|
2537
|
+
const size = Number(attr(wChild(rPr, "sz"), "val"));
|
|
2538
|
+
if (Number.isFinite(size) && size > 0 && size < 3300) format.fontSize = `${size / 2}pt`;
|
|
2539
|
+
const color = attr(wChild(rPr, "color"), "val");
|
|
2540
|
+
if (color && /^[0-9a-f]{6}$/i.test(color)) format.color = `#${color.toLowerCase()}`;
|
|
2541
|
+
if (toggle(wChild(rPr, "caps"))) format.textTransform = "uppercase";
|
|
2542
|
+
const smallCaps = toggle(wChild(rPr, "smallCaps"));
|
|
2543
|
+
if (smallCaps !== void 0) format.smallCaps = smallCaps;
|
|
2544
|
+
return format;
|
|
2545
|
+
}
|
|
2738
2546
|
function readStyles(doc) {
|
|
2739
2547
|
const styles = /* @__PURE__ */ new Map();
|
|
2740
2548
|
if (!doc) return styles;
|
|
@@ -2742,17 +2550,85 @@ function readStyles(doc) {
|
|
|
2742
2550
|
const id = attr(style, "styleId");
|
|
2743
2551
|
if (!id) return;
|
|
2744
2552
|
const pPr = wChild(style, "pPr");
|
|
2553
|
+
const rPr = wChild(style, "rPr");
|
|
2745
2554
|
const outline = attr(wChild(pPr, "outlineLvl"), "val");
|
|
2555
|
+
const priority = Number(attr(wChild(style, "uiPriority"), "val"));
|
|
2746
2556
|
styles.set(id, {
|
|
2747
2557
|
name: attr(wChild(style, "name"), "val") ?? id,
|
|
2558
|
+
type: attr(style, "type") ?? "paragraph",
|
|
2748
2559
|
basedOn: attr(wChild(style, "basedOn"), "val"),
|
|
2560
|
+
next: attr(wChild(style, "next"), "val"),
|
|
2561
|
+
link: attr(wChild(style, "link"), "val"),
|
|
2562
|
+
priority: Number.isFinite(priority) && attr(wChild(style, "uiPriority"), "val") !== void 0 ? priority : void 0,
|
|
2563
|
+
quick: toggle(wChild(style, "qFormat")),
|
|
2564
|
+
hidden: toggle(wChild(style, "semiHidden")) || toggle(wChild(style, "hidden")),
|
|
2749
2565
|
outlineLevel: outline !== void 0 ? Number(outline) : void 0,
|
|
2750
2566
|
numPr: readNumPr(pPr),
|
|
2751
|
-
format: readFormat(
|
|
2567
|
+
format: readFormat(rPr),
|
|
2568
|
+
paragraph: readParagraphFormat(pPr),
|
|
2569
|
+
character: readCharacterFormat(rPr)
|
|
2752
2570
|
});
|
|
2753
2571
|
});
|
|
2754
2572
|
return styles;
|
|
2755
2573
|
}
|
|
2574
|
+
function displayStyleName(name) {
|
|
2575
|
+
const heading = /^heading ([1-9])$/.exec(name);
|
|
2576
|
+
return heading ? `Heading ${heading[1]}` : name;
|
|
2577
|
+
}
|
|
2578
|
+
function mapStyleIds(styles) {
|
|
2579
|
+
const ids = /* @__PURE__ */ new Map();
|
|
2580
|
+
const used = /* @__PURE__ */ new Set();
|
|
2581
|
+
styles.forEach((style, fileId) => {
|
|
2582
|
+
if (style.type !== "paragraph" && style.type !== "character") return;
|
|
2583
|
+
let id = fileId.replace(/[^A-Za-z0-9_-]/g, "").slice(0, 60);
|
|
2584
|
+
if (!/^[A-Za-z]/.test(id)) id = `S${id}`;
|
|
2585
|
+
let unique = id;
|
|
2586
|
+
for (let n = 2; used.has(unique); n++) unique = `${id}${n}`;
|
|
2587
|
+
if (!isValidStyleId(unique)) return;
|
|
2588
|
+
used.add(unique);
|
|
2589
|
+
ids.set(fileId, unique);
|
|
2590
|
+
});
|
|
2591
|
+
return ids;
|
|
2592
|
+
}
|
|
2593
|
+
var styleKind = (style) => style?.type === "character" ? "character" : "paragraph";
|
|
2594
|
+
function styleDefinitions(styles, ids) {
|
|
2595
|
+
const out = [];
|
|
2596
|
+
styles.forEach((style, fileId) => {
|
|
2597
|
+
const id = ids.get(fileId);
|
|
2598
|
+
if (!id) return;
|
|
2599
|
+
const kind = styleKind(style);
|
|
2600
|
+
const sameKind = (other) => other && ids.has(other) && styleKind(styles.get(other)) === kind ? ids.get(other) : void 0;
|
|
2601
|
+
const definition = { id, name: displayStyleName(style.name || fileId), kind };
|
|
2602
|
+
const basedOn = sameKind(style.basedOn);
|
|
2603
|
+
if (basedOn) definition.basedOn = basedOn;
|
|
2604
|
+
if (kind === "paragraph") {
|
|
2605
|
+
const next = sameKind(style.next);
|
|
2606
|
+
if (next) definition.next = next;
|
|
2607
|
+
}
|
|
2608
|
+
const linked = style.link ? ids.get(style.link) : void 0;
|
|
2609
|
+
if (linked) definition.linked = linked;
|
|
2610
|
+
if (kind === "paragraph" && Object.keys(style.paragraph).length) definition.paragraph = style.paragraph;
|
|
2611
|
+
if (Object.keys(style.character).length) definition.character = style.character;
|
|
2612
|
+
if (kind === "paragraph") {
|
|
2613
|
+
const heading = /^heading([1-6])$/i.exec(fileId) ?? /^heading ([1-6])$/i.exec(style.name);
|
|
2614
|
+
if (heading) definition.block = { type: "heading", attrs: { level: Number(heading[1]) } };
|
|
2615
|
+
else if (style.outlineLevel !== void 0 && style.outlineLevel >= 0 && style.outlineLevel <= 5) {
|
|
2616
|
+
definition.block = { type: "heading", attrs: { level: style.outlineLevel + 1 } };
|
|
2617
|
+
} else if (id === "Code") definition.block = { type: "codeBlock" };
|
|
2618
|
+
else if (id === NORMAL_STYLE_ID) definition.block = { type: "paragraph" };
|
|
2619
|
+
}
|
|
2620
|
+
if (style.priority !== void 0) definition.priority = style.priority;
|
|
2621
|
+
if (style.quick) definition.quick = true;
|
|
2622
|
+
if (style.hidden) definition.hidden = true;
|
|
2623
|
+
const builtin = DEFAULT_STYLES.find((s) => s.id === id && s.kind === kind);
|
|
2624
|
+
if (builtin) {
|
|
2625
|
+
definition.builtin = true;
|
|
2626
|
+
definition.block ??= builtin.block;
|
|
2627
|
+
}
|
|
2628
|
+
out.push(definition);
|
|
2629
|
+
});
|
|
2630
|
+
return out;
|
|
2631
|
+
}
|
|
2756
2632
|
function styleChain(styles, id) {
|
|
2757
2633
|
const chain = [];
|
|
2758
2634
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2778,6 +2654,16 @@ function styleHeadingLevel(styles, id) {
|
|
|
2778
2654
|
if (id && /^title$/i.test(id)) return 1;
|
|
2779
2655
|
return void 0;
|
|
2780
2656
|
}
|
|
2657
|
+
function specialStyle(styles, id) {
|
|
2658
|
+
if (!id) return void 0;
|
|
2659
|
+
for (const style of styleChain(styles, id)) {
|
|
2660
|
+
if (/^block ?text$/i.test(style.name)) return "quote";
|
|
2661
|
+
if (/^code$/i.test(style.name)) return "code";
|
|
2662
|
+
}
|
|
2663
|
+
if (/^blocktext$/i.test(id)) return "quote";
|
|
2664
|
+
if (id === "Code") return "code";
|
|
2665
|
+
return void 0;
|
|
2666
|
+
}
|
|
2781
2667
|
function readNumbering(doc) {
|
|
2782
2668
|
const numbering = { abstracts: /* @__PURE__ */ new Map(), nums: /* @__PURE__ */ new Map() };
|
|
2783
2669
|
if (!doc) return numbering;
|
|
@@ -2807,7 +2693,184 @@ function readNumbering(doc) {
|
|
|
2807
2693
|
});
|
|
2808
2694
|
return numbering;
|
|
2809
2695
|
}
|
|
2810
|
-
|
|
2696
|
+
function readPeople(doc) {
|
|
2697
|
+
const people = /* @__PURE__ */ new Map();
|
|
2698
|
+
if (!doc) return people;
|
|
2699
|
+
descendants(doc, "person").forEach((person) => {
|
|
2700
|
+
const author = attr(person, "author");
|
|
2701
|
+
const userId = attr(descendants(person, "presenceInfo")[0], "userId");
|
|
2702
|
+
if (author && userId && !people.has(author)) people.set(author, userId);
|
|
2703
|
+
});
|
|
2704
|
+
return people;
|
|
2705
|
+
}
|
|
2706
|
+
function dateOf(value) {
|
|
2707
|
+
const ms = value ? Date.parse(value) : NaN;
|
|
2708
|
+
return Number.isFinite(ms) ? ms : 0;
|
|
2709
|
+
}
|
|
2710
|
+
function authorOf(ctx, name) {
|
|
2711
|
+
const authorName = (name ?? "").trim() || "Unknown";
|
|
2712
|
+
return { id: ctx.people.get(authorName) ?? authorName, name: authorName };
|
|
2713
|
+
}
|
|
2714
|
+
function commentBody(comment) {
|
|
2715
|
+
const lines = [];
|
|
2716
|
+
const walk = (el, line) => {
|
|
2717
|
+
for (const child of childElements(el)) {
|
|
2718
|
+
if (!isW(child)) continue;
|
|
2719
|
+
switch (child.localName) {
|
|
2720
|
+
case "t":
|
|
2721
|
+
line.push(child.textContent ?? "");
|
|
2722
|
+
break;
|
|
2723
|
+
case "tab":
|
|
2724
|
+
line.push(" ");
|
|
2725
|
+
break;
|
|
2726
|
+
case "br":
|
|
2727
|
+
case "cr":
|
|
2728
|
+
line.push("\n");
|
|
2729
|
+
break;
|
|
2730
|
+
case "delText":
|
|
2731
|
+
case "del":
|
|
2732
|
+
case "moveFrom":
|
|
2733
|
+
break;
|
|
2734
|
+
default:
|
|
2735
|
+
walk(child, line);
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
};
|
|
2739
|
+
for (const block of childElements(comment)) {
|
|
2740
|
+
if (!isW(block)) continue;
|
|
2741
|
+
const paragraphs = block.localName === "p" ? [block] : descendants(block, "p").filter((p) => isW(p));
|
|
2742
|
+
for (const p of paragraphs) {
|
|
2743
|
+
const line = [];
|
|
2744
|
+
walk(p, line);
|
|
2745
|
+
lines.push(line.join(""));
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
return lines.join("\n").trim();
|
|
2749
|
+
}
|
|
2750
|
+
function readComments(commentsXml, extendedXml, people) {
|
|
2751
|
+
const byFileId = /* @__PURE__ */ new Map();
|
|
2752
|
+
if (!commentsXml) return { threads: [], byFileId };
|
|
2753
|
+
const entries = /* @__PURE__ */ new Map();
|
|
2754
|
+
const byParaId = /* @__PURE__ */ new Map();
|
|
2755
|
+
for (const comment of descendants(commentsXml, "comment").filter((el) => isW(el))) {
|
|
2756
|
+
if (entries.size >= MAX_COMMENTS) break;
|
|
2757
|
+
const fileId = attr(comment, "id");
|
|
2758
|
+
if (fileId === void 0 || entries.has(fileId)) continue;
|
|
2759
|
+
entries.set(fileId, {
|
|
2760
|
+
fileId,
|
|
2761
|
+
author: authorOf({ people }, attr(comment, "author")),
|
|
2762
|
+
createdAt: dateOf(attr(comment, "date")),
|
|
2763
|
+
body: commentBody(comment),
|
|
2764
|
+
done: false
|
|
2765
|
+
});
|
|
2766
|
+
const paragraphs = descendants(comment, "p");
|
|
2767
|
+
const paraId = attr(paragraphs[paragraphs.length - 1], "paraId");
|
|
2768
|
+
if (paraId) byParaId.set(paraId, fileId);
|
|
2769
|
+
}
|
|
2770
|
+
if (extendedXml) {
|
|
2771
|
+
for (const ex of descendants(extendedXml, "commentEx")) {
|
|
2772
|
+
const fileId = byParaId.get(attr(ex, "paraId") ?? "");
|
|
2773
|
+
const entry = fileId !== void 0 ? entries.get(fileId) : void 0;
|
|
2774
|
+
if (!entry) continue;
|
|
2775
|
+
const parent = byParaId.get(attr(ex, "paraIdParent") ?? "");
|
|
2776
|
+
if (parent !== void 0 && parent !== fileId) entry.parent = parent;
|
|
2777
|
+
const done = attr(ex, "done");
|
|
2778
|
+
entry.done = done === "1" || done === "true";
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
const rootOf = (entry) => {
|
|
2782
|
+
let current = entry;
|
|
2783
|
+
for (let i = 0; i < MAX_PARENT_CHAIN && current.parent !== void 0; i++) {
|
|
2784
|
+
const parent = entries.get(current.parent);
|
|
2785
|
+
if (!parent || parent === entry) break;
|
|
2786
|
+
current = parent;
|
|
2787
|
+
}
|
|
2788
|
+
return current;
|
|
2789
|
+
};
|
|
2790
|
+
const threads = /* @__PURE__ */ new Map();
|
|
2791
|
+
for (const entry of entries.values()) {
|
|
2792
|
+
if (rootOf(entry) !== entry) continue;
|
|
2793
|
+
const id = createReviewId("comment");
|
|
2794
|
+
byFileId.set(entry.fileId, id);
|
|
2795
|
+
threads.set(entry.fileId, {
|
|
2796
|
+
id,
|
|
2797
|
+
anchor: null,
|
|
2798
|
+
author: entry.author,
|
|
2799
|
+
createdAt: entry.createdAt,
|
|
2800
|
+
body: entry.body,
|
|
2801
|
+
replies: [],
|
|
2802
|
+
resolved: entry.done,
|
|
2803
|
+
orphaned: false
|
|
2804
|
+
});
|
|
2805
|
+
}
|
|
2806
|
+
for (const entry of entries.values()) {
|
|
2807
|
+
const root = rootOf(entry);
|
|
2808
|
+
if (root === entry) continue;
|
|
2809
|
+
const thread = threads.get(root.fileId);
|
|
2810
|
+
if (!thread) continue;
|
|
2811
|
+
byFileId.set(entry.fileId, thread.id);
|
|
2812
|
+
const reply = {
|
|
2813
|
+
id: createReviewId("reply"),
|
|
2814
|
+
author: entry.author,
|
|
2815
|
+
body: entry.body,
|
|
2816
|
+
createdAt: entry.createdAt
|
|
2817
|
+
};
|
|
2818
|
+
thread.replies.push(reply);
|
|
2819
|
+
}
|
|
2820
|
+
return { threads: Array.from(threads.values()), byFileId };
|
|
2821
|
+
}
|
|
2822
|
+
function applyMarker(el, ctx) {
|
|
2823
|
+
switch (el.localName) {
|
|
2824
|
+
case "commentRangeStart": {
|
|
2825
|
+
const thread = ctx.commentThreads.get(attr(el, "id") ?? "");
|
|
2826
|
+
if (thread) ctx.openComments.set(thread, (ctx.openComments.get(thread) ?? 0) + 1);
|
|
2827
|
+
return true;
|
|
2828
|
+
}
|
|
2829
|
+
case "commentRangeEnd": {
|
|
2830
|
+
const thread = ctx.commentThreads.get(attr(el, "id") ?? "");
|
|
2831
|
+
const open = thread ? ctx.openComments.get(thread) : void 0;
|
|
2832
|
+
if (thread && open !== void 0) {
|
|
2833
|
+
if (open <= 1) ctx.openComments.delete(thread);
|
|
2834
|
+
else ctx.openComments.set(thread, open - 1);
|
|
2835
|
+
}
|
|
2836
|
+
return true;
|
|
2837
|
+
}
|
|
2838
|
+
case "moveFromRangeStart":
|
|
2839
|
+
case "moveToRangeStart": {
|
|
2840
|
+
const id = attr(el, "id");
|
|
2841
|
+
const name = attr(el, "name") ?? `range-${id}`;
|
|
2842
|
+
let moveId = ctx.moveIds.get(name);
|
|
2843
|
+
if (!moveId) {
|
|
2844
|
+
moveId = createReviewId("move");
|
|
2845
|
+
ctx.moveIds.set(name, moveId);
|
|
2846
|
+
}
|
|
2847
|
+
if (id !== void 0) {
|
|
2848
|
+
ctx.moveRanges.delete(id);
|
|
2849
|
+
ctx.moveRanges.set(id, { moveId, to: el.localName === "moveToRangeStart" });
|
|
2850
|
+
}
|
|
2851
|
+
return true;
|
|
2852
|
+
}
|
|
2853
|
+
case "moveFromRangeEnd":
|
|
2854
|
+
case "moveToRangeEnd":
|
|
2855
|
+
ctx.moveRanges.delete(attr(el, "id") ?? "");
|
|
2856
|
+
return true;
|
|
2857
|
+
default:
|
|
2858
|
+
return false;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
var FORMAT_MARK_TYPES = [
|
|
2862
|
+
["b", "bold"],
|
|
2863
|
+
["i", "italic"],
|
|
2864
|
+
["u", "underline"],
|
|
2865
|
+
["s", "strike"],
|
|
2866
|
+
["sub", "subscript"],
|
|
2867
|
+
["sup", "superscript"]
|
|
2868
|
+
];
|
|
2869
|
+
var formatMarks = (f) => FORMAT_MARK_TYPES.filter(([key]) => f[key]).map(([, type]) => ({ type }));
|
|
2870
|
+
var formatKey = (f) => `${f.b ? 1 : 0}${f.i ? 1 : 0}${f.u ? 1 : 0}${f.s ? 1 : 0}${f.sup ? 1 : 0}${f.sub ? 1 : 0}|${f.href ?? ""}` + (f.rev ? `|${f.rev.kind}:${f.rev.changeId}:${f.rev.moveId ?? ""}` : "") + (f.fmt ? `|f:${f.fmt.changeId}` : "") + (f.comments ? `|c:${f.comments.join(",")}` : "");
|
|
2871
|
+
function changeAttrs(change) {
|
|
2872
|
+
return ` data-change-id="${escapeHtml(change.changeId)}" data-author-id="${escapeHtml(change.authorId)}" data-author-name="${escapeHtml(change.authorName)}" data-created-at="${change.createdAt}"`;
|
|
2873
|
+
}
|
|
2811
2874
|
function wrapFormat(inner, f) {
|
|
2812
2875
|
let html = inner;
|
|
2813
2876
|
if (f.sup) html = `<sup>${html}</sup>`;
|
|
@@ -2816,10 +2879,19 @@ function wrapFormat(inner, f) {
|
|
|
2816
2879
|
if (f.u) html = `<u>${html}</u>`;
|
|
2817
2880
|
if (f.i) html = `<em>${html}</em>`;
|
|
2818
2881
|
if (f.b) html = `<strong>${html}</strong>`;
|
|
2882
|
+
if (f.fmt) {
|
|
2883
|
+
html = `<span data-change-type="format"${changeAttrs(f.fmt)} data-format-before="${escapeHtml(JSON.stringify(f.fmt.before))}" data-format-after="${escapeHtml(JSON.stringify(f.fmt.after))}">${html}</span>`;
|
|
2884
|
+
}
|
|
2885
|
+
if (f.rev) {
|
|
2886
|
+
const tag = f.rev.kind === "insertion" ? "ins" : "del";
|
|
2887
|
+
const move = f.rev.moveId ? ` data-move-id="${escapeHtml(f.rev.moveId)}"` : "";
|
|
2888
|
+
html = `<${tag} data-change-type="${f.rev.kind}"${changeAttrs(f.rev)}${move}>${html}</${tag}>`;
|
|
2889
|
+
}
|
|
2890
|
+
for (const id of [...f.comments ?? []].reverse()) html = `<span data-comment-id="${escapeHtml(id)}">${html}</span>`;
|
|
2819
2891
|
if (f.href) html = `<a href="${escapeHtml(f.href)}">${html}</a>`;
|
|
2820
2892
|
return html;
|
|
2821
2893
|
}
|
|
2822
|
-
function renderSegments(segments) {
|
|
2894
|
+
function renderSegments(segments, code = false) {
|
|
2823
2895
|
let html = "";
|
|
2824
2896
|
let i = 0;
|
|
2825
2897
|
while (i < segments.length) {
|
|
@@ -2829,11 +2901,12 @@ function renderSegments(segments) {
|
|
|
2829
2901
|
for (; j < segments.length && formatKey(segments[j].format) === key; j++) {
|
|
2830
2902
|
const seg = segments[j];
|
|
2831
2903
|
if (seg.kind === "text") inner += escapeHtml(seg.text);
|
|
2832
|
-
else if (seg.kind === "br") inner += "<br>";
|
|
2833
|
-
else if (seg.kind === "img") inner += `<img src="${escapeHtml(seg.src)}" alt="${escapeHtml(seg.alt)}">`;
|
|
2904
|
+
else if (seg.kind === "br") inner += code ? "\n" : "<br>";
|
|
2905
|
+
else if (seg.kind === "img") inner += code ? "" : `<img src="${escapeHtml(seg.src)}" alt="${escapeHtml(seg.alt)}">`;
|
|
2834
2906
|
else inner += `<sup>${seg.n}</sup>`;
|
|
2835
2907
|
}
|
|
2836
|
-
|
|
2908
|
+
const format = segments[i].format;
|
|
2909
|
+
html += wrapFormat(inner, code ? { rev: format.rev, comments: format.comments } : format);
|
|
2837
2910
|
i = j;
|
|
2838
2911
|
}
|
|
2839
2912
|
return html;
|
|
@@ -2858,9 +2931,33 @@ var ParagraphRenderer = class {
|
|
|
2858
2931
|
segments = [];
|
|
2859
2932
|
/** Open complex fields (`w:fldChar`), innermost last. */
|
|
2860
2933
|
fields = [];
|
|
2861
|
-
|
|
2934
|
+
collect(p) {
|
|
2862
2935
|
this.walk(p, {});
|
|
2863
|
-
return
|
|
2936
|
+
return this;
|
|
2937
|
+
}
|
|
2938
|
+
render(p) {
|
|
2939
|
+
return this.collect(p).html();
|
|
2940
|
+
}
|
|
2941
|
+
html(code = false) {
|
|
2942
|
+
return renderSegments(this.segments, code);
|
|
2943
|
+
}
|
|
2944
|
+
/** Removes a leading task-list glyph (`☐ ` / `☒ `) and returns its checked state. */
|
|
2945
|
+
takeTaskGlyph() {
|
|
2946
|
+
const first = this.segments[0];
|
|
2947
|
+
if (!first || first.kind !== "text") return void 0;
|
|
2948
|
+
const glyph = first.text.charAt(0);
|
|
2949
|
+
if (!(glyph in TASK_GLYPHS)) return void 0;
|
|
2950
|
+
const rest = first.text.slice(1).replace(/^ /, "");
|
|
2951
|
+
if (rest) first.text = rest;
|
|
2952
|
+
else {
|
|
2953
|
+
this.segments.shift();
|
|
2954
|
+
const next = this.segments[0];
|
|
2955
|
+
if (next?.kind === "text") {
|
|
2956
|
+
next.text = next.text.replace(/^ /, "");
|
|
2957
|
+
if (!next.text) this.segments.shift();
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
return TASK_GLYPHS[glyph];
|
|
2864
2961
|
}
|
|
2865
2962
|
fieldHref() {
|
|
2866
2963
|
for (let i = this.fields.length - 1; i >= 0; i--) {
|
|
@@ -2871,8 +2968,38 @@ var ParagraphRenderer = class {
|
|
|
2871
2968
|
inFieldInstruction() {
|
|
2872
2969
|
return this.fields.some((field) => !field.separated);
|
|
2873
2970
|
}
|
|
2971
|
+
/** A tracked change id shared with the previous change when adjacent and by the same author at the same time. */
|
|
2972
|
+
changeId(key) {
|
|
2973
|
+
const last = this.ctx.lastChange;
|
|
2974
|
+
if (last && last.key === key && last.end === this.ctx.segmentCount) return last.changeId;
|
|
2975
|
+
return createReviewId("change");
|
|
2976
|
+
}
|
|
2977
|
+
change(el, kind, extra = "") {
|
|
2978
|
+
const author = authorOf(this.ctx, attr(el, "author"));
|
|
2979
|
+
const createdAt = dateOf(attr(el, "date"));
|
|
2980
|
+
const key = `${kind}|${author.name}|${createdAt}|${extra}`;
|
|
2981
|
+
return {
|
|
2982
|
+
key,
|
|
2983
|
+
info: { changeId: this.changeId(key), authorId: author.id, authorName: author.name, createdAt }
|
|
2984
|
+
};
|
|
2985
|
+
}
|
|
2986
|
+
revision(el, kind) {
|
|
2987
|
+
let moveId;
|
|
2988
|
+
if (el.localName === "moveFrom" || el.localName === "moveTo") {
|
|
2989
|
+
const to = el.localName === "moveTo";
|
|
2990
|
+
for (const range of this.ctx.moveRanges.values()) if (range.to === to) moveId = range.moveId;
|
|
2991
|
+
moveId ??= createReviewId("move");
|
|
2992
|
+
}
|
|
2993
|
+
const { info, key } = this.change(el, kind, moveId ?? "");
|
|
2994
|
+
return { rev: { ...info, kind, ...moveId ? { moveId } : {} }, key };
|
|
2995
|
+
}
|
|
2996
|
+
walkChange(el, base, kind) {
|
|
2997
|
+
const { rev, key } = this.revision(el, kind);
|
|
2998
|
+
this.walk(el, { ...base, rev });
|
|
2999
|
+
this.ctx.lastChange = { key, changeId: rev.changeId, end: this.ctx.segmentCount };
|
|
3000
|
+
}
|
|
2874
3001
|
walk(el, base) {
|
|
2875
|
-
const
|
|
3002
|
+
const tracked = this.ctx.tracked;
|
|
2876
3003
|
for (const child of childElements(el)) {
|
|
2877
3004
|
if (!isW(child)) {
|
|
2878
3005
|
continue;
|
|
@@ -2896,11 +3023,13 @@ var ParagraphRenderer = class {
|
|
|
2896
3023
|
}
|
|
2897
3024
|
case "ins":
|
|
2898
3025
|
case "moveTo":
|
|
2899
|
-
if (accepted) this.walk(child, base);
|
|
3026
|
+
if (tracked === "accepted") this.walk(child, base);
|
|
3027
|
+
else if (tracked === "marks") this.walkChange(child, base, "insertion");
|
|
2900
3028
|
break;
|
|
2901
3029
|
case "del":
|
|
2902
3030
|
case "moveFrom":
|
|
2903
|
-
if (
|
|
3031
|
+
if (tracked === "original") this.walk(child, base);
|
|
3032
|
+
else if (tracked === "marks") this.walkChange(child, base, "deletion");
|
|
2904
3033
|
break;
|
|
2905
3034
|
case "sdt":
|
|
2906
3035
|
this.walk(wChild(child, "sdtContent") ?? child, base);
|
|
@@ -2913,24 +3042,42 @@ var ParagraphRenderer = class {
|
|
|
2913
3042
|
this.walk(child, base);
|
|
2914
3043
|
break;
|
|
2915
3044
|
default:
|
|
3045
|
+
applyMarker(child, this.ctx);
|
|
2916
3046
|
break;
|
|
2917
3047
|
}
|
|
2918
3048
|
}
|
|
2919
3049
|
}
|
|
2920
3050
|
run(r, base) {
|
|
2921
3051
|
const rPr = wChild(r, "rPr");
|
|
2922
|
-
const
|
|
3052
|
+
const runStyle = this.ctx.styles.get(attr(wChild(rPr, "rStyle"), "val") ?? "");
|
|
3053
|
+
const styleFormat = base.href && runStyle && /^hyperlink$/i.test(runStyle.name) ? {} : runStyle?.format ?? {};
|
|
2923
3054
|
const own = readFormat(rPr);
|
|
2924
3055
|
const format = { ...base, ...styleFormat, ...own };
|
|
3056
|
+
const rPrChange = wChild(rPr, "rPrChange");
|
|
3057
|
+
let changeKey;
|
|
3058
|
+
if (rPrChange && this.ctx.tracked === "marks") {
|
|
3059
|
+
const { info, key } = this.change(rPrChange, "format");
|
|
3060
|
+
const before = { ...styleFormat, ...readFormat(wChild(rPrChange, "rPr")) };
|
|
3061
|
+
format.fmt = { ...info, before: formatMarks(before), after: formatMarks(format) };
|
|
3062
|
+
changeKey = key;
|
|
3063
|
+
}
|
|
2925
3064
|
for (const child of childElements(r)) {
|
|
2926
3065
|
this.runChild(child, format);
|
|
2927
3066
|
}
|
|
3067
|
+
if (format.fmt && changeKey) {
|
|
3068
|
+
this.ctx.lastChange = { key: changeKey, changeId: format.fmt.changeId, end: this.ctx.segmentCount };
|
|
3069
|
+
}
|
|
2928
3070
|
}
|
|
2929
3071
|
runChild(child, format) {
|
|
2930
3072
|
const push = (segment) => {
|
|
2931
3073
|
if (this.inFieldInstruction()) return;
|
|
2932
3074
|
const href = format.href ?? this.fieldHref();
|
|
2933
|
-
|
|
3075
|
+
let out = href && !format.href ? { ...segment, format: { ...format, href } } : segment;
|
|
3076
|
+
if (this.ctx.openComments.size) {
|
|
3077
|
+
out = { ...out, format: { ...out.format, comments: Array.from(this.ctx.openComments.keys()) } };
|
|
3078
|
+
}
|
|
3079
|
+
this.segments.push(out);
|
|
3080
|
+
this.ctx.segmentCount++;
|
|
2934
3081
|
};
|
|
2935
3082
|
if (child.localName === "AlternateContent") {
|
|
2936
3083
|
const branch = childElements(child).find(
|
|
@@ -2945,7 +3092,7 @@ var ParagraphRenderer = class {
|
|
|
2945
3092
|
push({ kind: "text", text: child.textContent ?? "", format });
|
|
2946
3093
|
break;
|
|
2947
3094
|
case "delText":
|
|
2948
|
-
if (this.ctx.tracked
|
|
3095
|
+
if (this.ctx.tracked !== "accepted") push({ kind: "text", text: child.textContent ?? "", format });
|
|
2949
3096
|
break;
|
|
2950
3097
|
case "tab":
|
|
2951
3098
|
case "ptab":
|
|
@@ -3009,8 +3156,16 @@ var ParagraphRenderer = class {
|
|
|
3009
3156
|
push({ kind: "img", src, alt, format });
|
|
3010
3157
|
}
|
|
3011
3158
|
};
|
|
3159
|
+
var MARKERS = /* @__PURE__ */ new Set([
|
|
3160
|
+
"commentRangeStart",
|
|
3161
|
+
"commentRangeEnd",
|
|
3162
|
+
"moveFromRangeStart",
|
|
3163
|
+
"moveFromRangeEnd",
|
|
3164
|
+
"moveToRangeStart",
|
|
3165
|
+
"moveToRangeEnd"
|
|
3166
|
+
]);
|
|
3012
3167
|
function flattenBlocks(container, ctx, out = []) {
|
|
3013
|
-
const
|
|
3168
|
+
const tracked = ctx.tracked;
|
|
3014
3169
|
for (const child of childElements(container)) {
|
|
3015
3170
|
if (!isW(child)) continue;
|
|
3016
3171
|
switch (child.localName) {
|
|
@@ -3027,13 +3182,14 @@ function flattenBlocks(container, ctx, out = []) {
|
|
|
3027
3182
|
break;
|
|
3028
3183
|
case "ins":
|
|
3029
3184
|
case "moveTo":
|
|
3030
|
-
if (
|
|
3185
|
+
if (tracked !== "original") flattenBlocks(child, ctx, out);
|
|
3031
3186
|
break;
|
|
3032
3187
|
case "del":
|
|
3033
3188
|
case "moveFrom":
|
|
3034
|
-
if (
|
|
3189
|
+
if (tracked !== "accepted") flattenBlocks(child, ctx, out);
|
|
3035
3190
|
break;
|
|
3036
3191
|
default:
|
|
3192
|
+
if (MARKERS.has(child.localName)) out.push(child);
|
|
3037
3193
|
break;
|
|
3038
3194
|
}
|
|
3039
3195
|
}
|
|
@@ -3062,9 +3218,30 @@ function paragraphInfo(p, ctx) {
|
|
|
3062
3218
|
start: num?.starts.get(numPr.ilvl) ?? def?.start ?? 1
|
|
3063
3219
|
};
|
|
3064
3220
|
}
|
|
3065
|
-
|
|
3221
|
+
const special = heading === void 0 && !list ? specialStyle(ctx.styles, styleId) : void 0;
|
|
3222
|
+
return { heading, list, styleId, special, pPr };
|
|
3223
|
+
}
|
|
3224
|
+
function blockChangeAttr(pPr, ctx) {
|
|
3225
|
+
const change = wChild(pPr, "pPrChange");
|
|
3226
|
+
if (!change) return "";
|
|
3227
|
+
const oldPPr = wChild(change, "pPr");
|
|
3228
|
+
const oldStyle = attr(wChild(oldPPr, "pStyle"), "val");
|
|
3229
|
+
const oldOutline = attr(wChild(oldPPr, "outlineLvl"), "val");
|
|
3230
|
+
const level = oldOutline !== void 0 ? Number(oldOutline) >= 0 && Number(oldOutline) <= 5 ? Number(oldOutline) + 1 : void 0 : styleHeadingLevel(ctx.styles, oldStyle);
|
|
3231
|
+
const mappedStyle = oldStyle ? ctx.styleIds.get(oldStyle) : void 0;
|
|
3232
|
+
const previous = level !== void 0 ? { type: "heading", attrs: { level }, wrappers: [] } : specialStyle(ctx.styles, oldStyle) === "code" ? { type: "codeBlock", attrs: {}, wrappers: [] } : { type: "paragraph", attrs: mappedStyle && mappedStyle !== NORMAL_STYLE_ID ? { styleId: mappedStyle } : {}, wrappers: [] };
|
|
3233
|
+
const author = authorOf(ctx, attr(change, "author"));
|
|
3234
|
+
const record = {
|
|
3235
|
+
changeId: createReviewId("change"),
|
|
3236
|
+
authorId: author.id,
|
|
3237
|
+
authorName: author.name,
|
|
3238
|
+
authorColor: null,
|
|
3239
|
+
createdAt: dateOf(attr(change, "date")),
|
|
3240
|
+
previous
|
|
3241
|
+
};
|
|
3242
|
+
return ` data-block-change="${escapeHtml(JSON.stringify(record))}"`;
|
|
3066
3243
|
}
|
|
3067
|
-
function renderBlocks(container, ctx, part) {
|
|
3244
|
+
function renderBlocks(container, ctx, part, topLevel = false) {
|
|
3068
3245
|
let html = "";
|
|
3069
3246
|
const stack = [];
|
|
3070
3247
|
const closeList = () => {
|
|
@@ -3074,34 +3251,62 @@ function renderBlocks(container, ctx, part) {
|
|
|
3074
3251
|
const closeAll = () => {
|
|
3075
3252
|
while (stack.length) closeList();
|
|
3076
3253
|
};
|
|
3254
|
+
let group = null;
|
|
3255
|
+
const flush = () => {
|
|
3256
|
+
if (!group) return;
|
|
3257
|
+
html += group.kind === "quote" ? `<blockquote>${group.parts.join("")}</blockquote>` : `<pre><code>${group.parts.join("\n")}</code></pre>`;
|
|
3258
|
+
group = null;
|
|
3259
|
+
};
|
|
3077
3260
|
for (const block of flattenBlocks(container, ctx)) {
|
|
3261
|
+
if (MARKERS.has(block.localName)) {
|
|
3262
|
+
applyMarker(block, ctx);
|
|
3263
|
+
continue;
|
|
3264
|
+
}
|
|
3078
3265
|
if (block.localName === "tbl") {
|
|
3079
3266
|
closeAll();
|
|
3267
|
+
flush();
|
|
3080
3268
|
html += renderTable(block, ctx, part);
|
|
3081
3269
|
continue;
|
|
3082
3270
|
}
|
|
3083
|
-
const { heading, list } = paragraphInfo(block, ctx);
|
|
3084
|
-
const
|
|
3085
|
-
|
|
3271
|
+
const { heading, list, styleId, special, pPr } = paragraphInfo(block, ctx);
|
|
3272
|
+
const renderer = new ParagraphRenderer(ctx, part).collect(block);
|
|
3273
|
+
if (special) {
|
|
3274
|
+
closeAll();
|
|
3275
|
+
if (group && group.kind !== special) flush();
|
|
3276
|
+
group ??= { kind: special, parts: [] };
|
|
3277
|
+
group.parts.push(special === "code" ? renderer.html(true) : `<p>${renderer.html()}</p>`);
|
|
3278
|
+
continue;
|
|
3279
|
+
}
|
|
3280
|
+
flush();
|
|
3281
|
+
const task = list && !list.ordered ? renderer.takeTaskGlyph() : void 0;
|
|
3282
|
+
const inner = renderer.html();
|
|
3283
|
+
const mappedStyle = styleId ? ctx.styleIds.get(styleId) : void 0;
|
|
3284
|
+
const styleAttr = !heading && !list && mappedStyle && mappedStyle !== NORMAL_STYLE_ID ? ` data-style="${escapeHtml(mappedStyle)}"` : "";
|
|
3285
|
+
const changeAttr = topLevel && !list && ctx.tracked === "marks" ? blockChangeAttr(pPr, ctx) : "";
|
|
3286
|
+
const blockHtml = heading ? `<h${heading}${changeAttr}>${inner}</h${heading}>` : `<p${styleAttr}${changeAttr}>${inner}</p>`;
|
|
3086
3287
|
if (!list) {
|
|
3087
3288
|
closeAll();
|
|
3088
3289
|
html += blockHtml;
|
|
3089
3290
|
continue;
|
|
3090
3291
|
}
|
|
3091
3292
|
const tag = list.ordered ? "ol" : "ul";
|
|
3293
|
+
const isTask = task !== void 0;
|
|
3294
|
+
const item = isTask ? `<li data-type="taskItem" data-checked="${task ? "true" : "false"}">` : "<li>";
|
|
3092
3295
|
while (stack.length && stack[stack.length - 1].level > list.level) closeList();
|
|
3093
3296
|
const top = stack[stack.length - 1];
|
|
3094
|
-
if (top && top.level === list.level && top.tag === tag) {
|
|
3095
|
-
html +=
|
|
3297
|
+
if (top && top.level === list.level && top.tag === tag && top.task === isTask) {
|
|
3298
|
+
html += `</li>${item}`;
|
|
3096
3299
|
} else {
|
|
3097
3300
|
if (top && top.level === list.level) closeList();
|
|
3098
3301
|
const start2 = tag === "ol" && list.start !== 1 ? ` start="${list.start}"` : "";
|
|
3099
|
-
|
|
3100
|
-
|
|
3302
|
+
const type = isTask ? ' data-type="taskList"' : "";
|
|
3303
|
+
html += `<${tag}${type}${start2}>${item}`;
|
|
3304
|
+
stack.push({ level: list.level, tag, task: isTask });
|
|
3101
3305
|
}
|
|
3102
3306
|
html += blockHtml;
|
|
3103
3307
|
}
|
|
3104
3308
|
closeAll();
|
|
3309
|
+
flush();
|
|
3105
3310
|
return html;
|
|
3106
3311
|
}
|
|
3107
3312
|
function renderTable(tbl, ctx, part) {
|
|
@@ -3195,12 +3400,38 @@ async function docxToDocumentImport(data, options = {}) {
|
|
|
3195
3400
|
const baseDir = dirname(mainPath);
|
|
3196
3401
|
const stylesPath = partByType("styles") ?? `${baseDir}styles.xml`;
|
|
3197
3402
|
const numberingPath = partByType("numbering") ?? `${baseDir}numbering.xml`;
|
|
3403
|
+
const styles = readStyles(await readXmlPart(zip, Parser, stylesPath));
|
|
3404
|
+
const useStyles = options.paragraphStyles !== false;
|
|
3405
|
+
const styleIds = useStyles ? mapStyleIds(styles) : /* @__PURE__ */ new Map();
|
|
3406
|
+
const peoplePath = partByType("people");
|
|
3407
|
+
const people = readPeople(peoplePath ? await readXmlPart(zip, Parser, peoplePath) : null);
|
|
3408
|
+
let threads = [];
|
|
3409
|
+
let commentThreads = /* @__PURE__ */ new Map();
|
|
3410
|
+
if (options.comments !== false) {
|
|
3411
|
+
const commentsPath = partByType("comments");
|
|
3412
|
+
const extendedPath = partByType("commentsExtended");
|
|
3413
|
+
const read = readComments(
|
|
3414
|
+
commentsPath ? await readXmlPart(zip, Parser, commentsPath) : null,
|
|
3415
|
+
extendedPath ? await readXmlPart(zip, Parser, extendedPath) : null,
|
|
3416
|
+
people
|
|
3417
|
+
);
|
|
3418
|
+
threads = read.threads;
|
|
3419
|
+
commentThreads = read.byFileId;
|
|
3420
|
+
}
|
|
3198
3421
|
const ctx = {
|
|
3199
|
-
styles
|
|
3422
|
+
styles,
|
|
3200
3423
|
numbering: readNumbering(await readXmlPart(zip, Parser, numberingPath)),
|
|
3201
3424
|
notes: /* @__PURE__ */ new Map(),
|
|
3202
3425
|
noteOrder: [],
|
|
3203
|
-
tracked: options.trackedChanges ?? "accepted"
|
|
3426
|
+
tracked: options.trackedChanges ?? "accepted",
|
|
3427
|
+
styleIds,
|
|
3428
|
+
people,
|
|
3429
|
+
commentThreads,
|
|
3430
|
+
openComments: /* @__PURE__ */ new Map(),
|
|
3431
|
+
moveRanges: /* @__PURE__ */ new Map(),
|
|
3432
|
+
moveIds: /* @__PURE__ */ new Map(),
|
|
3433
|
+
segmentCount: 0,
|
|
3434
|
+
lastChange: null
|
|
3204
3435
|
};
|
|
3205
3436
|
for (const kind of ["footnote", "endnote"]) {
|
|
3206
3437
|
const path = partByType(`${kind}s`) ?? `${baseDir}${kind}s.xml`;
|
|
@@ -3215,7 +3446,7 @@ async function docxToDocumentImport(data, options = {}) {
|
|
|
3215
3446
|
});
|
|
3216
3447
|
}
|
|
3217
3448
|
const part = { rels, images: await loadImages(zip, documentXml, rels, options) };
|
|
3218
|
-
let html = renderBlocks(body, ctx, part);
|
|
3449
|
+
let html = renderBlocks(body, ctx, part, true);
|
|
3219
3450
|
if (ctx.noteOrder.length) {
|
|
3220
3451
|
let notesHtml = "";
|
|
3221
3452
|
for (let i = 0; i < ctx.noteOrder.length; i++) {
|
|
@@ -3225,7 +3456,13 @@ async function docxToDocumentImport(data, options = {}) {
|
|
|
3225
3456
|
html += `<hr><ol>${notesHtml}</ol>`;
|
|
3226
3457
|
}
|
|
3227
3458
|
const sanitized = sanitizeImportedHtml(html);
|
|
3228
|
-
|
|
3459
|
+
const result = { html: sanitized, text: htmlToPlainText(sanitized) };
|
|
3460
|
+
if (threads.length) result.comments = { version: 1, threads };
|
|
3461
|
+
if (useStyles) {
|
|
3462
|
+
const definitions = styleDefinitions(styles, styleIds);
|
|
3463
|
+
if (definitions.length) result.styles = createStyleRegistry({ styles: definitions });
|
|
3464
|
+
}
|
|
3465
|
+
return result;
|
|
3229
3466
|
}
|
|
3230
3467
|
function createDocxImportAdapter(options = {}) {
|
|
3231
3468
|
return {
|
|
@@ -3342,16 +3579,46 @@ function insertImportedDocument(target, content, options = {}) {
|
|
|
3342
3579
|
view.dispatch(tr.scrollIntoView().setMeta("uiEvent", "drop"));
|
|
3343
3580
|
return end;
|
|
3344
3581
|
}
|
|
3582
|
+
function applyImportedReviewData(editor, content) {
|
|
3583
|
+
const storage = editor?.storage ?? {};
|
|
3584
|
+
let comments = 0;
|
|
3585
|
+
let styles = 0;
|
|
3586
|
+
const store = storage.comment?.store;
|
|
3587
|
+
const threads = content.comments?.threads ?? [];
|
|
3588
|
+
if (store && threads.length) {
|
|
3589
|
+
const existing = store.toJSON().threads;
|
|
3590
|
+
const fresh = threads.filter((thread) => !existing.some((t) => t.id === thread.id));
|
|
3591
|
+
if (fresh.length) {
|
|
3592
|
+
store.load({ version: 1, threads: [...existing, ...fresh] });
|
|
3593
|
+
comments = fresh.length;
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
const registry = storage.paragraphStyles?.registry;
|
|
3597
|
+
if (registry && content.styles) {
|
|
3598
|
+
for (const style of content.styles.list()) {
|
|
3599
|
+
if (registry.get(style.id)) continue;
|
|
3600
|
+
registry.upsert(style);
|
|
3601
|
+
styles++;
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
return { comments, styles };
|
|
3605
|
+
}
|
|
3345
3606
|
async function importFilesIntoEditor(target, files, options = {}) {
|
|
3346
3607
|
const registry = options.registry ?? defaultImportRegistry;
|
|
3347
3608
|
const outcomes = [];
|
|
3348
3609
|
let at = options.at;
|
|
3349
3610
|
for (const file of Array.from(files)) {
|
|
3350
3611
|
try {
|
|
3351
|
-
const outcome = await registry.importFile(file, {
|
|
3612
|
+
const outcome = await registry.importFile(file, {
|
|
3613
|
+
target: "document",
|
|
3614
|
+
adapterOptions: options.adapterOptions
|
|
3615
|
+
});
|
|
3352
3616
|
const view = toView(target);
|
|
3353
3617
|
if (view.isDestroyed) break;
|
|
3354
3618
|
at = insertImportedDocument(view, outcome.result, { at, asPlainText: options.asPlainText });
|
|
3619
|
+
if (!options.asPlainText && "storage" in target) {
|
|
3620
|
+
applyImportedReviewData(target, outcome.result);
|
|
3621
|
+
}
|
|
3355
3622
|
outcomes.push(outcome);
|
|
3356
3623
|
options.onImport?.(outcome, file);
|
|
3357
3624
|
} catch (error) {
|
|
@@ -3382,6 +3649,7 @@ var FileImport = Extension8.create({
|
|
|
3382
3649
|
addOptions() {
|
|
3383
3650
|
return {
|
|
3384
3651
|
registry: void 0,
|
|
3652
|
+
adapterOptions: void 0,
|
|
3385
3653
|
asPlainText: false,
|
|
3386
3654
|
enableDrop: true,
|
|
3387
3655
|
enablePaste: true,
|
|
@@ -3397,6 +3665,7 @@ var FileImport = Extension8.create({
|
|
|
3397
3665
|
registry: registry(),
|
|
3398
3666
|
at,
|
|
3399
3667
|
asPlainText: options.asPlainText,
|
|
3668
|
+
adapterOptions: options.adapterOptions,
|
|
3400
3669
|
onImport: options.onImport,
|
|
3401
3670
|
onError: options.onImportError
|
|
3402
3671
|
});
|
|
@@ -6469,6 +6738,365 @@ function safeClipboard(get) {
|
|
|
6469
6738
|
}
|
|
6470
6739
|
}
|
|
6471
6740
|
|
|
6741
|
+
// src/extensions/paragraph-styles/extension.ts
|
|
6742
|
+
import { Extension as Extension13, Mark as Mark5, mergeAttributes as mergeAttributes7 } from "@tiptap/core";
|
|
6743
|
+
import { Plugin as Plugin15, PluginKey as PluginKey12 } from "@tiptap/pm/state";
|
|
6744
|
+
var STYLE_ID_ATTRIBUTE = "styleId";
|
|
6745
|
+
var CHARACTER_STYLE_MARK_NAME = "characterStyle";
|
|
6746
|
+
var paragraphStylesPluginKey = new PluginKey12("paragraphStyles");
|
|
6747
|
+
function getStyleRegistry(editor) {
|
|
6748
|
+
return editor?.storage?.paragraphStyles?.registry ?? null;
|
|
6749
|
+
}
|
|
6750
|
+
function headingLevels(editor) {
|
|
6751
|
+
const heading = editor?.extensionManager?.extensions.find((e) => e.name === "heading");
|
|
6752
|
+
const levels = heading?.options?.levels;
|
|
6753
|
+
return Array.isArray(levels) ? levels : null;
|
|
6754
|
+
}
|
|
6755
|
+
function isParagraphStyleAvailable(editor, registry, id) {
|
|
6756
|
+
const style = registry.get(id);
|
|
6757
|
+
if (!style || style.kind !== "paragraph") return false;
|
|
6758
|
+
const block = registry.resolve(id).block;
|
|
6759
|
+
if (!editor.schema.nodes[block.type]) return false;
|
|
6760
|
+
if (block.type === "heading") {
|
|
6761
|
+
const levels = headingLevels(editor);
|
|
6762
|
+
if (levels && !levels.includes(Number(block.attrs?.level))) return false;
|
|
6763
|
+
}
|
|
6764
|
+
return true;
|
|
6765
|
+
}
|
|
6766
|
+
function getParagraphStyleAt(state, registry, pos = state.selection.from) {
|
|
6767
|
+
const $pos = state.doc.resolve(Math.max(0, Math.min(pos, state.doc.content.size)));
|
|
6768
|
+
const block = $pos.parent;
|
|
6769
|
+
if (!block.isTextblock) return null;
|
|
6770
|
+
return registry.styleOfBlock(block.type.name, block.attrs);
|
|
6771
|
+
}
|
|
6772
|
+
var MARK_FORMAT = {
|
|
6773
|
+
bold: "bold",
|
|
6774
|
+
italic: "italic",
|
|
6775
|
+
underline: "underline",
|
|
6776
|
+
strike: "strike"
|
|
6777
|
+
};
|
|
6778
|
+
function selectionMarks(state) {
|
|
6779
|
+
const { from, to, empty, $from } = state.selection;
|
|
6780
|
+
if (empty) return state.storedMarks ?? $from.marks();
|
|
6781
|
+
let common = null;
|
|
6782
|
+
state.doc.nodesBetween(from, to, (node) => {
|
|
6783
|
+
if (!node.isText) return true;
|
|
6784
|
+
common = common === null ? node.marks : common.filter((m) => m.isInSet(node.marks));
|
|
6785
|
+
return false;
|
|
6786
|
+
});
|
|
6787
|
+
return common ?? $from.marks();
|
|
6788
|
+
}
|
|
6789
|
+
function captureSelectionFormat(state) {
|
|
6790
|
+
const character = {};
|
|
6791
|
+
selectionMarks(state).forEach((mark) => {
|
|
6792
|
+
const name = mark.type.name;
|
|
6793
|
+
if (MARK_FORMAT[name]) character[MARK_FORMAT[name]] = true;
|
|
6794
|
+
if (name === "textStyle") {
|
|
6795
|
+
if (mark.attrs.fontFamily) character.fontFamily = mark.attrs.fontFamily;
|
|
6796
|
+
if (mark.attrs.fontSize) character.fontSize = mark.attrs.fontSize;
|
|
6797
|
+
if (mark.attrs.color) character.color = mark.attrs.color;
|
|
6798
|
+
}
|
|
6799
|
+
if (name === "highlight") character.backgroundColor = mark.attrs.color || "#fef08a";
|
|
6800
|
+
});
|
|
6801
|
+
const paragraph = {};
|
|
6802
|
+
const align = state.selection.$from.parent.attrs?.textAlign;
|
|
6803
|
+
if (align && align !== "left") paragraph.textAlign = align;
|
|
6804
|
+
return { paragraph, character };
|
|
6805
|
+
}
|
|
6806
|
+
function carriedAttributes(node, type) {
|
|
6807
|
+
const spec = type.spec.attrs ?? {};
|
|
6808
|
+
return Object.fromEntries(Object.entries(node.attrs).filter(([key]) => key in spec));
|
|
6809
|
+
}
|
|
6810
|
+
function applyStyleToBlock(tr, pos, id, registry) {
|
|
6811
|
+
const node = tr.doc.nodeAt(pos);
|
|
6812
|
+
if (!node || !node.isTextblock) return false;
|
|
6813
|
+
const resolved = registry.resolve(id);
|
|
6814
|
+
const type = tr.doc.type.schema.nodes[resolved.block.type];
|
|
6815
|
+
if (!type) return false;
|
|
6816
|
+
const blockAttrs = resolved.block.attrs ?? {};
|
|
6817
|
+
const isDefault = registry.defaultStyleFor(resolved.block.type, blockAttrs) === id;
|
|
6818
|
+
const attrs = { ...carriedAttributes(node, type), ...blockAttrs };
|
|
6819
|
+
if (STYLE_ID_ATTRIBUTE in (type.spec.attrs ?? {})) attrs[STYLE_ID_ATTRIBUTE] = isDefault ? null : id;
|
|
6820
|
+
if ("textAlign" in (type.spec.attrs ?? {})) {
|
|
6821
|
+
const fallback = type.spec.attrs.textAlign.default ?? null;
|
|
6822
|
+
attrs.textAlign = fallback === null ? null : resolved.paragraph.textAlign ?? fallback;
|
|
6823
|
+
}
|
|
6824
|
+
if (node.type === type && Object.entries(attrs).every(([k, v]) => node.attrs[k] === v)) return false;
|
|
6825
|
+
try {
|
|
6826
|
+
tr.setNodeMarkup(pos, type, attrs);
|
|
6827
|
+
} catch {
|
|
6828
|
+
try {
|
|
6829
|
+
tr.setBlockType(pos + 1, pos + 1, type, attrs);
|
|
6830
|
+
} catch {
|
|
6831
|
+
return false;
|
|
6832
|
+
}
|
|
6833
|
+
}
|
|
6834
|
+
return true;
|
|
6835
|
+
}
|
|
6836
|
+
function selectedBlocks(state) {
|
|
6837
|
+
const { from, to } = state.selection;
|
|
6838
|
+
const positions = [];
|
|
6839
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
6840
|
+
if (node.isTextblock) {
|
|
6841
|
+
positions.push(pos);
|
|
6842
|
+
return false;
|
|
6843
|
+
}
|
|
6844
|
+
return true;
|
|
6845
|
+
});
|
|
6846
|
+
if (positions.length === 0 && state.selection.$from.parent.isTextblock) {
|
|
6847
|
+
positions.push(state.selection.$from.before());
|
|
6848
|
+
}
|
|
6849
|
+
return positions;
|
|
6850
|
+
}
|
|
6851
|
+
function setParagraphStyle(tr, state, id, registry) {
|
|
6852
|
+
const start2 = tr.steps.length;
|
|
6853
|
+
selectedBlocks(state).forEach((pos) => {
|
|
6854
|
+
applyStyleToBlock(tr, tr.mapping.slice(start2).map(pos), id, registry);
|
|
6855
|
+
});
|
|
6856
|
+
}
|
|
6857
|
+
function nextStyleTransaction(transactions, oldState, newState, registry) {
|
|
6858
|
+
if (transactions.length !== 1) return null;
|
|
6859
|
+
const [tr] = transactions;
|
|
6860
|
+
if (!tr.docChanged || tr.getMeta("uiEvent") || tr.getMeta("history$") || tr.getMeta("y-sync$")) {
|
|
6861
|
+
return null;
|
|
6862
|
+
}
|
|
6863
|
+
const old = oldState.selection;
|
|
6864
|
+
const $old = old.$from;
|
|
6865
|
+
if (!old.empty || !$old.parent.isTextblock || $old.parent.type.spec.code) return null;
|
|
6866
|
+
if ($old.parentOffset !== $old.parent.content.size) return null;
|
|
6867
|
+
if (newState.doc.content.size !== oldState.doc.content.size + 2) return null;
|
|
6868
|
+
const $new = newState.selection.$from;
|
|
6869
|
+
if (!newState.selection.empty || !$new.parent.isTextblock || $new.parent.content.size !== 0) return null;
|
|
6870
|
+
const depth = $new.depth;
|
|
6871
|
+
const index = $new.index(depth - 1);
|
|
6872
|
+
if (index === 0 || $new.depth !== $old.depth) return null;
|
|
6873
|
+
const previous = $new.node(depth - 1).child(index - 1);
|
|
6874
|
+
if (!previous.isTextblock || !previous.eq($old.parent)) return null;
|
|
6875
|
+
const style = registry.styleOfBlock($old.parent.type.name, $old.parent.attrs);
|
|
6876
|
+
if (!style) return null;
|
|
6877
|
+
const next = registry.nextStyleId(style);
|
|
6878
|
+
const current = registry.styleOfBlock($new.parent.type.name, $new.parent.attrs);
|
|
6879
|
+
const target = registry.resolve(next).block;
|
|
6880
|
+
const typeMatches = $new.parent.type.name === target.type && Object.entries(target.attrs ?? {}).every(([k, v]) => $new.parent.attrs[k] === v);
|
|
6881
|
+
if (current === next && typeMatches) return null;
|
|
6882
|
+
const out = newState.tr;
|
|
6883
|
+
if (!applyStyleToBlock(out, $new.before(), next, registry)) return null;
|
|
6884
|
+
return out;
|
|
6885
|
+
}
|
|
6886
|
+
var CharacterStyle = Mark5.create({
|
|
6887
|
+
name: CHARACTER_STYLE_MARK_NAME,
|
|
6888
|
+
addAttributes() {
|
|
6889
|
+
return {
|
|
6890
|
+
[STYLE_ID_ATTRIBUTE]: {
|
|
6891
|
+
default: null,
|
|
6892
|
+
parseHTML: (el) => {
|
|
6893
|
+
const id = el.getAttribute("data-char-style");
|
|
6894
|
+
return isValidStyleId(id) ? id : null;
|
|
6895
|
+
},
|
|
6896
|
+
renderHTML: (attrs) => attrs[STYLE_ID_ATTRIBUTE] ? { "data-char-style": attrs[STYLE_ID_ATTRIBUTE] } : {}
|
|
6897
|
+
}
|
|
6898
|
+
};
|
|
6899
|
+
},
|
|
6900
|
+
parseHTML() {
|
|
6901
|
+
return [{ tag: "span[data-char-style]" }];
|
|
6902
|
+
},
|
|
6903
|
+
renderHTML({ HTMLAttributes }) {
|
|
6904
|
+
return ["span", mergeAttributes7(HTMLAttributes), 0];
|
|
6905
|
+
}
|
|
6906
|
+
});
|
|
6907
|
+
var ParagraphStyles = Extension13.create({
|
|
6908
|
+
name: "paragraphStyles",
|
|
6909
|
+
addOptions() {
|
|
6910
|
+
return {
|
|
6911
|
+
registry: null,
|
|
6912
|
+
types: ["paragraph", "heading", "codeBlock"],
|
|
6913
|
+
injectCSS: true,
|
|
6914
|
+
cssScope: ".ProseMirror",
|
|
6915
|
+
cssNonce: void 0,
|
|
6916
|
+
linkedCharacterStyles: true
|
|
6917
|
+
};
|
|
6918
|
+
},
|
|
6919
|
+
addStorage() {
|
|
6920
|
+
return { registry: this.options.registry ?? createStyleRegistry() };
|
|
6921
|
+
},
|
|
6922
|
+
addExtensions() {
|
|
6923
|
+
return [CharacterStyle];
|
|
6924
|
+
},
|
|
6925
|
+
addGlobalAttributes() {
|
|
6926
|
+
return [
|
|
6927
|
+
{
|
|
6928
|
+
types: this.options.types,
|
|
6929
|
+
attributes: {
|
|
6930
|
+
[STYLE_ID_ATTRIBUTE]: {
|
|
6931
|
+
default: null,
|
|
6932
|
+
keepOnSplit: true,
|
|
6933
|
+
parseHTML: (el) => {
|
|
6934
|
+
const id = el.getAttribute("data-style");
|
|
6935
|
+
return isValidStyleId(id) ? id : null;
|
|
6936
|
+
},
|
|
6937
|
+
renderHTML: (attrs) => {
|
|
6938
|
+
const id = attrs[STYLE_ID_ATTRIBUTE];
|
|
6939
|
+
return isValidStyleId(id) ? { "data-style": id, class: `pixerate-style-${id}` } : {};
|
|
6940
|
+
}
|
|
6941
|
+
}
|
|
6942
|
+
}
|
|
6943
|
+
}
|
|
6944
|
+
];
|
|
6945
|
+
},
|
|
6946
|
+
addCommands() {
|
|
6947
|
+
const registry = () => this.storage.registry;
|
|
6948
|
+
const editor = () => this.editor;
|
|
6949
|
+
return {
|
|
6950
|
+
setParagraphStyle: (id) => ({ state, tr, dispatch }) => {
|
|
6951
|
+
const reg = registry();
|
|
6952
|
+
if (!isParagraphStyleAvailable(editor(), reg, id)) return false;
|
|
6953
|
+
const { $from, $to, empty } = state.selection;
|
|
6954
|
+
const linked = this.options.linkedCharacterStyles ? reg.linkedCharacterStyle(id) : void 0;
|
|
6955
|
+
const partial = !empty && $from.sameParent($to) && $from.parent.isTextblock && ($from.parentOffset > 0 || $to.parentOffset < $from.parent.content.size);
|
|
6956
|
+
const markType = state.schema.marks[CHARACTER_STYLE_MARK_NAME];
|
|
6957
|
+
if (partial && linked && markType) {
|
|
6958
|
+
if (dispatch) {
|
|
6959
|
+
tr.addMark($from.pos, $to.pos, markType.create({ [STYLE_ID_ATTRIBUTE]: linked.id }));
|
|
6960
|
+
}
|
|
6961
|
+
return true;
|
|
6962
|
+
}
|
|
6963
|
+
if (dispatch) setParagraphStyle(tr, state, id, reg);
|
|
6964
|
+
return true;
|
|
6965
|
+
},
|
|
6966
|
+
clearParagraphStyle: () => ({ commands }) => commands.setParagraphStyle(NORMAL_STYLE_ID),
|
|
6967
|
+
setCharacterStyle: (id) => ({ commands }) => {
|
|
6968
|
+
if (registry().get(id)?.kind !== "character") return false;
|
|
6969
|
+
return commands.setMark(CHARACTER_STYLE_MARK_NAME, { [STYLE_ID_ATTRIBUTE]: id });
|
|
6970
|
+
},
|
|
6971
|
+
unsetCharacterStyle: () => ({ commands }) => commands.unsetMark(CHARACTER_STYLE_MARK_NAME),
|
|
6972
|
+
updateParagraphStyleFromSelection: (id) => ({ state, dispatch }) => {
|
|
6973
|
+
const reg = registry();
|
|
6974
|
+
const target = id ?? getParagraphStyleAt(state, reg);
|
|
6975
|
+
const style = target ? reg.get(target) : void 0;
|
|
6976
|
+
if (!style || style.kind !== "paragraph") return false;
|
|
6977
|
+
if (dispatch) {
|
|
6978
|
+
const captured = captureSelectionFormat(state);
|
|
6979
|
+
reg.update(style.id, captured);
|
|
6980
|
+
}
|
|
6981
|
+
return true;
|
|
6982
|
+
},
|
|
6983
|
+
createParagraphStyleFromSelection: (name, options = {}) => ({ state, tr, dispatch }) => {
|
|
6984
|
+
const reg = registry();
|
|
6985
|
+
const trimmed = name.trim();
|
|
6986
|
+
if (!trimmed) return false;
|
|
6987
|
+
const id = options.id ?? reg.newId(trimmed);
|
|
6988
|
+
if (!isValidStyleId(id) || reg.get(id)) return false;
|
|
6989
|
+
const basedOn = options.basedOn === void 0 ? getParagraphStyleAt(state, reg) : options.basedOn;
|
|
6990
|
+
if (dispatch) {
|
|
6991
|
+
const captured = captureSelectionFormat(state);
|
|
6992
|
+
const definition = {
|
|
6993
|
+
id,
|
|
6994
|
+
name: trimmed,
|
|
6995
|
+
kind: "paragraph",
|
|
6996
|
+
basedOn: basedOn ?? NORMAL_STYLE_ID,
|
|
6997
|
+
paragraph: captured.paragraph,
|
|
6998
|
+
character: captured.character,
|
|
6999
|
+
priority: 50,
|
|
7000
|
+
quick: true
|
|
7001
|
+
};
|
|
7002
|
+
reg.upsert(definition);
|
|
7003
|
+
if (options.apply !== false) setParagraphStyle(tr, state, id, reg);
|
|
7004
|
+
}
|
|
7005
|
+
return true;
|
|
7006
|
+
}
|
|
7007
|
+
};
|
|
7008
|
+
},
|
|
7009
|
+
addProseMirrorPlugins() {
|
|
7010
|
+
const registry = this.storage.registry;
|
|
7011
|
+
return [
|
|
7012
|
+
new Plugin15({
|
|
7013
|
+
key: paragraphStylesPluginKey,
|
|
7014
|
+
appendTransaction: (transactions, oldState, newState) => nextStyleTransaction(transactions, oldState, newState, registry)
|
|
7015
|
+
})
|
|
7016
|
+
];
|
|
7017
|
+
},
|
|
7018
|
+
onBeforeCreate() {
|
|
7019
|
+
if (!this.options.injectCSS || typeof document === "undefined") return;
|
|
7020
|
+
const element = document.createElement("style");
|
|
7021
|
+
element.setAttribute("data-pixerate-paragraph-styles", "");
|
|
7022
|
+
if (this.options.cssNonce) element.nonce = this.options.cssNonce;
|
|
7023
|
+
document.head.appendChild(element);
|
|
7024
|
+
const scope = this.options.cssScope;
|
|
7025
|
+
const unsubscribe = this.storage.registry.subscribe(() => {
|
|
7026
|
+
element.textContent = this.storage.registry.toCSS({ scope });
|
|
7027
|
+
});
|
|
7028
|
+
this.storage.cleanup = () => {
|
|
7029
|
+
unsubscribe();
|
|
7030
|
+
element.remove();
|
|
7031
|
+
};
|
|
7032
|
+
},
|
|
7033
|
+
onDestroy() {
|
|
7034
|
+
this.storage.cleanup?.();
|
|
7035
|
+
}
|
|
7036
|
+
});
|
|
7037
|
+
var EMPTY_STYLES = Object.freeze({
|
|
7038
|
+
gallery: [],
|
|
7039
|
+
styles: [],
|
|
7040
|
+
characterStyles: [],
|
|
7041
|
+
currentStyleId: null,
|
|
7042
|
+
version: -1
|
|
7043
|
+
});
|
|
7044
|
+
function createParagraphStylesStore(editor) {
|
|
7045
|
+
const registry = getStyleRegistry(editor);
|
|
7046
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
7047
|
+
let snapshot = EMPTY_STYLES;
|
|
7048
|
+
let unsubscribeRegistry = null;
|
|
7049
|
+
const compute = () => {
|
|
7050
|
+
if (!editor || editor.isDestroyed || !registry) return EMPTY_STYLES;
|
|
7051
|
+
const { version } = registry.getSnapshot();
|
|
7052
|
+
const currentStyleId = getParagraphStyleAt(editor.state, registry);
|
|
7053
|
+
if (snapshot.version === version && snapshot.currentStyleId === currentStyleId) return snapshot;
|
|
7054
|
+
if (snapshot.version === version) return { ...snapshot, currentStyleId };
|
|
7055
|
+
const styles = registry.list("paragraph").filter((style) => !style.hidden && isParagraphStyleAvailable(editor, registry, style.id));
|
|
7056
|
+
return {
|
|
7057
|
+
gallery: styles.filter((style) => style.quick),
|
|
7058
|
+
styles,
|
|
7059
|
+
characterStyles: registry.list("character").filter((style) => !style.hidden),
|
|
7060
|
+
currentStyleId,
|
|
7061
|
+
version
|
|
7062
|
+
};
|
|
7063
|
+
};
|
|
7064
|
+
const update = () => {
|
|
7065
|
+
const next = compute();
|
|
7066
|
+
if (next !== snapshot) {
|
|
7067
|
+
snapshot = next;
|
|
7068
|
+
listeners.forEach((listener) => listener());
|
|
7069
|
+
}
|
|
7070
|
+
};
|
|
7071
|
+
const detach = () => {
|
|
7072
|
+
editor?.off("transaction", update);
|
|
7073
|
+
unsubscribeRegistry?.();
|
|
7074
|
+
unsubscribeRegistry = null;
|
|
7075
|
+
};
|
|
7076
|
+
return {
|
|
7077
|
+
getSnapshot: () => {
|
|
7078
|
+
if (!listeners.size) snapshot = compute();
|
|
7079
|
+
return snapshot;
|
|
7080
|
+
},
|
|
7081
|
+
subscribe(listener) {
|
|
7082
|
+
if (!listeners.size) {
|
|
7083
|
+
snapshot = compute();
|
|
7084
|
+
editor?.on("transaction", update);
|
|
7085
|
+
unsubscribeRegistry = registry ? registry.subscribe(update) : null;
|
|
7086
|
+
}
|
|
7087
|
+
listeners.add(listener);
|
|
7088
|
+
return () => {
|
|
7089
|
+
listeners.delete(listener);
|
|
7090
|
+
if (!listeners.size) detach();
|
|
7091
|
+
};
|
|
7092
|
+
},
|
|
7093
|
+
destroy() {
|
|
7094
|
+
detach();
|
|
7095
|
+
listeners.clear();
|
|
7096
|
+
}
|
|
7097
|
+
};
|
|
7098
|
+
}
|
|
7099
|
+
|
|
6472
7100
|
// src/extensions/rich-text-preset.ts
|
|
6473
7101
|
var resolveExt3 = (mod, name) => mod?.[name] || mod?.default?.[name] || mod?.default?.default || mod?.default || mod;
|
|
6474
7102
|
var StarterKit = resolveExt3(_StarterKit, "StarterKit");
|
|
@@ -6491,7 +7119,7 @@ function createRichTextPreset(options = {}) {
|
|
|
6491
7119
|
openLinksOnClick = false,
|
|
6492
7120
|
enableSmilies = true,
|
|
6493
7121
|
enableColorHighlighter = true,
|
|
6494
|
-
headingLevels = [1, 2, 3, 4]
|
|
7122
|
+
headingLevels: headingLevels2 = [1, 2, 3, 4]
|
|
6495
7123
|
} = options;
|
|
6496
7124
|
const extensions2 = [
|
|
6497
7125
|
StarterKit.configure({
|
|
@@ -6506,7 +7134,7 @@ function createRichTextPreset(options = {}) {
|
|
|
6506
7134
|
}
|
|
6507
7135
|
},
|
|
6508
7136
|
heading: {
|
|
6509
|
-
levels:
|
|
7137
|
+
levels: headingLevels2,
|
|
6510
7138
|
HTMLAttributes: {
|
|
6511
7139
|
class: "font-bold tracking-tight"
|
|
6512
7140
|
}
|
|
@@ -6565,6 +7193,9 @@ function createRichTextPreset(options = {}) {
|
|
|
6565
7193
|
placeholder: typeof placeholder === "function" ? placeholder : () => placeholder
|
|
6566
7194
|
})
|
|
6567
7195
|
];
|
|
7196
|
+
if (options.table !== false) {
|
|
7197
|
+
extensions2.push(...createTableExtensions(optionObject(options.table)));
|
|
7198
|
+
}
|
|
6568
7199
|
if (characterLimit) {
|
|
6569
7200
|
extensions2.push(
|
|
6570
7201
|
CharacterCount.configure({
|
|
@@ -6668,6 +7299,9 @@ function createRichTextPreset(options = {}) {
|
|
|
6668
7299
|
if (options.findReplace) {
|
|
6669
7300
|
extensions2.push(FindReplace.configure(optionObject(options.findReplace)));
|
|
6670
7301
|
}
|
|
7302
|
+
if (options.paragraphStyles) {
|
|
7303
|
+
extensions2.push(ParagraphStyles.configure(optionObject(options.paragraphStyles)));
|
|
7304
|
+
}
|
|
6671
7305
|
return extensions2;
|
|
6672
7306
|
}
|
|
6673
7307
|
|
|
@@ -6808,6 +7442,69 @@ function validateFindPattern(query, options = {}) {
|
|
|
6808
7442
|
return result.ok ? null : result.error;
|
|
6809
7443
|
}
|
|
6810
7444
|
|
|
7445
|
+
// src/extensions/table/commands.ts
|
|
7446
|
+
var PARAMS = {
|
|
7447
|
+
insertTable: {
|
|
7448
|
+
type: "object",
|
|
7449
|
+
properties: {
|
|
7450
|
+
rows: { type: "integer", minimum: 1, maximum: MAX_TABLE_ROWS, description: "Rows (default 3)." },
|
|
7451
|
+
cols: { type: "integer", minimum: 1, maximum: MAX_TABLE_COLUMNS, description: "Columns (default 3)." },
|
|
7452
|
+
withHeaderRow: { type: "boolean", description: "Make the first row a header row (default true)." }
|
|
7453
|
+
},
|
|
7454
|
+
additionalProperties: false
|
|
7455
|
+
},
|
|
7456
|
+
setCellAlignment: {
|
|
7457
|
+
type: "object",
|
|
7458
|
+
properties: {
|
|
7459
|
+
align: {
|
|
7460
|
+
type: ["string", "null"],
|
|
7461
|
+
enum: ["left", "center", "right", "justify", null],
|
|
7462
|
+
description: "Horizontal alignment; null clears it."
|
|
7463
|
+
}
|
|
7464
|
+
},
|
|
7465
|
+
required: ["align"],
|
|
7466
|
+
additionalProperties: false
|
|
7467
|
+
},
|
|
7468
|
+
setCellBackground: {
|
|
7469
|
+
type: "object",
|
|
7470
|
+
properties: {
|
|
7471
|
+
color: { type: ["string", "null"], description: "CSS color (e.g. #fde68a); null clears it." }
|
|
7472
|
+
},
|
|
7473
|
+
required: ["color"],
|
|
7474
|
+
additionalProperties: false
|
|
7475
|
+
}
|
|
7476
|
+
};
|
|
7477
|
+
function createTableCommands(editor, options = {}) {
|
|
7478
|
+
const prefix = options.prefix ?? "table.";
|
|
7479
|
+
const group = options.group ?? "Table";
|
|
7480
|
+
const scope = options.scope ? { scope: options.scope } : {};
|
|
7481
|
+
const focus = options.focus ?? true;
|
|
7482
|
+
return TABLE_ACTIONS.map(({ action, label, description, keywords }) => {
|
|
7483
|
+
const params = PARAMS[action];
|
|
7484
|
+
return {
|
|
7485
|
+
id: `${prefix}${action}`,
|
|
7486
|
+
label,
|
|
7487
|
+
group,
|
|
7488
|
+
keywords: [...keywords],
|
|
7489
|
+
description,
|
|
7490
|
+
...params ? { params } : {},
|
|
7491
|
+
...scope,
|
|
7492
|
+
enabled: (_ctx, p) => getTableActionState(editor, action, p ?? {}),
|
|
7493
|
+
run: (_ctx, p) => {
|
|
7494
|
+
if (!runTableAction(editor, action, p ?? {}, { focus })) {
|
|
7495
|
+
const reason = getTableActionState(editor, action, p ?? {});
|
|
7496
|
+
throw new Error(reason === true ? `${label} did not change the document.` : reason);
|
|
7497
|
+
}
|
|
7498
|
+
const state = getTableState(editor);
|
|
7499
|
+
return {
|
|
7500
|
+
done: true,
|
|
7501
|
+
table: state.inTable ? { rows: state.rows, columns: state.columns, row: state.row, column: state.column } : null
|
|
7502
|
+
};
|
|
7503
|
+
}
|
|
7504
|
+
};
|
|
7505
|
+
});
|
|
7506
|
+
}
|
|
7507
|
+
|
|
6811
7508
|
export {
|
|
6812
7509
|
GradientText,
|
|
6813
7510
|
SlashCommands,
|
|
@@ -6820,6 +7517,8 @@ export {
|
|
|
6820
7517
|
ColorHighlighter,
|
|
6821
7518
|
FontSize,
|
|
6822
7519
|
Mention,
|
|
7520
|
+
getMentionNodes,
|
|
7521
|
+
setMentionRoleAt,
|
|
6823
7522
|
createMentionExtension,
|
|
6824
7523
|
Markdown2 as Markdown,
|
|
6825
7524
|
imagePastePluginKey,
|
|
@@ -6842,13 +7541,6 @@ export {
|
|
|
6842
7541
|
ImportError,
|
|
6843
7542
|
createImportContext,
|
|
6844
7543
|
ImportAdapterRegistry,
|
|
6845
|
-
ZipError,
|
|
6846
|
-
DEFAULT_ZIP_MAX_ENTRIES,
|
|
6847
|
-
DEFAULT_ZIP_MAX_TOTAL_SIZE,
|
|
6848
|
-
zipCrc32,
|
|
6849
|
-
isUnsafeZipPath,
|
|
6850
|
-
ZipArchive,
|
|
6851
|
-
readZip,
|
|
6852
7544
|
DOCX_MIME_TYPES,
|
|
6853
7545
|
DEFAULT_DOCX_MAX_IMAGE_SIZE,
|
|
6854
7546
|
docxToDocumentImport,
|
|
@@ -6868,6 +7560,7 @@ export {
|
|
|
6868
7560
|
getImportAccept,
|
|
6869
7561
|
htmlToSlice,
|
|
6870
7562
|
insertImportedDocument,
|
|
7563
|
+
applyImportedReviewData,
|
|
6871
7564
|
importFilesIntoEditor,
|
|
6872
7565
|
fileImportPluginKey,
|
|
6873
7566
|
FileImport,
|
|
@@ -6929,8 +7622,19 @@ export {
|
|
|
6929
7622
|
FIND_OPTION_TOGGLES,
|
|
6930
7623
|
formatFindStatus,
|
|
6931
7624
|
FindReplace,
|
|
7625
|
+
STYLE_ID_ATTRIBUTE,
|
|
7626
|
+
CHARACTER_STYLE_MARK_NAME,
|
|
7627
|
+
paragraphStylesPluginKey,
|
|
7628
|
+
getStyleRegistry,
|
|
7629
|
+
isParagraphStyleAvailable,
|
|
7630
|
+
getParagraphStyleAt,
|
|
7631
|
+
captureSelectionFormat,
|
|
7632
|
+
CharacterStyle,
|
|
7633
|
+
ParagraphStyles,
|
|
7634
|
+
createParagraphStylesStore,
|
|
6932
7635
|
createRichTextPreset,
|
|
6933
7636
|
createFindReplaceCommands,
|
|
6934
|
-
validateFindPattern
|
|
7637
|
+
validateFindPattern,
|
|
7638
|
+
createTableCommands
|
|
6935
7639
|
};
|
|
6936
|
-
//# sourceMappingURL=chunk-
|
|
7640
|
+
//# sourceMappingURL=chunk-Q2OHWD2A.js.map
|