superdoc 2.20.0-next.9 → 2.20.1-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/chunks/{create-super-doc-ui-B8olYVBF.es.js → create-super-doc-ui-B4_V1haj.es.js} +160 -10
- package/dist/chunks/{create-super-doc-ui-Dc2QEczb.cjs → create-super-doc-ui-DFCfYEpW.cjs} +160 -10
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/document-api/src/contract/operation-definitions.d.ts +1 -1
- package/dist/layout-engine/contracts/src/index.d.ts +1 -0
- package/dist/layout-engine/layout-bridge/src/index.d.ts +0 -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 +87 -86
- package/dist/style.layered.css +87 -86
- package/dist/superdoc/src/core/types/index.d.ts +4 -2
- package/dist/superdoc/src/internal/toolbar/built-in/default-items.d.ts +1 -1
- package/dist/superdoc/src/public/ui/types.d.ts +21 -2
- package/dist/superdoc/src/public/ui.d.cts +4 -0
- package/dist/superdoc/src/public/ui.d.ts +1 -1
- package/dist/superdoc.cjs +73 -19
- package/dist/superdoc.es.js +73 -19
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +38 -38
- package/package.json +2 -2
- package/dist/layout-engine/layout-bridge/src/hydrateTableTextboxMeasures.d.ts +0 -9
package/README.md
CHANGED
|
@@ -28,3 +28,29 @@ See [package compatibility](https://docs.superdoc.dev/resources/package-compatib
|
|
|
28
28
|
## License
|
|
29
29
|
|
|
30
30
|
AGPL-3.0. Commercial licenses are available from [SuperDoc](https://www.superdoc.dev).
|
|
31
|
+
|
|
32
|
+
## Navigate to a bookmark
|
|
33
|
+
|
|
34
|
+
After the V2 browser editor is ready, navigate by an exact bookmark name:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
const result = await editor.ui.bookmarks.navigateTo('Terms');
|
|
38
|
+
if (!result.success) console.log(result.reason);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
You can also pass a `BookmarkAddress` returned by `editor.activeEditor.doc.bookmarks.get()`
|
|
42
|
+
or `.list()`. The method reveals the bookmark's start and selects its complete range,
|
|
43
|
+
including across paragraphs. A collapsed bookmark places a caret. It supports editing,
|
|
44
|
+
suggesting, and viewing modes. Navigation stays local in a shared room and does not change
|
|
45
|
+
content or another client's selection. It does not take native keyboard focus.
|
|
46
|
+
|
|
47
|
+
Scrolling defaults to instant, centered navigation. Pass `{ block: 'start', behavior: 'auto' }`
|
|
48
|
+
as a second argument to change alignment or scrolling behavior.
|
|
49
|
+
|
|
50
|
+
The first release supports body bookmarks. Non-body and table-column bookmarks, malformed,
|
|
51
|
+
missing, deleted, or ambiguous targets return `{ success: false, ok: false, reason: 'target-unresolved' }`.
|
|
52
|
+
Name-only lookup requires a unique match across the document; an explicit body address scopes
|
|
53
|
+
lookup to the body. Resolution or reveal failure preserves the existing selection. Navigation
|
|
54
|
+
abandons stale work after content changes, document replacement, or a newer request, and times
|
|
55
|
+
out after 15 seconds. Missing editor or host capabilities return their readiness or availability
|
|
56
|
+
reason. The handle and address types are exported from `superdoc/ui`.
|
package/dist/chunks/{create-super-doc-ui-B8olYVBF.es.js → create-super-doc-ui-B4_V1haj.es.js}
RENAMED
|
@@ -4219,6 +4219,14 @@ function readCollapsedHostTrackChangeId(snapshot) {
|
|
|
4219
4219
|
const focusId = focusVisual?.trackChangeId;
|
|
4220
4220
|
return typeof anchorId === "string" && anchorId.length > 0 && anchorId === focusId ? anchorId : null;
|
|
4221
4221
|
}
|
|
4222
|
+
function isNonCollapsedHostSelection(snapshot) {
|
|
4223
|
+
if (!snapshot || typeof snapshot !== "object") return false;
|
|
4224
|
+
const record = snapshot;
|
|
4225
|
+
const anchor = record.anchor;
|
|
4226
|
+
const focus = record.focus;
|
|
4227
|
+
if (typeof anchor?.blockId !== "string" || !anchor.blockId || typeof focus?.blockId !== "string" || !focus.blockId || !Number.isFinite(anchor.blockOffset) || !Number.isFinite(focus.blockOffset)) return false;
|
|
4228
|
+
return anchor.blockId !== focus.blockId || anchor.blockOffset !== focus.blockOffset || Number.isFinite(anchor.trackedBlockOffset) && Number.isFinite(focus.trackedBlockOffset) && anchor.trackedBlockOffset !== focus.trackedBlockOffset;
|
|
4229
|
+
}
|
|
4222
4230
|
var trackedChangeIdContextCache = /* @__PURE__ */ new WeakMap();
|
|
4223
4231
|
/**
|
|
4224
4232
|
* Collect the raw source-provenance ids a tracked-change list item exposes,
|
|
@@ -6250,7 +6258,7 @@ function createSuperDocUI(options) {
|
|
|
6250
6258
|
}
|
|
6251
6259
|
if (pendingPostPaintSelectionRefresh) continue;
|
|
6252
6260
|
selectionEpoch += 1;
|
|
6253
|
-
|
|
6261
|
+
refreshSelectionFromHost();
|
|
6254
6262
|
recompute(paintCompleted ? "post-paint-selection" : "post-paint-selection-failed");
|
|
6255
6263
|
}
|
|
6256
6264
|
};
|
|
@@ -6647,8 +6655,9 @@ function createSuperDocUI(options) {
|
|
|
6647
6655
|
* effective font resolved from it) on the next recompute, instead of serving
|
|
6648
6656
|
* the previous selection until the worker `selection.current` round-trip lands
|
|
6649
6657
|
* (SD-3652). Only a resolvable COLLAPSED CARET is seeded - a range's snapshot
|
|
6650
|
-
* cannot be resolved synchronously in worker mode, so
|
|
6651
|
-
* read
|
|
6658
|
+
* cannot be resolved synchronously in worker mode, so a new range starts an
|
|
6659
|
+
* authoritative async read without waiting for the input-idle gate (SD-5394).
|
|
6660
|
+
* Seeding an empty value would wrongly disable range-only commands. The
|
|
6652
6661
|
* authoritative async read still overwrites marks/text/review overlap, but
|
|
6653
6662
|
* foreground typing defers and coalesces that worker hop through the shared
|
|
6654
6663
|
* retry gate. Previous marks are carried forward for toolbar continuity. A
|
|
@@ -6656,14 +6665,19 @@ function createSuperDocUI(options) {
|
|
|
6656
6665
|
* same carrier, or while an active typing dispatch advances the same caret by
|
|
6657
6666
|
* one code point. Pending work alone never carries review command context.
|
|
6658
6667
|
*/
|
|
6659
|
-
const
|
|
6668
|
+
const refreshSelectionFromHost = (hostSelectionSnapshot) => {
|
|
6669
|
+
const foreground = foregroundMutationState();
|
|
6670
|
+
if (isNonCollapsedHostSelection(hostSelectionSnapshot) && !(foreground && foreground.active > 0)) {
|
|
6671
|
+
pendingSelectionSeedValidationToken = null;
|
|
6672
|
+
issueAsyncRead("selection", selectionReadToken(), selectionCurrentRun, normalizeSelectionInfo);
|
|
6673
|
+
return;
|
|
6674
|
+
}
|
|
6660
6675
|
const host = getHost();
|
|
6661
6676
|
const read = host?.readLiveSelectionSyncSnapshot;
|
|
6662
6677
|
if (typeof read !== "function") return;
|
|
6663
6678
|
const seed = normalizeSelectionInfo(safeCall(() => read.call(host), null));
|
|
6664
6679
|
if (!seed || !isCollapsedCaretSnapshot(seed)) return;
|
|
6665
6680
|
const token = selectionReadToken();
|
|
6666
|
-
const foreground = foregroundMutationState();
|
|
6667
6681
|
const deferAuthoritativeRead = Boolean(foreground && (foreground.active > 0 || foreground.pending > 0));
|
|
6668
6682
|
if (!deferAuthoritativeRead) {
|
|
6669
6683
|
pendingSelectionSeedValidationToken = null;
|
|
@@ -8895,7 +8909,7 @@ function createSuperDocUI(options) {
|
|
|
8895
8909
|
const unsubscribe = next.subscribe((snapshot) => {
|
|
8896
8910
|
if (foregroundMutationActive() && caretSelectionNeedsProjectionPaint() && schedulePostPaintSelectionRefresh()) return;
|
|
8897
8911
|
selectionEpoch += 1;
|
|
8898
|
-
|
|
8912
|
+
refreshSelectionFromHost(snapshot);
|
|
8899
8913
|
recompute("host-selection");
|
|
8900
8914
|
});
|
|
8901
8915
|
if (typeof unsubscribe === "function") detachHostSelection = unsubscribe;
|
|
@@ -11274,6 +11288,113 @@ function createSuperDocUI(options) {
|
|
|
11274
11288
|
};
|
|
11275
11289
|
}
|
|
11276
11290
|
};
|
|
11291
|
+
let bookmarkNavigationGeneration = 0;
|
|
11292
|
+
documentResetHooks.push(() => {
|
|
11293
|
+
bookmarkNavigationGeneration += 1;
|
|
11294
|
+
});
|
|
11295
|
+
const bookmarks = { navigateTo: async (input, options) => {
|
|
11296
|
+
const generation = ++bookmarkNavigationGeneration;
|
|
11297
|
+
const unresolved = () => ({
|
|
11298
|
+
success: false,
|
|
11299
|
+
ok: false,
|
|
11300
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
11301
|
+
});
|
|
11302
|
+
const address = typeof input === "string" ? {
|
|
11303
|
+
kind: "entity",
|
|
11304
|
+
entityType: "bookmark",
|
|
11305
|
+
name: input
|
|
11306
|
+
} : input;
|
|
11307
|
+
if (!address || address.kind !== "entity" || address.entityType !== "bookmark" || typeof address.name !== "string" || address.name.length === 0 || address.story !== void 0 && (!address.story || address.story.kind !== "story" || address.story.storyType !== "body")) return unresolved();
|
|
11308
|
+
const editor = getEditor();
|
|
11309
|
+
if (!editor || disposed) return {
|
|
11310
|
+
success: false,
|
|
11311
|
+
ok: false,
|
|
11312
|
+
reason: SUPERDOC_UI_REASONS.notReady
|
|
11313
|
+
};
|
|
11314
|
+
const doc = getDoc();
|
|
11315
|
+
const api = doc?.bookmarks;
|
|
11316
|
+
if (typeof api?.list !== "function" || typeof api?.get !== "function") return {
|
|
11317
|
+
success: false,
|
|
11318
|
+
ok: false,
|
|
11319
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
11320
|
+
};
|
|
11321
|
+
const helper = getSelectionApplyHelper();
|
|
11322
|
+
if (!("helper" in helper)) return {
|
|
11323
|
+
success: false,
|
|
11324
|
+
ok: false,
|
|
11325
|
+
reason: helper.reason
|
|
11326
|
+
};
|
|
11327
|
+
const host = getHost();
|
|
11328
|
+
if (typeof host?.scrollTargetIntoView !== "function") return {
|
|
11329
|
+
success: false,
|
|
11330
|
+
ok: false,
|
|
11331
|
+
reason: SUPERDOC_UI_REASONS.hostCapabilityUnavailable
|
|
11332
|
+
};
|
|
11333
|
+
const token = metadataResolutionToken();
|
|
11334
|
+
let active = true;
|
|
11335
|
+
const current = () => active && !disposed && generation === bookmarkNavigationGeneration && getEditor() === editor && getDoc() === doc && getHost() === host && metadataResolutionToken() === token;
|
|
11336
|
+
const run = async () => {
|
|
11337
|
+
try {
|
|
11338
|
+
const directory = await api.list.call(api, address.story ? { in: address.story } : {});
|
|
11339
|
+
if (!current()) return unresolved();
|
|
11340
|
+
if ((Array.isArray(directory?.items) ? directory.items : []).filter((item) => item?.name === address.name).length !== 1) return unresolved();
|
|
11341
|
+
const info = await api.get.call(api, { target: address });
|
|
11342
|
+
if (!current()) return unresolved();
|
|
11343
|
+
const from = info?.range?.from;
|
|
11344
|
+
const to = info?.range?.to;
|
|
11345
|
+
const pointValid = (point) => typeof point?.blockId === "string" && point.blockId.length > 0 && Number.isInteger(point.offset) && point.offset >= 0;
|
|
11346
|
+
if (info?.name !== address.name || info?.address?.story && info.address.story.storyType !== "body" || info?.tableColumn || !pointValid(from) || !pointValid(to) || from.blockId === to.blockId && from.offset > to.offset) return unresolved();
|
|
11347
|
+
const result = await scrollTargetIntoView({
|
|
11348
|
+
kind: "text",
|
|
11349
|
+
segments: [{
|
|
11350
|
+
blockId: from.blockId,
|
|
11351
|
+
range: {
|
|
11352
|
+
start: from.offset,
|
|
11353
|
+
end: from.offset
|
|
11354
|
+
}
|
|
11355
|
+
}]
|
|
11356
|
+
}, {
|
|
11357
|
+
block: options?.block ?? "center",
|
|
11358
|
+
behavior: options?.behavior ?? "instant",
|
|
11359
|
+
shouldContinue: current
|
|
11360
|
+
});
|
|
11361
|
+
if (!current()) return unresolved();
|
|
11362
|
+
if (!result.ok) return result;
|
|
11363
|
+
const applied = selection.apply({
|
|
11364
|
+
kind: "selection",
|
|
11365
|
+
start: {
|
|
11366
|
+
kind: "text",
|
|
11367
|
+
blockId: from.blockId,
|
|
11368
|
+
offset: from.offset
|
|
11369
|
+
},
|
|
11370
|
+
end: {
|
|
11371
|
+
kind: "text",
|
|
11372
|
+
blockId: to.blockId,
|
|
11373
|
+
offset: to.offset
|
|
11374
|
+
}
|
|
11375
|
+
});
|
|
11376
|
+
return {
|
|
11377
|
+
...applied,
|
|
11378
|
+
success: applied.ok
|
|
11379
|
+
};
|
|
11380
|
+
} catch {
|
|
11381
|
+
return unresolved();
|
|
11382
|
+
}
|
|
11383
|
+
};
|
|
11384
|
+
let timer;
|
|
11385
|
+
const timeout = new Promise((resolve) => {
|
|
11386
|
+
timer = setTimeout(() => {
|
|
11387
|
+
active = false;
|
|
11388
|
+
resolve(unresolved());
|
|
11389
|
+
}, 15e3);
|
|
11390
|
+
});
|
|
11391
|
+
try {
|
|
11392
|
+
return await Promise.race([run(), timeout]);
|
|
11393
|
+
} finally {
|
|
11394
|
+
active = false;
|
|
11395
|
+
clearTimeout(timer);
|
|
11396
|
+
}
|
|
11397
|
+
} };
|
|
11277
11398
|
/**
|
|
11278
11399
|
* Derive the browser-shell's `importedId` carrier-lookup alias from a
|
|
11279
11400
|
* public list row's `wordRevisionIds` / `sourceIds` provenance fields,
|
|
@@ -12507,6 +12628,7 @@ function createSuperDocUI(options) {
|
|
|
12507
12628
|
};
|
|
12508
12629
|
let searchRequestGeneration = 0;
|
|
12509
12630
|
let pendingFallbackGeneration = null;
|
|
12631
|
+
let completedFallbackSearch = null;
|
|
12510
12632
|
/**
|
|
12511
12633
|
* How to tear down the session that is currently open, captured when it was
|
|
12512
12634
|
* opened.
|
|
@@ -12555,6 +12677,7 @@ function createSuperDocUI(options) {
|
|
|
12555
12677
|
* is deliberately not made here.
|
|
12556
12678
|
*/
|
|
12557
12679
|
const resetSearchForActiveEditorChange = () => {
|
|
12680
|
+
completedFallbackSearch = null;
|
|
12558
12681
|
searchRequestGeneration += 1;
|
|
12559
12682
|
pendingFallbackGeneration = null;
|
|
12560
12683
|
shellFallbackOutstanding = false;
|
|
@@ -12608,8 +12731,8 @@ function createSuperDocUI(options) {
|
|
|
12608
12731
|
const editSearch = getEditCommandSearch();
|
|
12609
12732
|
if (editSearch && typeof editSearch.query === "function") safeCall(() => editSearch.query({ query: "" }), null);
|
|
12610
12733
|
};
|
|
12611
|
-
const readEditCommandCanReplace = () => readEditCommandStateEntry("find.replace")?.enabled === true;
|
|
12612
|
-
const readEditCommandCanReplaceAll = () => readEditCommandStateEntry("find.replaceAll")?.enabled === true;
|
|
12734
|
+
const readEditCommandCanReplace = () => pendingFallbackGeneration !== searchRequestGeneration && readEditCommandStateEntry("find.replace")?.enabled === true;
|
|
12735
|
+
const readEditCommandCanReplaceAll = () => pendingFallbackGeneration !== searchRequestGeneration && readEditCommandStateEntry("find.replaceAll")?.enabled === true;
|
|
12613
12736
|
const applyHostSearchResult = (result, fallbackCanReplace = false, fallbackCanReplaceAll = fallbackCanReplace) => {
|
|
12614
12737
|
const snapshot = normalizeHostSearchResult(result, fallbackCanReplace, fallbackCanReplaceAll);
|
|
12615
12738
|
if (!snapshot) {
|
|
@@ -12770,6 +12893,7 @@ function createSuperDocUI(options) {
|
|
|
12770
12893
|
return { ok: true };
|
|
12771
12894
|
},
|
|
12772
12895
|
close: () => {
|
|
12896
|
+
completedFallbackSearch = null;
|
|
12773
12897
|
searchRequestGeneration += 1;
|
|
12774
12898
|
cancelRefreshShellSearch();
|
|
12775
12899
|
if (releaseActiveSearchSession) releaseSearchSession();
|
|
@@ -12794,6 +12918,16 @@ function createSuperDocUI(options) {
|
|
|
12794
12918
|
const caseSensitive = Boolean(options?.caseSensitive);
|
|
12795
12919
|
const includeDeletedText = (options?.includeTrackedDeletions ?? options?.includeDeletedText) === true;
|
|
12796
12920
|
const regex = options?.regex === true;
|
|
12921
|
+
if ((!host || typeof host.setSession !== "function") && completedFallbackSearch !== null && completedFallbackSearch === getEditCommandSearch() && pendingFallbackGeneration !== searchRequestGeneration && searchRefreshTimer === null && searchState.open && searchState.available && !searchState.reason && searchState.query === query && searchState.caseSensitive === caseSensitive && searchState.includeDeletedText === includeDeletedText && searchState.regex === regex) {
|
|
12922
|
+
syncSearchStateFromHost();
|
|
12923
|
+
emitSearch();
|
|
12924
|
+
return searchState;
|
|
12925
|
+
}
|
|
12926
|
+
completedFallbackSearch = null;
|
|
12927
|
+
if (searchRefreshTimer !== null) {
|
|
12928
|
+
clearTimeout(searchRefreshTimer);
|
|
12929
|
+
searchRefreshTimer = null;
|
|
12930
|
+
}
|
|
12797
12931
|
const generation = ++searchRequestGeneration;
|
|
12798
12932
|
cancelRefreshShellSearch();
|
|
12799
12933
|
cancelOutstandingShellFallback();
|
|
@@ -12829,6 +12963,7 @@ function createSuperDocUI(options) {
|
|
|
12829
12963
|
if (generation !== searchRequestGeneration) return;
|
|
12830
12964
|
shellFallbackOutstanding = false;
|
|
12831
12965
|
pendingFallbackGeneration = null;
|
|
12966
|
+
completedFallbackSearch = editSearch;
|
|
12832
12967
|
applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
|
|
12833
12968
|
}, () => {
|
|
12834
12969
|
if (generation !== searchRequestGeneration) return;
|
|
@@ -12841,6 +12976,7 @@ function createSuperDocUI(options) {
|
|
|
12841
12976
|
return searchState;
|
|
12842
12977
|
}
|
|
12843
12978
|
pendingFallbackGeneration = null;
|
|
12979
|
+
completedFallbackSearch = editSearch;
|
|
12844
12980
|
applyHostSearchResult(result, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
|
|
12845
12981
|
applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace(), readEditCommandCanReplaceAll());
|
|
12846
12982
|
return searchState;
|
|
@@ -12983,6 +13119,7 @@ function createSuperDocUI(options) {
|
|
|
12983
13119
|
return { ok: true };
|
|
12984
13120
|
},
|
|
12985
13121
|
clear: () => {
|
|
13122
|
+
completedFallbackSearch = null;
|
|
12986
13123
|
searchRequestGeneration += 1;
|
|
12987
13124
|
cancelRefreshShellSearch();
|
|
12988
13125
|
cancelOutstandingShellFallback();
|
|
@@ -13098,6 +13235,7 @@ function createSuperDocUI(options) {
|
|
|
13098
13235
|
};
|
|
13099
13236
|
let searchRefreshTimer = null;
|
|
13100
13237
|
scheduleActiveSearchRefresh = () => {
|
|
13238
|
+
completedFallbackSearch = null;
|
|
13101
13239
|
if (searchRefreshTimer !== null) clearTimeout(searchRefreshTimer);
|
|
13102
13240
|
if (!searchState.open || !searchState.query) return;
|
|
13103
13241
|
const scheduledGeneration = searchRequestGeneration;
|
|
@@ -13124,19 +13262,29 @@ function createSuperDocUI(options) {
|
|
|
13124
13262
|
const result = typeof editSearch?.refresh === "function" ? safeCall(() => editSearch.refresh(input), null) : safeCall(() => host.refresh(), null);
|
|
13125
13263
|
if (isPromiseLike(result)) {
|
|
13126
13264
|
pendingFallbackGeneration = generation;
|
|
13265
|
+
setSearchState({
|
|
13266
|
+
canReplace: false,
|
|
13267
|
+
canReplaceAll: false
|
|
13268
|
+
});
|
|
13127
13269
|
Promise.resolve(result).then((resolved) => {
|
|
13128
13270
|
if (generation !== searchRequestGeneration || disposed) return;
|
|
13271
|
+
releaseRefreshShellSearch = null;
|
|
13129
13272
|
pendingFallbackGeneration = null;
|
|
13273
|
+
completedFallbackSearch = editSearch;
|
|
13130
13274
|
applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
|
|
13131
13275
|
}, () => {
|
|
13132
13276
|
if (generation !== searchRequestGeneration || disposed) return;
|
|
13133
|
-
|
|
13277
|
+
releaseRefreshShellSearch = null;
|
|
13134
13278
|
setSearchState({
|
|
13135
13279
|
available: false,
|
|
13136
13280
|
reason: SUPERDOC_UI_REASONS.searchUnavailable
|
|
13137
13281
|
});
|
|
13138
13282
|
});
|
|
13139
|
-
} else if (result !== null)
|
|
13283
|
+
} else if (result !== null) {
|
|
13284
|
+
releaseRefreshShellSearch = null;
|
|
13285
|
+
completedFallbackSearch = editSearch;
|
|
13286
|
+
applyHostSearchResult(result);
|
|
13287
|
+
}
|
|
13140
13288
|
}, 120);
|
|
13141
13289
|
};
|
|
13142
13290
|
const stylesSub = sliceHandle((s) => s.styles);
|
|
@@ -13186,6 +13334,7 @@ function createSuperDocUI(options) {
|
|
|
13186
13334
|
watermark.destroy();
|
|
13187
13335
|
clearContentControlHighlight();
|
|
13188
13336
|
disposed = true;
|
|
13337
|
+
completedFallbackSearch = null;
|
|
13189
13338
|
if (searchRefreshTimer !== null) clearTimeout(searchRefreshTimer);
|
|
13190
13339
|
searchRefreshTimer = null;
|
|
13191
13340
|
cancelRefreshShellSearch();
|
|
@@ -13261,6 +13410,7 @@ function createSuperDocUI(options) {
|
|
|
13261
13410
|
comments,
|
|
13262
13411
|
trackChanges,
|
|
13263
13412
|
contentControls,
|
|
13413
|
+
bookmarks,
|
|
13264
13414
|
fonts,
|
|
13265
13415
|
zoom,
|
|
13266
13416
|
document: documentHandle,
|
|
@@ -4220,6 +4220,14 @@ function readCollapsedHostTrackChangeId(snapshot) {
|
|
|
4220
4220
|
const focusId = focusVisual?.trackChangeId;
|
|
4221
4221
|
return typeof anchorId === "string" && anchorId.length > 0 && anchorId === focusId ? anchorId : null;
|
|
4222
4222
|
}
|
|
4223
|
+
function isNonCollapsedHostSelection(snapshot) {
|
|
4224
|
+
if (!snapshot || typeof snapshot !== "object") return false;
|
|
4225
|
+
const record = snapshot;
|
|
4226
|
+
const anchor = record.anchor;
|
|
4227
|
+
const focus = record.focus;
|
|
4228
|
+
if (typeof anchor?.blockId !== "string" || !anchor.blockId || typeof focus?.blockId !== "string" || !focus.blockId || !Number.isFinite(anchor.blockOffset) || !Number.isFinite(focus.blockOffset)) return false;
|
|
4229
|
+
return anchor.blockId !== focus.blockId || anchor.blockOffset !== focus.blockOffset || Number.isFinite(anchor.trackedBlockOffset) && Number.isFinite(focus.trackedBlockOffset) && anchor.trackedBlockOffset !== focus.trackedBlockOffset;
|
|
4230
|
+
}
|
|
4223
4231
|
var trackedChangeIdContextCache = /* @__PURE__ */ new WeakMap();
|
|
4224
4232
|
/**
|
|
4225
4233
|
* Collect the raw source-provenance ids a tracked-change list item exposes,
|
|
@@ -6251,7 +6259,7 @@ function createSuperDocUI(options) {
|
|
|
6251
6259
|
}
|
|
6252
6260
|
if (pendingPostPaintSelectionRefresh) continue;
|
|
6253
6261
|
selectionEpoch += 1;
|
|
6254
|
-
|
|
6262
|
+
refreshSelectionFromHost();
|
|
6255
6263
|
recompute(paintCompleted ? "post-paint-selection" : "post-paint-selection-failed");
|
|
6256
6264
|
}
|
|
6257
6265
|
};
|
|
@@ -6648,8 +6656,9 @@ function createSuperDocUI(options) {
|
|
|
6648
6656
|
* effective font resolved from it) on the next recompute, instead of serving
|
|
6649
6657
|
* the previous selection until the worker `selection.current` round-trip lands
|
|
6650
6658
|
* (SD-3652). Only a resolvable COLLAPSED CARET is seeded - a range's snapshot
|
|
6651
|
-
* cannot be resolved synchronously in worker mode, so
|
|
6652
|
-
* read
|
|
6659
|
+
* cannot be resolved synchronously in worker mode, so a new range starts an
|
|
6660
|
+
* authoritative async read without waiting for the input-idle gate (SD-5394).
|
|
6661
|
+
* Seeding an empty value would wrongly disable range-only commands. The
|
|
6653
6662
|
* authoritative async read still overwrites marks/text/review overlap, but
|
|
6654
6663
|
* foreground typing defers and coalesces that worker hop through the shared
|
|
6655
6664
|
* retry gate. Previous marks are carried forward for toolbar continuity. A
|
|
@@ -6657,14 +6666,19 @@ function createSuperDocUI(options) {
|
|
|
6657
6666
|
* same carrier, or while an active typing dispatch advances the same caret by
|
|
6658
6667
|
* one code point. Pending work alone never carries review command context.
|
|
6659
6668
|
*/
|
|
6660
|
-
const
|
|
6669
|
+
const refreshSelectionFromHost = (hostSelectionSnapshot) => {
|
|
6670
|
+
const foreground = foregroundMutationState();
|
|
6671
|
+
if (isNonCollapsedHostSelection(hostSelectionSnapshot) && !(foreground && foreground.active > 0)) {
|
|
6672
|
+
pendingSelectionSeedValidationToken = null;
|
|
6673
|
+
issueAsyncRead("selection", selectionReadToken(), selectionCurrentRun, normalizeSelectionInfo);
|
|
6674
|
+
return;
|
|
6675
|
+
}
|
|
6661
6676
|
const host = getHost();
|
|
6662
6677
|
const read = host?.readLiveSelectionSyncSnapshot;
|
|
6663
6678
|
if (typeof read !== "function") return;
|
|
6664
6679
|
const seed = normalizeSelectionInfo(safeCall(() => read.call(host), null));
|
|
6665
6680
|
if (!seed || !isCollapsedCaretSnapshot(seed)) return;
|
|
6666
6681
|
const token = selectionReadToken();
|
|
6667
|
-
const foreground = foregroundMutationState();
|
|
6668
6682
|
const deferAuthoritativeRead = Boolean(foreground && (foreground.active > 0 || foreground.pending > 0));
|
|
6669
6683
|
if (!deferAuthoritativeRead) {
|
|
6670
6684
|
pendingSelectionSeedValidationToken = null;
|
|
@@ -8896,7 +8910,7 @@ function createSuperDocUI(options) {
|
|
|
8896
8910
|
const unsubscribe = next.subscribe((snapshot) => {
|
|
8897
8911
|
if (foregroundMutationActive() && caretSelectionNeedsProjectionPaint() && schedulePostPaintSelectionRefresh()) return;
|
|
8898
8912
|
selectionEpoch += 1;
|
|
8899
|
-
|
|
8913
|
+
refreshSelectionFromHost(snapshot);
|
|
8900
8914
|
recompute("host-selection");
|
|
8901
8915
|
});
|
|
8902
8916
|
if (typeof unsubscribe === "function") detachHostSelection = unsubscribe;
|
|
@@ -11275,6 +11289,113 @@ function createSuperDocUI(options) {
|
|
|
11275
11289
|
};
|
|
11276
11290
|
}
|
|
11277
11291
|
};
|
|
11292
|
+
let bookmarkNavigationGeneration = 0;
|
|
11293
|
+
documentResetHooks.push(() => {
|
|
11294
|
+
bookmarkNavigationGeneration += 1;
|
|
11295
|
+
});
|
|
11296
|
+
const bookmarks = { navigateTo: async (input, options) => {
|
|
11297
|
+
const generation = ++bookmarkNavigationGeneration;
|
|
11298
|
+
const unresolved = () => ({
|
|
11299
|
+
success: false,
|
|
11300
|
+
ok: false,
|
|
11301
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
11302
|
+
});
|
|
11303
|
+
const address = typeof input === "string" ? {
|
|
11304
|
+
kind: "entity",
|
|
11305
|
+
entityType: "bookmark",
|
|
11306
|
+
name: input
|
|
11307
|
+
} : input;
|
|
11308
|
+
if (!address || address.kind !== "entity" || address.entityType !== "bookmark" || typeof address.name !== "string" || address.name.length === 0 || address.story !== void 0 && (!address.story || address.story.kind !== "story" || address.story.storyType !== "body")) return unresolved();
|
|
11309
|
+
const editor = getEditor();
|
|
11310
|
+
if (!editor || disposed) return {
|
|
11311
|
+
success: false,
|
|
11312
|
+
ok: false,
|
|
11313
|
+
reason: SUPERDOC_UI_REASONS.notReady
|
|
11314
|
+
};
|
|
11315
|
+
const doc = getDoc();
|
|
11316
|
+
const api = doc?.bookmarks;
|
|
11317
|
+
if (typeof api?.list !== "function" || typeof api?.get !== "function") return {
|
|
11318
|
+
success: false,
|
|
11319
|
+
ok: false,
|
|
11320
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
11321
|
+
};
|
|
11322
|
+
const helper = getSelectionApplyHelper();
|
|
11323
|
+
if (!("helper" in helper)) return {
|
|
11324
|
+
success: false,
|
|
11325
|
+
ok: false,
|
|
11326
|
+
reason: helper.reason
|
|
11327
|
+
};
|
|
11328
|
+
const host = getHost();
|
|
11329
|
+
if (typeof host?.scrollTargetIntoView !== "function") return {
|
|
11330
|
+
success: false,
|
|
11331
|
+
ok: false,
|
|
11332
|
+
reason: SUPERDOC_UI_REASONS.hostCapabilityUnavailable
|
|
11333
|
+
};
|
|
11334
|
+
const token = metadataResolutionToken();
|
|
11335
|
+
let active = true;
|
|
11336
|
+
const current = () => active && !disposed && generation === bookmarkNavigationGeneration && getEditor() === editor && getDoc() === doc && getHost() === host && metadataResolutionToken() === token;
|
|
11337
|
+
const run = async () => {
|
|
11338
|
+
try {
|
|
11339
|
+
const directory = await api.list.call(api, address.story ? { in: address.story } : {});
|
|
11340
|
+
if (!current()) return unresolved();
|
|
11341
|
+
if ((Array.isArray(directory?.items) ? directory.items : []).filter((item) => item?.name === address.name).length !== 1) return unresolved();
|
|
11342
|
+
const info = await api.get.call(api, { target: address });
|
|
11343
|
+
if (!current()) return unresolved();
|
|
11344
|
+
const from = info?.range?.from;
|
|
11345
|
+
const to = info?.range?.to;
|
|
11346
|
+
const pointValid = (point) => typeof point?.blockId === "string" && point.blockId.length > 0 && Number.isInteger(point.offset) && point.offset >= 0;
|
|
11347
|
+
if (info?.name !== address.name || info?.address?.story && info.address.story.storyType !== "body" || info?.tableColumn || !pointValid(from) || !pointValid(to) || from.blockId === to.blockId && from.offset > to.offset) return unresolved();
|
|
11348
|
+
const result = await scrollTargetIntoView({
|
|
11349
|
+
kind: "text",
|
|
11350
|
+
segments: [{
|
|
11351
|
+
blockId: from.blockId,
|
|
11352
|
+
range: {
|
|
11353
|
+
start: from.offset,
|
|
11354
|
+
end: from.offset
|
|
11355
|
+
}
|
|
11356
|
+
}]
|
|
11357
|
+
}, {
|
|
11358
|
+
block: options?.block ?? "center",
|
|
11359
|
+
behavior: options?.behavior ?? "instant",
|
|
11360
|
+
shouldContinue: current
|
|
11361
|
+
});
|
|
11362
|
+
if (!current()) return unresolved();
|
|
11363
|
+
if (!result.ok) return result;
|
|
11364
|
+
const applied = selection.apply({
|
|
11365
|
+
kind: "selection",
|
|
11366
|
+
start: {
|
|
11367
|
+
kind: "text",
|
|
11368
|
+
blockId: from.blockId,
|
|
11369
|
+
offset: from.offset
|
|
11370
|
+
},
|
|
11371
|
+
end: {
|
|
11372
|
+
kind: "text",
|
|
11373
|
+
blockId: to.blockId,
|
|
11374
|
+
offset: to.offset
|
|
11375
|
+
}
|
|
11376
|
+
});
|
|
11377
|
+
return {
|
|
11378
|
+
...applied,
|
|
11379
|
+
success: applied.ok
|
|
11380
|
+
};
|
|
11381
|
+
} catch {
|
|
11382
|
+
return unresolved();
|
|
11383
|
+
}
|
|
11384
|
+
};
|
|
11385
|
+
let timer;
|
|
11386
|
+
const timeout = new Promise((resolve) => {
|
|
11387
|
+
timer = setTimeout(() => {
|
|
11388
|
+
active = false;
|
|
11389
|
+
resolve(unresolved());
|
|
11390
|
+
}, 15e3);
|
|
11391
|
+
});
|
|
11392
|
+
try {
|
|
11393
|
+
return await Promise.race([run(), timeout]);
|
|
11394
|
+
} finally {
|
|
11395
|
+
active = false;
|
|
11396
|
+
clearTimeout(timer);
|
|
11397
|
+
}
|
|
11398
|
+
} };
|
|
11278
11399
|
/**
|
|
11279
11400
|
* Derive the browser-shell's `importedId` carrier-lookup alias from a
|
|
11280
11401
|
* public list row's `wordRevisionIds` / `sourceIds` provenance fields,
|
|
@@ -12508,6 +12629,7 @@ function createSuperDocUI(options) {
|
|
|
12508
12629
|
};
|
|
12509
12630
|
let searchRequestGeneration = 0;
|
|
12510
12631
|
let pendingFallbackGeneration = null;
|
|
12632
|
+
let completedFallbackSearch = null;
|
|
12511
12633
|
/**
|
|
12512
12634
|
* How to tear down the session that is currently open, captured when it was
|
|
12513
12635
|
* opened.
|
|
@@ -12556,6 +12678,7 @@ function createSuperDocUI(options) {
|
|
|
12556
12678
|
* is deliberately not made here.
|
|
12557
12679
|
*/
|
|
12558
12680
|
const resetSearchForActiveEditorChange = () => {
|
|
12681
|
+
completedFallbackSearch = null;
|
|
12559
12682
|
searchRequestGeneration += 1;
|
|
12560
12683
|
pendingFallbackGeneration = null;
|
|
12561
12684
|
shellFallbackOutstanding = false;
|
|
@@ -12609,8 +12732,8 @@ function createSuperDocUI(options) {
|
|
|
12609
12732
|
const editSearch = getEditCommandSearch();
|
|
12610
12733
|
if (editSearch && typeof editSearch.query === "function") safeCall(() => editSearch.query({ query: "" }), null);
|
|
12611
12734
|
};
|
|
12612
|
-
const readEditCommandCanReplace = () => readEditCommandStateEntry("find.replace")?.enabled === true;
|
|
12613
|
-
const readEditCommandCanReplaceAll = () => readEditCommandStateEntry("find.replaceAll")?.enabled === true;
|
|
12735
|
+
const readEditCommandCanReplace = () => pendingFallbackGeneration !== searchRequestGeneration && readEditCommandStateEntry("find.replace")?.enabled === true;
|
|
12736
|
+
const readEditCommandCanReplaceAll = () => pendingFallbackGeneration !== searchRequestGeneration && readEditCommandStateEntry("find.replaceAll")?.enabled === true;
|
|
12614
12737
|
const applyHostSearchResult = (result, fallbackCanReplace = false, fallbackCanReplaceAll = fallbackCanReplace) => {
|
|
12615
12738
|
const snapshot = normalizeHostSearchResult(result, fallbackCanReplace, fallbackCanReplaceAll);
|
|
12616
12739
|
if (!snapshot) {
|
|
@@ -12771,6 +12894,7 @@ function createSuperDocUI(options) {
|
|
|
12771
12894
|
return { ok: true };
|
|
12772
12895
|
},
|
|
12773
12896
|
close: () => {
|
|
12897
|
+
completedFallbackSearch = null;
|
|
12774
12898
|
searchRequestGeneration += 1;
|
|
12775
12899
|
cancelRefreshShellSearch();
|
|
12776
12900
|
if (releaseActiveSearchSession) releaseSearchSession();
|
|
@@ -12795,6 +12919,16 @@ function createSuperDocUI(options) {
|
|
|
12795
12919
|
const caseSensitive = Boolean(options?.caseSensitive);
|
|
12796
12920
|
const includeDeletedText = (options?.includeTrackedDeletions ?? options?.includeDeletedText) === true;
|
|
12797
12921
|
const regex = options?.regex === true;
|
|
12922
|
+
if ((!host || typeof host.setSession !== "function") && completedFallbackSearch !== null && completedFallbackSearch === getEditCommandSearch() && pendingFallbackGeneration !== searchRequestGeneration && searchRefreshTimer === null && searchState.open && searchState.available && !searchState.reason && searchState.query === query && searchState.caseSensitive === caseSensitive && searchState.includeDeletedText === includeDeletedText && searchState.regex === regex) {
|
|
12923
|
+
syncSearchStateFromHost();
|
|
12924
|
+
emitSearch();
|
|
12925
|
+
return searchState;
|
|
12926
|
+
}
|
|
12927
|
+
completedFallbackSearch = null;
|
|
12928
|
+
if (searchRefreshTimer !== null) {
|
|
12929
|
+
clearTimeout(searchRefreshTimer);
|
|
12930
|
+
searchRefreshTimer = null;
|
|
12931
|
+
}
|
|
12798
12932
|
const generation = ++searchRequestGeneration;
|
|
12799
12933
|
cancelRefreshShellSearch();
|
|
12800
12934
|
cancelOutstandingShellFallback();
|
|
@@ -12830,6 +12964,7 @@ function createSuperDocUI(options) {
|
|
|
12830
12964
|
if (generation !== searchRequestGeneration) return;
|
|
12831
12965
|
shellFallbackOutstanding = false;
|
|
12832
12966
|
pendingFallbackGeneration = null;
|
|
12967
|
+
completedFallbackSearch = editSearch;
|
|
12833
12968
|
applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
|
|
12834
12969
|
}, () => {
|
|
12835
12970
|
if (generation !== searchRequestGeneration) return;
|
|
@@ -12842,6 +12977,7 @@ function createSuperDocUI(options) {
|
|
|
12842
12977
|
return searchState;
|
|
12843
12978
|
}
|
|
12844
12979
|
pendingFallbackGeneration = null;
|
|
12980
|
+
completedFallbackSearch = editSearch;
|
|
12845
12981
|
applyHostSearchResult(result, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
|
|
12846
12982
|
applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace(), readEditCommandCanReplaceAll());
|
|
12847
12983
|
return searchState;
|
|
@@ -12984,6 +13120,7 @@ function createSuperDocUI(options) {
|
|
|
12984
13120
|
return { ok: true };
|
|
12985
13121
|
},
|
|
12986
13122
|
clear: () => {
|
|
13123
|
+
completedFallbackSearch = null;
|
|
12987
13124
|
searchRequestGeneration += 1;
|
|
12988
13125
|
cancelRefreshShellSearch();
|
|
12989
13126
|
cancelOutstandingShellFallback();
|
|
@@ -13099,6 +13236,7 @@ function createSuperDocUI(options) {
|
|
|
13099
13236
|
};
|
|
13100
13237
|
let searchRefreshTimer = null;
|
|
13101
13238
|
scheduleActiveSearchRefresh = () => {
|
|
13239
|
+
completedFallbackSearch = null;
|
|
13102
13240
|
if (searchRefreshTimer !== null) clearTimeout(searchRefreshTimer);
|
|
13103
13241
|
if (!searchState.open || !searchState.query) return;
|
|
13104
13242
|
const scheduledGeneration = searchRequestGeneration;
|
|
@@ -13125,19 +13263,29 @@ function createSuperDocUI(options) {
|
|
|
13125
13263
|
const result = typeof editSearch?.refresh === "function" ? safeCall(() => editSearch.refresh(input), null) : safeCall(() => host.refresh(), null);
|
|
13126
13264
|
if (isPromiseLike(result)) {
|
|
13127
13265
|
pendingFallbackGeneration = generation;
|
|
13266
|
+
setSearchState({
|
|
13267
|
+
canReplace: false,
|
|
13268
|
+
canReplaceAll: false
|
|
13269
|
+
});
|
|
13128
13270
|
Promise.resolve(result).then((resolved) => {
|
|
13129
13271
|
if (generation !== searchRequestGeneration || disposed) return;
|
|
13272
|
+
releaseRefreshShellSearch = null;
|
|
13130
13273
|
pendingFallbackGeneration = null;
|
|
13274
|
+
completedFallbackSearch = editSearch;
|
|
13131
13275
|
applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
|
|
13132
13276
|
}, () => {
|
|
13133
13277
|
if (generation !== searchRequestGeneration || disposed) return;
|
|
13134
|
-
|
|
13278
|
+
releaseRefreshShellSearch = null;
|
|
13135
13279
|
setSearchState({
|
|
13136
13280
|
available: false,
|
|
13137
13281
|
reason: SUPERDOC_UI_REASONS.searchUnavailable
|
|
13138
13282
|
});
|
|
13139
13283
|
});
|
|
13140
|
-
} else if (result !== null)
|
|
13284
|
+
} else if (result !== null) {
|
|
13285
|
+
releaseRefreshShellSearch = null;
|
|
13286
|
+
completedFallbackSearch = editSearch;
|
|
13287
|
+
applyHostSearchResult(result);
|
|
13288
|
+
}
|
|
13141
13289
|
}, 120);
|
|
13142
13290
|
};
|
|
13143
13291
|
const stylesSub = sliceHandle((s) => s.styles);
|
|
@@ -13187,6 +13335,7 @@ function createSuperDocUI(options) {
|
|
|
13187
13335
|
watermark.destroy();
|
|
13188
13336
|
clearContentControlHighlight();
|
|
13189
13337
|
disposed = true;
|
|
13338
|
+
completedFallbackSearch = null;
|
|
13190
13339
|
if (searchRefreshTimer !== null) clearTimeout(searchRefreshTimer);
|
|
13191
13340
|
searchRefreshTimer = null;
|
|
13192
13341
|
cancelRefreshShellSearch();
|
|
@@ -13262,6 +13411,7 @@ function createSuperDocUI(options) {
|
|
|
13262
13411
|
comments,
|
|
13263
13412
|
trackChanges,
|
|
13264
13413
|
contentControls,
|
|
13414
|
+
bookmarks,
|
|
13265
13415
|
fonts,
|
|
13266
13416
|
zoom,
|
|
13267
13417
|
document: documentHandle,
|
|
@@ -19,7 +19,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
|
|
|
19
19
|
var PRIVATE_ENGINE_INFO = (0, _superdoc_docx_engine_collaboration_upgrade_engine.getCollaborationUpgradeEngineInfo)();
|
|
20
20
|
var ENGINE_INFO = Object.freeze({
|
|
21
21
|
...PRIVATE_ENGINE_INFO,
|
|
22
|
-
superdocVersion: "2.20.
|
|
22
|
+
superdocVersion: "2.20.1-next.1",
|
|
23
23
|
roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
|
|
24
24
|
supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
|
|
25
25
|
supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
|
|
@@ -18,7 +18,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
|
|
|
18
18
|
var PRIVATE_ENGINE_INFO = getCollaborationUpgradeEngineInfo$1();
|
|
19
19
|
var ENGINE_INFO = Object.freeze({
|
|
20
20
|
...PRIVATE_ENGINE_INFO,
|
|
21
|
-
superdocVersion: "2.20.
|
|
21
|
+
superdocVersion: "2.20.1-next.1",
|
|
22
22
|
roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
|
|
23
23
|
supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
|
|
24
24
|
supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
|
|
@@ -3649,7 +3649,7 @@ export declare const OPERATION_DEFINITIONS: {
|
|
|
3649
3649
|
readonly find: {
|
|
3650
3650
|
readonly memberPath: "find";
|
|
3651
3651
|
readonly description: "Search the document for text or node matches using SDM/1 selectors. Returns discovery-grade results: for mutation targeting, use query.match instead.";
|
|
3652
|
-
readonly expectedResult: "Returns an SDFindResult envelope ({ total, limit, offset, items }). Each item is an SDNodeResult ({ node, address }).";
|
|
3652
|
+
readonly expectedResult: "Returns an SDFindResult envelope ({ total, limit, offset, items }). Each item is an SDNodeResult ({ node, address }). Text hits contain only the matched text; use getNode or getNodeById for the full containing node. Node selectors return full node projections.";
|
|
3653
3653
|
readonly requiresDocumentContext: true;
|
|
3654
3654
|
readonly metadata: CommandStaticMetadata;
|
|
3655
3655
|
readonly referenceDocPath: "find.mdx";
|