vitest-prosemirror 0.2.2 → 0.3.1
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/vitest-prosemirror.d.ts +8 -7
- package/dist/vitest-prosemirror.js +205 -63
- package/dist/vitest-prosemirror.js.map +1 -1
- package/package.json +32 -29
|
@@ -8,6 +8,13 @@ export declare interface CustomMatchers<R = unknown> {
|
|
|
8
8
|
toEqualProseMirrorNode(expected: Node_2): R;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export declare interface KeyboardModifiers {
|
|
12
|
+
altKey?: boolean;
|
|
13
|
+
ctrlKey?: boolean;
|
|
14
|
+
metaKey?: boolean;
|
|
15
|
+
shiftKey?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
export declare interface Options {
|
|
12
19
|
plugins: Array<Plugin_2>;
|
|
13
20
|
}
|
|
@@ -17,9 +24,8 @@ export declare class ProseMirrorTester {
|
|
|
17
24
|
get schema(): Schema;
|
|
18
25
|
private readonly view;
|
|
19
26
|
constructor(documentRoot: Node_2, options?: Partial<Options>);
|
|
20
|
-
insertText(text: string): void;
|
|
27
|
+
insertText(text: string, modifiers?: KeyboardModifiers): void;
|
|
21
28
|
selectText(selection: TesterSelection): void;
|
|
22
|
-
shortcut(text: string): void;
|
|
23
29
|
private getSelection;
|
|
24
30
|
}
|
|
25
31
|
|
|
@@ -28,11 +34,6 @@ export declare type TesterSelection = "all" | "end" | "start" | {
|
|
|
28
34
|
to: number;
|
|
29
35
|
} | Selection_2 | number;
|
|
30
36
|
|
|
31
|
-
/**
|
|
32
|
-
* @public
|
|
33
|
-
*/
|
|
34
|
-
export declare function trimProseMirrorNode(node: Node_2): Node_2;
|
|
35
|
-
|
|
36
37
|
export { }
|
|
37
38
|
|
|
38
39
|
|
|
@@ -2,8 +2,6 @@ import { expect } from "vitest";
|
|
|
2
2
|
import stringifyObject from "stringify-object";
|
|
3
3
|
import { EditorState, AllSelection, TextSelection } from "prosemirror-state";
|
|
4
4
|
import { EditorView } from "prosemirror-view";
|
|
5
|
-
import { Keyboard } from "test-keyboard";
|
|
6
|
-
import { Fragment } from "prosemirror-model";
|
|
7
5
|
function getMarks(marks, origContent) {
|
|
8
6
|
let content = `'${origContent}'`;
|
|
9
7
|
for (const mark of [...marks].reverse()) {
|
|
@@ -28,33 +26,116 @@ const renamedTypes = {
|
|
|
28
26
|
paragraph: "p"
|
|
29
27
|
};
|
|
30
28
|
function stringifyProseMirrorNode(node, indentation = "") {
|
|
31
|
-
var _a;
|
|
32
|
-
const nextIndentation = `${indentation} `;
|
|
33
29
|
if (node.type.name === "text") {
|
|
34
30
|
return `${indentation}${getMarks(node.marks, node.text ?? "")}`;
|
|
35
31
|
}
|
|
36
32
|
const type = renamedTypes[node.type.name] ?? node.type.name;
|
|
37
33
|
const content = [];
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
34
|
+
const nextIndentation = `${indentation} `;
|
|
35
|
+
if (Object.keys(node.attrs).length > 0) {
|
|
40
36
|
content.push(
|
|
41
|
-
stringifyObject(node.attrs, { indent: " ", inlineCharacterLimit: 1e3 })
|
|
37
|
+
`${nextIndentation}${stringifyObject(node.attrs, { indent: " ", inlineCharacterLimit: 1e3 })},`
|
|
42
38
|
);
|
|
43
39
|
}
|
|
44
40
|
node.content.forEach((item) => {
|
|
45
|
-
content.push(stringifyProseMirrorNode(item, nextIndentation));
|
|
41
|
+
content.push(`${stringifyProseMirrorNode(item, nextIndentation)},`);
|
|
46
42
|
});
|
|
47
|
-
if (
|
|
43
|
+
if (content.length === 0) {
|
|
44
|
+
return `${indentation}${type}()`;
|
|
45
|
+
}
|
|
46
|
+
if (content.length === 1 && node.content.firstChild?.type.name === "text") {
|
|
48
47
|
return `${indentation}${type}(${stringifyProseMirrorNode(node.content.firstChild, "")})`;
|
|
49
48
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
return `${indentation}${type}(
|
|
50
|
+
${content.join("\n")}
|
|
51
|
+
${indentation})`;
|
|
52
|
+
}
|
|
53
|
+
function tokenizeKeyboardInput(input) {
|
|
54
|
+
const output = [];
|
|
55
|
+
let currentGroupOpener = null;
|
|
56
|
+
let group = "";
|
|
57
|
+
for (const char of input) {
|
|
58
|
+
if (currentGroupOpener !== null) {
|
|
59
|
+
if (["]", "}"].includes(char)) {
|
|
60
|
+
if (group.endsWith("\\") && char === matchingBrace(currentGroupOpener)) {
|
|
61
|
+
group = group.slice(0, -2) + char;
|
|
62
|
+
} else if (char === matchingBrace(currentGroupOpener)) {
|
|
63
|
+
if (group.length === 4 && group.startsWith("Key")) {
|
|
64
|
+
output.push(group.slice(3).toLowerCase());
|
|
65
|
+
} else {
|
|
66
|
+
output.push(group);
|
|
67
|
+
}
|
|
68
|
+
currentGroupOpener = null;
|
|
69
|
+
group = "";
|
|
70
|
+
} else {
|
|
71
|
+
group += char;
|
|
72
|
+
}
|
|
73
|
+
} else if (group === "" && currentGroupOpener === char) {
|
|
74
|
+
output.push(char);
|
|
75
|
+
currentGroupOpener = null;
|
|
76
|
+
group = "";
|
|
77
|
+
} else {
|
|
78
|
+
group += char;
|
|
79
|
+
}
|
|
80
|
+
} else if (["[", "{"].includes(char)) {
|
|
81
|
+
currentGroupOpener = char;
|
|
82
|
+
} else {
|
|
83
|
+
output.push(char);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
output.forEach(assertSupported);
|
|
87
|
+
return output;
|
|
57
88
|
}
|
|
89
|
+
function assertSupported(character) {
|
|
90
|
+
if (/^\/.+/u.exec(character) || /.+>[\d]*\/?$/u.exec(character)) {
|
|
91
|
+
throw new Error("Unsupported keyboard input");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function matchingBrace(opener) {
|
|
95
|
+
return opener === "{" ? "}" : "]";
|
|
96
|
+
}
|
|
97
|
+
class KeyboardEventMock extends KeyboardEvent {
|
|
98
|
+
constructor(onPreventDefault, type, eventInitDict) {
|
|
99
|
+
super(type, eventInitDict);
|
|
100
|
+
this.onPreventDefault = onPreventDefault;
|
|
101
|
+
}
|
|
102
|
+
preventDefault() {
|
|
103
|
+
super.preventDefault();
|
|
104
|
+
this.onPreventDefault();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const _MutationObserverMock = class _MutationObserverMock {
|
|
108
|
+
constructor(callback) {
|
|
109
|
+
this.callback = callback;
|
|
110
|
+
this.target = void 0;
|
|
111
|
+
}
|
|
112
|
+
static createMutation(target, mutationRecords) {
|
|
113
|
+
const observer = _MutationObserverMock.activeObservers.get(target);
|
|
114
|
+
if (observer === void 0) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
observer.callback(
|
|
118
|
+
mutationRecords,
|
|
119
|
+
observer
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
disconnect() {
|
|
123
|
+
if (this.target !== void 0) {
|
|
124
|
+
_MutationObserverMock.activeObservers.delete(this.target);
|
|
125
|
+
}
|
|
126
|
+
this.target = void 0;
|
|
127
|
+
}
|
|
128
|
+
observe(target) {
|
|
129
|
+
this.target = target;
|
|
130
|
+
_MutationObserverMock.activeObservers.set(target, this);
|
|
131
|
+
}
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/class-methods-use-this -- Mocking another method
|
|
133
|
+
takeRecords() {
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
_MutationObserverMock.activeObservers = /* @__PURE__ */ new Map();
|
|
138
|
+
let MutationObserverMock = _MutationObserverMock;
|
|
58
139
|
class ProseMirrorTester {
|
|
59
140
|
get doc() {
|
|
60
141
|
return this.view.state.doc;
|
|
@@ -72,49 +153,109 @@ class ProseMirrorTester {
|
|
|
72
153
|
doc: documentRoot,
|
|
73
154
|
plugins: options.plugins ?? []
|
|
74
155
|
});
|
|
156
|
+
global.MutationObserver = MutationObserverMock;
|
|
75
157
|
this.view = new EditorView(element, {
|
|
76
158
|
state
|
|
77
159
|
});
|
|
78
160
|
}
|
|
79
|
-
insertText(text) {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
161
|
+
insertText(text, modifiers) {
|
|
162
|
+
for (const key of tokenizeKeyboardInput(text)) {
|
|
163
|
+
const character = keyToChar(key);
|
|
164
|
+
let keydownPrevented = false;
|
|
165
|
+
this.view.dispatchEvent(
|
|
166
|
+
new KeyboardEventMock(
|
|
167
|
+
() => {
|
|
168
|
+
keydownPrevented = true;
|
|
169
|
+
},
|
|
170
|
+
"keydown",
|
|
171
|
+
{
|
|
172
|
+
bubbles: true,
|
|
173
|
+
charCode: character.charCodeAt(0),
|
|
174
|
+
key,
|
|
175
|
+
...modifiers
|
|
176
|
+
}
|
|
92
177
|
)
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
178
|
+
);
|
|
179
|
+
if (keydownPrevented) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
this.view.dispatchEvent(
|
|
183
|
+
new KeyboardEvent("keypress", {
|
|
184
|
+
bubbles: true,
|
|
185
|
+
charCode: character.charCodeAt(0),
|
|
186
|
+
key,
|
|
187
|
+
keyCode: character.charCodeAt(0),
|
|
188
|
+
...modifiers
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
const domNode = this.view.domAtPos(this.view.state.selection.from).node;
|
|
192
|
+
if (domNode.childNodes.length === 1 && domNode.firstChild instanceof HTMLBRElement && domNode.firstChild.classList.contains("ProseMirror-trailingBreak")) {
|
|
193
|
+
const brNode = domNode.firstChild;
|
|
194
|
+
const textNode = new Text(character);
|
|
195
|
+
domNode.removeChild(brNode);
|
|
196
|
+
domNode.appendChild(textNode);
|
|
197
|
+
MutationObserverMock.createMutation(this.view.dom, [
|
|
198
|
+
{
|
|
199
|
+
addedNodes: [textNode],
|
|
200
|
+
attributeName: null,
|
|
201
|
+
attributeNamespace: null,
|
|
202
|
+
nextSibling: brNode,
|
|
203
|
+
oldValue: null,
|
|
204
|
+
previousSibling: null,
|
|
205
|
+
removedNodes: [],
|
|
206
|
+
target: domNode,
|
|
207
|
+
type: "childList"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
addedNodes: [],
|
|
211
|
+
attributeName: null,
|
|
212
|
+
attributeNamespace: null,
|
|
213
|
+
nextSibling: null,
|
|
214
|
+
oldValue: null,
|
|
215
|
+
previousSibling: textNode,
|
|
216
|
+
removedNodes: [brNode],
|
|
217
|
+
target: domNode,
|
|
218
|
+
type: "childList"
|
|
219
|
+
}
|
|
220
|
+
]);
|
|
221
|
+
} else {
|
|
222
|
+
const target = findLastCharacterDataNode(domNode);
|
|
223
|
+
if (target === null) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const oldValue = target.data;
|
|
227
|
+
const domOffset = this.view.state.selection.from - this.view.posAtDOM(target, 0);
|
|
228
|
+
target.data = target.data.slice(0, domOffset) + character + target.data.slice(domOffset);
|
|
229
|
+
MutationObserverMock.createMutation(this.view.dom, [
|
|
230
|
+
{
|
|
231
|
+
addedNodes: [],
|
|
232
|
+
attributeName: null,
|
|
233
|
+
attributeNamespace: null,
|
|
234
|
+
nextSibling: null,
|
|
235
|
+
oldValue,
|
|
236
|
+
previousSibling: null,
|
|
237
|
+
removedNodes: [],
|
|
238
|
+
target,
|
|
239
|
+
type: "characterData"
|
|
240
|
+
}
|
|
241
|
+
]);
|
|
101
242
|
}
|
|
243
|
+
this.view.dispatchEvent(
|
|
244
|
+
new KeyboardEvent("keyup", {
|
|
245
|
+
bubbles: true,
|
|
246
|
+
charCode: character.charCodeAt(0),
|
|
247
|
+
key,
|
|
248
|
+
keyCode: character.charCodeAt(0),
|
|
249
|
+
...modifiers
|
|
250
|
+
})
|
|
251
|
+
);
|
|
102
252
|
}
|
|
103
|
-
keys.end();
|
|
104
253
|
}
|
|
105
254
|
selectText(selection) {
|
|
106
255
|
this.view.dispatch(
|
|
107
256
|
this.view.state.tr.setSelection(this.getSelection(selection))
|
|
108
257
|
);
|
|
109
258
|
}
|
|
110
|
-
shortcut(text) {
|
|
111
|
-
Keyboard.create({
|
|
112
|
-
batch: true,
|
|
113
|
-
target: this.view.dom
|
|
114
|
-
}).start().mod({ text: text.replace(/Enter$/u, "\n") }).forEach(({ event }) => {
|
|
115
|
-
this.view.dispatchEvent(event);
|
|
116
|
-
}).end();
|
|
117
|
-
}
|
|
118
259
|
getSelection(selection) {
|
|
119
260
|
if (selection === "all") {
|
|
120
261
|
return new AllSelection(this.doc);
|
|
@@ -139,24 +280,26 @@ class ProseMirrorTester {
|
|
|
139
280
|
return TextSelection.near(this.doc.resolve(pos));
|
|
140
281
|
}
|
|
141
282
|
}
|
|
142
|
-
function
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
for (const child of node.children) {
|
|
146
|
-
if (child.type.name === "paragraph" && ["", "\n"].includes(child.textContent)) {
|
|
147
|
-
start++;
|
|
148
|
-
} else {
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
283
|
+
function findLastCharacterDataNode(node) {
|
|
284
|
+
if (node instanceof CharacterData) {
|
|
285
|
+
return node;
|
|
151
286
|
}
|
|
152
|
-
for (const child of node.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
break;
|
|
287
|
+
for (const child of Array.from(node.childNodes).reverse()) {
|
|
288
|
+
const textNode = findLastCharacterDataNode(child);
|
|
289
|
+
if (textNode !== null) {
|
|
290
|
+
return textNode;
|
|
157
291
|
}
|
|
158
292
|
}
|
|
159
|
-
return
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
function keyToChar(key) {
|
|
296
|
+
if (key === "Enter") {
|
|
297
|
+
return "\n";
|
|
298
|
+
}
|
|
299
|
+
if (key === "Tab") {
|
|
300
|
+
return " ";
|
|
301
|
+
}
|
|
302
|
+
return key;
|
|
160
303
|
}
|
|
161
304
|
expect.extend({
|
|
162
305
|
toEqualProseMirrorNode(received, expected) {
|
|
@@ -194,7 +337,6 @@ ${diffString}` : ""}`;
|
|
|
194
337
|
}
|
|
195
338
|
});
|
|
196
339
|
export {
|
|
197
|
-
ProseMirrorTester
|
|
198
|
-
trimProseMirrorNode
|
|
340
|
+
ProseMirrorTester
|
|
199
341
|
};
|
|
200
342
|
//# sourceMappingURL=vitest-prosemirror.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-prosemirror.js","sources":["../src/stringifyProseMirrorNode.ts","../src/ProseMirrorTester.ts","../src/trimProseMirrorNode.ts","../src/index.ts"],"sourcesContent":["import type { Mark, Node } from \"prosemirror-model\";\n\nimport stringifyObject from \"stringify-object\";\n\nfunction getMarks(marks: ReadonlyArray<Mark>, origContent: string): string {\n let content = `'${origContent}'`;\n\n for (const mark of [...marks].reverse()) {\n const hasAttrs = Object.keys(mark.attrs).length > 0;\n const items: Array<string> = [content];\n\n if (hasAttrs) {\n items.unshift(\n stringifyObject(mark.attrs, {\n indent: \" \",\n inlineCharacterLimit: 1000,\n }),\n );\n }\n\n content = `${mark.type.name}(${items.join(\", \")})`;\n }\n\n return content;\n}\n\nconst renamedTypes: Record<string, string> = {\n hardBreak: \"br\",\n heading: \"h\",\n horizontalRule: \"hr\",\n paragraph: \"p\",\n};\n\nexport function stringifyProseMirrorNode(node: Node, indentation = \"\"): string {\n const nextIndentation = `${indentation} `;\n\n if (node.type.name === \"text\") {\n return `${indentation}${getMarks(node.marks, node.text ?? \"\")}`;\n }\n\n const type = renamedTypes[node.type.name] ?? node.type.name;\n const content: Array<string> = [];\n const hasAttrs = Object.keys(node.attrs).length > 0;\n\n if (hasAttrs) {\n content.push(\n stringifyObject(node.attrs, { indent: \" \", inlineCharacterLimit: 1000 }),\n );\n }\n\n node.content.forEach((item) => {\n content.push(stringifyProseMirrorNode(item, nextIndentation));\n });\n\n if (\n !hasAttrs &&\n content.length === 1 &&\n node.content.firstChild?.type.name === \"text\"\n ) {\n return `${indentation}${type}(${stringifyProseMirrorNode(node.content.firstChild, \"\")})`;\n }\n\n const joiner = `,\\n`;\n const prefix = hasAttrs\n ? `\\n${nextIndentation}`\n : content.length > 0\n ? \"\\n\"\n : \"\";\n const postfix = content.length > 0 ? `\\n${indentation}` : \"\";\n\n return `${indentation}${type}(${prefix}${content.join(joiner)}${postfix})`;\n}\n","import type { Node, Schema } from \"prosemirror-model\";\n\nimport {\n AllSelection,\n EditorState,\n type Plugin,\n type Selection,\n TextSelection,\n} from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\nimport { Keyboard } from \"test-keyboard\";\n\nexport interface Options {\n plugins: Array<Plugin>;\n}\n\nexport type TesterSelection =\n | \"all\"\n | \"end\"\n | \"start\"\n | { from: number; to: number }\n | Selection\n | number;\n\nexport class ProseMirrorTester {\n public get doc(): Node {\n return this.view.state.doc;\n }\n\n public get schema(): Schema {\n return this.view.state.schema;\n }\n\n private readonly view: EditorView;\n\n public constructor(documentRoot: Node, options: Partial<Options> = {}) {\n if (typeof document === \"undefined\") {\n throw new Error(\"TODO\");\n }\n\n const element = document.createElement(\"div\");\n document.body.append(element);\n\n const state = EditorState.create({\n doc: documentRoot,\n plugins: options.plugins ?? [],\n });\n this.view = new EditorView(element, {\n state,\n });\n }\n\n public insertText(text: string): void {\n const keys = Keyboard.create({\n target: this.view.dom,\n }).start();\n\n for (const character of text) {\n keys.char({ text: character, typing: true });\n\n if (\n this.view.someProp(\"handleTextInput\", (f) =>\n f(\n this.view,\n this.view.state.selection.from,\n this.view.state.selection.from,\n character,\n ),\n ) !== true\n ) {\n this.view.dispatch(\n this.view.state.tr.insertText(\n character,\n this.view.state.selection.from,\n this.view.state.selection.from,\n ),\n );\n }\n }\n keys.end();\n }\n\n public selectText(selection: TesterSelection): void {\n this.view.dispatch(\n this.view.state.tr.setSelection(this.getSelection(selection)),\n );\n }\n\n public shortcut(text: string): void {\n Keyboard.create({\n batch: true,\n target: this.view.dom,\n })\n .start()\n .mod({ text: text.replace(/Enter$/u, \"\\n\") })\n .forEach(({ event }) => {\n this.view.dispatchEvent(event);\n })\n .end();\n }\n\n private getSelection(selection: TesterSelection): Selection {\n if (selection === \"all\") {\n return new AllSelection(this.doc);\n }\n\n if (\n typeof selection === \"object\" &&\n \"$anchor\" in selection &&\n \"$head\" in selection\n ) {\n return selection;\n }\n\n if (\n typeof selection === \"object\" &&\n \"from\" in selection &&\n \"to\" in selection\n ) {\n return TextSelection.between(\n this.doc.resolve(selection.from),\n this.doc.resolve(selection.to),\n );\n }\n\n let pos = 0;\n if (selection === \"start\") {\n pos = 0;\n } else if (selection === \"end\") {\n pos = this.doc.nodeSize - 2;\n } else {\n pos = selection;\n }\n\n return TextSelection.near(this.doc.resolve(pos));\n }\n}\n","import { Fragment, type Node } from \"prosemirror-model\";\n\n/**\n * @public\n */\nexport function trimProseMirrorNode(node: Node): Node {\n let start = 0;\n let end = node.children.length;\n for (const child of node.children) {\n if (\n child.type.name === \"paragraph\" &&\n [\"\", \"\\n\"].includes(child.textContent)\n ) {\n start++;\n } else {\n break;\n }\n }\n for (const child of node.children.slice().reverse()) {\n if (\n child.type.name === \"paragraph\" &&\n [\"\", \"\\n\"].includes(child.textContent)\n ) {\n end--;\n } else {\n break;\n }\n }\n return node.copy(Fragment.from(node.children.slice(start, end)));\n}\n","import type { Node } from \"prosemirror-model\";\n\nimport { expect } from \"vitest\";\n\nimport { stringifyProseMirrorNode } from \"./stringifyProseMirrorNode\";\n\nexport {\n type Options,\n ProseMirrorTester,\n type TesterSelection,\n} from \"./ProseMirrorTester\";\nexport { trimProseMirrorNode } from \"./trimProseMirrorNode\";\n\nexport interface CustomMatchers<R = unknown> {\n toEqualProseMirrorNode(expected: Node): R;\n}\n\n/* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-explicit-any -- These are overridest for vitest matchers */\n\ndeclare module \"vitest\" {\n interface Assertion<T = any> extends CustomMatchers<T> {}\n interface AsymmetricMatchersContaining extends CustomMatchers {}\n}\n\n/* eslint-enable */\n\nexpect.extend({\n toEqualProseMirrorNode(received: Node, expected: Node) {\n const receivedDoc = `\\n${stringifyProseMirrorNode(received)}\\n`;\n const expectedDoc = `\\n${stringifyProseMirrorNode(expected)}\\n`;\n const pass = this.equals(receivedDoc, expectedDoc);\n const message = pass\n ? (): string =>\n `${this.utils.matcherHint(\".not.toEqualProsemirrorNode\")}\\n\\n` +\n `Expected value of document to not equal:\\n ${this.utils.printExpected(expectedDoc)}\\n` +\n `Actual:\\n ${this.utils.printReceived(receivedDoc)}`\n : (): string => {\n const diffString = this.utils.diff(expectedDoc, receivedDoc, {\n expand: this.expand ?? false,\n });\n return `${this.utils.matcherHint(\".toEqualProsemirrorNode\")}\\n\\nExpected value of document to equal:\\n${this.utils.printExpected(expectedDoc)}\\nActual:\\n${this.utils.printReceived(receivedDoc)}${diffString !== undefined ? `\\n\\nDifference:\\n\\n${diffString}` : \"\"}`;\n };\n return {\n message,\n pass,\n };\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vitest-prosemirror.js","sources":["../src/stringifyProseMirrorNode.ts","../src/utils/keyboardInput.ts","../src/ProseMirrorTester.ts","../src/index.ts"],"sourcesContent":["import type { Mark, Node } from \"prosemirror-model\";\n\nimport stringifyObject from \"stringify-object\";\n\nfunction getMarks(marks: ReadonlyArray<Mark>, origContent: string): string {\n let content = `'${origContent}'`;\n\n for (const mark of [...marks].reverse()) {\n const hasAttrs = Object.keys(mark.attrs).length > 0;\n const items: Array<string> = [content];\n\n if (hasAttrs) {\n items.unshift(\n stringifyObject(mark.attrs, {\n indent: \" \",\n inlineCharacterLimit: 1000,\n }),\n );\n }\n\n content = `${mark.type.name}(${items.join(\", \")})`;\n }\n\n return content;\n}\n\nconst renamedTypes: Record<string, string> = {\n hardBreak: \"br\",\n heading: \"h\",\n horizontalRule: \"hr\",\n paragraph: \"p\",\n};\n\nexport function stringifyProseMirrorNode(node: Node, indentation = \"\"): string {\n if (node.type.name === \"text\") {\n return `${indentation}${getMarks(node.marks, node.text ?? \"\")}`;\n }\n\n const type = renamedTypes[node.type.name] ?? node.type.name;\n const content: Array<string> = [];\n const nextIndentation = `${indentation} `;\n\n if (Object.keys(node.attrs).length > 0) {\n content.push(\n `${nextIndentation}${stringifyObject(node.attrs, { indent: \" \", inlineCharacterLimit: 1000 })},`,\n );\n }\n\n node.content.forEach((item) => {\n content.push(`${stringifyProseMirrorNode(item, nextIndentation)},`);\n });\n\n if (content.length === 0) {\n return `${indentation}${type}()`;\n }\n\n if (content.length === 1 && node.content.firstChild?.type.name === \"text\") {\n return `${indentation}${type}(${stringifyProseMirrorNode(node.content.firstChild, \"\")})`;\n }\n\n return `${indentation}${type}(\\n${content.join(\"\\n\")}\\n${indentation})`;\n}\n","export function tokenizeKeyboardInput(input: string): Array<string> {\n const output = [];\n\n let currentGroupOpener: \"[\" | \"{\" | null = null;\n let group = \"\";\n for (const char of input) {\n if (currentGroupOpener !== null) {\n if ([\"]\", \"}\"].includes(char)) {\n if (\n group.endsWith(\"\\\\\") &&\n char === matchingBrace(currentGroupOpener)\n ) {\n group = group.slice(0, -2) + char;\n } else if (char === matchingBrace(currentGroupOpener)) {\n if (group.length === 4 && group.startsWith(\"Key\")) {\n output.push(group.slice(3).toLowerCase());\n } else {\n output.push(group);\n }\n currentGroupOpener = null;\n group = \"\";\n } else {\n group += char;\n }\n } else if (group === \"\" && currentGroupOpener === char) {\n output.push(char);\n currentGroupOpener = null;\n group = \"\";\n } else {\n group += char;\n }\n } else if ([\"[\", \"{\"].includes(char)) {\n currentGroupOpener = char as \"[\" | \"{\";\n } else {\n output.push(char);\n }\n }\n\n output.forEach(assertSupported);\n return output;\n}\n\nfunction assertSupported(character: string): never | void {\n if (/^\\/.+/u.exec(character) || /.+>[\\d]*\\/?$/u.exec(character)) {\n throw new Error(\"Unsupported keyboard input\");\n }\n}\n\nfunction matchingBrace(opener: \"[\" | \"{\"): \"]\" | \"}\" {\n return opener === \"{\" ? \"}\" : \"]\";\n}\n","import type { Node as ProseMirrorNode, Schema } from \"prosemirror-model\";\n\nimport {\n AllSelection,\n EditorState,\n type Plugin,\n type Selection,\n TextSelection,\n} from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport { tokenizeKeyboardInput } from \"./utils/keyboardInput\";\n\nexport interface KeyboardModifiers {\n altKey?: boolean;\n ctrlKey?: boolean;\n metaKey?: boolean;\n shiftKey?: boolean;\n}\n\nexport interface Options {\n plugins: Array<Plugin>;\n}\n\nexport type TesterSelection =\n | \"all\"\n | \"end\"\n | \"start\"\n | { from: number; to: number }\n | Selection\n | number;\n\ntype UsableMutationRecord = Omit<\n MutationRecord,\n \"addedNodes\" | \"removedNodes\"\n> & {\n addedNodes: Array<Node>;\n removedNodes: Array<Node>;\n};\n\nclass KeyboardEventMock extends KeyboardEvent {\n private readonly onPreventDefault: () => void;\n\n public constructor(\n onPreventDefault: () => void,\n type: string,\n eventInitDict?: KeyboardEventInit,\n ) {\n super(type, eventInitDict);\n this.onPreventDefault = onPreventDefault;\n }\n public override preventDefault(): void {\n super.preventDefault();\n this.onPreventDefault();\n }\n}\n\nclass MutationObserverMock {\n private static readonly activeObservers: Map<Node, MutationObserverMock> =\n new Map<Node, MutationObserverMock>();\n\n private readonly callback: MutationCallback;\n private target: Node | undefined;\n\n public constructor(callback: MutationCallback) {\n this.callback = callback;\n this.target = undefined;\n }\n\n public static createMutation(\n target: Node,\n mutationRecords: Array<UsableMutationRecord>,\n ): void {\n const observer = MutationObserverMock.activeObservers.get(target);\n if (observer === undefined) {\n return;\n }\n observer.callback(\n mutationRecords as unknown as Array<MutationRecord>,\n observer,\n );\n }\n\n public disconnect(): void {\n if (this.target !== undefined) {\n MutationObserverMock.activeObservers.delete(this.target);\n }\n this.target = undefined;\n }\n\n public observe(target: Node): void {\n this.target = target;\n MutationObserverMock.activeObservers.set(target, this);\n }\n\n // eslint-disable-next-line @typescript-eslint/class-methods-use-this -- Mocking another method\n public takeRecords(): Array<MutationRecord> {\n return [];\n }\n}\n\nexport class ProseMirrorTester {\n public get doc(): ProseMirrorNode {\n return this.view.state.doc;\n }\n\n public get schema(): Schema {\n return this.view.state.schema;\n }\n\n private readonly view: EditorView;\n\n public constructor(\n documentRoot: ProseMirrorNode,\n options: Partial<Options> = {},\n ) {\n if (typeof document === \"undefined\") {\n throw new Error(\"TODO\");\n }\n\n const element = document.createElement(\"div\");\n document.body.append(element);\n\n const state = EditorState.create({\n doc: documentRoot,\n plugins: options.plugins ?? [],\n });\n\n global.MutationObserver = MutationObserverMock;\n\n this.view = new EditorView(element, {\n state,\n });\n }\n\n public insertText(text: string, modifiers?: KeyboardModifiers): void {\n for (const key of tokenizeKeyboardInput(text)) {\n const character = keyToChar(key);\n\n let keydownPrevented = false;\n this.view.dispatchEvent(\n new KeyboardEventMock(\n () => {\n keydownPrevented = true;\n },\n \"keydown\",\n {\n bubbles: true,\n charCode: character.charCodeAt(0),\n key,\n ...modifiers,\n },\n ),\n );\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- False positive due to the value being set in a callback\n if (keydownPrevented) {\n continue;\n }\n\n this.view.dispatchEvent(\n new KeyboardEvent(\"keypress\", {\n bubbles: true,\n charCode: character.charCodeAt(0),\n key,\n keyCode: character.charCodeAt(0),\n ...modifiers,\n }),\n );\n\n const domNode = this.view.domAtPos(this.view.state.selection.from).node;\n if (\n domNode.childNodes.length === 1 &&\n domNode.firstChild instanceof HTMLBRElement &&\n domNode.firstChild.classList.contains(\"ProseMirror-trailingBreak\")\n ) {\n const brNode = domNode.firstChild;\n const textNode = new Text(character);\n domNode.removeChild(brNode);\n domNode.appendChild(textNode);\n MutationObserverMock.createMutation(this.view.dom, [\n {\n addedNodes: [textNode],\n attributeName: null,\n attributeNamespace: null,\n nextSibling: brNode,\n oldValue: null,\n previousSibling: null,\n removedNodes: [],\n target: domNode,\n type: \"childList\",\n },\n {\n addedNodes: [],\n attributeName: null,\n attributeNamespace: null,\n nextSibling: null,\n oldValue: null,\n previousSibling: textNode,\n removedNodes: [brNode],\n target: domNode,\n type: \"childList\",\n },\n ]);\n } else {\n const target = findLastCharacterDataNode(domNode);\n if (target === null) {\n continue;\n }\n const oldValue = target.data;\n const domOffset =\n this.view.state.selection.from - this.view.posAtDOM(target, 0);\n target.data =\n target.data.slice(0, domOffset) +\n character +\n target.data.slice(domOffset);\n MutationObserverMock.createMutation(this.view.dom, [\n {\n addedNodes: [],\n attributeName: null,\n attributeNamespace: null,\n nextSibling: null,\n oldValue,\n previousSibling: null,\n removedNodes: [],\n target,\n type: \"characterData\",\n },\n ]);\n }\n\n this.view.dispatchEvent(\n new KeyboardEvent(\"keyup\", {\n bubbles: true,\n charCode: character.charCodeAt(0),\n key,\n keyCode: character.charCodeAt(0),\n ...modifiers,\n }),\n );\n }\n }\n\n public selectText(selection: TesterSelection): void {\n this.view.dispatch(\n this.view.state.tr.setSelection(this.getSelection(selection)),\n );\n }\n\n private getSelection(selection: TesterSelection): Selection {\n if (selection === \"all\") {\n return new AllSelection(this.doc);\n }\n\n if (\n typeof selection === \"object\" &&\n \"$anchor\" in selection &&\n \"$head\" in selection\n ) {\n return selection;\n }\n\n if (\n typeof selection === \"object\" &&\n \"from\" in selection &&\n \"to\" in selection\n ) {\n return TextSelection.between(\n this.doc.resolve(selection.from),\n this.doc.resolve(selection.to),\n );\n }\n\n let pos = 0;\n if (selection === \"start\") {\n pos = 0;\n } else if (selection === \"end\") {\n pos = this.doc.nodeSize - 2;\n } else {\n pos = selection;\n }\n\n return TextSelection.near(this.doc.resolve(pos));\n }\n}\n\nfunction findLastCharacterDataNode(node: Node): CharacterData | null {\n if (node instanceof CharacterData) {\n return node;\n }\n for (const child of Array.from(node.childNodes).reverse()) {\n const textNode = findLastCharacterDataNode(child);\n if (textNode !== null) {\n return textNode;\n }\n }\n return null;\n}\n\nfunction keyToChar(key: string): string {\n if (key === \"Enter\") {\n return \"\\n\";\n }\n if (key === \"Tab\") {\n return \"\\t\";\n }\n return key;\n}\n","import type { Node } from \"prosemirror-model\";\n\nimport { expect } from \"vitest\";\n\nimport { stringifyProseMirrorNode } from \"./stringifyProseMirrorNode\";\n\nexport {\n type KeyboardModifiers,\n type Options,\n ProseMirrorTester,\n type TesterSelection,\n} from \"./ProseMirrorTester\";\n\nexport interface CustomMatchers<R = unknown> {\n toEqualProseMirrorNode(expected: Node): R;\n}\n\n/* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-explicit-any -- These are overridest for vitest matchers */\n\ndeclare module \"vitest\" {\n interface Assertion<T = any> extends CustomMatchers<T> {}\n interface AsymmetricMatchersContaining extends CustomMatchers {}\n}\n\n/* eslint-enable */\n\nexpect.extend({\n toEqualProseMirrorNode(received: Node, expected: Node) {\n const receivedDoc = `\\n${stringifyProseMirrorNode(received)}\\n`;\n const expectedDoc = `\\n${stringifyProseMirrorNode(expected)}\\n`;\n const pass = this.equals(receivedDoc, expectedDoc);\n const message = pass\n ? (): string =>\n `${this.utils.matcherHint(\".not.toEqualProsemirrorNode\")}\\n\\n` +\n `Expected value of document to not equal:\\n ${this.utils.printExpected(expectedDoc)}\\n` +\n `Actual:\\n ${this.utils.printReceived(receivedDoc)}`\n : (): string => {\n const diffString = this.utils.diff(expectedDoc, receivedDoc, {\n expand: this.expand ?? false,\n });\n return `${this.utils.matcherHint(\".toEqualProsemirrorNode\")}\\n\\nExpected value of document to equal:\\n${this.utils.printExpected(expectedDoc)}\\nActual:\\n${this.utils.printReceived(receivedDoc)}${diffString !== undefined ? `\\n\\nDifference:\\n\\n${diffString}` : \"\"}`;\n };\n return {\n message,\n pass,\n };\n },\n});\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-prosemirror",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "A plugin for Vitest that enables you to write tests using the ProseMirror editor",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vitest",
|
|
@@ -11,69 +11,72 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/marekdedic/vitest-prosemirror/issues"
|
|
13
13
|
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/marekdedic/vitest-prosemirror.git"
|
|
17
|
+
},
|
|
14
18
|
"license": "MIT",
|
|
15
19
|
"author": "Marek Dědič",
|
|
20
|
+
"sideEffects": true,
|
|
16
21
|
"type": "module",
|
|
17
|
-
"module": "dist/vitest-prosemirror.js",
|
|
18
|
-
"types": "dist/vitest-prosemirror.d.ts",
|
|
19
22
|
"exports": {
|
|
20
23
|
".": {
|
|
21
24
|
"import": "./dist/vitest-prosemirror.js"
|
|
22
25
|
}
|
|
23
26
|
},
|
|
24
|
-
"
|
|
27
|
+
"module": "dist/vitest-prosemirror.js",
|
|
28
|
+
"types": "dist/vitest-prosemirror.d.ts",
|
|
25
29
|
"files": [
|
|
26
|
-
"dist"
|
|
27
|
-
"LICENSE",
|
|
28
|
-
"README.md"
|
|
30
|
+
"dist"
|
|
29
31
|
],
|
|
30
|
-
"repository": {
|
|
31
|
-
"type": "git",
|
|
32
|
-
"url": "git+https://github.com/marekdedic/vitest-prosemirror.git"
|
|
33
|
-
},
|
|
34
32
|
"scripts": {
|
|
35
|
-
"clean": "rimraf dist/*",
|
|
36
33
|
"prebuild": "npm run clean",
|
|
37
34
|
"build": "vite build",
|
|
35
|
+
"clean": "rimraf dist/*",
|
|
36
|
+
"lint": "eslint",
|
|
38
37
|
"start": "vite build --watch",
|
|
39
|
-
"lint": "eslint --color 'src/**/*.ts' 'tests/**/*.ts' '*.config.{js,ts}'",
|
|
40
38
|
"test": "vitest",
|
|
41
39
|
"test-coverage": "vitest run --coverage"
|
|
42
40
|
},
|
|
43
|
-
"peerDependencies": {
|
|
44
|
-
"vitest": "^2.1.9 || ^3.0.7"
|
|
45
|
-
},
|
|
46
|
-
"peerDependenciesMeta": {
|
|
47
|
-
"vitest": {
|
|
48
|
-
"optional": true
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
41
|
"dependencies": {
|
|
52
42
|
"prosemirror-model": "^1.24.1",
|
|
53
43
|
"prosemirror-state": "^1.4.3",
|
|
54
44
|
"prosemirror-view": "^1.38.0",
|
|
55
|
-
"stringify-object": "^
|
|
56
|
-
"test-keyboard": "^2.0.7"
|
|
45
|
+
"stringify-object": "^6.0.0"
|
|
57
46
|
},
|
|
58
47
|
"devDependencies": {
|
|
59
48
|
"@eslint-community/eslint-plugin-eslint-comments": "^4.4.0",
|
|
60
49
|
"@eslint/js": "^9.9.1",
|
|
61
|
-
"@
|
|
50
|
+
"@eslint/json": "^0.13.0",
|
|
51
|
+
"@eslint/markdown": "^7.0.0",
|
|
52
|
+
"@types/node": "^24.0.2",
|
|
62
53
|
"@types/stringify-object": "^4.0.5",
|
|
63
|
-
"@vitest/coverage-v8": "^
|
|
64
|
-
"@vitest/eslint-plugin": "^1.
|
|
54
|
+
"@vitest/coverage-v8": "^4.0.4",
|
|
55
|
+
"@vitest/eslint-plugin": "^1.3.26",
|
|
65
56
|
"eslint": "^9.9.0",
|
|
66
57
|
"eslint-config-prettier": "^10.0.1",
|
|
58
|
+
"eslint-plugin-package-json": "^0.59.0",
|
|
67
59
|
"eslint-plugin-perfectionist": "^4.1.2",
|
|
68
|
-
"eslint-plugin-prefer-arrow-functions": "^3.
|
|
60
|
+
"eslint-plugin-prefer-arrow-functions": "^3.9.1",
|
|
69
61
|
"eslint-plugin-prettier": "^5.1.3",
|
|
70
|
-
"jsdom": "^
|
|
62
|
+
"jsdom": "^27.0.0",
|
|
71
63
|
"prettier": "^3.3.0",
|
|
64
|
+
"prosemirror-commands": "^1.7.1",
|
|
65
|
+
"prosemirror-inputrules": "^1.5.0",
|
|
66
|
+
"prosemirror-keymap": "^1.2.3",
|
|
72
67
|
"prosemirror-schema-basic": "^1.2.3",
|
|
73
68
|
"rimraf": "^6.0.1",
|
|
74
69
|
"typescript": "^5.3.3",
|
|
75
70
|
"typescript-eslint": "^8.2.0",
|
|
76
|
-
"vite": "^
|
|
71
|
+
"vite": "^7.0.0",
|
|
77
72
|
"vite-plugin-dts": "^4.5.1"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"vitest": "^2.1.9 || ^3.0.7 || ^4.0.4"
|
|
76
|
+
},
|
|
77
|
+
"peerDependenciesMeta": {
|
|
78
|
+
"vitest": {
|
|
79
|
+
"optional": true
|
|
80
|
+
}
|
|
78
81
|
}
|
|
79
82
|
}
|