@beyondwork/docx-react-component 1.0.102 → 1.0.104
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/package.json +1 -1
- package/src/api/public-types.ts +63 -1
- package/src/api/v3/_runtime-handle.ts +2 -0
- package/src/api/v3/ai/outline.ts +2 -7
- package/src/api/v3/runtime/geometry.ts +79 -0
- package/src/core/commands/formatting-commands.ts +8 -7
- package/src/core/commands/paragraph-layout-commands.ts +11 -10
- package/src/core/commands/section-layout-commands.ts +7 -6
- package/src/core/commands/style-commands.ts +3 -2
- package/src/io/normalize/normalize-text.ts +6 -5
- package/src/io/ooxml/parse-anchor.ts +15 -15
- package/src/io/ooxml/parse-drawing.ts +103 -5
- package/src/io/ooxml/parse-fields.ts +43 -21
- package/src/io/ooxml/parse-font-table.ts +2 -1
- package/src/io/ooxml/parse-footnotes.ts +3 -2
- package/src/io/ooxml/parse-headers-footers.ts +7 -6
- package/src/io/ooxml/parse-main-document.ts +41 -40
- package/src/io/ooxml/parse-numbering.ts +3 -2
- package/src/io/ooxml/parse-object.ts +6 -6
- package/src/io/ooxml/parse-paragraph-formatting.ts +12 -11
- package/src/io/ooxml/parse-picture.ts +16 -16
- package/src/io/ooxml/parse-run-formatting.ts +11 -10
- package/src/io/ooxml/parse-settings.ts +2 -1
- package/src/io/ooxml/parse-shapes.ts +148 -17
- package/src/io/ooxml/parse-styles.ts +16 -16
- package/src/io/ooxml/parse-theme.ts +5 -4
- package/src/model/canonical-document.ts +869 -836
- package/src/model/canonical-layout-inputs.ts +979 -0
- package/src/model/layout/index.ts +6 -0
- package/src/model/layout/page-graph-types.ts +61 -0
- package/src/model/layout/runtime-page-graph-types.ts +10 -0
- package/src/runtime/collab/runtime-collab-sync.ts +3 -3
- package/src/runtime/debug/build-debug-inspector-snapshot.ts +17 -4
- package/src/runtime/document-runtime.ts +30 -14
- package/src/runtime/event-refresh-hints.ts +3 -0
- package/src/runtime/formatting/document-lookup.ts +3 -2
- package/src/runtime/formatting/formatting-context.ts +176 -34
- package/src/runtime/formatting/index.ts +20 -0
- package/src/runtime/formatting/layout-inputs.ts +320 -0
- package/src/runtime/formatting/numbering/geometry.ts +13 -12
- package/src/runtime/formatting/style-cascade.ts +2 -1
- package/src/runtime/formatting/table-style-resolver.ts +8 -7
- package/src/runtime/geometry/caret-geometry.ts +82 -10
- package/src/runtime/geometry/geometry-facet.ts +36 -0
- package/src/runtime/geometry/geometry-index.ts +891 -0
- package/src/runtime/geometry/geometry-types.ts +221 -1
- package/src/runtime/geometry/index.ts +26 -0
- package/src/runtime/geometry/inert-geometry-facet.ts +3 -0
- package/src/runtime/geometry/replacement-envelope.ts +41 -2
- package/src/runtime/layout/layout-engine-version.ts +16 -1
- package/src/runtime/layout/page-graph.ts +191 -1
- package/src/runtime/prerender/graph-canonicalize.ts +30 -0
- package/src/runtime/surface-projection.ts +74 -39
- package/src/runtime/workflow/coordinator.ts +57 -11
- package/src/session/import/normalize.ts +2 -1
- package/src/session/import/source-package-evidence.ts +612 -1
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +3 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
RuntimeBlockFragment,
|
|
3
3
|
RuntimePageAnchor,
|
|
4
|
+
RuntimePageFrame,
|
|
4
5
|
RuntimePageGraph,
|
|
5
6
|
RuntimePageNode,
|
|
6
7
|
RuntimePageRegion,
|
|
@@ -54,6 +55,9 @@ export function canonicalizeGraph(graph: RuntimePageGraph): RuntimePageGraph {
|
|
|
54
55
|
...page,
|
|
55
56
|
pageId: rewriteId(page.pageId),
|
|
56
57
|
regions: rewriteRegions(page.regions, rewriteId),
|
|
58
|
+
...(page.frame === undefined
|
|
59
|
+
? {}
|
|
60
|
+
: { frame: rewriteFrame(page.frame, rewriteId) }),
|
|
57
61
|
lineBoxes: page.lineBoxes.map((line) => ({
|
|
58
62
|
...line,
|
|
59
63
|
fragmentId: rewriteId(line.fragmentId),
|
|
@@ -86,6 +90,32 @@ export function canonicalizeGraph(graph: RuntimePageGraph): RuntimePageGraph {
|
|
|
86
90
|
};
|
|
87
91
|
}
|
|
88
92
|
|
|
93
|
+
function rewriteFrame(
|
|
94
|
+
frame: RuntimePageFrame,
|
|
95
|
+
rewriteId: (id: string) => string,
|
|
96
|
+
): RuntimePageFrame {
|
|
97
|
+
return {
|
|
98
|
+
...frame,
|
|
99
|
+
pageId: rewriteId(frame.pageId),
|
|
100
|
+
regions: {
|
|
101
|
+
...frame.regions,
|
|
102
|
+
body: rewriteRegion(frame.regions.body, rewriteId),
|
|
103
|
+
...(frame.regions.header
|
|
104
|
+
? { header: rewriteRegion(frame.regions.header, rewriteId) }
|
|
105
|
+
: {}),
|
|
106
|
+
...(frame.regions.footer
|
|
107
|
+
? { footer: rewriteRegion(frame.regions.footer, rewriteId) }
|
|
108
|
+
: {}),
|
|
109
|
+
...(frame.regions.columns
|
|
110
|
+
? { columns: frame.regions.columns.map((region) => rewriteRegion(region, rewriteId)) }
|
|
111
|
+
: {}),
|
|
112
|
+
...(frame.regions.footnotes
|
|
113
|
+
? { footnotes: frame.regions.footnotes.map((region) => rewriteRegion(region, rewriteId)) }
|
|
114
|
+
: {}),
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
89
119
|
function rewriteRegions(
|
|
90
120
|
regions: RuntimePageRegions,
|
|
91
121
|
rewriteId: (id: string) => string,
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
SurfaceDrawingAnchor,
|
|
7
7
|
SurfaceInlineSegment,
|
|
8
8
|
SurfacePictureEffects,
|
|
9
|
+
SurfacePreserveOnlyObjectSizing,
|
|
9
10
|
SurfaceTableCellSnapshot,
|
|
10
11
|
SurfaceTableRowSnapshot,
|
|
11
12
|
SurfaceTextMark,
|
|
@@ -38,9 +39,11 @@ import type {
|
|
|
38
39
|
TextMark,
|
|
39
40
|
DrawingFrameNode,
|
|
40
41
|
PictureContent,
|
|
42
|
+
PreserveOnlyObjectSizing,
|
|
41
43
|
ShapeContent,
|
|
42
44
|
VmlShapeNode,
|
|
43
45
|
WordArtNode,
|
|
46
|
+
Mutable,
|
|
44
47
|
} from "../model/canonical-document.ts";
|
|
45
48
|
import {
|
|
46
49
|
describeOpaqueFragment,
|
|
@@ -575,7 +578,7 @@ function createSurfaceBlock(
|
|
|
575
578
|
|
|
576
579
|
function createTableBlock(
|
|
577
580
|
tableIndex: number,
|
|
578
|
-
table: TableNode
|
|
581
|
+
table: Mutable<TableNode>,
|
|
579
582
|
document: CanonicalDocumentEnvelope,
|
|
580
583
|
cursor: number,
|
|
581
584
|
counters: {
|
|
@@ -769,7 +772,7 @@ function createTableBlock(
|
|
|
769
772
|
};
|
|
770
773
|
}
|
|
771
774
|
|
|
772
|
-
function computeTableRowSpans(table: TableNode): Map<string, number> {
|
|
775
|
+
function computeTableRowSpans(table: Mutable<TableNode>): Map<string, number> {
|
|
773
776
|
const positionedRows = table.rows.map((row) => {
|
|
774
777
|
let startColumn = 0;
|
|
775
778
|
|
|
@@ -933,7 +936,7 @@ function toSurfaceFrameProperties(
|
|
|
933
936
|
}
|
|
934
937
|
|
|
935
938
|
function resolveSurfaceParagraphFormatting(
|
|
936
|
-
formatting: CanonicalParagraphFormatting
|
|
939
|
+
formatting: Mutable<CanonicalParagraphFormatting>,
|
|
937
940
|
themeResolver: ThemeColorResolver | undefined,
|
|
938
941
|
): CanonicalParagraphFormatting {
|
|
939
942
|
if (!formatting.shading) {
|
|
@@ -1065,7 +1068,7 @@ function resolveCellBorderStyles(
|
|
|
1065
1068
|
|
|
1066
1069
|
function createSdtBlock(
|
|
1067
1070
|
sdtIndex: number,
|
|
1068
|
-
block: SdtNode
|
|
1071
|
+
block: Mutable<SdtNode>,
|
|
1069
1072
|
document: CanonicalDocumentEnvelope,
|
|
1070
1073
|
cursor: number,
|
|
1071
1074
|
counters: {
|
|
@@ -1123,7 +1126,7 @@ function createSdtBlock(
|
|
|
1123
1126
|
|
|
1124
1127
|
function createParagraphBlock(
|
|
1125
1128
|
paragraphIndex: number,
|
|
1126
|
-
paragraph: ParagraphNode
|
|
1129
|
+
paragraph: Mutable<ParagraphNode>,
|
|
1127
1130
|
document: CanonicalDocumentEnvelope,
|
|
1128
1131
|
start: number,
|
|
1129
1132
|
formattingContext: FormattingContext,
|
|
@@ -1548,6 +1551,9 @@ function appendInlineSegments(
|
|
|
1548
1551
|
...(c.line ? { line: c.line } : {}),
|
|
1549
1552
|
...(c.isTextBox ? { isTextBox: true } : {}),
|
|
1550
1553
|
...(c.textBoxBody ? { textBoxBody: c.textBoxBody } : {}),
|
|
1554
|
+
...(c.preserveOnlyObject
|
|
1555
|
+
? { preserveOnlyObject: surfacePreserveOnlyObject(c.preserveOnlyObject) }
|
|
1556
|
+
: {}),
|
|
1551
1557
|
...(txbxText ? { txbxText } : {}),
|
|
1552
1558
|
...(txbxTextSegment?.marks && txbxTextSegment.marks.length > 0
|
|
1553
1559
|
? { txbxMarks: txbxTextSegment.marks }
|
|
@@ -1567,6 +1573,7 @@ function appendInlineSegments(
|
|
|
1567
1573
|
{
|
|
1568
1574
|
previewMediaId: c.previewMediaId,
|
|
1569
1575
|
parsedChartId,
|
|
1576
|
+
anchor: surfaceAnchorFromGeometry(node.anchor),
|
|
1570
1577
|
},
|
|
1571
1578
|
);
|
|
1572
1579
|
}
|
|
@@ -1577,7 +1584,10 @@ function appendInlineSegments(
|
|
|
1577
1584
|
start,
|
|
1578
1585
|
"SmartArt diagram",
|
|
1579
1586
|
`DrawingFrame smartart_preview (${node.anchor.wrapMode}).`,
|
|
1580
|
-
{
|
|
1587
|
+
{
|
|
1588
|
+
previewMediaId: c.previewMediaId,
|
|
1589
|
+
anchor: surfaceAnchorFromGeometry(node.anchor),
|
|
1590
|
+
},
|
|
1581
1591
|
);
|
|
1582
1592
|
}
|
|
1583
1593
|
return appendComplexPreviewSegment(
|
|
@@ -1586,6 +1596,7 @@ function appendInlineSegments(
|
|
|
1586
1596
|
start,
|
|
1587
1597
|
"Drawing frame",
|
|
1588
1598
|
`DrawingFrame ${c.type} (${node.anchor.wrapMode}).`,
|
|
1599
|
+
{ anchor: surfaceAnchorFromGeometry(node.anchor) },
|
|
1589
1600
|
);
|
|
1590
1601
|
}
|
|
1591
1602
|
case "symbol":
|
|
@@ -1757,13 +1768,7 @@ function appendInlineSegments(
|
|
|
1757
1768
|
const fieldLabel =
|
|
1758
1769
|
node.fieldFamily === "TOC"
|
|
1759
1770
|
? "Table of Contents"
|
|
1760
|
-
: node.fieldFamily
|
|
1761
|
-
? "Current page number"
|
|
1762
|
-
: node.fieldFamily === "NUMPAGES"
|
|
1763
|
-
? "Total pages"
|
|
1764
|
-
: node.fieldFamily === "SECTIONPAGES"
|
|
1765
|
-
? "Section pages"
|
|
1766
|
-
: `${node.fieldFamily ?? "Field"}: ${node.fieldTarget ?? node.instruction.trim()}`;
|
|
1771
|
+
: `${node.fieldFamily ?? "Field"}: ${node.fieldTarget ?? node.instruction.trim()}`;
|
|
1767
1772
|
paragraph.segments.push({
|
|
1768
1773
|
segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
|
|
1769
1774
|
kind: "field_ref",
|
|
@@ -1804,7 +1809,7 @@ function appendInlineSegments(
|
|
|
1804
1809
|
}
|
|
1805
1810
|
|
|
1806
1811
|
function registerParsedChartPreview(
|
|
1807
|
-
node: ChartPreviewNode
|
|
1812
|
+
node: Mutable<ChartPreviewNode>,
|
|
1808
1813
|
document: CanonicalDocumentEnvelope,
|
|
1809
1814
|
): string | undefined {
|
|
1810
1815
|
if (!node.parsedData) return undefined;
|
|
@@ -1946,7 +1951,7 @@ function surfaceAnchorFromGeometry(
|
|
|
1946
1951
|
* fast-path image rendering.
|
|
1947
1952
|
*/
|
|
1948
1953
|
function surfacePictureEffectsFromContent(
|
|
1949
|
-
content: PictureContent
|
|
1954
|
+
content: Mutable<PictureContent>,
|
|
1950
1955
|
themeResolver?: ThemeColorResolver,
|
|
1951
1956
|
): SurfacePictureEffects | undefined {
|
|
1952
1957
|
const outerShadow = resolveSurfacePictureShadow(content.outerShadow, themeResolver);
|
|
@@ -2114,12 +2119,19 @@ function extractTxbxFirstTextSegment(
|
|
|
2114
2119
|
|
|
2115
2120
|
function appendComplexPreviewSegment(
|
|
2116
2121
|
paragraph: ParagraphAccumulator,
|
|
2117
|
-
node: { rawXml: string },
|
|
2122
|
+
node: { rawXml: string; preserveOnlyObject?: PreserveOnlyObjectSizing },
|
|
2118
2123
|
start: number,
|
|
2119
2124
|
label: string,
|
|
2120
2125
|
detail: string,
|
|
2121
|
-
extras: {
|
|
2126
|
+
extras: {
|
|
2127
|
+
previewMediaId?: string;
|
|
2128
|
+
parsedChartId?: string;
|
|
2129
|
+
anchor?: SurfaceDrawingAnchor;
|
|
2130
|
+
} = {},
|
|
2122
2131
|
): { nextCursor: number; lockedFragmentIds: string[] } {
|
|
2132
|
+
const preserveOnlyObject = node.preserveOnlyObject
|
|
2133
|
+
? surfacePreserveOnlyObject(node.preserveOnlyObject)
|
|
2134
|
+
: undefined;
|
|
2123
2135
|
paragraph.segments.push({
|
|
2124
2136
|
segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
|
|
2125
2137
|
kind: "opaque_inline",
|
|
@@ -2131,11 +2143,34 @@ function appendComplexPreviewSegment(
|
|
|
2131
2143
|
detail,
|
|
2132
2144
|
...(extras.previewMediaId ? { previewMediaId: extras.previewMediaId } : {}),
|
|
2133
2145
|
...(extras.parsedChartId ? { parsedChartId: extras.parsedChartId } : {}),
|
|
2146
|
+
...(preserveOnlyObject ? { preserveOnlyObject } : {}),
|
|
2147
|
+
...(extras.anchor ? { anchor: extras.anchor } : {}),
|
|
2134
2148
|
state: "locked-preserve-only",
|
|
2135
2149
|
});
|
|
2136
2150
|
return { nextCursor: start + 1, lockedFragmentIds: [] };
|
|
2137
2151
|
}
|
|
2138
2152
|
|
|
2153
|
+
function surfacePreserveOnlyObject(
|
|
2154
|
+
object: PreserveOnlyObjectSizing,
|
|
2155
|
+
): SurfacePreserveOnlyObjectSizing {
|
|
2156
|
+
return {
|
|
2157
|
+
...(object.sourceId ? { sourceId: object.sourceId } : {}),
|
|
2158
|
+
display: object.display,
|
|
2159
|
+
...(object.extentEmu
|
|
2160
|
+
? {
|
|
2161
|
+
extentEmu: {
|
|
2162
|
+
widthEmu: object.extentEmu.widthEmu,
|
|
2163
|
+
heightEmu: object.extentEmu.heightEmu,
|
|
2164
|
+
},
|
|
2165
|
+
}
|
|
2166
|
+
: {}),
|
|
2167
|
+
fallbackHint: object.fallbackHint,
|
|
2168
|
+
...(object.relationshipIds && object.relationshipIds.length > 0
|
|
2169
|
+
? { relationshipIds: [...object.relationshipIds] }
|
|
2170
|
+
: {}),
|
|
2171
|
+
};
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2139
2174
|
function appendTextBoxSegment(
|
|
2140
2175
|
paragraph: ParagraphAccumulator,
|
|
2141
2176
|
start: number,
|
|
@@ -2159,7 +2194,7 @@ function appendTextBoxSegment(
|
|
|
2159
2194
|
return { nextCursor: start + 1, lockedFragmentIds: [] };
|
|
2160
2195
|
}
|
|
2161
2196
|
|
|
2162
|
-
function shouldRenderSecondaryStoryVmlTextBox(node: VmlShapeNode): boolean {
|
|
2197
|
+
function shouldRenderSecondaryStoryVmlTextBox(node: Mutable<VmlShapeNode>): boolean {
|
|
2163
2198
|
return Boolean(node.text) && (!node.shapeType || /_x0000_t202$/iu.test(node.shapeType));
|
|
2164
2199
|
}
|
|
2165
2200
|
|
|
@@ -2174,7 +2209,7 @@ function isMicrosoftSensitivityLabelShape(
|
|
|
2174
2209
|
/"Placement"\s*:\s*"Footer"/iu.test(node.rawXml);
|
|
2175
2210
|
}
|
|
2176
2211
|
|
|
2177
|
-
function createChartDetail(node: ChartPreviewNode): string {
|
|
2212
|
+
function createChartDetail(node: Mutable<ChartPreviewNode>): string {
|
|
2178
2213
|
const parts = ["Embedded chart."];
|
|
2179
2214
|
if (node.previewMediaId) {
|
|
2180
2215
|
parts.push(`Preview available via fallback image (${node.previewMediaId}).`);
|
|
@@ -2185,7 +2220,7 @@ function createChartDetail(node: ChartPreviewNode): string {
|
|
|
2185
2220
|
return parts.join(" ");
|
|
2186
2221
|
}
|
|
2187
2222
|
|
|
2188
|
-
function createSmartArtDetail(node: SmartArtPreviewNode): string {
|
|
2223
|
+
function createSmartArtDetail(node: Mutable<SmartArtPreviewNode>): string {
|
|
2189
2224
|
const parts = ["SmartArt diagram."];
|
|
2190
2225
|
if (node.previewMediaId) {
|
|
2191
2226
|
parts.push(`Preview available via fallback image (${node.previewMediaId}).`);
|
|
@@ -2196,7 +2231,7 @@ function createSmartArtDetail(node: SmartArtPreviewNode): string {
|
|
|
2196
2231
|
return parts.join(" ");
|
|
2197
2232
|
}
|
|
2198
2233
|
|
|
2199
|
-
function createShapeDetail(node: ShapeNode): string {
|
|
2234
|
+
function createShapeDetail(node: Mutable<ShapeNode>): string {
|
|
2200
2235
|
if (node.isTextBox) {
|
|
2201
2236
|
const parts = ["Text box."];
|
|
2202
2237
|
if (node.text) parts.push(`Content: "${node.text}".`);
|
|
@@ -2210,7 +2245,7 @@ function createShapeDetail(node: ShapeNode): string {
|
|
|
2210
2245
|
return parts.join(" ");
|
|
2211
2246
|
}
|
|
2212
2247
|
|
|
2213
|
-
function createWordArtDetail(node: WordArtNode): string {
|
|
2248
|
+
function createWordArtDetail(node: Mutable<WordArtNode>): string {
|
|
2214
2249
|
const parts = ["WordArt decorative text."];
|
|
2215
2250
|
if (node.text) parts.push(`Text: "${node.text}".`);
|
|
2216
2251
|
if (node.geometry) parts.push(`Effect: ${node.geometry}.`);
|
|
@@ -2218,7 +2253,7 @@ function createWordArtDetail(node: WordArtNode): string {
|
|
|
2218
2253
|
return parts.join(" ");
|
|
2219
2254
|
}
|
|
2220
2255
|
|
|
2221
|
-
function createVmlDetail(node: VmlShapeNode): string {
|
|
2256
|
+
function createVmlDetail(node: Mutable<VmlShapeNode>): string {
|
|
2222
2257
|
const parts = ["Legacy VML drawing."];
|
|
2223
2258
|
if (node.shapeType) parts.push(`Type: ${node.shapeType}.`);
|
|
2224
2259
|
if (node.text) parts.push(`Text content: "${node.text}".`);
|
|
@@ -2587,22 +2622,22 @@ function toSurfaceTabStop(
|
|
|
2587
2622
|
}
|
|
2588
2623
|
|
|
2589
2624
|
function buildDirectParagraphFormattingFromNode(
|
|
2590
|
-
paragraph: ParagraphNode
|
|
2625
|
+
paragraph: Mutable<ParagraphNode>,
|
|
2591
2626
|
): CanonicalParagraphFormatting | undefined {
|
|
2592
|
-
const direct: CanonicalParagraphFormatting = {};
|
|
2593
|
-
if (paragraph.spacing) direct.spacing = paragraph.spacing;
|
|
2594
|
-
if (paragraph.indentation) direct.indentation = paragraph.indentation;
|
|
2595
|
-
if (paragraph.alignment) direct.alignment = paragraph.alignment;
|
|
2596
|
-
if (paragraph.borders) direct.borders = paragraph.borders;
|
|
2597
|
-
if (paragraph.shading) direct.shading = paragraph.shading;
|
|
2598
|
-
if (paragraph.tabStops && paragraph.tabStops.length > 0) direct.tabStops = [...paragraph.tabStops];
|
|
2599
|
-
if (paragraph.contextualSpacing !== undefined) direct.contextualSpacing = paragraph.contextualSpacing;
|
|
2600
|
-
if (paragraph.keepNext !== undefined) direct.keepNext = paragraph.keepNext;
|
|
2601
|
-
if (paragraph.keepLines !== undefined) direct.keepLines = paragraph.keepLines;
|
|
2602
|
-
if (paragraph.widowControl !== undefined) direct.widowControl = paragraph.widowControl;
|
|
2603
|
-
if (paragraph.pageBreakBefore !== undefined) direct.pageBreakBefore = paragraph.pageBreakBefore;
|
|
2604
|
-
if (paragraph.outlineLevel !== undefined) direct.outlineLevel = paragraph.outlineLevel;
|
|
2605
|
-
if (paragraph.bidi !== undefined) direct.bidi = paragraph.bidi;
|
|
2627
|
+
const direct: Mutable<CanonicalParagraphFormatting> = {};
|
|
2628
|
+
if (paragraph.spacing) (direct as Mutable<typeof direct>).spacing = paragraph.spacing;
|
|
2629
|
+
if (paragraph.indentation) (direct as Mutable<typeof direct>).indentation = paragraph.indentation;
|
|
2630
|
+
if (paragraph.alignment) (direct as Mutable<typeof direct>).alignment = paragraph.alignment;
|
|
2631
|
+
if (paragraph.borders) (direct as Mutable<typeof direct>).borders = paragraph.borders;
|
|
2632
|
+
if (paragraph.shading) (direct as Mutable<typeof direct>).shading = paragraph.shading;
|
|
2633
|
+
if (paragraph.tabStops && paragraph.tabStops.length > 0) (direct as Mutable<typeof direct>).tabStops = [...paragraph.tabStops];
|
|
2634
|
+
if (paragraph.contextualSpacing !== undefined) (direct as Mutable<typeof direct>).contextualSpacing = paragraph.contextualSpacing;
|
|
2635
|
+
if (paragraph.keepNext !== undefined) (direct as Mutable<typeof direct>).keepNext = paragraph.keepNext;
|
|
2636
|
+
if (paragraph.keepLines !== undefined) (direct as Mutable<typeof direct>).keepLines = paragraph.keepLines;
|
|
2637
|
+
if (paragraph.widowControl !== undefined) (direct as Mutable<typeof direct>).widowControl = paragraph.widowControl;
|
|
2638
|
+
if (paragraph.pageBreakBefore !== undefined) (direct as Mutable<typeof direct>).pageBreakBefore = paragraph.pageBreakBefore;
|
|
2639
|
+
if (paragraph.outlineLevel !== undefined) (direct as Mutable<typeof direct>).outlineLevel = paragraph.outlineLevel;
|
|
2640
|
+
if (paragraph.bidi !== undefined) (direct as Mutable<typeof direct>).bidi = paragraph.bidi;
|
|
2606
2641
|
if (paragraph.suppressLineNumbers !== undefined) direct.suppressLineNumbers = paragraph.suppressLineNumbers;
|
|
2607
2642
|
return Object.keys(direct).length > 0 ? direct : undefined;
|
|
2608
2643
|
}
|
|
@@ -2947,7 +2982,7 @@ function createFloatingImageDetail(
|
|
|
2947
2982
|
return parts.join(" ");
|
|
2948
2983
|
}
|
|
2949
2984
|
|
|
2950
|
-
function hasMediaItem(media: MediaCatalog
|
|
2985
|
+
function hasMediaItem(media: Mutable<MediaCatalog>, mediaId: string): boolean {
|
|
2951
2986
|
return mediaId in media.items;
|
|
2952
2987
|
}
|
|
2953
2988
|
|
|
@@ -62,6 +62,7 @@ import type {
|
|
|
62
62
|
WorkflowMetadataDefinition,
|
|
63
63
|
WorkflowMetadataEntry,
|
|
64
64
|
WorkflowMetadataSnapshot,
|
|
65
|
+
WorkflowEventOrigin,
|
|
65
66
|
WorkflowOverlay,
|
|
66
67
|
WorkflowScope,
|
|
67
68
|
WorkflowScopeGuardPolicy,
|
|
@@ -100,10 +101,8 @@ import {
|
|
|
100
101
|
} from "./visibility-policy.ts";
|
|
101
102
|
import { type WorkflowMarkupModePolicy } from "./markup-mode-policy.ts";
|
|
102
103
|
|
|
103
|
-
/** Shape of origin metadata attached to commands.
|
|
104
|
-
|
|
105
|
-
* open shape here to avoid coupling. */
|
|
106
|
-
type CoordinatorCommandOrigin = { readonly source: string; readonly at?: string };
|
|
104
|
+
/** Shape of origin metadata attached to workflow commands/events. */
|
|
105
|
+
type CoordinatorCommandOrigin = WorkflowEventOrigin;
|
|
107
106
|
|
|
108
107
|
/** Document-mutation commands the coordinator emits through `deps.dispatch`. */
|
|
109
108
|
type CoordinatorDispatchedCommand =
|
|
@@ -157,10 +156,17 @@ export interface WorkflowEmittableEvent {
|
|
|
157
156
|
readonly type:
|
|
158
157
|
| "workflow_overlay_changed"
|
|
159
158
|
| "workflow_active_work_item_changed"
|
|
160
|
-
| "workflow_metadata_changed"
|
|
159
|
+
| "workflow_metadata_changed"
|
|
160
|
+
| "workflow_shared_state_changed"
|
|
161
|
+
| "workflow_visibility_policy_changed"
|
|
162
|
+
| "workflow_markup_mode_policy_changed";
|
|
161
163
|
readonly documentId: string;
|
|
162
164
|
readonly snapshot?: WorkflowScopeSnapshot | WorkflowMetadataSnapshot | null;
|
|
163
165
|
readonly activeWorkItemId?: string | null;
|
|
166
|
+
readonly state?: SharedWorkflowState | null;
|
|
167
|
+
readonly kind?: OverlayKind;
|
|
168
|
+
readonly policy?: OverlayVisibilityPolicy | WorkflowMarkupModePolicy | null;
|
|
169
|
+
readonly origin?: CoordinatorCommandOrigin;
|
|
164
170
|
}
|
|
165
171
|
|
|
166
172
|
export interface PerfCounters {
|
|
@@ -276,7 +282,10 @@ export interface WorkflowCoordinator {
|
|
|
276
282
|
* seam) so UI surfaces re-fire when policy changes mid-session. */
|
|
277
283
|
subscribeMarkupModePolicy(listener: () => void): () => void;
|
|
278
284
|
/* --- collab shared state --- */
|
|
279
|
-
setSharedWorkflowState(
|
|
285
|
+
setSharedWorkflowState(
|
|
286
|
+
state: SharedWorkflowState | null,
|
|
287
|
+
origin?: CoordinatorCommandOrigin,
|
|
288
|
+
): void;
|
|
280
289
|
/* --- snapshots (cached) --- */
|
|
281
290
|
getInteractionGuardSnapshot(): InteractionGuardSnapshot;
|
|
282
291
|
getWorkflowScopeSnapshot(): WorkflowScopeSnapshot | null;
|
|
@@ -1133,12 +1142,21 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1133
1142
|
return overlayStore.getMetadataSnapshot();
|
|
1134
1143
|
}
|
|
1135
1144
|
|
|
1136
|
-
function setSharedWorkflowState(
|
|
1145
|
+
function setSharedWorkflowState(
|
|
1146
|
+
state: SharedWorkflowState | null,
|
|
1147
|
+
origin: CoordinatorCommandOrigin = { source: "api", at: clock() },
|
|
1148
|
+
): void {
|
|
1137
1149
|
const prior = overlayStore.getSharedWorkflowState();
|
|
1138
1150
|
if (state === prior) return;
|
|
1139
1151
|
overlayStore.replaceSharedWorkflowState(state);
|
|
1140
1152
|
cachedInteractionGuardSnapshot = undefined;
|
|
1141
1153
|
cachedWorkflowScopeSnapshot = undefined;
|
|
1154
|
+
deps.emitEvent({
|
|
1155
|
+
type: "workflow_shared_state_changed",
|
|
1156
|
+
documentId: deps.getState().documentId,
|
|
1157
|
+
state,
|
|
1158
|
+
origin,
|
|
1159
|
+
});
|
|
1142
1160
|
}
|
|
1143
1161
|
|
|
1144
1162
|
function setScopeChromeVisibility(state: ScopeChromeVisibilityState): void {
|
|
@@ -1161,13 +1179,13 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1161
1179
|
|
|
1162
1180
|
function setVisibilityPolicy(policy: OverlayVisibilityPolicy): boolean {
|
|
1163
1181
|
const changed = overlayStore.replaceVisibilityPolicy(policy.kind, policy);
|
|
1164
|
-
if (changed) emitVisibilityPolicyChanged();
|
|
1182
|
+
if (changed) emitVisibilityPolicyChanged(policy.kind, policy);
|
|
1165
1183
|
return changed;
|
|
1166
1184
|
}
|
|
1167
1185
|
|
|
1168
1186
|
function clearVisibilityPolicy(kind: OverlayKind): boolean {
|
|
1169
1187
|
const changed = overlayStore.replaceVisibilityPolicy(kind, null);
|
|
1170
|
-
if (changed) emitVisibilityPolicyChanged();
|
|
1188
|
+
if (changed) emitVisibilityPolicyChanged(kind, null);
|
|
1171
1189
|
return changed;
|
|
1172
1190
|
}
|
|
1173
1191
|
|
|
@@ -1175,7 +1193,10 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1175
1193
|
policies: readonly OverlayVisibilityPolicy[],
|
|
1176
1194
|
): boolean {
|
|
1177
1195
|
const changed = overlayStore.replaceVisibilityPolicies(policies);
|
|
1178
|
-
if (changed) emitVisibilityPolicyChanged(
|
|
1196
|
+
if (changed) emitVisibilityPolicyChanged(undefined, undefined, {
|
|
1197
|
+
source: "runtime",
|
|
1198
|
+
at: clock(),
|
|
1199
|
+
});
|
|
1179
1200
|
return changed;
|
|
1180
1201
|
}
|
|
1181
1202
|
|
|
@@ -1195,6 +1216,12 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1195
1216
|
const changed = overlayStore.replaceMarkupModePolicy(policy);
|
|
1196
1217
|
if (changed) {
|
|
1197
1218
|
overlayStore.notifyMarkupModePolicyChanged();
|
|
1219
|
+
deps.emitEvent({
|
|
1220
|
+
type: "workflow_markup_mode_policy_changed",
|
|
1221
|
+
documentId: deps.getState().documentId,
|
|
1222
|
+
policy,
|
|
1223
|
+
origin: { source: "api", at: clock() },
|
|
1224
|
+
});
|
|
1198
1225
|
if (deps.telemetryBus.isEnabled("scope")) {
|
|
1199
1226
|
deps.telemetryBus.emit({
|
|
1200
1227
|
channel: "scope",
|
|
@@ -1211,11 +1238,22 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1211
1238
|
return overlayStore.subscribeMarkupModePolicy(listener);
|
|
1212
1239
|
}
|
|
1213
1240
|
|
|
1214
|
-
function emitVisibilityPolicyChanged(
|
|
1241
|
+
function emitVisibilityPolicyChanged(
|
|
1242
|
+
kind?: OverlayKind,
|
|
1243
|
+
policy?: OverlayVisibilityPolicy | null,
|
|
1244
|
+
origin: CoordinatorCommandOrigin = { source: "api", at: clock() },
|
|
1245
|
+
): void {
|
|
1215
1246
|
// Notify direct subscribers first — L10 X3's ui.overlays.subscribeVisibility
|
|
1216
1247
|
// chains onto this signal so UI surfaces re-fire when an authoring tool
|
|
1217
1248
|
// mutates policy mid-session.
|
|
1218
1249
|
overlayStore.notifyVisibilityPolicyChanged();
|
|
1250
|
+
deps.emitEvent({
|
|
1251
|
+
type: "workflow_visibility_policy_changed",
|
|
1252
|
+
documentId: deps.getState().documentId,
|
|
1253
|
+
...(kind !== undefined ? { kind } : {}),
|
|
1254
|
+
...(policy !== undefined ? { policy } : {}),
|
|
1255
|
+
origin,
|
|
1256
|
+
});
|
|
1219
1257
|
if (!deps.telemetryBus.isEnabled("scope")) return;
|
|
1220
1258
|
deps.telemetryBus.emit({
|
|
1221
1259
|
channel: "scope",
|
|
@@ -1301,12 +1339,14 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1301
1339
|
type: "workflow_overlay_changed",
|
|
1302
1340
|
documentId,
|
|
1303
1341
|
snapshot,
|
|
1342
|
+
origin: command.origin,
|
|
1304
1343
|
});
|
|
1305
1344
|
if (command.overlay.activeWorkItemId !== undefined) {
|
|
1306
1345
|
deps.emitEvent({
|
|
1307
1346
|
type: "workflow_active_work_item_changed",
|
|
1308
1347
|
documentId,
|
|
1309
1348
|
activeWorkItemId: command.overlay.activeWorkItemId ?? null,
|
|
1349
|
+
origin: command.origin,
|
|
1310
1350
|
});
|
|
1311
1351
|
}
|
|
1312
1352
|
return warningDelta;
|
|
@@ -1323,6 +1363,7 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1323
1363
|
type: "workflow_active_work_item_changed",
|
|
1324
1364
|
documentId,
|
|
1325
1365
|
activeWorkItemId: null,
|
|
1366
|
+
origin: command.origin,
|
|
1326
1367
|
});
|
|
1327
1368
|
deps.emitEvent({
|
|
1328
1369
|
type: "workflow_overlay_changed",
|
|
@@ -1334,6 +1375,7 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1334
1375
|
candidates: [],
|
|
1335
1376
|
blockedReasons: [],
|
|
1336
1377
|
},
|
|
1378
|
+
origin: command.origin,
|
|
1337
1379
|
});
|
|
1338
1380
|
return warningDelta;
|
|
1339
1381
|
}
|
|
@@ -1343,6 +1385,7 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1343
1385
|
type: "workflow_metadata_changed",
|
|
1344
1386
|
documentId,
|
|
1345
1387
|
snapshot: overlayStore.getMetadataSnapshot(),
|
|
1388
|
+
origin: command.origin,
|
|
1346
1389
|
});
|
|
1347
1390
|
return null;
|
|
1348
1391
|
}
|
|
@@ -1352,6 +1395,7 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1352
1395
|
type: "workflow_metadata_changed",
|
|
1353
1396
|
documentId,
|
|
1354
1397
|
snapshot: overlayStore.getMetadataSnapshot(),
|
|
1398
|
+
origin: command.origin,
|
|
1355
1399
|
});
|
|
1356
1400
|
return null;
|
|
1357
1401
|
}
|
|
@@ -1361,6 +1405,7 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1361
1405
|
type: "workflow_metadata_changed",
|
|
1362
1406
|
documentId,
|
|
1363
1407
|
snapshot: overlayStore.getMetadataSnapshot(),
|
|
1408
|
+
origin: command.origin,
|
|
1364
1409
|
});
|
|
1365
1410
|
return null;
|
|
1366
1411
|
}
|
|
@@ -1370,6 +1415,7 @@ export function createWorkflowCoordinator(deps: CoordinatorDeps): WorkflowCoordi
|
|
|
1370
1415
|
type: "workflow_metadata_changed",
|
|
1371
1416
|
documentId,
|
|
1372
1417
|
snapshot: overlayStore.getMetadataSnapshot(),
|
|
1418
|
+
origin: command.origin,
|
|
1373
1419
|
});
|
|
1374
1420
|
return null;
|
|
1375
1421
|
}
|
|
@@ -22,6 +22,7 @@ import type {
|
|
|
22
22
|
CanonicalDocument,
|
|
23
23
|
FootnoteCollection,
|
|
24
24
|
OpaqueFragmentRecord,
|
|
25
|
+
Mutable,
|
|
25
26
|
} from "../../model/canonical-document.ts";
|
|
26
27
|
|
|
27
28
|
/** Warning shape carried on `CanonicalDocument.diagnostics.warnings`. */
|
|
@@ -130,7 +131,7 @@ export function normalizeFootnoteCollectionOpaqueBlocks(
|
|
|
130
131
|
if (!collection) return;
|
|
131
132
|
const notes = kind === "footnote" ? collection.footnotes : collection.endnotes;
|
|
132
133
|
for (const definition of Object.values(notes)) {
|
|
133
|
-
definition.blocks = normalizeSubPartOpaqueBlocks(
|
|
134
|
+
(definition as Mutable<typeof definition>).blocks = normalizeSubPartOpaqueBlocks(
|
|
134
135
|
definition.blocks,
|
|
135
136
|
opaqueFragments,
|
|
136
137
|
warnings,
|