@prosekit/core 0.7.1 → 0.7.3
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/_tsup-dts-rollup.d.ts +295 -152
- package/dist/{chunk-YWQGKV6X.js → chunk-UDQXAK7F.js} +379 -195
- package/dist/prosekit-core-test.js +66 -26
- package/dist/prosekit-core.d.ts +18 -1
- package/dist/prosekit-core.js +690 -327
- package/package.json +3 -3
@@ -1,12 +1,14 @@
|
|
1
1
|
// src/error.ts
|
2
2
|
var ProseKitError = class extends Error {
|
3
|
-
}
|
3
|
+
};
|
4
|
+
var EditorNotFoundError = class extends ProseKitError {
|
4
5
|
constructor() {
|
5
6
|
super(
|
6
7
|
"Unable to find editor. Pass it as an argument or call this function inside a ProseKit component."
|
7
8
|
);
|
8
9
|
}
|
9
|
-
}
|
10
|
+
};
|
11
|
+
var DOMDocumentNotFoundError = class extends ProseKitError {
|
10
12
|
constructor() {
|
11
13
|
super(
|
12
14
|
"Unable to find browser Document. When not in the browser environment, you need to pass a DOM Document."
|
@@ -17,10 +19,11 @@ var ProseKitError = class extends Error {
|
|
17
19
|
// src/utils/get-mark-type.ts
|
18
20
|
import "@prosekit/pm/model";
|
19
21
|
function getMarkType(schema, type) {
|
20
|
-
if (typeof type
|
21
|
-
|
22
|
-
if (!markType)
|
22
|
+
if (typeof type === "string") {
|
23
|
+
const markType = schema.marks[type];
|
24
|
+
if (!markType) {
|
23
25
|
throw new ProseKitError(`Cannot find mark type "${type}"`);
|
26
|
+
}
|
24
27
|
return markType;
|
25
28
|
}
|
26
29
|
return type;
|
@@ -28,27 +31,37 @@ function getMarkType(schema, type) {
|
|
28
31
|
|
29
32
|
// src/utils/assert.ts
|
30
33
|
function assert(condition, message = "Assertion failed") {
|
31
|
-
if (!condition)
|
34
|
+
if (!condition) {
|
32
35
|
throw new ProseKitError(message);
|
36
|
+
}
|
33
37
|
}
|
34
38
|
|
35
39
|
// src/utils/get-node-type.ts
|
36
40
|
import "@prosekit/pm/model";
|
37
41
|
function getNodeType(schema, type) {
|
38
|
-
if (typeof type
|
39
|
-
|
40
|
-
if (!nodeType)
|
42
|
+
if (typeof type === "string") {
|
43
|
+
const nodeType = schema.nodes[type];
|
44
|
+
if (!nodeType) {
|
41
45
|
throw new ProseKitError(`Cannot find ProseMirror node type "${type}"`);
|
46
|
+
}
|
42
47
|
return nodeType;
|
43
48
|
}
|
44
49
|
return type;
|
45
50
|
}
|
46
51
|
|
47
52
|
// src/types/priority.ts
|
48
|
-
var Priority = /* @__PURE__ */ ((Priority2) =>
|
53
|
+
var Priority = /* @__PURE__ */ ((Priority2) => {
|
54
|
+
Priority2[Priority2["lowest"] = 0] = "lowest";
|
55
|
+
Priority2[Priority2["low"] = 1] = "low";
|
56
|
+
Priority2[Priority2["default"] = 2] = "default";
|
57
|
+
Priority2[Priority2["high"] = 3] = "high";
|
58
|
+
Priority2[Priority2["highest"] = 4] = "highest";
|
59
|
+
return Priority2;
|
60
|
+
})(Priority || {});
|
49
61
|
|
50
62
|
// src/facets/facet.ts
|
51
|
-
var facetCount = 0
|
63
|
+
var facetCount = 0;
|
64
|
+
var Facet = class {
|
52
65
|
/**
|
53
66
|
* @internal
|
54
67
|
*/
|
@@ -59,7 +72,10 @@ var facetCount = 0, Facet = class {
|
|
59
72
|
* @internal
|
60
73
|
*/
|
61
74
|
this.index = facetCount++;
|
62
|
-
assert((_reduce || _reducer) && !(_reduce && _reducer))
|
75
|
+
assert((_reduce || _reducer) && !(_reduce && _reducer));
|
76
|
+
this.parent = parent;
|
77
|
+
this.singleton = singleton;
|
78
|
+
this.path = parent ? [...parent.path, this.index] : [];
|
63
79
|
}
|
64
80
|
get reducer() {
|
65
81
|
var _a, _b;
|
@@ -70,7 +86,7 @@ function defineFacet(options) {
|
|
70
86
|
var _a;
|
71
87
|
return new Facet(
|
72
88
|
options.parent,
|
73
|
-
(_a = options.singleton) != null ? _a :
|
89
|
+
(_a = options.singleton) != null ? _a : false,
|
74
90
|
options.reducer,
|
75
91
|
options.reduce
|
76
92
|
);
|
@@ -81,9 +97,12 @@ import "@prosekit/pm/model";
|
|
81
97
|
|
82
98
|
// src/utils/array.ts
|
83
99
|
function uniqPush(prev, next) {
|
84
|
-
|
85
|
-
for (
|
86
|
-
result.includes(item)
|
100
|
+
const result = [...prev];
|
101
|
+
for (const item of next) {
|
102
|
+
if (!result.includes(item)) {
|
103
|
+
result.push(item);
|
104
|
+
}
|
105
|
+
}
|
87
106
|
return result;
|
88
107
|
}
|
89
108
|
function arraySubstract(a, b) {
|
@@ -110,29 +129,35 @@ function zip5(a, b, mapper) {
|
|
110
129
|
];
|
111
130
|
}
|
112
131
|
function unionInput(a, b) {
|
113
|
-
|
132
|
+
if (!a && !b) return null;
|
133
|
+
return uniqPush(a != null ? a : [], b != null ? b : []);
|
114
134
|
}
|
115
135
|
function subtractInput(a, b) {
|
116
|
-
|
136
|
+
if (!a) return null;
|
137
|
+
if (!b) return [...a];
|
138
|
+
return arraySubstract(a, b);
|
117
139
|
}
|
118
140
|
function unionChildren(a, b) {
|
119
|
-
|
120
|
-
for (
|
121
|
-
|
141
|
+
const merged = new Map(a);
|
142
|
+
for (const [key, valueB] of b.entries()) {
|
143
|
+
const valueA = a.get(key);
|
122
144
|
merged.set(key, valueA ? unionFacetNode(valueA, valueB) : valueB);
|
123
145
|
}
|
124
146
|
return merged;
|
125
147
|
}
|
126
148
|
function subtractChildren(a, b) {
|
127
|
-
|
128
|
-
for (
|
129
|
-
|
130
|
-
|
149
|
+
const merged = new Map(a);
|
150
|
+
for (const [key, valueB] of b.entries()) {
|
151
|
+
const valueA = a.get(key);
|
152
|
+
if (valueA) {
|
153
|
+
merged.set(key, subtractFacetNode(valueA, valueB));
|
154
|
+
}
|
131
155
|
}
|
132
156
|
return merged;
|
133
157
|
}
|
134
158
|
function unionFacetNode(a, b) {
|
135
|
-
|
159
|
+
assert(a.facet === b.facet);
|
160
|
+
return new FacetNode(
|
136
161
|
a.facet,
|
137
162
|
zip5(a.inputs, b.inputs, unionInput),
|
138
163
|
unionChildren(a.children, b.children),
|
@@ -140,7 +165,8 @@ function unionFacetNode(a, b) {
|
|
140
165
|
);
|
141
166
|
}
|
142
167
|
function subtractFacetNode(a, b) {
|
143
|
-
|
168
|
+
assert(a.facet === b.facet);
|
169
|
+
return new FacetNode(
|
144
170
|
a.facet,
|
145
171
|
zip5(a.inputs, b.inputs, subtractInput),
|
146
172
|
subtractChildren(a.children, b.children),
|
@@ -163,39 +189,53 @@ var FacetNode = class {
|
|
163
189
|
}
|
164
190
|
calcOutput() {
|
165
191
|
var _a, _b, _c;
|
166
|
-
|
192
|
+
const inputs = [null, null, null, null, null];
|
193
|
+
const output = [null, null, null, null, null];
|
167
194
|
for (let pri = 0; pri < 5; pri++) {
|
168
|
-
|
169
|
-
|
195
|
+
const input = this.inputs[pri];
|
196
|
+
if (input) {
|
197
|
+
inputs[pri] = [...input];
|
198
|
+
}
|
170
199
|
}
|
171
|
-
for (
|
172
|
-
|
173
|
-
for (let pri = 0; pri < 5; pri++)
|
174
|
-
|
200
|
+
for (const child of this.children.values()) {
|
201
|
+
const childOutput = child.getOutput();
|
202
|
+
for (let pri = 0; pri < 5; pri++) {
|
203
|
+
if (childOutput[pri]) {
|
204
|
+
const input = inputs[pri] || (inputs[pri] = []);
|
205
|
+
input.push(childOutput[pri]);
|
206
|
+
}
|
207
|
+
}
|
175
208
|
}
|
176
209
|
if (this.facet.singleton) {
|
177
|
-
|
210
|
+
const reducer = (_a = this.reducers)[_b = 2 /* default */] || (_a[_b] = this.facet.reducer);
|
211
|
+
const input = inputs.filter(isNotNull).flat();
|
178
212
|
output[2 /* default */] = reducer(input);
|
179
|
-
} else
|
213
|
+
} else {
|
180
214
|
for (let pri = 0; pri < 5; pri++) {
|
181
|
-
|
215
|
+
const input = inputs[pri];
|
182
216
|
if (input) {
|
183
|
-
|
217
|
+
const reducer = (_c = this.reducers)[pri] || (_c[pri] = this.facet.reducer);
|
184
218
|
output[pri] = reducer(input);
|
185
219
|
}
|
186
220
|
}
|
221
|
+
}
|
187
222
|
return output;
|
188
223
|
}
|
189
224
|
getOutput() {
|
190
|
-
|
225
|
+
if (!this.output) {
|
226
|
+
this.output = this.calcOutput();
|
227
|
+
}
|
228
|
+
return this.output;
|
191
229
|
}
|
192
230
|
getSingletonOutput() {
|
193
|
-
|
231
|
+
assert(this.facet.singleton);
|
232
|
+
return this.getOutput()[2 /* default */];
|
194
233
|
}
|
195
234
|
getRootOutput() {
|
196
235
|
assert(this.isRoot());
|
197
|
-
|
198
|
-
|
236
|
+
const output = this.getSingletonOutput();
|
237
|
+
assert(output);
|
238
|
+
return output;
|
199
239
|
}
|
200
240
|
isRoot() {
|
201
241
|
return !this.facet.parent;
|
@@ -208,15 +248,22 @@ import { Schema as Schema3 } from "@prosekit/pm/model";
|
|
208
248
|
// src/facets/root.ts
|
209
249
|
function rootReducer(inputs) {
|
210
250
|
var _a;
|
211
|
-
let schema
|
212
|
-
|
213
|
-
|
214
|
-
let
|
251
|
+
let schema;
|
252
|
+
let commands;
|
253
|
+
let stateFunc;
|
254
|
+
let view;
|
255
|
+
for (const input of inputs) {
|
256
|
+
schema = input.schema || schema;
|
257
|
+
commands = input.commands || commands;
|
258
|
+
stateFunc = input.state || stateFunc;
|
259
|
+
view = input.view || view;
|
260
|
+
}
|
261
|
+
const state = schema && ((_a = stateFunc == null ? void 0 : stateFunc({ schema })) != null ? _a : { schema });
|
215
262
|
return { schema, state, commands, view };
|
216
263
|
}
|
217
264
|
var rootFacet = new Facet(
|
218
265
|
null,
|
219
|
-
|
266
|
+
true,
|
220
267
|
rootReducer
|
221
268
|
);
|
222
269
|
|
@@ -224,11 +271,12 @@ var rootFacet = new Facet(
|
|
224
271
|
var schemaFacet = defineFacet({
|
225
272
|
reducer: (specs) => {
|
226
273
|
assert(specs.length <= 1);
|
227
|
-
|
228
|
-
|
274
|
+
const spec = specs[0];
|
275
|
+
const schema = spec ? new Schema3(spec) : null;
|
276
|
+
return { schema };
|
229
277
|
},
|
230
278
|
parent: rootFacet,
|
231
|
-
singleton:
|
279
|
+
singleton: true
|
232
280
|
});
|
233
281
|
|
234
282
|
// src/facets/base-extension.ts
|
@@ -242,7 +290,7 @@ var BaseExtension = class {
|
|
242
290
|
*/
|
243
291
|
getTree(priority) {
|
244
292
|
var _a, _b;
|
245
|
-
|
293
|
+
const pri = (_a = priority != null ? priority : this.priority) != null ? _a : 2 /* default */;
|
246
294
|
return (_b = this.trees)[pri] || (_b[pri] = this.createTree(pri));
|
247
295
|
}
|
248
296
|
/**
|
@@ -251,13 +299,14 @@ var BaseExtension = class {
|
|
251
299
|
findFacetOutput(facet) {
|
252
300
|
var _a;
|
253
301
|
let node = this.getTree();
|
254
|
-
for (
|
302
|
+
for (const index of facet.path) {
|
255
303
|
node = node == null ? void 0 : node.children.get(index);
|
304
|
+
}
|
256
305
|
return (_a = node == null ? void 0 : node.getOutput()) != null ? _a : null;
|
257
306
|
}
|
258
307
|
get schema() {
|
259
308
|
var _a, _b;
|
260
|
-
|
309
|
+
const output = this.findFacetOutput(schemaFacet);
|
261
310
|
return (_b = (_a = output == null ? void 0 : output.find(Boolean)) == null ? void 0 : _a.schema) != null ? _b : null;
|
262
311
|
}
|
263
312
|
};
|
@@ -277,11 +326,12 @@ var FacetExtensionImpl = class extends BaseExtension {
|
|
277
326
|
*/
|
278
327
|
createTree(priority) {
|
279
328
|
var _a;
|
280
|
-
|
329
|
+
const pri = (_a = this.priority) != null ? _a : priority;
|
330
|
+
const inputs = [null, null, null, null, null];
|
281
331
|
inputs[pri] = [...this.payloads];
|
282
332
|
let node = new FacetNode(this.facet, inputs);
|
283
|
-
|
284
|
-
|
333
|
+
while (node.facet.parent) {
|
334
|
+
const children = /* @__PURE__ */ new Map([[node.facet.index, node]]);
|
285
335
|
node = new FacetNode(node.facet.parent, void 0, children);
|
286
336
|
}
|
287
337
|
return node;
|
@@ -297,16 +347,20 @@ import { EditorState } from "@prosekit/pm/state";
|
|
297
347
|
|
298
348
|
// src/utils/get-dom-api.ts
|
299
349
|
function findGlobalBrowserDocument() {
|
300
|
-
if (typeof document
|
350
|
+
if (typeof document !== "undefined") {
|
301
351
|
return document;
|
302
|
-
|
352
|
+
}
|
353
|
+
if (typeof globalThis !== "undefined" && globalThis.document) {
|
303
354
|
return globalThis.document;
|
355
|
+
}
|
304
356
|
}
|
305
357
|
function findGlobalBrowserWindow() {
|
306
|
-
if (typeof window
|
358
|
+
if (typeof window !== "undefined") {
|
307
359
|
return window;
|
308
|
-
|
360
|
+
}
|
361
|
+
if (typeof globalThis !== "undefined" && globalThis.window) {
|
309
362
|
return globalThis.window;
|
363
|
+
}
|
310
364
|
}
|
311
365
|
function findBrowserDocument(options) {
|
312
366
|
var _a, _b, _c;
|
@@ -317,12 +371,12 @@ function findBrowserWindow(options) {
|
|
317
371
|
return (_d = (_b = (_a = options == null ? void 0 : options.document) == null ? void 0 : _a.defaultView) != null ? _b : findGlobalBrowserWindow()) != null ? _d : (_c = findBrowserDocument(options)) == null ? void 0 : _c.defaultView;
|
318
372
|
}
|
319
373
|
function getBrowserDocument(options) {
|
320
|
-
|
374
|
+
const doc = findBrowserDocument(options);
|
321
375
|
if (doc) return doc;
|
322
376
|
throw new DOMDocumentNotFoundError();
|
323
377
|
}
|
324
378
|
function getBrowserWindow(options) {
|
325
|
-
|
379
|
+
const win = findBrowserWindow(options);
|
326
380
|
if (win) return win;
|
327
381
|
throw new DOMDocumentNotFoundError();
|
328
382
|
}
|
@@ -341,20 +395,28 @@ function nodeFromJSON(json, options) {
|
|
341
395
|
return options.schema.nodeFromJSON(json);
|
342
396
|
}
|
343
397
|
function nodeFromElement(element, options) {
|
344
|
-
|
398
|
+
const { DOMParser: CustomDOMParser, schema, ...parseOptions } = options;
|
345
399
|
return (CustomDOMParser || DOMParser).fromSchema(schema).parse(element, parseOptions);
|
346
400
|
}
|
347
401
|
function elementFromNode(node, options) {
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
402
|
+
const Serializer = (options == null ? void 0 : options.DOMSerializer) || DOMSerializer;
|
403
|
+
const document2 = getBrowserDocument(options);
|
404
|
+
const schema = node.type.schema;
|
405
|
+
const serializer = Serializer.fromSchema(schema);
|
406
|
+
if (schema.topNodeType !== node.type) {
|
407
|
+
return serializer.serializeNode(node, { document: document2 });
|
408
|
+
} else {
|
409
|
+
return serializer.serializeFragment(
|
410
|
+
node.content,
|
411
|
+
{ document: document2 },
|
412
|
+
document2.createElement("div")
|
413
|
+
);
|
414
|
+
}
|
354
415
|
}
|
355
416
|
function elementFromHTML(html, options) {
|
356
|
-
|
357
|
-
|
417
|
+
const win = getBrowserWindow(options);
|
418
|
+
const parser = new win.DOMParser();
|
419
|
+
return parser.parseFromString(`<body><div>${html}</div></body>`, "text/html").body.firstElementChild;
|
358
420
|
}
|
359
421
|
function htmlFromElement(element) {
|
360
422
|
return element.outerHTML;
|
@@ -384,25 +446,37 @@ import { Selection } from "@prosekit/pm/state";
|
|
384
446
|
// src/facets/state.ts
|
385
447
|
var stateFacet = defineFacet({
|
386
448
|
reduce: () => {
|
387
|
-
let callbacks = []
|
449
|
+
let callbacks = [];
|
450
|
+
const state = (ctx) => {
|
388
451
|
var _a, _b, _c, _d, _e, _f;
|
389
|
-
|
452
|
+
const configs = callbacks.map((cb) => cb(ctx));
|
453
|
+
const config = {
|
390
454
|
schema: ctx.schema,
|
391
455
|
storedMarks: [],
|
392
456
|
plugins: []
|
393
457
|
};
|
394
|
-
for (
|
395
|
-
config.schema = (_a = config.schema) != null ? _a : c.schema
|
396
|
-
|
458
|
+
for (const c of configs) {
|
459
|
+
config.schema = (_a = config.schema) != null ? _a : c.schema;
|
460
|
+
config.doc = (_b = config.doc) != null ? _b : c.doc;
|
461
|
+
config.selection = (_c = config.selection) != null ? _c : c.selection;
|
462
|
+
config.storedMarks = [...config.storedMarks, ...(_d = c.storedMarks) != null ? _d : []];
|
463
|
+
config.plugins = uniqPush((_e = config.plugins) != null ? _e : [], (_f = c.plugins) != null ? _f : []);
|
464
|
+
}
|
465
|
+
assert(
|
397
466
|
config.doc || config.schema,
|
398
467
|
"Can't create state without a schema nor a document"
|
399
|
-
)
|
468
|
+
);
|
469
|
+
if (config.doc) {
|
470
|
+
config.schema = void 0;
|
471
|
+
}
|
472
|
+
return config;
|
400
473
|
};
|
401
|
-
return function(inputs) {
|
402
|
-
|
474
|
+
return function reducer(inputs) {
|
475
|
+
callbacks = inputs;
|
476
|
+
return { state };
|
403
477
|
};
|
404
478
|
},
|
405
|
-
singleton:
|
479
|
+
singleton: true,
|
406
480
|
parent: rootFacet
|
407
481
|
});
|
408
482
|
|
@@ -412,31 +486,53 @@ function defineDefaultState({
|
|
412
486
|
defaultHTML,
|
413
487
|
defaultSelection
|
414
488
|
}) {
|
415
|
-
if (defaultHTML && defaultDoc)
|
489
|
+
if (defaultHTML && defaultDoc) {
|
416
490
|
throw new ProseKitError(
|
417
491
|
"Only one of defaultHTML and defaultDoc can be provided"
|
418
492
|
);
|
493
|
+
}
|
419
494
|
return defineFacetPayload(stateFacet, [
|
420
495
|
({ schema }) => {
|
421
|
-
|
422
|
-
|
496
|
+
const config = {};
|
497
|
+
if (defaultHTML) {
|
498
|
+
if (typeof defaultHTML === "string") {
|
499
|
+
defaultDoc = jsonFromHTML(defaultHTML, { schema });
|
500
|
+
} else {
|
501
|
+
defaultDoc = jsonFromElement(defaultHTML, { schema });
|
502
|
+
}
|
503
|
+
}
|
504
|
+
if (defaultDoc) {
|
505
|
+
config.doc = schema.nodeFromJSON(defaultDoc);
|
506
|
+
if (defaultSelection) {
|
507
|
+
config.selection = Selection.fromJSON(config.doc, defaultSelection);
|
508
|
+
}
|
509
|
+
}
|
510
|
+
return config;
|
423
511
|
}
|
424
512
|
]);
|
425
513
|
}
|
426
514
|
|
427
515
|
// src/utils/is-mark-absent.ts
|
428
516
|
function isMarkAbsent(node, from, to, markType, attrs) {
|
429
|
-
|
430
|
-
|
431
|
-
|
517
|
+
const mark = attrs ? markType.create(attrs) : markType;
|
518
|
+
let missing = false;
|
519
|
+
node.nodesBetween(from, to, (node2, pos, parent) => {
|
520
|
+
if (missing) return false;
|
432
521
|
missing = !mark.isInSet(node2.marks) && !!parent && parent.type.allowsMarkType(markType);
|
433
|
-
})
|
522
|
+
});
|
523
|
+
return missing;
|
434
524
|
}
|
435
525
|
|
436
526
|
// src/utils/is-mark-active.ts
|
437
527
|
function isMarkActive(state, type, attrs) {
|
438
|
-
|
439
|
-
|
528
|
+
const { from, $from, to, empty } = state.selection;
|
529
|
+
const markType = getMarkType(state.schema, type);
|
530
|
+
if (empty) {
|
531
|
+
const mark = attrs ? markType.create(attrs) : markType;
|
532
|
+
return !!mark.isInSet(state.storedMarks || $from.marks());
|
533
|
+
} else {
|
534
|
+
return !isMarkAbsent(state.doc, from, to, markType, attrs);
|
535
|
+
}
|
440
536
|
}
|
441
537
|
|
442
538
|
// src/utils/type-assertion.ts
|
@@ -476,24 +572,27 @@ var UnionExtensionImpl = class extends BaseExtension {
|
|
476
572
|
*/
|
477
573
|
createTree(priority) {
|
478
574
|
var _a;
|
479
|
-
|
575
|
+
const pri = (_a = this.priority) != null ? _a : priority;
|
576
|
+
const extensions = [...this.extension];
|
480
577
|
extensions.sort((a, b) => {
|
481
578
|
var _a2, _b;
|
482
579
|
return ((_a2 = a.priority) != null ? _a2 : pri) - ((_b = b.priority) != null ? _b : pri);
|
483
580
|
});
|
484
|
-
|
581
|
+
const children = extensions.map((ext) => ext.getTree(pri));
|
485
582
|
assert(children.length > 0);
|
486
583
|
let node = children[0];
|
487
|
-
for (let i = 1; i < children.length; i++)
|
584
|
+
for (let i = 1; i < children.length; i++) {
|
488
585
|
node = unionFacetNode(node, children[i]);
|
586
|
+
}
|
489
587
|
return node;
|
490
588
|
}
|
491
589
|
};
|
492
590
|
|
493
591
|
// src/editor/union.ts
|
494
592
|
function union(extension) {
|
495
|
-
|
496
|
-
|
593
|
+
const array = Array.isArray(extension) ? extension : [extension];
|
594
|
+
assert(array.length > 0, "At least one extension is required");
|
595
|
+
return new UnionExtensionImpl(
|
497
596
|
array
|
498
597
|
);
|
499
598
|
}
|
@@ -506,19 +605,24 @@ import { EditorView } from "@prosekit/pm/view";
|
|
506
605
|
// src/utils/deep-equals.ts
|
507
606
|
import OrderedMap from "orderedmap";
|
508
607
|
function deepEquals(a, b) {
|
509
|
-
if (a === b)
|
510
|
-
return
|
511
|
-
|
512
|
-
|
513
|
-
|
608
|
+
if (a === b) {
|
609
|
+
return true;
|
610
|
+
}
|
611
|
+
if (!a || !b) {
|
612
|
+
return false;
|
613
|
+
}
|
614
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
514
615
|
return a.length === b.length && a.every((x, i) => deepEquals(x, b[i]));
|
515
|
-
|
616
|
+
}
|
617
|
+
if (a instanceof OrderedMap && b instanceof OrderedMap) {
|
516
618
|
return a.size === b.size && deepEquals(a.toObject(), b.toObject());
|
517
|
-
|
518
|
-
|
619
|
+
}
|
620
|
+
if (typeof a === "object" && typeof b === "object") {
|
621
|
+
const aKeys = Object.keys(a);
|
622
|
+
const bKeys = Object.keys(b);
|
519
623
|
return aKeys.length === bKeys.length && aKeys.every((key) => deepEquals(a[key], b[key]));
|
520
624
|
}
|
521
|
-
return
|
625
|
+
return false;
|
522
626
|
}
|
523
627
|
|
524
628
|
// src/editor/builder.ts
|
@@ -526,95 +630,122 @@ import "@prosekit/pm/model";
|
|
526
630
|
|
527
631
|
// src/utils/attrs-match.ts
|
528
632
|
function attrsMatch(nodeOrMark, attrs) {
|
529
|
-
|
530
|
-
for (
|
531
|
-
if (currentAttrs[key] !== value)
|
532
|
-
return
|
533
|
-
|
633
|
+
const currentAttrs = nodeOrMark.attrs;
|
634
|
+
for (const [key, value] of Object.entries(attrs)) {
|
635
|
+
if (currentAttrs[key] !== value) {
|
636
|
+
return false;
|
637
|
+
}
|
638
|
+
}
|
639
|
+
return true;
|
534
640
|
}
|
535
641
|
|
536
642
|
// src/utils/is-node-active.ts
|
537
643
|
function isNodeActive(state, type, attrs) {
|
538
|
-
|
644
|
+
const $pos = state.selection.$from;
|
645
|
+
const nodeType = getNodeType(state.schema, type);
|
539
646
|
for (let depth = $pos.depth; depth >= 0; depth--) {
|
540
|
-
|
541
|
-
if (node.type === nodeType && (!attrs || attrsMatch(node, attrs)))
|
542
|
-
return
|
647
|
+
const node = $pos.node(depth);
|
648
|
+
if (node.type === nodeType && (!attrs || attrsMatch(node, attrs))) {
|
649
|
+
return true;
|
650
|
+
}
|
543
651
|
}
|
544
|
-
return
|
652
|
+
return false;
|
545
653
|
}
|
546
654
|
|
547
655
|
// src/editor/builder.ts
|
548
656
|
function createNodeBuilders(schema, getState, createNode = defaultCreateNode) {
|
549
|
-
|
550
|
-
for (
|
551
|
-
|
657
|
+
const builders = {};
|
658
|
+
for (const type of Object.values(schema.nodes)) {
|
659
|
+
const builder = (...args) => buildNode(type, args, createNode);
|
552
660
|
builder.isActive = (attrs) => {
|
553
|
-
|
554
|
-
return state ? isNodeActive(state, type, attrs) :
|
555
|
-
}
|
661
|
+
const state = getState();
|
662
|
+
return state ? isNodeActive(state, type, attrs) : false;
|
663
|
+
};
|
664
|
+
builders[type.name] = builder;
|
556
665
|
}
|
557
666
|
return builders;
|
558
667
|
}
|
559
668
|
function createMarkBuilders(schema, getState, applyMark = defaultApplyMark) {
|
560
|
-
|
561
|
-
for (
|
562
|
-
|
669
|
+
const builders = {};
|
670
|
+
for (const type of Object.values(schema.marks)) {
|
671
|
+
const builder = (...args) => buildMark(type, args, applyMark);
|
563
672
|
builder.isActive = (attrs) => {
|
564
|
-
|
565
|
-
return state ? isMarkActive(state, type, attrs) :
|
566
|
-
}
|
673
|
+
const state = getState();
|
674
|
+
return state ? isMarkActive(state, type, attrs) : false;
|
675
|
+
};
|
676
|
+
builders[type.name] = builder;
|
567
677
|
}
|
568
678
|
return builders;
|
569
679
|
}
|
570
680
|
function buildMark(type, args, applyMark) {
|
571
|
-
|
681
|
+
const [attrs, children] = normalizeArgs(args);
|
682
|
+
const mark = type.create(attrs);
|
572
683
|
return applyMark(mark, flattenChildren(type.schema, children));
|
573
684
|
}
|
574
|
-
var defaultApplyMark = (mark, children) =>
|
685
|
+
var defaultApplyMark = (mark, children) => {
|
686
|
+
return children.map((child) => child.mark([mark]));
|
687
|
+
};
|
575
688
|
function buildNode(type, args, createNode) {
|
576
|
-
|
689
|
+
const [attrs, children] = normalizeArgs(args);
|
577
690
|
return createNode(type, attrs, flattenChildren(type.schema, children));
|
578
691
|
}
|
579
692
|
var defaultCreateNode = (type, attrs, children) => {
|
580
|
-
|
581
|
-
|
693
|
+
const node = type.createAndFill(attrs, children);
|
694
|
+
assert(node, `Failed to create node ${type.name}`);
|
695
|
+
return node;
|
582
696
|
};
|
583
697
|
function flattenChildren(schema, children) {
|
584
|
-
|
585
|
-
for (
|
586
|
-
if (typeof child
|
587
|
-
|
588
|
-
|
698
|
+
const nodes = [];
|
699
|
+
for (const child of children) {
|
700
|
+
if (typeof child === "string") {
|
701
|
+
if (child) {
|
702
|
+
nodes.push(schema.text(child, null));
|
703
|
+
}
|
704
|
+
} else if (Array.isArray(child)) {
|
589
705
|
nodes.push(...flattenChildren(schema, child));
|
590
|
-
else if (isProseMirrorNode(child))
|
706
|
+
} else if (isProseMirrorNode(child)) {
|
591
707
|
nodes.push(child);
|
592
|
-
else
|
708
|
+
} else {
|
593
709
|
throw new ProseKitError(`Invalid node child: ${typeof child}`);
|
710
|
+
}
|
711
|
+
}
|
594
712
|
return nodes;
|
595
713
|
}
|
596
714
|
function normalizeArgs(args) {
|
597
|
-
|
598
|
-
|
715
|
+
const [attrs, ...children] = args;
|
716
|
+
if (isNodeChild(attrs)) {
|
717
|
+
children.unshift(attrs);
|
718
|
+
return [null, children];
|
719
|
+
} else if (typeof attrs === "object") {
|
720
|
+
return [attrs, children];
|
721
|
+
} else {
|
722
|
+
return [null, children];
|
723
|
+
}
|
599
724
|
}
|
600
725
|
function isNodeChild(value) {
|
601
|
-
|
726
|
+
if (!value) {
|
727
|
+
return false;
|
728
|
+
}
|
729
|
+
return typeof value === "string" || Array.isArray(value) || isProseMirrorNode(value);
|
602
730
|
}
|
603
731
|
|
604
732
|
// src/editor/editor.ts
|
605
733
|
function setupEditorExtension(options) {
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
734
|
+
const { defaultDoc, defaultHTML, defaultSelection } = options;
|
735
|
+
if (defaultDoc || defaultHTML) {
|
736
|
+
return union([
|
737
|
+
options.extension,
|
738
|
+
defineDefaultState({
|
739
|
+
defaultDoc,
|
740
|
+
defaultHTML,
|
741
|
+
defaultSelection
|
742
|
+
})
|
743
|
+
]);
|
744
|
+
}
|
745
|
+
return options.extension;
|
615
746
|
}
|
616
747
|
function createEditor(options) {
|
617
|
-
|
748
|
+
const extension = setupEditorExtension(options);
|
618
749
|
return Editor.create(new EditorInstance(extension));
|
619
750
|
}
|
620
751
|
var EditorInstance = class {
|
@@ -626,97 +757,139 @@ var EditorInstance = class {
|
|
626
757
|
return ((_a = this.view) == null ? void 0 : _a.state) || this.directEditorProps.state;
|
627
758
|
};
|
628
759
|
this.tree = extension.getTree();
|
629
|
-
|
760
|
+
const payload = this.tree.getRootOutput();
|
761
|
+
const schema = payload.schema;
|
762
|
+
const stateConfig = payload.state;
|
630
763
|
assert(schema && stateConfig, "Schema must be defined");
|
631
|
-
|
632
|
-
if (payload.commands)
|
633
|
-
for (
|
764
|
+
const state = EditorState2.create(stateConfig);
|
765
|
+
if (payload.commands) {
|
766
|
+
for (const [name, commandCreator] of Object.entries(payload.commands)) {
|
634
767
|
this.defineCommand(name, commandCreator);
|
635
|
-
|
768
|
+
}
|
769
|
+
}
|
770
|
+
this.nodeBuilders = createNodeBuilders(state.schema, this.getState);
|
771
|
+
this.markBuilders = createMarkBuilders(state.schema, this.getState);
|
772
|
+
this.schema = state.schema;
|
773
|
+
this.directEditorProps = { state, ...payload.view };
|
636
774
|
}
|
637
775
|
updateState(state) {
|
638
|
-
|
776
|
+
if (this.view) {
|
777
|
+
this.view.updateState(state);
|
778
|
+
} else {
|
779
|
+
this.directEditorProps.state = state;
|
780
|
+
}
|
639
781
|
}
|
640
782
|
updateExtension(extension, add) {
|
641
783
|
var _a, _b, _c, _d;
|
642
|
-
|
643
|
-
if (!view || view.isDestroyed)
|
784
|
+
const view = this.view;
|
785
|
+
if (!view || view.isDestroyed) {
|
644
786
|
return;
|
645
|
-
|
646
|
-
|
787
|
+
}
|
788
|
+
const tree = extension.getTree();
|
789
|
+
const payload = tree.getRootOutput();
|
790
|
+
if (payload == null ? void 0 : payload.schema) {
|
647
791
|
throw new ProseKitError("Schema cannot be changed");
|
648
|
-
|
792
|
+
}
|
793
|
+
if (payload == null ? void 0 : payload.view) {
|
649
794
|
throw new ProseKitError("View cannot be changed");
|
650
|
-
|
795
|
+
}
|
796
|
+
const oldPayload = this.tree.getRootOutput();
|
797
|
+
const oldPlugins = [...(_b = (_a = view.state) == null ? void 0 : _a.plugins) != null ? _b : []];
|
651
798
|
this.tree = add ? unionFacetNode(this.tree, tree) : subtractFacetNode(this.tree, tree);
|
652
|
-
|
799
|
+
const newPayload = this.tree.getRootOutput();
|
800
|
+
const newPlugins = [...(_d = (_c = newPayload == null ? void 0 : newPayload.state) == null ? void 0 : _c.plugins) != null ? _d : []];
|
653
801
|
if (!deepEquals(oldPlugins, newPlugins)) {
|
654
|
-
|
802
|
+
const state = view.state.reconfigure({ plugins: newPlugins });
|
655
803
|
view.updateState(state);
|
656
804
|
}
|
657
|
-
if (newPayload
|
658
|
-
|
659
|
-
|
805
|
+
if ((newPayload == null ? void 0 : newPayload.commands) && !deepEquals(oldPayload == null ? void 0 : oldPayload.commands, newPayload == null ? void 0 : newPayload.commands)) {
|
806
|
+
const commands = newPayload.commands;
|
807
|
+
const names = Object.keys(commands);
|
808
|
+
for (const name of names) {
|
660
809
|
this.defineCommand(name, commands[name]);
|
810
|
+
}
|
661
811
|
}
|
662
812
|
}
|
663
813
|
mount(place) {
|
664
|
-
if (this.view)
|
814
|
+
if (this.view) {
|
665
815
|
throw new ProseKitError("Editor is already mounted");
|
666
|
-
|
816
|
+
}
|
817
|
+
if (!place) {
|
667
818
|
throw new ProseKitError("Can't mount editor without a place");
|
819
|
+
}
|
668
820
|
this.view = new EditorView({ mount: place }, this.directEditorProps);
|
669
821
|
}
|
670
822
|
unmount() {
|
671
|
-
if (!this.view)
|
823
|
+
if (!this.view) {
|
672
824
|
throw new ProseKitError("Editor is not mounted yet");
|
673
|
-
|
825
|
+
}
|
826
|
+
this.directEditorProps.state = this.view.state;
|
827
|
+
this.view.destroy();
|
828
|
+
this.view = null;
|
674
829
|
}
|
675
830
|
get mounted() {
|
676
831
|
return !!this.view && !this.view.isDestroyed;
|
677
832
|
}
|
678
833
|
get assertView() {
|
679
|
-
if (!this.view)
|
834
|
+
if (!this.view) {
|
680
835
|
throw new ProseKitError("Editor is not mounted");
|
836
|
+
}
|
681
837
|
return this.view;
|
682
838
|
}
|
683
839
|
definePlugins(plugins) {
|
684
|
-
|
840
|
+
const view = this.assertView;
|
841
|
+
const state = view.state;
|
842
|
+
const newPlugins = [...plugins, ...state.plugins];
|
843
|
+
const newState = state.reconfigure({ plugins: newPlugins });
|
685
844
|
view.setProps({ state: newState });
|
686
845
|
}
|
687
846
|
removePlugins(plugins) {
|
688
|
-
|
847
|
+
const view = this.view;
|
689
848
|
if (!view) return;
|
690
|
-
|
849
|
+
const state = view.state;
|
850
|
+
const newPlugins = state.plugins.filter((p) => !plugins.includes(p));
|
851
|
+
const newState = state.reconfigure({ plugins: newPlugins });
|
691
852
|
view.setProps({ state: newState });
|
692
853
|
}
|
693
854
|
defineCommand(name, commandCreator) {
|
694
|
-
|
695
|
-
|
696
|
-
|
855
|
+
const applier = (...args) => {
|
856
|
+
const view = this.view;
|
857
|
+
assert(view, `Cannot call command "${name}" before the editor is mounted`);
|
858
|
+
const command = commandCreator(...args);
|
859
|
+
return command(view.state, view.dispatch.bind(view), view);
|
697
860
|
};
|
698
861
|
applier.canApply = (...args) => {
|
699
|
-
|
700
|
-
|
701
|
-
|
862
|
+
const view = this.view;
|
863
|
+
if (!view) {
|
864
|
+
return false;
|
865
|
+
}
|
866
|
+
const command = commandCreator(...args);
|
867
|
+
return command(view.state, void 0, view);
|
868
|
+
};
|
869
|
+
this.commandAppliers[name] = applier;
|
702
870
|
}
|
703
871
|
removeCommand(name) {
|
704
872
|
delete this.commandAppliers[name];
|
705
873
|
}
|
706
|
-
}
|
874
|
+
};
|
875
|
+
var Editor = class _Editor {
|
707
876
|
/**
|
708
877
|
* @internal
|
709
878
|
*/
|
710
879
|
constructor(instance) {
|
711
880
|
this.afterMounted = [];
|
712
|
-
this.instance = instance
|
881
|
+
this.instance = instance;
|
882
|
+
this.mount = this.mount.bind(this);
|
883
|
+
this.unmount = this.unmount.bind(this);
|
884
|
+
this.use = this.use.bind(this);
|
713
885
|
}
|
714
886
|
/**
|
715
887
|
* @internal
|
716
888
|
*/
|
717
889
|
static create(instance) {
|
718
|
-
if (!(instance instanceof EditorInstance))
|
890
|
+
if (!(instance instanceof EditorInstance)) {
|
719
891
|
throw new TypeError("Invalid EditorInstance");
|
892
|
+
}
|
720
893
|
return new _Editor(instance);
|
721
894
|
}
|
722
895
|
/**
|
@@ -748,36 +921,40 @@ var EditorInstance = class {
|
|
748
921
|
*/
|
749
922
|
get focused() {
|
750
923
|
var _a, _b;
|
751
|
-
return (_b = (_a = this.instance.view) == null ? void 0 : _a.hasFocus()) != null ? _b :
|
924
|
+
return (_b = (_a = this.instance.view) == null ? void 0 : _a.hasFocus()) != null ? _b : false;
|
752
925
|
}
|
753
926
|
/**
|
754
927
|
* Mount the editor to the given HTML element.
|
755
928
|
* Pass `null` or `undefined` to unmount the editor.
|
756
929
|
*/
|
757
930
|
mount(place) {
|
758
|
-
if (!place)
|
931
|
+
if (!place) {
|
759
932
|
return this.unmount();
|
760
|
-
|
933
|
+
}
|
934
|
+
this.instance.mount(place);
|
935
|
+
this.afterMounted.forEach((callback) => callback());
|
761
936
|
}
|
762
937
|
/**
|
763
938
|
* Unmount the editor. This is equivalent to `mount(null)`.
|
764
939
|
*/
|
765
940
|
unmount() {
|
766
|
-
this.mounted
|
941
|
+
if (this.mounted) {
|
942
|
+
this.instance.unmount();
|
943
|
+
}
|
767
944
|
}
|
768
945
|
/**
|
769
946
|
* Focus the editor.
|
770
947
|
*/
|
771
948
|
focus() {
|
772
949
|
var _a;
|
773
|
-
(_a = this.instance.view) == null
|
950
|
+
(_a = this.instance.view) == null ? void 0 : _a.focus();
|
774
951
|
}
|
775
952
|
/**
|
776
953
|
* Blur the editor.
|
777
954
|
*/
|
778
955
|
blur() {
|
779
956
|
var _a;
|
780
|
-
(_a = this.instance.view) == null
|
957
|
+
(_a = this.instance.view) == null ? void 0 : _a.dom.blur();
|
781
958
|
}
|
782
959
|
/**
|
783
960
|
* Register an extension to the editor. Return a function to unregister the
|
@@ -785,14 +962,21 @@ var EditorInstance = class {
|
|
785
962
|
*/
|
786
963
|
use(extension) {
|
787
964
|
if (!this.mounted) {
|
788
|
-
let canceled =
|
789
|
-
|
965
|
+
let canceled = false;
|
966
|
+
let lazyRemove = null;
|
967
|
+
const lazyCreate = () => {
|
968
|
+
if (!canceled) {
|
969
|
+
lazyRemove = this.use(extension);
|
970
|
+
}
|
790
971
|
};
|
791
|
-
|
792
|
-
|
972
|
+
this.afterMounted.push(lazyCreate);
|
973
|
+
return () => {
|
974
|
+
canceled = true;
|
975
|
+
lazyRemove == null ? void 0 : lazyRemove();
|
793
976
|
};
|
794
977
|
}
|
795
|
-
|
978
|
+
this.instance.updateExtension(extension, true);
|
979
|
+
return () => this.instance.updateExtension(extension, false);
|
796
980
|
}
|
797
981
|
/**
|
798
982
|
* The editor's current state.
|