@prosekit/core 0.0.9 → 0.0.11

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.
@@ -8,6 +8,7 @@ import { EditorView } from '@prosekit/pm/view';
8
8
  import type { EmptyObject } from 'type-fest';
9
9
  import { InputRule } from '@prosekit/pm/inputrules';
10
10
  import type { IsEqual } from 'type-fest';
11
+ import { Mark } from '@prosekit/pm/model';
11
12
  import type { MarkSpec } from '@prosekit/pm/model';
12
13
  import { MarkType } from '@prosekit/pm/model';
13
14
  import type { NodeSpec } from '@prosekit/pm/model';
@@ -15,6 +16,7 @@ import { NodeType } from '@prosekit/pm/model';
15
16
  import { NodeViewConstructor } from '@prosekit/pm/view';
16
17
  import { Options } from 'tsup';
17
18
  import { Plugin as Plugin_2 } from '@prosekit/pm/state';
19
+ import { ProseMirrorFragment } from '@prosekit/pm/model';
18
20
  import { ProseMirrorNode } from '@prosekit/pm/model';
19
21
  import { Schema } from '@prosekit/pm/model';
20
22
  import type { SchemaSpec } from '@prosekit/pm/model';
@@ -84,6 +86,27 @@ NODES: "doc";
84
86
  export { addDoc }
85
87
  export { addDoc as addDoc_alias_1 }
86
88
 
89
+ /**
90
+ * @internal
91
+ */
92
+ declare function addEventHandler(options: {
93
+ update?: VoidFunction;
94
+ }): FacetExtension<VoidFunction, PluginFacetInput>;
95
+ export { addEventHandler }
96
+ export { addEventHandler as addEventHandler_alias_1 }
97
+
98
+ /**
99
+ * Add undo/redo history to the editor.
100
+ */
101
+ declare function addHistory(): Extension< {
102
+ COMMAND_ARGS: {
103
+ undo: [];
104
+ redo: [];
105
+ };
106
+ }>;
107
+ export { addHistory }
108
+ export { addHistory as addHistory_alias_1 }
109
+
87
110
  /**
88
111
  * @public
89
112
  */
@@ -176,6 +199,13 @@ export declare function applyAction(operator: Action): Command;
176
199
  */
177
200
  export declare function assertTypeEqual<T, U>(_val: IsEqual<T, U>): void;
178
201
 
202
+ export declare function collectNodes(content: NodeContent): ProseMirrorNode[];
203
+
204
+ export declare interface CommandApplier<Args extends any[] = any[]> {
205
+ (...args: Args): boolean;
206
+ canApply(...args: Args): boolean;
207
+ }
208
+
179
209
  /** @internal */
180
210
  declare interface CommandArgs {
181
211
  [name: string]: any[];
@@ -189,8 +219,6 @@ export declare interface CommandCreators {
189
219
  [name: string]: CommandCreator;
190
220
  }
191
221
 
192
- export declare type CommandDispatcher<Args extends any[] = any[]> = (...arg: Args) => boolean;
193
-
194
222
  export declare const commandSlot: Facet<CommandSlotInput, CommandSlotInput>;
195
223
 
196
224
  export declare type CommandSlotInput = Record<string, CommandCreator<any>>;
@@ -200,6 +228,10 @@ declare function createEditor<E extends Extension>({ extension, defaultDoc, defa
200
228
  export { createEditor }
201
229
  export { createEditor as createEditor_alias_1 }
202
230
 
231
+ export declare function createMarkBuilder(getState: () => EditorState | null | undefined, type: MarkType): MarkBuilder;
232
+
233
+ export declare function createNodeBuilder(getState: () => EditorState | null | undefined, type: NodeType): NodeBuilder;
234
+
203
235
  export declare const default_alias: Options | Options[] | ((overrideOptions: Options) => Options | Options[] | Promise<Options | Options[]>);
204
236
 
205
237
  export declare const default_alias_1: UserProjectConfigExport;
@@ -231,12 +263,20 @@ declare class Editor<E extends Extension = any> {
231
263
  get mounted(): boolean;
232
264
  get view(): EditorView;
233
265
  get schema(): Schema<ExtractNodes<E>, ExtractMarks<E>>;
234
- get commands(): ExtractCommandDispatchers<E>;
266
+ get commands(): ExtractCommandAppliers<E>;
235
267
  mount(place: HTMLElement | null | undefined | void): void;
236
268
  unmount(): void;
237
269
  use(extension: Extension): VoidFunction;
270
+ /**
271
+ * @deprecated
272
+ */
238
273
  isNodeActive(nodeType: string | NodeType, attrs?: Attrs): boolean;
274
+ /**
275
+ * @deprecated
276
+ */
239
277
  isMarkActive(markType: string | MarkType, attrs?: Attrs): boolean;
278
+ get nodes(): Record<ExtractNodes<E>, NodeBuilder>;
279
+ get marks(): Record<ExtractMarks<E>, MarkBuilder>;
240
280
  }
241
281
  export { Editor }
242
282
  export { Editor as Editor_alias_1 }
@@ -287,6 +327,13 @@ declare interface ExtensionTyping<Node extends string = string, Mark extends str
287
327
  export { ExtensionTyping }
288
328
  export { ExtensionTyping as ExtensionTyping_alias_1 }
289
329
 
330
+ /**
331
+ * @public
332
+ */
333
+ declare type ExtractCommandAppliers<E extends Extension> = ToCommandApplier<ExtractCommandArgs<E>>;
334
+ export { ExtractCommandAppliers }
335
+ export { ExtractCommandAppliers as ExtractCommandAppliers_alias_1 }
336
+
290
337
  /**
291
338
  * @internal
292
339
  */
@@ -301,13 +348,6 @@ declare type ExtractCommandCreators<E extends Extension> = ToCommandCreators<Ext
301
348
  export { ExtractCommandCreators }
302
349
  export { ExtractCommandCreators as ExtractCommandCreators_alias_1 }
303
350
 
304
- /**
305
- * @public
306
- */
307
- declare type ExtractCommandDispatchers<E extends Extension> = ToCommandDispatcher<ExtractCommandArgs<E>>;
308
- export { ExtractCommandDispatchers }
309
- export { ExtractCommandDispatchers as ExtractCommandDispatchers_alias_1 }
310
-
311
351
  /**
312
352
  * @intneral
313
353
  */
@@ -396,10 +436,16 @@ export declare function insertNode({ node, pos, }: {
396
436
  pos?: number;
397
437
  }): Action;
398
438
 
439
+ export declare const isMac: boolean;
440
+
441
+ export declare function isMark(mark: unknown): mark is Mark;
442
+
399
443
  export declare function isMarkActive(state: EditorState, type: string | MarkType, attrs?: Attrs | null): boolean;
400
444
 
401
445
  export declare function isNodeActive(state: EditorState, type: string | NodeType, attrs?: Attrs | null): boolean;
402
446
 
447
+ export declare function isProseMirrorNode(node: unknown): node is ProseMirrorNode;
448
+
403
449
  /** @public */
404
450
  declare interface Keymap {
405
451
  [key: string]: Command;
@@ -407,6 +453,12 @@ declare interface Keymap {
407
453
  export { Keymap }
408
454
  export { Keymap as Keymap_alias_1 }
409
455
 
456
+ export declare interface MarkBuilder {
457
+ (attrs: Attrs | null, ...children: NodeChild[]): ProseMirrorNode[];
458
+ (...children: NodeChild[]): ProseMirrorNode[];
459
+ isActive(attrs?: Attrs): boolean;
460
+ }
461
+
410
462
  /**
411
463
  * @public
412
464
  */
@@ -416,6 +468,16 @@ declare interface MarkSpecOptions<MarkName extends string = string> extends Mark
416
468
  export { MarkSpecOptions }
417
469
  export { MarkSpecOptions as MarkSpecOptions_alias_1 }
418
470
 
471
+ export declare interface NodeBuilder {
472
+ (attrs: Attrs | null, ...children: NodeChild[]): ProseMirrorNode;
473
+ (...children: NodeChild[]): ProseMirrorNode;
474
+ isActive(attrs?: Attrs): boolean;
475
+ }
476
+
477
+ export declare type NodeChild = ProseMirrorNode | string | NodeChild[];
478
+
479
+ export declare type NodeContent = ProseMirrorNode | ProseMirrorFragment | NodeContent[];
480
+
419
481
  /**
420
482
  * A JSON representation of the prosemirror node.
421
483
  *
@@ -566,6 +628,10 @@ export { StateJson as StateJson_alias_1 }
566
628
 
567
629
  export declare const stateSlot: Facet<StateConfigCallback, StateConfigCallback>;
568
630
 
631
+ export declare type ToCommandApplier<T extends CommandArgs> = {
632
+ [K in keyof T]: CommandApplier<T[K]>;
633
+ };
634
+
569
635
  export declare type ToCommandArgs<T extends CommandCreators> = {
570
636
  [K in keyof T]: Parameters<T[K]>;
571
637
  };
@@ -574,10 +640,6 @@ export declare type ToCommandCreators<T extends CommandArgs> = {
574
640
  [K in keyof T]: CommandCreator<T[K]>;
575
641
  };
576
642
 
577
- export declare type ToCommandDispatcher<T extends CommandArgs> = {
578
- [K in keyof T]: CommandDispatcher<T[K]>;
579
- };
580
-
581
643
  declare function toggleMark(options: ToggleMarkOptions): Command;
582
644
  export { toggleMark }
583
645
  export { toggleMark as toggleMark_alias_1 }
@@ -18,6 +18,8 @@ export { addCommands } from './_tsup-dts-rollup';
18
18
  export { addDefaultState } from './_tsup-dts-rollup';
19
19
  export { DefaultStateOptions } from './_tsup-dts-rollup';
20
20
  export { addDoc } from './_tsup-dts-rollup';
21
+ export { addEventHandler } from './_tsup-dts-rollup';
22
+ export { addHistory } from './_tsup-dts-rollup';
21
23
  export { addInputRule } from './_tsup-dts-rollup';
22
24
  export { addBaseKeymap } from './_tsup-dts-rollup';
23
25
  export { addKeymap } from './_tsup-dts-rollup';
@@ -35,8 +37,8 @@ export { PluginFacetInput } from './_tsup-dts-rollup';
35
37
  export { addText } from './_tsup-dts-rollup';
36
38
  export { CommandArgs } from './_tsup-dts-rollup';
37
39
  export { Extension } from './_tsup-dts-rollup';
40
+ export { ExtractCommandAppliers } from './_tsup-dts-rollup';
38
41
  export { ExtractCommandCreators } from './_tsup-dts-rollup';
39
- export { ExtractCommandDispatchers } from './_tsup-dts-rollup';
40
42
  export { ExtractMarks } from './_tsup-dts-rollup';
41
43
  export { ExtractNodes } from './_tsup-dts-rollup';
42
44
  export { SimplifyExtension } from './_tsup-dts-rollup';
@@ -127,27 +127,15 @@ function toggleNode(options) {
127
127
  }
128
128
 
129
129
  // src/editor/editor.ts
130
- import { Schema as Schema3 } from "@prosekit/pm/model";
130
+ import { Schema as Schema4 } from "@prosekit/pm/model";
131
131
  import { EditorState } from "@prosekit/pm/state";
132
132
  import { EditorView } from "@prosekit/pm/view";
133
133
 
134
- // src/utils/is-mark-active.ts
135
- function isMarkActive(state, type, attrs) {
136
- const markType = getMarkType(state.schema, type);
137
- const mark = attrs ? markType.create(attrs) : markType;
138
- const { from, to } = state.selection;
139
- return state.doc.rangeHasMark(from, to, mark);
140
- }
134
+ // src/extensions/default-state.ts
135
+ import { Selection } from "@prosekit/pm/state";
141
136
 
142
- // src/types/priority.ts
143
- var Priority = /* @__PURE__ */ ((Priority2) => {
144
- Priority2[Priority2["lowest"] = 4] = "lowest";
145
- Priority2[Priority2["low"] = 3] = "low";
146
- Priority2[Priority2["default"] = 2] = "default";
147
- Priority2[Priority2["high"] = 1] = "high";
148
- Priority2[Priority2["highest"] = 0] = "highest";
149
- return Priority2;
150
- })(Priority || {});
137
+ // src/editor/slots.ts
138
+ import OrderedMap from "orderedmap";
151
139
 
152
140
  // src/utils/uniq-array.ts
153
141
  function uniqPush(prev, next) {
@@ -257,13 +245,12 @@ function sortFacets(unsorted) {
257
245
  }
258
246
  }
259
247
  if (facetCount !== sortedFacets.length) {
260
- throw new Error(`Facet has circular dependency`);
248
+ throw new ProseKitError(`Facet has circular dependency`);
261
249
  }
262
250
  return sortedFacets;
263
251
  }
264
252
 
265
253
  // src/editor/slots.ts
266
- import OrderedMap from "orderedmap";
267
254
  var schemaSlot = Facet.defineSlot({
268
255
  combine: (specs) => {
269
256
  var _a;
@@ -296,7 +283,9 @@ var stateSlot = Facet.defineSlot({
296
283
  config.plugins = uniqPush((_e = config.plugins) != null ? _e : [], (_f = c.plugins) != null ? _f : []);
297
284
  }
298
285
  if (!config.doc && !config.schema) {
299
- throw new Error("Can't create state without a schema nor a document");
286
+ throw new ProseKitError(
287
+ "Can't create state without a schema nor a document"
288
+ );
300
289
  }
301
290
  if (config.doc) {
302
291
  config.schema = void 0;
@@ -316,6 +305,128 @@ var commandSlot = Facet.defineSlot({
316
305
  }
317
306
  });
318
307
 
308
+ // src/extensions/default-state.ts
309
+ function addDefaultState(options) {
310
+ return stateSlot.extension([
311
+ ({ schema }) => {
312
+ const config = {};
313
+ if (options.doc) {
314
+ config.doc = schema.nodeFromJSON(options.doc);
315
+ if (options.selection) {
316
+ config.selection = Selection.fromJSON(config.doc, options.selection);
317
+ }
318
+ }
319
+ return config;
320
+ }
321
+ ]);
322
+ }
323
+
324
+ // src/utils/type-assertion.ts
325
+ import { Mark, ProseMirrorNode } from "@prosekit/pm/model";
326
+ function isProseMirrorNode(node) {
327
+ return node instanceof ProseMirrorNode;
328
+ }
329
+ function isMark(mark) {
330
+ return mark instanceof Mark;
331
+ }
332
+
333
+ // src/utils/is-mark-active.ts
334
+ function isMarkActive(state, type, attrs) {
335
+ var _a;
336
+ const markType = getMarkType(state.schema, type);
337
+ const mark = attrs ? markType.create(attrs) : markType;
338
+ const { from, to, $from, $to } = state.selection;
339
+ return state.doc.rangeHasMark(from, to, mark) || hasMark(
340
+ [...$from.marks(), ...$to.marks(), ...(_a = state.storedMarks) != null ? _a : []],
341
+ mark
342
+ );
343
+ }
344
+ function hasMark(marks, mark) {
345
+ if (marks.length === 0) {
346
+ return false;
347
+ }
348
+ if (isMark(mark)) {
349
+ return marks.some((m) => m.eq(mark));
350
+ } else {
351
+ return marks.some((m) => m.type === mark);
352
+ }
353
+ }
354
+
355
+ // src/editor/builder.ts
356
+ import "@prosekit/pm/model";
357
+ function createNodeBuilder(getState, type) {
358
+ const builder = (...args) => buildNode(type, args);
359
+ builder.isActive = (attrs) => {
360
+ const state = getState();
361
+ return state ? isNodeActive(state, type, attrs) : false;
362
+ };
363
+ return builder;
364
+ }
365
+ function createMarkBuilder(getState, type) {
366
+ const builder = (...args) => buildMark(type, args);
367
+ builder.isActive = (attrs) => {
368
+ const state = getState();
369
+ return state ? isMarkActive(state, type, attrs) : false;
370
+ };
371
+ return builder;
372
+ }
373
+ function buildMark(type, args) {
374
+ const [attrs, children] = normalizeArgs(args);
375
+ return flattenChildren(type.schema, children, type.create(attrs));
376
+ }
377
+ function buildNode(type, args) {
378
+ const [attrs, children] = normalizeArgs(args);
379
+ const node = type.createAndFill(attrs, flattenChildren(type.schema, children));
380
+ if (!node) {
381
+ throw new ProseKitError(`Couldn't create node ${type.name}`);
382
+ }
383
+ return node;
384
+ }
385
+ function flattenChildren(schema, children, mark) {
386
+ const nodes = [];
387
+ for (const child of children) {
388
+ if (typeof child === "string") {
389
+ if (child) {
390
+ nodes.push(schema.text(child, mark ? [mark] : null));
391
+ }
392
+ } else if (Array.isArray(child)) {
393
+ nodes.push(...flattenChildren(schema, child, mark));
394
+ } else if (isProseMirrorNode(child)) {
395
+ nodes.push(mark ? child.mark(mark.addToSet(child.marks)) : child);
396
+ } else {
397
+ throw new ProseKitError(`Invalid node child: ${typeof child}`);
398
+ }
399
+ }
400
+ return nodes;
401
+ }
402
+ function normalizeArgs(args) {
403
+ const [attrs, ...children] = args;
404
+ if (isNodeChild(args)) {
405
+ children.unshift(args);
406
+ return [null, children];
407
+ } else if (typeof attrs === "object") {
408
+ return [attrs, children];
409
+ } else {
410
+ return [null, children];
411
+ }
412
+ }
413
+ function isNodeChild(value) {
414
+ if (!value) {
415
+ return false;
416
+ }
417
+ return typeof value === "string" || Array.isArray(value) || isProseMirrorNode(value);
418
+ }
419
+
420
+ // src/types/priority.ts
421
+ var Priority = /* @__PURE__ */ ((Priority2) => {
422
+ Priority2[Priority2["lowest"] = 4] = "lowest";
423
+ Priority2[Priority2["low"] = 3] = "low";
424
+ Priority2[Priority2["default"] = 2] = "default";
425
+ Priority2[Priority2["high"] = 1] = "high";
426
+ Priority2[Priority2["highest"] = 0] = "highest";
427
+ return Priority2;
428
+ })(Priority || {});
429
+
319
430
  // src/editor/flatten.ts
320
431
  function flattenInputTuple(inputTuple) {
321
432
  return [
@@ -385,7 +496,7 @@ function extractFacets(root) {
385
496
  priorities.push(p);
386
497
  }
387
498
  } else {
388
- throw new Error("Invalid extension");
499
+ throw new ProseKitError("Invalid extension");
389
500
  }
390
501
  }
391
502
  return [facets, inputs];
@@ -477,7 +588,7 @@ function updateExtension(prevInputs, prevSlots, extension, mode) {
477
588
  commandInput = output;
478
589
  break;
479
590
  default:
480
- throw new Error("Invalid facet");
591
+ throw new ProseKitError("Invalid facet");
481
592
  }
482
593
  }
483
594
  }
@@ -485,6 +596,14 @@ function updateExtension(prevInputs, prevSlots, extension, mode) {
485
596
  return { schemaInput, stateInput, viewInput, commandInput };
486
597
  }
487
598
 
599
+ // src/editor/type-utils.ts
600
+ function defineExtension(extension) {
601
+ if (extension && Array.isArray(extension)) {
602
+ return { extension };
603
+ }
604
+ return extension;
605
+ }
606
+
488
607
  // src/editor/editor.ts
489
608
  function createEditor({
490
609
  extension,
@@ -505,16 +624,16 @@ function createEditor({
505
624
  var EditorInstance = class {
506
625
  constructor(extension) {
507
626
  this.view = null;
508
- this.commandDispatchers = {};
627
+ this.commandAppliers = {};
509
628
  this.inputs = [];
510
629
  this.slots = [];
511
630
  this.mount = this.mount.bind(this);
512
631
  this.unmount = this.unmount.bind(this);
513
632
  const { schemaInput, stateInput, viewInput, commandInput } = updateExtension(this.inputs, this.slots, extension, "add");
514
633
  if (!schemaInput) {
515
- throw new Error("Schema must be defined");
634
+ throw new ProseKitError("Schema must be defined");
516
635
  }
517
- const schema = new Schema3(schemaInput);
636
+ const schema = new Schema4(schemaInput);
518
637
  const stateConfig = stateInput ? stateInput({ schema }) : { schema };
519
638
  const state = EditorState.create(stateConfig);
520
639
  if (commandInput) {
@@ -524,6 +643,22 @@ var EditorInstance = class {
524
643
  }
525
644
  this.directEditorProps = { state, ...viewInput };
526
645
  this.schema = this.directEditorProps.state.schema;
646
+ const getState = () => {
647
+ var _a;
648
+ return (_a = this.view) == null ? void 0 : _a.state;
649
+ };
650
+ this.nodeBuilders = Object.fromEntries(
651
+ Object.values(this.schema.nodes).map((type) => [
652
+ type.name,
653
+ createNodeBuilder(getState, type)
654
+ ])
655
+ );
656
+ this.markBuilders = Object.fromEntries(
657
+ Object.values(this.schema.marks).map((type) => [
658
+ type.name,
659
+ createMarkBuilder(getState, type)
660
+ ])
661
+ );
527
662
  }
528
663
  updateExtension(extension, mode) {
529
664
  var _a;
@@ -553,23 +688,23 @@ var EditorInstance = class {
553
688
  }
554
689
  mount(place) {
555
690
  if (this.view) {
556
- throw new Error("Editor is already mounted");
691
+ throw new ProseKitError("Editor is already mounted");
557
692
  }
558
693
  if (!place) {
559
- throw new Error("Can't mount editor without a place");
694
+ throw new ProseKitError("Can't mount editor without a place");
560
695
  }
561
696
  this.view = new EditorView({ mount: place }, this.directEditorProps);
562
697
  }
563
698
  unmount() {
564
699
  if (!this.view) {
565
- throw new Error("Editor is not mounted yet");
700
+ throw new ProseKitError("Editor is not mounted yet");
566
701
  }
567
702
  this.view.destroy();
568
703
  this.view = null;
569
704
  }
570
705
  get assertView() {
571
706
  if (!this.view)
572
- throw new Error("Editor is not mounted");
707
+ throw new ProseKitError("Editor is not mounted");
573
708
  return this.view;
574
709
  }
575
710
  addPlugins(plugins) {
@@ -589,15 +724,26 @@ var EditorInstance = class {
589
724
  view.setProps({ state: newState });
590
725
  }
591
726
  addCommand(name, commandCreator) {
592
- const dispatcher = (...args) => {
593
- const view = this.assertView;
727
+ const applier = (...args) => {
728
+ const view = this.view;
729
+ if (!view) {
730
+ return false;
731
+ }
594
732
  const command = commandCreator(...args);
595
733
  return command(view.state, view.dispatch.bind(view), view);
596
734
  };
597
- this.commandDispatchers[name] = dispatcher;
735
+ applier.canApply = (...args) => {
736
+ const view = this.view;
737
+ if (!view) {
738
+ return false;
739
+ }
740
+ const command = commandCreator(...args);
741
+ return command(view.state, void 0, view);
742
+ };
743
+ this.commandAppliers[name] = applier;
598
744
  }
599
745
  removeCommand(name) {
600
- delete this.commandDispatchers[name];
746
+ delete this.commandAppliers[name];
601
747
  }
602
748
  };
603
749
  var Editor = class _Editor {
@@ -625,7 +771,7 @@ var Editor = class _Editor {
625
771
  return this.instance.schema;
626
772
  }
627
773
  get commands() {
628
- return this.instance.commandDispatchers;
774
+ return this.instance.commandAppliers;
629
775
  }
630
776
  mount(place) {
631
777
  if (!place) {
@@ -653,21 +799,25 @@ var Editor = class _Editor {
653
799
  this.instance.updateExtension(extension, "add");
654
800
  return () => this.instance.updateExtension(extension, "remove");
655
801
  }
802
+ /**
803
+ * @deprecated
804
+ */
656
805
  isNodeActive(nodeType, attrs) {
657
806
  return isNodeActive(this.view.state, nodeType, attrs);
658
807
  }
808
+ /**
809
+ * @deprecated
810
+ */
659
811
  isMarkActive(markType, attrs) {
660
812
  return isMarkActive(this.view.state, markType, attrs);
661
813
  }
662
- };
663
-
664
- // src/editor/type-utils.ts
665
- function defineExtension(extension) {
666
- if (extension && Array.isArray(extension)) {
667
- return { extension };
814
+ get nodes() {
815
+ return this.instance.nodeBuilders;
668
816
  }
669
- return extension;
670
- }
817
+ get marks() {
818
+ return this.instance.markBuilders;
819
+ }
820
+ };
671
821
 
672
822
  // src/editor/with-priority.ts
673
823
  function withPriority(extension, priority) {
@@ -749,23 +899,6 @@ function addBaseCommands() {
749
899
  });
750
900
  }
751
901
 
752
- // src/extensions/default-state.ts
753
- import { Selection } from "@prosekit/pm/state";
754
- function addDefaultState(options) {
755
- return stateSlot.extension([
756
- ({ schema }) => {
757
- const config = {};
758
- if (options.doc) {
759
- config.doc = schema.nodeFromJSON(options.doc);
760
- if (options.selection) {
761
- config.selection = Selection.fromJSON(config.doc, options.selection);
762
- }
763
- }
764
- return config;
765
- }
766
- ]);
767
- }
768
-
769
902
  // src/extensions/node-spec.ts
770
903
  function addNodeSpec(options) {
771
904
  return nodeSpecFacet.extension([options]);
@@ -776,7 +909,7 @@ var nodeSpecFacet = Facet.define({
776
909
  let topNodeName = void 0;
777
910
  for (const { name, topNode, ...spec } of options) {
778
911
  if (nodes[name]) {
779
- throw new Error(`Node type ${name} has already been defined`);
912
+ throw new ProseKitError(`Node type ${name} has already been defined`);
780
913
  }
781
914
  if (topNodeName && !topNode) {
782
915
  topNodeName = name;
@@ -796,10 +929,12 @@ function addDoc() {
796
929
  });
797
930
  }
798
931
 
799
- // src/extensions/input-rules.ts
800
- import { inputRules } from "@prosekit/pm/inputrules";
801
- import "@prosekit/pm/model";
802
- import "@prosekit/pm/state";
932
+ // src/extensions/event-handler.ts
933
+ import { PluginKey, ProseMirrorPlugin } from "@prosekit/pm/state";
934
+
935
+ // src/types/void-function.ts
936
+ function voidFunction() {
937
+ }
803
938
 
804
939
  // src/extensions/plugin.ts
805
940
  import "@prosekit/pm/model";
@@ -826,24 +961,52 @@ var pluginFacet = Facet.define({
826
961
  next: stateSlot
827
962
  });
828
963
 
829
- // src/extensions/input-rules.ts
830
- function addInputRule(rules) {
831
- return inputRuleFacet.extension([rules]);
964
+ // src/extensions/event-handler.ts
965
+ function addEventHandler(options) {
966
+ var _a;
967
+ const updateHandler = (_a = options == null ? void 0 : options.update) != null ? _a : voidFunction;
968
+ return eventFacet.extension([updateHandler]);
832
969
  }
833
- var inputRuleFacet = Facet.define({
834
- combine: (inputs) => {
835
- return (context) => {
836
- const rules = inputs.flatMap((callback) => callback(context));
837
- return [inputRules({ rules })];
970
+ var eventFacet = Facet.define({
971
+ slot: () => {
972
+ let updateHandlers = [];
973
+ const plugin = new ProseMirrorPlugin({
974
+ key: pluginKey,
975
+ view: () => {
976
+ return {
977
+ update: (_view, _prevState) => {
978
+ updateHandlers.forEach((fn) => fn());
979
+ }
980
+ };
981
+ }
982
+ });
983
+ const pluginFunc = () => [plugin];
984
+ return {
985
+ create: (handlers) => {
986
+ updateHandlers = handlers;
987
+ return pluginFunc;
988
+ },
989
+ update: (handlers) => {
990
+ updateHandlers = handlers;
991
+ return null;
992
+ }
838
993
  };
839
994
  },
840
- next: pluginFacet
995
+ next: pluginFacet,
996
+ single: true
841
997
  });
998
+ var pluginKey = new PluginKey("prosekit-event-handler");
999
+
1000
+ // src/extensions/history.ts
1001
+ import { history, redo, undo } from "@prosekit/pm/history";
1002
+
1003
+ // src/utils/env.ts
1004
+ var isMac = typeof navigator !== "undefined" ? /Mac|iP(hone|[ao]d)/.test(navigator.platform) : false;
842
1005
 
843
1006
  // src/extensions/keymap.ts
844
1007
  import { baseKeymap, chainCommands } from "@prosekit/pm/commands";
845
1008
  import { keydownHandler } from "@prosekit/pm/keymap";
846
- import { Plugin as Plugin4, PluginKey } from "@prosekit/pm/state";
1009
+ import { Plugin as Plugin3, PluginKey as PluginKey2 } from "@prosekit/pm/state";
847
1010
  function addKeymap(keymap) {
848
1011
  return keymapFacet.extension([keymap]);
849
1012
  }
@@ -858,7 +1021,7 @@ var keymapFacet = Facet.define({
858
1021
  return handler(view, event);
859
1022
  return false;
860
1023
  };
861
- const plugin = new Plugin4({
1024
+ const plugin = new Plugin3({
862
1025
  key: keymapPluginKey,
863
1026
  props: { handleKeyDown: handlerWrapper }
864
1027
  });
@@ -892,7 +1055,43 @@ function mergeKeymaps(keymaps) {
892
1055
  ])
893
1056
  );
894
1057
  }
895
- var keymapPluginKey = new PluginKey("prosekit-keymap");
1058
+ var keymapPluginKey = new PluginKey2("prosekit-keymap");
1059
+
1060
+ // src/extensions/history.ts
1061
+ function addHistory() {
1062
+ const keymap = {
1063
+ "Mod-z": undo,
1064
+ "Shift-Mod-z": redo
1065
+ };
1066
+ if (!isMac) {
1067
+ keymap["Mod-y"] = redo;
1068
+ }
1069
+ return defineExtension([
1070
+ addPlugin(history()),
1071
+ addKeymap(keymap),
1072
+ addCommands({
1073
+ undo: () => undo,
1074
+ redo: () => redo
1075
+ })
1076
+ ]);
1077
+ }
1078
+
1079
+ // src/extensions/input-rules.ts
1080
+ import { inputRules } from "@prosekit/pm/inputrules";
1081
+ import "@prosekit/pm/model";
1082
+ import "@prosekit/pm/state";
1083
+ function addInputRule(rules) {
1084
+ return inputRuleFacet.extension([rules]);
1085
+ }
1086
+ var inputRuleFacet = Facet.define({
1087
+ combine: (inputs) => {
1088
+ return (context) => {
1089
+ const rules = inputs.flatMap((callback) => callback(context));
1090
+ return [inputRules({ rules })];
1091
+ };
1092
+ },
1093
+ next: pluginFacet
1094
+ });
896
1095
 
897
1096
  // src/extensions/mark-spec.ts
898
1097
  function addMarkSpec(options) {
@@ -903,7 +1102,7 @@ var markSpecFacet = Facet.define({
903
1102
  const marks = {};
904
1103
  for (const { name, ...spec } of options) {
905
1104
  if (marks[name]) {
906
- throw new Error(`Mark type ${name} has already been defined`);
1105
+ throw new ProseKitError(`Mark type ${name} has already been defined`);
907
1106
  }
908
1107
  marks[name] = spec;
909
1108
  }
@@ -962,6 +1161,8 @@ export {
962
1161
  addCommands,
963
1162
  addDefaultState,
964
1163
  addDoc,
1164
+ addEventHandler,
1165
+ addHistory,
965
1166
  addInputRule,
966
1167
  addKeymap,
967
1168
  addMark,
package/dist/style.css CHANGED
@@ -1,4 +1,4 @@
1
- /* ../../node_modules/.pnpm/prosemirror-view@1.31.7/node_modules/prosemirror-view/style/prosemirror.css */
1
+ /* ../../node_modules/.pnpm/prosemirror-view@1.31.8/node_modules/prosemirror-view/style/prosemirror.css */
2
2
  .ProseMirror {
3
3
  position: relative;
4
4
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/core",
3
3
  "type": "module",
4
- "version": "0.0.9",
4
+ "version": "0.0.11",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -38,7 +38,7 @@
38
38
  "dist"
39
39
  ],
40
40
  "dependencies": {
41
- "@prosekit/pm": "^0.0.4",
41
+ "@prosekit/pm": "^0.0.6",
42
42
  "orderedmap": "^2.1.1",
43
43
  "type-fest": "^4.3.1"
44
44
  },
@@ -46,7 +46,7 @@
46
46
  "@prosekit/dev": "*",
47
47
  "tsup": "^7.2.0",
48
48
  "typescript": "^5.2.2",
49
- "vitest": "^0.34.3"
49
+ "vitest": "^0.34.5"
50
50
  },
51
51
  "scripts": {
52
52
  "build:tsup": "tsup",
package/src/index.ts CHANGED
@@ -12,6 +12,8 @@ export {
12
12
  type DefaultStateOptions,
13
13
  } from './extensions/default-state'
14
14
  export { addDoc } from './extensions/doc'
15
+ export { addEventHandler } from './extensions/event-handler'
16
+ export { addHistory } from './extensions/history'
15
17
  export { addInputRule } from './extensions/input-rules'
16
18
  export { addBaseKeymap, addKeymap, type Keymap } from './extensions/keymap'
17
19
  export { addMarkSpec, type MarkSpecOptions } from './extensions/mark-spec'
@@ -28,8 +30,8 @@ export { type CommandArgs as CommandArgs } from './types/command'
28
30
  export * from './types/editor'
29
31
  export {
30
32
  type Extension,
33
+ type ExtractCommandAppliers,
31
34
  type ExtractCommandCreators,
32
- type ExtractCommandDispatchers,
33
35
  type ExtractMarks,
34
36
  type ExtractNodes,
35
37
  type SimplifyExtension,