@harbour-enterprises/superdoc 1.17.0-next.11 → 1.17.0-next.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{SuperConverter-D0cZ7DBR.es.js → SuperConverter-0JaBYpRa.es.js} +1 -1
- package/dist/chunks/{SuperConverter-DOQaFkjd.cjs → SuperConverter-BgHHB-Z2.cjs} +1 -1
- package/dist/chunks/{src-DQKyE7kq.cjs → src-ByCDwKn7.cjs} +458 -129
- package/dist/chunks/{src-bsYwK29H.es.js → src-C52EYA_H.es.js} +452 -130
- package/dist/super-editor/converter.cjs +1 -1
- package/dist/super-editor/converter.es.js +1 -1
- package/dist/super-editor/src/document-api-adapters/assemble-adapters.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/capabilities-adapter.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/errors.d.ts +1 -1
- package/dist/super-editor/src/document-api-adapters/errors.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/helpers/node-address-resolver.d.ts +12 -0
- package/dist/super-editor/src/document-api-adapters/helpers/node-address-resolver.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/index.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/plan-engine/blocks-wrappers.d.ts +4 -0
- package/dist/super-editor/src/document-api-adapters/plan-engine/blocks-wrappers.d.ts.map +1 -0
- package/dist/super-editor/src/document-api-adapters/plan-engine/compiler.d.ts +14 -0
- package/dist/super-editor/src/document-api-adapters/plan-engine/compiler.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/plan-engine/create-insertion.d.ts +16 -0
- package/dist/super-editor/src/document-api-adapters/plan-engine/create-insertion.d.ts.map +1 -0
- package/dist/super-editor/src/document-api-adapters/plan-engine/create-wrappers.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/plan-engine/executor.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/plan-engine/plan-wrappers.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/plan-engine/preview.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/plan-engine/query-match-adapter.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/plan-engine/revision-tracker.d.ts.map +1 -1
- package/dist/super-editor/src/document-api-adapters/plan-engine/style-resolver.d.ts.map +1 -1
- package/dist/super-editor.cjs +2 -2
- package/dist/super-editor.es.js +2 -2
- package/dist/superdoc.cjs +3 -3
- package/dist/superdoc.es.js +3 -3
- package/dist/superdoc.umd.js +459 -137
- package/dist/superdoc.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-Dp2H1eGw.cjs");
|
|
2
|
-
const require_SuperConverter = require("./SuperConverter-
|
|
2
|
+
const require_SuperConverter = require("./SuperConverter-BgHHB-Z2.cjs");
|
|
3
3
|
const require_jszip = require("./jszip-DCT9QYaK.cjs");
|
|
4
4
|
const require_uuid = require("./uuid-CHj_rjgt.cjs");
|
|
5
5
|
const require_constants = require("./constants-CpniKo9Z.cjs");
|
|
@@ -261,7 +261,7 @@ var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
|
|
|
261
261
|
const COMMUNITY_LICENSE_KEY = "community-and-eval-agplv3";
|
|
262
262
|
function getSuperdocVersion() {
|
|
263
263
|
try {
|
|
264
|
-
return "1.17.0-next.
|
|
264
|
+
return "1.17.0-next.13";
|
|
265
265
|
} catch {
|
|
266
266
|
return "unknown";
|
|
267
267
|
}
|
|
@@ -20734,7 +20734,7 @@ const canUseDOM = () => {
|
|
|
20734
20734
|
return false;
|
|
20735
20735
|
}
|
|
20736
20736
|
};
|
|
20737
|
-
var summaryVersion = "1.17.0-next.
|
|
20737
|
+
var summaryVersion = "1.17.0-next.13";
|
|
20738
20738
|
var nodeKeys = [
|
|
20739
20739
|
"group",
|
|
20740
20740
|
"content",
|
|
@@ -21113,6 +21113,13 @@ const BLOCK_NODE_TYPES = [
|
|
|
21113
21113
|
"image",
|
|
21114
21114
|
"sdt"
|
|
21115
21115
|
];
|
|
21116
|
+
const DELETABLE_BLOCK_NODE_TYPES = [
|
|
21117
|
+
"paragraph",
|
|
21118
|
+
"heading",
|
|
21119
|
+
"listItem",
|
|
21120
|
+
"table",
|
|
21121
|
+
"sdt"
|
|
21122
|
+
];
|
|
21116
21123
|
const INLINE_NODE_TYPES = [
|
|
21117
21124
|
"run",
|
|
21118
21125
|
"bookmark",
|
|
@@ -21204,6 +21211,9 @@ var T_PLAN_ENGINE = [
|
|
|
21204
21211
|
"TARGET_MOVED",
|
|
21205
21212
|
"PLAN_CONFLICT_OVERLAP",
|
|
21206
21213
|
"INVALID_STEP_COMBINATION",
|
|
21214
|
+
"REVISION_CHANGED_SINCE_COMPILE",
|
|
21215
|
+
"INVALID_INSERTION_CONTEXT",
|
|
21216
|
+
"DOCUMENT_IDENTITY_CONFLICT",
|
|
21207
21217
|
"CAPABILITY_UNAVAILABLE"
|
|
21208
21218
|
];
|
|
21209
21219
|
var T_QUERY_MATCH = [
|
|
@@ -21305,6 +21315,27 @@ const OPERATION_DEFINITIONS = {
|
|
|
21305
21315
|
referenceDocPath: "delete.mdx",
|
|
21306
21316
|
referenceGroup: "core"
|
|
21307
21317
|
},
|
|
21318
|
+
"blocks.delete": {
|
|
21319
|
+
memberPath: "blocks.delete",
|
|
21320
|
+
description: "Delete an entire block node (paragraph, heading, list item, table, image, or sdt) deterministically.",
|
|
21321
|
+
requiresDocumentContext: true,
|
|
21322
|
+
metadata: mutationOperation({
|
|
21323
|
+
idempotency: "conditional",
|
|
21324
|
+
supportsDryRun: true,
|
|
21325
|
+
supportsTrackedMode: false,
|
|
21326
|
+
possibleFailureCodes: NONE_FAILURES,
|
|
21327
|
+
throws: [
|
|
21328
|
+
"TARGET_NOT_FOUND",
|
|
21329
|
+
"AMBIGUOUS_TARGET",
|
|
21330
|
+
"CAPABILITY_UNAVAILABLE",
|
|
21331
|
+
"INVALID_TARGET",
|
|
21332
|
+
"INVALID_INPUT",
|
|
21333
|
+
"INTERNAL_ERROR"
|
|
21334
|
+
]
|
|
21335
|
+
}),
|
|
21336
|
+
referenceDocPath: "blocks/delete.mdx",
|
|
21337
|
+
referenceGroup: "blocks"
|
|
21338
|
+
},
|
|
21308
21339
|
"format.apply": {
|
|
21309
21340
|
memberPath: "format.apply",
|
|
21310
21341
|
description: "Apply explicit inline style changes (bold, italic, underline, strike) to the target range using boolean patch semantics.",
|
|
@@ -21879,6 +21910,7 @@ function ref$1(name) {
|
|
|
21879
21910
|
}
|
|
21880
21911
|
var nodeTypeValues = NODE_TYPES;
|
|
21881
21912
|
var blockNodeTypeValues = BLOCK_NODE_TYPES;
|
|
21913
|
+
var deletableBlockNodeTypeValues = DELETABLE_BLOCK_NODE_TYPES;
|
|
21882
21914
|
var inlineNodeTypeValues = INLINE_NODE_TYPES;
|
|
21883
21915
|
var SHARED_DEFS = {
|
|
21884
21916
|
Range: objectSchema({
|
|
@@ -21938,6 +21970,15 @@ var SHARED_DEFS = {
|
|
|
21938
21970
|
"nodeType",
|
|
21939
21971
|
"nodeId"
|
|
21940
21972
|
]),
|
|
21973
|
+
DeletableBlockNodeAddress: objectSchema({
|
|
21974
|
+
kind: { const: "block" },
|
|
21975
|
+
nodeType: { enum: [...deletableBlockNodeTypeValues] },
|
|
21976
|
+
nodeId: { type: "string" }
|
|
21977
|
+
}, [
|
|
21978
|
+
"kind",
|
|
21979
|
+
"nodeType",
|
|
21980
|
+
"nodeId"
|
|
21981
|
+
]),
|
|
21941
21982
|
ParagraphAddress: objectSchema({
|
|
21942
21983
|
kind: { const: "block" },
|
|
21943
21984
|
nodeType: { const: "paragraph" },
|
|
@@ -22105,6 +22146,7 @@ ref$1("TargetKind");
|
|
|
22105
22146
|
var textAddressSchema = ref$1("TextAddress");
|
|
22106
22147
|
var textTargetSchema = ref$1("TextTarget");
|
|
22107
22148
|
var blockNodeAddressSchema = ref$1("BlockNodeAddress");
|
|
22149
|
+
var deletableBlockNodeAddressSchema = ref$1("DeletableBlockNodeAddress");
|
|
22108
22150
|
var paragraphAddressSchema = ref$1("ParagraphAddress");
|
|
22109
22151
|
var headingAddressSchema = ref$1("HeadingAddress");
|
|
22110
22152
|
var listItemAddressSchema = ref$1("ListItemAddress");
|
|
@@ -22481,6 +22523,7 @@ var trackChangesListResultSchema = discoveryResultSchema(discoveryItemSchema({
|
|
|
22481
22523
|
}, ["address", "type"]));
|
|
22482
22524
|
var capabilityReasonsSchema = arraySchema({ enum: [
|
|
22483
22525
|
"COMMAND_UNAVAILABLE",
|
|
22526
|
+
"HELPER_UNAVAILABLE",
|
|
22484
22527
|
"OPERATION_UNAVAILABLE",
|
|
22485
22528
|
"TRACKED_MODE_UNAVAILABLE",
|
|
22486
22529
|
"DRY_RUN_UNAVAILABLE",
|
|
@@ -22639,6 +22682,18 @@ var operationSchemas = {
|
|
|
22639
22682
|
success: textMutationSuccessSchema,
|
|
22640
22683
|
failure: textMutationFailureSchemaFor("format.align")
|
|
22641
22684
|
},
|
|
22685
|
+
"blocks.delete": {
|
|
22686
|
+
input: objectSchema({ target: deletableBlockNodeAddressSchema }, ["target"]),
|
|
22687
|
+
output: objectSchema({
|
|
22688
|
+
success: { const: true },
|
|
22689
|
+
deleted: deletableBlockNodeAddressSchema
|
|
22690
|
+
}, ["success", "deleted"]),
|
|
22691
|
+
success: objectSchema({
|
|
22692
|
+
success: { const: true },
|
|
22693
|
+
deleted: deletableBlockNodeAddressSchema
|
|
22694
|
+
}, ["success", "deleted"]),
|
|
22695
|
+
failure: preApplyFailureResultSchemaFor("blocks.delete")
|
|
22696
|
+
},
|
|
22642
22697
|
"create.paragraph": {
|
|
22643
22698
|
input: objectSchema({
|
|
22644
22699
|
at: { oneOf: [
|
|
@@ -22941,6 +22996,11 @@ var GROUP_METADATA = {
|
|
|
22941
22996
|
description: "Primary read and write operations.",
|
|
22942
22997
|
pagePath: "core/index.mdx"
|
|
22943
22998
|
},
|
|
22999
|
+
blocks: {
|
|
23000
|
+
title: "Blocks",
|
|
23001
|
+
description: "Block-level structural operations.",
|
|
23002
|
+
pagePath: "blocks/index.mdx"
|
|
23003
|
+
},
|
|
22944
23004
|
capabilities: {
|
|
22945
23005
|
title: "Capabilities",
|
|
22946
23006
|
description: "Runtime support discovery for capability-aware branching.",
|
|
@@ -22989,6 +23049,7 @@ const REFERENCE_OPERATION_GROUPS = Object.keys(GROUP_METADATA).map((key$1) => ({
|
|
|
22989
23049
|
}));
|
|
22990
23050
|
const CAPABILITY_REASON_CODES = [
|
|
22991
23051
|
"COMMAND_UNAVAILABLE",
|
|
23052
|
+
"HELPER_UNAVAILABLE",
|
|
22992
23053
|
"OPERATION_UNAVAILABLE",
|
|
22993
23054
|
"TRACKED_MODE_UNAVAILABLE",
|
|
22994
23055
|
"DRY_RUN_UNAVAILABLE",
|
|
@@ -23286,6 +23347,27 @@ function executeCreateHeading(adapter, input, options) {
|
|
|
23286
23347
|
validateCreateLocation(normalized.at, "create.heading");
|
|
23287
23348
|
return adapter.heading(normalized, normalizeMutationOptions(options));
|
|
23288
23349
|
}
|
|
23350
|
+
var SUPPORTED_DELETE_NODE_TYPES = new Set(DELETABLE_BLOCK_NODE_TYPES);
|
|
23351
|
+
var REJECTED_DELETE_NODE_TYPES = new Set(["tableRow", "tableCell"]);
|
|
23352
|
+
function validateBlocksDeleteInput(input) {
|
|
23353
|
+
if (!input || typeof input !== "object") throw new DocumentApiValidationError("INVALID_INPUT", "blocks.delete requires an input object.", { fields: ["input"] });
|
|
23354
|
+
if (!input.target) throw new DocumentApiValidationError("INVALID_INPUT", "blocks.delete requires a target.", { fields: ["target"] });
|
|
23355
|
+
if (input.target.kind !== "block") throw new DocumentApiValidationError("INVALID_INPUT", "blocks.delete target must have kind \"block\".", { fields: ["target.kind"] });
|
|
23356
|
+
if (!input.target.nodeId || typeof input.target.nodeId !== "string") throw new DocumentApiValidationError("INVALID_INPUT", "blocks.delete target requires a nodeId string.", { fields: ["target.nodeId"] });
|
|
23357
|
+
const { nodeType } = input.target;
|
|
23358
|
+
if (REJECTED_DELETE_NODE_TYPES.has(nodeType)) throw new DocumentApiValidationError("INVALID_TARGET", `blocks.delete does not support "${nodeType}" targets. Table row/column operations are out of scope.`, {
|
|
23359
|
+
fields: ["target.nodeType"],
|
|
23360
|
+
nodeType
|
|
23361
|
+
});
|
|
23362
|
+
if (!SUPPORTED_DELETE_NODE_TYPES.has(nodeType)) throw new DocumentApiValidationError("INVALID_TARGET", `blocks.delete does not support "${nodeType}" targets.`, {
|
|
23363
|
+
fields: ["target.nodeType"],
|
|
23364
|
+
nodeType
|
|
23365
|
+
});
|
|
23366
|
+
}
|
|
23367
|
+
function executeBlocksDelete(adapter, input, options) {
|
|
23368
|
+
validateBlocksDeleteInput(input);
|
|
23369
|
+
return adapter.delete(input, normalizeMutationOptions(options));
|
|
23370
|
+
}
|
|
23289
23371
|
function executeTrackChangesList(adapter, input) {
|
|
23290
23372
|
return adapter.list(input);
|
|
23291
23373
|
}
|
|
@@ -23329,6 +23411,7 @@ function buildDispatchTable(api) {
|
|
|
23329
23411
|
insert: (input, options) => api.insert(input, options),
|
|
23330
23412
|
replace: (input, options) => api.replace(input, options),
|
|
23331
23413
|
delete: (input, options) => api.delete(input, options),
|
|
23414
|
+
"blocks.delete": (input, options) => api.blocks.delete(input, options),
|
|
23332
23415
|
"format.apply": (input, options) => api.format.apply(input, options),
|
|
23333
23416
|
"format.fontSize": (input, options) => api.format.fontSize(input, options),
|
|
23334
23417
|
"format.fontFamily": (input, options) => api.format.fontFamily(input, options),
|
|
@@ -23454,6 +23537,9 @@ function createDocumentApi(adapters) {
|
|
|
23454
23537
|
return executeTrackChangesDecide(adapters.trackChanges, input, options);
|
|
23455
23538
|
}
|
|
23456
23539
|
},
|
|
23540
|
+
blocks: { delete(input, options) {
|
|
23541
|
+
return executeBlocksDelete(adapters.blocks, input, options);
|
|
23542
|
+
} },
|
|
23457
23543
|
create: {
|
|
23458
23544
|
paragraph(input, options) {
|
|
23459
23545
|
return executeCreateParagraph(adapters.create, input, options);
|
|
@@ -23538,6 +23624,7 @@ var REQUIRED_COMMANDS = {
|
|
|
23538
23624
|
"lists.outdent": ["setTextSelection", "decreaseListIndent"],
|
|
23539
23625
|
"lists.restart": ["setTextSelection", "restartNumbering"],
|
|
23540
23626
|
"lists.exit": ["exitListItemAt"],
|
|
23627
|
+
"blocks.delete": ["deleteBlockNodeById"],
|
|
23541
23628
|
"comments.create": [
|
|
23542
23629
|
"addComment",
|
|
23543
23630
|
"setTextSelection",
|
|
@@ -23566,6 +23653,12 @@ function hasAllCommands(editor, operationId) {
|
|
|
23566
23653
|
if (!required || required.length === 0) return true;
|
|
23567
23654
|
return required.every((command$1) => hasCommand(editor, command$1));
|
|
23568
23655
|
}
|
|
23656
|
+
var REQUIRED_HELPERS = { "blocks.delete": (editor) => typeof editor.helpers?.blockNode?.getBlockNodeById === "function" };
|
|
23657
|
+
function hasRequiredHelpers(editor, operationId) {
|
|
23658
|
+
const check = REQUIRED_HELPERS[operationId];
|
|
23659
|
+
if (!check) return true;
|
|
23660
|
+
return check(editor);
|
|
23661
|
+
}
|
|
23569
23662
|
function hasMarkCapability(editor, markName) {
|
|
23570
23663
|
return Boolean(editor.schema?.marks?.[markName]);
|
|
23571
23664
|
}
|
|
@@ -23611,7 +23704,7 @@ function pushReason(reasons, reason) {
|
|
|
23611
23704
|
function isOperationAvailable(editor, operationId) {
|
|
23612
23705
|
if (operationId === "format.apply") return MARK_KEYS.some((key$1) => hasMarkCapability(editor, STYLE_MARK_SCHEMA_NAMES[key$1] ?? key$1));
|
|
23613
23706
|
if (INLINE_FORMAT_OPERATIONS.has(operationId)) return hasAllCommands(editor, operationId) && hasMarkCapability(editor, "textStyle");
|
|
23614
|
-
return hasAllCommands(editor, operationId);
|
|
23707
|
+
return hasAllCommands(editor, operationId) && hasRequiredHelpers(editor, operationId);
|
|
23615
23708
|
}
|
|
23616
23709
|
function isCommandBackedAvailability(operationId) {
|
|
23617
23710
|
return !isMarkBackedOperation(operationId) && !INLINE_FORMAT_OPERATIONS.has(operationId);
|
|
@@ -23625,7 +23718,10 @@ function buildOperationCapabilities(editor) {
|
|
|
23625
23718
|
const dryRun = metadata.supportsDryRun && available;
|
|
23626
23719
|
const reasons = [];
|
|
23627
23720
|
if (!available) {
|
|
23628
|
-
if (isCommandBackedAvailability(operationId))
|
|
23721
|
+
if (isCommandBackedAvailability(operationId)) {
|
|
23722
|
+
if (!hasAllCommands(editor, operationId)) pushReason(reasons, "COMMAND_UNAVAILABLE");
|
|
23723
|
+
if (!hasRequiredHelpers(editor, operationId)) pushReason(reasons, "HELPER_UNAVAILABLE");
|
|
23724
|
+
}
|
|
23629
23725
|
pushReason(reasons, "OPERATION_UNAVAILABLE");
|
|
23630
23726
|
}
|
|
23631
23727
|
if (metadata.supportsTrackedMode && !tracked) pushReason(reasons, "TRACKED_MODE_UNAVAILABLE");
|
|
@@ -24115,13 +24211,21 @@ function buildBlockIndex(editor) {
|
|
|
24115
24211
|
});
|
|
24116
24212
|
return {
|
|
24117
24213
|
candidates,
|
|
24118
|
-
byId
|
|
24214
|
+
byId,
|
|
24215
|
+
ambiguous
|
|
24119
24216
|
};
|
|
24120
24217
|
}
|
|
24121
24218
|
function findBlockById(index, address) {
|
|
24122
24219
|
if (address.kind !== "block") return void 0;
|
|
24123
24220
|
return index.byId.get(`${address.nodeType}:${address.nodeId}`);
|
|
24124
24221
|
}
|
|
24222
|
+
function findBlockByIdStrict(index, address) {
|
|
24223
|
+
const key$1 = `${address.nodeType}:${address.nodeId}`;
|
|
24224
|
+
if (index.ambiguous.has(key$1)) throw new DocumentApiAdapterError("AMBIGUOUS_TARGET", `Multiple blocks share key "${key$1}".`, { target: address });
|
|
24225
|
+
const candidate = index.byId.get(key$1);
|
|
24226
|
+
if (!candidate) throw new DocumentApiAdapterError("TARGET_NOT_FOUND", `Block "${key$1}" was not found.`, { target: address });
|
|
24227
|
+
return candidate;
|
|
24228
|
+
}
|
|
24125
24229
|
function isTextBlockCandidate(candidate) {
|
|
24126
24230
|
const node = candidate.node;
|
|
24127
24231
|
return Boolean(node?.inlineContent || node?.isTextblock);
|
|
@@ -24207,9 +24311,11 @@ function trackRevisions(editor) {
|
|
|
24207
24311
|
function checkRevision(editor, expectedRevision) {
|
|
24208
24312
|
if (expectedRevision === void 0) return;
|
|
24209
24313
|
const current = getRevision(editor);
|
|
24210
|
-
if (expectedRevision !== current) throw new PlanError("REVISION_MISMATCH", `REVISION_MISMATCH — expected revision "${expectedRevision}" but document is at "${current}"
|
|
24314
|
+
if (expectedRevision !== current) throw new PlanError("REVISION_MISMATCH", `REVISION_MISMATCH — expected revision "${expectedRevision}" but document is at "${current}". Re-run query.match to obtain a fresh ref.`, void 0, {
|
|
24211
24315
|
expectedRevision,
|
|
24212
|
-
currentRevision: current
|
|
24316
|
+
currentRevision: current,
|
|
24317
|
+
refStability: "ephemeral",
|
|
24318
|
+
remediation: "Re-run query.match() to obtain a fresh ref valid for the current revision."
|
|
24213
24319
|
});
|
|
24214
24320
|
}
|
|
24215
24321
|
function resolveSegmentPosition(targetOffset, segmentStart, segmentLength, docFrom, docTo) {
|
|
@@ -24459,7 +24565,9 @@ function captureRunsInRange(editor, blockPos, from$1, to) {
|
|
|
24459
24565
|
return;
|
|
24460
24566
|
}
|
|
24461
24567
|
if (node.isLeaf) {
|
|
24568
|
+
const start$1 = offset$1;
|
|
24462
24569
|
offset$1 += 1;
|
|
24570
|
+
maybePushRun(start$1, offset$1, []);
|
|
24463
24571
|
return;
|
|
24464
24572
|
}
|
|
24465
24573
|
let isFirstChild = true;
|
|
@@ -24859,12 +24967,62 @@ function executeBlockSelector(index, query, diagnostics) {
|
|
|
24859
24967
|
function isAssertStep(step) {
|
|
24860
24968
|
return step.op === "assert";
|
|
24861
24969
|
}
|
|
24970
|
+
function isCreateOp(op) {
|
|
24971
|
+
return op === "create.heading" || op === "create.paragraph";
|
|
24972
|
+
}
|
|
24973
|
+
var VALID_CREATE_POSITIONS = ["before", "after"];
|
|
24862
24974
|
function isSelectWhere(where) {
|
|
24863
24975
|
return where.by === "select";
|
|
24864
24976
|
}
|
|
24865
24977
|
function isRefWhere(where) {
|
|
24866
24978
|
return where.by === "ref";
|
|
24867
24979
|
}
|
|
24980
|
+
function validateCreateStepPosition(step) {
|
|
24981
|
+
const args$1 = step.args;
|
|
24982
|
+
if (args$1.position === void 0 || args$1.position === null) {
|
|
24983
|
+
args$1.position = "after";
|
|
24984
|
+
return;
|
|
24985
|
+
}
|
|
24986
|
+
if (!VALID_CREATE_POSITIONS.includes(args$1.position)) throw planError("INVALID_INPUT", `create step requires args.position to be 'before' or 'after'`, step.id, {
|
|
24987
|
+
receivedPosition: args$1.position,
|
|
24988
|
+
allowedValues: [...VALID_CREATE_POSITIONS],
|
|
24989
|
+
default: "after"
|
|
24990
|
+
});
|
|
24991
|
+
}
|
|
24992
|
+
function resolveCreateAnchorFromTargets(targets, position, stepId) {
|
|
24993
|
+
const target = targets[0];
|
|
24994
|
+
if (!target) throw planError("INVALID_INPUT", "create step has no resolved targets", stepId);
|
|
24995
|
+
if (target.kind === "range") return target.blockId;
|
|
24996
|
+
const segments = target.segments;
|
|
24997
|
+
if (!segments.length) throw planError("INVALID_INPUT", "span target has no segments", stepId);
|
|
24998
|
+
return position === "before" ? segments[0].blockId : segments[segments.length - 1].blockId;
|
|
24999
|
+
}
|
|
25000
|
+
function validateInsertionContext(editor, index, step, stepIndex, anchorBlockId, position) {
|
|
25001
|
+
const candidate = index.candidates.find((c$3) => c$3.nodeId === anchorBlockId);
|
|
25002
|
+
if (!candidate) return;
|
|
25003
|
+
const paragraphType = editor.state.schema?.nodes?.paragraph;
|
|
25004
|
+
if (!paragraphType) return;
|
|
25005
|
+
const resolvedPos = editor.state.doc.resolve(candidate.pos);
|
|
25006
|
+
const parent = resolvedPos.parent;
|
|
25007
|
+
const anchorIndex = resolvedPos.index();
|
|
25008
|
+
const insertionIndex = position === "before" ? anchorIndex : anchorIndex + 1;
|
|
25009
|
+
if (!(typeof parent.canReplaceWith === "function" ? parent.canReplaceWith(insertionIndex, insertionIndex, paragraphType) : parent.type.contentMatch.matchType(paragraphType))) {
|
|
25010
|
+
const allowedChildTypes = [];
|
|
25011
|
+
const match$1 = parent.type.contentMatch;
|
|
25012
|
+
for (const nodeType of Object.values(editor.state.schema.nodes)) if (match$1.matchType(nodeType)) allowedChildTypes.push(nodeType.name);
|
|
25013
|
+
throw planError("INVALID_INSERTION_CONTEXT", `Cannot create ${step.op} inside ${parent.type.name}`, step.id, {
|
|
25014
|
+
stepIndex,
|
|
25015
|
+
stepId: step.id,
|
|
25016
|
+
operation: step.op,
|
|
25017
|
+
anchorBlockId,
|
|
25018
|
+
parentType: parent.type.name,
|
|
25019
|
+
allowedChildTypes,
|
|
25020
|
+
insertionIndex,
|
|
25021
|
+
requestedChildType: "paragraph",
|
|
25022
|
+
requestedSemanticType: step.op === "create.heading" ? "heading" : "paragraph"
|
|
25023
|
+
});
|
|
25024
|
+
}
|
|
25025
|
+
}
|
|
24868
25026
|
function isV3Ref(payload) {
|
|
24869
25027
|
return typeof payload === "object" && payload !== null && "v" in payload && payload.v === 3;
|
|
24870
25028
|
}
|
|
@@ -25077,9 +25235,13 @@ function decodeTextRefPayload(encoded, stepId) {
|
|
|
25077
25235
|
}
|
|
25078
25236
|
function resolveV3TextRef(editor, index, step, refData) {
|
|
25079
25237
|
const currentRevision = getRevision(editor);
|
|
25080
|
-
if (refData.rev !== currentRevision) throw planError("REVISION_MISMATCH", `
|
|
25238
|
+
if (refData.rev !== currentRevision) throw planError("REVISION_MISMATCH", `Text ref is ephemeral and revision-scoped. Re-run query.match to obtain a fresh handle.ref for revision ${currentRevision}.`, step.id, {
|
|
25081
25239
|
refRevision: refData.rev,
|
|
25082
|
-
currentRevision
|
|
25240
|
+
currentRevision,
|
|
25241
|
+
refStability: "ephemeral",
|
|
25242
|
+
refScope: refData.scope,
|
|
25243
|
+
blockId: refData.segments?.[0]?.blockId,
|
|
25244
|
+
remediation: `Re-run query.match() to obtain a fresh ref valid for the current revision.`
|
|
25083
25245
|
});
|
|
25084
25246
|
if (!refData.segments?.length) return [];
|
|
25085
25247
|
const segments = refData.segments.map((s) => ({
|
|
@@ -25178,7 +25340,11 @@ function resolveStepTargets(editor, index, step) {
|
|
|
25178
25340
|
return t.blockId !== prev.blockId || t.from !== prev.from || t.to !== prev.to;
|
|
25179
25341
|
});
|
|
25180
25342
|
if (refWhere) {
|
|
25181
|
-
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", `ref "${refWhere.ref}" did not resolve to any targets`, step.id
|
|
25343
|
+
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", `ref "${refWhere.ref}" did not resolve to any targets`, step.id, {
|
|
25344
|
+
selectorType: "ref",
|
|
25345
|
+
selectorPattern: refWhere.ref,
|
|
25346
|
+
candidateCount: 0
|
|
25347
|
+
});
|
|
25182
25348
|
if (targets.length > 1) throw planError("AMBIGUOUS_MATCH", `ref "${refWhere.ref}" resolved to ${targets.length} targets`, step.id, { matchCount: targets.length });
|
|
25183
25349
|
return targets;
|
|
25184
25350
|
}
|
|
@@ -25187,57 +25353,157 @@ function resolveStepTargets(editor, index, step) {
|
|
|
25187
25353
|
if (selectWhere.require === "first" && targets.length > 1) targets = [targets[0]];
|
|
25188
25354
|
return targets;
|
|
25189
25355
|
}
|
|
25356
|
+
function buildMatchNotFoundDetails(step) {
|
|
25357
|
+
const where = step.where;
|
|
25358
|
+
const select = "select" in where ? where.select : void 0;
|
|
25359
|
+
const within$1 = "within" in where ? where.within : void 0;
|
|
25360
|
+
return {
|
|
25361
|
+
selectorType: select?.type ?? "unknown",
|
|
25362
|
+
selectorPattern: select?.pattern ?? "",
|
|
25363
|
+
selectorMode: select?.mode ?? "contains",
|
|
25364
|
+
searchScope: within$1?.blockId ?? "document",
|
|
25365
|
+
candidateCount: 0
|
|
25366
|
+
};
|
|
25367
|
+
}
|
|
25190
25368
|
function applyCardinalityCheck(step, targets) {
|
|
25191
25369
|
const where = step.where;
|
|
25192
25370
|
if (!("require" in where) || where.require === void 0) return;
|
|
25193
25371
|
const require$1 = where.require;
|
|
25194
25372
|
if (require$1 === "first") {
|
|
25195
|
-
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges", step.id);
|
|
25373
|
+
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges", step.id, buildMatchNotFoundDetails(step));
|
|
25196
25374
|
} else if (require$1 === "exactlyOne") {
|
|
25197
|
-
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges", step.id);
|
|
25375
|
+
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges", step.id, buildMatchNotFoundDetails(step));
|
|
25198
25376
|
if (targets.length > 1) throw planError("AMBIGUOUS_MATCH", `selector matched ${targets.length} ranges, expected exactly one`, step.id, { matchCount: targets.length });
|
|
25199
25377
|
} else if (require$1 === "all") {
|
|
25200
|
-
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges", step.id);
|
|
25201
|
-
}
|
|
25202
|
-
}
|
|
25203
|
-
|
|
25204
|
-
|
|
25205
|
-
|
|
25206
|
-
|
|
25207
|
-
|
|
25208
|
-
|
|
25209
|
-
|
|
25210
|
-
|
|
25211
|
-
|
|
25212
|
-
|
|
25378
|
+
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges", step.id, buildMatchNotFoundDetails(step));
|
|
25379
|
+
}
|
|
25380
|
+
}
|
|
25381
|
+
const STEP_INTERACTION_MATRIX = new Map([
|
|
25382
|
+
["text.rewrite::format.apply::same_target", "allow"],
|
|
25383
|
+
["text.rewrite::text.rewrite::same_target", "reject"],
|
|
25384
|
+
["text.rewrite::text.delete::overlapping", "reject"],
|
|
25385
|
+
["text.rewrite::create.*::same_block", "allow"],
|
|
25386
|
+
["text.rewrite::text.insert::same_target", "reject"],
|
|
25387
|
+
["format.apply::format.apply::same_target", "allow"],
|
|
25388
|
+
["format.apply::text.rewrite::same_target", "reject"],
|
|
25389
|
+
["format.apply::text.delete::overlapping", "reject"],
|
|
25390
|
+
["format.apply::create.*::same_block", "allow"],
|
|
25391
|
+
["format.apply::text.insert::same_target", "allow"],
|
|
25392
|
+
["text.delete::text.rewrite::overlapping", "reject"],
|
|
25393
|
+
["text.delete::text.delete::overlapping", "reject"],
|
|
25394
|
+
["text.delete::format.apply::overlapping", "reject"],
|
|
25395
|
+
["text.delete::create.*::same_block", "allow"],
|
|
25396
|
+
["text.delete::text.insert::overlapping", "reject"],
|
|
25397
|
+
["create.*::text.rewrite::same_block", "allow"],
|
|
25398
|
+
["create.*::format.apply::same_block", "allow"],
|
|
25399
|
+
["create.*::text.delete::same_block", "allow"],
|
|
25400
|
+
["create.*::create.*::same_block", "allow"],
|
|
25401
|
+
["create.*::text.insert::same_block", "allow"],
|
|
25402
|
+
["text.insert::format.apply::same_target", "allow"],
|
|
25403
|
+
["text.insert::text.rewrite::same_target", "reject"],
|
|
25404
|
+
["text.insert::text.delete::overlapping", "reject"],
|
|
25405
|
+
["text.insert::create.*::same_block", "allow"],
|
|
25406
|
+
["text.insert::text.insert::same_target", "reject"]
|
|
25407
|
+
]);
|
|
25408
|
+
const MATRIX_EXEMPT_OPS = new Set(["assert"]);
|
|
25409
|
+
function normalizeOpForMatrix(op) {
|
|
25410
|
+
return op.startsWith("create.") ? "create.*" : op;
|
|
25411
|
+
}
|
|
25412
|
+
function classifyOverlap(stepA, stepB) {
|
|
25413
|
+
const rangesA = extractBlockRanges(stepA);
|
|
25414
|
+
const rangesB = extractBlockRanges(stepB);
|
|
25415
|
+
const opA = normalizeOpForMatrix(stepA.step.op);
|
|
25416
|
+
const opB = normalizeOpForMatrix(stepB.step.op);
|
|
25417
|
+
const isCreateA = opA === "create.*";
|
|
25418
|
+
const isCreateB = opB === "create.*";
|
|
25419
|
+
for (const [blockId, aEntries] of rangesA) {
|
|
25420
|
+
const bEntries = rangesB.get(blockId);
|
|
25421
|
+
if (!bEntries) continue;
|
|
25422
|
+
for (const a of aEntries) for (const b$1 of bEntries) {
|
|
25423
|
+
if (isCreateA || isCreateB) return {
|
|
25424
|
+
overlapClass: "same_block",
|
|
25213
25425
|
blockId,
|
|
25214
|
-
rangeA:
|
|
25215
|
-
|
|
25216
|
-
|
|
25217
|
-
|
|
25218
|
-
|
|
25219
|
-
|
|
25220
|
-
|
|
25221
|
-
|
|
25222
|
-
|
|
25426
|
+
rangeA: a,
|
|
25427
|
+
rangeB: b$1
|
|
25428
|
+
};
|
|
25429
|
+
if (a.to <= b$1.from || b$1.to <= a.from) continue;
|
|
25430
|
+
if (a.from === b$1.from && a.to === b$1.to) return {
|
|
25431
|
+
overlapClass: "same_target",
|
|
25432
|
+
blockId,
|
|
25433
|
+
rangeA: a,
|
|
25434
|
+
rangeB: b$1
|
|
25435
|
+
};
|
|
25436
|
+
return {
|
|
25437
|
+
overlapClass: "overlapping",
|
|
25438
|
+
blockId,
|
|
25439
|
+
rangeA: a,
|
|
25440
|
+
rangeB: b$1
|
|
25441
|
+
};
|
|
25223
25442
|
}
|
|
25224
25443
|
}
|
|
25225
25444
|
}
|
|
25226
|
-
function
|
|
25227
|
-
|
|
25228
|
-
if (
|
|
25229
|
-
|
|
25230
|
-
|
|
25445
|
+
function extractBlockRanges(compiled) {
|
|
25446
|
+
const result = /* @__PURE__ */ new Map();
|
|
25447
|
+
for (const target of compiled.targets) if (target.kind === "range") pushBlockRange(result, target.blockId, target.from, target.to);
|
|
25448
|
+
else for (const seg of target.segments) pushBlockRange(result, seg.blockId, seg.from, seg.to);
|
|
25449
|
+
return result;
|
|
25450
|
+
}
|
|
25451
|
+
function pushBlockRange(map$2, blockId, from$1, to) {
|
|
25452
|
+
let entries = map$2.get(blockId);
|
|
25453
|
+
if (!entries) {
|
|
25454
|
+
entries = [];
|
|
25455
|
+
map$2.set(blockId, entries);
|
|
25231
25456
|
}
|
|
25232
|
-
|
|
25233
|
-
stepId,
|
|
25457
|
+
entries.push({
|
|
25234
25458
|
from: from$1,
|
|
25235
25459
|
to
|
|
25236
25460
|
});
|
|
25237
25461
|
}
|
|
25462
|
+
function validateStepInteractions(steps) {
|
|
25463
|
+
for (let i$1 = 0; i$1 < steps.length; i$1++) for (let j = i$1 + 1; j < steps.length; j++) {
|
|
25464
|
+
const stepA = steps[i$1];
|
|
25465
|
+
const stepB = steps[j];
|
|
25466
|
+
if (MATRIX_EXEMPT_OPS.has(stepA.step.op) || MATRIX_EXEMPT_OPS.has(stepB.step.op)) continue;
|
|
25467
|
+
const overlap = classifyOverlap(stepA, stepB);
|
|
25468
|
+
if (!overlap) continue;
|
|
25469
|
+
const matrixKey = `${normalizeOpForMatrix(stepA.step.op)}::${normalizeOpForMatrix(stepB.step.op)}::${overlap.overlapClass}`;
|
|
25470
|
+
const verdict = STEP_INTERACTION_MATRIX.get(matrixKey) ?? "reject";
|
|
25471
|
+
if (verdict === "reject") throw planError("PLAN_CONFLICT_OVERLAP", `steps "${stepA.step.id}" and "${stepB.step.id}" target overlapping ranges in block "${overlap.blockId}"`, stepB.step.id, {
|
|
25472
|
+
blockId: overlap.blockId,
|
|
25473
|
+
stepIdA: stepA.step.id,
|
|
25474
|
+
stepIdB: stepB.step.id,
|
|
25475
|
+
opKeyA: stepA.step.op,
|
|
25476
|
+
opKeyB: stepB.step.op,
|
|
25477
|
+
rangeA: overlap.rangeA,
|
|
25478
|
+
rangeB: overlap.rangeB,
|
|
25479
|
+
overlapRegion: {
|
|
25480
|
+
from: Math.max(overlap.rangeA.from, overlap.rangeB.from),
|
|
25481
|
+
to: Math.min(overlap.rangeA.to, overlap.rangeB.to)
|
|
25482
|
+
},
|
|
25483
|
+
matrixVerdict: verdict,
|
|
25484
|
+
matrixKey
|
|
25485
|
+
});
|
|
25486
|
+
}
|
|
25487
|
+
}
|
|
25488
|
+
function assertNoDuplicateBlockIds(index) {
|
|
25489
|
+
const seen = /* @__PURE__ */ new Map();
|
|
25490
|
+
const duplicates = [];
|
|
25491
|
+
for (const candidate of index.candidates) {
|
|
25492
|
+
const count = seen.get(candidate.nodeId) ?? 0;
|
|
25493
|
+
seen.set(candidate.nodeId, count + 1);
|
|
25494
|
+
if (count === 1) duplicates.push(candidate.nodeId);
|
|
25495
|
+
}
|
|
25496
|
+
if (duplicates.length > 0) throw planError("DOCUMENT_IDENTITY_CONFLICT", "Document contains blocks with duplicate identities. This must be resolved before mutations can be applied.", void 0, {
|
|
25497
|
+
duplicateBlockIds: duplicates,
|
|
25498
|
+
blockCount: duplicates.length,
|
|
25499
|
+
remediation: "Re-import the document or call document.repair() to assign unique identities."
|
|
25500
|
+
});
|
|
25501
|
+
}
|
|
25238
25502
|
function compilePlan(editor, steps) {
|
|
25239
25503
|
if (steps.length > 200) throw planError("INVALID_INPUT", `plan contains ${steps.length} steps, maximum is 200`);
|
|
25504
|
+
const compiledRevision = getRevision(editor);
|
|
25240
25505
|
const index = getBlockIndex(editor);
|
|
25506
|
+
assertNoDuplicateBlockIds(index);
|
|
25241
25507
|
const mutationSteps = [];
|
|
25242
25508
|
const assertSteps = [];
|
|
25243
25509
|
const seenIds = /* @__PURE__ */ new Set();
|
|
@@ -25247,26 +25513,41 @@ function compilePlan(editor, steps) {
|
|
|
25247
25513
|
seenIds.add(step.id);
|
|
25248
25514
|
}
|
|
25249
25515
|
let totalTargets = 0;
|
|
25516
|
+
let stepIndex = 0;
|
|
25250
25517
|
for (const step of steps) {
|
|
25251
25518
|
if (isAssertStep(step)) {
|
|
25252
25519
|
assertSteps.push(step);
|
|
25520
|
+
stepIndex++;
|
|
25253
25521
|
continue;
|
|
25254
25522
|
}
|
|
25255
25523
|
if (!hasStepExecutor(step.op)) throw planError("INVALID_INPUT", `unknown step op "${step.op}"`, step.id);
|
|
25524
|
+
if (isCreateOp(step.op)) validateCreateStepPosition(step);
|
|
25256
25525
|
const targets = resolveStepTargets(editor, index, step);
|
|
25526
|
+
if (isCreateOp(step.op) && targets.length > 0) {
|
|
25527
|
+
const position = step.args.position ?? "after";
|
|
25528
|
+
const anchorBlockId = resolveCreateAnchorFromTargets(targets, position, step.id);
|
|
25529
|
+
validateInsertionContext(editor, index, step, stepIndex, anchorBlockId, position);
|
|
25530
|
+
}
|
|
25257
25531
|
totalTargets += targets.length;
|
|
25258
25532
|
mutationSteps.push({
|
|
25259
25533
|
step,
|
|
25260
25534
|
targets
|
|
25261
25535
|
});
|
|
25536
|
+
stepIndex++;
|
|
25262
25537
|
}
|
|
25263
25538
|
if (totalTargets > 500) throw planError("INVALID_INPUT", `plan resolved ${totalTargets} total targets, maximum is 500`);
|
|
25264
|
-
|
|
25539
|
+
validateStepInteractions(mutationSteps);
|
|
25265
25540
|
return {
|
|
25266
25541
|
mutationSteps,
|
|
25267
|
-
assertSteps
|
|
25542
|
+
assertSteps,
|
|
25543
|
+
compiledRevision
|
|
25268
25544
|
};
|
|
25269
25545
|
}
|
|
25546
|
+
function resolveBlockInsertionPos(editor, anchorBlockId, position, stepId) {
|
|
25547
|
+
const candidate = getBlockIndex(editor).candidates.find((c$3) => c$3.nodeId === anchorBlockId);
|
|
25548
|
+
if (!candidate) throw planError("TARGET_NOT_FOUND", `block "${anchorBlockId}" not found`, stepId);
|
|
25549
|
+
return position === "before" ? candidate.pos : candidate.end;
|
|
25550
|
+
}
|
|
25270
25551
|
function applyDirectMutationMeta(tr) {
|
|
25271
25552
|
tr.setMeta("inputType", "programmatic");
|
|
25272
25553
|
tr.setMeta("skipTrackChanges", true);
|
|
@@ -25311,10 +25592,28 @@ function buildMarksFromSetMarks(editor, setMarks) {
|
|
|
25311
25592
|
if (setMarks.strike && schema.marks.strike) marks.push(schema.marks.strike.create());
|
|
25312
25593
|
return marks;
|
|
25313
25594
|
}
|
|
25314
|
-
function
|
|
25315
|
-
const
|
|
25316
|
-
|
|
25317
|
-
|
|
25595
|
+
function applyInlineMarkPatches(editor, tr, absFrom, absTo, inline) {
|
|
25596
|
+
const { schema } = editor.state;
|
|
25597
|
+
let changed = false;
|
|
25598
|
+
const markEntries = [
|
|
25599
|
+
[inline.bold, schema.marks.bold],
|
|
25600
|
+
[inline.italic, schema.marks.italic],
|
|
25601
|
+
[inline.underline, schema.marks.underline],
|
|
25602
|
+
[inline.strike, schema.marks.strike]
|
|
25603
|
+
];
|
|
25604
|
+
for (const [value, markType] of markEntries) {
|
|
25605
|
+
if (value === void 0 || !markType) continue;
|
|
25606
|
+
if (value) tr.addMark(absFrom, absTo, markType.create());
|
|
25607
|
+
else tr.removeMark(absFrom, absTo, markType);
|
|
25608
|
+
changed = true;
|
|
25609
|
+
}
|
|
25610
|
+
return changed;
|
|
25611
|
+
}
|
|
25612
|
+
function resolveCreateAnchorBlockId(target, position, stepId) {
|
|
25613
|
+
if (target.kind === "range") return target.blockId;
|
|
25614
|
+
const segments = target.segments;
|
|
25615
|
+
if (!segments.length) throw planError("INVALID_INPUT", "span target has no segments", stepId);
|
|
25616
|
+
return position === "before" ? segments[0].blockId : segments[segments.length - 1].blockId;
|
|
25318
25617
|
}
|
|
25319
25618
|
function executeTextRewrite(editor, tr, target, step, mapping) {
|
|
25320
25619
|
const absFrom = mapping.map(target.absFrom);
|
|
@@ -25348,39 +25647,7 @@ function executeTextDelete(_editor, tr, target, _step, mapping) {
|
|
|
25348
25647
|
return { changed: true };
|
|
25349
25648
|
}
|
|
25350
25649
|
function executeStyleApply(editor, tr, target, step, mapping) {
|
|
25351
|
-
|
|
25352
|
-
const absTo = mapping.map(target.absTo);
|
|
25353
|
-
const { schema } = editor.state;
|
|
25354
|
-
let changed = false;
|
|
25355
|
-
const markEntries = [
|
|
25356
|
-
[
|
|
25357
|
-
"bold",
|
|
25358
|
-
step.args.inline.bold,
|
|
25359
|
-
schema.marks.bold
|
|
25360
|
-
],
|
|
25361
|
-
[
|
|
25362
|
-
"italic",
|
|
25363
|
-
step.args.inline.italic,
|
|
25364
|
-
schema.marks.italic
|
|
25365
|
-
],
|
|
25366
|
-
[
|
|
25367
|
-
"underline",
|
|
25368
|
-
step.args.inline.underline,
|
|
25369
|
-
schema.marks.underline
|
|
25370
|
-
],
|
|
25371
|
-
[
|
|
25372
|
-
"strike",
|
|
25373
|
-
step.args.inline.strike,
|
|
25374
|
-
schema.marks.strike
|
|
25375
|
-
]
|
|
25376
|
-
];
|
|
25377
|
-
for (const [, value, markType] of markEntries) {
|
|
25378
|
-
if (value === void 0 || !markType) continue;
|
|
25379
|
-
if (value) tr.addMark(absFrom, absTo, markType.create());
|
|
25380
|
-
else tr.removeMark(absFrom, absTo, markType);
|
|
25381
|
-
changed = true;
|
|
25382
|
-
}
|
|
25383
|
-
return { changed };
|
|
25650
|
+
return { changed: applyInlineMarkPatches(editor, tr, mapping.map(target.absFrom), mapping.map(target.absTo), step.args.inline) };
|
|
25384
25651
|
}
|
|
25385
25652
|
function validateMappedSpanContiguity(target, mapping, stepId) {
|
|
25386
25653
|
let lastMappedEnd = -1;
|
|
@@ -25441,41 +25708,9 @@ function executeSpanTextDelete(_editor, tr, target, step, mapping) {
|
|
|
25441
25708
|
}
|
|
25442
25709
|
function executeSpanStyleApply(editor, tr, target, step, mapping) {
|
|
25443
25710
|
validateMappedSpanContiguity(target, mapping, step.id);
|
|
25444
|
-
const { schema } = editor.state;
|
|
25445
|
-
let changed = false;
|
|
25446
25711
|
const firstSeg = target.segments[0];
|
|
25447
25712
|
const lastSeg = target.segments[target.segments.length - 1];
|
|
25448
|
-
|
|
25449
|
-
const absTo = mapping.map(lastSeg.absTo, -1);
|
|
25450
|
-
const markEntries = [
|
|
25451
|
-
[
|
|
25452
|
-
"bold",
|
|
25453
|
-
step.args.inline.bold,
|
|
25454
|
-
schema.marks.bold
|
|
25455
|
-
],
|
|
25456
|
-
[
|
|
25457
|
-
"italic",
|
|
25458
|
-
step.args.inline.italic,
|
|
25459
|
-
schema.marks.italic
|
|
25460
|
-
],
|
|
25461
|
-
[
|
|
25462
|
-
"underline",
|
|
25463
|
-
step.args.inline.underline,
|
|
25464
|
-
schema.marks.underline
|
|
25465
|
-
],
|
|
25466
|
-
[
|
|
25467
|
-
"strike",
|
|
25468
|
-
step.args.inline.strike,
|
|
25469
|
-
schema.marks.strike
|
|
25470
|
-
]
|
|
25471
|
-
];
|
|
25472
|
-
for (const [, value, markType] of markEntries) {
|
|
25473
|
-
if (value === void 0 || !markType) continue;
|
|
25474
|
-
if (value) tr.addMark(absFrom, absTo, markType.create());
|
|
25475
|
-
else tr.removeMark(absFrom, absTo, markType);
|
|
25476
|
-
changed = true;
|
|
25477
|
-
}
|
|
25478
|
-
return { changed };
|
|
25713
|
+
return { changed: applyInlineMarkPatches(editor, tr, mapping.map(firstSeg.absFrom, 1), mapping.map(lastSeg.absTo, -1), step.args.inline) };
|
|
25479
25714
|
}
|
|
25480
25715
|
function getReplacementText(replacement) {
|
|
25481
25716
|
if (replacement.blocks !== void 0) return replacement.blocks.map((b$1) => b$1.text).join("\n\n");
|
|
@@ -25587,7 +25822,8 @@ function buildAssertIndex(doc$2) {
|
|
|
25587
25822
|
});
|
|
25588
25823
|
return {
|
|
25589
25824
|
candidates,
|
|
25590
|
-
byId
|
|
25825
|
+
byId,
|
|
25826
|
+
ambiguous
|
|
25591
25827
|
};
|
|
25592
25828
|
}
|
|
25593
25829
|
function resolveAssertScope(index, select, within$1) {
|
|
@@ -25645,9 +25881,11 @@ function executeAssertStep(_editor, tr, step) {
|
|
|
25645
25881
|
}
|
|
25646
25882
|
function executeCreateStep(editor, tr, step, targets, mapping) {
|
|
25647
25883
|
const target = targets[0];
|
|
25648
|
-
if (!target
|
|
25884
|
+
if (!target) throw planError("INVALID_INPUT", `${step.op} step requires at least one target`, step.id);
|
|
25649
25885
|
const args$1 = step.args;
|
|
25650
|
-
const
|
|
25886
|
+
const position = args$1.position ?? "after";
|
|
25887
|
+
const anchorPos = resolveBlockInsertionPos(editor, resolveCreateAnchorBlockId(target, position, step.id), position, step.id);
|
|
25888
|
+
const pos = mapping.map(anchorPos);
|
|
25651
25889
|
const paragraphType = editor.state.schema?.nodes?.paragraph;
|
|
25652
25890
|
if (!paragraphType) throw planError("INVALID_INPUT", "paragraph node type not in schema", step.id);
|
|
25653
25891
|
const sdBlockId = args$1.sdBlockId;
|
|
@@ -25664,6 +25902,7 @@ function executeCreateStep(editor, tr, step, targets, mapping) {
|
|
|
25664
25902
|
const node = paragraphType.createAndFill(attrs, textNode ?? void 0) ?? paragraphType.create(attrs, textNode ? [textNode] : void 0);
|
|
25665
25903
|
if (!node) throw planError("INVALID_INPUT", `could not create ${step.op} node`, step.id);
|
|
25666
25904
|
tr.insert(pos, node);
|
|
25905
|
+
assertNoPostInsertDuplicateIds(tr.doc, step.id);
|
|
25667
25906
|
return {
|
|
25668
25907
|
stepId: step.id,
|
|
25669
25908
|
op: step.op,
|
|
@@ -25675,6 +25914,27 @@ function executeCreateStep(editor, tr, step, targets, mapping) {
|
|
|
25675
25914
|
}
|
|
25676
25915
|
};
|
|
25677
25916
|
}
|
|
25917
|
+
function assertNoPostInsertDuplicateIds(doc$2, stepId) {
|
|
25918
|
+
const seen = /* @__PURE__ */ new Set();
|
|
25919
|
+
const duplicateSet = /* @__PURE__ */ new Set();
|
|
25920
|
+
doc$2.descendants((node) => {
|
|
25921
|
+
if (!node.isTextblock) return true;
|
|
25922
|
+
const attrs = node.attrs ?? {};
|
|
25923
|
+
const id = typeof attrs.paraId === "string" && attrs.paraId || typeof attrs.sdBlockId === "string" && attrs.sdBlockId || typeof attrs.nodeId === "string" && attrs.nodeId;
|
|
25924
|
+
if (!id) return true;
|
|
25925
|
+
if (seen.has(id)) duplicateSet.add(id);
|
|
25926
|
+
else seen.add(id);
|
|
25927
|
+
return true;
|
|
25928
|
+
});
|
|
25929
|
+
if (duplicateSet.size > 0) {
|
|
25930
|
+
const duplicates = [...duplicateSet];
|
|
25931
|
+
throw planError("INTERNAL_ERROR", `create step produced duplicate block identities: [${duplicates.join(", ")}]`, stepId, {
|
|
25932
|
+
source: "executor:checkPostInsertIdentityUniqueness",
|
|
25933
|
+
invariant: "post-insert block IDs must be unique",
|
|
25934
|
+
duplicateBlockIds: duplicates
|
|
25935
|
+
});
|
|
25936
|
+
}
|
|
25937
|
+
}
|
|
25678
25938
|
function runMutationsOnTransaction(editor, tr, compiled, options) {
|
|
25679
25939
|
const mapping = tr.mapping;
|
|
25680
25940
|
const stepOutcomes = [];
|
|
@@ -25730,6 +25990,13 @@ function executeCompiledPlan(editor, compiled, options = {}) {
|
|
|
25730
25990
|
const startTime = performance.now();
|
|
25731
25991
|
const revisionBefore = getRevision(editor);
|
|
25732
25992
|
checkRevision(editor, options.expectedRevision);
|
|
25993
|
+
if (compiled.compiledRevision !== revisionBefore) throw planError("REVISION_CHANGED_SINCE_COMPILE", `Document revision changed between compile and execute. Compiled at "${compiled.compiledRevision}", now at "${revisionBefore}".`, void 0, {
|
|
25994
|
+
compiledRevision: compiled.compiledRevision,
|
|
25995
|
+
currentRevision: revisionBefore,
|
|
25996
|
+
stepCount: compiled.mutationSteps.length,
|
|
25997
|
+
failedAtStep: "pre-execution",
|
|
25998
|
+
remediation: "Re-compile the plan against the current document state."
|
|
25999
|
+
});
|
|
25733
26000
|
const tr = editor.state.tr;
|
|
25734
26001
|
if ((options.changeMode ?? "direct") === "tracked") applyTrackedMutationMeta(tr);
|
|
25735
26002
|
else applyDirectMutationMeta(tr);
|
|
@@ -25938,7 +26205,8 @@ function executeDomainCommand(editor, handler, options) {
|
|
|
25938
26205
|
},
|
|
25939
26206
|
targets: []
|
|
25940
26207
|
}],
|
|
25941
|
-
assertSteps: []
|
|
26208
|
+
assertSteps: [],
|
|
26209
|
+
compiledRevision: getRevision(editor)
|
|
25942
26210
|
}, { expectedRevision: options?.expectedRevision });
|
|
25943
26211
|
}
|
|
25944
26212
|
function validateWriteRequest(request, resolved) {
|
|
@@ -26025,7 +26293,8 @@ function writeWrapper(editor, request, options) {
|
|
|
26025
26293
|
step: stepDef,
|
|
26026
26294
|
targets: [toCompiledTarget(stepId, op, resolved)]
|
|
26027
26295
|
}],
|
|
26028
|
-
assertSteps: []
|
|
26296
|
+
assertSteps: [],
|
|
26297
|
+
compiledRevision: getRevision(editor)
|
|
26029
26298
|
}, {
|
|
26030
26299
|
changeMode: mode,
|
|
26031
26300
|
expectedRevision: options?.expectedRevision
|
|
@@ -26091,7 +26360,8 @@ function styleApplyWrapper(editor, input, options) {
|
|
|
26091
26360
|
marks: []
|
|
26092
26361
|
}]
|
|
26093
26362
|
}],
|
|
26094
|
-
assertSteps: []
|
|
26363
|
+
assertSteps: [],
|
|
26364
|
+
compiledRevision: getRevision(editor)
|
|
26095
26365
|
}, {
|
|
26096
26366
|
changeMode: mode,
|
|
26097
26367
|
expectedRevision: options?.expectedRevision
|
|
@@ -26857,6 +27127,51 @@ function createCommentsWrapper(editor) {
|
|
|
26857
27127
|
list: (query) => listCommentsHandler(editor, query)
|
|
26858
27128
|
};
|
|
26859
27129
|
}
|
|
27130
|
+
var SUPPORTED_NODE_TYPES = new Set(DELETABLE_BLOCK_NODE_TYPES);
|
|
27131
|
+
var REJECTED_NODE_TYPES = new Set(["tableRow", "tableCell"]);
|
|
27132
|
+
function validateTargetNodeType(nodeType) {
|
|
27133
|
+
if (REJECTED_NODE_TYPES.has(nodeType)) throw new DocumentApiAdapterError("INVALID_TARGET", `blocks.delete does not support "${nodeType}" targets. Table row/column operations are out of scope.`, { nodeType });
|
|
27134
|
+
if (!SUPPORTED_NODE_TYPES.has(nodeType)) throw new DocumentApiAdapterError("INVALID_TARGET", `blocks.delete does not support "${nodeType}" targets.`, { nodeType });
|
|
27135
|
+
}
|
|
27136
|
+
function resolveSdBlockId(candidate) {
|
|
27137
|
+
const sdBlockId = candidate.node.attrs?.sdBlockId;
|
|
27138
|
+
if (typeof sdBlockId === "string" && sdBlockId.length > 0) return sdBlockId;
|
|
27139
|
+
throw new DocumentApiAdapterError("INTERNAL_ERROR", "Resolved block candidate is missing sdBlockId attribute. This indicates a schema/extension invariant violation.", { attrs: candidate.node.attrs });
|
|
27140
|
+
}
|
|
27141
|
+
function validateCommandLayerUniqueness(editor, sdBlockId) {
|
|
27142
|
+
const getBlockNodeById = editor.helpers?.blockNode?.getBlockNodeById;
|
|
27143
|
+
if (typeof getBlockNodeById !== "function") throw new DocumentApiAdapterError("CAPABILITY_UNAVAILABLE", "blocks.delete requires the blockNode helper to be registered.", { reason: "missing_helper" });
|
|
27144
|
+
const matches = getBlockNodeById(sdBlockId);
|
|
27145
|
+
if (!matches || Array.isArray(matches) && matches.length === 0) throw new DocumentApiAdapterError("TARGET_NOT_FOUND", `Block with sdBlockId "${sdBlockId}" was not found at the command layer.`, { sdBlockId });
|
|
27146
|
+
if (Array.isArray(matches) && matches.length > 1) throw new DocumentApiAdapterError("AMBIGUOUS_TARGET", `Multiple blocks share sdBlockId "${sdBlockId}" at the command layer.`, {
|
|
27147
|
+
sdBlockId,
|
|
27148
|
+
count: matches.length
|
|
27149
|
+
});
|
|
27150
|
+
}
|
|
27151
|
+
function blocksDeleteWrapper(editor, input, options) {
|
|
27152
|
+
rejectTrackedMode("blocks.delete", options);
|
|
27153
|
+
const candidate = findBlockByIdStrict(getBlockIndex(editor), input.target);
|
|
27154
|
+
validateTargetNodeType(candidate.nodeType);
|
|
27155
|
+
const sdBlockId = resolveSdBlockId(candidate);
|
|
27156
|
+
const deleteBlockNodeById = requireEditorCommand(editor.commands?.deleteBlockNodeById, "blocks.delete");
|
|
27157
|
+
validateCommandLayerUniqueness(editor, sdBlockId);
|
|
27158
|
+
if (options?.dryRun) return {
|
|
27159
|
+
success: true,
|
|
27160
|
+
deleted: input.target
|
|
27161
|
+
};
|
|
27162
|
+
if (executeDomainCommand(editor, () => {
|
|
27163
|
+
const didApply = deleteBlockNodeById(sdBlockId);
|
|
27164
|
+
if (didApply) clearIndexCache(editor);
|
|
27165
|
+
return didApply;
|
|
27166
|
+
}, { expectedRevision: options?.expectedRevision }).steps[0]?.effect !== "changed") throw new DocumentApiAdapterError("INTERNAL_ERROR", "blocks.delete command returned false despite passing all pre-apply checks. This is an internal invariant violation.", {
|
|
27167
|
+
sdBlockId,
|
|
27168
|
+
target: input.target
|
|
27169
|
+
});
|
|
27170
|
+
return {
|
|
27171
|
+
success: true,
|
|
27172
|
+
deleted: input.target
|
|
27173
|
+
};
|
|
27174
|
+
}
|
|
26860
27175
|
var DERIVED_ID_LENGTH = 24;
|
|
26861
27176
|
function getRawTrackedMarks(editor) {
|
|
26862
27177
|
try {
|
|
@@ -26980,9 +27295,7 @@ function resolveCreateInsertPosition(editor, at, operationLabel) {
|
|
|
26980
27295
|
const location$1 = at ?? { kind: "documentEnd" };
|
|
26981
27296
|
if (location$1.kind === "documentStart") return 0;
|
|
26982
27297
|
if (location$1.kind === "documentEnd") return editor.state.doc.content.size;
|
|
26983
|
-
|
|
26984
|
-
if (!target) throw new DocumentApiAdapterError("TARGET_NOT_FOUND", `Create ${operationLabel} target block was not found.`, { target: location$1.target });
|
|
26985
|
-
return location$1.kind === "before" ? target.pos : target.end;
|
|
27298
|
+
return resolveBlockInsertionPos(editor, location$1.target.nodeId, location$1.kind);
|
|
26986
27299
|
}
|
|
26987
27300
|
function resolveCreatedBlock(editor, nodeType, blockId) {
|
|
26988
27301
|
const index = getBlockIndex(editor);
|
|
@@ -27084,7 +27397,9 @@ function createParagraphWrapper(editor, input, options) {
|
|
|
27084
27397
|
try {
|
|
27085
27398
|
const paragraph = resolveCreatedBlock(editor, "paragraph", paragraphId);
|
|
27086
27399
|
if (mode === "tracked") trackedChangeRefs = collectTrackInsertRefsInRange(editor, paragraph.pos, paragraph.end);
|
|
27087
|
-
} catch {
|
|
27400
|
+
} catch (e) {
|
|
27401
|
+
if (!(e instanceof DocumentApiAdapterError)) throw e;
|
|
27402
|
+
}
|
|
27088
27403
|
}
|
|
27089
27404
|
return didApply;
|
|
27090
27405
|
}, { expectedRevision: options?.expectedRevision }).steps[0]?.effect !== "changed") return {
|
|
@@ -27146,7 +27461,9 @@ function createHeadingWrapper(editor, input, options) {
|
|
|
27146
27461
|
try {
|
|
27147
27462
|
const heading = resolveCreatedBlock(editor, "heading", headingId);
|
|
27148
27463
|
if (mode === "tracked") trackedChangeRefs = collectTrackInsertRefsInRange(editor, heading.pos, heading.end);
|
|
27149
|
-
} catch {
|
|
27464
|
+
} catch (e) {
|
|
27465
|
+
if (!(e instanceof DocumentApiAdapterError)) throw e;
|
|
27466
|
+
}
|
|
27150
27467
|
}
|
|
27151
27468
|
return didApply;
|
|
27152
27469
|
}, { expectedRevision: options?.expectedRevision }).steps[0]?.effect !== "changed") return {
|
|
@@ -28358,14 +28675,15 @@ function trackChangesRejectAllWrapper(editor, _input, options) {
|
|
|
28358
28675
|
return { success: true };
|
|
28359
28676
|
}
|
|
28360
28677
|
function previewPlan(editor, input) {
|
|
28361
|
-
const evaluatedRevision = getRevision(editor);
|
|
28362
28678
|
checkRevision(editor, input.expectedRevision);
|
|
28363
28679
|
if (!input.steps?.length) throw planError("INVALID_INPUT", "plan must contain at least one step");
|
|
28364
28680
|
const failures = [];
|
|
28365
28681
|
const stepPreviews = [];
|
|
28366
28682
|
let currentPhase = "compile";
|
|
28683
|
+
let evaluatedRevision = getRevision(editor);
|
|
28367
28684
|
try {
|
|
28368
28685
|
const compiled = compilePlan(editor, input.steps);
|
|
28686
|
+
evaluatedRevision = compiled.compiledRevision;
|
|
28369
28687
|
currentPhase = "execute";
|
|
28370
28688
|
const tr = editor.state.tr;
|
|
28371
28689
|
const { stepOutcomes, assertFailures } = runMutationsOnTransaction(editor, tr, compiled, { throwOnAssertFailure: false });
|
|
@@ -28868,14 +29186,24 @@ function queryMatchAdapter(editor, input) {
|
|
|
28868
29186
|
const userOffset = input.offset ?? 0;
|
|
28869
29187
|
const paginatedMatches = isTextSelector ? applyPagination(rawMatches, userOffset, input.limit) : rawMatches;
|
|
28870
29188
|
if (require$1 === "first" || require$1 === "exactlyOne" || require$1 === "all") {
|
|
28871
|
-
if (totalMatches === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges"
|
|
29189
|
+
if (totalMatches === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges", void 0, {
|
|
29190
|
+
selectorType: input.select?.type ?? "unknown",
|
|
29191
|
+
selectorPattern: input.select?.pattern ?? "",
|
|
29192
|
+
selectorMode: input.select?.mode ?? "contains",
|
|
29193
|
+
searchScope: (input.within?.kind === "block" ? input.within.nodeId : void 0) ?? "document",
|
|
29194
|
+
candidateCount: 0
|
|
29195
|
+
});
|
|
28872
29196
|
}
|
|
28873
29197
|
if (require$1 === "exactlyOne" && totalMatches > 1) throw planError("AMBIGUOUS_MATCH", `selector matched ${totalMatches} ranges, expected exactly one`, void 0, { matchCount: totalMatches });
|
|
28874
29198
|
const matchItems = paginatedMatches.map((raw, pageIdx) => {
|
|
28875
29199
|
const id = `m:${userOffset + pageIdx}`;
|
|
28876
29200
|
if (isTextSelector && raw.textRanges?.length) {
|
|
28877
29201
|
const blocks = buildMatchBlocks(editor, raw.textRanges, evaluatedRevision, id);
|
|
28878
|
-
if (blocks.length === 0) throw planError("INTERNAL_ERROR", `text match produced no blocks for ${id}
|
|
29202
|
+
if (blocks.length === 0) throw planError("INTERNAL_ERROR", `text match produced no blocks for ${id}`, void 0, {
|
|
29203
|
+
source: "query-match-adapter:buildMatchEntries",
|
|
29204
|
+
invariant: "text match must have at least one block after zero-width filtering",
|
|
29205
|
+
context: { matchId: id }
|
|
29206
|
+
});
|
|
28879
29207
|
const snippetResult = buildBlocksSnippet(editor, blocks);
|
|
28880
29208
|
return {
|
|
28881
29209
|
id,
|
|
@@ -29088,6 +29416,7 @@ function getDocumentApiAdapters(editor) {
|
|
|
29088
29416
|
acceptAll: (input, options) => trackChangesAcceptAllWrapper(editor, input, options),
|
|
29089
29417
|
rejectAll: (input, options) => trackChangesRejectAllWrapper(editor, input, options)
|
|
29090
29418
|
},
|
|
29419
|
+
blocks: { delete: (input, options) => blocksDeleteWrapper(editor, input, options) },
|
|
29091
29420
|
create: {
|
|
29092
29421
|
paragraph: (input, options) => createParagraphWrapper(editor, input, options),
|
|
29093
29422
|
heading: (input, options) => createHeadingWrapper(editor, input, options)
|
|
@@ -30479,7 +30808,7 @@ var Editor = class Editor extends EventEmitter$1 {
|
|
|
30479
30808
|
return migrations.length > 0;
|
|
30480
30809
|
}
|
|
30481
30810
|
processCollaborationMigrations() {
|
|
30482
|
-
console.debug("[checkVersionMigrations] Current editor version", "1.17.0-next.
|
|
30811
|
+
console.debug("[checkVersionMigrations] Current editor version", "1.17.0-next.13");
|
|
30483
30812
|
if (!this.options.ydoc) return;
|
|
30484
30813
|
let docVersion = this.options.ydoc.getMap("meta").get("version");
|
|
30485
30814
|
if (!docVersion) docVersion = "initial";
|