@stll/folio-core 0.60.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/ai-edits/apply.js +139 -32
- package/dist/ai-edits/headless.d.ts +3 -0
- package/dist/ai-edits/headless.js +70 -75
- package/dist/ai-edits/note-story-inventory.d.ts +7 -0
- package/dist/ai-edits/note-story-inventory.js +11 -0
- package/dist/ai-edits/read.js +16 -9
- package/dist/ai-edits/revisionStretches.js +52 -1
- package/dist/ai-edits/table-row-column-mutations.js +6 -1
- package/dist/compare/reproducible-package.js +2 -1
- package/dist/compare/verification.js +1 -0
- package/dist/compat/eigenpal.d.ts +3 -1
- package/dist/controller/canonicalClipboard.js +2 -1
- package/dist/controller/canonicalListRendering.d.ts +4 -6
- package/dist/controller/canonicalListRendering.js +3 -157
- package/dist/controller/headerFooterEditorManager.d.ts +1 -0
- package/dist/controller/headerFooterEditorManager.js +11 -0
- package/dist/controller/hiddenEditorManager.d.ts +1 -1
- package/dist/controller/hiddenEditorManager.js +3 -1
- package/dist/controller/layoutPipeline.d.ts +3 -1
- package/dist/controller/layoutPipeline.js +13 -4
- package/dist/controller/layoutSession.d.ts +2 -1
- package/dist/controller/noteEditorManager.d.ts +1 -1
- package/dist/display-list/build/imagePrimitives.js +28 -12
- package/dist/display-list/build/paragraphPrimitives.js +15 -2
- package/dist/display-list/dom/renderDisplayListToDom.js +8 -5
- package/dist/display-list/types.d.ts +7 -3
- package/dist/docx/canonicalStoryRepack.js +3 -2
- package/dist/docx/commentTextParagraph.d.ts +6 -0
- package/dist/docx/commentTextParagraph.js +15 -0
- package/dist/docx/conformance.js +6 -1
- package/dist/docx/diagramPreview.js +2 -1
- package/dist/docx/documentParser.d.ts +13 -1
- package/dist/docx/documentParser.js +1 -1
- package/dist/docx/encryption/compoundFile.d.ts +0 -8
- package/dist/docx/encryption/compoundFile.js +2 -1
- package/dist/docx/encryption/cryptoBytes.d.ts +2 -2
- package/dist/docx/encryption/cryptoBytes.js +3 -18
- package/dist/docx/encryption/encryptionInfo.d.ts +0 -5
- package/dist/docx/encryption/encryptionInfo.js +2 -1
- package/dist/docx/ensureParaIds.js +2 -1
- package/dist/docx/groupDrawingParser.js +28 -13
- package/dist/docx/listModelNormalization.d.ts +10 -0
- package/dist/docx/listModelNormalization.js +166 -0
- package/dist/docx/metadataPrivacy.js +3 -2
- package/dist/docx/metafileRaster.js +2 -1
- package/dist/docx/packageParts.js +6 -5
- package/dist/docx/paragraphParser.js +6 -4
- package/dist/docx/parser.js +5 -4
- package/dist/docx/preservedRunContent.js +11 -2
- package/dist/docx/removeHeaderFooterParts.js +8 -7
- package/dist/docx/replyToComment.js +3 -13
- package/dist/docx/rezip.js +88 -89
- package/dist/docx/runParser.js +12 -6
- package/dist/docx/runPropertyPresence.d.ts +11 -0
- package/dist/docx/runPropertyPresence.js +14 -0
- package/dist/docx/selectiveSave.js +15 -14
- package/dist/docx/serializer/runSerializer.js +3 -2
- package/dist/docx/serializer/tableSerializer.js +2 -1
- package/dist/docx/server/applyDocxXmlPatchProposal.js +2 -2
- package/dist/docx/server/boundedArchive.js +2 -1
- package/dist/docx/server/evaluateDocxXmlPatchProposal.js +2 -1
- package/dist/docx/server/inspectDocxPackage.js +5 -1
- package/dist/docx/server/validateDocxConformance.js +2 -1
- package/dist/docx/tableParser.js +7 -4
- package/dist/docx/tableRowPropertyPresence.d.ts +9 -0
- package/dist/docx/tableRowPropertyPresence.js +15 -0
- package/dist/docx/unzip.js +2 -1
- package/dist/docx/xmlEncoding.js +6 -5
- package/dist/fonts/fontsourceFaces.js +2 -1
- package/dist/fonts/sfnt/parse.js +6 -9
- package/dist/fonts/sfnt/subset.js +2 -1
- package/dist/fonts/sfnt/tables.js +2 -3
- package/dist/fonts/sfnt/woff.js +2 -1
- package/dist/i18n/messages/ar.gen.js +1 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
- package/dist/i18n/messages/catalogs.gen.js +17 -0
- package/dist/i18n/messages/cs.gen.js +1 -0
- package/dist/i18n/messages/de.gen.js +1 -0
- package/dist/i18n/messages/en.gen.js +1 -0
- package/dist/i18n/messages/es.gen.js +1 -0
- package/dist/i18n/messages/et.gen.js +1 -0
- package/dist/i18n/messages/fr.gen.js +1 -0
- package/dist/i18n/messages/he.gen.js +1 -0
- package/dist/i18n/messages/hi.gen.js +1 -0
- package/dist/i18n/messages/hu.gen.js +1 -0
- package/dist/i18n/messages/lt.gen.js +1 -0
- package/dist/i18n/messages/lv.gen.js +1 -0
- package/dist/i18n/messages/messages.gen.d.ts +1 -0
- package/dist/i18n/messages/pl.gen.js +1 -0
- package/dist/i18n/messages/pt-BR.gen.js +1 -0
- package/dist/i18n/messages/sk.gen.js +1 -0
- package/dist/i18n/messages/tr.gen.js +1 -0
- package/dist/i18n/messages/zh-CN.gen.js +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/internal/revisionResolutionInline.d.ts +2 -1
- package/dist/internal/revisionResolutionInline.js +22 -1
- package/dist/internal/wholeStoryRevisionResolution.js +24 -7
- package/dist/layout-bridge/convert/endnoteLayout.d.ts +1 -1
- package/dist/layout-bridge/convert/endnoteLayout.js +1 -3
- package/dist/layout-bridge/convert/flowConversionShared.d.ts +2 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +4 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +13 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +5 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +12 -15
- package/dist/layout-bridge/convert/paragraphRuns.js +2 -1
- package/dist/layout-engine/index.js +2 -2
- package/dist/layout-engine/measure/crossRunWords.js +12 -2
- package/dist/layout-engine/noteAreaFlow.d.ts +4 -4
- package/dist/layout-engine/noteAreaFlow.js +12 -6
- package/dist/layout-engine/types.d.ts +5 -2
- package/dist/layout-painter/index.d.ts +1 -1
- package/dist/managers/AutoSaveManager.js +2 -1
- package/dist/managers/EditorModeManager.d.ts +10 -1
- package/dist/managers/EditorModeManager.js +15 -1
- package/dist/managers/FindReplaceManager.d.ts +13 -6
- package/dist/managers/FindReplaceManager.js +15 -9
- package/dist/managers/TableSelectionManager.d.ts +1 -1
- package/dist/managers/autoSaveCodec.js +2 -6
- package/dist/managers/reviewDisplayMode.d.ts +8 -0
- package/dist/managers/reviewDisplayMode.js +15 -0
- package/dist/paged-layout/editorScrollRoot.d.ts +3 -1
- package/dist/paged-layout/editorScrollRoot.js +2 -2
- package/dist/paged-layout/pageText.d.ts +11 -2
- package/dist/paged-layout/pageText.js +8 -3
- package/dist/pdf/fonts.js +5 -14
- package/dist/pdf/images.js +4 -2
- package/dist/pdf/objects.d.ts +0 -11
- package/dist/pdf/objects.js +7 -9
- package/dist/pdf/writePdf.js +2 -1
- package/dist/prosemirror/commands/comments.js +51 -13
- package/dist/prosemirror/commentRangeInlineAtoms.d.ts +40 -0
- package/dist/prosemirror/commentRangeInlineAtoms.js +33 -0
- package/dist/prosemirror/containerFinalParagraph.d.ts +8 -8
- package/dist/prosemirror/containerFinalParagraph.js +8 -8
- package/dist/prosemirror/conversion/fromProseDoc.js +14 -8
- package/dist/prosemirror/conversion/toProseDoc.js +16 -23
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +16 -2
- package/dist/prosemirror/fieldRepresentation.js +4 -2
- package/dist/prosemirror/findReplaceSelection.d.ts +48 -2
- package/dist/prosemirror/findReplaceSelection.js +153 -38
- package/dist/prosemirror/inlineDisplayText.d.ts +10 -0
- package/dist/prosemirror/inlineDisplayText.js +29 -0
- package/dist/prosemirror/markupViewProjection.d.ts +10 -1
- package/dist/prosemirror/markupViewProjection.js +21 -3
- package/dist/prosemirror/plugins/transactionInvariants.js +6 -1
- package/dist/prosemirror/replacedAnnotations.d.ts +15 -1
- package/dist/prosemirror/replacedAnnotations.js +71 -12
- package/dist/prosemirror/runFormattingReconciliation.d.ts +3 -1
- package/dist/prosemirror/runFormattingReconciliation.js +10 -2
- package/dist/prosemirror/runIdentityAcrossRevisions.d.ts +5 -7
- package/dist/prosemirror/runIdentityAcrossRevisions.js +66 -38
- package/dist/prosemirror/runPropertyChangeResolution.js +13 -1
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -1
- package/dist/prosemirror/trackedRunInlineAtoms.js +1 -1
- package/dist/utils/base64.d.ts +1 -31
- package/dist/utils/base64.js +19 -33
- package/dist/utils/clipboard.js +5 -4
- package/dist/utils/colorResolver.js +11 -2
- package/dist/utils/findMatchView.d.ts +32 -0
- package/dist/utils/findMatchView.js +406 -0
- package/dist/utils/findReplace.d.ts +67 -4
- package/dist/utils/findReplace.js +359 -37
- package/dist/utils/findSearchKey.d.ts +29 -0
- package/dist/utils/findSearchKey.js +34 -0
- package/dist/utils/replaceText.js +138 -94
- package/dist/utils/sliceText.d.ts +2 -0
- package/dist/utils/sliceText.js +2 -0
- package/dist/utils/textEncoding.d.ts +2 -0
- package/dist/utils/textEncoding.js +2 -0
- package/dist/utils/tiffConverter.d.ts +0 -9
- package/dist/utils/tiffConverter.js +2 -4
- package/package.json +51 -25
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* The plain text of a single rendered page (1-based), read by joining each of
|
|
4
4
|
* the page's layout fragments' `[pmStart, pmEnd)` document text with a
|
|
5
|
-
* newline.
|
|
5
|
+
* newline. A review projection maps those authored ranges to the displayed
|
|
6
|
+
* document, excluding text the view hides. Fragments with no `pmStart`/`pmEnd`
|
|
7
|
+
* (e.g. a page-shell placeholder)
|
|
6
8
|
* are skipped. Returns `null` when the layout hasn't been computed yet or the
|
|
7
9
|
* page number is out of range.
|
|
8
10
|
*/
|
|
9
|
-
const getPageTextFromLayout = (layout, doc, page) => {
|
|
11
|
+
const getPageTextFromLayout = ({ layout, doc, page, projection }) => {
|
|
10
12
|
if (!layout || !Number.isInteger(page) || page < 1) return null;
|
|
11
13
|
const layoutPage = layout.pages[page - 1];
|
|
12
14
|
if (!layoutPage) return null;
|
|
15
|
+
const viewDoc = projection?.type === "resolved" ? projection.doc : doc;
|
|
13
16
|
const fragmentTexts = [];
|
|
14
17
|
for (const fragment of layoutPage.fragments) {
|
|
15
18
|
if (typeof fragment.pmStart !== "number" || typeof fragment.pmEnd !== "number") continue;
|
|
16
|
-
|
|
19
|
+
const from = projection?.type === "resolved" ? projection.toView(fragment.pmStart, 1) : fragment.pmStart;
|
|
20
|
+
const to = projection?.type === "resolved" ? projection.toView(fragment.pmEnd, -1) : fragment.pmEnd;
|
|
21
|
+
fragmentTexts.push(viewDoc.textBetween(from, to, "\n"));
|
|
17
22
|
}
|
|
18
23
|
return fragmentTexts.join("\n");
|
|
19
24
|
};
|
package/dist/pdf/fonts.js
CHANGED
|
@@ -2,6 +2,7 @@ import { parseSfnt } from "../fonts/sfnt/parse.js";
|
|
|
2
2
|
import { subsetTrueType } from "../fonts/sfnt/subset.js";
|
|
3
3
|
import { toSfntBytes } from "../fonts/sfnt/woff.js";
|
|
4
4
|
import { needsShaping, placeRun } from "../shaping/placeRun.js";
|
|
5
|
+
import { bytesToHex, decodeText, encodeUtf16BE, encodeUtf8 } from "../utils/textEncoding.js";
|
|
5
6
|
import { pdfArray, pdfAsciiString, pdfDict, pdfFlateStream, pdfName, pdfNumber, pdfNumberArray } from "./objects.js";
|
|
6
7
|
import { Result, TaggedError, panic } from "better-result";
|
|
7
8
|
//#region src/pdf/fonts.ts
|
|
@@ -46,7 +47,7 @@ const SUBSET_TAG_LENGTH = 6;
|
|
|
46
47
|
const ALPHABET_LENGTH = 26;
|
|
47
48
|
const UPPERCASE_A = 65;
|
|
48
49
|
const WOFF_SIGNATURES = ["wOFF", "wOF2"];
|
|
49
|
-
const readTag = (bytes) =>
|
|
50
|
+
const readTag = (bytes) => decodeText(Uint8Array.of(bytes[0] ?? 0, bytes[1] ?? 0, bytes[2] ?? 0, bytes[3] ?? 0), { encoding: "binary" });
|
|
50
51
|
/**
|
|
51
52
|
* Six uppercase letters derived from the face and the exact glyph set, so the
|
|
52
53
|
* tag is stable across runs and two different subsets of one family do not
|
|
@@ -148,18 +149,8 @@ const buildWinAnsiTable = () => {
|
|
|
148
149
|
return table;
|
|
149
150
|
};
|
|
150
151
|
const WIN_ANSI_BY_CODE_POINT = buildWinAnsiTable();
|
|
151
|
-
const utf16BeHexOf = (text) =>
|
|
152
|
-
const utf16BeHex = (codePoint) =>
|
|
153
|
-
const SUPPLEMENTARY_START = 65536;
|
|
154
|
-
const SURROGATE_HALF_BITS = 10;
|
|
155
|
-
const LOW_SURROGATE_MASK = 1023;
|
|
156
|
-
const HIGH_SURROGATE_BASE = 55296;
|
|
157
|
-
const LOW_SURROGATE_BASE = 56320;
|
|
158
|
-
const hex = (unit) => unit.toString(16).padStart(4, "0").toUpperCase();
|
|
159
|
-
if (codePoint < SUPPLEMENTARY_START) return hex(codePoint);
|
|
160
|
-
const offset = codePoint - SUPPLEMENTARY_START;
|
|
161
|
-
return hex(HIGH_SURROGATE_BASE + (offset >> SURROGATE_HALF_BITS)) + hex(LOW_SURROGATE_BASE + (offset & LOW_SURROGATE_MASK));
|
|
162
|
-
};
|
|
152
|
+
const utf16BeHexOf = (text) => bytesToHex(encodeUtf16BE(text)).toUpperCase();
|
|
153
|
+
const utf16BeHex = (codePoint) => utf16BeHexOf(String.fromCodePoint(codePoint));
|
|
163
154
|
/** Entries per `beginbfchar` block; the CMap syntax caps this at 100. */
|
|
164
155
|
const BFCHAR_BLOCK_SIZE = 100;
|
|
165
156
|
const toUnicodeCMap = (glyphToText) => {
|
|
@@ -290,7 +281,7 @@ const emitFont = (document, plan) => {
|
|
|
290
281
|
fontFileKey: font.isCff ? "FontFile3" : "FontFile2",
|
|
291
282
|
fontFileRef
|
|
292
283
|
}));
|
|
293
|
-
const toUnicodeRef = document.add(pdfFlateStream([],
|
|
284
|
+
const toUnicodeRef = document.add(pdfFlateStream([], encodeUtf8(toUnicodeCMap(plan.glyphToText))));
|
|
294
285
|
const descendantRef = document.add(pdfDict([
|
|
295
286
|
["Type", pdfName("Font")],
|
|
296
287
|
["Subtype", pdfName(font.isCff ? "CIDFontType0" : "CIDFontType2")],
|
package/dist/pdf/images.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { decodeText } from "../utils/textEncoding.js";
|
|
1
2
|
import { pdfArray, pdfHexString, pdfName, pdfNumber } from "./objects.js";
|
|
2
3
|
import { Result, TaggedError } from "better-result";
|
|
3
4
|
import { inflateSync } from "node:zlib";
|
|
@@ -63,7 +64,7 @@ const readPngChunks = (bytes) => {
|
|
|
63
64
|
const CHUNK_CRC_BYTES = 4;
|
|
64
65
|
while (cursor + CHUNK_HEADER_BYTES <= bytes.length) {
|
|
65
66
|
const length = view.getUint32(cursor);
|
|
66
|
-
const type =
|
|
67
|
+
const type = decodeText(bytes.subarray(cursor + 4, cursor + 8), { encoding: "binary" });
|
|
67
68
|
const dataStart = cursor + CHUNK_HEADER_BYTES;
|
|
68
69
|
const dataEnd = dataStart + length;
|
|
69
70
|
if (dataEnd > bytes.length) return Result.err(new PdfImageError({ message: `PNG chunk ${type} runs past the end` }));
|
|
@@ -538,7 +539,7 @@ const decodeJpeg = (bytes) => {
|
|
|
538
539
|
const length = view.getUint16(cursor + 2);
|
|
539
540
|
const segment = cursor + 4;
|
|
540
541
|
const frame = JPEG_FRAME_MODES[marker];
|
|
541
|
-
if (marker === APP14 && length >= 12) adobe =
|
|
542
|
+
if (marker === APP14 && length >= 12) adobe = decodeText(bytes.subarray(segment, segment + 5), { encoding: "binary" }) === "Adobe";
|
|
542
543
|
if (frame !== void 0) {
|
|
543
544
|
if (!frame.dctDecodable) return Result.err(new PdfImageError({ message: `JPEG ${frame.name} frame (marker 0xff${marker.toString(16)}) has no /DCTDecode equivalent` }));
|
|
544
545
|
const height = view.getUint16(segment + 1);
|
|
@@ -565,6 +566,7 @@ const decodeImage = (source) => {
|
|
|
565
566
|
switch (source.format) {
|
|
566
567
|
case "png": return decodePng(source.bytes);
|
|
567
568
|
case "jpeg": return decodeJpeg(source.bytes);
|
|
569
|
+
case "svg": return Result.err(new PdfImageError({ message: "SVG images are not supported in PDF" }));
|
|
568
570
|
default: {
|
|
569
571
|
const unreachable = source.format;
|
|
570
572
|
return Result.err(new PdfImageError({ message: `unsupported image format ${String(unreachable)}` }));
|
package/dist/pdf/objects.d.ts
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
//#region src/pdf/objects.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* The PDF object model: values, serialization, the cross-reference table and
|
|
4
|
-
* the trailer.
|
|
5
|
-
*
|
|
6
|
-
* Everything a backend writes into a PDF file passes through here, which is
|
|
7
|
-
* what makes byte-for-byte determinism enforceable rather than aspirational:
|
|
8
|
-
* numbers go through one formatter, dictionaries carry their entries as an
|
|
9
|
-
* ordered list (never an object or a `Map` whose iteration order depends on
|
|
10
|
-
* how it was built), and object numbers come from one allocator in call
|
|
11
|
-
* order.
|
|
12
|
-
*/
|
|
13
2
|
/** The one number formatter. Every number in the file is emitted through it. */
|
|
14
3
|
declare const formatNumber: (value: number) => string;
|
|
15
4
|
type PdfRef = {
|
package/dist/pdf/objects.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bytesToHex, encodeBinaryString, encodeUtf16BE, encodeUtf8 } from "../utils/textEncoding.js";
|
|
1
2
|
import { panic } from "better-result";
|
|
2
3
|
import { deflateSync } from "node:zlib";
|
|
3
4
|
//#region src/pdf/objects.ts
|
|
@@ -94,7 +95,10 @@ const pdfFlateStream = (entries, data) => pdfStream(pdfDict([...entries, ["Filte
|
|
|
94
95
|
const NAME_REGULAR = /^[A-Za-z0-9._\-+]$/u;
|
|
95
96
|
const encodeName = (value) => {
|
|
96
97
|
let out = "/";
|
|
97
|
-
for (const
|
|
98
|
+
for (const byte of encodeUtf8(value)) {
|
|
99
|
+
const char = String.fromCharCode(byte);
|
|
100
|
+
out += NAME_REGULAR.test(char) ? char : `#${byte.toString(16).padStart(2, "0").toUpperCase()}`;
|
|
101
|
+
}
|
|
98
102
|
return out;
|
|
99
103
|
};
|
|
100
104
|
const encodeAsciiString = (value) => {
|
|
@@ -108,11 +112,7 @@ const encodeAsciiString = (value) => {
|
|
|
108
112
|
}
|
|
109
113
|
return `${out})`;
|
|
110
114
|
};
|
|
111
|
-
const encodeTextString = (value) => {
|
|
112
|
-
let hex = "FEFF";
|
|
113
|
-
for (let index = 0; index < value.length; index += 1) hex += value.charCodeAt(index).toString(16).padStart(4, "0").toUpperCase();
|
|
114
|
-
return `<${hex}>`;
|
|
115
|
-
};
|
|
115
|
+
const encodeTextString = (value) => `<FEFF${bytesToHex(encodeUtf16BE(value)).toUpperCase()}>`;
|
|
116
116
|
const createByteSink = () => {
|
|
117
117
|
const chunks = [];
|
|
118
118
|
let length = 0;
|
|
@@ -122,9 +122,7 @@ const createByteSink = () => {
|
|
|
122
122
|
};
|
|
123
123
|
return {
|
|
124
124
|
writeAscii: (text) => {
|
|
125
|
-
|
|
126
|
-
for (let index = 0; index < text.length; index += 1) bytes[index] = text.charCodeAt(index) & 255;
|
|
127
|
-
writeBytes(bytes);
|
|
125
|
+
writeBytes(encodeBinaryString(text));
|
|
128
126
|
},
|
|
129
127
|
writeBytes,
|
|
130
128
|
offset: () => length,
|
package/dist/pdf/writePdf.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getShaper } from "../shaping/shaper.js";
|
|
2
|
+
import { encodeUtf8 } from "../utils/textEncoding.js";
|
|
2
3
|
import { collectResources, renderContentStream } from "./contentStream.js";
|
|
3
4
|
import { prepareFonts } from "./fonts.js";
|
|
4
5
|
import { decodeImage } from "./images.js";
|
|
@@ -288,7 +289,7 @@ const writePdf = async (list, options) => {
|
|
|
288
289
|
fonts: byFontIndex
|
|
289
290
|
});
|
|
290
291
|
const resources = collectResources(parts);
|
|
291
|
-
const contentRef = document.add(pdfFlateStream([],
|
|
292
|
+
const contentRef = document.add(pdfFlateStream([], encodeUtf8(renderContentStream(parts, resources))));
|
|
292
293
|
const annotationRefs = [];
|
|
293
294
|
for (const link of page.links) {
|
|
294
295
|
const annotation = buildLinkAnnotation({
|
|
@@ -13,11 +13,13 @@ import "../extensions/nodes/SdtExtension.js";
|
|
|
13
13
|
import { canonicalFieldNode } from "../fieldRepresentation.js";
|
|
14
14
|
import { resolveStateStory } from "../markupViewProjection.js";
|
|
15
15
|
import { joinAtParagraphMark } from "../paragraphMarkJoin.js";
|
|
16
|
+
import { carryParagraphProperties, paragraphLeftAfter } from "../paragraphPropertyCarry.js";
|
|
16
17
|
import { getDocumentNumbering } from "../plugins/documentNumbering.js";
|
|
17
18
|
import { getDocumentStyleResolver } from "../plugins/documentStyleState.js";
|
|
18
19
|
import { resolvedPreservedXmlAttrs } from "../preservedXmlReview.js";
|
|
19
20
|
import { setParagraphAttrsWithRebasedRunFormatting } from "../rebaseParagraphRunFormatting.js";
|
|
20
21
|
import { rejoinRunsAt } from "../rejoinRunCarriers.js";
|
|
22
|
+
import { commentPoint, resolvedCommentPoints } from "../replacedAnnotations.js";
|
|
21
23
|
import { getFolioNodeRevisionCarriers, nodePropertyRevisionSites } from "../revisionCarriers.js";
|
|
22
24
|
import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
|
|
23
25
|
import { reconstructRejectedRunFormattingMarks, restoreHistoricalRunFormatting } from "../runPropertyChangeResolution.js";
|
|
@@ -100,6 +102,16 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
100
102
|
const removeKeptMarksInBulk = revisionSet === null && keepType !== void 0;
|
|
101
103
|
const matchesRevision = (mark) => revisionSet === null || typeof mark.attrs["revisionId"] === "number" && revisionSet.has(mark.attrs["revisionId"]);
|
|
102
104
|
if (dispatch) {
|
|
105
|
+
const points = mode === "accept" ? resolvedCommentPoints({
|
|
106
|
+
doc: state.doc,
|
|
107
|
+
retiresStructure: (node, position) => {
|
|
108
|
+
if (node.type.name === "paragraph") return collectPPrMarkOp(node, position, from, to, mode, revisionSet)?.action === "join";
|
|
109
|
+
if (!rangeCoversNode(from, to, position, node)) return false;
|
|
110
|
+
if (node.type.name === "tableRow") return collectTableRowStructuralOp(node, position, mode, revisionSet)?.action === "remove";
|
|
111
|
+
return collectTableCellStructuralOps(node, position, mode, revisionSet).some((op) => op.type === "membership" && op.action === "remove");
|
|
112
|
+
},
|
|
113
|
+
removes: (node, position) => position >= from && position + node.nodeSize <= to && node.marks.some((mark) => mark.type === removeType && matchesRevision(mark))
|
|
114
|
+
}) : /* @__PURE__ */ new Map();
|
|
103
115
|
const tr = state.tr;
|
|
104
116
|
tr.setMeta(JOINED_RUNS_RESTYLED_META, true);
|
|
105
117
|
const deleteRanges = [];
|
|
@@ -110,6 +122,25 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
110
122
|
const tableCellStructuralOps = [];
|
|
111
123
|
let removedSectionEndpointCount = 0;
|
|
112
124
|
const removedSectionReferences = [];
|
|
125
|
+
const carryRestoredProperties = (position) => {
|
|
126
|
+
if (mode !== "reject" || revisionSet === null) return;
|
|
127
|
+
const source = tr.doc.nodeAt(position);
|
|
128
|
+
const mark = source ? expectParagraphAttrs(source).pPrMark : null;
|
|
129
|
+
if (!source || mark?.kind !== "del" && mark?.kind !== "moveFrom" || revisionSet.has(mark.info.id)) return;
|
|
130
|
+
const survivor = paragraphLeftAfter({
|
|
131
|
+
doc: tr.doc,
|
|
132
|
+
paragraphPos: position
|
|
133
|
+
});
|
|
134
|
+
if (survivor === null) return;
|
|
135
|
+
carryParagraphProperties({
|
|
136
|
+
tr,
|
|
137
|
+
position: survivor,
|
|
138
|
+
source,
|
|
139
|
+
styleResolver,
|
|
140
|
+
numbering,
|
|
141
|
+
revision: mark.info
|
|
142
|
+
});
|
|
143
|
+
};
|
|
113
144
|
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
114
145
|
if (node.type.name === "paragraph") {
|
|
115
146
|
const op = collectPPrMarkOp(node, pos, from, to, mode, revisionSet);
|
|
@@ -122,18 +153,21 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
122
153
|
styleResolver,
|
|
123
154
|
numbering
|
|
124
155
|
});
|
|
125
|
-
if (nextAttrs)
|
|
126
|
-
nextAttrs
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
156
|
+
if (nextAttrs) {
|
|
157
|
+
if (nextAttrs["styleId"] !== node.attrs["styleId"] && styleResolver) setParagraphAttrsWithRebasedRunFormatting({
|
|
158
|
+
nextAttrs,
|
|
159
|
+
paragraphPosition: pos,
|
|
160
|
+
styleResolver,
|
|
161
|
+
tr,
|
|
162
|
+
...mode === "reject" && { shouldRebase: (inline) => {
|
|
163
|
+
const deleted = inline.marks.some(({ type }) => type.name === "deletion");
|
|
164
|
+
const direct = inline.marks.some(({ type }) => type.name === "runFormattingOverride");
|
|
165
|
+
return !deleted || !direct;
|
|
166
|
+
} }
|
|
167
|
+
});
|
|
168
|
+
else tr.setNodeMarkup(pos, void 0, nextAttrs);
|
|
169
|
+
carryRestoredProperties(pos);
|
|
170
|
+
}
|
|
137
171
|
return true;
|
|
138
172
|
}
|
|
139
173
|
if (node.type.name === "tableRow" && rangeCoversNode(from, to, pos, node)) {
|
|
@@ -388,7 +422,10 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
388
422
|
removedSectionEndpointCount++;
|
|
389
423
|
removedSectionReferences.push(...sectionReferencesOf(paragraph));
|
|
390
424
|
}
|
|
391
|
-
} catch {
|
|
425
|
+
} catch {
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (op.markWasAdded) carryRestoredProperties(mappedPos);
|
|
392
429
|
}
|
|
393
430
|
if (removedSectionEndpointCount > 0) markTrackedSectionEndpointRemoval(tr, {
|
|
394
431
|
sourceDoc: state.doc,
|
|
@@ -416,6 +453,7 @@ function resolveChange(from, to, mode, revisionIds) {
|
|
|
416
453
|
if (field.type === node.type) tr.setNodeMarkup(position, void 0, node.attrs, node.marks);
|
|
417
454
|
else tr.replaceWith(position, position + field.nodeSize, node);
|
|
418
455
|
}
|
|
456
|
+
for (const [id, position] of [...points].toReversed()) tr.insert(tr.mapping.map(position, -1), commentPoint(tr.doc.type.schema, id));
|
|
419
457
|
if (tr.steps.length > 0) dispatch(tr);
|
|
420
458
|
}
|
|
421
459
|
return true;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Node } from "prosemirror-model";
|
|
2
|
+
//#region src/prosemirror/commentRangeInlineAtoms.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Whether an inline atom extends a comment range it sits in.
|
|
5
|
+
*
|
|
6
|
+
* - `extends`: a comment mark on the atom keeps the comment's range alive.
|
|
7
|
+
* - `inert`: the atom is invisible to the reader, so a comment mark on it would
|
|
8
|
+
* be a ghost range nobody can see or select. Comment integrity strips the mark
|
|
9
|
+
* and never counts the atom as range content.
|
|
10
|
+
*
|
|
11
|
+
* This is separate from revision ownership: a cached rendered page break must
|
|
12
|
+
* stay inside its tracked-change wrapper, but it can never hold a comment on
|
|
13
|
+
* its own.
|
|
14
|
+
*/
|
|
15
|
+
type CommentRangeInlineAtomParticipation = "extends" | "inert";
|
|
16
|
+
/** Keyed by the tracked-run atom set, which the fixed-point test binds to the schema. */
|
|
17
|
+
declare const COMMENT_RANGE_INLINE_ATOM_PARTICIPATION: Readonly<{
|
|
18
|
+
readonly bookmarkBoundary: "extends";
|
|
19
|
+
readonly commentReference: "inert";
|
|
20
|
+
readonly field: "extends";
|
|
21
|
+
readonly hardBreak: "extends";
|
|
22
|
+
readonly image: "extends";
|
|
23
|
+
readonly math: "extends";
|
|
24
|
+
readonly moveRangeBoundary: "extends";
|
|
25
|
+
readonly noteMarker: "extends";
|
|
26
|
+
readonly pageBreakRun: "extends";
|
|
27
|
+
readonly preservedXml: "extends";
|
|
28
|
+
readonly rangeAnchor: "inert";
|
|
29
|
+
readonly renderedPageBreak: "inert";
|
|
30
|
+
readonly shape: "extends";
|
|
31
|
+
readonly structuredField: "extends";
|
|
32
|
+
readonly symbol: "extends";
|
|
33
|
+
readonly tab: "extends";
|
|
34
|
+
readonly text: "extends";
|
|
35
|
+
readonly textBoxAnchor: "extends";
|
|
36
|
+
}>;
|
|
37
|
+
/** Whether a node is an inline atom that must never carry or extend a comment range. */
|
|
38
|
+
declare const isCommentRangeInertAtom: (node: Node) => boolean;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { COMMENT_RANGE_INLINE_ATOM_PARTICIPATION, CommentRangeInlineAtomParticipation, isCommentRangeInertAtom };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { panic } from "better-result";
|
|
2
|
+
//#region src/prosemirror/commentRangeInlineAtoms.ts
|
|
3
|
+
/** Keyed by the tracked-run atom set, which the fixed-point test binds to the schema. */
|
|
4
|
+
const COMMENT_RANGE_INLINE_ATOM_PARTICIPATION = Object.freeze({
|
|
5
|
+
bookmarkBoundary: "extends",
|
|
6
|
+
commentReference: "inert",
|
|
7
|
+
field: "extends",
|
|
8
|
+
hardBreak: "extends",
|
|
9
|
+
image: "extends",
|
|
10
|
+
math: "extends",
|
|
11
|
+
moveRangeBoundary: "extends",
|
|
12
|
+
noteMarker: "extends",
|
|
13
|
+
pageBreakRun: "extends",
|
|
14
|
+
preservedXml: "extends",
|
|
15
|
+
rangeAnchor: "inert",
|
|
16
|
+
renderedPageBreak: "inert",
|
|
17
|
+
shape: "extends",
|
|
18
|
+
structuredField: "extends",
|
|
19
|
+
symbol: "extends",
|
|
20
|
+
tab: "extends",
|
|
21
|
+
text: "extends",
|
|
22
|
+
textBoxAnchor: "extends"
|
|
23
|
+
});
|
|
24
|
+
const participationByName = new Map(Object.entries(COMMENT_RANGE_INLINE_ATOM_PARTICIPATION));
|
|
25
|
+
/** Whether a node is an inline atom that must never carry or extend a comment range. */
|
|
26
|
+
const isCommentRangeInertAtom = (node) => {
|
|
27
|
+
if (!node.isInline || !node.isAtom) return false;
|
|
28
|
+
const participation = participationByName.get(node.type.name);
|
|
29
|
+
if (!participation) panic(`Inline atom ${JSON.stringify(node.type.name)} has no comment-range participation`);
|
|
30
|
+
return participation === "inert";
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { COMMENT_RANGE_INLINE_ATOM_PARTICIPATION, isCommentRangeInertAtom };
|
|
@@ -2,15 +2,15 @@ import { Node, ResolvedPos } from "prosemirror-model";
|
|
|
2
2
|
//#region src/prosemirror/containerFinalParagraph.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Whether the paragraph starting at `at` is the one its container ENDS with,
|
|
5
|
-
*
|
|
5
|
+
* where a paragraph break cannot join into a following paragraph.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* Added boundaries normally rotate onto a preceding paragraph, so rejecting
|
|
8
|
+
* them joins back into this one. If an occupied boundary or a table prevents
|
|
9
|
+
* rotation, the final inserted paragraph must retain its own revision: the
|
|
10
|
+
* resolver removes the whole paragraph after rejecting its inserted content.
|
|
11
|
+
* A terminal deletion, by contrast, clears without removing the container's
|
|
12
|
+
* required ending. Bodies, table cells, headers, footers, notes and text boxes
|
|
13
|
+
* share these rules.
|
|
14
14
|
*
|
|
15
15
|
* A paragraph before a TABLE is not one of those: the table is a following
|
|
16
16
|
* sibling, so the paragraph does not end anything and carries its own mark
|
|
@@ -14,15 +14,15 @@ const nothingFollowsIn = (parent, fromIndex, paragraphTypeName) => {
|
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
16
|
* Whether the paragraph starting at `at` is the one its container ENDS with,
|
|
17
|
-
*
|
|
17
|
+
* where a paragraph break cannot join into a following paragraph.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
19
|
+
* Added boundaries normally rotate onto a preceding paragraph, so rejecting
|
|
20
|
+
* them joins back into this one. If an occupied boundary or a table prevents
|
|
21
|
+
* rotation, the final inserted paragraph must retain its own revision: the
|
|
22
|
+
* resolver removes the whole paragraph after rejecting its inserted content.
|
|
23
|
+
* A terminal deletion, by contrast, clears without removing the container's
|
|
24
|
+
* required ending. Bodies, table cells, headers, footers, notes and text boxes
|
|
25
|
+
* share these rules.
|
|
26
26
|
*
|
|
27
27
|
* A paragraph before a TABLE is not one of those: the table is a following
|
|
28
28
|
* sibling, so the paragraph does not end anything and carries its own mark
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { joinCommentRangesAcrossParagraphs } from "../../docx/commentRangeJoin.js";
|
|
2
2
|
import { completeCommentReferences } from "../../docx/commentReferenceCompletion.js";
|
|
3
|
+
import { buildSections } from "../../docx/documentParser.js";
|
|
3
4
|
import { normalizeFoldedListNumbers } from "../../docx/foldedListNumberFields.js";
|
|
4
5
|
import { getDocumentSourceStyles } from "../../docx/headerFooterVerbatim.js";
|
|
5
6
|
import { EDITED_PREVIEW_FINGERPRINT, imageRawXmlFingerprint } from "../../docx/imageRawXml.js";
|
|
@@ -16,6 +17,7 @@ import { createStyleEngine } from "../../style-engine/styleEngine.js";
|
|
|
16
17
|
import { normalizeShapeTextAnchor, presetDashForOutlineAttr } from "../../types/documentEnumValues.js";
|
|
17
18
|
import { presetDashForCssBorderStyle } from "../../utils/borderCss.js";
|
|
18
19
|
import { canonicalJson } from "../../utils/canonicalJson.js";
|
|
20
|
+
import { getFindParagraphText } from "../../utils/findReplace.js";
|
|
19
21
|
import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
|
|
20
22
|
import { emuToPixels, emuToStrokePixels, pixelsToEmu } from "../../utils/units.js";
|
|
21
23
|
import { unchangedAlternateContentXml } from "../alternateContentAttrs.js";
|
|
@@ -397,7 +399,7 @@ function fromProseDoc(pmDoc, baseDocument, { stylesheetSource, reuse = "none" })
|
|
|
397
399
|
const documentBody = { content: blocks };
|
|
398
400
|
if (baseDocument?.package.document.background) documentBody.background = baseDocument.package.document.background;
|
|
399
401
|
if (baseDocument?.package.document.finalSectionProperties) documentBody.finalSectionProperties = baseDocument.package.document.finalSectionProperties;
|
|
400
|
-
if (baseDocument?.package.document.sections) documentBody.sections =
|
|
402
|
+
if (baseDocument?.package.document.sections) documentBody.sections = buildSections(blocks, documentBody.finalSectionProperties);
|
|
401
403
|
if (baseDocument?.package.document.comments) documentBody.comments = baseDocument.package.document.comments;
|
|
402
404
|
const numbering = completeNumberingForDoc(baseDocument?.package.numbering, pmDoc);
|
|
403
405
|
if (baseDocument) {
|
|
@@ -1582,12 +1584,16 @@ function extractParagraphContent(originalParagraph, _documentCounts, emptyHyperl
|
|
|
1582
1584
|
};
|
|
1583
1585
|
const appendDirectRun = (node, run, coalescePlainText = false) => {
|
|
1584
1586
|
if (currentHyperlink) flushCurrentInline();
|
|
1585
|
-
const marksKey = getMarksKey(node.marks)
|
|
1587
|
+
const marksKey = getMarksKey(node.marks.filter((mark) => {
|
|
1588
|
+
if (mark.type.name !== "runIdentity") return true;
|
|
1589
|
+
const { emptyFormatting, preservedAttributes, preserved } = expectRunIdentityMarkAttrs(mark);
|
|
1590
|
+
return emptyFormatting !== true || (preservedAttributes?.length ?? 0) > 0 || (preserved?.children?.length ?? 0) > 0;
|
|
1591
|
+
}));
|
|
1586
1592
|
const ownerId = runIdentityId(node);
|
|
1587
1593
|
const currentOwnerId = currentRun ? sourceRunOwners.get(currentRun) : void 0;
|
|
1588
1594
|
const currentRunIsPlainText = currentRun?.content.every((runContent) => runContent.type === "text");
|
|
1589
1595
|
const joinsOwnedSourceRun = ownerId !== void 0 && ownerId === currentOwnerId && currentRun !== null && runsShareProperties(currentRun, run);
|
|
1590
|
-
const joinsOrdinaryText = coalescePlainText &&
|
|
1596
|
+
const joinsOrdinaryText = coalescePlainText && currentRun !== null && runsShareProperties(currentRun, run) && currentRunIsPlainText === true && currentMarksKey === marksKey;
|
|
1591
1597
|
if (currentRun && (joinsOwnedSourceRun || joinsOrdinaryText)) {
|
|
1592
1598
|
if (joinsOrdinaryText) {
|
|
1593
1599
|
for (const runContent of run.content) if (runContent.type === "text") appendTextToRun(currentRun, runContent.text);
|
|
@@ -2610,7 +2616,10 @@ const reconcileEmptyFieldResultRuns = (runs, displayRun) => {
|
|
|
2610
2616
|
return reconciled;
|
|
2611
2617
|
};
|
|
2612
2618
|
const synchronizeFieldDisplayText = (content, displayText, fallbackRun) => {
|
|
2613
|
-
|
|
2619
|
+
const currentText = getFindParagraphText({
|
|
2620
|
+
type: "paragraph",
|
|
2621
|
+
content
|
|
2622
|
+
});
|
|
2614
2623
|
const visitRunsIn = (items, visit) => {
|
|
2615
2624
|
for (const child of items) {
|
|
2616
2625
|
if (child.type === "run") {
|
|
@@ -2623,9 +2632,6 @@ const synchronizeFieldDisplayText = (content, displayText, fallbackRun) => {
|
|
|
2623
2632
|
const visitRuns = (visit) => {
|
|
2624
2633
|
visitRunsIn(content, visit);
|
|
2625
2634
|
};
|
|
2626
|
-
visitRuns((run) => {
|
|
2627
|
-
for (const runContent of run.content) if (runContent.type === "text") currentText += runContent.text;
|
|
2628
|
-
});
|
|
2629
2635
|
if (currentText === displayText) return content;
|
|
2630
2636
|
let replacedText = false;
|
|
2631
2637
|
visitRuns((run) => {
|
|
@@ -3319,7 +3325,7 @@ function tableCellAttrsToFormatting(attrs) {
|
|
|
3319
3325
|
if (attrs.margins && !sameResolvedValue(attrs.margins, attrs._resolvedMargins)) result.margins = buildCellMarginsFromAttrs(attrs.margins);
|
|
3320
3326
|
if (attrs.textDirection !== (orig.textDirection ?? void 0)) if (attrs.textDirection) result.textDirection = attrs.textDirection;
|
|
3321
3327
|
else delete result.textDirection;
|
|
3322
|
-
return result;
|
|
3328
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
3323
3329
|
}
|
|
3324
3330
|
const authoredWidth = attrs._authoredWidth;
|
|
3325
3331
|
if (!(attrs.colspan > 1 || attrs.rowspan > 1 || authoredWidth !== void 0 || attrs.verticalAlign || backgroundChanged || attrs.borders || attrs.margins || attrs.textDirection)) return;
|
|
@@ -31,6 +31,7 @@ import { MOVE_RANGE_BOUNDARY_NODE_NAME } from "../extensions/nodes/MoveRangeBoun
|
|
|
31
31
|
import { RANGE_ANCHOR_NODE_NAME } from "../extensions/nodes/RangeAnchorExtension.js";
|
|
32
32
|
import "../extensions/nodes/SdtExtension.js";
|
|
33
33
|
import { fieldRequiresStructuredContent } from "../fieldRepresentation.js";
|
|
34
|
+
import { getInlineDisplayText } from "../inlineDisplayText.js";
|
|
34
35
|
import { inlineWrapperLayer } from "../inlineWrapperStack.js";
|
|
35
36
|
import { CLEARED_LIST_RENDERING_ATTRS } from "../listMarker.js";
|
|
36
37
|
import { listRenderingFor } from "../listRendering.js";
|
|
@@ -42,7 +43,7 @@ import { directionFromBidi } from "../paragraphDirection.js";
|
|
|
42
43
|
import { paragraphIndentationFromFormatting } from "../paragraphIndentation.js";
|
|
43
44
|
import { lineSpacingProvenanceFromSpacing } from "../paragraphSpacing.js";
|
|
44
45
|
import { RUN_IDENTITY_MARK_NAME, hasRunIdentityPayload, runIdentityAttrs } from "../runIdentity.js";
|
|
45
|
-
import {
|
|
46
|
+
import { continueSourceCarrierIdentitiesAcrossRevisions } from "../runIdentityAcrossRevisions.js";
|
|
46
47
|
import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, resolveParagraphInheritedRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
|
|
47
48
|
import { schema } from "../schema/index.js";
|
|
48
49
|
import { PRESERVED_XML_LEVELS } from "../schema/nodes.js";
|
|
@@ -112,7 +113,7 @@ const runIdentityMark = (run, nextRunIdentityId) => {
|
|
|
112
113
|
const payload = {
|
|
113
114
|
preservedAttributes: run.preservedAttributes,
|
|
114
115
|
preserved: run.formatting?.preserved,
|
|
115
|
-
emptyFormatting: run.formatting !== void 0 && Object.keys(run.formatting).length === 0
|
|
116
|
+
emptyFormatting: run.formatting !== void 0 && Object.keys(run.formatting).length === 0 ? true : void 0
|
|
116
117
|
};
|
|
117
118
|
if (!runHasPageBreakContent(run) && !runHasMixedContent(run) && !hasRunIdentityPayload(payload)) return null;
|
|
118
119
|
return schema.mark(RUN_IDENTITY_MARK_NAME, runIdentityAttrs(nextRunIdentityId(), payload));
|
|
@@ -676,7 +677,7 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
|
|
|
676
677
|
if (emptyHyperlinks) attrs._emptyHyperlinks = emptyHyperlinks;
|
|
677
678
|
return createProseParagraphWithPropertySource(schema.nodes["paragraph"], paragraph, {
|
|
678
679
|
attrs,
|
|
679
|
-
content:
|
|
680
|
+
content: continueSourceCarrierIdentitiesAcrossRevisions(inlineNodes)
|
|
680
681
|
});
|
|
681
682
|
}
|
|
682
683
|
/**
|
|
@@ -1256,7 +1257,7 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1256
1257
|
attrs.margins = effectiveFormatting.margins;
|
|
1257
1258
|
attrs._resolvedMargins = effectiveFormatting.margins;
|
|
1258
1259
|
}
|
|
1259
|
-
|
|
1260
|
+
attrs._originalFormatting = formatting ?? {};
|
|
1260
1261
|
if (cell.propertyChanges && cell.propertyChanges.length > 0) attrs.tcPrChange = [...cell.propertyChanges];
|
|
1261
1262
|
if (cell.contentControls && cell.contentControls.length > 0) attrs.contentControls = cell.contentControls;
|
|
1262
1263
|
if (cell.carrierStack?.length) attrs.carrierStack = cell.carrierStack;
|
|
@@ -1368,27 +1369,24 @@ function standaloneTableCellToProseMirror(cell, nodeType) {
|
|
|
1368
1369
|
});
|
|
1369
1370
|
}
|
|
1370
1371
|
function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyperlinkInstanceIndex, runScope, textBoxAnchors }) {
|
|
1371
|
-
let displayText = "";
|
|
1372
1372
|
let fieldFormatting;
|
|
1373
1373
|
let fieldPropertyChanges;
|
|
1374
1374
|
const inlineNodes = [];
|
|
1375
|
-
const
|
|
1375
|
+
const hasPageBreakContent = fieldResultHasPageBreakContent(field);
|
|
1376
|
+
const resultRuns = field.type === "complexField" ? field.fieldResult : field.content.flatMap((content) => content.type === "run" ? [content] : []);
|
|
1376
1377
|
const appendRun = (run, into) => {
|
|
1377
|
-
for (const content of run.content) if (content.type === "text") displayText += content.text;
|
|
1378
1378
|
fieldFormatting ??= run.formatting;
|
|
1379
1379
|
fieldPropertyChanges ??= run.propertyChanges;
|
|
1380
|
-
if (field.type !== "simpleField" && !hasStructuredSourceContent) return;
|
|
1381
1380
|
into.push(...convertRun(run, getInheritedRunFormatting(run.formatting, field.fieldType), runScope, styleResolver, textBoxAnchors));
|
|
1382
1381
|
};
|
|
1383
|
-
const
|
|
1382
|
+
const collectFormatting = (items) => {
|
|
1384
1383
|
for (const item of items) switch (item.type) {
|
|
1385
1384
|
case "run":
|
|
1386
|
-
for (const child of item.content) if (child.type === "text") displayText += child.text;
|
|
1387
1385
|
fieldFormatting ??= item.formatting;
|
|
1388
1386
|
fieldPropertyChanges ??= item.propertyChanges;
|
|
1389
1387
|
break;
|
|
1390
1388
|
case "hyperlink":
|
|
1391
|
-
|
|
1389
|
+
collectFormatting(item.children);
|
|
1392
1390
|
break;
|
|
1393
1391
|
case "inlineWrapper":
|
|
1394
1392
|
case "inlineSdt":
|
|
@@ -1396,20 +1394,16 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1396
1394
|
case "deletion":
|
|
1397
1395
|
case "moveFrom":
|
|
1398
1396
|
case "moveTo":
|
|
1399
|
-
|
|
1397
|
+
collectFormatting(item.content);
|
|
1400
1398
|
break;
|
|
1401
1399
|
case "simpleField":
|
|
1402
|
-
|
|
1400
|
+
collectFormatting(item.content);
|
|
1403
1401
|
break;
|
|
1404
1402
|
case "complexField":
|
|
1405
|
-
|
|
1403
|
+
collectFormatting(item.fieldResult);
|
|
1406
1404
|
break;
|
|
1407
1405
|
case "preservedInline":
|
|
1408
|
-
|
|
1409
|
-
break;
|
|
1410
|
-
case "mathEquation":
|
|
1411
|
-
displayText += item.plainText ?? "";
|
|
1412
|
-
break;
|
|
1406
|
+
case "mathEquation": break;
|
|
1413
1407
|
case "bookmarkStart":
|
|
1414
1408
|
case "bookmarkEnd":
|
|
1415
1409
|
case "commentRangeStart":
|
|
@@ -1433,7 +1427,6 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1433
1427
|
break;
|
|
1434
1428
|
case "hyperlink":
|
|
1435
1429
|
for (const { content: child } of withInlineWrapperStacks(content.children)) if (child.type === "run") {
|
|
1436
|
-
for (const runContent of child.content) if (runContent.type === "text") displayText += runContent.text;
|
|
1437
1430
|
fieldFormatting ??= child.formatting;
|
|
1438
1431
|
fieldPropertyChanges ??= child.propertyChanges;
|
|
1439
1432
|
}
|
|
@@ -1449,7 +1442,7 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1449
1442
|
case "deletion":
|
|
1450
1443
|
case "moveFrom":
|
|
1451
1444
|
case "moveTo":
|
|
1452
|
-
|
|
1445
|
+
collectFormatting(content.content);
|
|
1453
1446
|
itemNodes.push(...convertTrackedChange(content, content.type === "insertion" || content.type === "moveTo" ? "insertion" : "deletion", nextHyperlinkInstanceIndex, runScope, {
|
|
1454
1447
|
current: getInheritedRunFormatting,
|
|
1455
1448
|
historical: getInheritedRunFormatting
|
|
@@ -1468,8 +1461,8 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
|
|
|
1468
1461
|
styleResolver,
|
|
1469
1462
|
createMark: runScope.createMark
|
|
1470
1463
|
});
|
|
1471
|
-
const createStructuredField = fieldRequiresStructuredContent(inlineNodes);
|
|
1472
|
-
const
|
|
1464
|
+
const createStructuredField = (field.type === "simpleField" || hasPageBreakContent) && fieldRequiresStructuredContent(inlineNodes);
|
|
1465
|
+
const displayText = getInlineDisplayText(schema.node("paragraph", null, inlineNodes));
|
|
1473
1466
|
const emptyResultRuns = displayText === "" && resultRuns.length > 0 && (field.type === "complexField" || field.content.length === resultRuns.length) && resultRuns.every((run) => run.content.every((item) => item.type === "text" && item.text === "")) ? resultRuns : void 0;
|
|
1474
1467
|
const resultPropertyChanges = emptyResultRuns ? emptyFieldRunPropertyChanges(emptyResultRuns) : fieldPropertyChanges;
|
|
1475
1468
|
if (!createStructuredField && resultPropertyChanges && resultPropertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...resultPropertyChanges] }));
|