@harbour-enterprises/superdoc 1.17.0-next.12 → 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-B8jWQriR.es.js → SuperConverter-0JaBYpRa.es.js} +1 -1
- package/dist/chunks/{SuperConverter-BSNvGA-_.cjs → SuperConverter-BgHHB-Z2.cjs} +1 -1
- package/dist/chunks/{src-D6cAnOaK.cjs → src-ByCDwKn7.cjs} +306 -125
- package/dist/chunks/{src-BI6hYDgO.es.js → src-C52EYA_H.es.js} +306 -125
- 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/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 +313 -132
- 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",
|
|
@@ -21211,6 +21211,9 @@ var T_PLAN_ENGINE = [
|
|
|
21211
21211
|
"TARGET_MOVED",
|
|
21212
21212
|
"PLAN_CONFLICT_OVERLAP",
|
|
21213
21213
|
"INVALID_STEP_COMBINATION",
|
|
21214
|
+
"REVISION_CHANGED_SINCE_COMPILE",
|
|
21215
|
+
"INVALID_INSERTION_CONTEXT",
|
|
21216
|
+
"DOCUMENT_IDENTITY_CONFLICT",
|
|
21214
21217
|
"CAPABILITY_UNAVAILABLE"
|
|
21215
21218
|
];
|
|
21216
21219
|
var T_QUERY_MATCH = [
|
|
@@ -24308,9 +24311,11 @@ function trackRevisions(editor) {
|
|
|
24308
24311
|
function checkRevision(editor, expectedRevision) {
|
|
24309
24312
|
if (expectedRevision === void 0) return;
|
|
24310
24313
|
const current = getRevision(editor);
|
|
24311
|
-
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, {
|
|
24312
24315
|
expectedRevision,
|
|
24313
|
-
currentRevision: current
|
|
24316
|
+
currentRevision: current,
|
|
24317
|
+
refStability: "ephemeral",
|
|
24318
|
+
remediation: "Re-run query.match() to obtain a fresh ref valid for the current revision."
|
|
24314
24319
|
});
|
|
24315
24320
|
}
|
|
24316
24321
|
function resolveSegmentPosition(targetOffset, segmentStart, segmentLength, docFrom, docTo) {
|
|
@@ -24560,7 +24565,9 @@ function captureRunsInRange(editor, blockPos, from$1, to) {
|
|
|
24560
24565
|
return;
|
|
24561
24566
|
}
|
|
24562
24567
|
if (node.isLeaf) {
|
|
24568
|
+
const start$1 = offset$1;
|
|
24563
24569
|
offset$1 += 1;
|
|
24570
|
+
maybePushRun(start$1, offset$1, []);
|
|
24564
24571
|
return;
|
|
24565
24572
|
}
|
|
24566
24573
|
let isFirstChild = true;
|
|
@@ -24960,12 +24967,62 @@ function executeBlockSelector(index, query, diagnostics) {
|
|
|
24960
24967
|
function isAssertStep(step) {
|
|
24961
24968
|
return step.op === "assert";
|
|
24962
24969
|
}
|
|
24970
|
+
function isCreateOp(op) {
|
|
24971
|
+
return op === "create.heading" || op === "create.paragraph";
|
|
24972
|
+
}
|
|
24973
|
+
var VALID_CREATE_POSITIONS = ["before", "after"];
|
|
24963
24974
|
function isSelectWhere(where) {
|
|
24964
24975
|
return where.by === "select";
|
|
24965
24976
|
}
|
|
24966
24977
|
function isRefWhere(where) {
|
|
24967
24978
|
return where.by === "ref";
|
|
24968
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
|
+
}
|
|
24969
25026
|
function isV3Ref(payload) {
|
|
24970
25027
|
return typeof payload === "object" && payload !== null && "v" in payload && payload.v === 3;
|
|
24971
25028
|
}
|
|
@@ -25178,9 +25235,13 @@ function decodeTextRefPayload(encoded, stepId) {
|
|
|
25178
25235
|
}
|
|
25179
25236
|
function resolveV3TextRef(editor, index, step, refData) {
|
|
25180
25237
|
const currentRevision = getRevision(editor);
|
|
25181
|
-
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, {
|
|
25182
25239
|
refRevision: refData.rev,
|
|
25183
|
-
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.`
|
|
25184
25245
|
});
|
|
25185
25246
|
if (!refData.segments?.length) return [];
|
|
25186
25247
|
const segments = refData.segments.map((s) => ({
|
|
@@ -25279,7 +25340,11 @@ function resolveStepTargets(editor, index, step) {
|
|
|
25279
25340
|
return t.blockId !== prev.blockId || t.from !== prev.from || t.to !== prev.to;
|
|
25280
25341
|
});
|
|
25281
25342
|
if (refWhere) {
|
|
25282
|
-
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
|
+
});
|
|
25283
25348
|
if (targets.length > 1) throw planError("AMBIGUOUS_MATCH", `ref "${refWhere.ref}" resolved to ${targets.length} targets`, step.id, { matchCount: targets.length });
|
|
25284
25349
|
return targets;
|
|
25285
25350
|
}
|
|
@@ -25288,57 +25353,157 @@ function resolveStepTargets(editor, index, step) {
|
|
|
25288
25353
|
if (selectWhere.require === "first" && targets.length > 1) targets = [targets[0]];
|
|
25289
25354
|
return targets;
|
|
25290
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
|
+
}
|
|
25291
25368
|
function applyCardinalityCheck(step, targets) {
|
|
25292
25369
|
const where = step.where;
|
|
25293
25370
|
if (!("require" in where) || where.require === void 0) return;
|
|
25294
25371
|
const require$1 = where.require;
|
|
25295
25372
|
if (require$1 === "first") {
|
|
25296
|
-
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));
|
|
25297
25374
|
} else if (require$1 === "exactlyOne") {
|
|
25298
|
-
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));
|
|
25299
25376
|
if (targets.length > 1) throw planError("AMBIGUOUS_MATCH", `selector matched ${targets.length} ranges, expected exactly one`, step.id, { matchCount: targets.length });
|
|
25300
25377
|
} else if (require$1 === "all") {
|
|
25301
|
-
if (targets.length === 0) throw planError("MATCH_NOT_FOUND", "selector matched zero ranges", step.id);
|
|
25302
|
-
}
|
|
25303
|
-
}
|
|
25304
|
-
|
|
25305
|
-
|
|
25306
|
-
|
|
25307
|
-
|
|
25308
|
-
|
|
25309
|
-
|
|
25310
|
-
|
|
25311
|
-
|
|
25312
|
-
|
|
25313
|
-
|
|
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",
|
|
25314
25425
|
blockId,
|
|
25315
|
-
rangeA:
|
|
25316
|
-
|
|
25317
|
-
|
|
25318
|
-
|
|
25319
|
-
|
|
25320
|
-
|
|
25321
|
-
|
|
25322
|
-
|
|
25323
|
-
|
|
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
|
+
};
|
|
25324
25442
|
}
|
|
25325
25443
|
}
|
|
25326
25444
|
}
|
|
25327
|
-
function
|
|
25328
|
-
|
|
25329
|
-
if (
|
|
25330
|
-
|
|
25331
|
-
|
|
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);
|
|
25332
25456
|
}
|
|
25333
|
-
|
|
25334
|
-
stepId,
|
|
25457
|
+
entries.push({
|
|
25335
25458
|
from: from$1,
|
|
25336
25459
|
to
|
|
25337
25460
|
});
|
|
25338
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
|
+
}
|
|
25339
25502
|
function compilePlan(editor, steps) {
|
|
25340
25503
|
if (steps.length > 200) throw planError("INVALID_INPUT", `plan contains ${steps.length} steps, maximum is 200`);
|
|
25504
|
+
const compiledRevision = getRevision(editor);
|
|
25341
25505
|
const index = getBlockIndex(editor);
|
|
25506
|
+
assertNoDuplicateBlockIds(index);
|
|
25342
25507
|
const mutationSteps = [];
|
|
25343
25508
|
const assertSteps = [];
|
|
25344
25509
|
const seenIds = /* @__PURE__ */ new Set();
|
|
@@ -25348,26 +25513,41 @@ function compilePlan(editor, steps) {
|
|
|
25348
25513
|
seenIds.add(step.id);
|
|
25349
25514
|
}
|
|
25350
25515
|
let totalTargets = 0;
|
|
25516
|
+
let stepIndex = 0;
|
|
25351
25517
|
for (const step of steps) {
|
|
25352
25518
|
if (isAssertStep(step)) {
|
|
25353
25519
|
assertSteps.push(step);
|
|
25520
|
+
stepIndex++;
|
|
25354
25521
|
continue;
|
|
25355
25522
|
}
|
|
25356
25523
|
if (!hasStepExecutor(step.op)) throw planError("INVALID_INPUT", `unknown step op "${step.op}"`, step.id);
|
|
25524
|
+
if (isCreateOp(step.op)) validateCreateStepPosition(step);
|
|
25357
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
|
+
}
|
|
25358
25531
|
totalTargets += targets.length;
|
|
25359
25532
|
mutationSteps.push({
|
|
25360
25533
|
step,
|
|
25361
25534
|
targets
|
|
25362
25535
|
});
|
|
25536
|
+
stepIndex++;
|
|
25363
25537
|
}
|
|
25364
25538
|
if (totalTargets > 500) throw planError("INVALID_INPUT", `plan resolved ${totalTargets} total targets, maximum is 500`);
|
|
25365
|
-
|
|
25539
|
+
validateStepInteractions(mutationSteps);
|
|
25366
25540
|
return {
|
|
25367
25541
|
mutationSteps,
|
|
25368
|
-
assertSteps
|
|
25542
|
+
assertSteps,
|
|
25543
|
+
compiledRevision
|
|
25369
25544
|
};
|
|
25370
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
|
+
}
|
|
25371
25551
|
function applyDirectMutationMeta(tr) {
|
|
25372
25552
|
tr.setMeta("inputType", "programmatic");
|
|
25373
25553
|
tr.setMeta("skipTrackChanges", true);
|
|
@@ -25412,10 +25592,28 @@ function buildMarksFromSetMarks(editor, setMarks) {
|
|
|
25412
25592
|
if (setMarks.strike && schema.marks.strike) marks.push(schema.marks.strike.create());
|
|
25413
25593
|
return marks;
|
|
25414
25594
|
}
|
|
25415
|
-
function
|
|
25416
|
-
const
|
|
25417
|
-
|
|
25418
|
-
|
|
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;
|
|
25419
25617
|
}
|
|
25420
25618
|
function executeTextRewrite(editor, tr, target, step, mapping) {
|
|
25421
25619
|
const absFrom = mapping.map(target.absFrom);
|
|
@@ -25449,39 +25647,7 @@ function executeTextDelete(_editor, tr, target, _step, mapping) {
|
|
|
25449
25647
|
return { changed: true };
|
|
25450
25648
|
}
|
|
25451
25649
|
function executeStyleApply(editor, tr, target, step, mapping) {
|
|
25452
|
-
|
|
25453
|
-
const absTo = mapping.map(target.absTo);
|
|
25454
|
-
const { schema } = editor.state;
|
|
25455
|
-
let changed = false;
|
|
25456
|
-
const markEntries = [
|
|
25457
|
-
[
|
|
25458
|
-
"bold",
|
|
25459
|
-
step.args.inline.bold,
|
|
25460
|
-
schema.marks.bold
|
|
25461
|
-
],
|
|
25462
|
-
[
|
|
25463
|
-
"italic",
|
|
25464
|
-
step.args.inline.italic,
|
|
25465
|
-
schema.marks.italic
|
|
25466
|
-
],
|
|
25467
|
-
[
|
|
25468
|
-
"underline",
|
|
25469
|
-
step.args.inline.underline,
|
|
25470
|
-
schema.marks.underline
|
|
25471
|
-
],
|
|
25472
|
-
[
|
|
25473
|
-
"strike",
|
|
25474
|
-
step.args.inline.strike,
|
|
25475
|
-
schema.marks.strike
|
|
25476
|
-
]
|
|
25477
|
-
];
|
|
25478
|
-
for (const [, value, markType] of markEntries) {
|
|
25479
|
-
if (value === void 0 || !markType) continue;
|
|
25480
|
-
if (value) tr.addMark(absFrom, absTo, markType.create());
|
|
25481
|
-
else tr.removeMark(absFrom, absTo, markType);
|
|
25482
|
-
changed = true;
|
|
25483
|
-
}
|
|
25484
|
-
return { changed };
|
|
25650
|
+
return { changed: applyInlineMarkPatches(editor, tr, mapping.map(target.absFrom), mapping.map(target.absTo), step.args.inline) };
|
|
25485
25651
|
}
|
|
25486
25652
|
function validateMappedSpanContiguity(target, mapping, stepId) {
|
|
25487
25653
|
let lastMappedEnd = -1;
|
|
@@ -25542,41 +25708,9 @@ function executeSpanTextDelete(_editor, tr, target, step, mapping) {
|
|
|
25542
25708
|
}
|
|
25543
25709
|
function executeSpanStyleApply(editor, tr, target, step, mapping) {
|
|
25544
25710
|
validateMappedSpanContiguity(target, mapping, step.id);
|
|
25545
|
-
const { schema } = editor.state;
|
|
25546
|
-
let changed = false;
|
|
25547
25711
|
const firstSeg = target.segments[0];
|
|
25548
25712
|
const lastSeg = target.segments[target.segments.length - 1];
|
|
25549
|
-
|
|
25550
|
-
const absTo = mapping.map(lastSeg.absTo, -1);
|
|
25551
|
-
const markEntries = [
|
|
25552
|
-
[
|
|
25553
|
-
"bold",
|
|
25554
|
-
step.args.inline.bold,
|
|
25555
|
-
schema.marks.bold
|
|
25556
|
-
],
|
|
25557
|
-
[
|
|
25558
|
-
"italic",
|
|
25559
|
-
step.args.inline.italic,
|
|
25560
|
-
schema.marks.italic
|
|
25561
|
-
],
|
|
25562
|
-
[
|
|
25563
|
-
"underline",
|
|
25564
|
-
step.args.inline.underline,
|
|
25565
|
-
schema.marks.underline
|
|
25566
|
-
],
|
|
25567
|
-
[
|
|
25568
|
-
"strike",
|
|
25569
|
-
step.args.inline.strike,
|
|
25570
|
-
schema.marks.strike
|
|
25571
|
-
]
|
|
25572
|
-
];
|
|
25573
|
-
for (const [, value, markType] of markEntries) {
|
|
25574
|
-
if (value === void 0 || !markType) continue;
|
|
25575
|
-
if (value) tr.addMark(absFrom, absTo, markType.create());
|
|
25576
|
-
else tr.removeMark(absFrom, absTo, markType);
|
|
25577
|
-
changed = true;
|
|
25578
|
-
}
|
|
25579
|
-
return { changed };
|
|
25713
|
+
return { changed: applyInlineMarkPatches(editor, tr, mapping.map(firstSeg.absFrom, 1), mapping.map(lastSeg.absTo, -1), step.args.inline) };
|
|
25580
25714
|
}
|
|
25581
25715
|
function getReplacementText(replacement) {
|
|
25582
25716
|
if (replacement.blocks !== void 0) return replacement.blocks.map((b$1) => b$1.text).join("\n\n");
|
|
@@ -25747,9 +25881,11 @@ function executeAssertStep(_editor, tr, step) {
|
|
|
25747
25881
|
}
|
|
25748
25882
|
function executeCreateStep(editor, tr, step, targets, mapping) {
|
|
25749
25883
|
const target = targets[0];
|
|
25750
|
-
if (!target
|
|
25884
|
+
if (!target) throw planError("INVALID_INPUT", `${step.op} step requires at least one target`, step.id);
|
|
25751
25885
|
const args$1 = step.args;
|
|
25752
|
-
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);
|
|
25753
25889
|
const paragraphType = editor.state.schema?.nodes?.paragraph;
|
|
25754
25890
|
if (!paragraphType) throw planError("INVALID_INPUT", "paragraph node type not in schema", step.id);
|
|
25755
25891
|
const sdBlockId = args$1.sdBlockId;
|
|
@@ -25766,6 +25902,7 @@ function executeCreateStep(editor, tr, step, targets, mapping) {
|
|
|
25766
25902
|
const node = paragraphType.createAndFill(attrs, textNode ?? void 0) ?? paragraphType.create(attrs, textNode ? [textNode] : void 0);
|
|
25767
25903
|
if (!node) throw planError("INVALID_INPUT", `could not create ${step.op} node`, step.id);
|
|
25768
25904
|
tr.insert(pos, node);
|
|
25905
|
+
assertNoPostInsertDuplicateIds(tr.doc, step.id);
|
|
25769
25906
|
return {
|
|
25770
25907
|
stepId: step.id,
|
|
25771
25908
|
op: step.op,
|
|
@@ -25777,6 +25914,27 @@ function executeCreateStep(editor, tr, step, targets, mapping) {
|
|
|
25777
25914
|
}
|
|
25778
25915
|
};
|
|
25779
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
|
+
}
|
|
25780
25938
|
function runMutationsOnTransaction(editor, tr, compiled, options) {
|
|
25781
25939
|
const mapping = tr.mapping;
|
|
25782
25940
|
const stepOutcomes = [];
|
|
@@ -25832,6 +25990,13 @@ function executeCompiledPlan(editor, compiled, options = {}) {
|
|
|
25832
25990
|
const startTime = performance.now();
|
|
25833
25991
|
const revisionBefore = getRevision(editor);
|
|
25834
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
|
+
});
|
|
25835
26000
|
const tr = editor.state.tr;
|
|
25836
26001
|
if ((options.changeMode ?? "direct") === "tracked") applyTrackedMutationMeta(tr);
|
|
25837
26002
|
else applyDirectMutationMeta(tr);
|
|
@@ -26040,7 +26205,8 @@ function executeDomainCommand(editor, handler, options) {
|
|
|
26040
26205
|
},
|
|
26041
26206
|
targets: []
|
|
26042
26207
|
}],
|
|
26043
|
-
assertSteps: []
|
|
26208
|
+
assertSteps: [],
|
|
26209
|
+
compiledRevision: getRevision(editor)
|
|
26044
26210
|
}, { expectedRevision: options?.expectedRevision });
|
|
26045
26211
|
}
|
|
26046
26212
|
function validateWriteRequest(request, resolved) {
|
|
@@ -26127,7 +26293,8 @@ function writeWrapper(editor, request, options) {
|
|
|
26127
26293
|
step: stepDef,
|
|
26128
26294
|
targets: [toCompiledTarget(stepId, op, resolved)]
|
|
26129
26295
|
}],
|
|
26130
|
-
assertSteps: []
|
|
26296
|
+
assertSteps: [],
|
|
26297
|
+
compiledRevision: getRevision(editor)
|
|
26131
26298
|
}, {
|
|
26132
26299
|
changeMode: mode,
|
|
26133
26300
|
expectedRevision: options?.expectedRevision
|
|
@@ -26193,7 +26360,8 @@ function styleApplyWrapper(editor, input, options) {
|
|
|
26193
26360
|
marks: []
|
|
26194
26361
|
}]
|
|
26195
26362
|
}],
|
|
26196
|
-
assertSteps: []
|
|
26363
|
+
assertSteps: [],
|
|
26364
|
+
compiledRevision: getRevision(editor)
|
|
26197
26365
|
}, {
|
|
26198
26366
|
changeMode: mode,
|
|
26199
26367
|
expectedRevision: options?.expectedRevision
|
|
@@ -27127,9 +27295,7 @@ function resolveCreateInsertPosition(editor, at, operationLabel) {
|
|
|
27127
27295
|
const location$1 = at ?? { kind: "documentEnd" };
|
|
27128
27296
|
if (location$1.kind === "documentStart") return 0;
|
|
27129
27297
|
if (location$1.kind === "documentEnd") return editor.state.doc.content.size;
|
|
27130
|
-
|
|
27131
|
-
if (!target) throw new DocumentApiAdapterError("TARGET_NOT_FOUND", `Create ${operationLabel} target block was not found.`, { target: location$1.target });
|
|
27132
|
-
return location$1.kind === "before" ? target.pos : target.end;
|
|
27298
|
+
return resolveBlockInsertionPos(editor, location$1.target.nodeId, location$1.kind);
|
|
27133
27299
|
}
|
|
27134
27300
|
function resolveCreatedBlock(editor, nodeType, blockId) {
|
|
27135
27301
|
const index = getBlockIndex(editor);
|
|
@@ -27231,7 +27397,9 @@ function createParagraphWrapper(editor, input, options) {
|
|
|
27231
27397
|
try {
|
|
27232
27398
|
const paragraph = resolveCreatedBlock(editor, "paragraph", paragraphId);
|
|
27233
27399
|
if (mode === "tracked") trackedChangeRefs = collectTrackInsertRefsInRange(editor, paragraph.pos, paragraph.end);
|
|
27234
|
-
} catch {
|
|
27400
|
+
} catch (e) {
|
|
27401
|
+
if (!(e instanceof DocumentApiAdapterError)) throw e;
|
|
27402
|
+
}
|
|
27235
27403
|
}
|
|
27236
27404
|
return didApply;
|
|
27237
27405
|
}, { expectedRevision: options?.expectedRevision }).steps[0]?.effect !== "changed") return {
|
|
@@ -27293,7 +27461,9 @@ function createHeadingWrapper(editor, input, options) {
|
|
|
27293
27461
|
try {
|
|
27294
27462
|
const heading = resolveCreatedBlock(editor, "heading", headingId);
|
|
27295
27463
|
if (mode === "tracked") trackedChangeRefs = collectTrackInsertRefsInRange(editor, heading.pos, heading.end);
|
|
27296
|
-
} catch {
|
|
27464
|
+
} catch (e) {
|
|
27465
|
+
if (!(e instanceof DocumentApiAdapterError)) throw e;
|
|
27466
|
+
}
|
|
27297
27467
|
}
|
|
27298
27468
|
return didApply;
|
|
27299
27469
|
}, { expectedRevision: options?.expectedRevision }).steps[0]?.effect !== "changed") return {
|
|
@@ -28505,14 +28675,15 @@ function trackChangesRejectAllWrapper(editor, _input, options) {
|
|
|
28505
28675
|
return { success: true };
|
|
28506
28676
|
}
|
|
28507
28677
|
function previewPlan(editor, input) {
|
|
28508
|
-
const evaluatedRevision = getRevision(editor);
|
|
28509
28678
|
checkRevision(editor, input.expectedRevision);
|
|
28510
28679
|
if (!input.steps?.length) throw planError("INVALID_INPUT", "plan must contain at least one step");
|
|
28511
28680
|
const failures = [];
|
|
28512
28681
|
const stepPreviews = [];
|
|
28513
28682
|
let currentPhase = "compile";
|
|
28683
|
+
let evaluatedRevision = getRevision(editor);
|
|
28514
28684
|
try {
|
|
28515
28685
|
const compiled = compilePlan(editor, input.steps);
|
|
28686
|
+
evaluatedRevision = compiled.compiledRevision;
|
|
28516
28687
|
currentPhase = "execute";
|
|
28517
28688
|
const tr = editor.state.tr;
|
|
28518
28689
|
const { stepOutcomes, assertFailures } = runMutationsOnTransaction(editor, tr, compiled, { throwOnAssertFailure: false });
|
|
@@ -29015,14 +29186,24 @@ function queryMatchAdapter(editor, input) {
|
|
|
29015
29186
|
const userOffset = input.offset ?? 0;
|
|
29016
29187
|
const paginatedMatches = isTextSelector ? applyPagination(rawMatches, userOffset, input.limit) : rawMatches;
|
|
29017
29188
|
if (require$1 === "first" || require$1 === "exactlyOne" || require$1 === "all") {
|
|
29018
|
-
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
|
+
});
|
|
29019
29196
|
}
|
|
29020
29197
|
if (require$1 === "exactlyOne" && totalMatches > 1) throw planError("AMBIGUOUS_MATCH", `selector matched ${totalMatches} ranges, expected exactly one`, void 0, { matchCount: totalMatches });
|
|
29021
29198
|
const matchItems = paginatedMatches.map((raw, pageIdx) => {
|
|
29022
29199
|
const id = `m:${userOffset + pageIdx}`;
|
|
29023
29200
|
if (isTextSelector && raw.textRanges?.length) {
|
|
29024
29201
|
const blocks = buildMatchBlocks(editor, raw.textRanges, evaluatedRevision, id);
|
|
29025
|
-
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
|
+
});
|
|
29026
29207
|
const snippetResult = buildBlocksSnippet(editor, blocks);
|
|
29027
29208
|
return {
|
|
29028
29209
|
id,
|
|
@@ -30627,7 +30808,7 @@ var Editor = class Editor extends EventEmitter$1 {
|
|
|
30627
30808
|
return migrations.length > 0;
|
|
30628
30809
|
}
|
|
30629
30810
|
processCollaborationMigrations() {
|
|
30630
|
-
console.debug("[checkVersionMigrations] Current editor version", "1.17.0-next.
|
|
30811
|
+
console.debug("[checkVersionMigrations] Current editor version", "1.17.0-next.13");
|
|
30631
30812
|
if (!this.options.ydoc) return;
|
|
30632
30813
|
let docVersion = this.options.ydoc.getMap("meta").get("version");
|
|
30633
30814
|
if (!docVersion) docVersion = "initial";
|