superdoc 2.0.0-next.32 → 2.0.0-next.34
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-C01vcKRO.es.js → create-super-doc-ui-C_kKiKQ4.es.js} +334 -29
- package/dist/chunks/{create-super-doc-ui-C0ZJE05U.cjs → create-super-doc-ui-DLyJzmj9.cjs} +558 -28
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/document-api/src/types/blocks.types.d.ts +5 -0
- package/dist/public/ui-react.cjs +1 -1
- package/dist/public/ui-react.es.js +1 -1
- package/dist/public/ui.cjs +1 -1
- package/dist/public/ui.es.js +1 -1
- package/dist/superdoc/src/internal/toolbar/built-in/toolbar-focus-helpers.d.ts +1 -1
- package/dist/superdoc.cjs +66 -306
- package/dist/superdoc.es.js +65 -86
- package/dist-cdn/superdoc.min.js +37 -37
- package/package.json +2 -2
|
@@ -1,3 +1,308 @@
|
|
|
1
|
+
function getParagraphInlineDirection(attrs) {
|
|
2
|
+
const fromContext = attrs?.directionContext?.inlineDirection;
|
|
3
|
+
if (fromContext != null) return fromContext;
|
|
4
|
+
const ppRtl = attrs?.paragraphProperties?.rightToLeft;
|
|
5
|
+
if (ppRtl === true) return "rtl";
|
|
6
|
+
if (ppRtl === false) return "ltr";
|
|
7
|
+
}
|
|
8
|
+
var FALLBACK_PALETTE = [
|
|
9
|
+
"#1f6feb",
|
|
10
|
+
"#d1242f",
|
|
11
|
+
"#8250df",
|
|
12
|
+
"#bf3989",
|
|
13
|
+
"#1a7f37",
|
|
14
|
+
"#9a6700",
|
|
15
|
+
"#bc4c00",
|
|
16
|
+
"#0969da",
|
|
17
|
+
"#cf222e",
|
|
18
|
+
"#6639ba",
|
|
19
|
+
"#116329",
|
|
20
|
+
"#7d4e00"
|
|
21
|
+
];
|
|
22
|
+
const authorIdentityKey = (author) => {
|
|
23
|
+
if (!author) return "";
|
|
24
|
+
return `${typeof author.name === "string" ? author.name : ""} ${typeof author.email === "string" ? author.email : ""}`;
|
|
25
|
+
};
|
|
26
|
+
var hashString = (value) => {
|
|
27
|
+
let hash = 2166136261;
|
|
28
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
29
|
+
hash ^= value.charCodeAt(i);
|
|
30
|
+
hash = Math.imul(hash, 16777619);
|
|
31
|
+
}
|
|
32
|
+
return hash >>> 0;
|
|
33
|
+
};
|
|
34
|
+
const fallbackAuthorColor = (author) => {
|
|
35
|
+
return FALLBACK_PALETTE[hashString(authorIdentityKey(author)) % FALLBACK_PALETTE.length];
|
|
36
|
+
};
|
|
37
|
+
var isNonEmptyString = (value) => typeof value === "string" && value.length > 0;
|
|
38
|
+
const composeAuthorColorResolver = (config) => {
|
|
39
|
+
if (!config || config.enabled === false) return void 0;
|
|
40
|
+
const overrides = config.overrides && typeof config.overrides === "object" ? config.overrides : void 0;
|
|
41
|
+
const resolve = typeof config.resolve === "function" ? config.resolve : void 0;
|
|
42
|
+
return (author) => {
|
|
43
|
+
const safeAuthor = author ?? {};
|
|
44
|
+
if (overrides) {
|
|
45
|
+
if (isNonEmptyString(safeAuthor.email) && isNonEmptyString(overrides[safeAuthor.email])) return overrides[safeAuthor.email];
|
|
46
|
+
if (isNonEmptyString(safeAuthor.name) && isNonEmptyString(overrides[safeAuthor.name])) return overrides[safeAuthor.name];
|
|
47
|
+
}
|
|
48
|
+
if (resolve) try {
|
|
49
|
+
const resolved = resolve(safeAuthor);
|
|
50
|
+
if (isNonEmptyString(resolved)) return resolved;
|
|
51
|
+
} catch {}
|
|
52
|
+
return fallbackAuthorColor(safeAuthor);
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const TRACKED_CHANGE_CONFIGURABLE_SEMANTIC_COLOR_KEYS = [
|
|
56
|
+
"insertion",
|
|
57
|
+
"deletion",
|
|
58
|
+
"move",
|
|
59
|
+
"move-from",
|
|
60
|
+
"move-to",
|
|
61
|
+
"table-cell-insertion",
|
|
62
|
+
"table-cell-deletion",
|
|
63
|
+
"cell-merge",
|
|
64
|
+
"cell-split",
|
|
65
|
+
"image-insertion",
|
|
66
|
+
"image-deletion",
|
|
67
|
+
"image-property-change"
|
|
68
|
+
];
|
|
69
|
+
var CONFIGURABLE_SEMANTIC_COLOR_KEY_SET = new Set(TRACKED_CHANGE_CONFIGURABLE_SEMANTIC_COLOR_KEYS);
|
|
70
|
+
const DRAWING_DIAGNOSTIC_CODES = {
|
|
71
|
+
externalImageDeferred: "render.media.external-image-deferred",
|
|
72
|
+
missingRelationship: "render.drawing.missing-relationship",
|
|
73
|
+
missingMediaPart: "render.media.missing-part",
|
|
74
|
+
unsupportedRelationshipType: "render.drawing.unsupported-relationship-type",
|
|
75
|
+
unsupportedMime: "render.media.unsupported-mime",
|
|
76
|
+
imageTooLarge: "render.media.image-too-large",
|
|
77
|
+
unsafeSvg: "render.media.unsafe-svg",
|
|
78
|
+
unsupportedFormat: "render.media.unsupported-format",
|
|
79
|
+
embeddedObjectNotSupported: "render.embedded-object-not-supported",
|
|
80
|
+
unsupportedObject: "render.drawing.unsupported-object",
|
|
81
|
+
vmlUnsupported: "render.drawing.vml-unsupported",
|
|
82
|
+
vmlImageUnsupported: "render.drawing.vml-image-unsupported",
|
|
83
|
+
unsupportedGeometryCommand: "render.drawing.unsupported-geometry-command",
|
|
84
|
+
anchorUnsupported: "render.drawing.anchor-unsupported",
|
|
85
|
+
wrapUnsupported: "render.drawing.wrap-unsupported",
|
|
86
|
+
altContentNoSupportedChoice: "render.drawing.altcontent-no-supported-choice",
|
|
87
|
+
groupChildUnsupported: "render.drawing.group-child-unsupported"
|
|
88
|
+
};
|
|
89
|
+
const DRAWING_DIAGNOSTIC_CODE_ALIASES = {
|
|
90
|
+
"render.media.missing-relationship": DRAWING_DIAGNOSTIC_CODES.missingRelationship,
|
|
91
|
+
"render.media.wrong-relationship-type": DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType,
|
|
92
|
+
"render.media.unsupported-target": DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType,
|
|
93
|
+
"render.media.invalid-image-size": DRAWING_DIAGNOSTIC_CODES.imageTooLarge,
|
|
94
|
+
"render.media-resolver-unavailable": DRAWING_DIAGNOSTIC_CODES.missingMediaPart,
|
|
95
|
+
"render.chart-not-supported": DRAWING_DIAGNOSTIC_CODES.unsupportedObject,
|
|
96
|
+
"render.textbox.vml-unsupported": DRAWING_DIAGNOSTIC_CODES.vmlUnsupported
|
|
97
|
+
};
|
|
98
|
+
const DRAWING_SUPPORT_TAXONOMY = {
|
|
99
|
+
inlineBitmap: {
|
|
100
|
+
family: "inlineBitmap",
|
|
101
|
+
support: "supported",
|
|
102
|
+
description: "wp:inline pic:pic with internal media and browser-safe MIME (PNG/JPEG; WebP/SVG once the host media resolver lands).",
|
|
103
|
+
contract: "ImageRun"
|
|
104
|
+
},
|
|
105
|
+
anchoredBitmap: {
|
|
106
|
+
family: "anchoredBitmap",
|
|
107
|
+
support: "supported",
|
|
108
|
+
description: "wp:anchor bitmap with anchor/wrap expressible by ImageAnchor/ImageWrap. Never silently inlined.",
|
|
109
|
+
contract: "ImageBlock"
|
|
110
|
+
},
|
|
111
|
+
imageChildInGroup: {
|
|
112
|
+
family: "imageChildInGroup",
|
|
113
|
+
support: "supported",
|
|
114
|
+
description: "Bitmap child of a supported DrawingML group/drawing wrapper. Supported only when the parent is.",
|
|
115
|
+
contract: "ImageDrawing"
|
|
116
|
+
},
|
|
117
|
+
vectorShape: {
|
|
118
|
+
family: "vectorShape",
|
|
119
|
+
support: "supported",
|
|
120
|
+
description: "Block/floating DrawingML preset/custom shape with the supported geometry/style subset.",
|
|
121
|
+
contract: "DrawingBlock",
|
|
122
|
+
drawingKind: "vectorShape"
|
|
123
|
+
},
|
|
124
|
+
shapeGroup: {
|
|
125
|
+
family: "shapeGroup",
|
|
126
|
+
support: "supported",
|
|
127
|
+
description: "DrawingML group whose rendered children are supported vector/image children.",
|
|
128
|
+
contract: "DrawingBlock",
|
|
129
|
+
drawingKind: "shapeGroup"
|
|
130
|
+
},
|
|
131
|
+
chart: {
|
|
132
|
+
family: "chart",
|
|
133
|
+
support: "supported",
|
|
134
|
+
description: "DrawingML chart projected into a ChartDrawing with parsed cached chart XML data. Complete Word chart fidelity remains deferred to chartFidelity.",
|
|
135
|
+
contract: "DrawingBlock",
|
|
136
|
+
drawingKind: "chart"
|
|
137
|
+
},
|
|
138
|
+
alternateContent: {
|
|
139
|
+
family: "alternateContent",
|
|
140
|
+
support: "supported",
|
|
141
|
+
description: "mc:AlternateContent traversal/select policy. Selected Choice/Fallback maps to its family contract; unselected branches preserved for save/reopen.",
|
|
142
|
+
contract: "selected-choice"
|
|
143
|
+
},
|
|
144
|
+
externalImage: {
|
|
145
|
+
family: "externalImage",
|
|
146
|
+
support: "fail-closed",
|
|
147
|
+
description: "External image relationship (r:link / TargetMode=\"External\"). Not fetched.",
|
|
148
|
+
contract: "none",
|
|
149
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.externalImageDeferred
|
|
150
|
+
},
|
|
151
|
+
missingRelationship: {
|
|
152
|
+
family: "missingRelationship",
|
|
153
|
+
support: "fail-closed",
|
|
154
|
+
description: "Drawing references a relationship id absent from the owner part .rels.",
|
|
155
|
+
contract: "none",
|
|
156
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.missingRelationship
|
|
157
|
+
},
|
|
158
|
+
missingMediaPart: {
|
|
159
|
+
family: "missingMediaPart",
|
|
160
|
+
support: "fail-closed",
|
|
161
|
+
description: "Relationship resolves but the target media part bytes are missing or empty.",
|
|
162
|
+
contract: "none",
|
|
163
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.missingMediaPart
|
|
164
|
+
},
|
|
165
|
+
wrongRelationshipType: {
|
|
166
|
+
family: "wrongRelationshipType",
|
|
167
|
+
support: "fail-closed",
|
|
168
|
+
description: "Relationship exists but is not an image relationship type.",
|
|
169
|
+
contract: "none",
|
|
170
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType
|
|
171
|
+
},
|
|
172
|
+
unsupportedMime: {
|
|
173
|
+
family: "unsupportedMime",
|
|
174
|
+
support: "fail-closed",
|
|
175
|
+
description: "Media MIME outside the supported allowlist (incl. GIF/BMP/ICO).",
|
|
176
|
+
contract: "none",
|
|
177
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedMime
|
|
178
|
+
},
|
|
179
|
+
oversizedMediaPart: {
|
|
180
|
+
family: "oversizedMediaPart",
|
|
181
|
+
support: "fail-closed",
|
|
182
|
+
description: "Media part exceeds the host byte-size policy before bytes are materialized.",
|
|
183
|
+
contract: "none",
|
|
184
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.imageTooLarge
|
|
185
|
+
},
|
|
186
|
+
unsafeSvg: {
|
|
187
|
+
family: "unsafeSvg",
|
|
188
|
+
support: "fail-closed",
|
|
189
|
+
description: "SVG content rejected by the SVG safety policy.",
|
|
190
|
+
contract: "none",
|
|
191
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsafeSvg
|
|
192
|
+
},
|
|
193
|
+
metafileOrTiff: {
|
|
194
|
+
family: "metafileOrTiff",
|
|
195
|
+
support: "fail-closed",
|
|
196
|
+
description: "EMF/WMF/TIFF and other non-browser-native formats with no approved conversion path.",
|
|
197
|
+
contract: "none",
|
|
198
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedFormat
|
|
199
|
+
},
|
|
200
|
+
embeddedObject: {
|
|
201
|
+
family: "embeddedObject",
|
|
202
|
+
support: "fail-closed",
|
|
203
|
+
description: "OLE / ActiveX / embedded package object.",
|
|
204
|
+
contract: "none",
|
|
205
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.embeddedObjectNotSupported
|
|
206
|
+
},
|
|
207
|
+
smartArtOrDiagram: {
|
|
208
|
+
family: "smartArtOrDiagram",
|
|
209
|
+
support: "fail-closed",
|
|
210
|
+
description: "SmartArt / diagram / unknown external graphic-data object.",
|
|
211
|
+
contract: "none",
|
|
212
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedObject
|
|
213
|
+
},
|
|
214
|
+
vml: {
|
|
215
|
+
family: "vml",
|
|
216
|
+
support: "fail-closed",
|
|
217
|
+
description: "VML structure outside any supported image-like subset (default fail-closed policy).",
|
|
218
|
+
contract: "none",
|
|
219
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.vmlUnsupported
|
|
220
|
+
},
|
|
221
|
+
vmlImageLike: {
|
|
222
|
+
family: "vmlImageLike",
|
|
223
|
+
support: "fail-closed",
|
|
224
|
+
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.",
|
|
225
|
+
contract: "none",
|
|
226
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.vmlImageUnsupported
|
|
227
|
+
},
|
|
228
|
+
unsupportedGeometryCommand: {
|
|
229
|
+
family: "unsupportedGeometryCommand",
|
|
230
|
+
support: "fail-closed",
|
|
231
|
+
description: "Custom geometry command the extractor does not implement, e.g. arcTo.",
|
|
232
|
+
contract: "none",
|
|
233
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.unsupportedGeometryCommand
|
|
234
|
+
},
|
|
235
|
+
unsupportedAnchorFields: {
|
|
236
|
+
family: "unsupportedAnchorFields",
|
|
237
|
+
support: "fail-closed",
|
|
238
|
+
description: "Anchor fields required for honest placement are unsupported (char-relative, alignment modes, etc.).",
|
|
239
|
+
contract: "none",
|
|
240
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.anchorUnsupported
|
|
241
|
+
},
|
|
242
|
+
unsupportedWrapFields: {
|
|
243
|
+
family: "unsupportedWrapFields",
|
|
244
|
+
support: "fail-closed",
|
|
245
|
+
description: "Wrap fields required for honest placement are unsupported (arbitrary wrap polygons, etc.).",
|
|
246
|
+
contract: "none",
|
|
247
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.wrapUnsupported
|
|
248
|
+
},
|
|
249
|
+
alternateContentNoSupportedChoice: {
|
|
250
|
+
family: "alternateContentNoSupportedChoice",
|
|
251
|
+
support: "fail-closed",
|
|
252
|
+
description: "mc:AlternateContent with no supported choice and no usable fallback.",
|
|
253
|
+
contract: "none",
|
|
254
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.altContentNoSupportedChoice
|
|
255
|
+
},
|
|
256
|
+
groupChildUnsupported: {
|
|
257
|
+
family: "groupChildUnsupported",
|
|
258
|
+
support: "fail-closed",
|
|
259
|
+
description: "Unsupported child inside an otherwise-supported group. Supported siblings are not dropped.",
|
|
260
|
+
contract: "none",
|
|
261
|
+
diagnostic: DRAWING_DIAGNOSTIC_CODES.groupChildUnsupported
|
|
262
|
+
},
|
|
263
|
+
objectEditing: {
|
|
264
|
+
family: "objectEditing",
|
|
265
|
+
support: "deferred",
|
|
266
|
+
description: "Editing/mutation of anchored/vector objects.",
|
|
267
|
+
contract: "none"
|
|
268
|
+
},
|
|
269
|
+
customWrapPolygon: {
|
|
270
|
+
family: "customWrapPolygon",
|
|
271
|
+
support: "deferred",
|
|
272
|
+
description: "Full Word-compatible text wrapping for arbitrary custom wrap polygons.",
|
|
273
|
+
contract: "none"
|
|
274
|
+
},
|
|
275
|
+
chartFidelity: {
|
|
276
|
+
family: "chartFidelity",
|
|
277
|
+
support: "deferred",
|
|
278
|
+
description: "Complete chart fidelity (a dedicated chart effort owns the parsed subset).",
|
|
279
|
+
contract: "none"
|
|
280
|
+
},
|
|
281
|
+
vmlFidelity: {
|
|
282
|
+
family: "vmlFidelity",
|
|
283
|
+
support: "deferred",
|
|
284
|
+
description: "Complete VML fidelity.",
|
|
285
|
+
contract: "none"
|
|
286
|
+
},
|
|
287
|
+
decorativeAccessibilityUi: {
|
|
288
|
+
family: "decorativeAccessibilityUi",
|
|
289
|
+
support: "deferred",
|
|
290
|
+
description: "Full accessibility UI for decorative image semantics beyond preserving source data.",
|
|
291
|
+
contract: "none"
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
const DRAWING_FAMILIES = Object.keys(DRAWING_SUPPORT_TAXONOMY);
|
|
295
|
+
const PAGE_CHECKPOINT_DEPENDENCY_CLASSES = Object.freeze([
|
|
296
|
+
"multiple-sections",
|
|
297
|
+
"furniture-page-tokens",
|
|
298
|
+
"non-balanceable-multi-column-sections",
|
|
299
|
+
"body-anchored-objects",
|
|
300
|
+
"footnotes",
|
|
301
|
+
"page-references",
|
|
302
|
+
"keep-constraints",
|
|
303
|
+
"tables",
|
|
304
|
+
"furniture-anchored-objects"
|
|
305
|
+
]);
|
|
1
306
|
function getV2TrackedChangeMutationImpact(event) {
|
|
2
307
|
if (event?.type !== "mutation:committed") return null;
|
|
3
308
|
const payload = event.origin === "history" ? event.result : event.receipt;
|
|
@@ -1262,6 +1567,11 @@ const HEAVY_DOC_READ_POLICY = [
|
|
|
1262
1567
|
note: "reserved: full sections list"
|
|
1263
1568
|
}
|
|
1264
1569
|
];
|
|
1570
|
+
var COMMENTS_CATALOG_PART_URIS = new Set([
|
|
1571
|
+
"/word/comments.xml",
|
|
1572
|
+
"/word/commentsExtended.xml",
|
|
1573
|
+
"/word/commentsIds.xml"
|
|
1574
|
+
]);
|
|
1265
1575
|
function isHeavyDocReadKey(key) {
|
|
1266
1576
|
return HEAVY_DOC_READ_POLICY.some((entry) => entry.match === "exact" ? entry.key === key : key.startsWith(entry.key));
|
|
1267
1577
|
}
|
|
@@ -2331,6 +2641,8 @@ function createSuperDocUI(options) {
|
|
|
2331
2641
|
const superdoc = options.superdoc;
|
|
2332
2642
|
const optimisticInlineValues = /* @__PURE__ */ new Map();
|
|
2333
2643
|
const optimisticInlineToggles = /* @__PURE__ */ new Map();
|
|
2644
|
+
let optimisticParagraphAlignment = null;
|
|
2645
|
+
let optimisticParagraphAlignmentGeneration = 0;
|
|
2334
2646
|
const pendingInlineToggleMutations = [];
|
|
2335
2647
|
let lastOptimisticInlineSelectionSignature = null;
|
|
2336
2648
|
let optimisticInlineToggleGeneration = 0;
|
|
@@ -2977,6 +3289,11 @@ function createSuperDocUI(options) {
|
|
|
2977
3289
|
demandedHeavyReads.set(key, token);
|
|
2978
3290
|
scheduleAsyncRefresh();
|
|
2979
3291
|
};
|
|
3292
|
+
const commentsCatalogMayHaveRows = () => {
|
|
3293
|
+
const entry = asyncReads.get("comments");
|
|
3294
|
+
if (!entry?.hasSettled) return entry?.inflightToken != null;
|
|
3295
|
+
return Array.isArray(entry.value) && entry.value.length > 0;
|
|
3296
|
+
};
|
|
2980
3297
|
const heavyReadDemandActive = (key, token) => demandedHeavyReads.get(key) === token;
|
|
2981
3298
|
const ensureContentControlsCatalog = (_reason) => {
|
|
2982
3299
|
demandHeavyDocRead("contentControls");
|
|
@@ -2993,20 +3310,28 @@ function createSuperDocUI(options) {
|
|
|
2993
3310
|
let lastTypingMutationAtMs = 0;
|
|
2994
3311
|
let heavyReadsHeldUntilIdle = false;
|
|
2995
3312
|
let heavyReadsTypingHoldSinceMs = 0;
|
|
3313
|
+
let heavyReadCeilingReleaseActive = false;
|
|
2996
3314
|
let heavyReadCompletionRecomputeTimer = null;
|
|
2997
3315
|
const scheduleHeavyReadCompletionRecompute = () => {
|
|
2998
3316
|
if (disposed || heavyReadCompletionRecomputeTimer) return;
|
|
2999
|
-
const startedAtMs = Date.now();
|
|
3317
|
+
const startedAtMs = heavyReadsTypingHoldSinceMs || Date.now();
|
|
3000
3318
|
const attempt = () => {
|
|
3001
3319
|
heavyReadCompletionRecomputeTimer = null;
|
|
3002
3320
|
if (disposed) return;
|
|
3003
3321
|
const idleForMs = Date.now() - lastEditableMutationAtMs;
|
|
3004
|
-
|
|
3322
|
+
const busy = foregroundMutationActive() || idleForMs < HEAVY_READ_IDLE_MS;
|
|
3323
|
+
if (busy && Date.now() - startedAtMs < HEAVY_READ_IDLE_CEILING_MS) {
|
|
3005
3324
|
heavyReadCompletionRecomputeTimer = setTimeout(attempt, HEAVY_READ_IDLE_POLL_MS);
|
|
3006
3325
|
return;
|
|
3007
3326
|
}
|
|
3008
3327
|
heavyReadsHeldUntilIdle = false;
|
|
3009
|
-
|
|
3328
|
+
heavyReadCeilingReleaseActive = busy;
|
|
3329
|
+
try {
|
|
3330
|
+
recompute();
|
|
3331
|
+
} finally {
|
|
3332
|
+
heavyReadCeilingReleaseActive = false;
|
|
3333
|
+
heavyReadsTypingHoldSinceMs = 0;
|
|
3334
|
+
}
|
|
3010
3335
|
};
|
|
3011
3336
|
heavyReadCompletionRecomputeTimer = setTimeout(attempt, 0);
|
|
3012
3337
|
};
|
|
@@ -3113,6 +3438,49 @@ function createSuperDocUI(options) {
|
|
|
3113
3438
|
invalidateDocumentContent();
|
|
3114
3439
|
recompute();
|
|
3115
3440
|
};
|
|
3441
|
+
let pendingPostPaintContentRefresh = null;
|
|
3442
|
+
let postPaintContentRefreshRunning = false;
|
|
3443
|
+
let postPaintContentRefreshDrainToken = 0;
|
|
3444
|
+
const resetPostPaintContentRefresh = () => {
|
|
3445
|
+
pendingPostPaintContentRefresh = null;
|
|
3446
|
+
postPaintContentRefreshRunning = false;
|
|
3447
|
+
postPaintContentRefreshDrainToken += 1;
|
|
3448
|
+
};
|
|
3449
|
+
const schedulePostPaintContentRefresh = () => {
|
|
3450
|
+
const editor = getEditor();
|
|
3451
|
+
const readiness = editor?.documentMutationReadiness;
|
|
3452
|
+
if (!editor || typeof readiness?.whenPainted !== "function") return;
|
|
3453
|
+
pendingPostPaintContentRefresh = {
|
|
3454
|
+
editor,
|
|
3455
|
+
readiness,
|
|
3456
|
+
afterEpoch: typeof readiness.getRenderEpoch === "function" ? safeCall(() => readiness.getRenderEpoch.call(readiness), null) : null
|
|
3457
|
+
};
|
|
3458
|
+
if (postPaintContentRefreshRunning) return;
|
|
3459
|
+
postPaintContentRefreshRunning = true;
|
|
3460
|
+
const drainToken = postPaintContentRefreshDrainToken;
|
|
3461
|
+
const drain = async () => {
|
|
3462
|
+
while (!disposed && drainToken === postPaintContentRefreshDrainToken) {
|
|
3463
|
+
const request = pendingPostPaintContentRefresh;
|
|
3464
|
+
pendingPostPaintContentRefresh = null;
|
|
3465
|
+
if (!request) {
|
|
3466
|
+
postPaintContentRefreshRunning = false;
|
|
3467
|
+
return;
|
|
3468
|
+
}
|
|
3469
|
+
let paintCompleted = false;
|
|
3470
|
+
try {
|
|
3471
|
+
await request.readiness.whenPainted.call(request.readiness, typeof request.afterEpoch === "number" ? { afterEpoch: request.afterEpoch } : void 0);
|
|
3472
|
+
paintCompleted = true;
|
|
3473
|
+
} catch {}
|
|
3474
|
+
if (disposed || drainToken !== postPaintContentRefreshDrainToken) return;
|
|
3475
|
+
if (getEditor() !== request.editor) {
|
|
3476
|
+
resetPostPaintContentRefresh();
|
|
3477
|
+
return;
|
|
3478
|
+
}
|
|
3479
|
+
if (paintCompleted) invalidateDocumentContentAndRecompute();
|
|
3480
|
+
}
|
|
3481
|
+
};
|
|
3482
|
+
drain();
|
|
3483
|
+
};
|
|
3116
3484
|
const scheduleTypingDocumentContentInvalidation = () => {
|
|
3117
3485
|
if (typingContentInvalidationTimer) clearTimeout(typingContentInvalidationTimer);
|
|
3118
3486
|
typingContentInvalidationTimer = setTimeout(() => {
|
|
@@ -3200,7 +3568,7 @@ function createSuperDocUI(options) {
|
|
|
3200
3568
|
status: "pending"
|
|
3201
3569
|
};
|
|
3202
3570
|
}
|
|
3203
|
-
if (heavyReadsHeldUntilIdle) {
|
|
3571
|
+
if (heavyReadsHeldUntilIdle && !heavyReadCeilingReleaseActive) {
|
|
3204
3572
|
scheduleHeavyReadCompletionRecompute();
|
|
3205
3573
|
if (entry?.hasSettled) return {
|
|
3206
3574
|
value: entry.value,
|
|
@@ -3211,21 +3579,23 @@ function createSuperDocUI(options) {
|
|
|
3211
3579
|
status: "pending"
|
|
3212
3580
|
};
|
|
3213
3581
|
}
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
if (!heavyReadsTypingHoldSinceMs
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3582
|
+
if (!heavyReadCeilingReleaseActive) {
|
|
3583
|
+
const nowMs = Date.now();
|
|
3584
|
+
if (nowMs - lastTypingMutationAtMs < HEAVY_READ_IDLE_MS && (!heavyReadsTypingHoldSinceMs || nowMs - heavyReadsTypingHoldSinceMs < HEAVY_READ_IDLE_CEILING_MS)) {
|
|
3585
|
+
if (!heavyReadsTypingHoldSinceMs) heavyReadsTypingHoldSinceMs = nowMs;
|
|
3586
|
+
heavyReadsHeldUntilIdle = true;
|
|
3587
|
+
scheduleHeavyReadCompletionRecompute();
|
|
3588
|
+
if (entry?.hasSettled) return {
|
|
3589
|
+
value: entry.value,
|
|
3590
|
+
status: "stale"
|
|
3591
|
+
};
|
|
3592
|
+
return {
|
|
3593
|
+
value: null,
|
|
3594
|
+
status: "pending"
|
|
3595
|
+
};
|
|
3596
|
+
}
|
|
3597
|
+
heavyReadsTypingHoldSinceMs = 0;
|
|
3227
3598
|
}
|
|
3228
|
-
heavyReadsTypingHoldSinceMs = 0;
|
|
3229
3599
|
}
|
|
3230
3600
|
if (foregroundMutationActive()) {
|
|
3231
3601
|
scheduleForegroundAsyncRetry();
|
|
@@ -3297,6 +3667,7 @@ function createSuperDocUI(options) {
|
|
|
3297
3667
|
const syncCoordinatorEditor = () => {
|
|
3298
3668
|
const editor = getEditor();
|
|
3299
3669
|
if (editor === lastCoordinatorEditor) return;
|
|
3670
|
+
resetPostPaintContentRefresh();
|
|
3300
3671
|
reviewMutationReconciler.reset();
|
|
3301
3672
|
reviewMutationToken = {};
|
|
3302
3673
|
lastCoordinatorEditor = editor;
|
|
@@ -3310,6 +3681,7 @@ function createSuperDocUI(options) {
|
|
|
3310
3681
|
pendingEffectiveInlineRead = null;
|
|
3311
3682
|
lastEffectiveInlineReadKey = null;
|
|
3312
3683
|
heldSettledInlineValues = null;
|
|
3684
|
+
optimisticParagraphAlignment = null;
|
|
3313
3685
|
pendingSelectionSeedValidationToken = null;
|
|
3314
3686
|
coldAsyncReadDeferrals.clear();
|
|
3315
3687
|
demandedHeavyReads.clear();
|
|
@@ -4215,6 +4587,7 @@ function createSuperDocUI(options) {
|
|
|
4215
4587
|
styleName: active.styleName
|
|
4216
4588
|
};
|
|
4217
4589
|
}
|
|
4590
|
+
if (descriptor.id === "text-align") return readToolbarParagraphAlignment(doc, selection$1);
|
|
4218
4591
|
if (descriptor.id === "link") return readActiveLinkHref(doc, selection$1) ?? void 0;
|
|
4219
4592
|
};
|
|
4220
4593
|
const readListStateSnapshotForBlock = (doc, blockId, story) => {
|
|
@@ -4266,22 +4639,160 @@ function createSuperDocUI(options) {
|
|
|
4266
4639
|
const readNodeById = (doc, blockId, story) => {
|
|
4267
4640
|
if (!doc) return {
|
|
4268
4641
|
value: null,
|
|
4269
|
-
status: "ready"
|
|
4642
|
+
status: "ready",
|
|
4643
|
+
refreshing: false
|
|
4270
4644
|
};
|
|
4271
4645
|
const storySignature = storyLocatorSignature(story);
|
|
4272
4646
|
const isBodyStory = storySignature === "story:body";
|
|
4273
4647
|
if (isBodyStory && typeof doc.getNodeById !== "function") return {
|
|
4274
4648
|
value: null,
|
|
4275
|
-
status: "ready"
|
|
4649
|
+
status: "ready",
|
|
4650
|
+
refreshing: false
|
|
4276
4651
|
};
|
|
4277
4652
|
if (!isBodyStory && typeof doc.getNode !== "function") return {
|
|
4278
4653
|
value: null,
|
|
4279
|
-
status: "ready"
|
|
4654
|
+
status: "ready",
|
|
4655
|
+
refreshing: false
|
|
4280
4656
|
};
|
|
4281
|
-
|
|
4657
|
+
const key = `node:${storySignature}:${blockId}`;
|
|
4658
|
+
const token = contentToken();
|
|
4659
|
+
const read = readAsync(key, token, () => isBodyStory ? doc.getNodeById({
|
|
4282
4660
|
nodeId: blockId,
|
|
4283
4661
|
nodeType: "paragraph"
|
|
4284
4662
|
}) : doc.getNode(paragraphTarget(blockId, story)), (raw) => raw && typeof raw === "object" ? raw : null);
|
|
4663
|
+
const entry = asyncReads.get(key);
|
|
4664
|
+
return {
|
|
4665
|
+
...read,
|
|
4666
|
+
refreshing: read.status === "stale" && entry?.inflightToken === token && entry.failedToken !== token
|
|
4667
|
+
};
|
|
4668
|
+
};
|
|
4669
|
+
const normalizeParagraphAlignment = (value) => {
|
|
4670
|
+
return value === "left" || value === "center" || value === "right" || value === "justify" ? value : void 0;
|
|
4671
|
+
};
|
|
4672
|
+
const isProjectionResolvedParagraphAlignment = (value) => {
|
|
4673
|
+
return value === "start" || value === "end" || value === "distributed" || value === "numTab" || value === "lowKashida" || value === "mediumKashida" || value === "highKashida" || value === "thaiDistribute";
|
|
4674
|
+
};
|
|
4675
|
+
const readEffectiveParagraphAlignments = (selection$1, blockIds) => {
|
|
4676
|
+
const host = getHost();
|
|
4677
|
+
const readByIds = host?.readMountedProjectionBlocksByIds;
|
|
4678
|
+
if (typeof readByIds !== "function") return null;
|
|
4679
|
+
const story = selectionStoryLocator(selection$1);
|
|
4680
|
+
const blocks = safeCall(() => story ? readByIds.call(host, [...blockIds], story) : readByIds.call(host, [...blockIds]), null);
|
|
4681
|
+
if (!Array.isArray(blocks)) return /* @__PURE__ */ new Map();
|
|
4682
|
+
const projectionBlocks = collectProjectionTextBlocks(blocks);
|
|
4683
|
+
const alignments = /* @__PURE__ */ new Map();
|
|
4684
|
+
for (const blockId of blockIds) {
|
|
4685
|
+
const block = projectionBlocks.find((candidate) => projectionBlockMatchesId(candidate, blockId));
|
|
4686
|
+
if (!block) continue;
|
|
4687
|
+
const attrs = block.attrs;
|
|
4688
|
+
const alignment = normalizeParagraphAlignment(attrs?.alignment);
|
|
4689
|
+
const inlineDirection = getParagraphInlineDirection(attrs);
|
|
4690
|
+
alignments.set(blockId, alignment ?? (inlineDirection === "rtl" ? "right" : "left"));
|
|
4691
|
+
}
|
|
4692
|
+
return alignments;
|
|
4693
|
+
};
|
|
4694
|
+
const readParagraphAlignment = (doc, blockId, story, effectiveAlignments) => {
|
|
4695
|
+
const { value: result, status, refreshing } = readNodeById(doc, blockId, story);
|
|
4696
|
+
const effective = effectiveAlignments?.get(blockId);
|
|
4697
|
+
if (status === "pending") return effective ? {
|
|
4698
|
+
status: "uniform",
|
|
4699
|
+
value: effective
|
|
4700
|
+
} : { status: "pending" };
|
|
4701
|
+
if (status === "stale" && !refreshing) return { status: "pending" };
|
|
4702
|
+
if (status === "stale" && effective) return {
|
|
4703
|
+
status: "uniform",
|
|
4704
|
+
value: effective
|
|
4705
|
+
};
|
|
4706
|
+
if (status === "stale" && effectiveAlignments && !effective) return { status: "unavailable" };
|
|
4707
|
+
if (!result) return { status: "unavailable" };
|
|
4708
|
+
const node = result.node;
|
|
4709
|
+
if (!node) return { status: "unavailable" };
|
|
4710
|
+
const kind = node.kind;
|
|
4711
|
+
if (kind !== "paragraph" && kind !== "heading") return { status: "unavailable" };
|
|
4712
|
+
const payload = node[kind];
|
|
4713
|
+
if (!payload || typeof payload !== "object") return { status: "unavailable" };
|
|
4714
|
+
const directAlignment = payload.props?.alignment;
|
|
4715
|
+
if (directAlignment == null) return effective ? {
|
|
4716
|
+
status: "uniform",
|
|
4717
|
+
value: effective
|
|
4718
|
+
} : { status: "unavailable" };
|
|
4719
|
+
const alignment = normalizeParagraphAlignment(directAlignment);
|
|
4720
|
+
if (alignment) return {
|
|
4721
|
+
status: "uniform",
|
|
4722
|
+
value: alignment
|
|
4723
|
+
};
|
|
4724
|
+
if (isProjectionResolvedParagraphAlignment(directAlignment) && effective) return {
|
|
4725
|
+
status: "uniform",
|
|
4726
|
+
value: effective
|
|
4727
|
+
};
|
|
4728
|
+
return { status: "unavailable" };
|
|
4729
|
+
};
|
|
4730
|
+
const readUniformParagraphAlignment = (doc, selection$1) => {
|
|
4731
|
+
const blockIds = selectionBlockIds(selection$1);
|
|
4732
|
+
if (blockIds.length === 0 || !canProbeEverySelectedBlock(blockIds)) return { status: "unavailable" };
|
|
4733
|
+
const story = selectionStory(selection$1);
|
|
4734
|
+
const effectiveAlignments = readEffectiveParagraphAlignments(selection$1, blockIds);
|
|
4735
|
+
const first = readParagraphAlignment(doc, blockIds[0], story, effectiveAlignments);
|
|
4736
|
+
if (first.status !== "uniform") return first;
|
|
4737
|
+
for (const blockId of blockIds.slice(1)) {
|
|
4738
|
+
const next = readParagraphAlignment(doc, blockId, story, effectiveAlignments);
|
|
4739
|
+
if (next.status !== "uniform") return next;
|
|
4740
|
+
if (next.value !== first.value) return { status: "mixed" };
|
|
4741
|
+
}
|
|
4742
|
+
return first;
|
|
4743
|
+
};
|
|
4744
|
+
const paragraphAlignmentSelectionSignature = (selection$1) => {
|
|
4745
|
+
const blockIds = selectionBlockIds(selection$1);
|
|
4746
|
+
if (blockIds.length === 0) return null;
|
|
4747
|
+
return `${storyLocatorSignature(selectionStory(selection$1))}:${blockIds.join(",")}`;
|
|
4748
|
+
};
|
|
4749
|
+
const readToolbarParagraphAlignment = (doc, selection$1) => {
|
|
4750
|
+
const resolution = readUniformParagraphAlignment(doc, selection$1);
|
|
4751
|
+
const resolved = resolution.status === "uniform" ? resolution.value : void 0;
|
|
4752
|
+
const optimistic = optimisticParagraphAlignment;
|
|
4753
|
+
if (!optimistic) return resolved;
|
|
4754
|
+
const selectionSignature$1 = paragraphAlignmentSelectionSignature(selection$1);
|
|
4755
|
+
if (selectionSignature$1 && selectionSignature$1 !== optimistic.selectionSignature) {
|
|
4756
|
+
optimisticParagraphAlignment = null;
|
|
4757
|
+
return resolved;
|
|
4758
|
+
}
|
|
4759
|
+
if (!selectionSignature$1) return optimistic.value;
|
|
4760
|
+
if (!optimistic.settled) return optimistic.value;
|
|
4761
|
+
if (resolution.status !== "pending") {
|
|
4762
|
+
optimisticParagraphAlignment = null;
|
|
4763
|
+
return resolved;
|
|
4764
|
+
}
|
|
4765
|
+
return optimistic.value;
|
|
4766
|
+
};
|
|
4767
|
+
const armOptimisticParagraphAlignment = (selection$1, payload) => {
|
|
4768
|
+
const alignment = normalizeParagraphAlignment(payload);
|
|
4769
|
+
const selectionSignature$1 = paragraphAlignmentSelectionSignature(selection$1);
|
|
4770
|
+
const blockIds = selectionBlockIds(selection$1);
|
|
4771
|
+
if (!alignment || !selectionSignature$1 || blockIds.length === 0) return null;
|
|
4772
|
+
const generation = ++optimisticParagraphAlignmentGeneration;
|
|
4773
|
+
optimisticParagraphAlignment = {
|
|
4774
|
+
selectionSignature: selectionSignature$1,
|
|
4775
|
+
value: alignment,
|
|
4776
|
+
generation,
|
|
4777
|
+
settled: false,
|
|
4778
|
+
canReconcile: canProbeEverySelectedBlock(blockIds)
|
|
4779
|
+
};
|
|
4780
|
+
recompute();
|
|
4781
|
+
return generation;
|
|
4782
|
+
};
|
|
4783
|
+
const settleOptimisticParagraphAlignment = (generation, result) => {
|
|
4784
|
+
if (generation == null) return;
|
|
4785
|
+
const optimistic = optimisticParagraphAlignment;
|
|
4786
|
+
if (!optimistic || optimistic.generation !== generation) return;
|
|
4787
|
+
if (!commandResultSucceeded(result)) {
|
|
4788
|
+
optimisticParagraphAlignment = null;
|
|
4789
|
+
return;
|
|
4790
|
+
}
|
|
4791
|
+
if (!optimistic.canReconcile) {
|
|
4792
|
+
optimisticParagraphAlignment = null;
|
|
4793
|
+
return;
|
|
4794
|
+
}
|
|
4795
|
+
optimistic.settled = true;
|
|
4285
4796
|
};
|
|
4286
4797
|
const resolveListMembershipForBlockAsync = async (doc, blockId, story) => {
|
|
4287
4798
|
const listsApi = doc?.lists;
|
|
@@ -4932,12 +5443,12 @@ function createSuperDocUI(options) {
|
|
|
4932
5443
|
}
|
|
4933
5444
|
return;
|
|
4934
5445
|
}
|
|
5446
|
+
if (type === "mutation:committed" || type === "collaboration:remote-changed") lastEditableMutationAtMs = Date.now();
|
|
4935
5447
|
if (type === "mutation:committed") {
|
|
4936
|
-
lastEditableMutationAtMs = Date.now();
|
|
4937
5448
|
clearAuthoritativeTrackChangesRetry();
|
|
4938
5449
|
reviewMutationToken = {};
|
|
4939
5450
|
}
|
|
4940
|
-
if (type === "mutation:committed" || type === "save:completed") {
|
|
5451
|
+
if (type === "mutation:committed" || type === "save:completed" || type === "collaboration:remote-changed") {
|
|
4941
5452
|
const impact = type === "mutation:committed" ? getV2TrackedChangeMutationImpact(event) : null;
|
|
4942
5453
|
const supersedesPendingReviewReconcile = type === "mutation:committed" && reviewMutationReconciler.getPendingIds().size > 0;
|
|
4943
5454
|
if (impact?.removedIds.size) markPostDecisionTrackChanges(new Set(impact.removedIds), event.receipt);
|
|
@@ -4967,13 +5478,20 @@ function createSuperDocUI(options) {
|
|
|
4967
5478
|
}
|
|
4968
5479
|
}
|
|
4969
5480
|
if (authoritativeHistoryImpact) return;
|
|
4970
|
-
|
|
4971
|
-
|
|
5481
|
+
const isTypingBurst = type === "mutation:committed" && isEditableTextMutationEvent(event) || type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0;
|
|
5482
|
+
if (isTypingBurst) lastTypingMutationAtMs = Date.now();
|
|
5483
|
+
if (type === "mutation:committed" && isTypingBurst) {
|
|
4972
5484
|
scheduleTypingDocumentContentInvalidation();
|
|
4973
5485
|
return;
|
|
4974
5486
|
}
|
|
4975
5487
|
if (impact?.removedIds.size && impact.upsertIds.size === 0) return;
|
|
4976
|
-
|
|
5488
|
+
if (type === "collaboration:remote-changed" || type === "mutation:committed" && !isTypingBurst) schedulePostPaintContentRefresh();
|
|
5489
|
+
const remoteCommentsPartChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedPartUris) && event.changedPartUris.some((partUri) => typeof partUri === "string" && COMMENTS_CATALOG_PART_URIS.has(partUri));
|
|
5490
|
+
const loadedCommentAnchorsMayHaveChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0 && commentsCatalogMayHaveRows();
|
|
5491
|
+
if (remoteCommentsPartChanged && !isTypingBurst) heavyReadsHeldUntilIdle = true;
|
|
5492
|
+
invalidateDocumentContent();
|
|
5493
|
+
if (remoteCommentsPartChanged || loadedCommentAnchorsMayHaveChanged) demandHeavyDocRead("comments");
|
|
5494
|
+
recompute();
|
|
4977
5495
|
}
|
|
4978
5496
|
});
|
|
4979
5497
|
if (typeof off === "function") detachHostEvents = off;
|
|
@@ -6100,7 +6618,13 @@ function createSuperDocUI(options) {
|
|
|
6100
6618
|
return false;
|
|
6101
6619
|
}
|
|
6102
6620
|
}
|
|
6103
|
-
if (descriptor.blockParagraph)
|
|
6621
|
+
if (descriptor.blockParagraph) {
|
|
6622
|
+
const result = executeBlockParagraph(descriptor, op, normalized);
|
|
6623
|
+
const optimisticAlignmentGeneration = descriptor.blockParagraph.kind === "alignment" && commandResultSucceeded(result) ? armOptimisticParagraphAlignment(state.selection, normalized) : null;
|
|
6624
|
+
return settleCommandExecution(result, (settled) => {
|
|
6625
|
+
settleOptimisticParagraphAlignment(optimisticAlignmentGeneration, settled);
|
|
6626
|
+
});
|
|
6627
|
+
}
|
|
6104
6628
|
if (descriptor.list) return settleCommandExecution(executeListCommand(descriptor, op));
|
|
6105
6629
|
if (descriptor.link) return settleCommandExecution(executeLinkCommand(normalized));
|
|
6106
6630
|
if (descriptor.create) return settleCommandExecution(executeCreateCommand(descriptor, op, normalized));
|
|
@@ -8206,6 +8730,12 @@ Object.defineProperty(exports, "BUILT_IN_COMMAND_IDS", {
|
|
|
8206
8730
|
return BUILT_IN_COMMAND_IDS;
|
|
8207
8731
|
}
|
|
8208
8732
|
});
|
|
8733
|
+
Object.defineProperty(exports, "composeAuthorColorResolver", {
|
|
8734
|
+
enumerable: true,
|
|
8735
|
+
get: function() {
|
|
8736
|
+
return composeAuthorColorResolver;
|
|
8737
|
+
}
|
|
8738
|
+
});
|
|
8209
8739
|
Object.defineProperty(exports, "createSuperDocUI", {
|
|
8210
8740
|
enumerable: true,
|
|
8211
8741
|
get: function() {
|