@stll/folio-core 0.47.7 → 0.49.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/dist/ai-edits/apply.js +565 -121
- package/dist/ai-edits/minimal-replacement.d.ts +64 -0
- package/dist/ai-edits/minimal-replacement.js +282 -0
- package/dist/controller/fontReadiness.js +3 -3
- package/dist/controller/hyphenationReadiness.d.ts +19 -0
- package/dist/controller/hyphenationReadiness.js +47 -0
- package/dist/controller/layoutPipeline.d.ts +3 -0
- package/dist/controller/layoutPipeline.js +70 -18
- package/dist/display-list/build/buildDisplayList.js +39 -12
- package/dist/display-list/build/pageFurniture.d.ts +7 -1
- package/dist/display-list/build/pageFurniture.js +21 -8
- package/dist/display-list/build/paragraphPrimitives.js +68 -11
- package/dist/display-list/build/tablePrimitives.js +10 -6
- package/dist/display-list/build/textBoxPrimitives.js +1 -1
- package/dist/display-list/build/unsupported.d.ts +2 -2
- package/dist/display-list/build/unsupported.js +0 -0
- package/dist/display-list/dom/renderDisplayListToDom.js +0 -1
- package/dist/docx/attributeRemainder.js +10 -2
- package/dist/docx/blockContentParser.d.ts +2 -0
- package/dist/docx/blockContentParser.js +79 -64
- package/dist/docx/bulletMarkers.d.ts +18 -2
- package/dist/docx/bulletMarkers.js +27 -2
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +57 -45
- package/dist/docx/containerChildren.d.ts +21 -8
- package/dist/docx/containerChildren.js +39 -9
- package/dist/docx/documentParser.d.ts +5 -1
- package/dist/docx/documentParser.js +8 -5
- package/dist/docx/documentSectionFacts.d.ts +22 -0
- package/dist/docx/documentSectionFacts.js +43 -0
- package/dist/docx/drawingGroupChildren.d.ts +60 -0
- package/dist/docx/drawingGroupChildren.js +176 -0
- package/dist/docx/drawingUtils.js +3 -0
- package/dist/docx/fieldParser.d.ts +8 -1
- package/dist/docx/fieldParser.js +47 -3
- package/dist/docx/fontTableParser.js +34 -27
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +15 -12
- package/dist/docx/groupDrawingParser.d.ts +9 -2
- package/dist/docx/groupDrawingParser.js +125 -37
- package/dist/docx/headerFooterParser.d.ts +7 -2
- package/dist/docx/headerFooterParser.js +15 -5
- package/dist/docx/hyperlinkParser.d.ts +48 -36
- package/dist/docx/hyperlinkParser.js +97 -82
- package/dist/docx/numberingParser.js +108 -84
- package/dist/docx/packageParts.d.ts +45 -1
- package/dist/docx/packageParts.js +93 -2
- package/dist/docx/paraIdAttribute.d.ts +3 -2
- package/dist/docx/paragraphParser.d.ts +5 -1
- package/dist/docx/paragraphParser.js +468 -365
- package/dist/docx/paragraphProperties.js +123 -109
- package/dist/docx/paragraphPropertySource.d.ts +6 -1
- package/dist/docx/paragraphPropertySource.js +9 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +143 -10
- package/dist/docx/parser.d.ts +7 -1
- package/dist/docx/parser.js +33 -16
- package/dist/docx/previewBudget.d.ts +55 -33
- package/dist/docx/previewBudget.js +59 -65
- package/dist/docx/rezip.js +41 -58
- package/dist/docx/runParser.d.ts +4 -1
- package/dist/docx/runParser.js +182 -184
- package/dist/docx/sdtProperties.js +87 -84
- package/dist/docx/sectionParser.js +169 -160
- package/dist/docx/selectiveSaveFlags.d.ts +10 -3
- package/dist/docx/selectiveSaveFlags.js +1 -1
- package/dist/docx/selectiveXmlPatch.d.ts +56 -34
- package/dist/docx/selectiveXmlPatch.js +222 -115
- package/dist/docx/serializer/groupTextBoxWriteBack.d.ts +12 -0
- package/dist/docx/serializer/groupTextBoxWriteBack.js +101 -0
- package/dist/docx/serializer/paragraphSerializer.js +47 -42
- package/dist/docx/serializer/runSerializer.d.ts +5 -1
- package/dist/docx/serializer/runSerializer.js +4 -3
- package/dist/docx/serializer/settingsSerializer.js +19 -1
- package/dist/docx/settingsParser.js +8 -0
- package/dist/docx/shapeAlternateContent.d.ts +25 -0
- package/dist/docx/shapeAlternateContent.js +52 -0
- package/dist/docx/streamingXmlParser.d.ts +6 -2
- package/dist/docx/streamingXmlParser.js +12 -7
- package/dist/docx/styleParser.js +34 -8
- package/dist/docx/tableParser.d.ts +21 -12
- package/dist/docx/tableParser.js +518 -441
- package/dist/docx/textBoxParser.d.ts +18 -5
- package/dist/docx/textBoxParser.js +12 -6
- package/dist/docx/verbatimCapture.d.ts +10 -8
- package/dist/docx/verbatimCapture.js +45 -2
- package/dist/docx/vmlImageParser.d.ts +15 -13
- package/dist/docx/vmlImageParser.js +75 -60
- package/dist/docx/vmlPreview.d.ts +3 -3
- package/dist/docx/vmlPreview.js +3 -4
- package/dist/docx/xmlNamespaceContext.d.ts +9 -0
- package/dist/docx/xmlNamespaceContext.js +54 -0
- package/dist/docx/xmlParser.d.ts +6 -3
- package/dist/docx/xmlParser.js +11 -41
- package/dist/docx/xmlResourceLimits.d.ts +2 -1
- package/dist/docx/xmlResourceLimits.js +4 -1
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/headless-layout.d.ts +11 -2
- package/dist/headless-layout.js +153 -107
- package/dist/internal/headlessRevisionResolution.js +50 -13
- package/dist/internal/paragraphFormattingSerialization.js +3 -3
- package/dist/layout-bridge/convert/endnoteLayout.d.ts +65 -0
- package/dist/layout-bridge/convert/endnoteLayout.js +227 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +19 -3
- package/dist/layout-bridge/convert/footnoteLayout.js +40 -31
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -7
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -20
- package/dist/layout-bridge/convert/paragraphMarkFormatting.d.ts +10 -0
- package/dist/layout-bridge/convert/paragraphMarkFormatting.js +59 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +29 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +284 -39
- package/dist/layout-bridge/engine/hitTest.js +5 -3
- package/dist/layout-bridge/engine/selectionRects.js +5 -3
- package/dist/layout-engine/anchorLayoutInCellCompatibility.d.ts +10 -0
- package/dist/layout-engine/anchorLayoutInCellCompatibility.js +22 -0
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +102 -14
- package/dist/layout-engine/justificationCompatibility.d.ts +1 -1
- package/dist/layout-engine/justificationCompatibility.js +9 -5
- package/dist/layout-engine/keep-together.d.ts +15 -6
- package/dist/layout-engine/keep-together.js +43 -16
- package/dist/layout-engine/layoutInstrumentation.d.ts +8 -2
- package/dist/layout-engine/layoutInstrumentation.js +8 -1
- package/dist/layout-engine/measure/advanceComposition.js +50 -7
- package/dist/layout-engine/measure/hyphenationDictionaries.d.ts +74 -0
- package/dist/layout-engine/measure/hyphenationDictionaries.js +138 -0
- package/dist/layout-engine/measure/hyphenationPreload.d.ts +11 -0
- package/dist/layout-engine/measure/hyphenationPreload.js +24 -0
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +12 -2
- package/dist/layout-engine/measure/lineBreakProvider.js +30 -30
- package/dist/layout-engine/measure/lineBreaks.d.ts +6 -1
- package/dist/layout-engine/measure/lineBreaks.js +10 -3
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +9 -6
- package/dist/layout-engine/measure/listMarkerWidth.js +20 -22
- package/dist/layout-engine/measure/measureBlocks.js +46 -10
- package/dist/layout-engine/measure/measureContainer.js +51 -8
- package/dist/layout-engine/measure/measureHelpers.d.ts +15 -3
- package/dist/layout-engine/measure/measureHelpers.js +34 -8
- package/dist/layout-engine/measure/measureParagraph.js +143 -101
- package/dist/layout-engine/measure/measureTypes.d.ts +5 -0
- package/dist/layout-engine/measure/smallCapsCasing.d.ts +56 -0
- package/dist/layout-engine/measure/smallCapsCasing.js +88 -0
- package/dist/layout-engine/measure/tabCalculator.d.ts +2 -0
- package/dist/layout-engine/measure/tabCalculator.js +2 -1
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +51 -19
- package/dist/layout-engine/measure/tableCellGrid.d.ts +28 -3
- package/dist/layout-engine/measure/tableCellGrid.js +45 -5
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
- package/dist/layout-engine/noteAreaFlow.d.ts +19 -0
- package/dist/layout-engine/noteAreaFlow.js +83 -0
- package/dist/layout-engine/paginator.d.ts +12 -1
- package/dist/layout-engine/paginator.js +18 -2
- package/dist/layout-engine/paragraphSpacing.d.ts +4 -2
- package/dist/layout-engine/paragraphSpacing.js +2 -1
- package/dist/layout-engine/tableRowBreak.d.ts +8 -1
- package/dist/layout-engine/tableRowBreak.js +25 -2
- package/dist/layout-engine/types.d.ts +108 -3
- package/dist/layout-engine/types.js +96 -1
- package/dist/layout-painter/index.d.ts +3 -0
- package/dist/layout-painter/renderPage.js +32 -83
- package/dist/layout-painter/renderParagraph.d.ts +6 -1
- package/dist/layout-painter/renderParagraph.js +75 -26
- package/dist/layout-painter/renderTable.js +26 -13
- package/dist/layout-painter/renderTextBox.d.ts +12 -2
- package/dist/layout-painter/renderTextBox.js +26 -2
- package/dist/prosemirror/alternateContentAttrs.d.ts +9 -0
- package/dist/prosemirror/alternateContentAttrs.js +35 -0
- package/dist/prosemirror/attrs/index.d.ts +9 -9
- package/dist/prosemirror/attrs/index.js +133 -11
- package/dist/prosemirror/commands/comments.js +51 -41
- package/dist/prosemirror/contentControlRevisions.d.ts +43 -0
- package/dist/prosemirror/contentControlRevisions.js +84 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +54 -23
- package/dist/prosemirror/conversion/markInterner.d.ts +21 -0
- package/dist/prosemirror/conversion/markInterner.js +90 -0
- package/dist/prosemirror/conversion/toProseDoc.js +117 -58
- package/dist/prosemirror/extensions/core/DocExtension.js +2 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +7 -7
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -7
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +6 -2
- package/dist/prosemirror/extensions/marks/markUtils.js +39 -51
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +6 -3
- package/dist/prosemirror/extensions/nodes/SdtExtension.js +9 -2
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +5 -1
- package/dist/prosemirror/listMarker.d.ts +1 -0
- package/dist/prosemirror/listMarker.js +4 -2
- package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
- package/dist/prosemirror/listRenderingAttrs.js +3 -0
- package/dist/prosemirror/paragraphDirection.d.ts +29 -2
- package/dist/prosemirror/paragraphDirection.js +21 -2
- package/dist/prosemirror/plugins/suggestionMode.js +37 -8
- package/dist/prosemirror/rejoinRunCarriers.d.ts +27 -0
- package/dist/prosemirror/rejoinRunCarriers.js +66 -0
- package/dist/prosemirror/runIdentityAcrossRevisions.d.ts +10 -0
- package/dist/prosemirror/runIdentityAcrossRevisions.js +90 -0
- package/dist/prosemirror/schema/nodes.d.ts +50 -6
- package/dist/prosemirror/textBoxHostParagraph.d.ts +13 -0
- package/dist/prosemirror/textBoxHostParagraph.js +21 -0
- package/dist/prosemirror/validation.js +91 -80
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/createDocument.js +10 -1
- package/dist/utils/scriptSegments.d.ts +33 -4
- package/dist/utils/scriptSegments.js +39 -6
- package/dist/utils/textFormattingMerge.d.ts +17 -3
- package/dist/utils/textFormattingMerge.js +18 -12
- package/dist/utils/trailingText.d.ts +22 -0
- package/dist/utils/trailingText.js +32 -0
- package/package.json +2 -2
- package/dist/layout-engine/justifiedLineFit.d.ts +0 -7
- package/dist/layout-engine/justifiedLineFit.js +0 -6
|
@@ -375,23 +375,16 @@ function getMarkAttr(state, markType, attr) {
|
|
|
375
375
|
});
|
|
376
376
|
return value;
|
|
377
377
|
}
|
|
378
|
-
const
|
|
378
|
+
const withDirectFontProvenance = (attrs, directFormatting) => {
|
|
379
379
|
const directFontProperties = [];
|
|
380
380
|
if (directFormatting?.fontFamily !== void 0) directFontProperties.push("fontFamily");
|
|
381
381
|
if (directFormatting?.fontSize !== void 0) directFontProperties.push("fontSize");
|
|
382
382
|
if (directFormatting?.color !== void 0) directFontProperties.push("color");
|
|
383
|
-
if (directFontProperties.length === 0) return;
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const override = schema.mark("runFormattingOverride", {
|
|
387
|
-
...existing?.attrs,
|
|
383
|
+
if (directFontProperties.length === 0) return attrs;
|
|
384
|
+
return {
|
|
385
|
+
...attrs,
|
|
388
386
|
directFontProperties
|
|
389
|
-
}
|
|
390
|
-
if (index >= 0) {
|
|
391
|
-
marks[index] = override;
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
marks.push(override);
|
|
387
|
+
};
|
|
395
388
|
};
|
|
396
389
|
const COMPLEX_SCRIPT_MIRRORS = [
|
|
397
390
|
{
|
|
@@ -407,25 +400,19 @@ const COMPLEX_SCRIPT_MIRRORS = [
|
|
|
407
400
|
complex: "fontSizeCs"
|
|
408
401
|
}
|
|
409
402
|
];
|
|
410
|
-
const
|
|
403
|
+
const withComplexScriptAbsenceProvenance = (attrs, directFormatting) => {
|
|
411
404
|
const absent = COMPLEX_SCRIPT_MIRRORS.filter(({ ordinary, complex }) => directFormatting?.[ordinary] !== void 0 && directFormatting[complex] === void 0).map(({ complex }) => complex);
|
|
412
|
-
if (absent.length === 0) return;
|
|
413
|
-
const
|
|
414
|
-
const existing = index >= 0 ? marks.at(index) : void 0;
|
|
415
|
-
const existingAbsences = new Set(existing?.attrs["complexScriptPropertyAbsences"] ?? []);
|
|
405
|
+
if (absent.length === 0) return attrs;
|
|
406
|
+
const existingAbsences = new Set(attrs?.complexScriptPropertyAbsences ?? []);
|
|
416
407
|
for (const property of absent) existingAbsences.add(property);
|
|
417
|
-
|
|
418
|
-
...
|
|
408
|
+
return {
|
|
409
|
+
...attrs,
|
|
419
410
|
complexScriptPropertyAbsences: COMPLEX_SCRIPT_RUN_PROPERTY_KEYS.filter((property) => existingAbsences.has(property))
|
|
420
|
-
}
|
|
421
|
-
if (index >= 0) {
|
|
422
|
-
marks[index] = override;
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
marks.push(override);
|
|
411
|
+
};
|
|
426
412
|
};
|
|
427
413
|
function textFormattingToMarks(formatting, schema, options) {
|
|
428
414
|
if (!formatting) return [];
|
|
415
|
+
const createMark = options?.createMark ?? ((type, attrs) => schema.mark(type, attrs));
|
|
429
416
|
const marks = [];
|
|
430
417
|
const overrideFormatting = options ? options.overrideFormatting : formatting;
|
|
431
418
|
let overrideAttrs;
|
|
@@ -435,25 +422,24 @@ function textFormattingToMarks(formatting, schema, options) {
|
|
|
435
422
|
formatting: options.directFormatting
|
|
436
423
|
});
|
|
437
424
|
else overrideAttrs = buildRunFormattingOverrideAttrs(overrideFormatting);
|
|
438
|
-
if (
|
|
439
|
-
if (formatting.
|
|
440
|
-
if (formatting.
|
|
441
|
-
if (formatting.underline && formatting.underline.style !== "none") marks.push(schema.mark("underline", {
|
|
425
|
+
if (formatting.bold) marks.push(createMark("bold"));
|
|
426
|
+
if (formatting.italic) marks.push(createMark("italic"));
|
|
427
|
+
if (formatting.underline && formatting.underline.style !== "none") marks.push(createMark("underline", {
|
|
442
428
|
style: formatting.underline.style,
|
|
443
429
|
color: formatting.underline.color
|
|
444
430
|
}));
|
|
445
|
-
if (formatting.strike || formatting.doubleStrike) marks.push(
|
|
446
|
-
if (formatting.color && !formatting.color.auto) marks.push(
|
|
431
|
+
if (formatting.strike || formatting.doubleStrike) marks.push(createMark("strike", { double: formatting.doubleStrike || false }));
|
|
432
|
+
if (formatting.color && !formatting.color.auto) marks.push(createMark("textColor", {
|
|
447
433
|
rgb: formatting.color.rgb,
|
|
448
434
|
themeColor: formatting.color.themeColor,
|
|
449
435
|
themeTint: formatting.color.themeTint,
|
|
450
436
|
themeShade: formatting.color.themeShade
|
|
451
437
|
}));
|
|
452
|
-
if (formatting.highlight && formatting.highlight !== "none") marks.push(
|
|
438
|
+
if (formatting.highlight && formatting.highlight !== "none") marks.push(createMark("highlight", { color: formatting.highlight }));
|
|
453
439
|
const runShadingMarkAttrs = shadingToRunShadingAttrs(formatting.shading);
|
|
454
|
-
if (runShadingMarkAttrs) marks.push(
|
|
455
|
-
if (formatting.fontSize) marks.push(
|
|
456
|
-
if (formatting.fontFamily) marks.push(
|
|
440
|
+
if (runShadingMarkAttrs) marks.push(createMark("runShading", runShadingMarkAttrs));
|
|
441
|
+
if (formatting.fontSize) marks.push(createMark("fontSize", { size: formatting.fontSize }));
|
|
442
|
+
if (formatting.fontFamily) marks.push(createMark("fontFamily", {
|
|
457
443
|
ascii: formatting.fontFamily.ascii,
|
|
458
444
|
hAnsi: formatting.fontFamily.hAnsi,
|
|
459
445
|
eastAsia: formatting.fontFamily.eastAsia,
|
|
@@ -464,31 +450,33 @@ function textFormattingToMarks(formatting, schema, options) {
|
|
|
464
450
|
eastAsiaTheme: formatting.fontFamily.eastAsiaTheme,
|
|
465
451
|
csTheme: formatting.fontFamily.csTheme
|
|
466
452
|
}));
|
|
467
|
-
if (formatting.language) marks.push(
|
|
468
|
-
if (formatting.vertAlign === "superscript") marks.push(
|
|
469
|
-
else if (formatting.vertAlign === "subscript") marks.push(
|
|
470
|
-
if (formatting.allCaps) marks.push(
|
|
471
|
-
if (formatting.smallCaps) marks.push(
|
|
453
|
+
if (formatting.language) marks.push(createMark("language", formatting.language));
|
|
454
|
+
if (formatting.vertAlign === "superscript") marks.push(createMark("superscript"));
|
|
455
|
+
else if (formatting.vertAlign === "subscript") marks.push(createMark("subscript"));
|
|
456
|
+
if (formatting.allCaps) marks.push(createMark("allCaps"));
|
|
457
|
+
if (formatting.smallCaps) marks.push(createMark("smallCaps"));
|
|
472
458
|
const spacing = typeof formatting.spacing === "number" ? formatting.spacing : null;
|
|
473
459
|
const position = typeof formatting.position === "number" ? formatting.position : null;
|
|
474
460
|
const scale = normalizeHorizontalScalePercent(formatting.scale) ?? null;
|
|
475
461
|
const kerning = typeof formatting.kerning === "number" ? formatting.kerning : null;
|
|
476
|
-
if (spacing !== null || position !== null || scale !== null || kerning !== null) marks.push(
|
|
462
|
+
if (spacing !== null || position !== null || scale !== null || kerning !== null) marks.push(createMark("characterSpacing", {
|
|
477
463
|
spacing,
|
|
478
464
|
position,
|
|
479
465
|
scale,
|
|
480
466
|
kerning
|
|
481
467
|
}));
|
|
482
|
-
if (formatting.hidden === true) marks.push(
|
|
483
|
-
if (formatting.emboss) marks.push(
|
|
484
|
-
if (formatting.imprint) marks.push(
|
|
485
|
-
if (formatting.shadow) marks.push(
|
|
486
|
-
if (formatting.emphasisMark && formatting.emphasisMark !== "none") marks.push(
|
|
487
|
-
if (formatting.outline) marks.push(
|
|
488
|
-
if (formatting.rtl) marks.push(
|
|
489
|
-
if (formatting.effect && formatting.effect !== "none") marks.push(
|
|
490
|
-
|
|
491
|
-
if (options?.authoredCarrier === "preserve")
|
|
468
|
+
if (formatting.hidden === true) marks.push(createMark("hidden"));
|
|
469
|
+
if (formatting.emboss) marks.push(createMark("emboss"));
|
|
470
|
+
if (formatting.imprint) marks.push(createMark("imprint"));
|
|
471
|
+
if (formatting.shadow) marks.push(createMark("textShadow"));
|
|
472
|
+
if (formatting.emphasisMark && formatting.emphasisMark !== "none") marks.push(createMark("emphasisMark", { type: formatting.emphasisMark }));
|
|
473
|
+
if (formatting.outline) marks.push(createMark("textOutline"));
|
|
474
|
+
if (formatting.rtl) marks.push(createMark("rtl"));
|
|
475
|
+
if (formatting.effect && formatting.effect !== "none") marks.push(createMark("textEffect", { effect: formatting.effect }));
|
|
476
|
+
let provenanceAttrs = withDirectFontProvenance(overrideAttrs, options?.directFormatting);
|
|
477
|
+
if (options?.authoredCarrier === "preserve") provenanceAttrs = withComplexScriptAbsenceProvenance(provenanceAttrs, options.directFormatting);
|
|
478
|
+
if (overrideAttrs) marks.unshift(createMark("runFormattingOverride", provenanceAttrs));
|
|
479
|
+
else if (provenanceAttrs) marks.push(createMark("runFormattingOverride", provenanceAttrs));
|
|
492
480
|
return marks;
|
|
493
481
|
}
|
|
494
482
|
/**
|
|
@@ -9,7 +9,8 @@ const createFieldAttrs = () => ({
|
|
|
9
9
|
_numberedRefBaseline: { default: void 0 },
|
|
10
10
|
fieldKind: { default: "simple" },
|
|
11
11
|
fldLock: { default: null },
|
|
12
|
-
dirty: { default: null }
|
|
12
|
+
dirty: { default: null },
|
|
13
|
+
fieldResultIsFallback: { default: null }
|
|
13
14
|
});
|
|
14
15
|
/** A `data-` flag a pasted field carried: absent states nothing. */
|
|
15
16
|
const statedFlag = (value) => value === void 0 ? null : value === "true";
|
|
@@ -19,10 +20,11 @@ const readFieldDomAttrs = (dom) => ({
|
|
|
19
20
|
displayText: dom.textContent ?? "",
|
|
20
21
|
fieldKind: dom.dataset["fieldKind"] ?? "simple",
|
|
21
22
|
fldLock: statedFlag(dom.dataset["fldLock"]),
|
|
22
|
-
dirty: statedFlag(dom.dataset["dirty"])
|
|
23
|
+
dirty: statedFlag(dom.dataset["dirty"]),
|
|
24
|
+
fieldResultIsFallback: statedFlag(dom.dataset["fieldResultIsFallback"])
|
|
23
25
|
});
|
|
24
26
|
const getFieldDomAttrs = (node) => {
|
|
25
|
-
const { fieldType, instruction, fieldKind, fldLock, dirty } = expectFieldAttrs(node);
|
|
27
|
+
const { fieldType, instruction, fieldKind, fldLock, dirty, fieldResultIsFallback } = expectFieldAttrs(node);
|
|
26
28
|
return {
|
|
27
29
|
class: `docx-field docx-field-${fieldType.toLowerCase()}`,
|
|
28
30
|
"data-field-type": fieldType,
|
|
@@ -30,6 +32,7 @@ const getFieldDomAttrs = (node) => {
|
|
|
30
32
|
"data-field-kind": fieldKind,
|
|
31
33
|
...fldLock === void 0 ? {} : { "data-fld-lock": String(fldLock) },
|
|
32
34
|
...dirty === void 0 ? {} : { "data-dirty": String(dirty) },
|
|
35
|
+
...fieldResultIsFallback === void 0 ? {} : { "data-field-result-is-fallback": String(fieldResultIsFallback) },
|
|
33
36
|
style: "outline: 1px solid var(--doc-field-outline, rgba(200,200,200,0.4)); padding: 0 1px; border-radius: 2px;"
|
|
34
37
|
};
|
|
35
38
|
};
|
|
@@ -54,7 +54,13 @@ const SdtExtension = createNodeExtension({
|
|
|
54
54
|
* `w:sdtEndPr` as a record, so a control the editor rebuilds still
|
|
55
55
|
* writes its end mark once the captured bytes are gone.
|
|
56
56
|
*/
|
|
57
|
-
endProperties: { default: null }
|
|
57
|
+
endProperties: { default: null },
|
|
58
|
+
/**
|
|
59
|
+
* The revisions whose element encloses the control (`w:ins > w:sdt`),
|
|
60
|
+
* as opposed to revising the content inside it (`w:sdt > w:ins`). Both
|
|
61
|
+
* put the same marks on the leaves; see `contentControlRevisions.ts`.
|
|
62
|
+
*/
|
|
63
|
+
_docxEnclosingRevisionIds: { default: null }
|
|
58
64
|
},
|
|
59
65
|
parseDOM: [{
|
|
60
66
|
tag: "span.docx-sdt",
|
|
@@ -78,7 +84,8 @@ const SdtExtension = createNodeExtension({
|
|
|
78
84
|
checked: onOffFromDataset(el.dataset["checked"]),
|
|
79
85
|
_preserved: null,
|
|
80
86
|
rawEndPropertiesXml: null,
|
|
81
|
-
endProperties: null
|
|
87
|
+
endProperties: null,
|
|
88
|
+
_docxEnclosingRevisionIds: null
|
|
82
89
|
};
|
|
83
90
|
}
|
|
84
91
|
}],
|
|
@@ -370,6 +370,7 @@ const ShapeExtension = createNodeExtension({
|
|
|
370
370
|
shapeType: { default: "rect" },
|
|
371
371
|
geometryAdjustments: { default: null },
|
|
372
372
|
_docxRunFormatting: { default: null },
|
|
373
|
+
_docxAlternateContent: { default: null },
|
|
373
374
|
shapeId: { default: null },
|
|
374
375
|
shapeName: { default: null },
|
|
375
376
|
alt: { default: null },
|
|
@@ -86,6 +86,7 @@ const TextBoxExtension = createNodeExtension({
|
|
|
86
86
|
alt: { default: null },
|
|
87
87
|
title: { default: null },
|
|
88
88
|
fillColor: { default: null },
|
|
89
|
+
gradientFill: { default: null },
|
|
89
90
|
outlineWidth: { default: null },
|
|
90
91
|
outlineColor: { default: null },
|
|
91
92
|
outlineStyle: { default: null },
|
|
@@ -111,13 +112,16 @@ const TextBoxExtension = createNodeExtension({
|
|
|
111
112
|
wrapDistanceSlots: { default: null },
|
|
112
113
|
wrapEffectExtentSlots: { default: null },
|
|
113
114
|
wrapPolygon: { default: null },
|
|
115
|
+
_docxAlternateContent: { default: null },
|
|
114
116
|
_docxPlacement: { default: null },
|
|
115
117
|
_docxGroupId: { default: null },
|
|
116
118
|
_docxAnchorId: { default: null },
|
|
119
|
+
_docxGroupChild: { default: null },
|
|
117
120
|
_docxTextBodyContentState: { default: { type: "authored" } },
|
|
118
121
|
_docxTrackedChange: { default: null },
|
|
119
122
|
_docxInlineSdts: { default: null },
|
|
120
|
-
_preservedAttributes: { default: null }
|
|
123
|
+
_preservedAttributes: { default: null },
|
|
124
|
+
_docxHostParagraph: { default: null }
|
|
121
125
|
},
|
|
122
126
|
parseDOM: [{
|
|
123
127
|
tag: "div.docx-textbox",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { convertBulletToUnicode } from "../docx/bulletMarkers.js";
|
|
1
|
+
import { bulletMarkerFontName, convertBulletToUnicode } from "../docx/bulletMarkers.js";
|
|
2
2
|
import { paragraphNumberingLevel, paragraphNumberingReferenceId, sameStatedParagraphNumbering } from "../docx/numberingReference.js";
|
|
3
3
|
import { formatOoxmlCounter } from "../docx/ooxmlCounterFormatter.js";
|
|
4
4
|
import { isListNumPr } from "../layout-engine/types.js";
|
|
@@ -20,6 +20,7 @@ const CLEARED_LIST_RENDERING_ATTRS = Object.freeze({
|
|
|
20
20
|
listMarkerSecondSlotOffsetTwips: null,
|
|
21
21
|
listLevelNumFmts: null,
|
|
22
22
|
listLevelStarts: null,
|
|
23
|
+
listLevelTabs: null,
|
|
23
24
|
listAbstractNumId: null,
|
|
24
25
|
listStartOverride: null
|
|
25
26
|
});
|
|
@@ -84,6 +85,7 @@ function previousListAttrs(attrs) {
|
|
|
84
85
|
...previous.listMarkerSecondSlotOffsetTwips !== void 0 ? { listMarkerSecondSlotOffsetTwips: previous.listMarkerSecondSlotOffsetTwips } : {},
|
|
85
86
|
...previous.listLevelNumFmts !== void 0 ? { listLevelNumFmts: previous.listLevelNumFmts } : {},
|
|
86
87
|
...previous.listLevelStarts !== void 0 ? { listLevelStarts: previous.listLevelStarts } : {},
|
|
88
|
+
...previous.listLevelTabs !== void 0 ? { listLevelTabs: previous.listLevelTabs } : {},
|
|
87
89
|
...previous.listAbstractNumId !== void 0 ? { listAbstractNumId: previous.listAbstractNumId } : {},
|
|
88
90
|
...previous.listStartOverride !== void 0 ? { listStartOverride: previous.listStartOverride } : {}
|
|
89
91
|
};
|
|
@@ -203,7 +205,7 @@ function advanceListMarker(attrs, state) {
|
|
|
203
205
|
fromStyle: false,
|
|
204
206
|
numId: null
|
|
205
207
|
};
|
|
206
|
-
return convertBulletToUnicode(attrs.listMarker ?? markerTemplate ?? "");
|
|
208
|
+
return convertBulletToUnicode(attrs.listMarker ?? markerTemplate ?? "", bulletMarkerFontName(attrs.listMarkerFormatting));
|
|
207
209
|
}
|
|
208
210
|
const firstInstanceEncounter = !state.counters.has(numId);
|
|
209
211
|
let counters = state.counters.get(numId) ?? Array.from({ length: 9 }, () => NaN);
|
|
@@ -14,6 +14,7 @@ declare const LIST_RENDERING_ATTR_BY_FIELD: {
|
|
|
14
14
|
readonly markerAlignment: "listMarkerAlignment";
|
|
15
15
|
readonly markerAllCaps: "listMarkerAllCaps";
|
|
16
16
|
readonly markerSuffix: "listMarkerSuffix";
|
|
17
|
+
readonly levelTabs: "listLevelTabs";
|
|
17
18
|
readonly levelNumFmts: "listLevelNumFmts";
|
|
18
19
|
readonly levelStarts: "listLevelStarts";
|
|
19
20
|
readonly abstractNumId: "listAbstractNumId";
|
|
@@ -20,6 +20,7 @@ const LIST_RENDERING_ATTR_BY_FIELD = {
|
|
|
20
20
|
markerAlignment: "listMarkerAlignment",
|
|
21
21
|
markerAllCaps: "listMarkerAllCaps",
|
|
22
22
|
markerSuffix: "listMarkerSuffix",
|
|
23
|
+
levelTabs: "listLevelTabs",
|
|
23
24
|
levelNumFmts: "listLevelNumFmts",
|
|
24
25
|
levelStarts: "listLevelStarts",
|
|
25
26
|
abstractNumId: "listAbstractNumId",
|
|
@@ -48,6 +49,7 @@ const listRenderingAttrPatch = (rendering) => {
|
|
|
48
49
|
listMarkerAlignment: rendering.markerAlignment || void 0,
|
|
49
50
|
listMarkerAllCaps: rendering.markerAllCaps || void 0,
|
|
50
51
|
listMarkerSuffix: rendering.markerSuffix || void 0,
|
|
52
|
+
listLevelTabs: rendering.levelTabs?.length ? rendering.levelTabs : void 0,
|
|
51
53
|
listLevelNumFmts: rendering.levelNumFmts || void 0,
|
|
52
54
|
listLevelStarts: rendering.levelStarts || void 0,
|
|
53
55
|
listAbstractNumId: rendering.abstractNumId,
|
|
@@ -71,6 +73,7 @@ const listRenderingFromAttrs = ({ attrs, numId }) => {
|
|
|
71
73
|
markerAlignment: attrs.listMarkerAlignment ?? void 0,
|
|
72
74
|
markerAllCaps: attrs.listMarkerAllCaps ?? void 0,
|
|
73
75
|
markerSuffix: attrs.listMarkerSuffix ?? void 0,
|
|
76
|
+
levelTabs: attrs.listLevelTabs ?? void 0,
|
|
74
77
|
levelNumFmts: attrs.listLevelNumFmts ?? void 0,
|
|
75
78
|
levelStarts: attrs.listLevelStarts ?? void 0,
|
|
76
79
|
abstractNumId: attrs.listAbstractNumId ?? void 0,
|
|
@@ -15,6 +15,17 @@
|
|
|
15
15
|
* The persisted/serialized model keeps the flat OOXML tri-state
|
|
16
16
|
* (`ParagraphFormatting.bidi: boolean | undefined`); `directionToBidi` /
|
|
17
17
|
* `directionFromBidi` bridge the two at the conversion boundary.
|
|
18
|
+
*
|
|
19
|
+
* `source: "auto"` is a *rendering* decision only — it makes the layout
|
|
20
|
+
* painter and the editor's DOM shape the paragraph RTL, so newly typed or
|
|
21
|
+
* pasted directional text displays correctly before the user ever makes an
|
|
22
|
+
* explicit choice. It must never reach the saved package on its own: a
|
|
23
|
+
* paragraph that arrived without `w:bidi` and was never touched by the user
|
|
24
|
+
* must save without `w:bidi` too, no matter how many auto-detection passes
|
|
25
|
+
* ran over it on load. Only `source: "manual"` (an explicit user toggle, or
|
|
26
|
+
* a `w:bidi` the source document already carried) is authored content and
|
|
27
|
+
* belongs in `w:pPr`. Use `directionToBidi` for layout/rendering and
|
|
28
|
+
* `directionToAuthoredBidi` for anything that gets serialized.
|
|
18
29
|
*/
|
|
19
30
|
type ParagraphDirection = {
|
|
20
31
|
source: "auto";
|
|
@@ -29,8 +40,24 @@ declare const directionIsRtl: (direction: ParagraphDirection | null | undefined)
|
|
|
29
40
|
* AutoBidiDetection may (re-)evaluate. A manual decision is left untouched.
|
|
30
41
|
*/
|
|
31
42
|
declare const directionIsAutoManaged: (direction: ParagraphDirection | null | undefined) => boolean;
|
|
32
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Map a direction to the OOXML `w:bidi` tri-state for layout/rendering: an
|
|
45
|
+
* auto-detected direction lays out RTL exactly like a manual one. Do not use
|
|
46
|
+
* this to decide what gets written to the saved package — see
|
|
47
|
+
* `directionToAuthoredBidi`.
|
|
48
|
+
*/
|
|
33
49
|
declare const directionToBidi: (direction: ParagraphDirection | null | undefined) => boolean | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Map a direction to the OOXML `w:bidi` tri-state as *authored* content, for
|
|
52
|
+
* serialization. Only a manual decision (explicit user toggle, or a `w:bidi`
|
|
53
|
+
* the source document already carried) is ever written: `undefined` here
|
|
54
|
+
* means "the paragraph does not state its own direction," which keeps
|
|
55
|
+
* `w:pPr` free of a flag the user never asked for. An auto-detected
|
|
56
|
+
* direction (`source: "auto"`) resolves to `undefined` — same as undecided —
|
|
57
|
+
* regardless of which way detection currently leans, so it stays a view-only
|
|
58
|
+
* aid until the user makes it explicit.
|
|
59
|
+
*/
|
|
60
|
+
declare const directionToAuthoredBidi: (direction: ParagraphDirection | null | undefined) => boolean | undefined;
|
|
34
61
|
/**
|
|
35
62
|
* Reconstruct a direction from a model `bidi` value (DOCX import / load): an
|
|
36
63
|
* explicit `true`/`false` is a manual decision, absence is undecided.
|
|
@@ -39,4 +66,4 @@ declare const directionFromBidi: (bidi: boolean | null | undefined) => Paragraph
|
|
|
39
66
|
/** Runtime guard for the PM attribute validator. */
|
|
40
67
|
declare const isParagraphDirection: (value: unknown) => value is ParagraphDirection;
|
|
41
68
|
//#endregion
|
|
42
|
-
export { ParagraphDirection, directionFromBidi, directionIsAutoManaged, directionIsRtl, directionToBidi, isParagraphDirection };
|
|
69
|
+
export { ParagraphDirection, directionFromBidi, directionIsAutoManaged, directionIsRtl, directionToAuthoredBidi, directionToBidi, isParagraphDirection };
|
|
@@ -6,13 +6,32 @@ const directionIsRtl = (direction) => direction?.source === "auto" || direction?
|
|
|
6
6
|
* AutoBidiDetection may (re-)evaluate. A manual decision is left untouched.
|
|
7
7
|
*/
|
|
8
8
|
const directionIsAutoManaged = (direction) => direction == null || direction.source === "auto";
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Map a direction to the OOXML `w:bidi` tri-state for layout/rendering: an
|
|
11
|
+
* auto-detected direction lays out RTL exactly like a manual one. Do not use
|
|
12
|
+
* this to decide what gets written to the saved package — see
|
|
13
|
+
* `directionToAuthoredBidi`.
|
|
14
|
+
*/
|
|
10
15
|
const directionToBidi = (direction) => {
|
|
11
16
|
if (direction == null) return;
|
|
12
17
|
if (direction.source === "auto") return true;
|
|
13
18
|
return direction.value === "rtl";
|
|
14
19
|
};
|
|
15
20
|
/**
|
|
21
|
+
* Map a direction to the OOXML `w:bidi` tri-state as *authored* content, for
|
|
22
|
+
* serialization. Only a manual decision (explicit user toggle, or a `w:bidi`
|
|
23
|
+
* the source document already carried) is ever written: `undefined` here
|
|
24
|
+
* means "the paragraph does not state its own direction," which keeps
|
|
25
|
+
* `w:pPr` free of a flag the user never asked for. An auto-detected
|
|
26
|
+
* direction (`source: "auto"`) resolves to `undefined` — same as undecided —
|
|
27
|
+
* regardless of which way detection currently leans, so it stays a view-only
|
|
28
|
+
* aid until the user makes it explicit.
|
|
29
|
+
*/
|
|
30
|
+
const directionToAuthoredBidi = (direction) => {
|
|
31
|
+
if (direction == null || direction.source === "auto") return;
|
|
32
|
+
return direction.value === "rtl";
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
16
35
|
* Reconstruct a direction from a model `bidi` value (DOCX import / load): an
|
|
17
36
|
* explicit `true`/`false` is a manual decision, absence is undecided.
|
|
18
37
|
*/
|
|
@@ -30,4 +49,4 @@ const isParagraphDirection = (value) => {
|
|
|
30
49
|
return value.source === "manual" && "value" in value && (value.value === "rtl" || value.value === "ltr");
|
|
31
50
|
};
|
|
32
51
|
//#endregion
|
|
33
|
-
export { directionFromBidi, directionIsAutoManaged, directionIsRtl, directionToBidi, isParagraphDirection };
|
|
52
|
+
export { directionFromBidi, directionIsAutoManaged, directionIsRtl, directionToAuthoredBidi, directionToBidi, isParagraphDirection };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { encloseWholeControls } from "../contentControlRevisions.js";
|
|
1
2
|
import { splitBlockClearBorders } from "../extensions/features/BaseKeymapExtension.js";
|
|
2
3
|
import { handleEditorBeforeInput } from "../textInput.js";
|
|
3
4
|
import { canCarryTrackedRunMark } from "../trackedRunInlineAtoms.js";
|
|
4
5
|
import { mintRevisionId, seedRevisionIdsFromDoc } from "./revisionIds.js";
|
|
6
|
+
import { Mapping } from "prosemirror-transform";
|
|
5
7
|
import { Plugin, PluginKey, TextSelection } from "prosemirror-state";
|
|
6
8
|
import { isHistoryTransaction } from "prosemirror-history";
|
|
7
9
|
//#region src/prosemirror/plugins/suggestionMode.ts
|
|
@@ -87,6 +89,12 @@ function markRangeAsDeleted(tr, doc, from, to, insertionType, deletionType, plug
|
|
|
87
89
|
});
|
|
88
90
|
if (ranges.length === 0) return;
|
|
89
91
|
const delAttrs = findAdjacentRevisionForRange(doc, from, to, "deletion", pluginState.author) || makeMarkAttrs(pluginState);
|
|
92
|
+
encloseWholeControls({
|
|
93
|
+
tr,
|
|
94
|
+
from: tr.mapping.map(from),
|
|
95
|
+
to: tr.mapping.map(to, -1),
|
|
96
|
+
revisionId: delAttrs.revisionId
|
|
97
|
+
});
|
|
90
98
|
for (let i = ranges.length - 1; i >= 0; i--) {
|
|
91
99
|
const range = ranges[i];
|
|
92
100
|
if (range.isOwnInsert) tr.delete(range.from, range.to);
|
|
@@ -107,6 +115,12 @@ function markRangeAsInserted(tr, doc, from, to, insertionType, deletionType, att
|
|
|
107
115
|
if (start >= end) return;
|
|
108
116
|
tr.addMark(start, end, insertionType.create(attrs));
|
|
109
117
|
});
|
|
118
|
+
encloseWholeControls({
|
|
119
|
+
tr,
|
|
120
|
+
from,
|
|
121
|
+
to,
|
|
122
|
+
revisionId: attrs.revisionId
|
|
123
|
+
});
|
|
110
124
|
}
|
|
111
125
|
/**
|
|
112
126
|
* With track changes on, pasting over a non-empty text selection marks the
|
|
@@ -439,16 +453,31 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
|
|
|
439
453
|
const tr = newState.tr;
|
|
440
454
|
tr.setMeta(SUGGESTION_META, true);
|
|
441
455
|
const deletionType = newState.schema.marks["deletion"];
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
456
|
+
const laterMaps = transactions.slice(transactions.indexOf(userTr) + 1).flatMap((transaction) => transaction.mapping.maps);
|
|
457
|
+
for (const [stepIndex, step] of userTr.steps.entries()) {
|
|
458
|
+
const stepMap = step.getMap();
|
|
459
|
+
const following = new Mapping([...userTr.mapping.maps.slice(stepIndex + 1), ...laterMaps]);
|
|
460
|
+
stepMap.forEach((_oldFrom, _oldTo, stepFrom, stepTo) => {
|
|
461
|
+
const newFrom = following.map(stepFrom, -1);
|
|
462
|
+
const newTo = following.map(stepTo, 1);
|
|
463
|
+
if (newTo > newFrom) {
|
|
464
|
+
newState.doc.nodesBetween(newFrom, newTo, (node, pos) => {
|
|
465
|
+
if (!canCarryTrackedRunMark(node)) return;
|
|
466
|
+
if (!node.marks.some((m) => m.type === insertionType || deletionType && m.type === deletionType)) {
|
|
467
|
+
const nodeStart = Math.max(pos, newFrom);
|
|
468
|
+
const nodeEnd = Math.min(pos + node.nodeSize, newTo);
|
|
469
|
+
tr.addMark(nodeStart, nodeEnd, insertionType.create(markAttrs));
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
encloseWholeControls({
|
|
473
|
+
tr,
|
|
474
|
+
from: newFrom,
|
|
475
|
+
to: newTo,
|
|
476
|
+
revisionId: markAttrs.revisionId
|
|
477
|
+
});
|
|
449
478
|
}
|
|
450
479
|
});
|
|
451
|
-
}
|
|
480
|
+
}
|
|
452
481
|
return tr.steps.length > 0 ? tr : null;
|
|
453
482
|
}
|
|
454
483
|
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ParagraphRunStyleContext, RunStyleResolver } from "./runStyleFormatting.js";
|
|
2
|
+
import { Transaction } from "prosemirror-state";
|
|
3
|
+
import { Mark, Node } from "prosemirror-model";
|
|
4
|
+
//#region src/prosemirror/rejoinRunCarriers.d.ts
|
|
5
|
+
type ContinuedRunMarksOptions = {
|
|
6
|
+
left: Node;
|
|
7
|
+
right: Node;
|
|
8
|
+
/** The paragraph's run style context, read only when the marks differ in formatting alone. */
|
|
9
|
+
context: () => ParagraphRunStyleContext;
|
|
10
|
+
styleResolver: RunStyleResolver | null;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The marks `right` takes to continue `left`'s run, or `null` when the two
|
|
14
|
+
* already share their marks or write different runs: another mark differs,
|
|
15
|
+
* or the formatting they state does.
|
|
16
|
+
*/
|
|
17
|
+
declare const continuedRunMarks: ({ left, right, context, styleResolver }: ContinuedRunMarksOptions) => readonly Mark[] | null;
|
|
18
|
+
type RejoinRunsAtOptions = {
|
|
19
|
+
tr: Transaction;
|
|
20
|
+
/** Positions in `tr.doc` where resolved content began or ended. */
|
|
21
|
+
boundaries: Iterable<number>;
|
|
22
|
+
styleResolver: RunStyleResolver | null;
|
|
23
|
+
};
|
|
24
|
+
/** Rejoin the runs meeting at each of `boundaries`, left to right. */
|
|
25
|
+
declare const rejoinRunsAt: ({ tr, boundaries, styleResolver }: RejoinRunsAtOptions) => void;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { continuedRunMarks, rejoinRunsAt };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { formattingEquals } from "../docx/runConsolidator.js";
|
|
2
|
+
import { RUN_FORMATTING_MARK_NAMES } from "./runFormattingMarkNames.js";
|
|
3
|
+
import { readAuthoredRunFormatting } from "./runFormattingReconciliation.js";
|
|
4
|
+
import { paragraphRunStyleContextAt } from "./runStyleFormatting.js";
|
|
5
|
+
import { Mark } from "prosemirror-model";
|
|
6
|
+
//#region src/prosemirror/rejoinRunCarriers.ts
|
|
7
|
+
/**
|
|
8
|
+
* Rejoin a run that resolving a revision left split.
|
|
9
|
+
*
|
|
10
|
+
* A revision splits the run it cuts into (`w:r`, `w:del > w:r`, `w:r`), and a
|
|
11
|
+
* run-property change rewrites the formatting marks of the piece it covers.
|
|
12
|
+
* Once the revision is resolved the pieces write the same `w:rPr`, but the
|
|
13
|
+
* editor can hold that formatting on different mark carriers (a restored
|
|
14
|
+
* `w:rPrChange` is rebuilt from its `w:rPr`), and leaves with different marks
|
|
15
|
+
* are written as different runs. At a resolved boundary, a leaf that writes
|
|
16
|
+
* the same run as the leaf before it takes that leaf's marks, so the two are
|
|
17
|
+
* one run again.
|
|
18
|
+
*
|
|
19
|
+
* Leaves the source wrote as separate runs keep them apart: a run identity
|
|
20
|
+
* (`runIdentity`) differs between them, and it is compared, not rewritten.
|
|
21
|
+
* The pieces of one run read back from a saved redline share an identity
|
|
22
|
+
* (`runIdentityAcrossRevisions.ts`).
|
|
23
|
+
*/
|
|
24
|
+
const isFormattingMark = (mark) => RUN_FORMATTING_MARK_NAMES.has(mark.type.name);
|
|
25
|
+
/**
|
|
26
|
+
* The marks `right` takes to continue `left`'s run, or `null` when the two
|
|
27
|
+
* already share their marks or write different runs: another mark differs,
|
|
28
|
+
* or the formatting they state does.
|
|
29
|
+
*/
|
|
30
|
+
const continuedRunMarks = ({ left, right, context, styleResolver }) => {
|
|
31
|
+
if (!left.isText || !right.isText || Mark.sameSet(left.marks, right.marks)) return null;
|
|
32
|
+
const otherMarks = (node) => node.marks.filter((mark) => !isFormattingMark(mark));
|
|
33
|
+
if (!Mark.sameSet(otherMarks(left), otherMarks(right))) return null;
|
|
34
|
+
const paragraphContext = context();
|
|
35
|
+
const stated = (node) => readAuthoredRunFormatting({
|
|
36
|
+
context: paragraphContext,
|
|
37
|
+
marks: node.marks,
|
|
38
|
+
styleResolver
|
|
39
|
+
});
|
|
40
|
+
return formattingEquals(stated(left), stated(right)) ? left.marks : null;
|
|
41
|
+
};
|
|
42
|
+
/** Rejoin the runs meeting at each of `boundaries`, left to right. */
|
|
43
|
+
const rejoinRunsAt = ({ tr, boundaries, styleResolver }) => {
|
|
44
|
+
for (const boundary of [...new Set(boundaries)].toSorted((left, right) => left - right)) {
|
|
45
|
+
if (boundary <= 0 || boundary >= tr.doc.content.size) continue;
|
|
46
|
+
const at = tr.doc.resolve(boundary);
|
|
47
|
+
const { nodeBefore: left, nodeAfter: right } = at;
|
|
48
|
+
if (!left || !right || !at.parent.inlineContent) continue;
|
|
49
|
+
const marks = continuedRunMarks({
|
|
50
|
+
left,
|
|
51
|
+
right,
|
|
52
|
+
context: () => paragraphRunStyleContextAt({
|
|
53
|
+
doc: tr.doc,
|
|
54
|
+
pos: boundary,
|
|
55
|
+
styleResolver
|
|
56
|
+
}),
|
|
57
|
+
styleResolver
|
|
58
|
+
});
|
|
59
|
+
if (marks === null) continue;
|
|
60
|
+
const to = boundary + right.nodeSize;
|
|
61
|
+
for (const mark of right.marks) if (!mark.isInSet(marks)) tr.removeMark(boundary, to, mark);
|
|
62
|
+
for (const mark of marks) if (!mark.isInSet(right.marks)) tr.addMark(boundary, to, mark);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
//#endregion
|
|
66
|
+
export { continuedRunMarks, rejoinRunsAt };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Node } from "prosemirror-model";
|
|
2
|
+
//#region src/prosemirror/runIdentityAcrossRevisions.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* `nodes`, one inline container's content, with each run a revision cut given
|
|
5
|
+
* the identity of the run it was cut from. A control is a container of its
|
|
6
|
+
* own. `nodes` itself comes back when nothing changes.
|
|
7
|
+
*/
|
|
8
|
+
declare const continueRunIdentitiesAcrossRevisions: (nodes: readonly Node[]) => readonly Node[];
|
|
9
|
+
//#endregion
|
|
10
|
+
export { continueRunIdentitiesAcrossRevisions };
|