superdoc 2.18.0-next.13 → 2.18.0-next.14
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/chunks/{create-super-doc-ui-BwM3I7-G.cjs → create-super-doc-ui-wDvhW9Tz.cjs} +990 -911
- package/dist/chunks/{create-super-doc-ui-Ci7OxbXV.es.js → create-super-doc-ui-wKzxrztu.es.js} +976 -909
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/public/ui-react.cjs +1 -1
- package/dist/public/ui-react.es.js +1 -1
- package/dist/public/ui-vue.cjs +1 -1
- package/dist/public/ui-vue.es.js +1 -1
- package/dist/public/ui.cjs +1 -1
- package/dist/public/ui.es.js +1 -1
- package/dist/style.css +22 -22
- package/dist/style.layered.css +22 -22
- package/dist/superdoc/src/internal/toolbar/built-in/LinkInput.vue.d.ts +4 -4
- package/dist/superdoc/src/public/ui/create-super-doc-ui.d.ts +9 -1
- package/dist/superdoc.cjs +83 -80
- package/dist/superdoc.es.js +83 -80
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +37 -37
- package/package.json +2 -2
|
@@ -510,363 +510,206 @@ var decodeLayoutStoryDataset = (raw) => {
|
|
|
510
510
|
`${DOM_CLASS_NAMES.BLOCK_SDT}${DATA_ATTRS.SDT_ID}`;
|
|
511
511
|
`${DATA_ATTRS.DRAGGABLE}`;
|
|
512
512
|
//#endregion
|
|
513
|
-
//#region
|
|
513
|
+
//#region src/public/ui/equality.ts
|
|
514
514
|
/**
|
|
515
|
-
*
|
|
515
|
+
* Shallow equality used by the controller to suppress redundant slice
|
|
516
|
+
* notifications. v2-native, dependency-free.
|
|
517
|
+
*/
|
|
518
|
+
/**
|
|
519
|
+
* Returns `true` when `a` and `b` are the same reference, or are objects with
|
|
520
|
+
* the same own-enumerable keys and `Object.is`-equal values one level deep.
|
|
521
|
+
* Arrays compare by index. Primitives compare with `Object.is`.
|
|
522
|
+
*/
|
|
523
|
+
function shallowEqual(a, b) {
|
|
524
|
+
if (Object.is(a, b)) return true;
|
|
525
|
+
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
|
|
526
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
527
|
+
const aKeys = Object.keys(a);
|
|
528
|
+
const bKeys = Object.keys(b);
|
|
529
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
530
|
+
for (const key of aKeys) {
|
|
531
|
+
if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
|
|
532
|
+
if (!Object.is(a[key], b[key])) return false;
|
|
533
|
+
}
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/public/ui/format-painter-helpers.js
|
|
538
|
+
/**
|
|
539
|
+
* Maps SDRunProps field names to InlineRunPatch field names.
|
|
540
|
+
* SDRunProps (read-side) and InlineRunPatch (write-side) use different keys
|
|
541
|
+
* for the same properties; direct assignment between them is forbidden.
|
|
516
542
|
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
|
|
520
|
-
|
|
543
|
+
* @param {Record<string, unknown>} props - SDRunProps object from doc.getNodeById
|
|
544
|
+
* @returns {Record<string, unknown>} InlineRunPatch ready for doc.format.apply
|
|
545
|
+
*/
|
|
546
|
+
function sdRunPropsToInlineRunPatch(props) {
|
|
547
|
+
if (!props || typeof props !== "object") return {};
|
|
548
|
+
const patch = {};
|
|
549
|
+
if (props.fonts) patch.rFonts = {
|
|
550
|
+
ascii: props.fonts.ascii,
|
|
551
|
+
hAnsi: props.fonts.hAnsi,
|
|
552
|
+
eastAsia: props.fonts.eastAsia,
|
|
553
|
+
cs: props.fonts.cs,
|
|
554
|
+
asciiTheme: props.fonts.asciiTheme,
|
|
555
|
+
hAnsiTheme: props.fonts.hAnsiTheme,
|
|
556
|
+
eastAsiaTheme: props.fonts.eastAsiaTheme,
|
|
557
|
+
csTheme: props.fonts.csTheme,
|
|
558
|
+
hint: props.fonts.hint
|
|
559
|
+
};
|
|
560
|
+
if (props.fontFamily != null) patch.fontFamily = props.fontFamily;
|
|
561
|
+
if (props.lang) patch.lang = {
|
|
562
|
+
val: props.lang.val,
|
|
563
|
+
eastAsia: props.lang.eastAsia,
|
|
564
|
+
bidi: props.lang.bidi
|
|
565
|
+
};
|
|
566
|
+
if (props.fontSize != null) patch.fontSize = props.fontSize;
|
|
567
|
+
if (props.fontSizeCs != null) patch.fontSizeCs = props.fontSizeCs;
|
|
568
|
+
const color = projectColorRefToInlineColor(props.color);
|
|
569
|
+
if (color != null) patch.color = color;
|
|
570
|
+
if (props.highlight != null) patch.highlight = props.highlight;
|
|
571
|
+
const shading = projectShadingToInlinePatch(props.shading);
|
|
572
|
+
if (shading) patch.shading = shading;
|
|
573
|
+
if (props.cs != null) patch.cs = props.cs;
|
|
574
|
+
if (props.rtl != null) patch.rtl = props.rtl;
|
|
575
|
+
if (props.bold != null) patch.bold = props.bold;
|
|
576
|
+
if (props.boldCs != null) patch.bCs = props.boldCs;
|
|
577
|
+
if (props.italic != null) patch.italic = props.italic;
|
|
578
|
+
if (props.italicCs != null) patch.iCs = props.italicCs;
|
|
579
|
+
const underline = projectUnderlineToInlinePatch(props.underline);
|
|
580
|
+
if (underline !== void 0) patch.underline = underline;
|
|
581
|
+
if (props.strikethrough != null) patch.strike = props.strikethrough;
|
|
582
|
+
if (props.doubleStrikethrough != null) patch.dstrike = props.doubleStrikethrough;
|
|
583
|
+
if (props.caps != null) patch.caps = props.caps;
|
|
584
|
+
if (props.smallCaps != null) patch.smallCaps = props.smallCaps;
|
|
585
|
+
if (props.outline != null) patch.outline = props.outline;
|
|
586
|
+
if (props.shadow != null) patch.shadow = props.shadow;
|
|
587
|
+
if (props.emboss != null) patch.emboss = props.emboss;
|
|
588
|
+
if (props.imprint != null) patch.imprint = props.imprint;
|
|
589
|
+
if (props.verticalAlign != null) patch.vertAlign = props.verticalAlign;
|
|
590
|
+
if (props.characterSpacing != null) patch.letterSpacing = props.characterSpacing;
|
|
591
|
+
if (props.characterScale != null) patch.charScale = props.characterScale;
|
|
592
|
+
if (props.kern != null) patch.kerning = props.kern;
|
|
593
|
+
if (props.baselineShift != null) patch.position = props.baselineShift;
|
|
594
|
+
if (props.fitTextWidth != null) patch.fitText = { val: props.fitTextWidth };
|
|
595
|
+
if (props.vanish != null) patch.vanish = props.vanish;
|
|
596
|
+
if (props.webHidden != null) patch.webHidden = props.webHidden;
|
|
597
|
+
if (props.specVanish != null) patch.specVanish = props.specVanish;
|
|
598
|
+
const border = projectBorderToInlinePatch(props.border);
|
|
599
|
+
if (border) patch.border = border;
|
|
600
|
+
return patch;
|
|
601
|
+
}
|
|
602
|
+
function projectColorRefToInlineColor(color) {
|
|
603
|
+
if (!color) return void 0;
|
|
604
|
+
if (typeof color === "string") return color;
|
|
605
|
+
if (color.model === "rgb") return color.value;
|
|
606
|
+
if (color.model === "auto") return "auto";
|
|
607
|
+
}
|
|
608
|
+
function projectUnderlineToInlinePatch(underline) {
|
|
609
|
+
if (underline == null) return void 0;
|
|
610
|
+
const patch = {};
|
|
611
|
+
if (underline.style != null) patch.style = underline.style;
|
|
612
|
+
if (underline.color?.model === "rgb") patch.color = underline.color.value;
|
|
613
|
+
if (underline.color?.model === "theme") patch.themeColor = underline.color.theme;
|
|
614
|
+
return Object.keys(patch).length > 0 ? patch : true;
|
|
615
|
+
}
|
|
616
|
+
function projectShadingToInlinePatch(shading) {
|
|
617
|
+
if (!shading) return void 0;
|
|
618
|
+
const patch = {};
|
|
619
|
+
const fill = projectColorRefToInlineColor(shading.fill);
|
|
620
|
+
if (fill != null) patch.fill = fill;
|
|
621
|
+
const color = projectColorRefToInlineColor(shading.color);
|
|
622
|
+
if (color != null) patch.color = color;
|
|
623
|
+
if (shading.pattern != null) patch.val = shading.pattern;
|
|
624
|
+
return Object.keys(patch).length > 0 ? patch : void 0;
|
|
625
|
+
}
|
|
626
|
+
function projectBorderToInlinePatch(border) {
|
|
627
|
+
if (!border) return void 0;
|
|
628
|
+
const patch = {};
|
|
629
|
+
if (border.style != null) patch.val = border.style;
|
|
630
|
+
if (border.width != null) patch.sz = border.width;
|
|
631
|
+
if (border.space != null) patch.space = border.space;
|
|
632
|
+
const color = projectColorRefToInlineColor(border.color);
|
|
633
|
+
if (color != null) patch.color = color;
|
|
634
|
+
return Object.keys(patch).length > 0 ? patch : void 0;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Serializes a selection to a stable string key used to detect whether
|
|
638
|
+
* the target selection is the same as the source (skip apply in that case).
|
|
521
639
|
*
|
|
522
|
-
*
|
|
523
|
-
*
|
|
640
|
+
* Falls back to the plain text target when the host has not populated an
|
|
641
|
+
* explicit `selectionTarget` yet.
|
|
642
|
+
*
|
|
643
|
+
* @param {{ selectionTarget?: unknown; target?: unknown } | null | undefined} selection
|
|
644
|
+
* @returns {string}
|
|
524
645
|
*/
|
|
525
|
-
function
|
|
526
|
-
const
|
|
527
|
-
if (
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
646
|
+
function selectionKey(selection) {
|
|
647
|
+
const target = selection?.selectionTarget ?? selection?.target;
|
|
648
|
+
if (!selection || !target) return "";
|
|
649
|
+
try {
|
|
650
|
+
return JSON.stringify(target);
|
|
651
|
+
} catch {
|
|
652
|
+
return String(target);
|
|
653
|
+
}
|
|
531
654
|
}
|
|
532
655
|
//#endregion
|
|
533
|
-
//#region
|
|
656
|
+
//#region src/helpers/v2-review-mutation-impact.js
|
|
534
657
|
/**
|
|
535
|
-
*
|
|
658
|
+
* Classify the tracked-change identities carried by a v2 mutation event.
|
|
536
659
|
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
* `
|
|
660
|
+
* Receipt entities are the durable invalidation contract between the document
|
|
661
|
+
* kernel and derived review UI. Direct receipts carry entity refs; mutation
|
|
662
|
+
* plans carry the same identities through `trackedChanges` and per-step ids.
|
|
540
663
|
*/
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
}
|
|
577
|
-
|
|
664
|
+
function getV2TrackedChangeMutationImpact(event) {
|
|
665
|
+
if (event?.type !== "mutation:committed") return null;
|
|
666
|
+
const payload = event.origin === "history" ? event.result : event.receipt;
|
|
667
|
+
if (!payload || typeof payload !== "object") return null;
|
|
668
|
+
const upsertIds = /* @__PURE__ */ new Set();
|
|
669
|
+
const removedIds = /* @__PURE__ */ new Set();
|
|
670
|
+
/** @type {Array<{ from: string, to: string }>} */
|
|
671
|
+
const remappedPairs = [];
|
|
672
|
+
const collectEntity = (entry, into) => {
|
|
673
|
+
if (entry?.kind !== "entity" || entry.entityType !== "trackedChange") return;
|
|
674
|
+
if (typeof entry.entityId === "string" && entry.entityId.length > 0) into.add(entry.entityId);
|
|
675
|
+
};
|
|
676
|
+
const readEntityId = (entry) => {
|
|
677
|
+
if (entry?.kind !== "entity" || entry.entityType !== "trackedChange") return null;
|
|
678
|
+
return typeof entry.entityId === "string" && entry.entityId.length > 0 ? entry.entityId : null;
|
|
679
|
+
};
|
|
680
|
+
if (Array.isArray(payload.inserted)) payload.inserted.forEach((entry) => collectEntity(entry, upsertIds));
|
|
681
|
+
if (Array.isArray(payload.updated)) payload.updated.forEach((entry) => collectEntity(entry, upsertIds));
|
|
682
|
+
if (Array.isArray(payload.trackedChangeRefs)) payload.trackedChangeRefs.forEach((entry) => collectEntity(entry, upsertIds));
|
|
683
|
+
if (Array.isArray(payload.trackedChanges)) payload.trackedChanges.forEach((entry) => collectEntity(entry, upsertIds));
|
|
684
|
+
if (Array.isArray(payload.steps)) for (const step of payload.steps) {
|
|
685
|
+
if (!Array.isArray(step?.trackedChangeIds)) continue;
|
|
686
|
+
for (const id of step.trackedChangeIds) if (typeof id === "string" && id.length > 0) upsertIds.add(id);
|
|
687
|
+
}
|
|
688
|
+
if (Array.isArray(payload.removed)) payload.removed.forEach((entry) => collectEntity(entry, removedIds));
|
|
689
|
+
if (Array.isArray(payload.invalidatedRefs)) payload.invalidatedRefs.forEach((entry) => collectEntity(entry, removedIds));
|
|
690
|
+
if (Array.isArray(payload.remappedRefs)) for (const mapping of payload.remappedRefs) {
|
|
691
|
+
const fromId = readEntityId(mapping?.from);
|
|
692
|
+
const toId = readEntityId(mapping?.to);
|
|
693
|
+
if (fromId) removedIds.add(fromId);
|
|
694
|
+
if (toId) upsertIds.add(toId);
|
|
695
|
+
if (fromId && toId && fromId !== toId) remappedPairs.push({
|
|
696
|
+
from: fromId,
|
|
697
|
+
to: toId
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
for (const id of removedIds) upsertIds.delete(id);
|
|
701
|
+
const allResolved = readAllResolvedFact(event, payload);
|
|
702
|
+
if (upsertIds.size === 0 && removedIds.size === 0 && !allResolved) return null;
|
|
703
|
+
return {
|
|
704
|
+
upsertIds,
|
|
705
|
+
removedIds,
|
|
706
|
+
remappedPairs,
|
|
707
|
+
reconcileMode: "targeted",
|
|
708
|
+
...allResolved ? { allResolved } : {}
|
|
709
|
+
};
|
|
710
|
+
}
|
|
578
711
|
/**
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
* Invariants (enforced by `drawing-taxonomy.test.ts`):
|
|
582
|
-
* - every `supported` family has a real contract target (`!== 'none'`);
|
|
583
|
-
* - every `DrawingBlock`-targeted family declares a `drawingKind`;
|
|
584
|
-
* - every `fail-closed` family declares a canonical `diagnostic`;
|
|
585
|
-
* - every canonical diagnostic code is referenced by at least one fail-closed
|
|
586
|
-
* family;
|
|
587
|
-
* - `deferred` families make no support claim (`contract: 'none'`, no
|
|
588
|
-
* diagnostic).
|
|
589
|
-
*/
|
|
590
|
-
var DRAWING_SUPPORT_TAXONOMY = {
|
|
591
|
-
inlineBitmap: {
|
|
592
|
-
family: "inlineBitmap",
|
|
593
|
-
support: "supported",
|
|
594
|
-
description: "wp:inline pic:pic with internal media and browser-safe MIME (PNG/JPEG; WebP/SVG once the host media resolver lands).",
|
|
595
|
-
contract: "ImageRun"
|
|
596
|
-
},
|
|
597
|
-
anchoredBitmap: {
|
|
598
|
-
family: "anchoredBitmap",
|
|
599
|
-
support: "supported",
|
|
600
|
-
description: "wp:anchor bitmap with anchor/wrap expressible by ImageAnchor/ImageWrap. Never silently inlined.",
|
|
601
|
-
contract: "ImageBlock"
|
|
602
|
-
},
|
|
603
|
-
imageChildInGroup: {
|
|
604
|
-
family: "imageChildInGroup",
|
|
605
|
-
support: "supported",
|
|
606
|
-
description: "Bitmap child of a supported DrawingML group/drawing wrapper. Supported only when the parent is.",
|
|
607
|
-
contract: "ImageDrawing"
|
|
608
|
-
},
|
|
609
|
-
vectorShape: {
|
|
610
|
-
family: "vectorShape",
|
|
611
|
-
support: "supported",
|
|
612
|
-
description: "Block/floating DrawingML preset/custom shape with the supported geometry/style subset.",
|
|
613
|
-
contract: "DrawingBlock",
|
|
614
|
-
drawingKind: "vectorShape"
|
|
615
|
-
},
|
|
616
|
-
shapeGroup: {
|
|
617
|
-
family: "shapeGroup",
|
|
618
|
-
support: "supported",
|
|
619
|
-
description: "DrawingML group whose rendered children are supported vector/image children.",
|
|
620
|
-
contract: "DrawingBlock",
|
|
621
|
-
drawingKind: "shapeGroup"
|
|
622
|
-
},
|
|
623
|
-
chart: {
|
|
624
|
-
family: "chart",
|
|
625
|
-
support: "supported",
|
|
626
|
-
description: "DrawingML chart projected into a ChartDrawing with parsed cached chart XML data. Complete Word chart fidelity remains deferred to chartFidelity.",
|
|
627
|
-
contract: "DrawingBlock",
|
|
628
|
-
drawingKind: "chart"
|
|
629
|
-
},
|
|
630
|
-
alternateContent: {
|
|
631
|
-
family: "alternateContent",
|
|
632
|
-
support: "supported",
|
|
633
|
-
description: "mc:AlternateContent traversal/select policy. Selected Choice/Fallback maps to its family contract; unselected branches preserved for save/reopen.",
|
|
634
|
-
contract: "selected-choice"
|
|
635
|
-
},
|
|
636
|
-
externalImage: {
|
|
637
|
-
family: "externalImage",
|
|
638
|
-
support: "fail-closed",
|
|
639
|
-
description: "External image relationship (r:link / TargetMode=\"External\"). Not fetched.",
|
|
640
|
-
contract: "none",
|
|
641
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.externalImageDeferred
|
|
642
|
-
},
|
|
643
|
-
missingRelationship: {
|
|
644
|
-
family: "missingRelationship",
|
|
645
|
-
support: "fail-closed",
|
|
646
|
-
description: "Drawing references a relationship id absent from the owner part .rels.",
|
|
647
|
-
contract: "none",
|
|
648
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.missingRelationship
|
|
649
|
-
},
|
|
650
|
-
missingMediaPart: {
|
|
651
|
-
family: "missingMediaPart",
|
|
652
|
-
support: "fail-closed",
|
|
653
|
-
description: "Relationship resolves but the target media part bytes are missing or empty.",
|
|
654
|
-
contract: "none",
|
|
655
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.missingMediaPart
|
|
656
|
-
},
|
|
657
|
-
wrongRelationshipType: {
|
|
658
|
-
family: "wrongRelationshipType",
|
|
659
|
-
support: "fail-closed",
|
|
660
|
-
description: "Relationship exists but is not an image relationship type.",
|
|
661
|
-
contract: "none",
|
|
662
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType
|
|
663
|
-
},
|
|
664
|
-
unsupportedMime: {
|
|
665
|
-
family: "unsupportedMime",
|
|
666
|
-
support: "fail-closed",
|
|
667
|
-
description: "Media MIME outside the supported allowlist (incl. GIF/BMP/ICO).",
|
|
668
|
-
contract: "none",
|
|
669
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedMime
|
|
670
|
-
},
|
|
671
|
-
oversizedMediaPart: {
|
|
672
|
-
family: "oversizedMediaPart",
|
|
673
|
-
support: "fail-closed",
|
|
674
|
-
description: "Media part exceeds the host byte-size policy before bytes are materialized.",
|
|
675
|
-
contract: "none",
|
|
676
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.imageTooLarge
|
|
677
|
-
},
|
|
678
|
-
unsafeSvg: {
|
|
679
|
-
family: "unsafeSvg",
|
|
680
|
-
support: "fail-closed",
|
|
681
|
-
description: "SVG content rejected by the SVG safety policy.",
|
|
682
|
-
contract: "none",
|
|
683
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsafeSvg
|
|
684
|
-
},
|
|
685
|
-
metafileOrTiff: {
|
|
686
|
-
family: "metafileOrTiff",
|
|
687
|
-
support: "fail-closed",
|
|
688
|
-
description: "EMF/WMF/TIFF and other non-browser-native formats with no approved conversion path.",
|
|
689
|
-
contract: "none",
|
|
690
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedFormat
|
|
691
|
-
},
|
|
692
|
-
embeddedObject: {
|
|
693
|
-
family: "embeddedObject",
|
|
694
|
-
support: "fail-closed",
|
|
695
|
-
description: "OLE / ActiveX / embedded package object.",
|
|
696
|
-
contract: "none",
|
|
697
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.embeddedObjectNotSupported
|
|
698
|
-
},
|
|
699
|
-
smartArtOrDiagram: {
|
|
700
|
-
family: "smartArtOrDiagram",
|
|
701
|
-
support: "fail-closed",
|
|
702
|
-
description: "SmartArt / diagram / unknown external graphic-data object.",
|
|
703
|
-
contract: "none",
|
|
704
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedObject
|
|
705
|
-
},
|
|
706
|
-
vml: {
|
|
707
|
-
family: "vml",
|
|
708
|
-
support: "fail-closed",
|
|
709
|
-
description: "VML structure outside any supported image-like subset (default fail-closed policy).",
|
|
710
|
-
contract: "none",
|
|
711
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.vmlUnsupported
|
|
712
|
-
},
|
|
713
|
-
vmlImageLike: {
|
|
714
|
-
family: "vmlImageLike",
|
|
715
|
-
support: "fail-closed",
|
|
716
|
-
description: "Simple VML image references (v:imagedata) / watermark image metadata. Fail-closed unless a later change promotes a named subset with deterministic fixtures and exact oracles.",
|
|
717
|
-
contract: "none",
|
|
718
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.vmlImageUnsupported
|
|
719
|
-
},
|
|
720
|
-
unsupportedGeometryCommand: {
|
|
721
|
-
family: "unsupportedGeometryCommand",
|
|
722
|
-
support: "fail-closed",
|
|
723
|
-
description: "Custom geometry command the extractor does not implement, e.g. arcTo.",
|
|
724
|
-
contract: "none",
|
|
725
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedGeometryCommand
|
|
726
|
-
},
|
|
727
|
-
unsupportedAnchorFields: {
|
|
728
|
-
family: "unsupportedAnchorFields",
|
|
729
|
-
support: "fail-closed",
|
|
730
|
-
description: "Anchor fields required for honest placement are unsupported (char-relative, alignment modes, etc.).",
|
|
731
|
-
contract: "none",
|
|
732
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.anchorUnsupported
|
|
733
|
-
},
|
|
734
|
-
unsupportedWrapFields: {
|
|
735
|
-
family: "unsupportedWrapFields",
|
|
736
|
-
support: "fail-closed",
|
|
737
|
-
description: "Wrap fields required for honest placement are unsupported (arbitrary wrap polygons, etc.).",
|
|
738
|
-
contract: "none",
|
|
739
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.wrapUnsupported
|
|
740
|
-
},
|
|
741
|
-
alternateContentNoSupportedChoice: {
|
|
742
|
-
family: "alternateContentNoSupportedChoice",
|
|
743
|
-
support: "fail-closed",
|
|
744
|
-
description: "mc:AlternateContent with no supported choice and no usable fallback.",
|
|
745
|
-
contract: "none",
|
|
746
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.altContentNoSupportedChoice
|
|
747
|
-
},
|
|
748
|
-
groupChildUnsupported: {
|
|
749
|
-
family: "groupChildUnsupported",
|
|
750
|
-
support: "fail-closed",
|
|
751
|
-
description: "Unsupported child inside an otherwise-supported group. Supported siblings are not dropped.",
|
|
752
|
-
contract: "none",
|
|
753
|
-
diagnostic: DRAWING_DIAGNOSTIC_CODES.groupChildUnsupported
|
|
754
|
-
},
|
|
755
|
-
objectEditing: {
|
|
756
|
-
family: "objectEditing",
|
|
757
|
-
support: "deferred",
|
|
758
|
-
description: "Editing/mutation of anchored/vector objects.",
|
|
759
|
-
contract: "none"
|
|
760
|
-
},
|
|
761
|
-
customWrapPolygon: {
|
|
762
|
-
family: "customWrapPolygon",
|
|
763
|
-
support: "deferred",
|
|
764
|
-
description: "Full Word-compatible text wrapping for arbitrary custom wrap polygons.",
|
|
765
|
-
contract: "none"
|
|
766
|
-
},
|
|
767
|
-
chartFidelity: {
|
|
768
|
-
family: "chartFidelity",
|
|
769
|
-
support: "deferred",
|
|
770
|
-
description: "Complete chart fidelity (a dedicated chart effort owns the parsed subset).",
|
|
771
|
-
contract: "none"
|
|
772
|
-
},
|
|
773
|
-
vmlFidelity: {
|
|
774
|
-
family: "vmlFidelity",
|
|
775
|
-
support: "deferred",
|
|
776
|
-
description: "Complete VML fidelity.",
|
|
777
|
-
contract: "none"
|
|
778
|
-
},
|
|
779
|
-
decorativeAccessibilityUi: {
|
|
780
|
-
family: "decorativeAccessibilityUi",
|
|
781
|
-
support: "deferred",
|
|
782
|
-
description: "Full accessibility UI for decorative image semantics beyond preserving source data.",
|
|
783
|
-
contract: "none"
|
|
784
|
-
}
|
|
785
|
-
};
|
|
786
|
-
Object.keys(DRAWING_SUPPORT_TAXONOMY);
|
|
787
|
-
Object.freeze([
|
|
788
|
-
"multiple-sections",
|
|
789
|
-
"furniture-page-tokens",
|
|
790
|
-
"non-balanceable-multi-column-sections",
|
|
791
|
-
"body-anchored-objects",
|
|
792
|
-
"non-flowing-page-relative-body-anchors",
|
|
793
|
-
"footnotes",
|
|
794
|
-
"page-references",
|
|
795
|
-
"cross-references",
|
|
796
|
-
"keep-constraints",
|
|
797
|
-
"tables",
|
|
798
|
-
"furniture-anchored-objects"
|
|
799
|
-
]);
|
|
800
|
-
var INCREMENTAL_DEPENDENCY_CERTIFICATE_CLASSES = Object.freeze([
|
|
801
|
-
"checkpoint-geometry",
|
|
802
|
-
"section-numbering",
|
|
803
|
-
"font-style-inputs",
|
|
804
|
-
"notes",
|
|
805
|
-
"furniture",
|
|
806
|
-
"flowing-anchors",
|
|
807
|
-
"non-flowing-page-anchors",
|
|
808
|
-
"convergence",
|
|
809
|
-
"source-topology"
|
|
810
|
-
]);
|
|
811
|
-
new Set(INCREMENTAL_DEPENDENCY_CERTIFICATE_CLASSES);
|
|
812
|
-
//#endregion
|
|
813
|
-
//#region src/helpers/v2-review-mutation-impact.js
|
|
814
|
-
/**
|
|
815
|
-
* Classify the tracked-change identities carried by a v2 mutation event.
|
|
816
|
-
*
|
|
817
|
-
* Receipt entities are the durable invalidation contract between the document
|
|
818
|
-
* kernel and derived review UI. Direct receipts carry entity refs; mutation
|
|
819
|
-
* plans carry the same identities through `trackedChanges` and per-step ids.
|
|
820
|
-
*/
|
|
821
|
-
function getV2TrackedChangeMutationImpact(event) {
|
|
822
|
-
if (event?.type !== "mutation:committed") return null;
|
|
823
|
-
const payload = event.origin === "history" ? event.result : event.receipt;
|
|
824
|
-
if (!payload || typeof payload !== "object") return null;
|
|
825
|
-
const upsertIds = /* @__PURE__ */ new Set();
|
|
826
|
-
const removedIds = /* @__PURE__ */ new Set();
|
|
827
|
-
/** @type {Array<{ from: string, to: string }>} */
|
|
828
|
-
const remappedPairs = [];
|
|
829
|
-
const collectEntity = (entry, into) => {
|
|
830
|
-
if (entry?.kind !== "entity" || entry.entityType !== "trackedChange") return;
|
|
831
|
-
if (typeof entry.entityId === "string" && entry.entityId.length > 0) into.add(entry.entityId);
|
|
832
|
-
};
|
|
833
|
-
const readEntityId = (entry) => {
|
|
834
|
-
if (entry?.kind !== "entity" || entry.entityType !== "trackedChange") return null;
|
|
835
|
-
return typeof entry.entityId === "string" && entry.entityId.length > 0 ? entry.entityId : null;
|
|
836
|
-
};
|
|
837
|
-
if (Array.isArray(payload.inserted)) payload.inserted.forEach((entry) => collectEntity(entry, upsertIds));
|
|
838
|
-
if (Array.isArray(payload.updated)) payload.updated.forEach((entry) => collectEntity(entry, upsertIds));
|
|
839
|
-
if (Array.isArray(payload.trackedChangeRefs)) payload.trackedChangeRefs.forEach((entry) => collectEntity(entry, upsertIds));
|
|
840
|
-
if (Array.isArray(payload.trackedChanges)) payload.trackedChanges.forEach((entry) => collectEntity(entry, upsertIds));
|
|
841
|
-
if (Array.isArray(payload.steps)) for (const step of payload.steps) {
|
|
842
|
-
if (!Array.isArray(step?.trackedChangeIds)) continue;
|
|
843
|
-
for (const id of step.trackedChangeIds) if (typeof id === "string" && id.length > 0) upsertIds.add(id);
|
|
844
|
-
}
|
|
845
|
-
if (Array.isArray(payload.removed)) payload.removed.forEach((entry) => collectEntity(entry, removedIds));
|
|
846
|
-
if (Array.isArray(payload.invalidatedRefs)) payload.invalidatedRefs.forEach((entry) => collectEntity(entry, removedIds));
|
|
847
|
-
if (Array.isArray(payload.remappedRefs)) for (const mapping of payload.remappedRefs) {
|
|
848
|
-
const fromId = readEntityId(mapping?.from);
|
|
849
|
-
const toId = readEntityId(mapping?.to);
|
|
850
|
-
if (fromId) removedIds.add(fromId);
|
|
851
|
-
if (toId) upsertIds.add(toId);
|
|
852
|
-
if (fromId && toId && fromId !== toId) remappedPairs.push({
|
|
853
|
-
from: fromId,
|
|
854
|
-
to: toId
|
|
855
|
-
});
|
|
856
|
-
}
|
|
857
|
-
for (const id of removedIds) upsertIds.delete(id);
|
|
858
|
-
const allResolved = readAllResolvedFact(event, payload);
|
|
859
|
-
if (upsertIds.size === 0 && removedIds.size === 0 && !allResolved) return null;
|
|
860
|
-
return {
|
|
861
|
-
upsertIds,
|
|
862
|
-
removedIds,
|
|
863
|
-
remappedPairs,
|
|
864
|
-
reconcileMode: "targeted",
|
|
865
|
-
...allResolved ? { allResolved } : {}
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
/**
|
|
869
|
-
* Comment ids retired by a committed v2 mutation.
|
|
712
|
+
* Comment ids retired by a committed v2 mutation.
|
|
870
713
|
*
|
|
871
714
|
* AIDEV-NOTE: History commits put invalidated comment ids on `result`; cut and
|
|
872
715
|
* other command receipts use `receipt`. Same origin split as
|
|
@@ -903,6 +746,56 @@ function readAllResolvedFact(event, receipt) {
|
|
|
903
746
|
return fact;
|
|
904
747
|
}
|
|
905
748
|
//#endregion
|
|
749
|
+
//#region src/helpers/v2-typing-mutation-event.js
|
|
750
|
+
/**
|
|
751
|
+
* Command kinds whose committed mutations belong to the sustained typing
|
|
752
|
+
* cadence class (insert / replace / plain paste / Backspace / Delete).
|
|
753
|
+
*
|
|
754
|
+
* The SuperDoc shell debounces per-keystroke review-row hydration for these
|
|
755
|
+
* kinds instead of refreshing comments + tracked changes on every commit —
|
|
756
|
+
* hydrating immediately per keystroke was a measured worker-read storm during
|
|
757
|
+
* typing and backspace bursts. The `text.*` aliases cover integrations that
|
|
758
|
+
* forward Document API style command ids rather than editable-input kinds.
|
|
759
|
+
*/
|
|
760
|
+
var V2_TYPING_COMMAND_KINDS = /* @__PURE__ */ new Set([
|
|
761
|
+
"insert-text",
|
|
762
|
+
"replace-text",
|
|
763
|
+
"plain-text-paste",
|
|
764
|
+
"delete-backward",
|
|
765
|
+
"delete-forward",
|
|
766
|
+
"text.insert",
|
|
767
|
+
"text.replace",
|
|
768
|
+
"text.pastePlain",
|
|
769
|
+
"text.deleteBackward",
|
|
770
|
+
"text.deleteForward",
|
|
771
|
+
"structural.enter",
|
|
772
|
+
"structural:enter-split-paragraph",
|
|
773
|
+
"structural:enter-insert-paragraph-before",
|
|
774
|
+
"structural:enter-insert-paragraph-after",
|
|
775
|
+
"structural:shift-enter-line-break",
|
|
776
|
+
"structural:backspace-boundary-merge-with-previous",
|
|
777
|
+
"structural:delete-boundary-merge-with-next",
|
|
778
|
+
"backspace:boundary-merge-with-previous",
|
|
779
|
+
"backspace:list-remove",
|
|
780
|
+
"backspace:list-outdent"
|
|
781
|
+
]);
|
|
782
|
+
/**
|
|
783
|
+
* True when a forwarded v2 host event is a committed editable-input mutation
|
|
784
|
+
* of the sustained-typing class, i.e. review-row hydration for it should be
|
|
785
|
+
* debounced rather than fired immediately.
|
|
786
|
+
*
|
|
787
|
+
* Events without a forwarded `editableCommandKind` (programmatic Document API
|
|
788
|
+
* mutations, history commits, unclassified structural commands) return false
|
|
789
|
+
* so they keep hydrating immediately.
|
|
790
|
+
*
|
|
791
|
+
* @param {{ type?: string, origin?: string, editableCommandKind?: string } | null | undefined} event
|
|
792
|
+
* @returns {boolean}
|
|
793
|
+
*/
|
|
794
|
+
var isV2EditableTextMutationEvent = (event) => {
|
|
795
|
+
if (event?.type !== "mutation:committed" || event.origin !== "command") return false;
|
|
796
|
+
return V2_TYPING_COMMAND_KINDS.has(event.editableCommandKind);
|
|
797
|
+
};
|
|
798
|
+
//#endregion
|
|
906
799
|
//#region src/public/ui/reasons.ts
|
|
907
800
|
/**
|
|
908
801
|
* Stable public reason taxonomy for the v2-native `superdoc/ui` controller.
|
|
@@ -1430,603 +1323,710 @@ var COMMAND_CATALOG = [
|
|
|
1430
1323
|
key: "highlight",
|
|
1431
1324
|
kind: "value-string"
|
|
1432
1325
|
},
|
|
1433
|
-
normalizePayload: normalizeColorPayload
|
|
1326
|
+
normalizePayload: normalizeColorPayload
|
|
1327
|
+
},
|
|
1328
|
+
{
|
|
1329
|
+
id: "link",
|
|
1330
|
+
family: "links",
|
|
1331
|
+
disposition: "routed",
|
|
1332
|
+
mutates: true,
|
|
1333
|
+
docRoute: "hyperlinks.wrap",
|
|
1334
|
+
activeMark: "link",
|
|
1335
|
+
link: { kind: "link" }
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
id: "text-align",
|
|
1339
|
+
family: "paragraph",
|
|
1340
|
+
disposition: "routed",
|
|
1341
|
+
mutates: true,
|
|
1342
|
+
docRoute: "format.paragraph.setAlignment",
|
|
1343
|
+
blockParagraph: { kind: "alignment" },
|
|
1344
|
+
normalizePayload: normalizeAlignmentPayload
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
id: "line-height",
|
|
1348
|
+
family: "paragraph",
|
|
1349
|
+
disposition: "routed",
|
|
1350
|
+
mutates: true,
|
|
1351
|
+
docRoute: "format.paragraph.setSpacing",
|
|
1352
|
+
blockParagraph: { kind: "spacing-line" },
|
|
1353
|
+
normalizePayload: normalizeLineHeightPayload
|
|
1354
|
+
},
|
|
1355
|
+
{
|
|
1356
|
+
id: "linked-style",
|
|
1357
|
+
family: "paragraph",
|
|
1358
|
+
disposition: "routed",
|
|
1359
|
+
mutates: true,
|
|
1360
|
+
docRoute: "styles.paragraph.setStyle",
|
|
1361
|
+
blockParagraph: { kind: "style" },
|
|
1362
|
+
normalizePayload: normalizeStyleIdPayload
|
|
1363
|
+
},
|
|
1364
|
+
{
|
|
1365
|
+
id: "bullet-list",
|
|
1366
|
+
family: "lists",
|
|
1367
|
+
disposition: "routed",
|
|
1368
|
+
mutates: true,
|
|
1369
|
+
docRoute: "lists.apply",
|
|
1370
|
+
list: {
|
|
1371
|
+
mode: "toggle-seed",
|
|
1372
|
+
seed: "bullet"
|
|
1373
|
+
}
|
|
1374
|
+
},
|
|
1375
|
+
{
|
|
1376
|
+
id: "numbered-list",
|
|
1377
|
+
family: "lists",
|
|
1378
|
+
disposition: "routed",
|
|
1379
|
+
mutates: true,
|
|
1380
|
+
docRoute: "lists.apply",
|
|
1381
|
+
list: {
|
|
1382
|
+
mode: "toggle-seed",
|
|
1383
|
+
seed: "ordered"
|
|
1384
|
+
}
|
|
1385
|
+
},
|
|
1386
|
+
{
|
|
1387
|
+
id: "indent-increase",
|
|
1388
|
+
family: "lists/indent",
|
|
1389
|
+
disposition: "routed",
|
|
1390
|
+
mutates: true,
|
|
1391
|
+
docRoute: "lists.indent",
|
|
1392
|
+
list: { mode: "indent" }
|
|
1393
|
+
},
|
|
1394
|
+
{
|
|
1395
|
+
id: "indent-decrease",
|
|
1396
|
+
family: "lists/indent",
|
|
1397
|
+
disposition: "routed",
|
|
1398
|
+
mutates: true,
|
|
1399
|
+
docRoute: "lists.outdent",
|
|
1400
|
+
list: { mode: "outdent" }
|
|
1401
|
+
},
|
|
1402
|
+
{
|
|
1403
|
+
id: "direction-ltr",
|
|
1404
|
+
family: "direction",
|
|
1405
|
+
disposition: "routed",
|
|
1406
|
+
mutates: true,
|
|
1407
|
+
docRoute: "format.paragraph.setDirection",
|
|
1408
|
+
blockParagraph: {
|
|
1409
|
+
kind: "direction",
|
|
1410
|
+
fixedValue: "ltr"
|
|
1411
|
+
}
|
|
1412
|
+
},
|
|
1413
|
+
{
|
|
1414
|
+
id: "direction-rtl",
|
|
1415
|
+
family: "direction",
|
|
1416
|
+
disposition: "routed",
|
|
1417
|
+
mutates: true,
|
|
1418
|
+
docRoute: "format.paragraph.setDirection",
|
|
1419
|
+
blockParagraph: {
|
|
1420
|
+
kind: "direction",
|
|
1421
|
+
fixedValue: "rtl"
|
|
1422
|
+
}
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
id: "clear-formatting",
|
|
1426
|
+
family: "formatting",
|
|
1427
|
+
disposition: "routed",
|
|
1428
|
+
mutates: true,
|
|
1429
|
+
docRoute: "format.apply",
|
|
1430
|
+
inline: {
|
|
1431
|
+
key: "*",
|
|
1432
|
+
kind: "clear"
|
|
1433
|
+
}
|
|
1434
|
+
},
|
|
1435
|
+
{
|
|
1436
|
+
id: "image",
|
|
1437
|
+
family: "media",
|
|
1438
|
+
disposition: "routed",
|
|
1439
|
+
mutates: true,
|
|
1440
|
+
docRoute: "create.image",
|
|
1441
|
+
create: { kind: "image" }
|
|
1442
|
+
},
|
|
1443
|
+
{
|
|
1444
|
+
id: "table-of-contents-insert",
|
|
1445
|
+
family: "TOC",
|
|
1446
|
+
disposition: "routed",
|
|
1447
|
+
mutates: true,
|
|
1448
|
+
docRoute: "create.tableOfContents",
|
|
1449
|
+
create: { kind: "toc" }
|
|
1450
|
+
},
|
|
1451
|
+
{
|
|
1452
|
+
id: "table-insert",
|
|
1453
|
+
family: "tables",
|
|
1454
|
+
disposition: "routed",
|
|
1455
|
+
mutates: true,
|
|
1456
|
+
docRoute: "create.table",
|
|
1457
|
+
create: { kind: "table" }
|
|
1458
|
+
},
|
|
1459
|
+
{
|
|
1460
|
+
id: "table-add-row-before",
|
|
1461
|
+
family: "tables",
|
|
1462
|
+
disposition: "routed",
|
|
1463
|
+
mutates: true,
|
|
1464
|
+
docRoute: "tables.insertRow",
|
|
1465
|
+
table: {
|
|
1466
|
+
action: "insert-row-before",
|
|
1467
|
+
op: "insertRow"
|
|
1468
|
+
},
|
|
1469
|
+
reason: TABLE_CONTEXT
|
|
1470
|
+
},
|
|
1471
|
+
{
|
|
1472
|
+
id: "table-add-row-after",
|
|
1473
|
+
family: "tables",
|
|
1474
|
+
disposition: "routed",
|
|
1475
|
+
mutates: true,
|
|
1476
|
+
docRoute: "tables.insertRow",
|
|
1477
|
+
table: {
|
|
1478
|
+
action: "insert-row-after",
|
|
1479
|
+
op: "insertRow"
|
|
1480
|
+
},
|
|
1481
|
+
reason: TABLE_CONTEXT
|
|
1482
|
+
},
|
|
1483
|
+
{
|
|
1484
|
+
id: "table-delete-row",
|
|
1485
|
+
family: "tables",
|
|
1486
|
+
disposition: "routed",
|
|
1487
|
+
mutates: true,
|
|
1488
|
+
docRoute: "tables.deleteRow",
|
|
1489
|
+
table: {
|
|
1490
|
+
action: "delete-row",
|
|
1491
|
+
op: "deleteRow"
|
|
1492
|
+
},
|
|
1493
|
+
reason: TABLE_CONTEXT
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
id: "table-add-column-before",
|
|
1497
|
+
family: "tables",
|
|
1498
|
+
disposition: "routed",
|
|
1499
|
+
mutates: true,
|
|
1500
|
+
docRoute: "tables.insertColumn",
|
|
1501
|
+
table: {
|
|
1502
|
+
action: "insert-column-before",
|
|
1503
|
+
op: "insertColumn"
|
|
1504
|
+
},
|
|
1505
|
+
reason: TABLE_CONTEXT
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
id: "table-add-column-after",
|
|
1509
|
+
family: "tables",
|
|
1510
|
+
disposition: "routed",
|
|
1511
|
+
mutates: true,
|
|
1512
|
+
docRoute: "tables.insertColumn",
|
|
1513
|
+
table: {
|
|
1514
|
+
action: "insert-column-after",
|
|
1515
|
+
op: "insertColumn"
|
|
1516
|
+
},
|
|
1517
|
+
reason: TABLE_CONTEXT
|
|
1518
|
+
},
|
|
1519
|
+
{
|
|
1520
|
+
id: "table-delete-column",
|
|
1521
|
+
family: "tables",
|
|
1522
|
+
disposition: "routed",
|
|
1523
|
+
mutates: true,
|
|
1524
|
+
docRoute: "tables.deleteColumn",
|
|
1525
|
+
table: {
|
|
1526
|
+
action: "delete-column",
|
|
1527
|
+
op: "deleteColumn"
|
|
1528
|
+
},
|
|
1529
|
+
reason: TABLE_CONTEXT
|
|
1434
1530
|
},
|
|
1435
1531
|
{
|
|
1436
|
-
id: "
|
|
1437
|
-
family: "
|
|
1532
|
+
id: "table-delete",
|
|
1533
|
+
family: "tables",
|
|
1438
1534
|
disposition: "routed",
|
|
1439
1535
|
mutates: true,
|
|
1440
|
-
docRoute: "
|
|
1441
|
-
|
|
1442
|
-
|
|
1536
|
+
docRoute: "tables.delete",
|
|
1537
|
+
table: {
|
|
1538
|
+
action: "delete-table",
|
|
1539
|
+
op: "delete"
|
|
1540
|
+
},
|
|
1541
|
+
reason: TABLE_CONTEXT
|
|
1443
1542
|
},
|
|
1444
1543
|
{
|
|
1445
|
-
id: "
|
|
1446
|
-
family: "
|
|
1544
|
+
id: "table-merge-cells",
|
|
1545
|
+
family: "tables",
|
|
1447
1546
|
disposition: "routed",
|
|
1448
1547
|
mutates: true,
|
|
1449
|
-
docRoute: "
|
|
1450
|
-
|
|
1451
|
-
|
|
1548
|
+
docRoute: "tables.mergeCells",
|
|
1549
|
+
table: {
|
|
1550
|
+
action: "merge-cells",
|
|
1551
|
+
op: "mergeCells"
|
|
1552
|
+
},
|
|
1553
|
+
reason: TABLE_CONTEXT
|
|
1452
1554
|
},
|
|
1453
1555
|
{
|
|
1454
|
-
id: "
|
|
1455
|
-
family: "
|
|
1556
|
+
id: "table-split-cell",
|
|
1557
|
+
family: "tables",
|
|
1456
1558
|
disposition: "routed",
|
|
1457
1559
|
mutates: true,
|
|
1458
|
-
docRoute: "
|
|
1459
|
-
|
|
1460
|
-
|
|
1560
|
+
docRoute: "tables.splitCell",
|
|
1561
|
+
table: {
|
|
1562
|
+
action: "split-cell",
|
|
1563
|
+
op: "splitCell",
|
|
1564
|
+
requiresCell: true
|
|
1565
|
+
},
|
|
1566
|
+
reason: TABLE_CONTEXT
|
|
1461
1567
|
},
|
|
1462
1568
|
{
|
|
1463
|
-
id: "
|
|
1464
|
-
family: "
|
|
1569
|
+
id: "table-remove-borders",
|
|
1570
|
+
family: "tables",
|
|
1465
1571
|
disposition: "routed",
|
|
1466
1572
|
mutates: true,
|
|
1467
|
-
docRoute: "
|
|
1468
|
-
|
|
1469
|
-
|
|
1573
|
+
docRoute: "tables.setBorders",
|
|
1574
|
+
table: {
|
|
1575
|
+
action: "remove-borders",
|
|
1576
|
+
op: "setBorders"
|
|
1577
|
+
},
|
|
1578
|
+
reason: TABLE_CONTEXT
|
|
1470
1579
|
},
|
|
1471
1580
|
{
|
|
1472
|
-
id: "
|
|
1473
|
-
family: "
|
|
1581
|
+
id: "ruler",
|
|
1582
|
+
family: "UI chrome",
|
|
1474
1583
|
disposition: "routed",
|
|
1475
|
-
mutates:
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
mode: "toggle-seed",
|
|
1479
|
-
seed: "bullet"
|
|
1480
|
-
}
|
|
1584
|
+
mutates: false,
|
|
1585
|
+
instanceRoute: "toggleRuler",
|
|
1586
|
+
valueFrom: "ruler"
|
|
1481
1587
|
},
|
|
1482
1588
|
{
|
|
1483
|
-
id: "
|
|
1484
|
-
family: "
|
|
1589
|
+
id: "formatting-marks",
|
|
1590
|
+
family: "UI chrome",
|
|
1485
1591
|
disposition: "routed",
|
|
1486
|
-
mutates:
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
mode: "toggle-seed",
|
|
1490
|
-
seed: "ordered"
|
|
1491
|
-
}
|
|
1592
|
+
mutates: false,
|
|
1593
|
+
instanceRoute: "toggleFormattingMarks",
|
|
1594
|
+
valueFrom: "formattingMarks"
|
|
1492
1595
|
},
|
|
1493
1596
|
{
|
|
1494
|
-
id: "
|
|
1495
|
-
family: "
|
|
1597
|
+
id: "copy-format",
|
|
1598
|
+
family: "formatting",
|
|
1496
1599
|
disposition: "routed",
|
|
1600
|
+
mutates: false
|
|
1601
|
+
},
|
|
1602
|
+
{
|
|
1603
|
+
id: "table-fix",
|
|
1604
|
+
family: "tables",
|
|
1605
|
+
disposition: "unsupported",
|
|
1497
1606
|
mutates: true,
|
|
1498
|
-
|
|
1499
|
-
|
|
1607
|
+
reason: UNSUPPORTED
|
|
1608
|
+
}
|
|
1609
|
+
];
|
|
1610
|
+
var CATALOG_BY_ID = new Map(COMMAND_CATALOG.map((descriptor) => [descriptor.id, descriptor]));
|
|
1611
|
+
/** All built-in command ids known to the controller (routed + deferred + unsupported). */
|
|
1612
|
+
var ALL_BUILT_IN_COMMAND_IDS = COMMAND_CATALOG.map((d) => d.id);
|
|
1613
|
+
/** Resolve a command descriptor by id, or `null` when the id is unknown. */
|
|
1614
|
+
function getCommandDescriptor(id) {
|
|
1615
|
+
return CATALOG_BY_ID.get(id) ?? null;
|
|
1616
|
+
}
|
|
1617
|
+
//#endregion
|
|
1618
|
+
//#region src/public/ui/entity-at.ts
|
|
1619
|
+
function parseCommaSeparatedIds(value) {
|
|
1620
|
+
return value.split(",").map((id) => id.trim()).filter(Boolean);
|
|
1621
|
+
}
|
|
1622
|
+
/**
|
|
1623
|
+
* Collect every public-id candidate a painted run can carry for a tracked
|
|
1624
|
+
* change, deduped, in priority order: the canonical
|
|
1625
|
+
* `data-track-change-preferred-target-id` first (when the painter stamps one),
|
|
1626
|
+
* then the `data-track-change-ids` list, then the singular
|
|
1627
|
+
* `data-track-change-id`. The caller validates these against the live
|
|
1628
|
+
* tracked-changes slice and keeps whichever is the public id, so it does not
|
|
1629
|
+
* matter which attribute carries it — an imported/raw alias on one attribute
|
|
1630
|
+
* never hides the public id on another (a union, not a prefer-one-attribute).
|
|
1631
|
+
*/
|
|
1632
|
+
function getTrackChangeIds(node) {
|
|
1633
|
+
const out = [];
|
|
1634
|
+
const add = (id) => {
|
|
1635
|
+
if (id && !out.includes(id)) out.push(id);
|
|
1636
|
+
};
|
|
1637
|
+
add(node.getAttribute("data-track-change-preferred-target-id"));
|
|
1638
|
+
const list = node.getAttribute("data-track-change-ids");
|
|
1639
|
+
if (list) for (const id of parseCommaSeparatedIds(list)) add(id);
|
|
1640
|
+
add(node.getAttribute("data-track-change-id"));
|
|
1641
|
+
return out;
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Read painted entities off `el` and every ancestor up to the document root, or
|
|
1645
|
+
* up to and INCLUDING `stopAt` when given. Innermost-first ordering: a tracked
|
|
1646
|
+
* change inside a comment highlight returns `[{ trackedChange }, { comment }]`,
|
|
1647
|
+
* matching what a switch on `hits[0]` expects when picking the most specific
|
|
1648
|
+
* entity.
|
|
1649
|
+
*
|
|
1650
|
+
* `stopAt` bounds the walk to the visible host: its own attributes are read, but
|
|
1651
|
+
* the walk never climbs into an app wrapper ABOVE it, so wrapper data-* cannot
|
|
1652
|
+
* leak into the hits. Omitting it keeps the original walk-to-document-root.
|
|
1653
|
+
*
|
|
1654
|
+
* Returns `[]` for null / non-Element starts. Uses duck-typed `getAttribute`
|
|
1655
|
+
* access so it works under any DOM implementation (happy-dom, jsdom, real
|
|
1656
|
+
* browser) without an `instanceof` check that could fail across realms.
|
|
1657
|
+
*/
|
|
1658
|
+
function collectEntityHitsFromChain(start, stopAt) {
|
|
1659
|
+
if (!start || typeof start.getAttribute !== "function") return [];
|
|
1660
|
+
const hits = [];
|
|
1661
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1662
|
+
let pendingStory = [];
|
|
1663
|
+
let el = start;
|
|
1664
|
+
while (el) {
|
|
1665
|
+
const node = el;
|
|
1666
|
+
const trackChangeIds = getTrackChangeIds(node);
|
|
1667
|
+
const storyKey = trackChangeIds.length > 0 ? node.getAttribute("data-story-key") : null;
|
|
1668
|
+
for (const trackChangeId of trackChangeIds) {
|
|
1669
|
+
const key = `trackedChange:${trackChangeId}`;
|
|
1670
|
+
if (!seen.has(key)) {
|
|
1671
|
+
seen.add(key);
|
|
1672
|
+
const hit = {
|
|
1673
|
+
type: "trackedChange",
|
|
1674
|
+
id: trackChangeId
|
|
1675
|
+
};
|
|
1676
|
+
if (storyKey) hit.storyKey = storyKey;
|
|
1677
|
+
hits.push(hit);
|
|
1678
|
+
pendingStory.push(hit);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
const layoutStory = node.getAttribute("data-layout-story");
|
|
1682
|
+
if (layoutStory && pendingStory.length > 0) {
|
|
1683
|
+
for (const hit of pendingStory) hit.story = layoutStory;
|
|
1684
|
+
pendingStory = [];
|
|
1685
|
+
}
|
|
1686
|
+
const citationId = node.getAttribute("data-citation-id");
|
|
1687
|
+
if (citationId) {
|
|
1688
|
+
const key = `citation:${citationId}`;
|
|
1689
|
+
if (!seen.has(key)) {
|
|
1690
|
+
seen.add(key);
|
|
1691
|
+
hits.push({
|
|
1692
|
+
type: "citation",
|
|
1693
|
+
id: citationId
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
const commentIds = node.getAttribute("data-comment-ids");
|
|
1698
|
+
if (commentIds) for (const id of parseCommaSeparatedIds(commentIds)) {
|
|
1699
|
+
const key = `comment:${id}`;
|
|
1700
|
+
if (!seen.has(key)) {
|
|
1701
|
+
seen.add(key);
|
|
1702
|
+
hits.push({
|
|
1703
|
+
type: "comment",
|
|
1704
|
+
id
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
const sdtType = node.getAttribute("data-sdt-type");
|
|
1709
|
+
const sdtId = node.getAttribute("data-sdt-id");
|
|
1710
|
+
if (sdtId && sdtType === "structuredContent") {
|
|
1711
|
+
const key = `contentControl:${sdtId}`;
|
|
1712
|
+
if (!seen.has(key)) {
|
|
1713
|
+
seen.add(key);
|
|
1714
|
+
const scopeAttr = node.getAttribute("data-sdt-scope");
|
|
1715
|
+
const tag = node.getAttribute("data-sdt-tag");
|
|
1716
|
+
const hit = {
|
|
1717
|
+
type: "contentControl",
|
|
1718
|
+
id: sdtId
|
|
1719
|
+
};
|
|
1720
|
+
if (scopeAttr === "block" || scopeAttr === "inline") hit.scope = scopeAttr;
|
|
1721
|
+
if (tag) hit.tag = tag;
|
|
1722
|
+
hits.push(hit);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
if (stopAt && el === stopAt) break;
|
|
1726
|
+
el = el.parentElement;
|
|
1727
|
+
}
|
|
1728
|
+
return hits;
|
|
1729
|
+
}
|
|
1730
|
+
//#endregion
|
|
1731
|
+
//#region ../layout-engine/contracts/src/direction-context.ts
|
|
1732
|
+
/**
|
|
1733
|
+
* Read a paragraph's inline base direction from its attributes.
|
|
1734
|
+
*
|
|
1735
|
+
* Prefers the resolved {@link ParagraphDirectionContext} (SD-2776) when
|
|
1736
|
+
* present. Falls back to `paragraphProperties.rightToLeft` for PM-node /
|
|
1737
|
+
* editor paths that store direction on the raw OOXML properties rather
|
|
1738
|
+
* than the typed direction context.
|
|
1739
|
+
*
|
|
1740
|
+
* Consumers should call this instead of inspecting attrs ad hoc so the
|
|
1741
|
+
* direction source check stays in one place.
|
|
1742
|
+
*/
|
|
1743
|
+
function getParagraphInlineDirection(attrs) {
|
|
1744
|
+
const fromContext = attrs?.directionContext?.inlineDirection;
|
|
1745
|
+
if (fromContext != null) return fromContext;
|
|
1746
|
+
const ppRtl = attrs?.paragraphProperties?.rightToLeft;
|
|
1747
|
+
if (ppRtl === true) return "rtl";
|
|
1748
|
+
if (ppRtl === false) return "ltr";
|
|
1749
|
+
}
|
|
1750
|
+
//#endregion
|
|
1751
|
+
//#region ../layout-engine/contracts/src/drawing-taxonomy.ts
|
|
1752
|
+
/**
|
|
1753
|
+
* Frozen canonical diagnostic codes for drawing rendering.
|
|
1754
|
+
*
|
|
1755
|
+
* New extractor/adapter diagnostics MUST use these exact strings. Family-
|
|
1756
|
+
* specific codes are required — do not collapse everything to
|
|
1757
|
+
* `render.unsupported-inline-ooxml` (plan §4).
|
|
1758
|
+
*/
|
|
1759
|
+
var DRAWING_DIAGNOSTIC_CODES = {
|
|
1760
|
+
/** External image relationship (`r:link` / `TargetMode="External"`). Not fetched. */
|
|
1761
|
+
externalImageDeferred: "render.media.external-image-deferred",
|
|
1762
|
+
/** Drawing references a relationship id that does not exist on the owner part. */
|
|
1763
|
+
missingRelationship: "render.drawing.missing-relationship",
|
|
1764
|
+
/** Relationship resolves but the target media part bytes are missing/empty. */
|
|
1765
|
+
missingMediaPart: "render.media.missing-part",
|
|
1766
|
+
/** Relationship exists but is not an image relationship type. */
|
|
1767
|
+
unsupportedRelationshipType: "render.drawing.unsupported-relationship-type",
|
|
1768
|
+
/** Media MIME is not in the supported allowlist. */
|
|
1769
|
+
unsupportedMime: "render.media.unsupported-mime",
|
|
1770
|
+
/** Media part exceeds the host byte-size policy before bytes are materialized. */
|
|
1771
|
+
imageTooLarge: "render.media.image-too-large",
|
|
1772
|
+
/** SVG content rejected by the SVG safety policy. */
|
|
1773
|
+
unsafeSvg: "render.media.unsafe-svg",
|
|
1774
|
+
/** Metafile / TIFF (EMF, WMF, TIFF) with no approved conversion path. */
|
|
1775
|
+
unsupportedFormat: "render.media.unsupported-format",
|
|
1776
|
+
/** OLE / ActiveX / embedded package object. */
|
|
1777
|
+
embeddedObjectNotSupported: "render.embedded-object-not-supported",
|
|
1778
|
+
/** SmartArt / diagram / unknown external graphic-data object. */
|
|
1779
|
+
unsupportedObject: "render.drawing.unsupported-object",
|
|
1780
|
+
/** VML structure outside any supported image-like subset. */
|
|
1781
|
+
vmlUnsupported: "render.drawing.vml-unsupported",
|
|
1782
|
+
/** VML image-like content that could not be promoted to a supported image. */
|
|
1783
|
+
vmlImageUnsupported: "render.drawing.vml-image-unsupported",
|
|
1784
|
+
/** Custom geometry command the extractor does not implement (e.g. `arcTo`). */
|
|
1785
|
+
unsupportedGeometryCommand: "render.drawing.unsupported-geometry-command",
|
|
1786
|
+
/** Anchor fields required for honest placement are unsupported. */
|
|
1787
|
+
anchorUnsupported: "render.drawing.anchor-unsupported",
|
|
1788
|
+
/** Wrap fields required for honest placement are unsupported. */
|
|
1789
|
+
wrapUnsupported: "render.drawing.wrap-unsupported",
|
|
1790
|
+
/** `mc:AlternateContent` had no supported choice and no usable fallback. */
|
|
1791
|
+
altContentNoSupportedChoice: "render.drawing.altcontent-no-supported-choice",
|
|
1792
|
+
/** A child of an otherwise-supported group is unsupported. */
|
|
1793
|
+
groupChildUnsupported: "render.drawing.group-child-unsupported"
|
|
1794
|
+
};
|
|
1795
|
+
DRAWING_DIAGNOSTIC_CODES.missingRelationship, DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType, DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType, DRAWING_DIAGNOSTIC_CODES.imageTooLarge, DRAWING_DIAGNOSTIC_CODES.missingMediaPart, DRAWING_DIAGNOSTIC_CODES.unsupportedObject, DRAWING_DIAGNOSTIC_CODES.vmlUnsupported;
|
|
1796
|
+
/**
|
|
1797
|
+
* The frozen drawing support taxonomy.
|
|
1798
|
+
*
|
|
1799
|
+
* Invariants (enforced by `drawing-taxonomy.test.ts`):
|
|
1800
|
+
* - every `supported` family has a real contract target (`!== 'none'`);
|
|
1801
|
+
* - every `DrawingBlock`-targeted family declares a `drawingKind`;
|
|
1802
|
+
* - every `fail-closed` family declares a canonical `diagnostic`;
|
|
1803
|
+
* - every canonical diagnostic code is referenced by at least one fail-closed
|
|
1804
|
+
* family;
|
|
1805
|
+
* - `deferred` families make no support claim (`contract: 'none'`, no
|
|
1806
|
+
* diagnostic).
|
|
1807
|
+
*/
|
|
1808
|
+
var DRAWING_SUPPORT_TAXONOMY = {
|
|
1809
|
+
inlineBitmap: {
|
|
1810
|
+
family: "inlineBitmap",
|
|
1811
|
+
support: "supported",
|
|
1812
|
+
description: "wp:inline pic:pic with internal media and browser-safe MIME (PNG/JPEG; WebP/SVG once the host media resolver lands).",
|
|
1813
|
+
contract: "ImageRun"
|
|
1500
1814
|
},
|
|
1501
|
-
{
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
docRoute: "lists.outdent",
|
|
1507
|
-
list: { mode: "outdent" }
|
|
1815
|
+
anchoredBitmap: {
|
|
1816
|
+
family: "anchoredBitmap",
|
|
1817
|
+
support: "supported",
|
|
1818
|
+
description: "wp:anchor bitmap with anchor/wrap expressible by ImageAnchor/ImageWrap. Never silently inlined.",
|
|
1819
|
+
contract: "ImageBlock"
|
|
1508
1820
|
},
|
|
1509
|
-
{
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
docRoute: "format.paragraph.setDirection",
|
|
1515
|
-
blockParagraph: {
|
|
1516
|
-
kind: "direction",
|
|
1517
|
-
fixedValue: "ltr"
|
|
1518
|
-
}
|
|
1821
|
+
imageChildInGroup: {
|
|
1822
|
+
family: "imageChildInGroup",
|
|
1823
|
+
support: "supported",
|
|
1824
|
+
description: "Bitmap child of a supported DrawingML group/drawing wrapper. Supported only when the parent is.",
|
|
1825
|
+
contract: "ImageDrawing"
|
|
1519
1826
|
},
|
|
1520
|
-
{
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
blockParagraph: {
|
|
1527
|
-
kind: "direction",
|
|
1528
|
-
fixedValue: "rtl"
|
|
1529
|
-
}
|
|
1827
|
+
vectorShape: {
|
|
1828
|
+
family: "vectorShape",
|
|
1829
|
+
support: "supported",
|
|
1830
|
+
description: "Block/floating DrawingML preset/custom shape with the supported geometry/style subset.",
|
|
1831
|
+
contract: "DrawingBlock",
|
|
1832
|
+
drawingKind: "vectorShape"
|
|
1530
1833
|
},
|
|
1531
|
-
{
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
inline: {
|
|
1538
|
-
key: "*",
|
|
1539
|
-
kind: "clear"
|
|
1540
|
-
}
|
|
1834
|
+
shapeGroup: {
|
|
1835
|
+
family: "shapeGroup",
|
|
1836
|
+
support: "supported",
|
|
1837
|
+
description: "DrawingML group whose rendered children are supported vector/image children.",
|
|
1838
|
+
contract: "DrawingBlock",
|
|
1839
|
+
drawingKind: "shapeGroup"
|
|
1541
1840
|
},
|
|
1542
|
-
{
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
create: { kind: "image" }
|
|
1841
|
+
chart: {
|
|
1842
|
+
family: "chart",
|
|
1843
|
+
support: "supported",
|
|
1844
|
+
description: "DrawingML chart projected into a ChartDrawing with parsed cached chart XML data. Complete Word chart fidelity remains deferred to chartFidelity.",
|
|
1845
|
+
contract: "DrawingBlock",
|
|
1846
|
+
drawingKind: "chart"
|
|
1549
1847
|
},
|
|
1550
|
-
{
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
docRoute: "create.tableOfContents",
|
|
1556
|
-
create: { kind: "toc" }
|
|
1848
|
+
alternateContent: {
|
|
1849
|
+
family: "alternateContent",
|
|
1850
|
+
support: "supported",
|
|
1851
|
+
description: "mc:AlternateContent traversal/select policy. Selected Choice/Fallback maps to its family contract; unselected branches preserved for save/reopen.",
|
|
1852
|
+
contract: "selected-choice"
|
|
1557
1853
|
},
|
|
1558
|
-
{
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
create: { kind: "table" }
|
|
1854
|
+
externalImage: {
|
|
1855
|
+
family: "externalImage",
|
|
1856
|
+
support: "fail-closed",
|
|
1857
|
+
description: "External image relationship (r:link / TargetMode=\"External\"). Not fetched.",
|
|
1858
|
+
contract: "none",
|
|
1859
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.externalImageDeferred
|
|
1565
1860
|
},
|
|
1566
|
-
{
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
table: {
|
|
1573
|
-
action: "insert-row-before",
|
|
1574
|
-
op: "insertRow"
|
|
1575
|
-
},
|
|
1576
|
-
reason: TABLE_CONTEXT
|
|
1861
|
+
missingRelationship: {
|
|
1862
|
+
family: "missingRelationship",
|
|
1863
|
+
support: "fail-closed",
|
|
1864
|
+
description: "Drawing references a relationship id absent from the owner part .rels.",
|
|
1865
|
+
contract: "none",
|
|
1866
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.missingRelationship
|
|
1577
1867
|
},
|
|
1578
|
-
{
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
table: {
|
|
1585
|
-
action: "insert-row-after",
|
|
1586
|
-
op: "insertRow"
|
|
1587
|
-
},
|
|
1588
|
-
reason: TABLE_CONTEXT
|
|
1868
|
+
missingMediaPart: {
|
|
1869
|
+
family: "missingMediaPart",
|
|
1870
|
+
support: "fail-closed",
|
|
1871
|
+
description: "Relationship resolves but the target media part bytes are missing or empty.",
|
|
1872
|
+
contract: "none",
|
|
1873
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.missingMediaPart
|
|
1589
1874
|
},
|
|
1590
|
-
{
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
table: {
|
|
1597
|
-
action: "delete-row",
|
|
1598
|
-
op: "deleteRow"
|
|
1599
|
-
},
|
|
1600
|
-
reason: TABLE_CONTEXT
|
|
1875
|
+
wrongRelationshipType: {
|
|
1876
|
+
family: "wrongRelationshipType",
|
|
1877
|
+
support: "fail-closed",
|
|
1878
|
+
description: "Relationship exists but is not an image relationship type.",
|
|
1879
|
+
contract: "none",
|
|
1880
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType
|
|
1601
1881
|
},
|
|
1602
|
-
{
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
table: {
|
|
1609
|
-
action: "insert-column-before",
|
|
1610
|
-
op: "insertColumn"
|
|
1611
|
-
},
|
|
1612
|
-
reason: TABLE_CONTEXT
|
|
1882
|
+
unsupportedMime: {
|
|
1883
|
+
family: "unsupportedMime",
|
|
1884
|
+
support: "fail-closed",
|
|
1885
|
+
description: "Media MIME outside the supported allowlist (incl. GIF/BMP/ICO).",
|
|
1886
|
+
contract: "none",
|
|
1887
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedMime
|
|
1613
1888
|
},
|
|
1614
|
-
{
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
table: {
|
|
1621
|
-
action: "insert-column-after",
|
|
1622
|
-
op: "insertColumn"
|
|
1623
|
-
},
|
|
1624
|
-
reason: TABLE_CONTEXT
|
|
1889
|
+
oversizedMediaPart: {
|
|
1890
|
+
family: "oversizedMediaPart",
|
|
1891
|
+
support: "fail-closed",
|
|
1892
|
+
description: "Media part exceeds the host byte-size policy before bytes are materialized.",
|
|
1893
|
+
contract: "none",
|
|
1894
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.imageTooLarge
|
|
1625
1895
|
},
|
|
1626
|
-
{
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
table: {
|
|
1633
|
-
action: "delete-column",
|
|
1634
|
-
op: "deleteColumn"
|
|
1635
|
-
},
|
|
1636
|
-
reason: TABLE_CONTEXT
|
|
1896
|
+
unsafeSvg: {
|
|
1897
|
+
family: "unsafeSvg",
|
|
1898
|
+
support: "fail-closed",
|
|
1899
|
+
description: "SVG content rejected by the SVG safety policy.",
|
|
1900
|
+
contract: "none",
|
|
1901
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsafeSvg
|
|
1637
1902
|
},
|
|
1638
|
-
{
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
table: {
|
|
1645
|
-
action: "delete-table",
|
|
1646
|
-
op: "delete"
|
|
1647
|
-
},
|
|
1648
|
-
reason: TABLE_CONTEXT
|
|
1903
|
+
metafileOrTiff: {
|
|
1904
|
+
family: "metafileOrTiff",
|
|
1905
|
+
support: "fail-closed",
|
|
1906
|
+
description: "EMF/WMF/TIFF and other non-browser-native formats with no approved conversion path.",
|
|
1907
|
+
contract: "none",
|
|
1908
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedFormat
|
|
1649
1909
|
},
|
|
1650
|
-
{
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
table: {
|
|
1657
|
-
action: "merge-cells",
|
|
1658
|
-
op: "mergeCells"
|
|
1659
|
-
},
|
|
1660
|
-
reason: TABLE_CONTEXT
|
|
1910
|
+
embeddedObject: {
|
|
1911
|
+
family: "embeddedObject",
|
|
1912
|
+
support: "fail-closed",
|
|
1913
|
+
description: "OLE / ActiveX / embedded package object.",
|
|
1914
|
+
contract: "none",
|
|
1915
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.embeddedObjectNotSupported
|
|
1661
1916
|
},
|
|
1662
|
-
{
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
table: {
|
|
1669
|
-
action: "split-cell",
|
|
1670
|
-
op: "splitCell",
|
|
1671
|
-
requiresCell: true
|
|
1672
|
-
},
|
|
1673
|
-
reason: TABLE_CONTEXT
|
|
1917
|
+
smartArtOrDiagram: {
|
|
1918
|
+
family: "smartArtOrDiagram",
|
|
1919
|
+
support: "fail-closed",
|
|
1920
|
+
description: "SmartArt / diagram / unknown external graphic-data object.",
|
|
1921
|
+
contract: "none",
|
|
1922
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedObject
|
|
1674
1923
|
},
|
|
1675
|
-
{
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
table: {
|
|
1682
|
-
action: "remove-borders",
|
|
1683
|
-
op: "setBorders"
|
|
1684
|
-
},
|
|
1685
|
-
reason: TABLE_CONTEXT
|
|
1924
|
+
vml: {
|
|
1925
|
+
family: "vml",
|
|
1926
|
+
support: "fail-closed",
|
|
1927
|
+
description: "VML structure outside any supported image-like subset (default fail-closed policy).",
|
|
1928
|
+
contract: "none",
|
|
1929
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.vmlUnsupported
|
|
1686
1930
|
},
|
|
1687
|
-
{
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
valueFrom: "ruler"
|
|
1931
|
+
vmlImageLike: {
|
|
1932
|
+
family: "vmlImageLike",
|
|
1933
|
+
support: "fail-closed",
|
|
1934
|
+
description: "Simple VML image references (v:imagedata) / watermark image metadata. Fail-closed unless a later change promotes a named subset with deterministic fixtures and exact oracles.",
|
|
1935
|
+
contract: "none",
|
|
1936
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.vmlImageUnsupported
|
|
1694
1937
|
},
|
|
1695
|
-
{
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
valueFrom: "formattingMarks"
|
|
1938
|
+
unsupportedGeometryCommand: {
|
|
1939
|
+
family: "unsupportedGeometryCommand",
|
|
1940
|
+
support: "fail-closed",
|
|
1941
|
+
description: "Custom geometry command the extractor does not implement, e.g. arcTo.",
|
|
1942
|
+
contract: "none",
|
|
1943
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedGeometryCommand
|
|
1702
1944
|
},
|
|
1703
|
-
{
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1945
|
+
unsupportedAnchorFields: {
|
|
1946
|
+
family: "unsupportedAnchorFields",
|
|
1947
|
+
support: "fail-closed",
|
|
1948
|
+
description: "Anchor fields required for honest placement are unsupported (char-relative, alignment modes, etc.).",
|
|
1949
|
+
contract: "none",
|
|
1950
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.anchorUnsupported
|
|
1708
1951
|
},
|
|
1709
|
-
{
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
if (!props || typeof props !== "object") return {};
|
|
1760
|
-
const patch = {};
|
|
1761
|
-
if (props.fonts) patch.rFonts = {
|
|
1762
|
-
ascii: props.fonts.ascii,
|
|
1763
|
-
hAnsi: props.fonts.hAnsi,
|
|
1764
|
-
eastAsia: props.fonts.eastAsia,
|
|
1765
|
-
cs: props.fonts.cs,
|
|
1766
|
-
asciiTheme: props.fonts.asciiTheme,
|
|
1767
|
-
hAnsiTheme: props.fonts.hAnsiTheme,
|
|
1768
|
-
eastAsiaTheme: props.fonts.eastAsiaTheme,
|
|
1769
|
-
csTheme: props.fonts.csTheme,
|
|
1770
|
-
hint: props.fonts.hint
|
|
1771
|
-
};
|
|
1772
|
-
if (props.fontFamily != null) patch.fontFamily = props.fontFamily;
|
|
1773
|
-
if (props.lang) patch.lang = {
|
|
1774
|
-
val: props.lang.val,
|
|
1775
|
-
eastAsia: props.lang.eastAsia,
|
|
1776
|
-
bidi: props.lang.bidi
|
|
1777
|
-
};
|
|
1778
|
-
if (props.fontSize != null) patch.fontSize = props.fontSize;
|
|
1779
|
-
if (props.fontSizeCs != null) patch.fontSizeCs = props.fontSizeCs;
|
|
1780
|
-
const color = projectColorRefToInlineColor(props.color);
|
|
1781
|
-
if (color != null) patch.color = color;
|
|
1782
|
-
if (props.highlight != null) patch.highlight = props.highlight;
|
|
1783
|
-
const shading = projectShadingToInlinePatch(props.shading);
|
|
1784
|
-
if (shading) patch.shading = shading;
|
|
1785
|
-
if (props.cs != null) patch.cs = props.cs;
|
|
1786
|
-
if (props.rtl != null) patch.rtl = props.rtl;
|
|
1787
|
-
if (props.bold != null) patch.bold = props.bold;
|
|
1788
|
-
if (props.boldCs != null) patch.bCs = props.boldCs;
|
|
1789
|
-
if (props.italic != null) patch.italic = props.italic;
|
|
1790
|
-
if (props.italicCs != null) patch.iCs = props.italicCs;
|
|
1791
|
-
const underline = projectUnderlineToInlinePatch(props.underline);
|
|
1792
|
-
if (underline !== void 0) patch.underline = underline;
|
|
1793
|
-
if (props.strikethrough != null) patch.strike = props.strikethrough;
|
|
1794
|
-
if (props.doubleStrikethrough != null) patch.dstrike = props.doubleStrikethrough;
|
|
1795
|
-
if (props.caps != null) patch.caps = props.caps;
|
|
1796
|
-
if (props.smallCaps != null) patch.smallCaps = props.smallCaps;
|
|
1797
|
-
if (props.outline != null) patch.outline = props.outline;
|
|
1798
|
-
if (props.shadow != null) patch.shadow = props.shadow;
|
|
1799
|
-
if (props.emboss != null) patch.emboss = props.emboss;
|
|
1800
|
-
if (props.imprint != null) patch.imprint = props.imprint;
|
|
1801
|
-
if (props.verticalAlign != null) patch.vertAlign = props.verticalAlign;
|
|
1802
|
-
if (props.characterSpacing != null) patch.letterSpacing = props.characterSpacing;
|
|
1803
|
-
if (props.characterScale != null) patch.charScale = props.characterScale;
|
|
1804
|
-
if (props.kern != null) patch.kerning = props.kern;
|
|
1805
|
-
if (props.baselineShift != null) patch.position = props.baselineShift;
|
|
1806
|
-
if (props.fitTextWidth != null) patch.fitText = { val: props.fitTextWidth };
|
|
1807
|
-
if (props.vanish != null) patch.vanish = props.vanish;
|
|
1808
|
-
if (props.webHidden != null) patch.webHidden = props.webHidden;
|
|
1809
|
-
if (props.specVanish != null) patch.specVanish = props.specVanish;
|
|
1810
|
-
const border = projectBorderToInlinePatch(props.border);
|
|
1811
|
-
if (border) patch.border = border;
|
|
1812
|
-
return patch;
|
|
1813
|
-
}
|
|
1814
|
-
function projectColorRefToInlineColor(color) {
|
|
1815
|
-
if (!color) return void 0;
|
|
1816
|
-
if (typeof color === "string") return color;
|
|
1817
|
-
if (color.model === "rgb") return color.value;
|
|
1818
|
-
if (color.model === "auto") return "auto";
|
|
1819
|
-
}
|
|
1820
|
-
function projectUnderlineToInlinePatch(underline) {
|
|
1821
|
-
if (underline == null) return void 0;
|
|
1822
|
-
const patch = {};
|
|
1823
|
-
if (underline.style != null) patch.style = underline.style;
|
|
1824
|
-
if (underline.color?.model === "rgb") patch.color = underline.color.value;
|
|
1825
|
-
if (underline.color?.model === "theme") patch.themeColor = underline.color.theme;
|
|
1826
|
-
return Object.keys(patch).length > 0 ? patch : true;
|
|
1827
|
-
}
|
|
1828
|
-
function projectShadingToInlinePatch(shading) {
|
|
1829
|
-
if (!shading) return void 0;
|
|
1830
|
-
const patch = {};
|
|
1831
|
-
const fill = projectColorRefToInlineColor(shading.fill);
|
|
1832
|
-
if (fill != null) patch.fill = fill;
|
|
1833
|
-
const color = projectColorRefToInlineColor(shading.color);
|
|
1834
|
-
if (color != null) patch.color = color;
|
|
1835
|
-
if (shading.pattern != null) patch.val = shading.pattern;
|
|
1836
|
-
return Object.keys(patch).length > 0 ? patch : void 0;
|
|
1837
|
-
}
|
|
1838
|
-
function projectBorderToInlinePatch(border) {
|
|
1839
|
-
if (!border) return void 0;
|
|
1840
|
-
const patch = {};
|
|
1841
|
-
if (border.style != null) patch.val = border.style;
|
|
1842
|
-
if (border.width != null) patch.sz = border.width;
|
|
1843
|
-
if (border.space != null) patch.space = border.space;
|
|
1844
|
-
const color = projectColorRefToInlineColor(border.color);
|
|
1845
|
-
if (color != null) patch.color = color;
|
|
1846
|
-
return Object.keys(patch).length > 0 ? patch : void 0;
|
|
1847
|
-
}
|
|
1848
|
-
/**
|
|
1849
|
-
* Serializes a selection to a stable string key used to detect whether
|
|
1850
|
-
* the target selection is the same as the source (skip apply in that case).
|
|
1851
|
-
*
|
|
1852
|
-
* Falls back to the plain text target when the host has not populated an
|
|
1853
|
-
* explicit `selectionTarget` yet.
|
|
1854
|
-
*
|
|
1855
|
-
* @param {{ selectionTarget?: unknown; target?: unknown } | null | undefined} selection
|
|
1856
|
-
* @returns {string}
|
|
1857
|
-
*/
|
|
1858
|
-
function selectionKey(selection) {
|
|
1859
|
-
const target = selection?.selectionTarget ?? selection?.target;
|
|
1860
|
-
if (!selection || !target) return "";
|
|
1861
|
-
try {
|
|
1862
|
-
return JSON.stringify(target);
|
|
1863
|
-
} catch {
|
|
1864
|
-
return String(target);
|
|
1952
|
+
unsupportedWrapFields: {
|
|
1953
|
+
family: "unsupportedWrapFields",
|
|
1954
|
+
support: "fail-closed",
|
|
1955
|
+
description: "Wrap fields required for honest placement are unsupported (arbitrary wrap polygons, etc.).",
|
|
1956
|
+
contract: "none",
|
|
1957
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.wrapUnsupported
|
|
1958
|
+
},
|
|
1959
|
+
alternateContentNoSupportedChoice: {
|
|
1960
|
+
family: "alternateContentNoSupportedChoice",
|
|
1961
|
+
support: "fail-closed",
|
|
1962
|
+
description: "mc:AlternateContent with no supported choice and no usable fallback.",
|
|
1963
|
+
contract: "none",
|
|
1964
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.altContentNoSupportedChoice
|
|
1965
|
+
},
|
|
1966
|
+
groupChildUnsupported: {
|
|
1967
|
+
family: "groupChildUnsupported",
|
|
1968
|
+
support: "fail-closed",
|
|
1969
|
+
description: "Unsupported child inside an otherwise-supported group. Supported siblings are not dropped.",
|
|
1970
|
+
contract: "none",
|
|
1971
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.groupChildUnsupported
|
|
1972
|
+
},
|
|
1973
|
+
objectEditing: {
|
|
1974
|
+
family: "objectEditing",
|
|
1975
|
+
support: "deferred",
|
|
1976
|
+
description: "Editing/mutation of anchored/vector objects.",
|
|
1977
|
+
contract: "none"
|
|
1978
|
+
},
|
|
1979
|
+
customWrapPolygon: {
|
|
1980
|
+
family: "customWrapPolygon",
|
|
1981
|
+
support: "deferred",
|
|
1982
|
+
description: "Full Word-compatible text wrapping for arbitrary custom wrap polygons.",
|
|
1983
|
+
contract: "none"
|
|
1984
|
+
},
|
|
1985
|
+
chartFidelity: {
|
|
1986
|
+
family: "chartFidelity",
|
|
1987
|
+
support: "deferred",
|
|
1988
|
+
description: "Complete chart fidelity (a dedicated chart effort owns the parsed subset).",
|
|
1989
|
+
contract: "none"
|
|
1990
|
+
},
|
|
1991
|
+
vmlFidelity: {
|
|
1992
|
+
family: "vmlFidelity",
|
|
1993
|
+
support: "deferred",
|
|
1994
|
+
description: "Complete VML fidelity.",
|
|
1995
|
+
contract: "none"
|
|
1996
|
+
},
|
|
1997
|
+
decorativeAccessibilityUi: {
|
|
1998
|
+
family: "decorativeAccessibilityUi",
|
|
1999
|
+
support: "deferred",
|
|
2000
|
+
description: "Full accessibility UI for decorative image semantics beyond preserving source data.",
|
|
2001
|
+
contract: "none"
|
|
1865
2002
|
}
|
|
1866
|
-
}
|
|
1867
|
-
//#endregion
|
|
1868
|
-
//#region src/helpers/v2-typing-mutation-event.js
|
|
1869
|
-
/**
|
|
1870
|
-
* Command kinds whose committed mutations belong to the sustained typing
|
|
1871
|
-
* cadence class (insert / replace / plain paste / Backspace / Delete).
|
|
1872
|
-
*
|
|
1873
|
-
* The SuperDoc shell debounces per-keystroke review-row hydration for these
|
|
1874
|
-
* kinds instead of refreshing comments + tracked changes on every commit —
|
|
1875
|
-
* hydrating immediately per keystroke was a measured worker-read storm during
|
|
1876
|
-
* typing and backspace bursts. The `text.*` aliases cover integrations that
|
|
1877
|
-
* forward Document API style command ids rather than editable-input kinds.
|
|
1878
|
-
*/
|
|
1879
|
-
var V2_TYPING_COMMAND_KINDS = /* @__PURE__ */ new Set([
|
|
1880
|
-
"insert-text",
|
|
1881
|
-
"replace-text",
|
|
1882
|
-
"plain-text-paste",
|
|
1883
|
-
"delete-backward",
|
|
1884
|
-
"delete-forward",
|
|
1885
|
-
"text.insert",
|
|
1886
|
-
"text.replace",
|
|
1887
|
-
"text.pastePlain",
|
|
1888
|
-
"text.deleteBackward",
|
|
1889
|
-
"text.deleteForward",
|
|
1890
|
-
"structural.enter",
|
|
1891
|
-
"structural:enter-split-paragraph",
|
|
1892
|
-
"structural:enter-insert-paragraph-before",
|
|
1893
|
-
"structural:enter-insert-paragraph-after",
|
|
1894
|
-
"structural:shift-enter-line-break",
|
|
1895
|
-
"structural:backspace-boundary-merge-with-previous",
|
|
1896
|
-
"structural:delete-boundary-merge-with-next",
|
|
1897
|
-
"backspace:boundary-merge-with-previous",
|
|
1898
|
-
"backspace:list-remove",
|
|
1899
|
-
"backspace:list-outdent"
|
|
1900
|
-
]);
|
|
1901
|
-
/**
|
|
1902
|
-
* True when a forwarded v2 host event is a committed editable-input mutation
|
|
1903
|
-
* of the sustained-typing class, i.e. review-row hydration for it should be
|
|
1904
|
-
* debounced rather than fired immediately.
|
|
1905
|
-
*
|
|
1906
|
-
* Events without a forwarded `editableCommandKind` (programmatic Document API
|
|
1907
|
-
* mutations, history commits, unclassified structural commands) return false
|
|
1908
|
-
* so they keep hydrating immediately.
|
|
1909
|
-
*
|
|
1910
|
-
* @param {{ type?: string, origin?: string, editableCommandKind?: string } | null | undefined} event
|
|
1911
|
-
* @returns {boolean}
|
|
1912
|
-
*/
|
|
1913
|
-
var isV2EditableTextMutationEvent = (event) => {
|
|
1914
|
-
if (event?.type !== "mutation:committed" || event.origin !== "command") return false;
|
|
1915
|
-
return V2_TYPING_COMMAND_KINDS.has(event.editableCommandKind);
|
|
1916
2003
|
};
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
/**
|
|
1944
|
-
* Read painted entities off `el` and every ancestor up to the document root, or
|
|
1945
|
-
* up to and INCLUDING `stopAt` when given. Innermost-first ordering: a tracked
|
|
1946
|
-
* change inside a comment highlight returns `[{ trackedChange }, { comment }]`,
|
|
1947
|
-
* matching what a switch on `hits[0]` expects when picking the most specific
|
|
1948
|
-
* entity.
|
|
1949
|
-
*
|
|
1950
|
-
* `stopAt` bounds the walk to the visible host: its own attributes are read, but
|
|
1951
|
-
* the walk never climbs into an app wrapper ABOVE it, so wrapper data-* cannot
|
|
1952
|
-
* leak into the hits. Omitting it keeps the original walk-to-document-root.
|
|
1953
|
-
*
|
|
1954
|
-
* Returns `[]` for null / non-Element starts. Uses duck-typed `getAttribute`
|
|
1955
|
-
* access so it works under any DOM implementation (happy-dom, jsdom, real
|
|
1956
|
-
* browser) without an `instanceof` check that could fail across realms.
|
|
1957
|
-
*/
|
|
1958
|
-
function collectEntityHitsFromChain(start, stopAt) {
|
|
1959
|
-
if (!start || typeof start.getAttribute !== "function") return [];
|
|
1960
|
-
const hits = [];
|
|
1961
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1962
|
-
let pendingStory = [];
|
|
1963
|
-
let el = start;
|
|
1964
|
-
while (el) {
|
|
1965
|
-
const node = el;
|
|
1966
|
-
const trackChangeIds = getTrackChangeIds(node);
|
|
1967
|
-
const storyKey = trackChangeIds.length > 0 ? node.getAttribute("data-story-key") : null;
|
|
1968
|
-
for (const trackChangeId of trackChangeIds) {
|
|
1969
|
-
const key = `trackedChange:${trackChangeId}`;
|
|
1970
|
-
if (!seen.has(key)) {
|
|
1971
|
-
seen.add(key);
|
|
1972
|
-
const hit = {
|
|
1973
|
-
type: "trackedChange",
|
|
1974
|
-
id: trackChangeId
|
|
1975
|
-
};
|
|
1976
|
-
if (storyKey) hit.storyKey = storyKey;
|
|
1977
|
-
hits.push(hit);
|
|
1978
|
-
pendingStory.push(hit);
|
|
1979
|
-
}
|
|
1980
|
-
}
|
|
1981
|
-
const layoutStory = node.getAttribute("data-layout-story");
|
|
1982
|
-
if (layoutStory && pendingStory.length > 0) {
|
|
1983
|
-
for (const hit of pendingStory) hit.story = layoutStory;
|
|
1984
|
-
pendingStory = [];
|
|
1985
|
-
}
|
|
1986
|
-
const citationId = node.getAttribute("data-citation-id");
|
|
1987
|
-
if (citationId) {
|
|
1988
|
-
const key = `citation:${citationId}`;
|
|
1989
|
-
if (!seen.has(key)) {
|
|
1990
|
-
seen.add(key);
|
|
1991
|
-
hits.push({
|
|
1992
|
-
type: "citation",
|
|
1993
|
-
id: citationId
|
|
1994
|
-
});
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
const commentIds = node.getAttribute("data-comment-ids");
|
|
1998
|
-
if (commentIds) for (const id of parseCommaSeparatedIds(commentIds)) {
|
|
1999
|
-
const key = `comment:${id}`;
|
|
2000
|
-
if (!seen.has(key)) {
|
|
2001
|
-
seen.add(key);
|
|
2002
|
-
hits.push({
|
|
2003
|
-
type: "comment",
|
|
2004
|
-
id
|
|
2005
|
-
});
|
|
2006
|
-
}
|
|
2007
|
-
}
|
|
2008
|
-
const sdtType = node.getAttribute("data-sdt-type");
|
|
2009
|
-
const sdtId = node.getAttribute("data-sdt-id");
|
|
2010
|
-
if (sdtId && sdtType === "structuredContent") {
|
|
2011
|
-
const key = `contentControl:${sdtId}`;
|
|
2012
|
-
if (!seen.has(key)) {
|
|
2013
|
-
seen.add(key);
|
|
2014
|
-
const scopeAttr = node.getAttribute("data-sdt-scope");
|
|
2015
|
-
const tag = node.getAttribute("data-sdt-tag");
|
|
2016
|
-
const hit = {
|
|
2017
|
-
type: "contentControl",
|
|
2018
|
-
id: sdtId
|
|
2019
|
-
};
|
|
2020
|
-
if (scopeAttr === "block" || scopeAttr === "inline") hit.scope = scopeAttr;
|
|
2021
|
-
if (tag) hit.tag = tag;
|
|
2022
|
-
hits.push(hit);
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
if (stopAt && el === stopAt) break;
|
|
2026
|
-
el = el.parentElement;
|
|
2027
|
-
}
|
|
2028
|
-
return hits;
|
|
2029
|
-
}
|
|
2004
|
+
Object.keys(DRAWING_SUPPORT_TAXONOMY);
|
|
2005
|
+
Object.freeze([
|
|
2006
|
+
"multiple-sections",
|
|
2007
|
+
"furniture-page-tokens",
|
|
2008
|
+
"non-balanceable-multi-column-sections",
|
|
2009
|
+
"body-anchored-objects",
|
|
2010
|
+
"non-flowing-page-relative-body-anchors",
|
|
2011
|
+
"footnotes",
|
|
2012
|
+
"page-references",
|
|
2013
|
+
"cross-references",
|
|
2014
|
+
"keep-constraints",
|
|
2015
|
+
"tables",
|
|
2016
|
+
"furniture-anchored-objects"
|
|
2017
|
+
]);
|
|
2018
|
+
var INCREMENTAL_DEPENDENCY_CERTIFICATE_CLASSES = Object.freeze([
|
|
2019
|
+
"checkpoint-geometry",
|
|
2020
|
+
"section-numbering",
|
|
2021
|
+
"font-style-inputs",
|
|
2022
|
+
"notes",
|
|
2023
|
+
"furniture",
|
|
2024
|
+
"flowing-anchors",
|
|
2025
|
+
"non-flowing-page-anchors",
|
|
2026
|
+
"convergence",
|
|
2027
|
+
"source-topology"
|
|
2028
|
+
]);
|
|
2029
|
+
new Set(INCREMENTAL_DEPENDENCY_CERTIFICATE_CLASSES);
|
|
2030
2030
|
//#endregion
|
|
2031
2031
|
//#region ../document-api/src/format/inline-run-patch.ts
|
|
2032
2032
|
var schemaBooleanOrNull = () => ({ oneOf: [{ type: "boolean" }, { type: "null" }] });
|
|
@@ -2295,6 +2295,19 @@ INLINE_PROPERTY_REGISTRY.filter((entry) => entry.storage === "mark").map((entry)
|
|
|
2295
2295
|
* `false` when the surface is unavailable (view mode, a pre-ready editor, or a
|
|
2296
2296
|
* host that has not exposed a Document API facade) rather than throwing.
|
|
2297
2297
|
*/
|
|
2298
|
+
var firstPartyCommandMutations = /* @__PURE__ */ new WeakMap();
|
|
2299
|
+
var firstPartyCommandExecutors = /* @__PURE__ */ new WeakMap();
|
|
2300
|
+
function registerFirstPartyCommandMutation(superdoc, host, mutation) {
|
|
2301
|
+
let hosts = firstPartyCommandMutations.get(superdoc);
|
|
2302
|
+
if (!hosts) {
|
|
2303
|
+
hosts = /* @__PURE__ */ new WeakMap();
|
|
2304
|
+
firstPartyCommandMutations.set(superdoc, hosts);
|
|
2305
|
+
}
|
|
2306
|
+
hosts.set(host, mutation);
|
|
2307
|
+
}
|
|
2308
|
+
function executeFirstPartyCommandAsync(ui, id, payload) {
|
|
2309
|
+
return firstPartyCommandExecutors.get(ui)?.(id, payload) ?? ui.commands.executeAsync(id, payload);
|
|
2310
|
+
}
|
|
2298
2311
|
function uiBenchNowMs() {
|
|
2299
2312
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
2300
2313
|
}
|
|
@@ -3915,6 +3928,7 @@ function createSuperDocUI(options) {
|
|
|
3915
3928
|
keyboardSelecting: false
|
|
3916
3929
|
};
|
|
3917
3930
|
let painterCaptureEpoch = 0;
|
|
3931
|
+
let painterCommandDoc = null;
|
|
3918
3932
|
const painterModeListeners = /* @__PURE__ */ new Set();
|
|
3919
3933
|
let frozenProjectedValues = {};
|
|
3920
3934
|
let frozenProjectedValuesKey = "";
|
|
@@ -3964,8 +3978,10 @@ function createSuperDocUI(options) {
|
|
|
3964
3978
|
},
|
|
3965
3979
|
contextAt
|
|
3966
3980
|
};
|
|
3981
|
+
let firstPartyCommandDoc;
|
|
3967
3982
|
/** Read the live browser Document API facade (or null). */
|
|
3968
3983
|
const getDoc = () => {
|
|
3984
|
+
if (firstPartyCommandDoc !== void 0) return firstPartyCommandDoc;
|
|
3969
3985
|
const doc = getEditor()?.doc;
|
|
3970
3986
|
return doc && typeof doc === "object" ? doc : null;
|
|
3971
3987
|
};
|
|
@@ -3996,6 +4012,25 @@ function createSuperDocUI(options) {
|
|
|
3996
4012
|
const host = getEditor()?.host;
|
|
3997
4013
|
return host && typeof host === "object" ? host : null;
|
|
3998
4014
|
};
|
|
4015
|
+
const createFirstPartyCommandDoc = () => {
|
|
4016
|
+
const editor = getEditor();
|
|
4017
|
+
const doc = editor?.doc;
|
|
4018
|
+
if (editor?.editorVersion !== 2) return doc;
|
|
4019
|
+
const host = getHost();
|
|
4020
|
+
const mutation = host ? firstPartyCommandMutations.get(superdoc)?.get(host) : null;
|
|
4021
|
+
if (!doc || !host || !mutation) return null;
|
|
4022
|
+
const wrap = (source, prefix) => new Proxy(source, { get(target, key, receiver) {
|
|
4023
|
+
const value = Reflect.get(target, key, receiver);
|
|
4024
|
+
if (typeof key !== "string") return value;
|
|
4025
|
+
const memberPath = prefix ? `${prefix}.${key}` : key;
|
|
4026
|
+
if (typeof value === "function" && mutation.supports(memberPath)) return (...args) => {
|
|
4027
|
+
if (getEditor() !== editor || getHost() !== host || editor.doc !== doc) return false;
|
|
4028
|
+
return mutation.run(memberPath, args);
|
|
4029
|
+
};
|
|
4030
|
+
return value && (typeof value === "object" || typeof value === "function") ? wrap(value, memberPath) : value;
|
|
4031
|
+
} });
|
|
4032
|
+
return wrap(doc, "");
|
|
4033
|
+
};
|
|
3999
4034
|
const resolveActiveHeaderFooterSlot = (story) => {
|
|
4000
4035
|
if (story.storyType !== "headerFooterPart" || typeof story.refId !== "string") return null;
|
|
4001
4036
|
const editor = getEditor();
|
|
@@ -7994,7 +8029,10 @@ function createSuperDocUI(options) {
|
|
|
7994
8029
|
function executeListToggleCommand(kind, payload) {
|
|
7995
8030
|
const lists = getEditCommands()?.lists;
|
|
7996
8031
|
const apply = lists?.apply;
|
|
7997
|
-
|
|
8032
|
+
const host = getHost();
|
|
8033
|
+
const firstPartyMutation = firstPartyCommandDoc !== void 0 && getEditor()?.editorVersion === 2 && host ? firstPartyCommandMutations.get(superdoc)?.get(host) : null;
|
|
8034
|
+
if (firstPartyCommandDoc !== void 0 && getEditor()?.editorVersion === 2 && !firstPartyMutation) return false;
|
|
8035
|
+
if (!firstPartyMutation && typeof apply !== "function") return false;
|
|
7998
8036
|
const { behavior, preset, continuity } = typeof payload === "string" ? presetFromToolbarStyleKey(payload) : payload && typeof payload === "object" ? payload : {};
|
|
7999
8037
|
const input = {
|
|
8000
8038
|
kind,
|
|
@@ -8003,7 +8041,7 @@ function createSuperDocUI(options) {
|
|
|
8003
8041
|
if (preset !== void 0) input.preset = preset;
|
|
8004
8042
|
if (continuity !== void 0) input.continuity = continuity;
|
|
8005
8043
|
try {
|
|
8006
|
-
return settleCommandExecution(apply.call(lists, input));
|
|
8044
|
+
return settleCommandExecution(firstPartyMutation ? firstPartyMutation.runListApply(input) : apply.call(lists, input));
|
|
8007
8045
|
} catch {
|
|
8008
8046
|
return false;
|
|
8009
8047
|
}
|
|
@@ -8626,7 +8664,8 @@ function createSuperDocUI(options) {
|
|
|
8626
8664
|
const linksApi = doc?.hyperlinks;
|
|
8627
8665
|
if (!linksApi) return false;
|
|
8628
8666
|
const hyperlinkHost = getHost();
|
|
8629
|
-
const
|
|
8667
|
+
const hyperlinkHandles = typeof hyperlinkHost?.getHandles === "function" ? hyperlinkHost.getHandles() : null;
|
|
8668
|
+
const trustedLinksApi = firstPartyCommandDoc ? (hyperlinkHandles?.editing)?.hyperlinks : linksApi;
|
|
8630
8669
|
const record = readLinkPayloadRecord(payload);
|
|
8631
8670
|
const href = readLinkPayloadHref(payload);
|
|
8632
8671
|
const payloadTarget = readLinkPayloadTarget(payload);
|
|
@@ -8838,10 +8877,12 @@ function createSuperDocUI(options) {
|
|
|
8838
8877
|
if (typeof record.title === "string") input.title = record.title;
|
|
8839
8878
|
if (record.size && typeof record.size === "object") input.size = record.size;
|
|
8840
8879
|
const imageHost = getHost();
|
|
8841
|
-
const
|
|
8842
|
-
|
|
8880
|
+
const imageHandles = typeof imageHost?.getHandles === "function" ? imageHost.getHandles() : null;
|
|
8881
|
+
const trustedImageCommands = firstPartyCommandDoc ? (imageHandles?.editing)?.images : null;
|
|
8882
|
+
const create = firstPartyCommandDoc ? trustedImageCommands?.create : op;
|
|
8883
|
+
if (typeof create !== "function") return false;
|
|
8843
8884
|
try {
|
|
8844
|
-
return callEditorMutation(descriptor.docRoute,
|
|
8885
|
+
return callEditorMutation(descriptor.docRoute, create, input);
|
|
8845
8886
|
} catch {
|
|
8846
8887
|
return false;
|
|
8847
8888
|
}
|
|
@@ -8855,6 +8896,13 @@ function createSuperDocUI(options) {
|
|
|
8855
8896
|
return false;
|
|
8856
8897
|
}
|
|
8857
8898
|
};
|
|
8899
|
+
const tableInsertionCommands = () => {
|
|
8900
|
+
if (firstPartyCommandDoc === null) return null;
|
|
8901
|
+
const host = getHost();
|
|
8902
|
+
if (!host) return null;
|
|
8903
|
+
if (firstPartyCommandDoc !== void 0) return ((typeof host.getHandles === "function" ? host.getHandles() : null)?.editing)?.tables ?? null;
|
|
8904
|
+
return typeof host.getCodeTableEditingCommands === "function" ? host.getCodeTableEditingCommands() : null;
|
|
8905
|
+
};
|
|
8858
8906
|
/**
|
|
8859
8907
|
* Route a table cell-context command (`tables.*`) against the live table
|
|
8860
8908
|
* context resolved from the shared facade. Fails closed (`false`) when the
|
|
@@ -8871,16 +8919,14 @@ function createSuperDocUI(options) {
|
|
|
8871
8919
|
if (!input) return false;
|
|
8872
8920
|
try {
|
|
8873
8921
|
if (spec.action === "insert-row-before" || spec.action === "insert-row-after") {
|
|
8874
|
-
const
|
|
8875
|
-
const tableCommands = ((typeof host?.getHandles === "function" ? host.getHandles() : null)?.editing)?.tables;
|
|
8922
|
+
const tableCommands = tableInsertionCommands();
|
|
8876
8923
|
if (typeof tableCommands?.insertRow !== "function") return false;
|
|
8877
8924
|
const options = editorMutationOptionsForRoute(descriptor.docRoute);
|
|
8878
8925
|
if (options && options.success === false) return options;
|
|
8879
8926
|
return options ? tableCommands.insertRow(input, options) : tableCommands.insertRow(input);
|
|
8880
8927
|
}
|
|
8881
8928
|
if (spec.action === "insert-column-before" || spec.action === "insert-column-after") {
|
|
8882
|
-
const
|
|
8883
|
-
const tableCommands = ((typeof host?.getHandles === "function" ? host.getHandles() : null)?.editing)?.tables;
|
|
8929
|
+
const tableCommands = tableInsertionCommands();
|
|
8884
8930
|
if (typeof tableCommands?.insertColumn !== "function") return false;
|
|
8885
8931
|
const options = editorMutationOptionsForRoute(descriptor.docRoute);
|
|
8886
8932
|
if (options && options.success === false) return options;
|
|
@@ -8979,9 +9025,10 @@ function createSuperDocUI(options) {
|
|
|
8979
9025
|
let releaseScheduledMutation = null;
|
|
8980
9026
|
try {
|
|
8981
9027
|
const commandEditor = getEditor();
|
|
9028
|
+
const commandDocSource = commandEditor?.doc;
|
|
8982
9029
|
const commandMode = readDocumentMode();
|
|
8983
9030
|
const mutate = () => {
|
|
8984
|
-
if (getEditor() !== commandEditor ||
|
|
9031
|
+
if (getEditor() !== commandEditor || commandEditor?.doc !== commandDocSource || readDocumentMode() !== commandMode) return false;
|
|
8985
9032
|
return callInlineFormatMutation(route, op, input);
|
|
8986
9033
|
};
|
|
8987
9034
|
const selectionSignature = selectionInlineValueSignature(state.selection) ?? selectionKey(state.selection);
|
|
@@ -9031,12 +9078,14 @@ function createSuperDocUI(options) {
|
|
|
9031
9078
|
return false;
|
|
9032
9079
|
}
|
|
9033
9080
|
};
|
|
9034
|
-
const
|
|
9081
|
+
const runCommand = (id, payload, context, firstParty) => {
|
|
9035
9082
|
const actionId = beginInteraction(superdoc, "command:started", () => ({
|
|
9036
9083
|
commandId: id,
|
|
9037
9084
|
selection: state.selection
|
|
9038
9085
|
}));
|
|
9039
9086
|
let result;
|
|
9087
|
+
const previousCommandDoc = firstPartyCommandDoc;
|
|
9088
|
+
firstPartyCommandDoc = firstParty && !customCommands.has(id) ? createFirstPartyCommandDoc() : void 0;
|
|
9040
9089
|
try {
|
|
9041
9090
|
result = executeCommandInternal(id, payload, context);
|
|
9042
9091
|
} catch (error) {
|
|
@@ -9046,6 +9095,8 @@ function createSuperDocUI(options) {
|
|
|
9046
9095
|
outcome: "threw"
|
|
9047
9096
|
}));
|
|
9048
9097
|
throw error;
|
|
9098
|
+
} finally {
|
|
9099
|
+
firstPartyCommandDoc = previousCommandDoc;
|
|
9049
9100
|
}
|
|
9050
9101
|
const settled = (value) => recordInteraction(superdoc, "command:settled", () => ({
|
|
9051
9102
|
actionId,
|
|
@@ -9059,8 +9110,10 @@ function createSuperDocUI(options) {
|
|
|
9059
9110
|
} catch {}
|
|
9060
9111
|
return result;
|
|
9061
9112
|
};
|
|
9113
|
+
const executeCommand = (id, payload, context) => runCommand(id, payload, context, false);
|
|
9062
9114
|
const exitFormatPainter = () => {
|
|
9063
9115
|
painterCaptureEpoch += 1;
|
|
9116
|
+
painterCommandDoc = null;
|
|
9064
9117
|
painter = {
|
|
9065
9118
|
mode: "idle",
|
|
9066
9119
|
snapshot: null,
|
|
@@ -9073,6 +9126,7 @@ function createSuperDocUI(options) {
|
|
|
9073
9126
|
recompute();
|
|
9074
9127
|
};
|
|
9075
9128
|
const executeCopyFormat = async () => {
|
|
9129
|
+
const commandDoc = firstPartyCommandDoc ?? null;
|
|
9076
9130
|
const visibleActiveMarksAtClick = [
|
|
9077
9131
|
"bold",
|
|
9078
9132
|
"italic",
|
|
@@ -9115,6 +9169,7 @@ function createSuperDocUI(options) {
|
|
|
9115
9169
|
sourceSelectionKey: selectionKey(captureSlice),
|
|
9116
9170
|
lastClickAt: now
|
|
9117
9171
|
};
|
|
9172
|
+
painterCommandDoc = commandDoc;
|
|
9118
9173
|
for (const cb of painterModeListeners) cb(painter.mode);
|
|
9119
9174
|
recompute();
|
|
9120
9175
|
return true;
|
|
@@ -9298,7 +9353,7 @@ function createSuperDocUI(options) {
|
|
|
9298
9353
|
if (painter.mode === "armed") exitFormatPainter();
|
|
9299
9354
|
return;
|
|
9300
9355
|
}
|
|
9301
|
-
const doc = getDoc();
|
|
9356
|
+
const doc = painterCommandDoc ?? getDoc();
|
|
9302
9357
|
if (!doc) return;
|
|
9303
9358
|
const targetSelection = selectionSliceFromInfo(selection, "ready");
|
|
9304
9359
|
const { lockModesById } = computeActiveContentControlLockModes(doc.contentControls, targetSelection);
|
|
@@ -9403,18 +9458,20 @@ function createSuperDocUI(options) {
|
|
|
9403
9458
|
if (painter.mode === "armed") exitFormatPainter();
|
|
9404
9459
|
recompute();
|
|
9405
9460
|
};
|
|
9406
|
-
const
|
|
9461
|
+
const runCommandAsync = (id, payload, context, firstParty) => {
|
|
9407
9462
|
const prepared = prepareCommandSelectionAsync(id, payload);
|
|
9408
9463
|
const settlement = prepared ? prepared.then(() => {
|
|
9409
|
-
|
|
9464
|
+
runCommand(id, payload, context, firstParty);
|
|
9410
9465
|
return lastCommandSettlement;
|
|
9411
9466
|
}) : (() => {
|
|
9412
|
-
|
|
9467
|
+
runCommand(id, payload, context, firstParty);
|
|
9413
9468
|
return lastCommandSettlement;
|
|
9414
9469
|
})();
|
|
9415
9470
|
if (getCommandDescriptor(id)?.inline?.kind === "toggle") lastInlineToggleCommandSettlement = settlement;
|
|
9416
9471
|
return settlement;
|
|
9417
9472
|
};
|
|
9473
|
+
const executeCommandAsync = (id, payload, context) => runCommandAsync(id, payload, context, false);
|
|
9474
|
+
const executeFirstPartyCommandAsync = (id, payload) => runCommandAsync(id, payload, void 0, true);
|
|
9418
9475
|
const makeCommandHandle = (id) => ({
|
|
9419
9476
|
id,
|
|
9420
9477
|
getState: () => state.toolbar.commands[id] ?? computeCommandState(id, getDoc(), state.selection, projectSelectionInlineValues(state.selection)),
|
|
@@ -10251,6 +10308,14 @@ function createSuperDocUI(options) {
|
|
|
10251
10308
|
kind,
|
|
10252
10309
|
scope: isAllTarget ? "all" : "id"
|
|
10253
10310
|
}, tcApi)) return false;
|
|
10311
|
+
if (firstPartyCommandDoc) {
|
|
10312
|
+
const host = getHost();
|
|
10313
|
+
const decide = (safeCall(typeof host?.getHandles === "function" ? () => host.getHandles() : void 0, null)?.trackChanges)?.decide;
|
|
10314
|
+
return typeof decide === "function" ? decide({
|
|
10315
|
+
decision: kind,
|
|
10316
|
+
target
|
|
10317
|
+
}) : false;
|
|
10318
|
+
}
|
|
10254
10319
|
const legacyName = isAllTarget ? `${kind}All` : kind;
|
|
10255
10320
|
const op = !isRangeTarget && !isMultiIdTarget && !story && tcApi && typeof tcApi[legacyName] === "function" ? tcApi[legacyName] : null;
|
|
10256
10321
|
const decide = tcApi && typeof tcApi.decide === "function" ? tcApi.decide : null;
|
|
@@ -11527,6 +11592,7 @@ function createSuperDocUI(options) {
|
|
|
11527
11592
|
listeners.clear();
|
|
11528
11593
|
searchListeners.clear();
|
|
11529
11594
|
painterCaptureEpoch += 1;
|
|
11595
|
+
painterCommandDoc = null;
|
|
11530
11596
|
painterModeListeners.clear();
|
|
11531
11597
|
searchRequestGeneration += 1;
|
|
11532
11598
|
customCommands.clear();
|
|
@@ -11596,6 +11662,7 @@ function createSuperDocUI(options) {
|
|
|
11596
11662
|
destroy
|
|
11597
11663
|
};
|
|
11598
11664
|
controllerRef = controller;
|
|
11665
|
+
firstPartyCommandExecutors.set(controller, executeFirstPartyCommandAsync);
|
|
11599
11666
|
return controller;
|
|
11600
11667
|
}
|
|
11601
11668
|
/**
|
|
@@ -11797,6 +11864,12 @@ Object.defineProperty(exports, "createSuperDocUI", {
|
|
|
11797
11864
|
return createSuperDocUI;
|
|
11798
11865
|
}
|
|
11799
11866
|
});
|
|
11867
|
+
Object.defineProperty(exports, "executeFirstPartyCommandAsync", {
|
|
11868
|
+
enumerable: true,
|
|
11869
|
+
get: function() {
|
|
11870
|
+
return executeFirstPartyCommandAsync;
|
|
11871
|
+
}
|
|
11872
|
+
});
|
|
11800
11873
|
Object.defineProperty(exports, "getV2TrackedChangeMutationImpact", {
|
|
11801
11874
|
enumerable: true,
|
|
11802
11875
|
get: function() {
|
|
@@ -11809,6 +11882,12 @@ Object.defineProperty(exports, "recordInteraction", {
|
|
|
11809
11882
|
return recordInteraction;
|
|
11810
11883
|
}
|
|
11811
11884
|
});
|
|
11885
|
+
Object.defineProperty(exports, "registerFirstPartyCommandMutation", {
|
|
11886
|
+
enumerable: true,
|
|
11887
|
+
get: function() {
|
|
11888
|
+
return registerFirstPartyCommandMutation;
|
|
11889
|
+
}
|
|
11890
|
+
});
|
|
11812
11891
|
Object.defineProperty(exports, "shallowEqual", {
|
|
11813
11892
|
enumerable: true,
|
|
11814
11893
|
get: function() {
|