superdoc 2.13.0-next.1 → 2.13.0-next.11

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.
Files changed (45) hide show
  1. package/dist/chunks/{create-super-doc-ui-BWWWNPP8.cjs → create-super-doc-ui-DNfQTF2k.cjs} +66 -6
  2. package/dist/chunks/{create-super-doc-ui-FnwgTkUv.es.js → create-super-doc-ui-XWtQHPGP.es.js} +66 -6
  3. package/dist/collaboration-upgrade-engine.cjs +1 -1
  4. package/dist/collaboration-upgrade-engine.es.js +1 -1
  5. package/dist/document-api/src/blocks/blocks.d.ts +3 -1
  6. package/dist/document-api/src/blocks/find-text.d.ts +3 -0
  7. package/dist/document-api/src/content-controls/content-controls.types.d.ts +1 -1
  8. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  9. package/dist/document-api/src/contract/operation-definitions.d.ts +11 -1
  10. package/dist/document-api/src/contract/operation-registry.d.ts +7 -2
  11. package/dist/document-api/src/index.d.ts +7 -6
  12. package/dist/document-api/src/invoke/invoke.d.ts +2 -1
  13. package/dist/document-api/src/types/blocks.types.d.ts +38 -0
  14. package/dist/document-api/src/types/mutation-plan.types.d.ts +28 -4
  15. package/dist/document-api/src/types/table-operations.types.d.ts +2 -0
  16. package/dist/layout-engine/dom-contract/src/data-attrs.d.ts +3 -0
  17. package/dist/layout-engine/painters/dom/src/page-content.d.ts +3 -2
  18. package/dist/layout-engine/painters/dom/src/renderer.d.ts +1 -0
  19. package/dist/public/collaboration-worker.cjs +9 -0
  20. package/dist/public/collaboration-worker.es.js +8 -0
  21. package/dist/public/ui-react.cjs +1 -1
  22. package/dist/public/ui-react.es.js +1 -1
  23. package/dist/public/ui-vue.cjs +1 -1
  24. package/dist/public/ui-vue.es.js +1 -1
  25. package/dist/public/ui.cjs +1 -1
  26. package/dist/public/ui.es.js +1 -1
  27. package/dist/style.css +26 -26
  28. package/dist/style.layered.css +26 -26
  29. package/dist/superdoc/src/composables/use-viewport-fit.d.ts +1 -0
  30. package/dist/superdoc/src/core/collaboration/collaboration-exception.d.ts +2 -0
  31. package/dist/superdoc/src/core/collaboration/resolve-v2-collaboration-target.d.ts +16 -5
  32. package/dist/superdoc/src/core/theme/create-theme.d.ts +32 -20
  33. package/dist/superdoc/src/core/types/index.d.ts +59 -71
  34. package/dist/superdoc/src/public/collaboration-worker.d.cts +18 -0
  35. package/dist/superdoc/src/public/collaboration-worker.d.ts +48 -0
  36. package/dist/superdoc/src/public/export-types.d.ts +23 -0
  37. package/dist/superdoc/src/public/index.d.cts +12 -0
  38. package/dist/superdoc/src/public/index.d.ts +3 -0
  39. package/dist/superdoc/src/public/ui/types.d.ts +18 -9
  40. package/dist/superdoc.cjs +384 -267
  41. package/dist/superdoc.es.js +384 -267
  42. package/dist-cdn/style.layered.css +1 -1
  43. package/dist-cdn/superdoc.min.css +1 -1
  44. package/dist-cdn/superdoc.min.js +37 -37
  45. package/package.json +13 -2
@@ -115,7 +115,9 @@ var DATA_ATTRS = {
115
115
  /** Encoded story locator (e.g. `body`, `header:rId4`, `footer:rId7`). */
116
116
  LAYOUT_STORY: "data-layout-story",
117
117
  /** Source block reference (today: producer's `blockId`). */
118
- LAYOUT_BLOCK_REF: "data-layout-block-ref"
118
+ LAYOUT_BLOCK_REF: "data-layout-block-ref",
119
+ /** Zero-based flow-column index that owns the rendered fragment. */
120
+ LAYOUT_COLUMN_INDEX: "data-layout-column-index"
119
121
  };
120
122
  /**
121
123
  * Decode the dataset string back into a `LayoutStoryLocator`-shaped object.
@@ -3109,6 +3111,18 @@ function commandResultFromOperationResult(result) {
3109
3111
  function isSuccessfulReceipt(result) {
3110
3112
  return Boolean(result) && typeof result === "object" && result.success === true;
3111
3113
  }
3114
+ /**
3115
+ * The host also emits `mutation:committed` for previews and no-op receipts;
3116
+ * those events must not mark the document as having unsaved edits.
3117
+ */
3118
+ function mutationCommittedEventChangedDocument(event) {
3119
+ if (event.dryRun === true) return false;
3120
+ const receipt = event.receipt;
3121
+ if (receipt && typeof receipt === "object" && receipt.changed === false) return false;
3122
+ if (receipt && typeof receipt === "object" && receipt.noop === true) return false;
3123
+ if (receipt && typeof receipt === "object" && receipt.status === "NO_OP") return false;
3124
+ return true;
3125
+ }
3112
3126
  function commandResultSucceeded(result) {
3113
3127
  if (result === false) return false;
3114
3128
  if (result && typeof result === "object" && result.success === false) return false;
@@ -3915,6 +3929,30 @@ function createSuperDocUI(options) {
3915
3929
  let allTrackedChangesResolvedToken = null;
3916
3930
  let selectionEpoch = 0;
3917
3931
  let lastCoordinatorEditor = null;
3932
+ /**
3933
+ * Fallback dirty state for editors that do not expose `isDirty` (V2). Kept
3934
+ * per host so switching the active editor away and back does not forget an
3935
+ * edit, and seeded from the host's local mutation revision so a controller
3936
+ * created after the first edit still reports it. A document replacement or
3937
+ * a verified zero revision clears an entry: `save:completed` fires for every DOCX export,
3938
+ * including a download, and producing bytes is not persistence.
3939
+ */
3940
+ const dirtyHosts = /* @__PURE__ */ new WeakSet();
3941
+ const hostSeededMutationRevision = /* @__PURE__ */ new WeakMap();
3942
+ const seedLocalDocumentMutation = (host) => {
3943
+ if (hostSeededMutationRevision.has(host)) return;
3944
+ const revision = typeof host.getLocalMutationRevision === "function" ? safeCall(() => host.getLocalMutationRevision(), null) : null;
3945
+ const seeded = typeof revision === "number" ? revision : 0;
3946
+ hostSeededMutationRevision.set(host, seeded);
3947
+ if (seeded > 0) dirtyHosts.add(host);
3948
+ else if (revision === 0) dirtyHosts.delete(host);
3949
+ };
3950
+ const hasLocalDocumentMutation = () => {
3951
+ const host = getHost();
3952
+ if (!host) return false;
3953
+ seedLocalDocumentMutation(host);
3954
+ return dirtyHosts.has(host);
3955
+ };
3918
3956
  /** Token shared by document-content reads (editor identity + mutation revision). */
3919
3957
  const contentToken = () => `${editorIdentityId(getEditor())}|m${documentMutationRevision}`;
3920
3958
  const clearPostDecisionTrackChanges = () => {
@@ -5182,10 +5220,11 @@ function createSuperDocUI(options) {
5182
5220
  };
5183
5221
  const computeDocument = () => {
5184
5222
  const editor = getEditor();
5223
+ const editorDirty = editor ? editor.isDirty : void 0;
5185
5224
  return {
5186
5225
  ready: editor != null,
5187
5226
  mode: readDocumentMode(),
5188
- dirty: editor ? Boolean(editor.isDirty) : false
5227
+ dirty: editor ? editorDirty === void 0 ? hasLocalDocumentMutation() : Boolean(editorDirty) : false
5189
5228
  };
5190
5229
  };
5191
5230
  /**
@@ -7112,7 +7151,8 @@ function createSuperDocUI(options) {
7112
7151
  state = computeState("initial");
7113
7152
  lastOptimisticInlineSelectionSignature = selectionInlineValueSignature(state.selection);
7114
7153
  const syncHostEventsSubscription = () => {
7115
- const events = (getEditor()?.host)?.events;
7154
+ const host = getEditor()?.host;
7155
+ const events = host?.events;
7116
7156
  const next = events && typeof events.subscribe === "function" ? events : null;
7117
7157
  if (next === currentHostEventsSource) return;
7118
7158
  if (detachHostEvents) {
@@ -7121,9 +7161,24 @@ function createSuperDocUI(options) {
7121
7161
  }
7122
7162
  currentHostEventsSource = next;
7123
7163
  if (!next) return;
7164
+ if (host) {
7165
+ hostSeededMutationRevision.delete(host);
7166
+ seedLocalDocumentMutation(host);
7167
+ }
7124
7168
  try {
7125
7169
  const off = next.subscribe((event) => {
7126
7170
  const type = event?.type;
7171
+ const isStandaloneDocumentMutation = type === "document:mutated" && event.hasCommitEvent !== true;
7172
+ if ((type === "document:mutated" || type === "mutation:committed" && mutationCommittedEventChangedDocument(event)) && host && !dirtyHosts.has(host)) {
7173
+ dirtyHosts.add(host);
7174
+ recompute("document-dirty");
7175
+ }
7176
+ if (type === "collaboration:document-replaced" && host) {
7177
+ dirtyHosts.delete(host);
7178
+ hostSeededMutationRevision.delete(host);
7179
+ seedLocalDocumentMutation(host);
7180
+ recompute("document-dirty");
7181
+ }
7127
7182
  if (type === "review-mutation:started") {
7128
7183
  beginUiReviewMutation(event.reviewMutation?.token);
7129
7184
  return;
@@ -7143,8 +7198,8 @@ function createSuperDocUI(options) {
7143
7198
  refreshIncompleteTrackChangesDirectories();
7144
7199
  return;
7145
7200
  }
7146
- if (type === "mutation:committed" || type === "collaboration:remote-changed") lastEditableMutationAtMs = Date.now();
7147
- if (type === "mutation:committed" || type === "save:completed" || type === "collaboration:remote-changed") {
7201
+ if (isStandaloneDocumentMutation || type === "mutation:committed" || type === "collaboration:remote-changed") lastEditableMutationAtMs = Date.now();
7202
+ if (isStandaloneDocumentMutation || type === "mutation:committed" || type === "save:completed" || type === "collaboration:remote-changed") {
7148
7203
  const impact = type === "mutation:committed" ? getV2TrackedChangeMutationImpact(event) : null;
7149
7204
  if (impact?.allResolved) {
7150
7205
  replaceTrackedChangeItemsInCache([]);
@@ -7159,7 +7214,7 @@ function createSuperDocUI(options) {
7159
7214
  return;
7160
7215
  }
7161
7216
  if (impact?.removedIds.size && impact.upsertIds.size === 0) return;
7162
- if (type === "collaboration:remote-changed" || type === "mutation:committed" && !isTypingBurst) schedulePostPaintContentRefresh();
7217
+ if (isStandaloneDocumentMutation || type === "collaboration:remote-changed" || type === "mutation:committed" && !isTypingBurst) schedulePostPaintContentRefresh();
7163
7218
  const remoteCommentsPartChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedPartUris) && event.changedPartUris.some((partUri) => typeof partUri === "string" && COMMENTS_CATALOG_PART_URIS.has(partUri));
7164
7219
  const loadedCommentAnchorsMayHaveChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0 && commentsCatalogMayHaveRows();
7165
7220
  if (remoteCommentsPartChanged && !isTypingBurst) heavyReadsHeldUntilIdle = true;
@@ -7273,6 +7328,11 @@ function createSuperDocUI(options) {
7273
7328
  const matchesEditor = Boolean(replacedEditor) && replacedEditor === getEditor();
7274
7329
  const matchesHost = Boolean(replacedHost) && replacedHost === getHost();
7275
7330
  if (!matchesEditor && !matchesHost) return;
7331
+ const replacedDirtyHost = matchesHost ? replacedHost : getHost();
7332
+ if (replacedDirtyHost) {
7333
+ dirtyHosts.delete(replacedDirtyHost);
7334
+ hostSeededMutationRevision.delete(replacedDirtyHost);
7335
+ }
7276
7336
  runDocumentResetHooks();
7277
7337
  asyncReads.clear();
7278
7338
  invalidateDocumentContent();
@@ -115,7 +115,9 @@ var DATA_ATTRS = {
115
115
  /** Encoded story locator (e.g. `body`, `header:rId4`, `footer:rId7`). */
116
116
  LAYOUT_STORY: "data-layout-story",
117
117
  /** Source block reference (today: producer's `blockId`). */
118
- LAYOUT_BLOCK_REF: "data-layout-block-ref"
118
+ LAYOUT_BLOCK_REF: "data-layout-block-ref",
119
+ /** Zero-based flow-column index that owns the rendered fragment. */
120
+ LAYOUT_COLUMN_INDEX: "data-layout-column-index"
119
121
  };
120
122
  /**
121
123
  * Decode the dataset string back into a `LayoutStoryLocator`-shaped object.
@@ -3109,6 +3111,18 @@ function commandResultFromOperationResult(result) {
3109
3111
  function isSuccessfulReceipt(result) {
3110
3112
  return Boolean(result) && typeof result === "object" && result.success === true;
3111
3113
  }
3114
+ /**
3115
+ * The host also emits `mutation:committed` for previews and no-op receipts;
3116
+ * those events must not mark the document as having unsaved edits.
3117
+ */
3118
+ function mutationCommittedEventChangedDocument(event) {
3119
+ if (event.dryRun === true) return false;
3120
+ const receipt = event.receipt;
3121
+ if (receipt && typeof receipt === "object" && receipt.changed === false) return false;
3122
+ if (receipt && typeof receipt === "object" && receipt.noop === true) return false;
3123
+ if (receipt && typeof receipt === "object" && receipt.status === "NO_OP") return false;
3124
+ return true;
3125
+ }
3112
3126
  function commandResultSucceeded(result) {
3113
3127
  if (result === false) return false;
3114
3128
  if (result && typeof result === "object" && result.success === false) return false;
@@ -3915,6 +3929,30 @@ function createSuperDocUI(options) {
3915
3929
  let allTrackedChangesResolvedToken = null;
3916
3930
  let selectionEpoch = 0;
3917
3931
  let lastCoordinatorEditor = null;
3932
+ /**
3933
+ * Fallback dirty state for editors that do not expose `isDirty` (V2). Kept
3934
+ * per host so switching the active editor away and back does not forget an
3935
+ * edit, and seeded from the host's local mutation revision so a controller
3936
+ * created after the first edit still reports it. A document replacement or
3937
+ * a verified zero revision clears an entry: `save:completed` fires for every DOCX export,
3938
+ * including a download, and producing bytes is not persistence.
3939
+ */
3940
+ const dirtyHosts = /* @__PURE__ */ new WeakSet();
3941
+ const hostSeededMutationRevision = /* @__PURE__ */ new WeakMap();
3942
+ const seedLocalDocumentMutation = (host) => {
3943
+ if (hostSeededMutationRevision.has(host)) return;
3944
+ const revision = typeof host.getLocalMutationRevision === "function" ? safeCall(() => host.getLocalMutationRevision(), null) : null;
3945
+ const seeded = typeof revision === "number" ? revision : 0;
3946
+ hostSeededMutationRevision.set(host, seeded);
3947
+ if (seeded > 0) dirtyHosts.add(host);
3948
+ else if (revision === 0) dirtyHosts.delete(host);
3949
+ };
3950
+ const hasLocalDocumentMutation = () => {
3951
+ const host = getHost();
3952
+ if (!host) return false;
3953
+ seedLocalDocumentMutation(host);
3954
+ return dirtyHosts.has(host);
3955
+ };
3918
3956
  /** Token shared by document-content reads (editor identity + mutation revision). */
3919
3957
  const contentToken = () => `${editorIdentityId(getEditor())}|m${documentMutationRevision}`;
3920
3958
  const clearPostDecisionTrackChanges = () => {
@@ -5182,10 +5220,11 @@ function createSuperDocUI(options) {
5182
5220
  };
5183
5221
  const computeDocument = () => {
5184
5222
  const editor = getEditor();
5223
+ const editorDirty = editor ? editor.isDirty : void 0;
5185
5224
  return {
5186
5225
  ready: editor != null,
5187
5226
  mode: readDocumentMode(),
5188
- dirty: editor ? Boolean(editor.isDirty) : false
5227
+ dirty: editor ? editorDirty === void 0 ? hasLocalDocumentMutation() : Boolean(editorDirty) : false
5189
5228
  };
5190
5229
  };
5191
5230
  /**
@@ -7112,7 +7151,8 @@ function createSuperDocUI(options) {
7112
7151
  state = computeState("initial");
7113
7152
  lastOptimisticInlineSelectionSignature = selectionInlineValueSignature(state.selection);
7114
7153
  const syncHostEventsSubscription = () => {
7115
- const events = (getEditor()?.host)?.events;
7154
+ const host = getEditor()?.host;
7155
+ const events = host?.events;
7116
7156
  const next = events && typeof events.subscribe === "function" ? events : null;
7117
7157
  if (next === currentHostEventsSource) return;
7118
7158
  if (detachHostEvents) {
@@ -7121,9 +7161,24 @@ function createSuperDocUI(options) {
7121
7161
  }
7122
7162
  currentHostEventsSource = next;
7123
7163
  if (!next) return;
7164
+ if (host) {
7165
+ hostSeededMutationRevision.delete(host);
7166
+ seedLocalDocumentMutation(host);
7167
+ }
7124
7168
  try {
7125
7169
  const off = next.subscribe((event) => {
7126
7170
  const type = event?.type;
7171
+ const isStandaloneDocumentMutation = type === "document:mutated" && event.hasCommitEvent !== true;
7172
+ if ((type === "document:mutated" || type === "mutation:committed" && mutationCommittedEventChangedDocument(event)) && host && !dirtyHosts.has(host)) {
7173
+ dirtyHosts.add(host);
7174
+ recompute("document-dirty");
7175
+ }
7176
+ if (type === "collaboration:document-replaced" && host) {
7177
+ dirtyHosts.delete(host);
7178
+ hostSeededMutationRevision.delete(host);
7179
+ seedLocalDocumentMutation(host);
7180
+ recompute("document-dirty");
7181
+ }
7127
7182
  if (type === "review-mutation:started") {
7128
7183
  beginUiReviewMutation(event.reviewMutation?.token);
7129
7184
  return;
@@ -7143,8 +7198,8 @@ function createSuperDocUI(options) {
7143
7198
  refreshIncompleteTrackChangesDirectories();
7144
7199
  return;
7145
7200
  }
7146
- if (type === "mutation:committed" || type === "collaboration:remote-changed") lastEditableMutationAtMs = Date.now();
7147
- if (type === "mutation:committed" || type === "save:completed" || type === "collaboration:remote-changed") {
7201
+ if (isStandaloneDocumentMutation || type === "mutation:committed" || type === "collaboration:remote-changed") lastEditableMutationAtMs = Date.now();
7202
+ if (isStandaloneDocumentMutation || type === "mutation:committed" || type === "save:completed" || type === "collaboration:remote-changed") {
7148
7203
  const impact = type === "mutation:committed" ? getV2TrackedChangeMutationImpact(event) : null;
7149
7204
  if (impact?.allResolved) {
7150
7205
  replaceTrackedChangeItemsInCache([]);
@@ -7159,7 +7214,7 @@ function createSuperDocUI(options) {
7159
7214
  return;
7160
7215
  }
7161
7216
  if (impact?.removedIds.size && impact.upsertIds.size === 0) return;
7162
- if (type === "collaboration:remote-changed" || type === "mutation:committed" && !isTypingBurst) schedulePostPaintContentRefresh();
7217
+ if (isStandaloneDocumentMutation || type === "collaboration:remote-changed" || type === "mutation:committed" && !isTypingBurst) schedulePostPaintContentRefresh();
7163
7218
  const remoteCommentsPartChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedPartUris) && event.changedPartUris.some((partUri) => typeof partUri === "string" && COMMENTS_CATALOG_PART_URIS.has(partUri));
7164
7219
  const loadedCommentAnchorsMayHaveChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0 && commentsCatalogMayHaveRows();
7165
7220
  if (remoteCommentsPartChanged && !isTypingBurst) heavyReadsHeldUntilIdle = true;
@@ -7273,6 +7328,11 @@ function createSuperDocUI(options) {
7273
7328
  const matchesEditor = Boolean(replacedEditor) && replacedEditor === getEditor();
7274
7329
  const matchesHost = Boolean(replacedHost) && replacedHost === getHost();
7275
7330
  if (!matchesEditor && !matchesHost) return;
7331
+ const replacedDirtyHost = matchesHost ? replacedHost : getHost();
7332
+ if (replacedDirtyHost) {
7333
+ dirtyHosts.delete(replacedDirtyHost);
7334
+ hostSeededMutationRevision.delete(replacedDirtyHost);
7335
+ }
7276
7336
  runDocumentResetHooks();
7277
7337
  asyncReads.clear();
7278
7338
  invalidateDocumentContent();
@@ -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.13.0-next.1",
22
+ superdocVersion: "2.13.0-next.11",
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.13.0-next.1",
21
+ superdocVersion: "2.13.0-next.11",
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
@@ -1,7 +1,8 @@
1
1
  import { MutationOptions } from '../write/write.js';
2
- import { BlocksDeleteInput, BlocksDeleteResult, BlocksListInput, BlocksListResult, BlocksDeleteRangeInput, BlocksDeleteRangeResult, BlocksMergeInput, BlocksMergeResult, BlocksMoveInput, BlocksMoveResult, BlocksSplitInput, BlocksSplitResult } from '../types/blocks.types.js';
2
+ import { BlocksDeleteInput, BlocksDeleteResult, BlocksListInput, BlocksListResult, BlocksFindTextInput, BlocksFindTextResult, BlocksDeleteRangeInput, BlocksDeleteRangeResult, BlocksMergeInput, BlocksMergeResult, BlocksMoveInput, BlocksMoveResult, BlocksSplitInput, BlocksSplitResult } from '../types/blocks.types.js';
3
3
  export interface BlocksApi {
4
4
  list(input?: BlocksListInput): BlocksListResult;
5
+ findText(input: BlocksFindTextInput): BlocksFindTextResult;
5
6
  delete(input: BlocksDeleteInput, options?: MutationOptions): BlocksDeleteResult;
6
7
  deleteRange(input: BlocksDeleteRangeInput, options?: MutationOptions): BlocksDeleteRangeResult;
7
8
  /** Split a paragraph at a visible-text offset. */
@@ -12,6 +13,7 @@ export interface BlocksApi {
12
13
  move(input: BlocksMoveInput, options?: MutationOptions): BlocksMoveResult;
13
14
  }
14
15
  export interface BlocksAdapter {
16
+ readonly supportsIdentityFilter?: boolean;
15
17
  list(input?: BlocksListInput): BlocksListResult;
16
18
  delete(input: BlocksDeleteInput, options?: MutationOptions): BlocksDeleteResult;
17
19
  deleteRange(input: BlocksDeleteRangeInput, options?: MutationOptions): BlocksDeleteRangeResult;
@@ -0,0 +1,3 @@
1
+ import { BlocksAdapter } from './blocks.js';
2
+ import { BlocksFindTextInput, BlocksFindTextResult } from '../types/blocks.types.js';
3
+ export declare function executeBlocksFindText(adapter: BlocksAdapter, input: BlocksFindTextInput): BlocksFindTextResult;
@@ -284,7 +284,7 @@ export interface ContentControlsGetContentResult {
284
284
  export interface ContentControlsReplaceContentInput {
285
285
  target: ContentControlTarget;
286
286
  content: string;
287
- format?: 'text' | 'html';
287
+ format?: 'text' | 'html' | 'ooxml';
288
288
  }
289
289
  export interface ContentControlsClearContentInput {
290
290
  target: ContentControlTarget;
@@ -1,7 +1,7 @@
1
1
  import { CommandCatalog, CommandStaticMetadata, OperationId } from './types.js';
2
2
  export declare const COMMAND_CATALOG: CommandCatalog;
3
3
  /** Operation IDs whose catalog entry has `mutates: true`. */
4
- export declare const MUTATING_OPERATION_IDS: ("replace" | "find" | "insert" | "delete" | "info" | "projectHtml" | "projectMarkdown" | "capabilities.check" | "format.apply" | "blocks.split" | "blocks.merge" | "blocks.move" | "lists.getState" | "lists.apply" | "lists.continue" | "lists.restart" | "lists.remove" | "format.paragraph.setMarkRunProps" | "tables.moveRow" | "format.bold" | "format.strike" | "format.color" | "format.rtl" | "format.cs" | "format.shading" | "format.fontFamily" | "format.lang" | "format.fontSize" | "format.fontSizeCs" | "format.highlight" | "format.italic" | "format.underline" | "format.caps" | "format.smallCaps" | "format.outline" | "format.shadow" | "format.emboss" | "format.imprint" | "format.vanish" | "format.webHidden" | "format.specVanish" | "format.border" | "format.fitText" | "format.dstrike" | "format.vertAlign" | "format.position" | "format.bCs" | "format.iCs" | "format.snapToGrid" | "format.oMath" | "format.letterSpacing" | "format.charScale" | "format.kerning" | "format.rStyle" | "format.rFonts" | "format.eastAsianLayout" | "format.em" | "format.ligatures" | "format.numForm" | "format.numSpacing" | "format.stylisticSets" | "format.contextualAlternates" | "get" | "getNode" | "getNodeById" | "getText" | "getMarkdown" | "getHtml" | "markdownToFragment" | "htmlToFragment" | "extract" | "clearContent" | "formatRange" | "blocks.list" | "blocks.delete" | "blocks.deleteRange" | "styles.apply" | "styles.getCatalog" | "templates.apply" | "create.paragraph" | "create.heading" | "create.sectionBreak" | "sections.list" | "sections.get" | "sections.setBreakType" | "sections.setPageMargins" | "sections.setHeaderFooterMargins" | "sections.setPageSetup" | "sections.setColumns" | "sections.setLineNumbering" | "sections.setPageNumbering" | "sections.setTitlePage" | "sections.setOddEvenHeadersFooters" | "sections.setVerticalAlign" | "sections.setSectionDirection" | "sections.setHeaderFooterRef" | "sections.clearHeaderFooterRef" | "sections.setLinkToPrevious" | "sections.setPageBorders" | "sections.clearPageBorders" | "styles.paragraph.setStyle" | "styles.paragraph.setStyleRef" | "styles.paragraph.clearStyle" | "format.paragraph.resetDirectFormatting" | "format.paragraph.setAlignment" | "format.paragraph.clearAlignment" | "format.paragraph.setIndentation" | "format.paragraph.clearIndentation" | "format.paragraph.setSpacing" | "format.paragraph.clearSpacing" | "format.paragraph.setKeepOptions" | "format.paragraph.setOutlineLevel" | "format.paragraph.setFlowOptions" | "format.paragraph.setTabStop" | "format.paragraph.clearTabStop" | "format.paragraph.clearAllTabStops" | "format.paragraph.setBorder" | "format.paragraph.clearBorder" | "format.paragraph.setShading" | "format.paragraph.clearShading" | "format.paragraph.setDirection" | "format.paragraph.clearDirection" | "format.paragraph.setNumbering" | "lists.list" | "lists.get" | "lists.insert" | "lists.create" | "lists.attach" | "lists.detach" | "lists.delete" | "lists.indent" | "lists.outdent" | "lists.join" | "lists.canJoin" | "lists.separate" | "lists.merge" | "lists.split" | "lists.setLevel" | "lists.setValue" | "lists.continuePrevious" | "lists.canContinuePrevious" | "lists.setLevelRestart" | "lists.convertToText" | "lists.applyTemplate" | "lists.applyPreset" | "lists.setType" | "lists.captureTemplate" | "lists.setLevelNumbering" | "lists.setLevelBullet" | "lists.setLevelPictureBullet" | "lists.setLevelAlignment" | "lists.setLevelIndents" | "lists.setLevelTrailingCharacter" | "lists.setLevelMarkerFont" | "lists.clearLevelOverrides" | "lists.getStyle" | "lists.applyStyle" | "lists.restartAt" | "lists.setLevelNumberStyle" | "lists.setLevelText" | "lists.setLevelStart" | "lists.setLevelLayout" | "comments.create" | "comments.patch" | "comments.delete" | "comments.get" | "comments.list" | "trackChanges.list" | "trackChanges.get" | "trackChanges.decide" | "query.match" | "ranges.resolve" | "selection.current" | "mutations.preview" | "mutations.apply" | "plan.execute" | "capabilities.get" | "create.table" | "tables.convertFromText" | "tables.delete" | "tables.clearContents" | "tables.move" | "tables.split" | "tables.convertToText" | "tables.setLayout" | "tables.insertRow" | "tables.deleteRow" | "tables.setRowHeight" | "tables.distributeRows" | "tables.setRowOptions" | "tables.insertColumn" | "tables.deleteColumn" | "tables.setColumnWidth" | "tables.distributeColumns" | "tables.insertCell" | "tables.deleteCell" | "tables.mergeCells" | "tables.unmergeCells" | "tables.splitCell" | "tables.setCellProperties" | "tables.setCellText" | "tables.sort" | "tables.setAltText" | "tables.setStyle" | "tables.clearStyle" | "tables.setStyleOption" | "tables.setBorder" | "tables.clearBorder" | "tables.applyBorderPreset" | "tables.setShading" | "tables.clearShading" | "tables.setTablePadding" | "tables.setCellPadding" | "tables.setCellSpacing" | "tables.clearCellSpacing" | "tables.applyStyle" | "tables.setBorders" | "tables.setTableOptions" | "tables.applyPreset" | "tables.get" | "tables.getCells" | "tables.getProperties" | "tables.getStyles" | "tables.setDefaultStyle" | "tables.clearDefaultStyle" | "create.tableOfContents" | "toc.list" | "toc.get" | "toc.configure" | "toc.update" | "toc.remove" | "toc.markEntry" | "toc.unmarkEntry" | "toc.listEntries" | "toc.getEntry" | "toc.editEntry" | "history.get" | "history.undo" | "history.redo" | "create.image" | "images.list" | "images.get" | "images.delete" | "images.move" | "images.convertToInline" | "images.convertToFloating" | "images.setSize" | "images.setWrapType" | "images.setWrapSide" | "images.setWrapDistances" | "images.setPosition" | "images.setAnchorOptions" | "images.setZOrder" | "images.scale" | "images.setLockAspectRatio" | "images.rotate" | "images.flip" | "images.crop" | "images.resetCrop" | "images.replaceSource" | "images.setAltText" | "images.setDecorative" | "images.setName" | "images.setHyperlink" | "images.insertCaption" | "images.updateCaption" | "images.removeCaption" | "hyperlinks.list" | "hyperlinks.get" | "hyperlinks.wrap" | "hyperlinks.insert" | "hyperlinks.patch" | "hyperlinks.remove" | "headerFooters.list" | "headerFooters.get" | "headerFooters.resolve" | "headerFooters.refs.set" | "headerFooters.refs.clear" | "headerFooters.refs.setLinkedToPrevious" | "headerFooters.parts.list" | "headerFooters.parts.create" | "headerFooters.parts.delete" | "create.contentControl" | "contentControls.list" | "contentControls.get" | "contentControls.listInRange" | "contentControls.selectByTag" | "contentControls.selectByTitle" | "contentControls.listChildren" | "contentControls.getParent" | "contentControls.wrap" | "contentControls.unwrap" | "contentControls.delete" | "contentControls.copy" | "contentControls.move" | "contentControls.patch" | "contentControls.setLockMode" | "contentControls.setType" | "contentControls.getContent" | "contentControls.replaceContent" | "contentControls.clearContent" | "contentControls.appendContent" | "contentControls.prependContent" | "contentControls.insertBefore" | "contentControls.insertAfter" | "contentControls.getBinding" | "contentControls.setBinding" | "contentControls.clearBinding" | "contentControls.getRawProperties" | "contentControls.patchRawProperties" | "contentControls.validateWordCompatibility" | "contentControls.normalizeWordCompatibility" | "contentControls.normalizeTagPayload" | "contentControls.text.setMultiline" | "contentControls.text.setValue" | "contentControls.text.clearValue" | "contentControls.date.setValue" | "contentControls.date.clearValue" | "contentControls.date.setDisplayFormat" | "contentControls.date.setDisplayLocale" | "contentControls.date.setStorageFormat" | "contentControls.date.setCalendar" | "contentControls.checkbox.getState" | "contentControls.checkbox.setState" | "contentControls.checkbox.toggle" | "contentControls.checkbox.setSymbolPair" | "contentControls.choiceList.getItems" | "contentControls.choiceList.setItems" | "contentControls.choiceList.setSelected" | "contentControls.repeatingSection.listItems" | "contentControls.repeatingSection.insertItemBefore" | "contentControls.repeatingSection.insertItemAfter" | "contentControls.repeatingSection.cloneItem" | "contentControls.repeatingSection.deleteItem" | "contentControls.repeatingSection.setAllowInsertDelete" | "contentControls.group.wrap" | "contentControls.group.ungroup" | "bookmarks.list" | "bookmarks.get" | "bookmarks.insert" | "bookmarks.rename" | "bookmarks.remove" | "footnotes.list" | "footnotes.get" | "footnotes.insert" | "footnotes.update" | "footnotes.remove" | "footnotes.configure" | "clipboard.parse" | "clipboard.insert" | "clipboard.serializeSelection" | "crossRefs.list" | "crossRefs.get" | "crossRefs.insert" | "crossRefs.rebuild" | "crossRefs.remove" | "index.list" | "index.get" | "index.insert" | "index.configure" | "index.rebuild" | "index.remove" | "index.entries.list" | "index.entries.get" | "index.entries.insert" | "index.entries.update" | "index.entries.remove" | "captions.list" | "captions.get" | "captions.insert" | "captions.update" | "captions.remove" | "captions.configure" | "fields.list" | "fields.get" | "fields.insert" | "fields.rebuild" | "fields.remove" | "citations.list" | "citations.get" | "citations.insert" | "citations.update" | "citations.remove" | "citations.sources.list" | "citations.sources.get" | "citations.sources.insert" | "citations.sources.update" | "citations.sources.remove" | "citations.bibliography.get" | "citations.bibliography.insert" | "citations.bibliography.rebuild" | "citations.bibliography.configure" | "citations.bibliography.remove" | "authorities.list" | "authorities.get" | "authorities.insert" | "authorities.configure" | "authorities.rebuild" | "authorities.remove" | "authorities.entries.list" | "authorities.entries.get" | "authorities.entries.insert" | "authorities.entries.update" | "authorities.entries.remove" | "diff.capture" | "diff.compare" | "diff.apply" | "export.toDocx" | "protection.get" | "protection.setEditingRestriction" | "protection.clearEditingRestriction" | "permissionRanges.list" | "permissionRanges.get" | "permissionRanges.create" | "permissionRanges.remove" | "permissionRanges.updatePrincipal" | "customXml.parts.list" | "customXml.parts.get" | "customXml.parts.create" | "customXml.parts.patch" | "customXml.parts.remove" | "metadata.attach" | "metadata.list" | "metadata.get" | "metadata.update" | "metadata.remove" | "metadata.resolve")[];
4
+ export declare const MUTATING_OPERATION_IDS: ("replace" | "find" | "insert" | "delete" | "info" | "projectHtml" | "projectMarkdown" | "capabilities.check" | "format.apply" | "blocks.split" | "blocks.merge" | "blocks.move" | "lists.getState" | "lists.apply" | "lists.continue" | "lists.restart" | "lists.remove" | "format.paragraph.setMarkRunProps" | "tables.moveRow" | "format.bold" | "format.strike" | "format.color" | "format.rtl" | "format.cs" | "format.shading" | "format.fontFamily" | "format.lang" | "format.fontSize" | "format.fontSizeCs" | "format.highlight" | "format.italic" | "format.underline" | "format.caps" | "format.smallCaps" | "format.outline" | "format.shadow" | "format.emboss" | "format.imprint" | "format.vanish" | "format.webHidden" | "format.specVanish" | "format.border" | "format.fitText" | "format.dstrike" | "format.vertAlign" | "format.position" | "format.bCs" | "format.iCs" | "format.snapToGrid" | "format.oMath" | "format.letterSpacing" | "format.charScale" | "format.kerning" | "format.rStyle" | "format.rFonts" | "format.eastAsianLayout" | "format.em" | "format.ligatures" | "format.numForm" | "format.numSpacing" | "format.stylisticSets" | "format.contextualAlternates" | "get" | "getNode" | "getNodeById" | "getText" | "getMarkdown" | "getHtml" | "markdownToFragment" | "htmlToFragment" | "extract" | "clearContent" | "formatRange" | "blocks.findText" | "blocks.list" | "blocks.delete" | "blocks.deleteRange" | "styles.apply" | "styles.getCatalog" | "templates.apply" | "create.paragraph" | "create.heading" | "create.sectionBreak" | "sections.list" | "sections.get" | "sections.setBreakType" | "sections.setPageMargins" | "sections.setHeaderFooterMargins" | "sections.setPageSetup" | "sections.setColumns" | "sections.setLineNumbering" | "sections.setPageNumbering" | "sections.setTitlePage" | "sections.setOddEvenHeadersFooters" | "sections.setVerticalAlign" | "sections.setSectionDirection" | "sections.setHeaderFooterRef" | "sections.clearHeaderFooterRef" | "sections.setLinkToPrevious" | "sections.setPageBorders" | "sections.clearPageBorders" | "styles.paragraph.setStyle" | "styles.paragraph.setStyleRef" | "styles.paragraph.clearStyle" | "format.paragraph.resetDirectFormatting" | "format.paragraph.setAlignment" | "format.paragraph.clearAlignment" | "format.paragraph.setIndentation" | "format.paragraph.clearIndentation" | "format.paragraph.setSpacing" | "format.paragraph.clearSpacing" | "format.paragraph.setKeepOptions" | "format.paragraph.setOutlineLevel" | "format.paragraph.setFlowOptions" | "format.paragraph.setTabStop" | "format.paragraph.clearTabStop" | "format.paragraph.clearAllTabStops" | "format.paragraph.setBorder" | "format.paragraph.clearBorder" | "format.paragraph.setShading" | "format.paragraph.clearShading" | "format.paragraph.setDirection" | "format.paragraph.clearDirection" | "format.paragraph.setNumbering" | "lists.list" | "lists.get" | "lists.insert" | "lists.create" | "lists.attach" | "lists.detach" | "lists.delete" | "lists.indent" | "lists.outdent" | "lists.join" | "lists.canJoin" | "lists.separate" | "lists.merge" | "lists.split" | "lists.setLevel" | "lists.setValue" | "lists.continuePrevious" | "lists.canContinuePrevious" | "lists.setLevelRestart" | "lists.convertToText" | "lists.applyTemplate" | "lists.applyPreset" | "lists.setType" | "lists.captureTemplate" | "lists.setLevelNumbering" | "lists.setLevelBullet" | "lists.setLevelPictureBullet" | "lists.setLevelAlignment" | "lists.setLevelIndents" | "lists.setLevelTrailingCharacter" | "lists.setLevelMarkerFont" | "lists.clearLevelOverrides" | "lists.getStyle" | "lists.applyStyle" | "lists.restartAt" | "lists.setLevelNumberStyle" | "lists.setLevelText" | "lists.setLevelStart" | "lists.setLevelLayout" | "comments.create" | "comments.patch" | "comments.delete" | "comments.get" | "comments.list" | "trackChanges.list" | "trackChanges.get" | "trackChanges.decide" | "query.match" | "ranges.resolve" | "selection.current" | "mutations.preview" | "mutations.apply" | "plan.execute" | "capabilities.get" | "create.table" | "tables.convertFromText" | "tables.delete" | "tables.clearContents" | "tables.move" | "tables.split" | "tables.convertToText" | "tables.setLayout" | "tables.insertRow" | "tables.deleteRow" | "tables.setRowHeight" | "tables.distributeRows" | "tables.setRowOptions" | "tables.insertColumn" | "tables.deleteColumn" | "tables.setColumnWidth" | "tables.distributeColumns" | "tables.insertCell" | "tables.deleteCell" | "tables.mergeCells" | "tables.unmergeCells" | "tables.splitCell" | "tables.setCellProperties" | "tables.setCellText" | "tables.sort" | "tables.setAltText" | "tables.setStyle" | "tables.clearStyle" | "tables.setStyleOption" | "tables.setBorder" | "tables.clearBorder" | "tables.applyBorderPreset" | "tables.setShading" | "tables.clearShading" | "tables.setTablePadding" | "tables.setCellPadding" | "tables.setCellSpacing" | "tables.clearCellSpacing" | "tables.applyStyle" | "tables.setBorders" | "tables.setTableOptions" | "tables.applyPreset" | "tables.get" | "tables.getCells" | "tables.getProperties" | "tables.getStyles" | "tables.setDefaultStyle" | "tables.clearDefaultStyle" | "create.tableOfContents" | "toc.list" | "toc.get" | "toc.configure" | "toc.update" | "toc.remove" | "toc.markEntry" | "toc.unmarkEntry" | "toc.listEntries" | "toc.getEntry" | "toc.editEntry" | "history.get" | "history.undo" | "history.redo" | "create.image" | "images.list" | "images.get" | "images.delete" | "images.move" | "images.convertToInline" | "images.convertToFloating" | "images.setSize" | "images.setWrapType" | "images.setWrapSide" | "images.setWrapDistances" | "images.setPosition" | "images.setAnchorOptions" | "images.setZOrder" | "images.scale" | "images.setLockAspectRatio" | "images.rotate" | "images.flip" | "images.crop" | "images.resetCrop" | "images.replaceSource" | "images.setAltText" | "images.setDecorative" | "images.setName" | "images.setHyperlink" | "images.insertCaption" | "images.updateCaption" | "images.removeCaption" | "hyperlinks.list" | "hyperlinks.get" | "hyperlinks.wrap" | "hyperlinks.insert" | "hyperlinks.patch" | "hyperlinks.remove" | "headerFooters.list" | "headerFooters.get" | "headerFooters.resolve" | "headerFooters.refs.set" | "headerFooters.refs.clear" | "headerFooters.refs.setLinkedToPrevious" | "headerFooters.parts.list" | "headerFooters.parts.create" | "headerFooters.parts.delete" | "create.contentControl" | "contentControls.list" | "contentControls.get" | "contentControls.listInRange" | "contentControls.selectByTag" | "contentControls.selectByTitle" | "contentControls.listChildren" | "contentControls.getParent" | "contentControls.wrap" | "contentControls.unwrap" | "contentControls.delete" | "contentControls.copy" | "contentControls.move" | "contentControls.patch" | "contentControls.setLockMode" | "contentControls.setType" | "contentControls.getContent" | "contentControls.replaceContent" | "contentControls.clearContent" | "contentControls.appendContent" | "contentControls.prependContent" | "contentControls.insertBefore" | "contentControls.insertAfter" | "contentControls.getBinding" | "contentControls.setBinding" | "contentControls.clearBinding" | "contentControls.getRawProperties" | "contentControls.patchRawProperties" | "contentControls.validateWordCompatibility" | "contentControls.normalizeWordCompatibility" | "contentControls.normalizeTagPayload" | "contentControls.text.setMultiline" | "contentControls.text.setValue" | "contentControls.text.clearValue" | "contentControls.date.setValue" | "contentControls.date.clearValue" | "contentControls.date.setDisplayFormat" | "contentControls.date.setDisplayLocale" | "contentControls.date.setStorageFormat" | "contentControls.date.setCalendar" | "contentControls.checkbox.getState" | "contentControls.checkbox.setState" | "contentControls.checkbox.toggle" | "contentControls.checkbox.setSymbolPair" | "contentControls.choiceList.getItems" | "contentControls.choiceList.setItems" | "contentControls.choiceList.setSelected" | "contentControls.repeatingSection.listItems" | "contentControls.repeatingSection.insertItemBefore" | "contentControls.repeatingSection.insertItemAfter" | "contentControls.repeatingSection.cloneItem" | "contentControls.repeatingSection.deleteItem" | "contentControls.repeatingSection.setAllowInsertDelete" | "contentControls.group.wrap" | "contentControls.group.ungroup" | "bookmarks.list" | "bookmarks.get" | "bookmarks.insert" | "bookmarks.rename" | "bookmarks.remove" | "footnotes.list" | "footnotes.get" | "footnotes.insert" | "footnotes.update" | "footnotes.remove" | "footnotes.configure" | "clipboard.parse" | "clipboard.insert" | "clipboard.serializeSelection" | "crossRefs.list" | "crossRefs.get" | "crossRefs.insert" | "crossRefs.rebuild" | "crossRefs.remove" | "index.list" | "index.get" | "index.insert" | "index.configure" | "index.rebuild" | "index.remove" | "index.entries.list" | "index.entries.get" | "index.entries.insert" | "index.entries.update" | "index.entries.remove" | "captions.list" | "captions.get" | "captions.insert" | "captions.update" | "captions.remove" | "captions.configure" | "fields.list" | "fields.get" | "fields.insert" | "fields.rebuild" | "fields.remove" | "citations.list" | "citations.get" | "citations.insert" | "citations.update" | "citations.remove" | "citations.sources.list" | "citations.sources.get" | "citations.sources.insert" | "citations.sources.update" | "citations.sources.remove" | "citations.bibliography.get" | "citations.bibliography.insert" | "citations.bibliography.rebuild" | "citations.bibliography.configure" | "citations.bibliography.remove" | "authorities.list" | "authorities.get" | "authorities.insert" | "authorities.configure" | "authorities.rebuild" | "authorities.remove" | "authorities.entries.list" | "authorities.entries.get" | "authorities.entries.insert" | "authorities.entries.update" | "authorities.entries.remove" | "diff.capture" | "diff.compare" | "diff.apply" | "export.toDocx" | "protection.get" | "protection.setEditingRestriction" | "protection.clearEditingRestriction" | "permissionRanges.list" | "permissionRanges.get" | "permissionRanges.create" | "permissionRanges.remove" | "permissionRanges.updatePrincipal" | "customXml.parts.list" | "customXml.parts.get" | "customXml.parts.create" | "customXml.parts.patch" | "customXml.parts.remove" | "metadata.attach" | "metadata.list" | "metadata.get" | "metadata.update" | "metadata.remove" | "metadata.resolve")[];
5
5
  /** Maps each operation to its human-readable description. */
6
6
  export declare const OPERATION_DESCRIPTION_MAP: Record<OperationId, string>;
7
7
  /** Maps each operation to whether it requires an open document to execute. */
@@ -3606,9 +3606,19 @@ export declare const OPERATION_DEFINITIONS: {
3606
3606
  readonly referenceGroup: "format";
3607
3607
  readonly skipAsATool: true;
3608
3608
  };
3609
+ readonly 'blocks.findText': {
3610
+ readonly memberPath: "blocks.findText";
3611
+ readonly description: "Find top-level body blocks containing a literal case-insensitive substring. Matches flattened block text, coalescing repeated hits and nested table paragraphs into one block. Scans at most 20,000 blocks inside the document host and returns compact previews without transferring full-text pages.";
3612
+ readonly expectedResult: "Returns matching-block total within the scan, limited matches with zero-based ordinals and 100-character previews, firstMatchOrdinal even for limit:0, scannedBlocks, truncated, and revision. A failed read retains completed pages and reports scanError; revision is unknown if no page succeeded. Whitespace and Unicode are not normalized.";
3613
+ readonly requiresDocumentContext: true;
3614
+ readonly metadata: CommandStaticMetadata;
3615
+ readonly referenceDocPath: "blocks/find-text.mdx";
3616
+ readonly referenceGroup: "blocks";
3617
+ readonly skipAsATool: true;
3618
+ };
3609
3619
  readonly 'blocks.list': {
3610
3620
  readonly memberPath: "blocks.list";
3611
- readonly description: "List top-level blocks in document order with IDs, types, text previews, and optional full text when includeText:true. Supports pagination via offset/limit, optional nodeType filtering, single-story scoping via `in: <StoryLocator>`, and final/original/redline projection of numbering metadata without changing block membership.";
3621
+ readonly description: "List top-level blocks in document order with IDs, types, text previews, and optional full text when includeText:true. Supports pagination via offset/limit after optional nodeTypes, nodeIds, and literal textSearch filtering, single-story scoping via `in: <StoryLocator>`, and final/original/redline projection of numbering metadata without changing block membership.";
3612
3622
  readonly expectedResult: "Returns a BlocksListResult with total block count, an ordered array of block entries, the effective numbering reviewMode, and the current document revision.";
3613
3623
  readonly requiresDocumentContext: true;
3614
3624
  readonly metadata: CommandStaticMetadata;
@@ -6,7 +6,7 @@ import { SDHtmlToFragmentResult, SDMutationReceipt, SDMarkdownToFragmentResult }
6
6
  import { DocumentInfo } from '../types/info.types.js';
7
7
  import { SDDocument } from '../types/fragment.js';
8
8
  import { CreateParagraphInput, CreateParagraphResult, CreateHeadingInput, CreateHeadingResult } from '../types/create.types.js';
9
- import { BlocksDeleteInput, BlocksDeleteResult, BlocksListInput, BlocksListResult, BlocksDeleteRangeInput, BlocksDeleteRangeResult, BlocksMergeInput, BlocksMergeResult, BlocksMoveInput, BlocksMoveResult, BlocksSplitInput, BlocksSplitResult } from '../types/blocks.types.js';
9
+ import { BlocksDeleteInput, BlocksDeleteResult, BlocksListInput, BlocksListResult, BlocksFindTextInput, BlocksFindTextResult, BlocksDeleteRangeInput, BlocksDeleteRangeResult, BlocksMergeInput, BlocksMergeResult, BlocksMoveInput, BlocksMoveResult, BlocksSplitInput, BlocksSplitResult } from '../types/blocks.types.js';
10
10
  import { GetNodeByIdInput } from '../get-node/get-node.js';
11
11
  import { GetTextInput } from '../get-text/get-text.js';
12
12
  import { GetMarkdownInput } from '../get-markdown/get-markdown.js';
@@ -165,6 +165,11 @@ export interface OperationRegistry extends FormatInlineAliasOperationRegistry {
165
165
  options: never;
166
166
  output: BlocksListResult;
167
167
  };
168
+ 'blocks.findText': {
169
+ input: BlocksFindTextInput;
170
+ options: never;
171
+ output: BlocksFindTextResult;
172
+ };
168
173
  'blocks.delete': {
169
174
  input: BlocksDeleteInput;
170
175
  options: MutationOptions;
@@ -2012,7 +2017,7 @@ export type InvokeRequest<T extends OperationId> = OperationRegistry[T]['options
2012
2017
  /**
2013
2018
  * Typed invoke result, narrowed by operationId.
2014
2019
  */
2015
- export type InvokeResult<T extends OperationId> = OperationRegistry[T]['output'];
2020
+ export type InvokeResult<T extends OperationId> = T extends 'mutations.preview' | 'mutations.apply' ? Promise<OperationRegistry[T]['output']> : T extends 'plan.execute' ? OperationRegistry[T]['output'] | Promise<OperationRegistry[T]['output']> : OperationRegistry[T]['output'];
2016
2021
  /**
2017
2022
  * Loose invoke request for dynamic callers who don't know the operation at compile time.
2018
2023
  * Invalid inputs will produce adapter-level errors, not input-validation errors.
@@ -36,7 +36,7 @@ import { CapabilitiesAdapter, DocumentApiCapabilities } from './capabilities/cap
36
36
  import { SDHtmlMarkdownSupportCheckInput, SDHtmlMarkdownSupportCheckResult } from './capabilities/html-markdown-support.js';
37
37
  import { OperationId } from './contract/types.js';
38
38
  import { DynamicInvokeRequest, InvokeRequest, InvokeResult } from './contract/operation-registry.js';
39
- import { PlanApi } from './plan/plan.js';
39
+ import { PlanApi, PlanExecuteResult } from './plan/plan.js';
40
40
  import { HistoryAdapter, HistoryApi } from './history/history.js';
41
41
  import { DiffAdapter, DiffApi } from './diff/diff.js';
42
42
  import { ExportAdapter, ExportApi } from './export/export.js';
@@ -161,6 +161,7 @@ export type { CommentsCreateReceipt, CommentsCreateInput, CommentCreateAttributi
161
161
  export { executeCommentsCreate, executeCommentsPatch, executeCommentsDelete, executeGetComment, executeListComments, } from './comments/comments.js';
162
162
  export type { CommentInfo, CommentDomain, CommentMetadata, CommentMetadataValue, CommentsListQuery, CommentsListResult, CommentTrackedChangeSide, CommentTrackedChangeLink, CommentTarget, } from './comments/comments.types.js';
163
163
  export type { BlocksApi } from './blocks/blocks.js';
164
+ export { executeBlocksFindText } from './blocks/find-text.js';
164
165
  export { executeBlocksList, executeBlocksDelete, executeBlocksDeleteRange, executeBlocksSplit, executeBlocksMerge, executeBlocksMove, } from './blocks/blocks.js';
165
166
  export { executeListsIndent, executeListsOutdent, executeListsGetState, executeListsApply, executeListsContinueV2, executeListsRestartV2, executeListsRemoveV2, } from './lists/lists.js';
166
167
  export { DocumentApiValidationError } from './errors.js';
@@ -242,8 +243,8 @@ export interface QueryApi {
242
243
  match(input: QueryMatchInput | TextSelector | NodeSelector): QueryMatchOutput;
243
244
  }
244
245
  export interface MutationsApi {
245
- preview(input: MutationsPreviewInput): MutationsPreviewOutput;
246
- apply(input: MutationsApplyInput): PlanReceipt;
246
+ preview(input: MutationsPreviewInput): Promise<MutationsPreviewOutput>;
247
+ apply(input: MutationsApplyInput): Promise<PlanReceipt>;
247
248
  }
248
249
  export interface RangesApi {
249
250
  resolve(input: ResolveRangeInput): ResolveRangeOutput;
@@ -255,8 +256,8 @@ export interface QueryAdapter {
255
256
  match(input: QueryMatchInput): QueryMatchOutput;
256
257
  }
257
258
  export interface MutationsAdapter {
258
- preview(input: MutationsPreviewInput): MutationsPreviewOutput;
259
- apply(input: MutationsApplyInput): PlanReceipt;
259
+ preview(input: MutationsPreviewInput): Promise<MutationsPreviewOutput>;
260
+ apply(input: MutationsApplyInput): Promise<PlanReceipt>;
260
261
  }
261
262
  /**
262
263
  * The Document API interface for querying and inspecting document nodes.
@@ -460,7 +461,7 @@ export interface DocumentApi {
460
461
  /**
461
462
  * Throughput-oriented batch executor with stepwise operation semantics.
462
463
  */
463
- plan: PlanApi;
464
+ plan: PlanApi<PlanExecuteResult | Promise<PlanExecuteResult>>;
464
465
  /**
465
466
  * Snapshot-based document comparison and replay.
466
467
  */
@@ -1,7 +1,8 @@
1
1
  import { OperationId } from '../contract/types.js';
2
2
  import { OperationRegistry } from '../contract/operation-registry.js';
3
3
  import { DocumentApi } from '../index.js';
4
- type TypedDispatchHandler<K extends OperationId> = OperationRegistry[K]['options'] extends never ? (input: OperationRegistry[K]['input']) => OperationRegistry[K]['output'] : (input: OperationRegistry[K]['input'], options?: OperationRegistry[K]['options']) => OperationRegistry[K]['output'];
4
+ type DispatchOutput<K extends OperationId> = K extends 'mutations.preview' | 'mutations.apply' ? Promise<OperationRegistry[K]['output']> : K extends 'plan.execute' ? OperationRegistry[K]['output'] | Promise<OperationRegistry[K]['output']> : OperationRegistry[K]['output'];
5
+ type TypedDispatchHandler<K extends OperationId> = OperationRegistry[K]['options'] extends never ? (input: OperationRegistry[K]['input']) => DispatchOutput<K> : (input: OperationRegistry[K]['input'], options?: OperationRegistry[K]['options']) => DispatchOutput<K>;
5
6
  export type TypedDispatchTable = {
6
7
  [K in OperationId]: TypedDispatchHandler<K>;
7
8
  };
@@ -50,6 +50,14 @@ export interface BlockListEntry {
50
50
  ref?: string;
51
51
  }
52
52
  export interface BlocksListInput {
53
+ /** Filter top-level blocks by identity before pagination. Cell paragraphs do not match body blocks. */
54
+ nodeIds?: string[];
55
+ /** Literal terms matched against complete block text before pagination; occurrences are blocks. */
56
+ textSearch?: {
57
+ terms: string[];
58
+ match?: 'all' | 'any';
59
+ caseSensitive?: boolean;
60
+ };
53
61
  offset?: number;
54
62
  limit?: number;
55
63
  nodeTypes?: BlockNodeType[];
@@ -72,6 +80,36 @@ export interface BlocksListResult {
72
80
  /** Effective numbering review mode. Defaults to final when omitted from the request. */
73
81
  reviewMode: SDProjectionReviewMode;
74
82
  }
83
+ export interface BlocksFindTextInput {
84
+ /** Literal, case-insensitive substring; whitespace and Unicode are not normalized. */
85
+ text: string;
86
+ /** Maximum matching blocks to return. Defaults to 8; zero returns counts only. */
87
+ limit?: number;
88
+ }
89
+ export interface BlocksFindTextMatch {
90
+ /** Zero-based top-level body ordinal, as in blocks.list. */
91
+ ordinal: number;
92
+ nodeId: string;
93
+ nodeType: BlockNodeType;
94
+ /** First 100 UTF-16 code units of the flattened block text. */
95
+ preview: string;
96
+ }
97
+ export interface BlocksFindTextResult {
98
+ /** Matching blocks, not occurrences, within the first 20,000 body blocks. */
99
+ total: number;
100
+ matches: BlocksFindTextMatch[];
101
+ /** Present even with limit: 0 so callers can locate a reading window. */
102
+ firstMatchOrdinal?: number;
103
+ scannedBlocks: number;
104
+ /** True when blocks beyond the scan cap were not searched. */
105
+ truncated: boolean;
106
+ /** A failed page read leaves preceding matches/counts intact; the scan is incomplete. */
107
+ scanError?: {
108
+ message: string;
109
+ };
110
+ /** Last successfully read revision, or "unknown" when the first page failed. */
111
+ revision: string;
112
+ }
75
113
  export interface BlocksDeleteInput {
76
114
  target: DeletableBlockNodeAddress;
77
115
  }
@@ -66,6 +66,10 @@ export type TextRewriteStep = {
66
66
  where: StepWhere;
67
67
  args: {
68
68
  replacement: ReplacementPayload;
69
+ /** Interpret positional `$1`…`$99` and `$&` tokens for regex matches. */
70
+ replacementMode?: 'literal' | 'regex-template';
71
+ /** Preserve the matched text's casing pattern instead of using replacement casing verbatim. */
72
+ caseHandling?: 'exact' | 'preserve-match';
69
73
  /**
70
74
  * Style policy for the replacement text.
71
75
  * When omitted, defaults to preserve mode:
@@ -157,10 +161,18 @@ export type MutationsPreviewInput = {
157
161
  atomic: true;
158
162
  changeMode: ChangeMode;
159
163
  steps: MutationStep[];
164
+ /** Optional page over verbose resolved-target details. Defaults to the first 100 targets. */
165
+ detail?: {
166
+ offset?: number;
167
+ limit?: number;
168
+ };
160
169
  };
161
170
  /** Maximum number of steps per mutation plan. */
162
171
  export declare const MAX_PLAN_STEPS = 200;
163
- /** Maximum total resolved targets across all steps in a plan. */
172
+ /**
173
+ * @deprecated Historical compatibility metadata. Text replacement no longer
174
+ * enforces this value; callers must not treat it as a supported target limit.
175
+ */
164
176
  export declare const MAX_PLAN_RESOLVED_TARGETS = 500;
165
177
  export type StepEffect = 'changed' | 'noop' | 'error' | 'assert_passed' | 'assert_failed';
166
178
  /** Resolution for a single-block (range) target. */
@@ -189,9 +201,14 @@ export type SelectionStepResolution = {
189
201
  };
190
202
  export type TextStepData = {
191
203
  domain: 'text';
192
- resolutions: TextStepResolution[];
193
- spanResolutions?: SpanStepResolution[];
194
- selectionResolutions?: SelectionStepResolution[];
204
+ /** Exact number of targets selected from the step's input revision. */
205
+ matchedCount: number;
206
+ /** Exact number of targets whose content changed. */
207
+ changedCount: number;
208
+ /** Exact number of targets already equal to their requested replacement. */
209
+ noopCount: number;
210
+ /** Exact number of tracked-change identities authored by this step. */
211
+ trackedChangeCount: number;
195
212
  };
196
213
  export type AssertStepData = {
197
214
  domain: 'assert';
@@ -247,7 +264,14 @@ export type PreviewFailure = {
247
264
  export type StepPreview = {
248
265
  stepId: string;
249
266
  op: string;
267
+ /** Exact number of targets resolved for this step. */
268
+ matchCount?: number;
250
269
  resolutions?: TextStepResolution[];
270
+ detailPage?: {
271
+ offset: number;
272
+ limit: number;
273
+ returned: number;
274
+ };
251
275
  spanResolutions?: SpanStepResolution[];
252
276
  selectionResolutions?: SelectionStepResolution[];
253
277
  style?: unknown;