@magic-marker/prosemirror-suggest-changes 0.3.3-wrap-unwrap.30 → 0.3.3-wrap-unwrap.31
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/__tests__/playwrightPage.d.ts +0 -2
- package/dist/commands.js +8 -59
- package/dist/features/joinOnDelete/types.d.ts +0 -2
- package/dist/features/joinOnDelete/types.js +0 -3
- package/dist/features/transactionShaping/tipTapParagraphIntoListJoin/handleTipTapParagraphIntoListJoin.js +10 -8
- package/dist/replaceStep.js +6 -8
- package/package.json +12 -24
- package/dist/features/joinOnDelete/__tests__/listWithJoinsAndStructureMarks.playwright.test.d.ts +0 -1
- package/dist/features/startToStartTextblockDeletion/index.d.ts +0 -6
- package/dist/features/startToStartTextblockDeletion/index.js +0 -54
|
@@ -9,8 +9,6 @@ export declare class EditorPage {
|
|
|
9
9
|
getParagraphText(index: number, childIndexes?: number[]): Promise<string>;
|
|
10
10
|
getParagraphAt(index: number): Locator;
|
|
11
11
|
getParagraphCount(): Promise<number>;
|
|
12
|
-
getListItems(): Locator;
|
|
13
|
-
getParagraphs(): Locator;
|
|
14
12
|
getListItemCount(): Promise<number>;
|
|
15
13
|
getProseMirrorMarkCount(name: string): Promise<number>;
|
|
16
14
|
getProseMirrorMarksJSON(): Promise<unknown[]>;
|
package/dist/commands.js
CHANGED
|
@@ -5,7 +5,6 @@ import { suggestChangesKey } from "./plugin.js";
|
|
|
5
5
|
import { getSuggestionMarks } from "./utils.js";
|
|
6
6
|
import { ZWSP } from "./constants.js";
|
|
7
7
|
import { maybeRevertJoinMark } from "./features/joinOnDelete/index.js";
|
|
8
|
-
import { isJoinMark } from "./features/joinOnDelete/types.js";
|
|
9
8
|
import { revertAllStructureSuggestions, revertStructureSuggestion } from "./features/wrapUnwrap/revert/index.js";
|
|
10
9
|
import { applyAllStructureSuggestions, applyStructureSuggestion } from "./features/wrapUnwrap/apply/index.js";
|
|
11
10
|
/**
|
|
@@ -66,9 +65,7 @@ import { applyAllStructureSuggestions, applyStructureSuggestion } from "./featur
|
|
|
66
65
|
tr.removeMark(insertionFrom, insertionTo, markTypeToApply);
|
|
67
66
|
const joinRevertResult = maybeRevertJoinMark(tr, insertionFrom, insertionTo, child, markTypeToApply);
|
|
68
67
|
// reverting a join mark may produce new structure marks that were serialized in the join metadata
|
|
69
|
-
if (joinRevertResult)
|
|
70
|
-
joinRevertResult.restoredStructureSuggestionIds.forEach((id)=>restoredStructureSuggestionIds.add(id));
|
|
71
|
-
}
|
|
68
|
+
if (joinRevertResult) joinRevertResult.restoredStructureSuggestionIds.forEach((id)=>restoredStructureSuggestionIds.add(id));
|
|
72
69
|
if (!joinRevertResult && child.text === ZWSP) {
|
|
73
70
|
tr.delete(insertionFrom, insertionTo);
|
|
74
71
|
}
|
|
@@ -81,47 +78,6 @@ import { applyAllStructureSuggestions, applyStructureSuggestion } from "./featur
|
|
|
81
78
|
restoredStructureSuggestionIds
|
|
82
79
|
};
|
|
83
80
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Collect suggestion IDs of join marks in the node
|
|
86
|
-
*
|
|
87
|
-
* @param node
|
|
88
|
-
* @param deletion
|
|
89
|
-
* @returns an array of suggestion IDs
|
|
90
|
-
*/ function findJoinSuggestionIds(node, deletion) {
|
|
91
|
-
const joinSuggestionIds = [];
|
|
92
|
-
node.descendants((child)=>{
|
|
93
|
-
const mark = deletion.isInSet(child.marks);
|
|
94
|
-
if (!mark || !isJoinMark(mark)) return true;
|
|
95
|
-
if (!child.isText || child.text !== ZWSP) return true;
|
|
96
|
-
joinSuggestionIds.push(mark.attrs.id);
|
|
97
|
-
return true;
|
|
98
|
-
});
|
|
99
|
-
return joinSuggestionIds.reverse();
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Revert suggestions revealed by reverting a join mark
|
|
103
|
-
* Prioritize reverting revealed suggestions with the same id as the join mark
|
|
104
|
-
* (that means they are linked to the join mark and has to be reverted together as one)
|
|
105
|
-
* Revert other revealed suggestions as well so the user doesn't have to revert multiple times at the same place
|
|
106
|
-
*
|
|
107
|
-
* @param tr
|
|
108
|
-
* @param suggestionId
|
|
109
|
-
* @param restoredStructureSuggestionIds
|
|
110
|
-
*/ function revertRestoredStructureSuggestions(tr, suggestionId, restoredStructureSuggestionIds) {
|
|
111
|
-
if (restoredStructureSuggestionIds.has(suggestionId)) {
|
|
112
|
-
const restoredStructureTransform = revertStructureSuggestion(tr.doc, suggestionId);
|
|
113
|
-
restoredStructureTransform.steps.forEach((step)=>{
|
|
114
|
-
tr.step(step);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
restoredStructureSuggestionIds.forEach((restoredSuggestionId)=>{
|
|
118
|
-
if (restoredSuggestionId === suggestionId) return;
|
|
119
|
-
const restoredStructureTransform = revertStructureSuggestion(tr.doc, restoredSuggestionId);
|
|
120
|
-
restoredStructureTransform.steps.forEach((step)=>{
|
|
121
|
-
tr.step(step);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
81
|
function revertModifications(node, pos, tr) {
|
|
126
82
|
const { modification } = getSuggestionMarks(node.type.schema);
|
|
127
83
|
const existingMods = node.marks.filter((mark)=>mark.type === modification);
|
|
@@ -335,17 +291,7 @@ export function applySuggestionsToRange(doc, from, to) {
|
|
|
335
291
|
const { deletion, insertion } = getSuggestionMarks(state.schema);
|
|
336
292
|
// create a structure transform that reverts all structure changes on the given document
|
|
337
293
|
const structureTransform = revertAllStructureSuggestions(state.doc);
|
|
338
|
-
//
|
|
339
|
-
const joinSuggestionIds = findJoinSuggestionIds(structureTransform.doc, deletion);
|
|
340
|
-
joinSuggestionIds.forEach((suggestionId)=>{
|
|
341
|
-
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
342
|
-
const { restoredStructureSuggestionIds } = applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, deletion, insertion, suggestionId);
|
|
343
|
-
suggestionsTransform.steps.forEach((step)=>{
|
|
344
|
-
structureTransform.step(step);
|
|
345
|
-
});
|
|
346
|
-
revertRestoredStructureSuggestions(structureTransform, suggestionId, restoredStructureSuggestionIds);
|
|
347
|
-
});
|
|
348
|
-
// then start a clear transform from the document where the structure changes and join marks are reverted
|
|
294
|
+
// then start a clear transform from the document where the structure changes are reverted
|
|
349
295
|
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
350
296
|
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, deletion, insertion);
|
|
351
297
|
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, -1);
|
|
@@ -424,9 +370,12 @@ export function applySuggestionsToRange(doc, from, to) {
|
|
|
424
370
|
suggestionsTransform.steps.forEach((step)=>{
|
|
425
371
|
structureTransform.step(step);
|
|
426
372
|
});
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
373
|
+
restoredStructureSuggestionIds.forEach((suggestionId)=>{
|
|
374
|
+
const restoredStructureTransform = revertStructureSuggestion(structureTransform.doc, suggestionId);
|
|
375
|
+
restoredStructureTransform.steps.forEach((step)=>{
|
|
376
|
+
structureTransform.step(step);
|
|
377
|
+
});
|
|
378
|
+
});
|
|
430
379
|
// apply the structure transform to the transaction
|
|
431
380
|
const transaction = state.tr;
|
|
432
381
|
structureTransform.steps.forEach((step)=>{
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type Mark, type Attrs, type Node } from "prosemirror-model";
|
|
2
|
-
import { type SuggestionId } from "../../generateId.js";
|
|
3
2
|
export interface SerializedJoinNode {
|
|
4
3
|
type: string;
|
|
5
4
|
attrs: object;
|
|
@@ -8,7 +7,6 @@ export interface SerializedJoinNode {
|
|
|
8
7
|
}[];
|
|
9
8
|
}
|
|
10
9
|
export interface JoinMarkAttrs {
|
|
11
|
-
id: SuggestionId;
|
|
12
10
|
type: "join";
|
|
13
11
|
data: {
|
|
14
12
|
leftNode?: SerializedJoinNode;
|
|
@@ -5,9 +5,6 @@ export function isSerializedJoinNode(node) {
|
|
|
5
5
|
return typeof data.type === "string" && typeof data.attrs === "object" && data.attrs !== null && Array.isArray(data.marks);
|
|
6
6
|
}
|
|
7
7
|
export function isJoinMarkAttrs(attrs) {
|
|
8
|
-
if (typeof attrs["id"] !== "string" && typeof attrs["id"] !== "number") {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
8
|
if (attrs["type"] !== "join") return false;
|
|
12
9
|
if (attrs["data"] == null) return false;
|
|
13
10
|
return true;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { EditorState } from "prosemirror-state";
|
|
1
|
+
import { EditorState, Selection } from "prosemirror-state";
|
|
2
2
|
import { preserveTransactionData, transformToSuggestionTransaction } from "../../../transformToSuggestionTransaction.js";
|
|
3
|
-
import { generateNextNumberId } from "../../../generateId.js";
|
|
4
3
|
import { suggestStructureChanges } from "../../wrapUnwrap/structureChangesPlugin.js";
|
|
5
4
|
import { detectSpecialTransactionShape } from "../detectSpecialTransactionShape.js";
|
|
6
5
|
// handle the specific TipTap pattern when backspacing from a paragraph into a list above
|
|
@@ -15,8 +14,6 @@ export function handleTipTapParagraphIntoListJoin(args) {
|
|
|
15
14
|
const docBefore = args.transaction.docs[0];
|
|
16
15
|
if (!docBefore) return null;
|
|
17
16
|
const trackedTransaction = args.state.tr;
|
|
18
|
-
const sharedSuggestionId = args.generateId ? args.generateId(args.state.schema, docBefore) : generateNextNumberId(args.state.schema, docBefore);
|
|
19
|
-
const generateSharedSuggestionId = ()=>sharedSuggestionId;
|
|
20
17
|
try {
|
|
21
18
|
trackedTransaction.step(shape.deleteStep);
|
|
22
19
|
trackedTransaction.step(shape.insertStep);
|
|
@@ -29,7 +26,7 @@ export function handleTipTapParagraphIntoListJoin(args) {
|
|
|
29
26
|
uniqueNodeIdsTransform.steps.forEach((step)=>{
|
|
30
27
|
trackedTransaction.step(step);
|
|
31
28
|
});
|
|
32
|
-
const structureChangesResult = suggestStructureChanges(docBefore, uniqueNodeIdsTransform.doc, args.structuralContextPaths,
|
|
29
|
+
const structureChangesResult = suggestStructureChanges(docBefore, uniqueNodeIdsTransform.doc, args.structuralContextPaths, args.generateId);
|
|
33
30
|
if (!structureChangesResult.handled) {
|
|
34
31
|
return null;
|
|
35
32
|
}
|
|
@@ -46,17 +43,22 @@ export function handleTipTapParagraphIntoListJoin(args) {
|
|
|
46
43
|
} catch {
|
|
47
44
|
return null;
|
|
48
45
|
}
|
|
49
|
-
const trackedJoinTransaction = transformToSuggestionTransaction(joinTransaction, intermediateState,
|
|
46
|
+
const trackedJoinTransaction = transformToSuggestionTransaction(joinTransaction, intermediateState, args.generateId);
|
|
50
47
|
trackedJoinTransaction.steps.forEach((step)=>{
|
|
51
48
|
trackedTransaction.step(step);
|
|
52
49
|
});
|
|
53
50
|
preserveTransactionData(trackedTransaction, trackedJoinTransaction, {
|
|
54
|
-
selection:
|
|
51
|
+
selection: false,
|
|
55
52
|
preserveScroll: false,
|
|
56
53
|
preserveStoredMarks: false,
|
|
57
54
|
preserveMeta: false
|
|
58
55
|
});
|
|
59
|
-
preserveTransactionData(trackedTransaction, args.transaction
|
|
56
|
+
preserveTransactionData(trackedTransaction, args.transaction, {
|
|
57
|
+
selection: false
|
|
58
|
+
});
|
|
59
|
+
if (args.transaction.selectionSet) {
|
|
60
|
+
trackedTransaction.setSelection(Selection.fromJSON(trackedTransaction.doc, args.transaction.selection.toJSON()));
|
|
61
|
+
}
|
|
60
62
|
return trackedTransaction;
|
|
61
63
|
}
|
|
62
64
|
function isTipTapParagraphIntoListJoinShape(shape) {
|
package/dist/replaceStep.js
CHANGED
|
@@ -4,7 +4,6 @@ import { rebasePos } from "./rebasePos.js";
|
|
|
4
4
|
import { getSuggestionMarks } from "./utils.js";
|
|
5
5
|
import { joinBlocks } from "./features/joinBlocks/index.js";
|
|
6
6
|
import { collapseZWSPNodes, findJoinMark, joinNodesAndMarkJoinPoints, removeZWSPDeletions } from "./features/joinOnDelete/index.js";
|
|
7
|
-
import { adjustForStartToStartTextblockDeletion } from "./features/startToStartTextblockDeletion/index.js";
|
|
8
7
|
/**
|
|
9
8
|
* Transform a replace step into its equivalent tracked steps.
|
|
10
9
|
*
|
|
@@ -36,18 +35,17 @@ import { adjustForStartToStartTextblockDeletion } from "./features/startToStartT
|
|
|
36
35
|
* zero-width spaces will be removed.
|
|
37
36
|
*/ export function suggestReplaceStep(trackedTransaction, state, doc, step, prevSteps, suggestionId) {
|
|
38
37
|
const { deletion, insertion } = getSuggestionMarks(state.schema);
|
|
39
|
-
const semanticStep = adjustForStartToStartTextblockDeletion(state.selection, step, prevSteps);
|
|
40
38
|
// Check for insertion and deletion marks directly
|
|
41
39
|
// adjacent to this step's boundaries. If they exist,
|
|
42
40
|
// we'll use their ids, rather than producing a new one
|
|
43
|
-
const nodeBefore = doc.resolve(
|
|
41
|
+
const nodeBefore = doc.resolve(step.from).nodeBefore;
|
|
44
42
|
const markBefore = nodeBefore?.marks.find((mark)=>mark.type === deletion || mark.type === insertion) ?? null;
|
|
45
|
-
const nodeAfter = doc.resolve(
|
|
43
|
+
const nodeAfter = doc.resolve(step.to).nodeAfter;
|
|
46
44
|
const markAfter = nodeAfter?.marks.find((mark)=>mark.type === deletion || mark.type === insertion) ?? null;
|
|
47
45
|
let markId = markBefore?.attrs["id"] ?? markAfter?.attrs["id"] ?? suggestionId;
|
|
48
46
|
// Rebase this step's boundaries onto the newest doc
|
|
49
|
-
let stepFrom = rebasePos(
|
|
50
|
-
let stepTo = rebasePos(
|
|
47
|
+
let stepFrom = rebasePos(step.from, prevSteps, trackedTransaction.steps);
|
|
48
|
+
let stepTo = rebasePos(step.to, prevSteps, trackedTransaction.steps);
|
|
51
49
|
if (state.selection.empty && stepFrom !== stepTo) {
|
|
52
50
|
trackedTransaction.setSelection(TextSelection.near(trackedTransaction.doc.resolve(stepFrom)));
|
|
53
51
|
}
|
|
@@ -60,8 +58,8 @@ import { adjustForStartToStartTextblockDeletion } from "./features/startToStartT
|
|
|
60
58
|
}
|
|
61
59
|
// Update the step boundaries, since we may have just changed
|
|
62
60
|
// the document
|
|
63
|
-
stepFrom = rebasePos(
|
|
64
|
-
stepTo = rebasePos(
|
|
61
|
+
stepFrom = rebasePos(step.from, prevSteps, trackedTransaction.steps);
|
|
62
|
+
stepTo = rebasePos(step.to, prevSteps, trackedTransaction.steps);
|
|
65
63
|
// Re-resolve nodeAfter and markAfter if we did a block join
|
|
66
64
|
// The original values are stale after joinBlocks modifies the document
|
|
67
65
|
let nodeAfterResolved = nodeAfter;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magic-marker/prosemirror-suggest-changes",
|
|
3
|
-
"version": "0.3.3-wrap-unwrap.
|
|
3
|
+
"version": "0.3.3-wrap-unwrap.31",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -55,17 +55,17 @@
|
|
|
55
55
|
"markdown-toc": "^1.2.0",
|
|
56
56
|
"playwright": "^1.56.0",
|
|
57
57
|
"prettier": "^3.5.3",
|
|
58
|
-
"prosemirror-commands": "1.7.
|
|
59
|
-
"prosemirror-history": "1.5.0",
|
|
60
|
-
"prosemirror-inputrules": "1.
|
|
61
|
-
"prosemirror-keymap": "1.2.
|
|
62
|
-
"prosemirror-model": "1.
|
|
63
|
-
"prosemirror-schema-basic": "1.2.
|
|
64
|
-
"prosemirror-schema-list": "1.5.
|
|
65
|
-
"prosemirror-state": "1.4.
|
|
66
|
-
"prosemirror-test-builder": "1.1.1",
|
|
67
|
-
"prosemirror-transform": "1.
|
|
68
|
-
"prosemirror-view": "1.
|
|
58
|
+
"prosemirror-commands": "^1.7.0",
|
|
59
|
+
"prosemirror-history": "^1.5.0",
|
|
60
|
+
"prosemirror-inputrules": "^1.4.0",
|
|
61
|
+
"prosemirror-keymap": "^1.2.2",
|
|
62
|
+
"prosemirror-model": "^1.24.1",
|
|
63
|
+
"prosemirror-schema-basic": "^1.2.3",
|
|
64
|
+
"prosemirror-schema-list": "^1.5.0",
|
|
65
|
+
"prosemirror-state": "^1.4.3",
|
|
66
|
+
"prosemirror-test-builder": "^1.1.1",
|
|
67
|
+
"prosemirror-transform": "^1.10.2",
|
|
68
|
+
"prosemirror-view": "^1.38.0",
|
|
69
69
|
"remark-parse": "^11.0.0",
|
|
70
70
|
"rimraf": "^6.0.1",
|
|
71
71
|
"typescript": "^5.8.2",
|
|
@@ -79,17 +79,5 @@
|
|
|
79
79
|
"prosemirror-state": "^1.0.0",
|
|
80
80
|
"prosemirror-transform": "^1.0.0",
|
|
81
81
|
"prosemirror-view": "^1.0.0"
|
|
82
|
-
},
|
|
83
|
-
"resolutions": {
|
|
84
|
-
"prosemirror-model": "1.25.4",
|
|
85
|
-
"prosemirror-state": "1.4.4",
|
|
86
|
-
"prosemirror-transform": "1.12.0",
|
|
87
|
-
"prosemirror-view": "1.41.9",
|
|
88
|
-
"prosemirror-keymap": "1.2.3",
|
|
89
|
-
"prosemirror-commands": "1.7.1",
|
|
90
|
-
"prosemirror-schema-basic": "1.2.4",
|
|
91
|
-
"prosemirror-schema-list": "1.5.1",
|
|
92
|
-
"prosemirror-history": "1.5.0",
|
|
93
|
-
"prosemirror-inputrules": "1.5.1"
|
|
94
82
|
}
|
|
95
83
|
}
|
package/dist/features/joinOnDelete/__tests__/listWithJoinsAndStructureMarks.playwright.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type Selection } from "prosemirror-state";
|
|
2
|
-
import { type ReplaceStep, type Step } from "prosemirror-transform";
|
|
3
|
-
export declare function adjustForStartToStartTextblockDeletion(selection: Selection, step: ReplaceStep, prevSteps: Step[]): {
|
|
4
|
-
from: number;
|
|
5
|
-
to: number;
|
|
6
|
-
};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { TextSelection } from "prosemirror-state";
|
|
2
|
-
export function adjustForStartToStartTextblockDeletion(selection, step, prevSteps) {
|
|
3
|
-
if (prevSteps.length > 0) return {
|
|
4
|
-
from: step.from,
|
|
5
|
-
to: step.to
|
|
6
|
-
};
|
|
7
|
-
if (!(selection instanceof TextSelection)) {
|
|
8
|
-
return {
|
|
9
|
-
from: step.from,
|
|
10
|
-
to: step.to
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
if (selection.empty || step.slice.size !== 0) {
|
|
14
|
-
return {
|
|
15
|
-
from: step.from,
|
|
16
|
-
to: step.to
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
const { $from, $to } = selection;
|
|
20
|
-
if (!$from.parent.isTextblock || !$to.parent.isTextblock) {
|
|
21
|
-
return {
|
|
22
|
-
from: step.from,
|
|
23
|
-
to: step.to
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
if ($from.parentOffset !== 0 || $to.parentOffset !== 0) {
|
|
27
|
-
return {
|
|
28
|
-
from: step.from,
|
|
29
|
-
to: step.to
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
if ($from.start() === $to.start()) return {
|
|
33
|
-
from: step.from,
|
|
34
|
-
to: step.to
|
|
35
|
-
};
|
|
36
|
-
if (step.from !== $from.before($from.depth)) {
|
|
37
|
-
return {
|
|
38
|
-
from: step.from,
|
|
39
|
-
to: step.to
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
if (step.to !== $to.before($to.depth)) {
|
|
43
|
-
return {
|
|
44
|
-
from: step.from,
|
|
45
|
-
to: step.to
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
// The step boundary is moved before the right textblock, but the selection
|
|
49
|
-
// boundary is the user-visible end of the deleted text range.
|
|
50
|
-
return {
|
|
51
|
-
from: step.from,
|
|
52
|
-
to: selection.to
|
|
53
|
-
};
|
|
54
|
-
}
|