@magic-marker/prosemirror-suggest-changes 0.3.3-wrap-unwrap.0 → 0.3.3-wrap-unwrap.2
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 +8 -1
- package/dist/commands.d.ts +1 -3
- package/dist/commands.js +133 -54
- package/dist/ensureSelectionPlugin.js +2 -2
- package/dist/features/wrapUnwrap/addIdAttr.d.ts +2 -0
- package/dist/features/wrapUnwrap/addIdAttr.js +62 -0
- package/dist/features/wrapUnwrap/buildMaterializedPaths.d.ts +3 -0
- package/dist/features/wrapUnwrap/buildMaterializedPaths.js +71 -0
- package/dist/features/wrapUnwrap/constants.d.ts +3 -0
- package/dist/features/wrapUnwrap/constants.js +7 -0
- package/dist/features/wrapUnwrap/generateUniqueNodeId.d.ts +1 -0
- package/dist/features/wrapUnwrap/generateUniqueNodeId.js +6 -0
- package/dist/features/wrapUnwrap/getNodeId.d.ts +2 -0
- package/dist/features/wrapUnwrap/getNodeId.js +5 -0
- package/dist/features/wrapUnwrap/revertStructureSuggestions.d.ts +9 -0
- package/dist/features/wrapUnwrap/revertStructureSuggestions.js +433 -0
- package/dist/features/wrapUnwrap/sameParentChain.d.ts +2 -0
- package/dist/features/wrapUnwrap/sameParentChain.js +4 -0
- package/dist/features/wrapUnwrap/structureChangesPlugin.d.ts +7 -0
- package/dist/features/wrapUnwrap/structureChangesPlugin.js +174 -0
- package/dist/features/wrapUnwrap/types.d.ts +44 -0
- package/dist/features/wrapUnwrap/types.js +13 -0
- package/dist/features/wrapUnwrap/uniqueNodeIdsPlugin.d.ts +17 -0
- package/dist/features/wrapUnwrap/uniqueNodeIdsPlugin.js +98 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/replaceAroundStep.js +1 -6
- package/dist/replaceStep.d.ts +1 -1
- package/dist/replaceStep.js +0 -5
- package/dist/testing/e2eTestSchema.d.ts +2 -0
- package/dist/testing/testBuilders.d.ts +1 -1
- package/dist/withSuggestChanges.d.ts +5 -1
- package/dist/withSuggestChanges.js +44 -2
- package/package.json +2 -2
- package/src/features/wrapUnwrap/README.md +96 -167
- package/dist/contentBetween.d.ts +0 -2
- package/dist/contentBetween.js +0 -33
- package/dist/features/wrapUnwrap/__tests__/blockquoteUnwrapAllNodes.data.d.ts +0 -38
- package/dist/features/wrapUnwrap/__tests__/blockquoteUnwrapAllNodes.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/blockquoteUnwrapOneNode.data.d.ts +0 -45
- package/dist/features/wrapUnwrap/__tests__/blockquoteUnwrapOneNode.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/blockquoteUnwrapOneNode.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/blockquoteUnwrapSingleNode.data.d.ts +0 -38
- package/dist/features/wrapUnwrap/__tests__/blockquoteUnwrapSingleNode.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/blockquoteUnwrapSingleNode.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/blockquoteWrapAllNodes.data.d.ts +0 -38
- package/dist/features/wrapUnwrap/__tests__/blockquoteWrapAllNodes.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/blockquoteWrapAllNodes.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/blockquoteWrapSingleNode.data.d.ts +0 -38
- package/dist/features/wrapUnwrap/__tests__/blockquoteWrapSingleNode.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/blockquoteWrapSingleNode.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftLast.data.d.ts +0 -54
- package/dist/features/wrapUnwrap/__tests__/listItemLiftLast.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftLast.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftMiddle.data.d.ts +0 -48
- package/dist/features/wrapUnwrap/__tests__/listItemLiftMiddle.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftMiddle.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftMultipleToTheTop.data.d.ts +0 -74
- package/dist/features/wrapUnwrap/__tests__/listItemLiftMultipleToTheTop.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftMultipleToTheTop.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftNestedOnce.data.d.ts +0 -71
- package/dist/features/wrapUnwrap/__tests__/listItemLiftNestedOnce.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftNestedOnce.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftTop.data.d.ts +0 -54
- package/dist/features/wrapUnwrap/__tests__/listItemLiftTop.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemLiftTop.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemSinkMultiple.data.d.ts +0 -181
- package/dist/features/wrapUnwrap/__tests__/listItemSinkMultiple.page.d.ts +0 -30
- package/dist/features/wrapUnwrap/__tests__/listItemSinkMultiple.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemSinkMultiple.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemSinkOneOnce.data.d.ts +0 -51
- package/dist/features/wrapUnwrap/__tests__/listItemSinkOneOnce.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemSinkOneOnce.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemsLiftMixedLevels.data.d.ts +0 -74
- package/dist/features/wrapUnwrap/__tests__/listItemsLiftMixedLevels.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/listItemsLiftMixedLevels.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/nestedListItemLiftToOuter.data.d.ts +0 -71
- package/dist/features/wrapUnwrap/__tests__/nestedListItemLiftToOuter.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/nestedListItemLiftToOuter.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/nestedListItemsLiftMultipleLevels.data.d.ts +0 -114
- package/dist/features/wrapUnwrap/__tests__/nestedListItemsLiftMultipleLevels.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/nestedListItemsLiftMultipleLevels.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/testUtils.d.ts +0 -5
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftMultipleNodesToTheTop.data.d.ts +0 -44
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftMultipleNodesToTheTop.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftMultipleNodesToTheTop.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftMultipleNodesUp.data.d.ts +0 -38
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftMultipleNodesUp.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftMultipleNodesUp.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeFromMiddle.data.d.ts +0 -46
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeFromMiddle.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeFromMiddle.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeToTheTop.data.d.ts +0 -57
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeToTheTop.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeToTheTop.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeUp.data.d.ts +0 -45
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeUp.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteLiftOneNodeUp.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteWrap.data.d.ts +0 -44
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteWrap.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteWrap.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteWrapMultiple.data.d.ts +0 -44
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteWrapMultiple.playwright.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/__tests__/tripleBlockquoteWrapMultiple.test.d.ts +0 -1
- package/dist/features/wrapUnwrap/addStructureMark.d.ts +0 -41
- package/dist/features/wrapUnwrap/addStructureMark.js +0 -15
- package/dist/features/wrapUnwrap/findMatchingNodeSides.d.ts +0 -15
- package/dist/features/wrapUnwrap/findMatchingNodeSides.js +0 -133
- package/dist/features/wrapUnwrap/handleStructureStep.d.ts +0 -4
- package/dist/features/wrapUnwrap/handleStructureStep.js +0 -174
- package/dist/features/wrapUnwrap/revertStructureSuggestion.d.ts +0 -44
- package/dist/features/wrapUnwrap/revertStructureSuggestion.js +0 -374
- /package/dist/features/wrapUnwrap/__tests__/{blockquoteUnwrapAllNodes.playwright.test.d.ts → listStructure.playwright.test.d.ts} +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type Locator, type Page } from "@playwright/test";
|
|
2
2
|
export declare class EditorPage {
|
|
3
3
|
readonly page: Page;
|
|
4
|
+
readonly deletionMarksVisibility: "hidden" | "visible";
|
|
4
5
|
private readonly selectors;
|
|
5
|
-
constructor(page: Page);
|
|
6
|
+
constructor(page: Page, deletionMarksVisibility?: "hidden" | "visible");
|
|
6
7
|
get editor(): Locator;
|
|
7
8
|
getParagraphText(index: number): Promise<string>;
|
|
8
9
|
getParagraphCount(): Promise<number>;
|
|
@@ -12,4 +13,10 @@ export declare class EditorPage {
|
|
|
12
13
|
head: number;
|
|
13
14
|
}>;
|
|
14
15
|
getDOMTextContentOfChildAtIndex(index: number): Promise<string>;
|
|
16
|
+
getDocJSON(): Promise<object>;
|
|
17
|
+
getCurrentAndExpectedDoc(expectedDocJSON: object): Promise<{
|
|
18
|
+
currentDoc: import("prosemirror-model").Node;
|
|
19
|
+
expectedDoc: import("prosemirror-model").Node;
|
|
20
|
+
}>;
|
|
21
|
+
revertAll(): Promise<void>;
|
|
15
22
|
}
|
package/dist/commands.d.ts
CHANGED
|
@@ -51,9 +51,7 @@ export declare function revertSuggestionsInRange(from?: number, to?: number): Co
|
|
|
51
51
|
* The deletion mark will be removed, and their contents left in the doc.
|
|
52
52
|
* Modifications tracked in modification marks will be reverted.
|
|
53
53
|
*/
|
|
54
|
-
export declare function revertSuggestion(suggestionId: SuggestionId, from?: number, to?: number
|
|
55
|
-
structure: boolean;
|
|
56
|
-
}): Command;
|
|
54
|
+
export declare function revertSuggestion(suggestionId: SuggestionId, from?: number, to?: number): Command;
|
|
57
55
|
/**
|
|
58
56
|
* Command that updates the selection to cover an existing change.
|
|
59
57
|
*/
|
package/dist/commands.js
CHANGED
|
@@ -5,7 +5,7 @@ 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 {
|
|
8
|
+
import { applyAllStructureSuggestions, applyAllStructureSuggestionsOnNode, applyOneStructureSuggestion, revertAllStructureSuggestions, revertAllStructureSuggestionsOnNode, revertOneStructureSuggestion } from "./features/wrapUnwrap/revertStructureSuggestions.js";
|
|
9
9
|
/**
|
|
10
10
|
* Given a node and a transform, add a set of steps to the
|
|
11
11
|
* transform that applies all marks of type markTypeToApply
|
|
@@ -135,20 +135,34 @@ function applyModificationsToTransform(node, tr, dir, suggestionId, from, to) {
|
|
|
135
135
|
}
|
|
136
136
|
export function applySuggestionsToNode(node) {
|
|
137
137
|
const { deletion, insertion } = getSuggestionMarks(node.type.schema);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
// first, create a structure transform that applies all structure changes on the given node
|
|
139
|
+
const structureTransform = applyAllStructureSuggestionsOnNode(node);
|
|
140
|
+
// then start a clear transform from the document where the structure changes are applied
|
|
141
|
+
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
142
|
+
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, insertion, deletion);
|
|
143
|
+
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, 1);
|
|
144
|
+
// replay suggestion transform on top of the structure transform
|
|
145
|
+
suggestionsTransform.steps.forEach((step)=>{
|
|
146
|
+
structureTransform.step(step);
|
|
147
|
+
});
|
|
148
|
+
return structureTransform.doc;
|
|
142
149
|
}
|
|
143
150
|
export function applySuggestionsToRange(doc, from, to) {
|
|
151
|
+
const { deletion, insertion } = getSuggestionMarks(doc.type.schema);
|
|
144
152
|
// blockRange can only return null if a predicate is provided
|
|
145
153
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
146
154
|
const nodeRange = doc.resolve(from).blockRange(doc.resolve(to));
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
155
|
+
// create a structure transform that applies all structure changes on the given node range
|
|
156
|
+
const structureTransform = applyAllStructureSuggestionsOnNode(doc, nodeRange.start, nodeRange.end);
|
|
157
|
+
// then start a clear transform from the document where the structure changes are applied
|
|
158
|
+
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
159
|
+
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, insertion, deletion, undefined, nodeRange.start, nodeRange.end);
|
|
160
|
+
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, 1, undefined, nodeRange.start, nodeRange.end);
|
|
161
|
+
// replay suggestion transform on top of the structure transform
|
|
162
|
+
suggestionsTransform.steps.forEach((step)=>{
|
|
163
|
+
structureTransform.step(step);
|
|
164
|
+
});
|
|
165
|
+
return structureTransform.doc.slice(structureTransform.mapping.map(from), structureTransform.mapping.map(to));
|
|
152
166
|
}
|
|
153
167
|
/**
|
|
154
168
|
* Command that applies all tracked changes in a document.
|
|
@@ -158,13 +172,26 @@ export function applySuggestionsToRange(doc, from, to) {
|
|
|
158
172
|
* contents left in the doc.
|
|
159
173
|
*/ export function applySuggestions(state, dispatch) {
|
|
160
174
|
const { deletion, insertion } = getSuggestionMarks(state.schema);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
175
|
+
// create a structure transform that applies all structure changes on the given document
|
|
176
|
+
const structureTransform = applyAllStructureSuggestions(state.doc);
|
|
177
|
+
// then start a clear transform from the document where the structure changes are applied
|
|
178
|
+
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
179
|
+
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, insertion, deletion);
|
|
180
|
+
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, 1);
|
|
181
|
+
// replay suggestion transform on top of the structure transform
|
|
182
|
+
suggestionsTransform.steps.forEach((step)=>{
|
|
183
|
+
structureTransform.step(step);
|
|
184
|
+
});
|
|
185
|
+
// apply the structure transform to the transaction
|
|
186
|
+
const transaction = state.tr;
|
|
187
|
+
structureTransform.steps.forEach((step)=>{
|
|
188
|
+
transaction.step(step);
|
|
189
|
+
});
|
|
190
|
+
if (!transaction.steps.length) return false;
|
|
191
|
+
transaction.setMeta(suggestChangesKey, {
|
|
165
192
|
skip: true
|
|
166
193
|
});
|
|
167
|
-
dispatch?.(
|
|
194
|
+
dispatch?.(transaction);
|
|
168
195
|
return true;
|
|
169
196
|
}
|
|
170
197
|
/**
|
|
@@ -176,13 +203,26 @@ export function applySuggestionsToRange(doc, from, to) {
|
|
|
176
203
|
*/ export function applySuggestionsInRange(from, to) {
|
|
177
204
|
return (state, dispatch)=>{
|
|
178
205
|
const { deletion, insertion } = getSuggestionMarks(state.schema);
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
206
|
+
// create a structure transform that applies all structure changes on the given node range
|
|
207
|
+
const structureTransform = applyAllStructureSuggestionsOnNode(state.doc, from, to);
|
|
208
|
+
// then start a clear transform from the document where the structure changes are applied
|
|
209
|
+
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
210
|
+
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, insertion, deletion, undefined, from, to);
|
|
211
|
+
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, 1, undefined, from, to);
|
|
212
|
+
// replay suggestion transform on top of the structure transform
|
|
213
|
+
suggestionsTransform.steps.forEach((step)=>{
|
|
214
|
+
structureTransform.step(step);
|
|
215
|
+
});
|
|
216
|
+
// apply the structure transform to the transaction
|
|
217
|
+
const transaction = state.tr;
|
|
218
|
+
structureTransform.steps.forEach((step)=>{
|
|
219
|
+
transaction.step(step);
|
|
220
|
+
});
|
|
221
|
+
if (!transaction.steps.length) return false;
|
|
222
|
+
transaction.setMeta(suggestChangesKey, {
|
|
183
223
|
skip: true
|
|
184
224
|
});
|
|
185
|
-
dispatch?.(
|
|
225
|
+
dispatch?.(transaction);
|
|
186
226
|
return true;
|
|
187
227
|
};
|
|
188
228
|
}
|
|
@@ -194,18 +234,27 @@ export function applySuggestionsToRange(doc, from, to) {
|
|
|
194
234
|
* contents left in the doc.
|
|
195
235
|
*/ export function applySuggestion(suggestionId, from, to) {
|
|
196
236
|
return (state, dispatch)=>{
|
|
197
|
-
if (isStructureSuggestion(suggestionId, state.tr)) {
|
|
198
|
-
return applyStructureSuggestion(suggestionId)(state, dispatch);
|
|
199
|
-
}
|
|
200
237
|
const { deletion, insertion } = getSuggestionMarks(state.schema);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
238
|
+
// create a structure transform that applies the given structure change on the given node
|
|
239
|
+
const structureTransform = applyOneStructureSuggestion(state.doc, suggestionId);
|
|
240
|
+
// then start a clear transform from the document where the structure changes are applied
|
|
241
|
+
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
242
|
+
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, insertion, deletion, suggestionId, from, to);
|
|
243
|
+
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, 1, undefined, from, to);
|
|
244
|
+
// replay suggestion transform on top of the structure transform
|
|
245
|
+
suggestionsTransform.steps.forEach((step)=>{
|
|
246
|
+
structureTransform.step(step);
|
|
247
|
+
});
|
|
248
|
+
// apply the structure transform to the transaction
|
|
249
|
+
const transaction = state.tr;
|
|
250
|
+
structureTransform.steps.forEach((step)=>{
|
|
251
|
+
transaction.step(step);
|
|
252
|
+
});
|
|
253
|
+
if (!transaction.steps.length) return false;
|
|
254
|
+
transaction.setMeta(suggestChangesKey, {
|
|
206
255
|
skip: true
|
|
207
256
|
});
|
|
208
|
-
dispatch?.(
|
|
257
|
+
dispatch?.(transaction);
|
|
209
258
|
return true;
|
|
210
259
|
};
|
|
211
260
|
}
|
|
@@ -217,15 +266,26 @@ export function applySuggestionsToRange(doc, from, to) {
|
|
|
217
266
|
* Modifications tracked in modification marks will be reverted.
|
|
218
267
|
*/ export function revertSuggestions(state, dispatch) {
|
|
219
268
|
const { deletion, insertion } = getSuggestionMarks(state.schema);
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
269
|
+
// create a structure transform that reverts all structure changes on the given document
|
|
270
|
+
const structureTransform = revertAllStructureSuggestions(state.doc);
|
|
271
|
+
// then start a clear transform from the document where the structure changes are reverted
|
|
272
|
+
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
273
|
+
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, deletion, insertion);
|
|
274
|
+
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, -1);
|
|
275
|
+
// replay suggestion transform on top of the structure transform
|
|
276
|
+
suggestionsTransform.steps.forEach((step)=>{
|
|
277
|
+
structureTransform.step(step);
|
|
278
|
+
});
|
|
279
|
+
// apply the structure transform to the transaction
|
|
280
|
+
const transaction = state.tr;
|
|
281
|
+
structureTransform.steps.forEach((step)=>{
|
|
282
|
+
transaction.step(step);
|
|
283
|
+
});
|
|
284
|
+
if (!transaction.steps.length) return false;
|
|
285
|
+
transaction.setMeta(suggestChangesKey, {
|
|
226
286
|
skip: true
|
|
227
287
|
});
|
|
228
|
-
dispatch?.(
|
|
288
|
+
dispatch?.(transaction);
|
|
229
289
|
return true;
|
|
230
290
|
}
|
|
231
291
|
/**
|
|
@@ -237,13 +297,26 @@ export function applySuggestionsToRange(doc, from, to) {
|
|
|
237
297
|
*/ export function revertSuggestionsInRange(from, to) {
|
|
238
298
|
return (state, dispatch)=>{
|
|
239
299
|
const { deletion, insertion } = getSuggestionMarks(state.schema);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
300
|
+
// create a structure transform that reverts all structure changes on the given node range
|
|
301
|
+
const structureTransform = revertAllStructureSuggestionsOnNode(state.doc, from, to);
|
|
302
|
+
// then start a clear transform from the document where the structure changes are reverted
|
|
303
|
+
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
304
|
+
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, deletion, insertion, undefined, from, to);
|
|
305
|
+
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, -1, undefined, from, to);
|
|
306
|
+
// replay suggestion transform on top of the structure transform
|
|
307
|
+
suggestionsTransform.steps.forEach((step)=>{
|
|
308
|
+
structureTransform.step(step);
|
|
309
|
+
});
|
|
310
|
+
// apply the structure transform to the transaction
|
|
311
|
+
const transaction = state.tr;
|
|
312
|
+
structureTransform.steps.forEach((step)=>{
|
|
313
|
+
transaction.step(step);
|
|
314
|
+
});
|
|
315
|
+
if (!transaction.steps.length) return false;
|
|
316
|
+
transaction.setMeta(suggestChangesKey, {
|
|
244
317
|
skip: true
|
|
245
318
|
});
|
|
246
|
-
dispatch?.(
|
|
319
|
+
dispatch?.(transaction);
|
|
247
320
|
return true;
|
|
248
321
|
};
|
|
249
322
|
}
|
|
@@ -253,23 +326,29 @@ export function applySuggestionsToRange(doc, from, to) {
|
|
|
253
326
|
* This means that all content within the insertion mark will be deleted.
|
|
254
327
|
* The deletion mark will be removed, and their contents left in the doc.
|
|
255
328
|
* Modifications tracked in modification marks will be reverted.
|
|
256
|
-
*/ export function revertSuggestion(suggestionId, from, to
|
|
329
|
+
*/ export function revertSuggestion(suggestionId, from, to) {
|
|
257
330
|
return (state, dispatch)=>{
|
|
258
|
-
if (opts?.structure === true) {
|
|
259
|
-
return revertStructureSuggestion(suggestionId)(state, dispatch);
|
|
260
|
-
}
|
|
261
|
-
if (opts?.structure !== false && isStructureSuggestion(suggestionId, state.tr)) {
|
|
262
|
-
return revertStructureSuggestion(suggestionId)(state, dispatch);
|
|
263
|
-
}
|
|
264
331
|
const { deletion, insertion } = getSuggestionMarks(state.schema);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
332
|
+
// create a structure transform that reverts the given structure change on the given node
|
|
333
|
+
const structureTransform = revertOneStructureSuggestion(state.doc, suggestionId);
|
|
334
|
+
// then start a clear transform from the document where the structure changes are reverted
|
|
335
|
+
const suggestionsTransform = new Transform(structureTransform.doc);
|
|
336
|
+
applySuggestionsToTransform(suggestionsTransform.doc, suggestionsTransform, deletion, insertion, suggestionId, from, to);
|
|
337
|
+
applyModificationsToTransform(suggestionsTransform.doc, suggestionsTransform, -1, undefined, from, to);
|
|
338
|
+
// replay suggestion transform on top of the structure transform
|
|
339
|
+
suggestionsTransform.steps.forEach((step)=>{
|
|
340
|
+
structureTransform.step(step);
|
|
341
|
+
});
|
|
342
|
+
// apply the structure transform to the transaction
|
|
343
|
+
const transaction = state.tr;
|
|
344
|
+
structureTransform.steps.forEach((step)=>{
|
|
345
|
+
transaction.step(step);
|
|
346
|
+
});
|
|
347
|
+
if (!transaction.steps.length) return false;
|
|
348
|
+
transaction.setMeta(suggestChangesKey, {
|
|
269
349
|
skip: true
|
|
270
350
|
});
|
|
271
|
-
|
|
272
|
-
dispatch?.(tr);
|
|
351
|
+
dispatch?.(transaction);
|
|
273
352
|
return true;
|
|
274
353
|
};
|
|
275
354
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Plugin, PluginKey, TextSelection } from "prosemirror-state";
|
|
2
2
|
import { getSuggestionMarks } from "./utils.js";
|
|
3
3
|
import { ZWSP } from "./constants.js";
|
|
4
|
-
const TRACE_ENABLED =
|
|
4
|
+
const TRACE_ENABLED = true;
|
|
5
5
|
function trace(...args) {
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
7
7
|
if (!TRACE_ENABLED) return;
|
|
@@ -63,7 +63,7 @@ export function ensureSelection() {
|
|
|
63
63
|
$newAnchor
|
|
64
64
|
});
|
|
65
65
|
trace("appendTransaction", "search for new valid $head...");
|
|
66
|
-
let $newHead = getNewValidPos(newState.selection.$head, getDirection(oldState.selection.$head, newState.selection.$head, pluginState));
|
|
66
|
+
let $newHead = newState.selection.empty ? $newAnchor : getNewValidPos(newState.selection.$head, getDirection(oldState.selection.$head, newState.selection.$head, pluginState));
|
|
67
67
|
trace("appendTransaction", "new valid $head", $newHead?.pos, {
|
|
68
68
|
$newHead
|
|
69
69
|
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const addIdAttr = (nodeSpec, key)=>{
|
|
2
|
+
const { toDOM, parseDOM } = nodeSpec;
|
|
3
|
+
if (!toDOM || !parseDOM) {
|
|
4
|
+
console.warn("addIdAttr", "ignored node", key, "with nodeSpec", nodeSpec);
|
|
5
|
+
return nodeSpec;
|
|
6
|
+
}
|
|
7
|
+
const newNodeSpec = {
|
|
8
|
+
...nodeSpec,
|
|
9
|
+
attrs: {
|
|
10
|
+
...nodeSpec.attrs ?? {},
|
|
11
|
+
id: {
|
|
12
|
+
default: null
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
toDOM (node) {
|
|
16
|
+
const domOutputSpec = toDOM(node);
|
|
17
|
+
if (!Array.isArray(domOutputSpec)) {
|
|
18
|
+
console.warn("addIdAttr", "domOutputSpec is not an array, id is not added", domOutputSpec);
|
|
19
|
+
return domOutputSpec;
|
|
20
|
+
}
|
|
21
|
+
const id = typeof node.attrs["id"] === "string" ? node.attrs["id"] : null;
|
|
22
|
+
const attrs = domOutputSpec[1];
|
|
23
|
+
if (!Array.isArray(attrs) && typeof attrs === "object" && attrs !== null) {
|
|
24
|
+
const theRest = domOutputSpec.slice(2);
|
|
25
|
+
const result = [
|
|
26
|
+
domOutputSpec[0],
|
|
27
|
+
id ? {
|
|
28
|
+
...attrs,
|
|
29
|
+
"data-id": id
|
|
30
|
+
} : attrs,
|
|
31
|
+
...theRest
|
|
32
|
+
];
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
const theRest = domOutputSpec.slice(1);
|
|
36
|
+
const result = [
|
|
37
|
+
domOutputSpec[0],
|
|
38
|
+
id ? {
|
|
39
|
+
"data-id": id
|
|
40
|
+
} : {},
|
|
41
|
+
...theRest
|
|
42
|
+
];
|
|
43
|
+
return result;
|
|
44
|
+
},
|
|
45
|
+
parseDOM: [
|
|
46
|
+
...parseDOM.map((tagParseRule)=>({
|
|
47
|
+
...tagParseRule,
|
|
48
|
+
getAttrs (dom) {
|
|
49
|
+
const id = dom.getAttribute("data-id");
|
|
50
|
+
return tagParseRule.getAttrs ? {
|
|
51
|
+
...tagParseRule.getAttrs(dom),
|
|
52
|
+
id
|
|
53
|
+
} : {
|
|
54
|
+
id
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}))
|
|
58
|
+
]
|
|
59
|
+
};
|
|
60
|
+
console.info("addIdAttr", "adding id to node", key, "with nodeSpec", nodeSpec, "new nodeSpec", newNodeSpec);
|
|
61
|
+
return newNodeSpec;
|
|
62
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { getNodeId } from "./getNodeId.js";
|
|
2
|
+
export function buildMaterializedPaths(doc) {
|
|
3
|
+
const paths = new Map();
|
|
4
|
+
// add direct doc children first since they have a specific parent signature due to doc not having an ID
|
|
5
|
+
doc.children.forEach((node, index, children)=>{
|
|
6
|
+
const nodeId = getNodeId(node);
|
|
7
|
+
if (nodeId == null) return;
|
|
8
|
+
const leftSibling = children[index - 1];
|
|
9
|
+
const leftSiblingId = leftSibling ? getNodeId(leftSibling) : null;
|
|
10
|
+
const rightSibling = children[index + 1];
|
|
11
|
+
const rightSiblingId = rightSibling ? getNodeId(rightSibling) : null;
|
|
12
|
+
const parent = {
|
|
13
|
+
nodeId: "__doc__",
|
|
14
|
+
nodeType: "__doc__",
|
|
15
|
+
nodeAttrs: {},
|
|
16
|
+
nodeMarks: [],
|
|
17
|
+
childSiblingIds: [
|
|
18
|
+
leftSiblingId,
|
|
19
|
+
rightSiblingId
|
|
20
|
+
],
|
|
21
|
+
childIndex: index
|
|
22
|
+
};
|
|
23
|
+
paths.set(nodeId, {
|
|
24
|
+
nodeType: node.type.name,
|
|
25
|
+
chain: [
|
|
26
|
+
parent
|
|
27
|
+
]
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
// now add the rest of the nodes
|
|
31
|
+
doc.descendants((node, _pos, parent, childIndex)=>{
|
|
32
|
+
if (node.isText) return false;
|
|
33
|
+
const nodeId = getNodeId(node);
|
|
34
|
+
if (nodeId == null) return true;
|
|
35
|
+
// this is to avoid processing direct doc children twice
|
|
36
|
+
if (paths.has(nodeId)) return true;
|
|
37
|
+
if (parent == null) return true;
|
|
38
|
+
const parentId = getNodeId(parent);
|
|
39
|
+
if (parentId == null) return true;
|
|
40
|
+
// by definition, for any node it's parent chain should already exist
|
|
41
|
+
// because we go downwards
|
|
42
|
+
const parentChain = paths.get(parentId);
|
|
43
|
+
if (parentChain == null) return true;
|
|
44
|
+
const leftSibling = parent.children[childIndex - 1];
|
|
45
|
+
const leftSiblingId = leftSibling ? getNodeId(leftSibling) : null;
|
|
46
|
+
const rightSibling = parent.children[childIndex + 1];
|
|
47
|
+
const rightSiblingId = rightSibling ? getNodeId(rightSibling) : null;
|
|
48
|
+
// (this node parent chain) is (parent chain of the parent node) + (the parent node itself)
|
|
49
|
+
const parentDesc = {
|
|
50
|
+
nodeId: parentId,
|
|
51
|
+
nodeType: parent.type.name,
|
|
52
|
+
nodeAttrs: parent.attrs,
|
|
53
|
+
nodeMarks: parent.marks.map((mark)=>mark.toJSON()),
|
|
54
|
+
childSiblingIds: [
|
|
55
|
+
leftSiblingId,
|
|
56
|
+
rightSiblingId
|
|
57
|
+
],
|
|
58
|
+
childIndex: childIndex
|
|
59
|
+
};
|
|
60
|
+
const chain = [
|
|
61
|
+
parentDesc,
|
|
62
|
+
...parentChain.chain
|
|
63
|
+
];
|
|
64
|
+
paths.set(nodeId, {
|
|
65
|
+
nodeType: node.type.name,
|
|
66
|
+
chain
|
|
67
|
+
});
|
|
68
|
+
return true;
|
|
69
|
+
});
|
|
70
|
+
return paths;
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateUniqueNodeId(): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Node } from "prosemirror-model";
|
|
2
|
+
import { Transform } from "prosemirror-transform";
|
|
3
|
+
import { type SuggestionId } from "../../generateId.js";
|
|
4
|
+
export declare function applyAllStructureSuggestions(node: Node): Transform;
|
|
5
|
+
export declare function revertAllStructureSuggestions(node: Node): Transform;
|
|
6
|
+
export declare function applyOneStructureSuggestion(node: Node, suggestionId: SuggestionId): Transform;
|
|
7
|
+
export declare function revertOneStructureSuggestion(node: Node, suggestionId: SuggestionId): Transform;
|
|
8
|
+
export declare function applyAllStructureSuggestionsOnNode(node: Node, from?: number, to?: number): Transform;
|
|
9
|
+
export declare function revertAllStructureSuggestionsOnNode(node: Node, from?: number, to?: number): Transform;
|