@prosekit/core 0.0.4 → 0.0.6

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.
@@ -1,4 +1,4 @@
1
- import { MarkType, Attrs, Schema, ProseMirrorNode, NodeType, MarkSpec, NodeSpec } from '@prosekit/pm/model';
1
+ import { MarkType, Attrs, NodeType, Schema, ProseMirrorNode, MarkSpec, NodeSpec } from '@prosekit/pm/model';
2
2
  import { Command, EditorStateConfig, Plugin } from '@prosekit/pm/state';
3
3
  import { EditorView, NodeViewConstructor, DirectEditorProps } from '@prosekit/pm/view';
4
4
  import { ConditionalExcept, EmptyObject, Simplify, UnionToIntersection } from 'type-fest';
@@ -10,6 +10,12 @@ interface ToggleMarkOptions {
10
10
  }
11
11
  declare function toggleMark(options: ToggleMarkOptions): Command;
12
12
 
13
+ interface ToggleNodeOptions {
14
+ type: string | NodeType;
15
+ attrs?: Attrs | null;
16
+ }
17
+ declare function toggleNode(options: ToggleNodeOptions): Command;
18
+
13
19
  type CommandDispatcher<Args extends any[] = any[]> = (...arg: Args) => boolean;
14
20
  type CommandCreator<Args extends any[] = any[]> = (...arg: Args) => Command;
15
21
  /** @internal */
@@ -120,25 +126,36 @@ declare class Editor<E extends Extension = any> {
120
126
  mount(place: HTMLElement | null | undefined | void): void;
121
127
  unmount(): void;
122
128
  use(extension: Extension): VoidFunction;
129
+ isNodeActive(nodeType: string | NodeType, attrs?: Attrs): boolean;
130
+ isMarkActive(markType: string | MarkType, attrs?: Attrs): boolean;
131
+ }
132
+
133
+ interface Slot<Input, Output> {
134
+ create: (inputs: Input[]) => Output;
135
+ update: (inputs: Input[]) => Output | null;
123
136
  }
124
137
 
125
138
  /** @public */
126
139
  interface FacetOptions<Input, Output> {
127
- combine: (inputs: Input[]) => Output;
140
+ combine?: (inputs: Input[]) => Output;
141
+ slot?: () => Slot<Input, Output>;
128
142
  next: Facet<Output, any>;
143
+ single?: boolean;
129
144
  }
130
145
  /** @public */
131
146
  declare class Facet<Input, Output> {
132
147
  /** @internal */
133
148
  readonly index: number;
134
149
  /** @internal */
135
- readonly combine: (inputs: Input[]) => Output;
150
+ readonly slot: () => Slot<Input, Output>;
136
151
  /** @internal */
137
152
  readonly next: Facet<Output, any> | null;
153
+ /** @internal */
154
+ readonly single: boolean;
138
155
  private constructor();
139
- static define<Input, Output>({ combine, next }: FacetOptions<Input, Output>): Facet<Input, Output>;
156
+ static define<Input, Output>({ slot, combine, next, single, }: FacetOptions<Input, Output>): Facet<Input, Output>;
140
157
  /** @internal */
141
- static defineSlot<Input>({ combine, }: Omit<FacetOptions<Input, Input>, 'next'>): Facet<Input, Input>;
158
+ static defineSlot<Input>(options: Omit<FacetOptions<Input, Input>, 'next'>): Facet<Input, Input>;
142
159
  extension(inputs: Input[]): FacetExtension<Input, Output>;
143
160
  }
144
161
  /** @public */
@@ -286,4 +303,4 @@ declare function getMarkType(schema: Schema, type: string | MarkType): MarkType;
286
303
  /** @internal */
287
304
  declare function getNodeType(schema: Schema, type: string | NodeType): NodeType;
288
305
 
289
- export { CommandArgs, Editor, EditorOptions, Extension, ExtensionTyping, ExtractCommandCreators, ExtractCommandDispatchers, ExtractMarks, ExtractNodes, Facet, FacetExtension, FacetOptions, Keymap, MarkSpecOptions, NodeSpecOptions, NodeViewOptions, PluginFacetInput, PluginOptions, Priority, ProseKitError, SimplifyUnion, StateConfigCallback, StateConfigContext, ViewProps, addBaseCommands, addBaseKeymap, addCommands, addDoc, addInputRule, addKeymap, addMarkSpec, addNodeSpec, addNodeView, addParagraph, addPlugin, addText, createEditor, defineExtension, getMarkType, getNodeType, pluginFacet, toggleMark, withPriority };
306
+ export { CommandArgs, Editor, EditorOptions, Extension, ExtensionTyping, ExtractCommandCreators, ExtractCommandDispatchers, ExtractMarks, ExtractNodes, Facet, FacetExtension, FacetOptions, Keymap, MarkSpecOptions, NodeSpecOptions, NodeViewOptions, PluginFacetInput, PluginOptions, Priority, ProseKitError, SimplifyExtension, SimplifyUnion, StateConfigCallback, StateConfigContext, ToggleMarkOptions, ToggleNodeOptions, ViewProps, addBaseCommands, addBaseKeymap, addCommands, addDoc, addInputRule, addKeymap, addMarkSpec, addNodeSpec, addNodeView, addParagraph, addPlugin, addText, createEditor, defineExtension, getMarkType, getNodeType, pluginFacet, toggleMark, toggleNode, withPriority };
@@ -32,13 +32,94 @@ function toggleMark(options) {
32
32
  };
33
33
  }
34
34
 
35
+ // src/commands/toggle-node.ts
36
+ import { setBlockType } from "@prosekit/pm/commands";
37
+ import "@prosekit/pm/model";
38
+ import "@prosekit/pm/state";
39
+
40
+ // src/utils/get-node-type.ts
41
+ import "@prosekit/pm/model";
42
+ function getNodeType(schema, type) {
43
+ if (typeof type === "string") {
44
+ const nodeType = schema.nodes[type];
45
+ if (!nodeType) {
46
+ throw new ProseKitError(`Cannot find ProseMirror node type "${type}"`);
47
+ }
48
+ return nodeType;
49
+ }
50
+ return type;
51
+ }
52
+
53
+ // src/utils/object-euqal.ts
54
+ function objectEqual(a, b) {
55
+ if (a === b) {
56
+ return true;
57
+ }
58
+ if (typeof a !== "object" || typeof b !== "object") {
59
+ return false;
60
+ }
61
+ if (a === null || b === null) {
62
+ return false;
63
+ }
64
+ if (Array.isArray(a) || Array.isArray(b)) {
65
+ return false;
66
+ }
67
+ const aKeys = Object.keys(a);
68
+ const bKeys = Object.keys(b);
69
+ if (aKeys.length !== bKeys.length) {
70
+ return false;
71
+ }
72
+ for (const key of aKeys) {
73
+ if (!bKeys.includes(key)) {
74
+ return false;
75
+ }
76
+ if (!objectEqual(a[key], b[key])) {
77
+ return false;
78
+ }
79
+ }
80
+ return true;
81
+ }
82
+
83
+ // src/utils/is-node-active.ts
84
+ function isNodeActive(state, type, attrs) {
85
+ const $pos = state.selection.$from;
86
+ const nodeType = getNodeType(state.schema, type);
87
+ for (let depth = $pos.depth; depth >= 0; depth--) {
88
+ const node = $pos.node(depth);
89
+ if (node.type === nodeType && (!attrs || objectEqual(attrs, node.attrs))) {
90
+ return true;
91
+ }
92
+ }
93
+ return false;
94
+ }
95
+
96
+ // src/commands/toggle-node.ts
97
+ function toggleNode(options) {
98
+ return (state, dispatch, view) => {
99
+ if (isNodeActive(state, options.type, options.attrs)) {
100
+ const defaultType = state.schema.topNodeType.contentMatch.defaultType;
101
+ if (!defaultType) {
102
+ return false;
103
+ }
104
+ return setBlockType(defaultType)(state, dispatch, view);
105
+ } else {
106
+ const nodeType = getNodeType(state.schema, options.type);
107
+ return setBlockType(nodeType, options.attrs)(state, dispatch, view);
108
+ }
109
+ };
110
+ }
111
+
35
112
  // src/editor/editor.ts
36
- import { Schema as Schema2 } from "@prosekit/pm/model";
113
+ import { Schema as Schema3 } from "@prosekit/pm/model";
37
114
  import { EditorState } from "@prosekit/pm/state";
38
115
  import { EditorView } from "@prosekit/pm/view";
39
116
 
40
- // src/types/void-function.ts
41
- function voidFunction() {
117
+ // src/utils/is-mark-active.ts
118
+ function isMarkActive(state, type, attrs) {
119
+ const markType = getMarkType(state.schema, type);
120
+ const mark = attrs ? markType.create(attrs) : markType;
121
+ const { from, to } = state.selection;
122
+ return state.doc.rangeHasMark(from, to, mark);
42
123
  }
43
124
 
44
125
  // src/types/priority.ts
@@ -51,23 +132,57 @@ var Priority = /* @__PURE__ */ ((Priority2) => {
51
132
  return Priority2;
52
133
  })(Priority || {});
53
134
 
135
+ // src/utils/uniq-array.ts
136
+ function uniqPush(prev, next) {
137
+ const result = [...prev];
138
+ for (const item of next) {
139
+ if (!result.includes(item)) {
140
+ result.push(item);
141
+ }
142
+ }
143
+ return result;
144
+ }
145
+ function uniqRemove(prev, next) {
146
+ const result = [...prev];
147
+ for (const item of next) {
148
+ const index = result.indexOf(item);
149
+ if (index !== -1) {
150
+ result.splice(index, 1);
151
+ }
152
+ }
153
+ return result;
154
+ }
155
+
54
156
  // src/editor/facet.ts
55
157
  var nextIndex = 0;
56
158
  var Facet = class _Facet {
57
- constructor(combine, next) {
159
+ constructor(slot, next, single) {
58
160
  /** @internal */
59
161
  this.index = nextIndex++;
60
- this.combine = combine;
162
+ this.slot = slot;
61
163
  this.next = next;
164
+ this.single = single;
62
165
  }
63
- static define({ combine, next }) {
64
- return new _Facet(combine, next);
166
+ static define({
167
+ slot,
168
+ combine,
169
+ next,
170
+ single
171
+ }) {
172
+ const slotFn = slot ? slot : combine ? () => ({
173
+ create: combine,
174
+ update: combine
175
+ }) : null;
176
+ if (!slotFn) {
177
+ throw new ProseKitError(
178
+ "Facet must have either 'slot' or 'combine' option"
179
+ );
180
+ }
181
+ return new _Facet(slotFn, next, single != null ? single : false);
65
182
  }
66
183
  /** @internal */
67
- static defineSlot({
68
- combine
69
- }) {
70
- return new _Facet(combine, null);
184
+ static defineSlot(options) {
185
+ return _Facet.define(options);
71
186
  }
72
187
  extension(inputs) {
73
188
  return new FacetExtension(this, inputs);
@@ -130,7 +245,7 @@ function sortFacets(unsorted) {
130
245
  return sortedFacets;
131
246
  }
132
247
 
133
- // src/editor/slot.ts
248
+ // src/editor/slots.ts
134
249
  import OrderedMap from "orderedmap";
135
250
  var schemaSlot = Facet.defineSlot({
136
251
  combine: (specs) => {
@@ -149,7 +264,7 @@ var schemaSlot = Facet.defineSlot({
149
264
  var stateSlot = Facet.defineSlot({
150
265
  combine: (callbacks) => {
151
266
  return (ctx) => {
152
- var _a, _b, _c, _d, _e;
267
+ var _a, _b, _c, _d, _e, _f;
153
268
  const configs = callbacks.map((cb) => cb(ctx));
154
269
  const config = {
155
270
  schema: ctx.schema,
@@ -161,7 +276,7 @@ var stateSlot = Facet.defineSlot({
161
276
  config.doc = (_b = config.doc) != null ? _b : c.doc;
162
277
  config.selection = (_c = config.selection) != null ? _c : c.selection;
163
278
  config.storedMarks = [...config.storedMarks, ...(_d = c.storedMarks) != null ? _d : []];
164
- config.plugins = [...config.plugins, ...(_e = c.plugins) != null ? _e : []];
279
+ config.plugins = uniqPush((_e = config.plugins) != null ? _e : [], (_f = c.plugins) != null ? _f : []);
165
280
  }
166
281
  if (!config.doc && !config.schema) {
167
282
  throw new Error("Can't create state without a schema nor a document");
@@ -185,7 +300,46 @@ var commandSlot = Facet.defineSlot({
185
300
  });
186
301
 
187
302
  // src/editor/flatten.ts
188
- function flatten(root) {
303
+ function flattenInputTuple(inputTuple) {
304
+ return [
305
+ ...inputTuple[0],
306
+ ...inputTuple[1],
307
+ ...inputTuple[2],
308
+ ...inputTuple[3],
309
+ ...inputTuple[4]
310
+ ];
311
+ }
312
+ function mergeInputTuple(tupleA, tupleB) {
313
+ if (!tupleA)
314
+ return tupleB;
315
+ if (!tupleB)
316
+ return tupleA;
317
+ const [a0, a1, a2, a3, a4] = tupleA;
318
+ const [b0, b1, b2, b3, b4] = tupleB;
319
+ return [
320
+ uniqPush(a0, b0),
321
+ uniqPush(a1, b1),
322
+ uniqPush(a2, b2),
323
+ uniqPush(a3, b3),
324
+ uniqPush(a4, b4)
325
+ ];
326
+ }
327
+ function removeInputTuple(tupleA, tupleB) {
328
+ if (!tupleA)
329
+ return [[], [], [], [], []];
330
+ if (!tupleB)
331
+ return tupleA;
332
+ const [a0, a1, a2, a3, a4] = tupleA;
333
+ const [b0, b1, b2, b3, b4] = tupleB;
334
+ return [
335
+ uniqRemove(a0, b0),
336
+ uniqRemove(a1, b1),
337
+ uniqRemove(a2, b2),
338
+ uniqRemove(a3, b3),
339
+ uniqRemove(a4, b4)
340
+ ];
341
+ }
342
+ function extractFacets(root) {
189
343
  var _a;
190
344
  const extensions = [root];
191
345
  const priorities = [2 /* default */];
@@ -217,43 +371,97 @@ function flatten(root) {
217
371
  throw new Error("Invalid extension");
218
372
  }
219
373
  }
374
+ return [facets, inputs];
375
+ }
376
+ function updateExtension(prevInputs, prevSlots, extension, mode) {
377
+ const modifyInputTuple = mode === "add" ? mergeInputTuple : removeInputTuple;
378
+ const [facets, inputs] = extractFacets(extension);
220
379
  let schemaInput = null;
221
380
  let stateInput = null;
222
381
  let viewInput = null;
223
382
  let commandInput = null;
224
- const sortedFacets = sortFacets(facets);
225
- for (const facet of sortedFacets) {
226
- const nextFacet = facet.next;
227
- if (nextFacet) {
383
+ for (const facet of sortFacets(facets)) {
384
+ if (!inputs[facet.index]) {
385
+ continue;
386
+ }
387
+ const inputTuple = modifyInputTuple(
388
+ prevInputs[facet.index],
389
+ inputs[facet.index]
390
+ );
391
+ prevInputs[facet.index] = inputTuple;
392
+ if (facet.next && !facet.single) {
393
+ let hasOutput = false;
394
+ const outputTuple = [[], [], [], [], []];
228
395
  for (let pri = 0; pri < 5; pri++) {
229
- const input = inputs[facet.index][pri];
230
- if (input.length > 0) {
231
- const output = facet.combine(input);
232
- if (!inputs[nextFacet.index]) {
233
- inputs[nextFacet.index] = [[], [], [], [], []];
234
- }
235
- inputs[nextFacet.index][pri].push(output);
396
+ const inputArray = inputTuple[pri];
397
+ if (inputArray.length === 0) {
398
+ continue;
236
399
  }
400
+ const slotTuple = prevSlots[facet.index] || (prevSlots[facet.index] = [
401
+ void 0,
402
+ void 0,
403
+ void 0,
404
+ void 0,
405
+ void 0
406
+ ]);
407
+ const prevSlot = slotTuple[pri];
408
+ const slot = prevSlot || facet.slot();
409
+ prevSlots[facet.index][pri] = slot;
410
+ const output = prevSlot ? slot.update(inputArray) : slot.create(inputArray);
411
+ if (!output) {
412
+ continue;
413
+ }
414
+ hasOutput = true;
415
+ outputTuple[pri].push(output);
416
+ }
417
+ if (!hasOutput) {
418
+ continue;
237
419
  }
238
- } else if (inputs[facet.index]) {
239
- const [i1, i2, i3, i4, i5] = inputs[facet.index];
240
- const jointInputs = [...i1, ...i2, ...i3, ...i4, ...i5];
241
- const output = facet.combine(jointInputs);
242
- switch (facet) {
243
- case schemaSlot:
244
- schemaInput = output;
245
- break;
246
- case stateSlot:
247
- stateInput = output;
248
- break;
249
- case viewSlot:
250
- viewInput = output;
251
- break;
252
- case commandSlot:
253
- commandInput = output;
254
- break;
255
- default:
256
- throw new Error("Invalid facet");
420
+ inputs[facet.next.index] = modifyInputTuple(
421
+ inputs[facet.next.index],
422
+ outputTuple
423
+ );
424
+ continue;
425
+ } else {
426
+ const inputArray = flattenInputTuple(inputTuple);
427
+ const slotTuple = prevSlots[facet.index] || (prevSlots[facet.index] = [
428
+ void 0,
429
+ void 0,
430
+ void 0,
431
+ void 0,
432
+ void 0
433
+ ]);
434
+ const prevSlot = slotTuple[2 /* default */];
435
+ const slot = prevSlot || facet.slot();
436
+ prevSlots[facet.index][2 /* default */] = slot;
437
+ const output = prevSlot ? slot.update(inputArray) : slot.create(inputArray);
438
+ if (!output) {
439
+ continue;
440
+ }
441
+ const outputTuple = [[], [], [output], [], []];
442
+ if (facet.next) {
443
+ inputs[facet.next.index] = modifyInputTuple(
444
+ inputs[facet.next.index],
445
+ outputTuple
446
+ );
447
+ continue;
448
+ } else {
449
+ switch (facet) {
450
+ case schemaSlot:
451
+ schemaInput = output;
452
+ break;
453
+ case stateSlot:
454
+ stateInput = output;
455
+ break;
456
+ case viewSlot:
457
+ viewInput = output;
458
+ break;
459
+ case commandSlot:
460
+ commandInput = output;
461
+ break;
462
+ default:
463
+ throw new Error("Invalid facet");
464
+ }
257
465
  }
258
466
  }
259
467
  }
@@ -264,30 +472,58 @@ function flatten(root) {
264
472
  function createEditor({
265
473
  extension
266
474
  }) {
267
- const { schemaInput, stateInput, viewInput, commandInput } = flatten(extension);
268
- if (!schemaInput) {
269
- throw new Error("Schema must be defined");
270
- }
271
- const schema = new Schema2(schemaInput);
272
- const stateConfig = stateInput ? stateInput({ schema }) : { schema };
273
- const state = EditorState.create(stateConfig);
274
- const directEditorProps = { state, ...viewInput };
275
- const instance = new EditorInstance(directEditorProps);
276
- if (commandInput) {
277
- for (const [name, commandCreator] of Object.entries(commandInput)) {
278
- instance.addCommand(name, commandCreator);
279
- }
280
- }
281
- return Editor.create(instance);
475
+ const instance = new EditorInstance(extension);
476
+ const editor = Editor.create(instance);
477
+ return editor;
282
478
  }
283
479
  var EditorInstance = class {
284
- constructor(directEditorProps) {
285
- this.directEditorProps = directEditorProps;
480
+ constructor(extension) {
286
481
  this.view = null;
287
482
  this.commandDispatchers = {};
483
+ this.inputs = [];
484
+ this.slots = [];
288
485
  this.mount = this.mount.bind(this);
289
486
  this.unmount = this.unmount.bind(this);
290
- this.schema = directEditorProps.state.schema;
487
+ const { schemaInput, stateInput, viewInput, commandInput } = updateExtension(this.inputs, this.slots, extension, "add");
488
+ if (!schemaInput) {
489
+ throw new Error("Schema must be defined");
490
+ }
491
+ const schema = new Schema3(schemaInput);
492
+ const stateConfig = stateInput ? stateInput({ schema }) : { schema };
493
+ const state = EditorState.create(stateConfig);
494
+ if (commandInput) {
495
+ for (const [name, commandCreator] of Object.entries(commandInput)) {
496
+ this.addCommand(name, commandCreator);
497
+ }
498
+ }
499
+ this.directEditorProps = { state, ...viewInput };
500
+ this.schema = this.directEditorProps.state.schema;
501
+ }
502
+ updateExtension(extension, mode) {
503
+ var _a;
504
+ const { schemaInput, stateInput, viewInput, commandInput } = updateExtension(this.inputs, this.slots, extension, mode);
505
+ if (schemaInput) {
506
+ throw new ProseKitError("Schema cannot be changed");
507
+ }
508
+ if (viewInput) {
509
+ throw new ProseKitError("View cannot be changed");
510
+ }
511
+ const plugins = (_a = stateInput == null ? void 0 : stateInput({ schema: this.schema })) == null ? void 0 : _a.plugins;
512
+ if (plugins && plugins.length > 0) {
513
+ if (!this.view) {
514
+ throw new ProseKitError(
515
+ "Unexpected inner state: EditorInstance.view is not defined"
516
+ );
517
+ }
518
+ const state = this.view.state.reconfigure({ plugins });
519
+ this.view.updateState(state);
520
+ }
521
+ if (commandInput) {
522
+ const names = Object.keys(commandInput);
523
+ for (const name of names) {
524
+ this.addCommand(name, commandInput[name]);
525
+ }
526
+ }
291
527
  }
292
528
  mount(place) {
293
529
  if (this.view) {
@@ -349,7 +585,7 @@ var Editor = class _Editor {
349
585
  /** @internal */
350
586
  static create(instance) {
351
587
  if (!(instance instanceof EditorInstance)) {
352
- throw new TypeError("Editor's instance is not EditorInstance");
588
+ throw new TypeError("Invalid EditorInstance");
353
589
  }
354
590
  return new _Editor(instance);
355
591
  }
@@ -388,33 +624,14 @@ var Editor = class _Editor {
388
624
  lazyRemove == null ? void 0 : lazyRemove();
389
625
  };
390
626
  }
391
- const { schemaInput, stateInput, viewInput, commandInput } = flatten(extension);
392
- if (schemaInput) {
393
- throw new ProseKitError("Schema cannot be changed");
394
- }
395
- if (viewInput) {
396
- throw new ProseKitError("View cannot be changed");
397
- }
398
- if (stateInput) {
399
- const stateConfig = stateInput({ schema: this.schema });
400
- const plugins = stateConfig.plugins;
401
- if (plugins && plugins.length > 0) {
402
- this.instance.addPlugins(plugins);
403
- return () => this.instance.removePlugins(plugins);
404
- }
405
- }
406
- if (commandInput) {
407
- const names = Object.keys(commandInput);
408
- for (const name of names) {
409
- this.instance.addCommand(name, commandInput[name]);
410
- }
411
- return () => {
412
- for (const name of names) {
413
- this.instance.removeCommand(name);
414
- }
415
- };
416
- }
417
- return voidFunction;
627
+ this.instance.updateExtension(extension, "add");
628
+ return () => this.instance.updateExtension(extension, "remove");
629
+ }
630
+ isNodeActive(nodeType, attrs) {
631
+ return isNodeActive(this.view.state, nodeType, attrs);
632
+ }
633
+ isMarkActive(markType, attrs) {
634
+ return isMarkActive(this.view.state, markType, attrs);
418
635
  }
419
636
  };
420
637
 
@@ -433,7 +650,7 @@ function withPriority(extension, priority) {
433
650
 
434
651
  // src/extensions/command.ts
435
652
  import "@prosekit/pm/model";
436
- import { AllSelection, Selection } from "@prosekit/pm/state";
653
+ import { AllSelection } from "@prosekit/pm/state";
437
654
  import { findWrapping, insertPoint } from "@prosekit/pm/transform";
438
655
  function addCommands(commands) {
439
656
  return commandSlot.extension([commands]);
@@ -463,8 +680,6 @@ function addBaseCommands() {
463
680
  return false;
464
681
  if (dispatch) {
465
682
  const tr = state.tr.insert(insertPos, node);
466
- const $pos = tr.doc.resolve(insertPos);
467
- tr.setSelection(Selection.near($pos));
468
683
  dispatch(tr);
469
684
  }
470
685
  return true;
@@ -583,8 +798,8 @@ var inputRuleFacet = Facet.define({
583
798
 
584
799
  // src/extensions/keymap.ts
585
800
  import { baseKeymap, chainCommands } from "@prosekit/pm/commands";
586
- import { keymap as createKeymapPlugin } from "@prosekit/pm/keymap";
587
- import "@prosekit/pm/state";
801
+ import { keydownHandler } from "@prosekit/pm/keymap";
802
+ import { Plugin as Plugin3, PluginKey } from "@prosekit/pm/state";
588
803
  function addKeymap(keymap) {
589
804
  return keymapFacet.extension([keymap]);
590
805
  }
@@ -592,20 +807,38 @@ function addBaseKeymap() {
592
807
  return addKeymap(baseKeymap);
593
808
  }
594
809
  var keymapFacet = Facet.define({
595
- combine: (keymaps) => {
596
- const keymap = mergeKeymaps(keymaps);
597
- const plugin = createKeymapPlugin(keymap);
598
- return () => [plugin];
810
+ slot: () => {
811
+ let handler = null;
812
+ const handlerWrapper = (view, event) => {
813
+ if (handler)
814
+ return handler(view, event);
815
+ return false;
816
+ };
817
+ const plugin = new Plugin3({
818
+ key: keymapPluginKey,
819
+ props: { handleKeyDown: handlerWrapper }
820
+ });
821
+ const pluginFunc = () => [plugin];
822
+ return {
823
+ create: (keymaps) => {
824
+ handler = keydownHandler(mergeKeymaps(keymaps));
825
+ return pluginFunc;
826
+ },
827
+ update: (keymaps) => {
828
+ handler = keydownHandler(mergeKeymaps(keymaps));
829
+ return null;
830
+ }
831
+ };
599
832
  },
600
- next: pluginFacet
833
+ next: pluginFacet,
834
+ single: true
601
835
  });
602
836
  function mergeKeymaps(keymaps) {
603
837
  const bindings = {};
604
838
  for (const keymap of keymaps) {
605
839
  for (const [key, command] of Object.entries(keymap)) {
606
- if (!bindings[key])
607
- bindings[key] = [];
608
- bindings[key].push(command);
840
+ const commands = bindings[key] || (bindings[key] = []);
841
+ commands.push(command);
609
842
  }
610
843
  }
611
844
  return Object.fromEntries(
@@ -615,6 +848,7 @@ function mergeKeymaps(keymaps) {
615
848
  ])
616
849
  );
617
850
  }
851
+ var keymapPluginKey = new PluginKey("prosekit-keymap");
618
852
 
619
853
  // src/extensions/mark-spec.ts
620
854
  function addMarkSpec(options) {
@@ -677,19 +911,6 @@ function addText() {
677
911
  }
678
912
  });
679
913
  }
680
-
681
- // src/utils/get-node-type.ts
682
- import "@prosekit/pm/model";
683
- function getNodeType(schema, type) {
684
- if (typeof type === "string") {
685
- const nodeType = schema.nodes[type];
686
- if (!nodeType) {
687
- throw new ProseKitError(`Cannot find ProseMirror node type "${type}"`);
688
- }
689
- return nodeType;
690
- }
691
- return type;
692
- }
693
914
  export {
694
915
  Editor,
695
916
  Facet,
@@ -714,5 +935,6 @@ export {
714
935
  getNodeType,
715
936
  pluginFacet,
716
937
  toggleMark,
938
+ toggleNode,
717
939
  withPriority
718
940
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/core",
3
3
  "type": "module",
4
- "version": "0.0.4",
4
+ "version": "0.0.6",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -40,7 +40,7 @@
40
40
  "dependencies": {
41
41
  "@prosekit/pm": "^0.0.3",
42
42
  "orderedmap": "^2.1.1",
43
- "type-fest": "^3.13.1"
43
+ "type-fest": "^4.0.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@prosekit/dev": "*",
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { toggleMark } from './commands/toggle-mark'
1
+ export { toggleMark, type ToggleMarkOptions } from './commands/toggle-mark'
2
+ export { toggleNode, type ToggleNodeOptions } from './commands/toggle-node'
2
3
  export { Editor, createEditor, type EditorOptions } from './editor/editor'
3
4
  export { Facet, FacetExtension, type FacetOptions } from './editor/facet'
4
5
  export { defineExtension } from './editor/type-utils'
@@ -27,6 +28,7 @@ export {
27
28
  type ExtractCommandDispatchers,
28
29
  type ExtractMarks,
29
30
  type ExtractNodes,
31
+ type SimplifyExtension,
30
32
  } from './types/extension'
31
33
  export { type ExtensionTyping } from './types/extension-typing'
32
34
  export { Priority } from './types/priority'