Skip to content

Commit f703272

Browse files
committed
Extracted method for getting suggestion marks.
1 parent 1c9a5c9 commit f703272

11 files changed

Lines changed: 69 additions & 147 deletions

demo/main.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,23 @@ const suggestChangesUiPlugin = new Plugin({
127127
const toggleButton = document.createElement("button");
128128
toggleButton.appendChild(document.createTextNode("Enable suggestions"));
129129
toggleButton.addEventListener("click", () => {
130-
// eslint-disable-next-line @typescript-eslint/unbound-method
130+
131131
toggleSuggestChanges(view.state, view.dispatch);
132132
view.focus();
133133
});
134134

135135
const applyAllButton = document.createElement("button");
136136
applyAllButton.appendChild(document.createTextNode("Apply all"));
137137
applyAllButton.addEventListener("click", () => {
138-
// eslint-disable-next-line @typescript-eslint/unbound-method
138+
139139
applySuggestions(view.state, view.dispatch);
140140
view.focus();
141141
});
142142

143143
const revertAllButton = document.createElement("button");
144144
revertAllButton.appendChild(document.createTextNode("Revert all"));
145145
revertAllButton.addEventListener("click", () => {
146-
// eslint-disable-next-line @typescript-eslint/unbound-method
146+
147147
revertSuggestions(view.state, view.dispatch);
148148
view.focus();
149149
});
@@ -205,5 +205,5 @@ const view = new EditorView(editorEl, {
205205
dispatchTransaction: withSuggestChanges(),
206206
});
207207

208-
// eslint-disable-next-line @typescript-eslint/unbound-method
208+
209209
enableSuggestChanges(view.state, view.dispatch);

src/__tests__/replaceAroundStep.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ describe("ReplaceAroundStep", () => {
115115
id: 1,
116116
type: "mark",
117117
// we know this mark exists
118-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
118+
119119
previousValue: doc.children[0]!.marks[0]!.toJSON(),
120120
newValue: null,
121121
},

src/addNodeMarkStep.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { type EditorState, type Transaction } from "prosemirror-state";
33
import { type AddNodeMarkStep, type Step } from "prosemirror-transform";
44

55
import { rebasePos } from "./rebasePos.js";
6+
import { getSuggestionMarks } from "./utils.js";
67

78
/**
89
* Transform an add node mark step into its equivalent tracked steps.
@@ -18,12 +19,7 @@ export function trackAddNodeMarkStep(
1819
prevSteps: Step[],
1920
suggestionId: number,
2021
) {
21-
const { modification } = state.schema.marks;
22-
if (!modification) {
23-
throw new Error(
24-
`Failed to apply modifications to node: schema does not contain modification mark. Did you forget to add it?`,
25-
);
26-
}
22+
const { modification } = getSuggestionMarks(state.schema);
2723

2824
const rebasedPos = rebasePos(step.pos, prevSteps, trackedTransaction.steps);
2925
const $pos = trackedTransaction.doc.resolve(rebasedPos);

src/attrStep.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { type EditorState, type Transaction } from "prosemirror-state";
33
import { type AttrStep, type Step } from "prosemirror-transform";
44

55
import { rebasePos } from "./rebasePos.js";
6+
import { getSuggestionMarks } from "./utils.js";
67

78
/**
89
* Transform an attr mark step into its equivalent tracked steps.
@@ -18,12 +19,7 @@ export function trackAttrStep(
1819
prevSteps: Step[],
1920
suggestionId: number,
2021
) {
21-
const { modification } = state.schema.marks;
22-
if (!modification) {
23-
throw new Error(
24-
`Failed to apply modifications to node: schema does not contain modification mark. Did you forget to add it?`,
25-
);
26-
}
22+
const { modification } = getSuggestionMarks(state.schema);
2723

2824
const rebasedPos = rebasePos(step.pos, prevSteps, trackedTransaction.steps);
2925
const $pos = trackedTransaction.doc.resolve(rebasedPos);

src/commands.ts

Lines changed: 12 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { type EditorView } from "prosemirror-view";
1515

1616
import { findSuggestionMarkEnd } from "./findSuggestionMarkEnd.js";
1717
import { suggestChangesKey } from "./plugin.js";
18+
import { getSuggestionMarks } from "./utils.js";
1819

1920
/**
2021
* Given a node and a transform, add a set of steps to the
@@ -86,9 +87,8 @@ function applySuggestionsToTransform(
8687
}
8788

8889
function revertModifications(node: Node, pos: number, tr: Transform) {
89-
const existingMods = node.marks.filter(
90-
(mark) => mark.type === node.type.schema.marks["modification"],
91-
);
90+
const { modification } = getSuggestionMarks(node.type.schema);
91+
const existingMods = node.marks.filter((mark) => mark.type === modification);
9292
for (const mod of existingMods) {
9393
if (
9494
mod.attrs["type"] === "attr" &&
@@ -129,12 +129,7 @@ function applyModificationsToTransform(
129129
dir: number,
130130
suggestionId?: number,
131131
) {
132-
const { modification } = node.type.schema.marks;
133-
if (!modification) {
134-
throw new Error(
135-
`Failed to apply modifications to node: schema does not contain modification mark. Did you forget to add it?`,
136-
);
137-
}
132+
const { modification } = getSuggestionMarks(node.type.schema);
138133

139134
const modificationIsInSet =
140135
suggestionId === undefined
@@ -177,17 +172,7 @@ function applyModificationsToTransform(
177172
}
178173

179174
function applySuggestionsToNode(node: Node) {
180-
const { deletion, insertion } = node.type.schema.marks;
181-
if (!deletion) {
182-
throw new Error(
183-
`Failed to apply tracked changes to node: schema does not contain deletion mark. Did you forget to add it?`,
184-
);
185-
}
186-
if (!insertion) {
187-
throw new Error(
188-
`Failed to apply tracked changes to node: schema does not contain insertion mark. Did you forget to add it?`,
189-
);
190-
}
175+
const { deletion, insertion } = getSuggestionMarks(node.type.schema);
191176

192177
if (deletion.isInSet(node.marks)) {
193178
return null;
@@ -219,17 +204,7 @@ export function applySuggestions(
219204
state: EditorState,
220205
dispatch?: EditorView["dispatch"],
221206
) {
222-
const { deletion, insertion } = state.schema.marks;
223-
if (!deletion) {
224-
throw new Error(
225-
`Failed to apply tracked changes to node: schema does not contain deletion mark. Did you forget to add it?`,
226-
);
227-
}
228-
if (!insertion) {
229-
throw new Error(
230-
`Failed to apply tracked changes to node: schema does not contain insertion mark. Did you forget to add it?`,
231-
);
232-
}
207+
const { deletion, insertion } = getSuggestionMarks(state.schema);
233208

234209
const tr = state.tr;
235210
applySuggestionsToTransform(state.doc, tr, insertion, deletion);
@@ -248,17 +223,7 @@ export function applySuggestions(
248223
*/
249224
export function applySuggestion(suggestionId: number): Command {
250225
return (state, dispatch) => {
251-
const { deletion, insertion } = state.schema.marks;
252-
if (!deletion) {
253-
throw new Error(
254-
`Failed to apply tracked changes to node: schema does not contain deletion mark. Did you forget to add it?`,
255-
);
256-
}
257-
if (!insertion) {
258-
throw new Error(
259-
`Failed to apply tracked changes to node: schema does not contain insertion mark. Did you forget to add it?`,
260-
);
261-
}
226+
const { deletion, insertion } = getSuggestionMarks(state.schema);
262227

263228
const tr = state.tr;
264229
applySuggestionsToTransform(
@@ -287,17 +252,7 @@ export function revertSuggestions(
287252
state: EditorState,
288253
dispatch?: EditorView["dispatch"],
289254
) {
290-
const { deletion, insertion } = state.schema.marks;
291-
if (!deletion) {
292-
throw new Error(
293-
`Failed to apply tracked changes to node: schema does not contain deletion mark. Did you forget to add it?`,
294-
);
295-
}
296-
if (!insertion) {
297-
throw new Error(
298-
`Failed to apply tracked changes to node: schema does not contain insertion mark. Did you forget to add it?`,
299-
);
300-
}
255+
const { deletion, insertion } = getSuggestionMarks(state.schema);
301256
const tr = state.tr;
302257
applySuggestionsToTransform(state.doc, tr, deletion, insertion);
303258
applyModificationsToTransform(tr.doc, tr, -1);
@@ -315,17 +270,7 @@ export function revertSuggestions(
315270
*/
316271
export function revertSuggestion(suggestionId: number): Command {
317272
return (state, dispatch) => {
318-
const { deletion, insertion } = state.schema.marks;
319-
if (!deletion) {
320-
throw new Error(
321-
`Failed to apply tracked changes to node: schema does not contain deletion mark. Did you forget to add it?`,
322-
);
323-
}
324-
if (!insertion) {
325-
throw new Error(
326-
`Failed to apply tracked changes to node: schema does not contain insertion mark. Did you forget to add it?`,
327-
);
328-
}
273+
const { deletion, insertion } = getSuggestionMarks(state.schema);
329274

330275
const tr = state.tr;
331276
applySuggestionsToTransform(
@@ -348,22 +293,9 @@ export function revertSuggestion(suggestionId: number): Command {
348293
*/
349294
export function selectSuggestion(suggestionId: number): Command {
350295
return (state, dispatch) => {
351-
const { deletion, insertion, modification } = state.schema.marks;
352-
if (!deletion) {
353-
throw new Error(
354-
`Failed to apply tracked changes to node: schema does not contain deletion mark. Did you forget to add it?`,
355-
);
356-
}
357-
if (!insertion) {
358-
throw new Error(
359-
`Failed to apply tracked changes to node: schema does not contain insertion mark. Did you forget to add it?`,
360-
);
361-
}
362-
if (!modification) {
363-
throw new Error(
364-
`Failed to apply tracked changes to node: schema does not contain modification mark. Did you forget to add it?`,
365-
);
366-
}
296+
const { deletion, insertion, modification } = getSuggestionMarks(
297+
state.schema,
298+
);
367299

368300
let changeStart = null as number | null;
369301
let changeEnd = null as number | null;

src/decorations.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
DecorationSet,
66
type DecorationSource,
77
} from "prosemirror-view";
8+
import { getSuggestionMarks } from "./utils.js";
89

910
function pilcrow() {
1011
const span = document.createElement("span");
@@ -13,17 +14,7 @@ function pilcrow() {
1314
}
1415

1516
export function getSuggestionDecorations(state: EditorState): DecorationSource {
16-
const { deletion, insertion } = state.schema.marks;
17-
if (!deletion) {
18-
throw new Error(
19-
`Failed to apply tracked changes to node: schema does not contain deletion mark. Did you forget to add it?`,
20-
);
21-
}
22-
if (!insertion) {
23-
throw new Error(
24-
`Failed to apply tracked changes to node: schema does not contain insertion mark. Did you forget to add it?`,
25-
);
26-
}
17+
const { deletion, insertion } = getSuggestionMarks(state.schema);
2718

2819
const changeDecorations: Decoration[] = [];
2920
let lastParentNode: Node | null = null;

src/removeNodeMarkStep.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { type EditorState, type Transaction } from "prosemirror-state";
33
import { type RemoveNodeMarkStep, type Step } from "prosemirror-transform";
44

55
import { rebasePos } from "./rebasePos.js";
6+
import { getSuggestionMarks } from "./utils.js";
67

78
/**
89
* Transform a remove node mark step into its equivalent tracked steps.
@@ -18,12 +19,7 @@ export function suggestRemoveNodeMarkStep(
1819
prevSteps: Step[],
1920
suggestionId: number,
2021
) {
21-
const { modification } = state.schema.marks;
22-
if (!modification) {
23-
throw new Error(
24-
`Failed to apply modifications to node: schema does not contain modification mark. Did you forget to add it?`,
25-
);
26-
}
22+
const { modification } = getSuggestionMarks(state.schema);
2723

2824
const rebasedPos = rebasePos(step.pos, prevSteps, trackedTransaction.steps);
2925
const $pos = trackedTransaction.doc.resolve(rebasedPos);

src/replaceAroundStep.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { applySuggestionsToSlice } from "./commands.js";
1616
import { rebasePos } from "./rebasePos.js";
1717
import { suggestRemoveNodeMarkStep } from "./removeNodeMarkStep.js";
1818
import { suggestReplaceStep } from "./replaceStep.js";
19+
import { getSuggestionMarks } from "./utils.js";
1920

2021
/**
2122
* This detects and handles changes from `setNodeMarkup` so that these are tracked as a modification
@@ -37,12 +38,7 @@ function suggestSetNodeMarkup(
3738
step.gapFrom === step.from + 1 &&
3839
(step as ReplaceAroundStep & { structure: boolean }).structure
3940
) {
40-
const { modification } = state.schema.marks;
41-
if (!modification) {
42-
throw new Error(
43-
`Failed to apply modifications to node: schema does not contain modification mark. Did you forget to add it?`,
44-
);
45-
}
41+
const { modification } = getSuggestionMarks(state.schema);
4642

4743
const newNode = step.slice.content.firstChild;
4844
let from = rebasePos(step.from, prevSteps, trackedTransaction.steps);

src/replaceStep.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { type ReplaceStep, type Step } from "prosemirror-transform";
88

99
import { findSuggestionMarkEnd } from "./findSuggestionMarkEnd.js";
1010
import { rebasePos } from "./rebasePos.js";
11+
import { getSuggestionMarks } from "./utils.js";
1112

1213
/**
1314
* Transform a replace step into its equivalent tracked steps.
@@ -47,17 +48,7 @@ export function suggestReplaceStep(
4748
prevSteps: Step[],
4849
suggestionId: number,
4950
) {
50-
const { deletion, insertion } = state.schema.marks;
51-
if (!deletion) {
52-
throw new Error(
53-
`Failed to apply tracked changes to node: schema does not contain deletion mark. Did you forget to add it?`,
54-
);
55-
}
56-
if (!insertion) {
57-
throw new Error(
58-
`Failed to apply tracked changes to node: schema does not contain insertion mark. Did you forget to add it?`,
59-
);
60-
}
51+
const { deletion, insertion } = getSuggestionMarks(state.schema);
6152

6253
// Check for insertion and deletion marks directly
6354
// adjacent to this step's boundaries. If they exist,

src/utils.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { type MarkType, type Schema } from "prosemirror-model";
2+
3+
export interface SuggestionMarks {
4+
insertion: MarkType;
5+
deletion: MarkType;
6+
modification: MarkType;
7+
}
8+
9+
/**
10+
* Get the suggestion mark types from a schema, with proper error handling.
11+
* Throws an error if any of the required marks are not found.
12+
*/
13+
export function getSuggestionMarks(schema: Schema): SuggestionMarks {
14+
const { insertion, deletion, modification } = schema.marks;
15+
16+
if (!insertion) {
17+
throw new Error(
18+
"Failed to find insertion mark in schema. Did you forget to add it?",
19+
);
20+
}
21+
22+
if (!deletion) {
23+
throw new Error(
24+
"Failed to find deletion mark in schema. Did you forget to add it?",
25+
);
26+
}
27+
28+
if (!modification) {
29+
throw new Error(
30+
"Failed to find modification mark in schema. Did you forget to add it?",
31+
);
32+
}
33+
34+
return { insertion, deletion, modification };
35+
}

0 commit comments

Comments
 (0)