@prosekit/core 0.0.0-next-20230627094841
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/LICENSE +21 -0
- package/README.md +0 -0
- package/dist/prosekit-core.js +696 -0
- package/dist/style.css +52 -0
- package/package.json +56 -0
- package/src/index.ts +30 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 ocavue
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
File without changes
|
@@ -0,0 +1,696 @@
|
|
1
|
+
// src/commands/toggle-mark.ts
|
2
|
+
import { toggleMark as baseToggleMark } from "@prosekit/pm/commands";
|
3
|
+
|
4
|
+
// src/error.ts
|
5
|
+
var ProseKitError = class extends Error {
|
6
|
+
};
|
7
|
+
|
8
|
+
// src/utils/get-mark-type.ts
|
9
|
+
function getMarkType(schema, type) {
|
10
|
+
if (typeof type === "string") {
|
11
|
+
const markType = schema.marks[type];
|
12
|
+
if (!markType) {
|
13
|
+
throw new ProseKitError(`Cannot find mark type "${type}"`);
|
14
|
+
}
|
15
|
+
return markType;
|
16
|
+
}
|
17
|
+
return type;
|
18
|
+
}
|
19
|
+
|
20
|
+
// src/commands/toggle-mark.ts
|
21
|
+
function toggleMark(options) {
|
22
|
+
return (state, dispatch, view) => {
|
23
|
+
return baseToggleMark(
|
24
|
+
getMarkType(state.schema, options.type),
|
25
|
+
options.attrs
|
26
|
+
)(state, dispatch, view);
|
27
|
+
};
|
28
|
+
}
|
29
|
+
|
30
|
+
// src/editor/editor.ts
|
31
|
+
import { Schema } from "@prosekit/pm/model";
|
32
|
+
import { EditorState } from "@prosekit/pm/state";
|
33
|
+
import { EditorView } from "@prosekit/pm/view";
|
34
|
+
|
35
|
+
// src/types/void-function.ts
|
36
|
+
function voidFunction() {
|
37
|
+
}
|
38
|
+
|
39
|
+
// src/types/priority.ts
|
40
|
+
var Priority = /* @__PURE__ */ ((Priority2) => {
|
41
|
+
Priority2[Priority2["lowest"] = 4] = "lowest";
|
42
|
+
Priority2[Priority2["low"] = 3] = "low";
|
43
|
+
Priority2[Priority2["default"] = 2] = "default";
|
44
|
+
Priority2[Priority2["high"] = 1] = "high";
|
45
|
+
Priority2[Priority2["highest"] = 0] = "highest";
|
46
|
+
return Priority2;
|
47
|
+
})(Priority || {});
|
48
|
+
|
49
|
+
// src/editor/facet.ts
|
50
|
+
var nextIndex = 0;
|
51
|
+
var Facet = class _Facet {
|
52
|
+
constructor(combine, next) {
|
53
|
+
/** @internal */
|
54
|
+
this.index = nextIndex++;
|
55
|
+
this.combine = combine;
|
56
|
+
this.next = next;
|
57
|
+
}
|
58
|
+
static define({ combine, next }) {
|
59
|
+
return new _Facet(combine, next);
|
60
|
+
}
|
61
|
+
/** @internal */
|
62
|
+
static defineSlot({
|
63
|
+
combine
|
64
|
+
}) {
|
65
|
+
return new _Facet(combine, null);
|
66
|
+
}
|
67
|
+
extension(inputs) {
|
68
|
+
return new FacetExtension(this, inputs);
|
69
|
+
}
|
70
|
+
};
|
71
|
+
var FacetExtension = class {
|
72
|
+
constructor(facet, inputs) {
|
73
|
+
this.facet = facet;
|
74
|
+
this.inputs = inputs;
|
75
|
+
}
|
76
|
+
};
|
77
|
+
function sortFacets(unsorted) {
|
78
|
+
var _a;
|
79
|
+
const facets = unsorted.filter((val) => val);
|
80
|
+
const facetMap = [];
|
81
|
+
const inbounds = [];
|
82
|
+
let facetCount = 0;
|
83
|
+
for (const facet of facets) {
|
84
|
+
const index = facet.index;
|
85
|
+
if (facetMap[index] != null) {
|
86
|
+
continue;
|
87
|
+
}
|
88
|
+
if (inbounds[index] == null) {
|
89
|
+
inbounds[index] = 0;
|
90
|
+
}
|
91
|
+
facetCount++;
|
92
|
+
facetMap[index] = facet;
|
93
|
+
if (facet.next) {
|
94
|
+
const nextIndex2 = facet.next.index;
|
95
|
+
if (inbounds[nextIndex2] == null) {
|
96
|
+
inbounds[nextIndex2] = 0;
|
97
|
+
}
|
98
|
+
inbounds[nextIndex2] += 1;
|
99
|
+
if (facetMap[nextIndex2] == null) {
|
100
|
+
facets.push(facet.next);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
const sortedFacets = [];
|
105
|
+
const sortedIndexes = [];
|
106
|
+
inbounds.forEach((inbound, index) => {
|
107
|
+
if (inbound === 0) {
|
108
|
+
sortedIndexes.push(index);
|
109
|
+
}
|
110
|
+
});
|
111
|
+
for (const index of sortedIndexes) {
|
112
|
+
const facet = facetMap[index];
|
113
|
+
sortedFacets.push(facet);
|
114
|
+
const nextIndex2 = (_a = facet.next) == null ? void 0 : _a.index;
|
115
|
+
if (nextIndex2 == null)
|
116
|
+
continue;
|
117
|
+
inbounds[nextIndex2] -= 1;
|
118
|
+
if (inbounds[nextIndex2] === 0) {
|
119
|
+
sortedIndexes.push(nextIndex2);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
if (facetCount !== sortedFacets.length) {
|
123
|
+
throw new Error(`Facet has circular dependency`);
|
124
|
+
}
|
125
|
+
return sortedFacets;
|
126
|
+
}
|
127
|
+
|
128
|
+
// src/editor/slot.ts
|
129
|
+
import OrderedMap from "orderedmap";
|
130
|
+
var schemaSlot = Facet.defineSlot({
|
131
|
+
combine: (specs) => {
|
132
|
+
var _a;
|
133
|
+
let nodes = OrderedMap.from({});
|
134
|
+
let marks = OrderedMap.from({});
|
135
|
+
let topNode = void 0;
|
136
|
+
for (const spec of specs) {
|
137
|
+
nodes = nodes.append(spec.nodes);
|
138
|
+
marks = marks.append((_a = spec.marks) != null ? _a : {});
|
139
|
+
topNode = topNode != null ? topNode : spec.topNode;
|
140
|
+
}
|
141
|
+
return { nodes, marks, topNode };
|
142
|
+
}
|
143
|
+
});
|
144
|
+
var stateSlot = Facet.defineSlot({
|
145
|
+
combine: (callbacks) => {
|
146
|
+
return (ctx) => {
|
147
|
+
var _a, _b, _c, _d, _e;
|
148
|
+
const configs = callbacks.map((cb) => cb(ctx));
|
149
|
+
const config = {
|
150
|
+
schema: ctx.schema,
|
151
|
+
storedMarks: [],
|
152
|
+
plugins: []
|
153
|
+
};
|
154
|
+
for (const c of configs) {
|
155
|
+
config.schema = (_a = config.schema) != null ? _a : c.schema;
|
156
|
+
config.doc = (_b = config.doc) != null ? _b : c.doc;
|
157
|
+
config.selection = (_c = config.selection) != null ? _c : c.selection;
|
158
|
+
config.storedMarks = [...config.storedMarks, ...(_d = c.storedMarks) != null ? _d : []];
|
159
|
+
config.plugins = [...config.plugins, ...(_e = c.plugins) != null ? _e : []];
|
160
|
+
}
|
161
|
+
if (!config.doc && !config.schema) {
|
162
|
+
throw new Error("Can't create state without a schema nor a document");
|
163
|
+
}
|
164
|
+
if (config.doc) {
|
165
|
+
config.schema = void 0;
|
166
|
+
}
|
167
|
+
return config;
|
168
|
+
};
|
169
|
+
}
|
170
|
+
});
|
171
|
+
var viewSlot = Facet.defineSlot({
|
172
|
+
combine: (props) => {
|
173
|
+
return Object.assign({}, ...props);
|
174
|
+
}
|
175
|
+
});
|
176
|
+
var commandSlot = Facet.defineSlot({
|
177
|
+
combine: (inputs) => {
|
178
|
+
return Object.assign({}, ...inputs);
|
179
|
+
}
|
180
|
+
});
|
181
|
+
|
182
|
+
// src/editor/flatten.ts
|
183
|
+
function flatten(root) {
|
184
|
+
var _a;
|
185
|
+
const extensions = [root];
|
186
|
+
const priorities = [2 /* default */];
|
187
|
+
const facets = [];
|
188
|
+
const inputs = [];
|
189
|
+
while (extensions.length > 0) {
|
190
|
+
const ext = extensions.pop();
|
191
|
+
const pri = priorities.pop();
|
192
|
+
if (ext instanceof FacetExtension) {
|
193
|
+
const facet = ext.facet;
|
194
|
+
if (!facets[facet.index]) {
|
195
|
+
facets[facet.index] = facet;
|
196
|
+
inputs[facet.index] = [[], [], [], [], []];
|
197
|
+
}
|
198
|
+
const facetInputs = ext.inputs;
|
199
|
+
inputs[facet.index][pri].push(...facetInputs);
|
200
|
+
} else if (ext.extension) {
|
201
|
+
const p = (_a = ext.priority) != null ? _a : pri;
|
202
|
+
if (Array.isArray(ext.extension)) {
|
203
|
+
for (const e of ext.extension) {
|
204
|
+
extensions.push(e);
|
205
|
+
priorities.push(p);
|
206
|
+
}
|
207
|
+
} else {
|
208
|
+
extensions.push(ext.extension);
|
209
|
+
priorities.push(p);
|
210
|
+
}
|
211
|
+
} else {
|
212
|
+
throw new Error("Invalid extension");
|
213
|
+
}
|
214
|
+
}
|
215
|
+
let schemaInput = null;
|
216
|
+
let stateInput = null;
|
217
|
+
let viewInput = null;
|
218
|
+
let commandInput = null;
|
219
|
+
const sortedFacets = sortFacets(facets);
|
220
|
+
for (const facet of sortedFacets) {
|
221
|
+
const nextFacet = facet.next;
|
222
|
+
if (nextFacet) {
|
223
|
+
for (let pri = 0; pri < 5; pri++) {
|
224
|
+
const input = inputs[facet.index][pri];
|
225
|
+
if (input.length > 0) {
|
226
|
+
const output = facet.combine(input);
|
227
|
+
if (!inputs[nextFacet.index]) {
|
228
|
+
inputs[nextFacet.index] = [[], [], [], [], []];
|
229
|
+
}
|
230
|
+
inputs[nextFacet.index][pri].push(output);
|
231
|
+
}
|
232
|
+
}
|
233
|
+
} else if (inputs[facet.index]) {
|
234
|
+
const [i1, i2, i3, i4, i5] = inputs[facet.index];
|
235
|
+
const jointInputs = [...i1, ...i2, ...i3, ...i4, ...i5];
|
236
|
+
const output = facet.combine(jointInputs);
|
237
|
+
switch (facet) {
|
238
|
+
case schemaSlot:
|
239
|
+
schemaInput = output;
|
240
|
+
break;
|
241
|
+
case stateSlot:
|
242
|
+
stateInput = output;
|
243
|
+
break;
|
244
|
+
case viewSlot:
|
245
|
+
viewInput = output;
|
246
|
+
break;
|
247
|
+
case commandSlot:
|
248
|
+
commandInput = output;
|
249
|
+
break;
|
250
|
+
default:
|
251
|
+
throw new Error("Invalid facet");
|
252
|
+
}
|
253
|
+
}
|
254
|
+
}
|
255
|
+
return { schemaInput, stateInput, viewInput, commandInput };
|
256
|
+
}
|
257
|
+
|
258
|
+
// src/editor/editor.ts
|
259
|
+
function createEditor({
|
260
|
+
extension
|
261
|
+
}) {
|
262
|
+
const { schemaInput, stateInput, viewInput, commandInput } = flatten(extension);
|
263
|
+
if (!schemaInput) {
|
264
|
+
throw new Error("Schema must be defined");
|
265
|
+
}
|
266
|
+
const schema = new Schema(schemaInput);
|
267
|
+
const stateConfig = stateInput ? stateInput({ schema }) : { schema };
|
268
|
+
const state = EditorState.create(stateConfig);
|
269
|
+
const directEditorProps = { state, ...viewInput };
|
270
|
+
const instance = new EditorInstance(directEditorProps);
|
271
|
+
if (commandInput) {
|
272
|
+
for (const [name, commandCreator] of Object.entries(commandInput)) {
|
273
|
+
instance.addCommand(name, commandCreator);
|
274
|
+
}
|
275
|
+
}
|
276
|
+
return Editor.create(instance);
|
277
|
+
}
|
278
|
+
var EditorInstance = class {
|
279
|
+
constructor(directEditorProps) {
|
280
|
+
this.directEditorProps = directEditorProps;
|
281
|
+
this.view = null;
|
282
|
+
this.commandDispatchers = {};
|
283
|
+
this.mount.bind(this);
|
284
|
+
this.unmount.bind(this);
|
285
|
+
this.schema = directEditorProps.state.schema;
|
286
|
+
}
|
287
|
+
mount(place) {
|
288
|
+
if (this.view) {
|
289
|
+
throw new Error("Editor is already mounted");
|
290
|
+
}
|
291
|
+
if (!place) {
|
292
|
+
throw new Error("Can't mount editor without a place");
|
293
|
+
}
|
294
|
+
this.view = new EditorView(place, this.directEditorProps);
|
295
|
+
}
|
296
|
+
unmount() {
|
297
|
+
if (!this.view) {
|
298
|
+
throw new Error("Editor is not mounted yet");
|
299
|
+
}
|
300
|
+
this.view.destroy();
|
301
|
+
this.view = null;
|
302
|
+
}
|
303
|
+
get assertView() {
|
304
|
+
if (!this.view)
|
305
|
+
throw new Error("Editor is not mounted");
|
306
|
+
return this.view;
|
307
|
+
}
|
308
|
+
addPlugins(plugins) {
|
309
|
+
const view = this.assertView;
|
310
|
+
const state = view.state;
|
311
|
+
const newPlugins = [...plugins, ...state.plugins];
|
312
|
+
const newState = state.reconfigure({ plugins: newPlugins });
|
313
|
+
view.setProps({ state: newState });
|
314
|
+
}
|
315
|
+
removePlugins(plugins) {
|
316
|
+
const view = this.view;
|
317
|
+
if (!view)
|
318
|
+
return;
|
319
|
+
const state = view.state;
|
320
|
+
const newPlugins = state.plugins.filter((p) => !plugins.includes(p));
|
321
|
+
const newState = state.reconfigure({ plugins: newPlugins });
|
322
|
+
view.setProps({ state: newState });
|
323
|
+
}
|
324
|
+
addCommand(name, commandCreator) {
|
325
|
+
const dispatcher = (...args) => {
|
326
|
+
const view = this.assertView;
|
327
|
+
const command = commandCreator(...args);
|
328
|
+
return command(view.state, view.dispatch.bind(view), view);
|
329
|
+
};
|
330
|
+
this.commandDispatchers[name] = dispatcher;
|
331
|
+
}
|
332
|
+
removeCommand(name) {
|
333
|
+
delete this.commandDispatchers[name];
|
334
|
+
}
|
335
|
+
};
|
336
|
+
var Editor = class _Editor {
|
337
|
+
constructor(instance) {
|
338
|
+
this.afterMounted = [];
|
339
|
+
this.instance = instance;
|
340
|
+
}
|
341
|
+
/** @internal */
|
342
|
+
static create(instance) {
|
343
|
+
if (!(instance instanceof EditorInstance)) {
|
344
|
+
throw new TypeError("Editor's instance is not EditorInstance");
|
345
|
+
}
|
346
|
+
return new _Editor(instance);
|
347
|
+
}
|
348
|
+
get mounted() {
|
349
|
+
return !!this.instance.view;
|
350
|
+
}
|
351
|
+
get view() {
|
352
|
+
return this.instance.assertView;
|
353
|
+
}
|
354
|
+
get schema() {
|
355
|
+
return this.instance.schema;
|
356
|
+
}
|
357
|
+
get commands() {
|
358
|
+
return this.instance.commandDispatchers;
|
359
|
+
}
|
360
|
+
mount(place) {
|
361
|
+
this.instance.mount(place);
|
362
|
+
this.afterMounted.forEach((callback) => callback());
|
363
|
+
}
|
364
|
+
unmount() {
|
365
|
+
this.instance.unmount();
|
366
|
+
}
|
367
|
+
use(extension) {
|
368
|
+
if (!this.mounted) {
|
369
|
+
let lazyRemove = null;
|
370
|
+
const lazyCreate = () => {
|
371
|
+
lazyRemove = this.use(extension);
|
372
|
+
};
|
373
|
+
this.afterMounted.push(lazyCreate);
|
374
|
+
return () => {
|
375
|
+
lazyRemove == null ? void 0 : lazyRemove();
|
376
|
+
};
|
377
|
+
}
|
378
|
+
const { schemaInput, stateInput, viewInput, commandInput } = flatten(extension);
|
379
|
+
if (schemaInput) {
|
380
|
+
throw new ProseKitError("Schema cannot be changed");
|
381
|
+
}
|
382
|
+
if (viewInput) {
|
383
|
+
throw new ProseKitError("View cannot be changed");
|
384
|
+
}
|
385
|
+
if (stateInput) {
|
386
|
+
const stateConfig = stateInput({ schema: this.schema });
|
387
|
+
const plugins = stateConfig.plugins;
|
388
|
+
if (plugins && plugins.length > 0) {
|
389
|
+
this.instance.addPlugins(plugins);
|
390
|
+
return () => this.instance.removePlugins(plugins);
|
391
|
+
}
|
392
|
+
}
|
393
|
+
if (commandInput) {
|
394
|
+
const names = Object.keys(commandInput);
|
395
|
+
for (const name of names) {
|
396
|
+
this.instance.addCommand(name, commandInput[name]);
|
397
|
+
}
|
398
|
+
return () => {
|
399
|
+
for (const name of names) {
|
400
|
+
this.instance.removeCommand(name);
|
401
|
+
}
|
402
|
+
};
|
403
|
+
}
|
404
|
+
return voidFunction;
|
405
|
+
}
|
406
|
+
};
|
407
|
+
|
408
|
+
// src/editor/type-utils.ts
|
409
|
+
function defineExtension(extension) {
|
410
|
+
if (extension && Array.isArray(extension)) {
|
411
|
+
return { extension };
|
412
|
+
}
|
413
|
+
return extension;
|
414
|
+
}
|
415
|
+
|
416
|
+
// src/editor/with-priority.ts
|
417
|
+
function withPriority(extension, priority) {
|
418
|
+
return { extension, priority };
|
419
|
+
}
|
420
|
+
|
421
|
+
// src/extensions/command.ts
|
422
|
+
import { AllSelection, Selection } from "@prosekit/pm/state";
|
423
|
+
import { findWrapping, insertPoint } from "@prosekit/pm/transform";
|
424
|
+
function addCommands(commands) {
|
425
|
+
return commandSlot.extension([commands]);
|
426
|
+
}
|
427
|
+
function addBaseCommands() {
|
428
|
+
return addCommands({
|
429
|
+
insertText: ({
|
430
|
+
text,
|
431
|
+
from,
|
432
|
+
to
|
433
|
+
}) => {
|
434
|
+
return (state, dispatch) => {
|
435
|
+
if (text) {
|
436
|
+
dispatch == null ? void 0 : dispatch(state.tr.insertText(text, from, to));
|
437
|
+
}
|
438
|
+
return true;
|
439
|
+
};
|
440
|
+
},
|
441
|
+
insertNode: ({ node, pos }) => {
|
442
|
+
return (state, dispatch) => {
|
443
|
+
const insertPos = insertPoint(
|
444
|
+
state.doc,
|
445
|
+
pos != null ? pos : state.selection.to,
|
446
|
+
node.type
|
447
|
+
);
|
448
|
+
if (insertPos == null)
|
449
|
+
return false;
|
450
|
+
if (dispatch) {
|
451
|
+
const tr = state.tr.insert(insertPos, node);
|
452
|
+
const $pos = tr.doc.resolve(insertPos);
|
453
|
+
tr.setSelection(Selection.near($pos));
|
454
|
+
dispatch(tr);
|
455
|
+
}
|
456
|
+
return true;
|
457
|
+
};
|
458
|
+
},
|
459
|
+
wrap: ({
|
460
|
+
nodeType,
|
461
|
+
attrs
|
462
|
+
}) => {
|
463
|
+
return (state, dispatch) => {
|
464
|
+
const { $from, $to } = state.selection;
|
465
|
+
const range = $from.blockRange($to);
|
466
|
+
if (!range)
|
467
|
+
return false;
|
468
|
+
const wrapping = findWrapping(range, nodeType, attrs);
|
469
|
+
if (!wrapping)
|
470
|
+
return false;
|
471
|
+
dispatch == null ? void 0 : dispatch(state.tr.wrap(range, wrapping));
|
472
|
+
return true;
|
473
|
+
};
|
474
|
+
},
|
475
|
+
setBlockType: ({
|
476
|
+
nodeType,
|
477
|
+
attrs,
|
478
|
+
from,
|
479
|
+
to
|
480
|
+
}) => {
|
481
|
+
return (state, dispatch) => {
|
482
|
+
from = from != null ? from : state.selection.from;
|
483
|
+
to = from != null ? from : state.selection.from;
|
484
|
+
dispatch == null ? void 0 : dispatch(state.tr.setBlockType(from, to, nodeType, attrs));
|
485
|
+
return true;
|
486
|
+
};
|
487
|
+
},
|
488
|
+
selectAll: () => {
|
489
|
+
return (state, dispatch) => {
|
490
|
+
dispatch == null ? void 0 : dispatch(state.tr.setSelection(new AllSelection(state.doc)));
|
491
|
+
return true;
|
492
|
+
};
|
493
|
+
}
|
494
|
+
});
|
495
|
+
}
|
496
|
+
|
497
|
+
// src/extensions/node-spec.ts
|
498
|
+
function addNodeSpec(options) {
|
499
|
+
return nodeSpecFacet.extension([options]);
|
500
|
+
}
|
501
|
+
var nodeSpecFacet = Facet.define({
|
502
|
+
combine: (options) => {
|
503
|
+
const nodes = {};
|
504
|
+
let topNode = void 0;
|
505
|
+
for (const { name, spec, topNode: isTopNode } of options) {
|
506
|
+
if (nodes[name]) {
|
507
|
+
throw new Error(`Node type ${name} has already been defined`);
|
508
|
+
}
|
509
|
+
nodes[name] = spec;
|
510
|
+
if (isTopNode && !topNode) {
|
511
|
+
topNode = name;
|
512
|
+
}
|
513
|
+
}
|
514
|
+
return { nodes, topNode };
|
515
|
+
},
|
516
|
+
next: schemaSlot
|
517
|
+
});
|
518
|
+
|
519
|
+
// src/extensions/doc.ts
|
520
|
+
function addDoc() {
|
521
|
+
return addNodeSpec({
|
522
|
+
name: "doc",
|
523
|
+
spec: {
|
524
|
+
content: "block+"
|
525
|
+
}
|
526
|
+
});
|
527
|
+
}
|
528
|
+
|
529
|
+
// src/extensions/input-rules.ts
|
530
|
+
import { inputRules } from "@prosekit/pm/inputrules";
|
531
|
+
|
532
|
+
// src/extensions/plugin.ts
|
533
|
+
function addPlugin({ plugins }) {
|
534
|
+
if (typeof plugins === "function") {
|
535
|
+
return pluginFacet.extension([plugins]);
|
536
|
+
} else if (Array.isArray(plugins)) {
|
537
|
+
return pluginFacet.extension([() => plugins]);
|
538
|
+
} else {
|
539
|
+
throw new TypeError("plugins must be a function or an array");
|
540
|
+
}
|
541
|
+
}
|
542
|
+
var pluginFacet = Facet.define({
|
543
|
+
combine: (callbacks) => {
|
544
|
+
return ({ schema }) => {
|
545
|
+
const plugins = callbacks.flatMap((func) => func({ schema }));
|
546
|
+
return { plugins };
|
547
|
+
};
|
548
|
+
},
|
549
|
+
next: stateSlot
|
550
|
+
});
|
551
|
+
|
552
|
+
// src/extensions/input-rules.ts
|
553
|
+
function addInputRule(rules) {
|
554
|
+
return inputRuleFacet.extension([rules]);
|
555
|
+
}
|
556
|
+
var inputRuleFacet = Facet.define({
|
557
|
+
combine: (inputs) => {
|
558
|
+
return (context) => {
|
559
|
+
const rules = inputs.flatMap((callback) => callback(context));
|
560
|
+
return [inputRules({ rules })];
|
561
|
+
};
|
562
|
+
},
|
563
|
+
next: pluginFacet
|
564
|
+
});
|
565
|
+
|
566
|
+
// src/extensions/keymap.ts
|
567
|
+
import { baseKeymap, chainCommands } from "@prosekit/pm/commands";
|
568
|
+
import { keymap as createKeymapPlugin } from "@prosekit/pm/keymap";
|
569
|
+
function addKeymap(keymap) {
|
570
|
+
return keymapFacet.extension([keymap]);
|
571
|
+
}
|
572
|
+
function addBaseKeymap() {
|
573
|
+
return addKeymap(baseKeymap);
|
574
|
+
}
|
575
|
+
var keymapFacet = Facet.define({
|
576
|
+
combine: (keymaps) => {
|
577
|
+
const keymap = mergeKeymaps(keymaps);
|
578
|
+
const plugin = createKeymapPlugin(keymap);
|
579
|
+
return () => [plugin];
|
580
|
+
},
|
581
|
+
next: pluginFacet
|
582
|
+
});
|
583
|
+
function mergeKeymaps(keymaps) {
|
584
|
+
const bindings = {};
|
585
|
+
for (const keymap of keymaps) {
|
586
|
+
for (const [key, command] of Object.entries(keymap)) {
|
587
|
+
if (!bindings[key])
|
588
|
+
bindings[key] = [];
|
589
|
+
bindings[key].push(command);
|
590
|
+
}
|
591
|
+
}
|
592
|
+
return Object.fromEntries(
|
593
|
+
Object.entries(bindings).map(([key, commands]) => [
|
594
|
+
key,
|
595
|
+
chainCommands(...commands)
|
596
|
+
])
|
597
|
+
);
|
598
|
+
}
|
599
|
+
|
600
|
+
// src/extensions/mark-spec.ts
|
601
|
+
function addMarkSpec(options) {
|
602
|
+
return markSpecFacet.extension([options]);
|
603
|
+
}
|
604
|
+
var markSpecFacet = Facet.define({
|
605
|
+
combine: (options) => {
|
606
|
+
const marks = {};
|
607
|
+
for (const { name, spec } of options) {
|
608
|
+
if (marks[name]) {
|
609
|
+
throw new Error(`Mark type ${name} has already been defined`);
|
610
|
+
}
|
611
|
+
marks[name] = spec;
|
612
|
+
}
|
613
|
+
return { marks, nodes: {} };
|
614
|
+
},
|
615
|
+
next: schemaSlot
|
616
|
+
});
|
617
|
+
|
618
|
+
// src/extensions/node-view.ts
|
619
|
+
import { Plugin as Plugin2 } from "@prosekit/pm/state";
|
620
|
+
function addNodeView(options) {
|
621
|
+
return nodeViewFacet.extension([options]);
|
622
|
+
}
|
623
|
+
var nodeViewFacet = Facet.define({
|
624
|
+
combine: (inputs) => {
|
625
|
+
const nodeViews = {};
|
626
|
+
for (const input of inputs) {
|
627
|
+
if (!nodeViews[input.name]) {
|
628
|
+
nodeViews[input.name] = input.constructor;
|
629
|
+
}
|
630
|
+
}
|
631
|
+
return () => [new Plugin2({ props: { nodeViews } })];
|
632
|
+
},
|
633
|
+
next: pluginFacet
|
634
|
+
});
|
635
|
+
|
636
|
+
// src/extensions/paragraph.ts
|
637
|
+
function addParagraph() {
|
638
|
+
return addNodeSpec({
|
639
|
+
name: "paragraph",
|
640
|
+
spec: {
|
641
|
+
content: "inline*",
|
642
|
+
group: "block",
|
643
|
+
parseDOM: [{ tag: "p" }],
|
644
|
+
toDOM() {
|
645
|
+
return ["p", 0];
|
646
|
+
}
|
647
|
+
}
|
648
|
+
});
|
649
|
+
}
|
650
|
+
|
651
|
+
// src/extensions/text.ts
|
652
|
+
function addText() {
|
653
|
+
return addNodeSpec({
|
654
|
+
name: "text",
|
655
|
+
spec: {
|
656
|
+
group: "inline"
|
657
|
+
}
|
658
|
+
});
|
659
|
+
}
|
660
|
+
|
661
|
+
// src/utils/get-node-type.ts
|
662
|
+
function getNodeType(schema, type) {
|
663
|
+
if (typeof type === "string") {
|
664
|
+
const nodeType = schema.nodes[type];
|
665
|
+
if (!nodeType) {
|
666
|
+
throw new ProseKitError(`Cannot find node type "${type}"`);
|
667
|
+
}
|
668
|
+
return nodeType;
|
669
|
+
}
|
670
|
+
return type;
|
671
|
+
}
|
672
|
+
export {
|
673
|
+
Editor,
|
674
|
+
Facet,
|
675
|
+
FacetExtension,
|
676
|
+
Priority,
|
677
|
+
ProseKitError,
|
678
|
+
addBaseCommands,
|
679
|
+
addBaseKeymap,
|
680
|
+
addCommands,
|
681
|
+
addDoc,
|
682
|
+
addInputRule,
|
683
|
+
addKeymap,
|
684
|
+
addMarkSpec,
|
685
|
+
addNodeSpec,
|
686
|
+
addNodeView,
|
687
|
+
addParagraph,
|
688
|
+
addPlugin,
|
689
|
+
addText,
|
690
|
+
createEditor,
|
691
|
+
defineExtension,
|
692
|
+
getMarkType,
|
693
|
+
getNodeType,
|
694
|
+
toggleMark,
|
695
|
+
withPriority
|
696
|
+
};
|
package/dist/style.css
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
/* ../../node_modules/.pnpm/prosemirror-view@1.31.5/node_modules/prosemirror-view/style/prosemirror.css */
|
2
|
+
.ProseMirror {
|
3
|
+
position: relative;
|
4
|
+
}
|
5
|
+
.ProseMirror {
|
6
|
+
word-wrap: break-word;
|
7
|
+
white-space: pre-wrap;
|
8
|
+
white-space: break-spaces;
|
9
|
+
-webkit-font-variant-ligatures: none;
|
10
|
+
font-variant-ligatures: none;
|
11
|
+
font-feature-settings: "liga" 0;
|
12
|
+
}
|
13
|
+
.ProseMirror pre {
|
14
|
+
white-space: pre-wrap;
|
15
|
+
}
|
16
|
+
.ProseMirror li {
|
17
|
+
position: relative;
|
18
|
+
}
|
19
|
+
.ProseMirror-hideselection *::selection {
|
20
|
+
background: transparent;
|
21
|
+
}
|
22
|
+
.ProseMirror-hideselection *::-moz-selection {
|
23
|
+
background: transparent;
|
24
|
+
}
|
25
|
+
.ProseMirror-hideselection {
|
26
|
+
caret-color: transparent;
|
27
|
+
}
|
28
|
+
.ProseMirror-selectednode {
|
29
|
+
outline: 2px solid #8cf;
|
30
|
+
}
|
31
|
+
li.ProseMirror-selectednode {
|
32
|
+
outline: none;
|
33
|
+
}
|
34
|
+
li.ProseMirror-selectednode:after {
|
35
|
+
content: "";
|
36
|
+
position: absolute;
|
37
|
+
left: -32px;
|
38
|
+
right: -2px;
|
39
|
+
top: -2px;
|
40
|
+
bottom: -2px;
|
41
|
+
border: 2px solid #8cf;
|
42
|
+
pointer-events: none;
|
43
|
+
}
|
44
|
+
img.ProseMirror-separator {
|
45
|
+
display: inline !important;
|
46
|
+
border: none !important;
|
47
|
+
margin: 0 !important;
|
48
|
+
}
|
49
|
+
|
50
|
+
/* ../pm/src/view/style/prosemirror.css */
|
51
|
+
|
52
|
+
/* src/style.css */
|
package/package.json
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
{
|
2
|
+
"name": "@prosekit/core",
|
3
|
+
"type": "module",
|
4
|
+
"version": "0.0.0-next-20230627094841",
|
5
|
+
"private": false,
|
6
|
+
"author": {
|
7
|
+
"name": "ocavue",
|
8
|
+
"email": "ocavue@gmail.com"
|
9
|
+
},
|
10
|
+
"license": "MIT",
|
11
|
+
"funding": "https://github.com/sponsors/ocavue",
|
12
|
+
"homepage": "https://github.com/ocavue/prosekit#readme",
|
13
|
+
"repository": {
|
14
|
+
"type": "git",
|
15
|
+
"url": "git+https://github.com/ocavue/prosekit.git",
|
16
|
+
"directory": "packages/core"
|
17
|
+
},
|
18
|
+
"bugs": {
|
19
|
+
"url": "https://github.com/ocavue/prosekit/issues"
|
20
|
+
},
|
21
|
+
"keywords": [
|
22
|
+
"ProseMirror"
|
23
|
+
],
|
24
|
+
"sideEffects": false,
|
25
|
+
"main": "./dist/prosekit-core.js",
|
26
|
+
"module": "./dist/prosekit-core.js",
|
27
|
+
"exports": {
|
28
|
+
".": {
|
29
|
+
"types": "./dist/prosekit-core.d.ts",
|
30
|
+
"import": "./dist/prosekit-core.js",
|
31
|
+
"default": "./dist/prosekit-core.js"
|
32
|
+
},
|
33
|
+
"./style.css": {
|
34
|
+
"default": "./dist/style.css"
|
35
|
+
}
|
36
|
+
},
|
37
|
+
"files": [
|
38
|
+
"dist"
|
39
|
+
],
|
40
|
+
"dependencies": {
|
41
|
+
"@prosekit/pm": "0.0.0-next-20230627094841",
|
42
|
+
"orderedmap": "^2.1.1",
|
43
|
+
"type-fest": "^3.12.0"
|
44
|
+
},
|
45
|
+
"devDependencies": {
|
46
|
+
"tsup": "^7.1.0",
|
47
|
+
"typescript": "^5.1.3",
|
48
|
+
"vitest": "^0.32.2",
|
49
|
+
"@prosekit/dev": "0.0.0"
|
50
|
+
},
|
51
|
+
"scripts": {
|
52
|
+
"build:tsup": "tsup",
|
53
|
+
"build:tsc": "tsc -b tsconfig.json"
|
54
|
+
},
|
55
|
+
"types": "./dist/prosekit-core.d.ts"
|
56
|
+
}
|
package/src/index.ts
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
export { toggleMark } from './commands/toggle-mark'
|
2
|
+
export { Editor, createEditor, type EditorOptions } from './editor/editor'
|
3
|
+
export { Facet, FacetExtension, type FacetOptions } from './editor/facet'
|
4
|
+
export { defineExtension } from './editor/type-utils'
|
5
|
+
export { withPriority } from './editor/with-priority'
|
6
|
+
export { ProseKitError } from './error'
|
7
|
+
export { addBaseCommands, addCommands } from './extensions/command'
|
8
|
+
export { addDoc } from './extensions/doc'
|
9
|
+
export { addInputRule } from './extensions/input-rules'
|
10
|
+
export { addBaseKeymap, addKeymap, type Keymap } from './extensions/keymap'
|
11
|
+
export { addMarkSpec, type MarkSpecOptions } from './extensions/mark-spec'
|
12
|
+
export { addNodeSpec, type NodeSpecOptions } from './extensions/node-spec'
|
13
|
+
export { addNodeView, type NodeViewOptions } from './extensions/node-view'
|
14
|
+
export { addParagraph } from './extensions/paragraph'
|
15
|
+
export { addPlugin, type PluginOptions } from './extensions/plugin'
|
16
|
+
export { addText } from './extensions/text'
|
17
|
+
export { type CommandArgs as CommandArgs } from './types/command'
|
18
|
+
export * from './types/editor'
|
19
|
+
export {
|
20
|
+
type Extension,
|
21
|
+
type ExtractCommandCreators,
|
22
|
+
type ExtractCommandDispatchers,
|
23
|
+
type ExtractMarks,
|
24
|
+
type ExtractNodes,
|
25
|
+
} from './types/extension'
|
26
|
+
export { type ExtensionTyping } from './types/extension-typing'
|
27
|
+
export { Priority } from './types/priority'
|
28
|
+
export { type SimplifyUnion } from './types/simplify-union'
|
29
|
+
export { getMarkType } from './utils/get-mark-type'
|
30
|
+
export { getNodeType } from './utils/get-node-type'
|