@prosekit/core 0.7.6 → 0.7.7

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,6 +1,5 @@
1
1
  import { AllSelection } from '@prosekit/pm/state';
2
2
  import { Attrs } from '@prosekit/pm/model';
3
- import { Attrs as Attrs_2 } from 'prosemirror-model';
4
3
  import { Command } from '@prosekit/pm/state';
5
4
  import type { ContentMatch } from '@prosekit/pm/model';
6
5
  import { config as default_alias_1 } from '@prosekit/dev/config-vitest';
@@ -229,6 +228,12 @@ export declare function baseToggleMark(markType: MarkType, attrs?: Attrs | null,
229
228
  removeWhenPresent: boolean;
230
229
  }): Command;
231
230
 
231
+ declare type BoldExtension = Extension<{
232
+ Marks: {
233
+ bold: Attrs;
234
+ };
235
+ }>;
236
+
232
237
  export declare function buildNode(type: NodeType, args: [Attrs | NodeChild | null | undefined, ...NodeChild[]], createNode: CreateNodeFunction): ProseMirrorNode;
233
238
 
234
239
  export declare function cache<T>(fn: () => T): () => T;
@@ -256,6 +261,14 @@ declare const clsx: (...args: Array<string | boolean | null | undefined>) => str
256
261
  export { clsx }
257
262
  export { clsx as clsx_alias_1 }
258
263
 
264
+ declare type CodeBlockExtension = Extension<{
265
+ Nodes: {
266
+ codeBlock: {
267
+ language: string;
268
+ };
269
+ };
270
+ }>;
271
+
259
272
  /**
260
273
  * Collects all nodes from a given content.
261
274
  *
@@ -317,12 +330,12 @@ export { createEditor as createEditor_alias_1 }
317
330
  /**
318
331
  * @internal
319
332
  */
320
- export declare function createMarkActions(schema: Schema, getState: () => EditorState | null | undefined, applyMark?: ApplyMarkFunction): Record<string, MarkAction>;
333
+ export declare function createMarkActions(schema: Schema, getState: GetStateFunction, applyMark?: ApplyMarkFunction): Record<string, MarkAction>;
321
334
 
322
335
  /**
323
336
  * @internal
324
337
  */
325
- export declare function createNodeActions(schema: Schema, getState: () => EditorState | null | undefined, createNode?: CreateNodeFunction): Record<string, NodeAction>;
338
+ export declare function createNodeActions(schema: Schema, getState: GetStateFunction, createNode?: CreateNodeFunction): Record<string, NodeAction>;
326
339
 
327
340
  export declare const createNodeForTest: CreateNodeFunction;
328
341
 
@@ -351,15 +364,27 @@ declare function defaultBlockAt(match: ContentMatch): NodeType_2 | null;
351
364
  export { defaultBlockAt }
352
365
  export { defaultBlockAt as defaultBlockAt_alias_1 }
353
366
 
367
+ /**
368
+ * @public
369
+ */
354
370
  declare interface DefaultStateOptions {
371
+ /**
372
+ * The starting document to use when creating the editor. It can be a
373
+ * ProseMirror node JSON object, a HTML string, or a HTML element instance.
374
+ */
375
+ defaultContent?: NodeJSON | string | HTMLElement;
355
376
  /**
356
377
  * A JSON object representing the starting document to use when creating the
357
378
  * editor.
379
+ *
380
+ * @deprecated Use `defaultContent` instead.
358
381
  */
359
382
  defaultDoc?: NodeJSON;
360
383
  /**
361
384
  * A HTML element or a HTML string representing the starting document to use
362
385
  * when creating the editor.
386
+ *
387
+ * @deprecated Use `defaultContent` instead.
363
388
  */
364
389
  defaultHTML?: string | HTMLElement;
365
390
  /**
@@ -422,7 +447,12 @@ declare function defineCommands<T extends Record<string, CommandCreator> = Recor
422
447
  export { defineCommands }
423
448
  export { defineCommands as defineCommands_alias_1 }
424
449
 
425
- declare function defineDefaultState({ defaultDoc, defaultHTML, defaultSelection, }: DefaultStateOptions): PlainExtension;
450
+ /**
451
+ * Define a default state for the editor.
452
+ *
453
+ * @public
454
+ */
455
+ declare function defineDefaultState(options: DefaultStateOptions): PlainExtension;
426
456
  export { defineDefaultState }
427
457
  export { defineDefaultState as defineDefaultState_alias_1 }
428
458
 
@@ -685,27 +715,9 @@ export { defineScrollToSelectionHandler as defineScrollToSelectionHandler_alias_
685
715
  */
686
716
  export declare function defineTestExtension(): Union<readonly [BaseCommandsExtension, PlainExtension, DocExtension, HistoryExtension, Extension<{
687
717
  Nodes: {
688
- paragraph: Attrs_2;
689
- };
690
- }>, TextExtension, Extension<{
691
- Marks: {
692
- bold: Attrs_2;
693
- };
694
- }>, Extension<{
695
- Marks: {
696
- italic: Attrs_2;
697
- };
698
- }>, Extension<{
699
- Nodes: {
700
- heading: Attrs_2;
701
- };
702
- }>, Extension<{
703
- Nodes: {
704
- codeBlock: {
705
- language: string;
718
+ paragraph: Attrs;
706
719
  };
707
- };
708
- }>]>;
720
+ }>, TextExtension, BoldExtension, ItalicExtension, LinkExtension, HeadingExtension, CodeBlockExtension]>;
709
721
 
710
722
  /**
711
723
  * @public
@@ -851,15 +863,10 @@ export { DropHandler as DropHandler_alias_1 }
851
863
  */
852
864
  declare class Editor<E extends Extension = any> {
853
865
  private instance;
854
- private afterMounted;
855
866
  /**
856
867
  * @internal
857
868
  */
858
869
  constructor(instance: EditorInstance);
859
- /**
860
- * @internal
861
- */
862
- static create(instance: any): Editor;
863
870
  /**
864
871
  * Whether the editor is mounted.
865
872
  */
@@ -872,6 +879,10 @@ declare class Editor<E extends Extension = any> {
872
879
  * The editor schema.
873
880
  */
874
881
  get schema(): Schema<ExtractNodeNames<E>, ExtractMarkNames<E>>;
882
+ /**
883
+ * The editor's current state.
884
+ */
885
+ get state(): EditorState;
875
886
  /**
876
887
  * Whether the editor is focused.
877
888
  */
@@ -880,28 +891,24 @@ declare class Editor<E extends Extension = any> {
880
891
  * Mount the editor to the given HTML element.
881
892
  * Pass `null` or `undefined` to unmount the editor.
882
893
  */
883
- mount(place: HTMLElement | null | undefined): void;
894
+ mount: (place: HTMLElement | null | undefined) => void;
884
895
  /**
885
896
  * Unmount the editor. This is equivalent to `mount(null)`.
886
897
  */
887
- unmount(): void;
898
+ unmount: () => void;
888
899
  /**
889
900
  * Focus the editor.
890
901
  */
891
- focus(): void;
902
+ focus: () => void;
892
903
  /**
893
904
  * Blur the editor.
894
905
  */
895
- blur(): void;
906
+ blur: () => void;
896
907
  /**
897
908
  * Register an extension to the editor. Return a function to unregister the
898
909
  * extension.
899
910
  */
900
- use(extension: Extension): VoidFunction;
901
- /**
902
- * The editor's current state.
903
- */
904
- get state(): EditorState;
911
+ use: (extension: Extension) => VoidFunction;
905
912
  /**
906
913
  * Update the editor's state.
907
914
  *
@@ -910,7 +917,22 @@ declare class Editor<E extends Extension = any> {
910
917
  * This is an advanced method. Use it only if you have a specific reason to
911
918
  * directly manipulate the editor's state.
912
919
  */
913
- updateState(state: EditorState): void;
920
+ updateState: (state: EditorState) => void;
921
+ /**
922
+ * Update the editor's document and selection.
923
+ *
924
+ * @param content - The new document to set. It can be one of the following:
925
+ * - A ProseMirror node instance
926
+ * - A ProseMirror node JSON object
927
+ * - An HTML string
928
+ * - An HTML element instance
929
+ * @param selection - Optional. Specifies the new selection. It can be one of the following:
930
+ * - A ProseMirror selection instance
931
+ * - A ProseMirror selection JSON object
932
+ * - The string "start" (to set selection at the beginning, default value)
933
+ * - The string "end" (to set selection at the end)
934
+ */
935
+ setContent: (content: ProseMirrorNode | NodeJSON | string | HTMLElement, selection?: SelectionJSON | Selection_2 | "start" | "end") => void;
914
936
  /**
915
937
  * All {@link CommandAction}s defined by the editor.
916
938
  */
@@ -928,6 +950,8 @@ export { Editor }
928
950
  export { Editor as Editor_alias_1 }
929
951
 
930
952
  /**
953
+ * An internal class to make TypeScript generic type easier to use.
954
+ *
931
955
  * @internal
932
956
  */
933
957
  export declare class EditorInstance {
@@ -938,10 +962,13 @@ export declare class EditorInstance {
938
962
  commands: Record<string, CommandAction>;
939
963
  private tree;
940
964
  private directEditorProps;
965
+ private afterMounted;
941
966
  constructor(extension: Extension);
942
967
  getState: () => EditorState;
943
968
  updateState(state: EditorState): void;
944
- updateExtension(extension: Extension, add: boolean): void;
969
+ setContent(content: NodeJSON | string | HTMLElement | ProseMirrorNode, selection?: SelectionJSON | Selection_2 | 'start' | 'end'): void;
970
+ private updateExtension;
971
+ use(extension: Extension): VoidFunction;
945
972
  mount(place: HTMLElement): void;
946
973
  unmount(): void;
947
974
  get mounted(): boolean;
@@ -969,14 +996,23 @@ declare interface EditorOptions<E extends Extension> {
969
996
  * The extension to use when creating the editor.
970
997
  */
971
998
  extension: E;
999
+ /**
1000
+ * The starting document to use when creating the editor. It can be a
1001
+ * ProseMirror node JSON object, a HTML string, or a HTML element instance.
1002
+ */
1003
+ defaultContent?: NodeJSON | string | HTMLElement;
972
1004
  /**
973
1005
  * A JSON object representing the starting document to use when creating the
974
1006
  * editor.
1007
+ *
1008
+ * @deprecated Use `defaultContent` instead.
975
1009
  */
976
1010
  defaultDoc?: NodeJSON;
977
1011
  /**
978
1012
  * A HTML element or a HTML string representing the starting document to use
979
1013
  * when creating the editor.
1014
+ *
1015
+ * @deprecated Use `defaultContent` instead.
980
1016
  */
981
1017
  defaultHTML?: string | HTMLElement;
982
1018
  /**
@@ -1242,6 +1278,14 @@ export declare function getBrowserWindow(options?: {
1242
1278
 
1243
1279
  export declare function getCustomSelection(state: EditorState, from?: number | null, to?: number | null): Selection_3;
1244
1280
 
1281
+ export declare function getEditorContentDoc(schema: Schema, content: NodeJSON | string | HTMLElement | ProseMirrorNode): ProseMirrorNode;
1282
+
1283
+ export declare function getEditorContentJSON(schema: Schema, content: NodeJSON | string | HTMLElement): NodeJSON;
1284
+
1285
+ export declare function getEditorContentNode(schema: Schema, content: NodeJSON | string | HTMLElement | ProseMirrorNode): ProseMirrorNode;
1286
+
1287
+ export declare function getEditorSelection(doc: ProseMirrorNode, selection: SelectionJSON | Selection_2 | 'start' | 'end'): Selection_2;
1288
+
1245
1289
  /**
1246
1290
  * Returns a unique id in the current process that can be used in various places.
1247
1291
  *
@@ -1270,12 +1314,20 @@ export { getNodeType as getNodeType_alias_1 }
1270
1314
  */
1271
1315
  export declare function getNodeTypes(schema: Schema, types: string | NodeType | string[] | NodeType[]): NodeType[];
1272
1316
 
1317
+ declare type GetStateFunction = () => EditorState | null | undefined;
1318
+
1273
1319
  export declare type GroupedEntries<T extends Record<string, any>> = {
1274
1320
  [K in keyof T]?: T[K][];
1275
1321
  };
1276
1322
 
1277
1323
  export declare function groupEntries<T extends Record<string, any>>(entries: ObjectEntries<T>[]): GroupedEntries<T>;
1278
1324
 
1325
+ declare type HeadingExtension = Extension<{
1326
+ Nodes: {
1327
+ heading: Attrs;
1328
+ };
1329
+ }>;
1330
+
1279
1331
  /**
1280
1332
  * @internal
1281
1333
  */
@@ -1416,7 +1468,7 @@ declare function isAtBlockStart(state: EditorState, view?: EditorView): Resolved
1416
1468
  export { isAtBlockStart }
1417
1469
  export { isAtBlockStart as isAtBlockStart_alias_1 }
1418
1470
 
1419
- export declare function isElement(value: unknown): value is Element;
1471
+ export declare function isElement(el: unknown): el is Element;
1420
1472
 
1421
1473
  /**
1422
1474
  * Check if the selection is in a code block.
@@ -1463,6 +1515,8 @@ export { isNodeSelection as isNodeSelection_alias_1 }
1463
1515
 
1464
1516
  export declare function isNotNull<T>(value: T | null | undefined): value is T;
1465
1517
 
1518
+ export declare function isObject(v: unknown): v is Record<string, unknown>;
1519
+
1466
1520
  /**
1467
1521
  * @internal
1468
1522
  */
@@ -1470,6 +1524,13 @@ declare function isProseMirrorNode(node: unknown): node is ProseMirrorNode;
1470
1524
  export { isProseMirrorNode }
1471
1525
  export { isProseMirrorNode as isProseMirrorNode_alias_1 }
1472
1526
 
1527
+ /**
1528
+ * @internal
1529
+ */
1530
+ declare function isSelection(sel: unknown): sel is Selection_2;
1531
+ export { isSelection }
1532
+ export { isSelection as isSelection_alias_1 }
1533
+
1473
1534
  /**
1474
1535
  * Check if `subset` is a subset of `superset`.
1475
1536
  *
@@ -1484,6 +1545,12 @@ declare function isTextSelection(sel: Selection_2): sel is TextSelection;
1484
1545
  export { isTextSelection }
1485
1546
  export { isTextSelection as isTextSelection_alias_1 }
1486
1547
 
1548
+ declare type ItalicExtension = Extension<{
1549
+ Marks: {
1550
+ italic: Attrs;
1551
+ };
1552
+ }>;
1553
+
1487
1554
  /**
1488
1555
  * Serialize a HTML element to a ProseMirror document JSON object.
1489
1556
  *
@@ -1556,6 +1623,16 @@ declare type KeyPressHandler = (view: EditorView, event: KeyboardEvent) => boole
1556
1623
  export { KeyPressHandler }
1557
1624
  export { KeyPressHandler as KeyPressHandler_alias_1 }
1558
1625
 
1626
+ declare interface LinkAttrs {
1627
+ href: string;
1628
+ }
1629
+
1630
+ declare type LinkExtension = Extension<{
1631
+ Marks: {
1632
+ link: LinkAttrs;
1633
+ };
1634
+ }>;
1635
+
1559
1636
  /**
1560
1637
  * A function for creating a mark with optional attributes and any number of
1561
1638
  * children.
@@ -1768,7 +1845,10 @@ export { nodeFromJSON as nodeFromJSON_alias_1 }
1768
1845
  */
1769
1846
  declare interface NodeJSON {
1770
1847
  type: string;
1771
- marks?: Array<any>;
1848
+ marks?: Array<{
1849
+ type: string;
1850
+ attrs?: Record<string, any>;
1851
+ }>;
1772
1852
  text?: string;
1773
1853
  content?: NodeJSON[];
1774
1854
  attrs?: Record<string, any>;
@@ -2127,27 +2207,9 @@ export declare function setupEditorExtension<E extends Extension>(options: Edito
2127
2207
  export declare function setupTest(): {
2128
2208
  editor: TestEditor<Union<readonly [BaseCommandsExtension, PlainExtension, DocExtension, HistoryExtension, Extension<{
2129
2209
  Nodes: {
2130
- paragraph: Attrs_2;
2131
- };
2132
- }>, TextExtension, Extension<{
2133
- Marks: {
2134
- bold: Attrs_2;
2135
- };
2136
- }>, Extension<{
2137
- Marks: {
2138
- italic: Attrs_2;
2139
- };
2140
- }>, Extension<{
2141
- Nodes: {
2142
- heading: Attrs_2;
2143
- };
2144
- }>, Extension<{
2145
- Nodes: {
2146
- codeBlock: {
2147
- language: string;
2210
+ paragraph: Attrs;
2148
2211
  };
2149
- };
2150
- }>]>>;
2212
+ }>, TextExtension, BoldExtension, ItalicExtension, LinkExtension, HeadingExtension, CodeBlockExtension]>>;
2151
2213
  m: ToMarkAction<SimplifyDeeper< {
2152
2214
  bold: {
2153
2215
  readonly [x: string]: any;
@@ -2155,6 +2217,9 @@ export declare function setupTest(): {
2155
2217
  italic: {
2156
2218
  readonly [x: string]: any;
2157
2219
  };
2220
+ link: {
2221
+ href: string;
2222
+ };
2158
2223
  }>>;
2159
2224
  n: {
2160
2225
  p: NodeAction< {
@@ -2169,12 +2234,12 @@ export declare function setupTest(): {
2169
2234
  text: NodeAction< {
2170
2235
  readonly [x: string]: any;
2171
2236
  }>;
2172
- codeBlock: NodeAction< {
2173
- language: string;
2174
- }>;
2175
2237
  heading: NodeAction< {
2176
2238
  readonly [x: string]: any;
2177
2239
  }>;
2240
+ codeBlock: NodeAction< {
2241
+ language: string;
2242
+ }>;
2178
2243
  };
2179
2244
  };
2180
2245
 
@@ -440,8 +440,35 @@ function htmlFromJSON(json, options) {
440
440
  return htmlFromElement(elementFromJSON(json, options));
441
441
  }
442
442
 
443
+ // src/utils/type-assertion.ts
444
+ import { Mark, ProseMirrorNode } from "@prosekit/pm/model";
445
+ import {
446
+ AllSelection,
447
+ NodeSelection,
448
+ TextSelection,
449
+ Selection
450
+ } from "@prosekit/pm/state";
451
+ function isProseMirrorNode(node) {
452
+ return node instanceof ProseMirrorNode;
453
+ }
454
+ function isMark(mark) {
455
+ return mark instanceof Mark;
456
+ }
457
+ function isSelection(sel) {
458
+ return sel instanceof Selection;
459
+ }
460
+ function isTextSelection(sel) {
461
+ return sel instanceof TextSelection;
462
+ }
463
+ function isNodeSelection(sel) {
464
+ return sel instanceof NodeSelection;
465
+ }
466
+ function isAllSelection(sel) {
467
+ return sel instanceof AllSelection;
468
+ }
469
+
443
470
  // src/extensions/default-state.ts
444
- import { Selection } from "@prosekit/pm/state";
471
+ import { Selection as Selection3 } from "@prosekit/pm/state";
445
472
 
446
473
  // src/facets/state.ts
447
474
  var stateFacet = defineFacet({
@@ -480,31 +507,74 @@ var stateFacet = defineFacet({
480
507
  parent: rootFacet
481
508
  });
482
509
 
483
- // src/extensions/default-state.ts
484
- function defineDefaultState({
485
- defaultDoc,
486
- defaultHTML,
487
- defaultSelection
488
- }) {
489
- if (defaultHTML && defaultDoc) {
490
- throw new ProseKitError(
491
- "Only one of defaultHTML and defaultDoc can be provided"
492
- );
510
+ // src/utils/editor-content.ts
511
+ import { Selection as Selection2 } from "@prosekit/pm/state";
512
+
513
+ // src/utils/is-object.ts
514
+ function isObject(v) {
515
+ return typeof v === "object" && v != null;
516
+ }
517
+
518
+ // src/utils/is-element.ts
519
+ var ELEMENT_NODE = 1;
520
+ function isElement(el) {
521
+ return isObject(el) && el.nodeType === ELEMENT_NODE && typeof el.nodeName === "string";
522
+ }
523
+
524
+ // src/utils/editor-content.ts
525
+ function getEditorContentJSON(schema, content) {
526
+ if (typeof content === "string") {
527
+ return jsonFromHTML(content, { schema });
528
+ } else if (isElement(content)) {
529
+ return jsonFromElement(content, { schema });
530
+ } else {
531
+ return content;
532
+ }
533
+ }
534
+ function getEditorContentNode(schema, content) {
535
+ if (isProseMirrorNode(content)) {
536
+ return content;
493
537
  }
538
+ return schema.nodeFromJSON(getEditorContentJSON(schema, content));
539
+ }
540
+ function getEditorContentDoc(schema, content) {
541
+ const doc = getEditorContentNode(schema, content);
542
+ assert(
543
+ doc.type.schema === schema,
544
+ "Document schema does not match editor schema"
545
+ );
546
+ assert(
547
+ doc.type === schema.topNodeType,
548
+ `Document type does not match editor top node type. Expected ${schema.topNodeType.name}, got ${doc.type.name}`
549
+ );
550
+ return doc;
551
+ }
552
+ function getEditorSelection(doc, selection) {
553
+ if (isSelection(selection)) {
554
+ assert(selection.$head.doc === doc, "Selection and doc do not match");
555
+ return selection;
556
+ }
557
+ if (selection === "start") {
558
+ return Selection2.atStart(doc);
559
+ }
560
+ if (selection === "end") {
561
+ return Selection2.atEnd(doc);
562
+ }
563
+ return Selection2.fromJSON(doc, selection);
564
+ }
565
+
566
+ // src/extensions/default-state.ts
567
+ function defineDefaultState(options) {
568
+ const { defaultSelection, defaultContent, defaultDoc, defaultHTML } = options;
569
+ const defaultDocContent = defaultContent || defaultDoc || defaultHTML;
494
570
  return defineFacetPayload(stateFacet, [
495
571
  ({ schema }) => {
496
572
  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);
573
+ if (defaultDocContent) {
574
+ const json = getEditorContentJSON(schema, defaultDocContent);
575
+ config.doc = schema.nodeFromJSON(json);
506
576
  if (defaultSelection) {
507
- config.selection = Selection.fromJSON(config.doc, defaultSelection);
577
+ config.selection = Selection3.fromJSON(config.doc, defaultSelection);
508
578
  }
509
579
  }
510
580
  return config;
@@ -556,29 +626,6 @@ function isMarkActive(state, type, attrs) {
556
626
  }
557
627
  }
558
628
 
559
- // src/utils/type-assertion.ts
560
- import { Mark, ProseMirrorNode } from "@prosekit/pm/model";
561
- import {
562
- AllSelection,
563
- NodeSelection,
564
- TextSelection
565
- } from "@prosekit/pm/state";
566
- function isProseMirrorNode(node) {
567
- return node instanceof ProseMirrorNode;
568
- }
569
- function isMark(mark) {
570
- return mark instanceof Mark;
571
- }
572
- function isTextSelection(sel) {
573
- return sel instanceof TextSelection;
574
- }
575
- function isNodeSelection(sel) {
576
- return sel instanceof NodeSelection;
577
- }
578
- function isAllSelection(sel) {
579
- return sel instanceof AllSelection;
580
- }
581
-
582
629
  // src/facets/union-extension.ts
583
630
  var UnionExtensionImpl = class extends BaseExtension {
584
631
  /**
@@ -646,6 +693,7 @@ function deepEquals(a, b) {
646
693
 
647
694
  // src/editor/action.ts
648
695
  import "@prosekit/pm/model";
696
+ import mapValues from "just-map-values";
649
697
 
650
698
  // src/utils/attrs-match.ts
651
699
  function attrsMatch(nodeOrMark, attrs) {
@@ -673,28 +721,32 @@ function isNodeActive(state, type, attrs) {
673
721
 
674
722
  // src/editor/action.ts
675
723
  function createNodeActions(schema, getState, createNode = defaultCreateNode) {
676
- const builders = {};
677
- for (const type of Object.values(schema.nodes)) {
678
- const builder = (...args) => buildNode(type, args, createNode);
679
- builder.isActive = (attrs) => {
680
- const state = getState();
681
- return state ? isNodeActive(state, type, attrs) : false;
682
- };
683
- builders[type.name] = builder;
684
- }
685
- return builders;
724
+ return mapValues(
725
+ schema.nodes,
726
+ (type) => createNodeAction(type, getState, createNode)
727
+ );
728
+ }
729
+ function createNodeAction(type, getState, createNode) {
730
+ const action = (...args) => buildNode(type, args, createNode);
731
+ action.isActive = (attrs) => {
732
+ const state = getState();
733
+ return state ? isNodeActive(state, type, attrs) : false;
734
+ };
735
+ return action;
686
736
  }
687
737
  function createMarkActions(schema, getState, applyMark = defaultApplyMark) {
688
- const builders = {};
689
- for (const type of Object.values(schema.marks)) {
690
- const builder = (...args) => buildMark(type, args, applyMark);
691
- builder.isActive = (attrs) => {
692
- const state = getState();
693
- return state ? isMarkActive(state, type, attrs) : false;
694
- };
695
- builders[type.name] = builder;
696
- }
697
- return builders;
738
+ return mapValues(
739
+ schema.marks,
740
+ (type) => createMarkAction(type, getState, applyMark)
741
+ );
742
+ }
743
+ function createMarkAction(type, getState, applyMark) {
744
+ const action = (...args) => buildMark(type, args, applyMark);
745
+ action.isActive = (attrs) => {
746
+ const state = getState();
747
+ return state ? isMarkActive(state, type, attrs) : false;
748
+ };
749
+ return action;
698
750
  }
699
751
  function buildMark(type, args, applyMark) {
700
752
  const [attrs, children] = normalizeArgs(args);
@@ -702,7 +754,7 @@ function buildMark(type, args, applyMark) {
702
754
  return applyMark(mark, flattenChildren(type.schema, children));
703
755
  }
704
756
  var defaultApplyMark = (mark, children) => {
705
- return children.map((child) => child.mark([mark]));
757
+ return children.map((node) => node.mark(mark.addToSet(node.marks)));
706
758
  };
707
759
  function buildNode(type, args, createNode) {
708
760
  const [attrs, children] = normalizeArgs(args);
@@ -750,27 +802,24 @@ function isNodeChild(value) {
750
802
 
751
803
  // src/editor/editor.ts
752
804
  function setupEditorExtension(options) {
753
- const { defaultDoc, defaultHTML, defaultSelection } = options;
754
- if (defaultDoc || defaultHTML) {
805
+ if (options.defaultContent || options.defaultDoc || options.defaultHTML) {
755
806
  return union([
756
807
  options.extension,
757
- defineDefaultState({
758
- defaultDoc,
759
- defaultHTML,
760
- defaultSelection
761
- })
808
+ defineDefaultState(options)
762
809
  ]);
763
810
  }
764
811
  return options.extension;
765
812
  }
766
813
  function createEditor(options) {
767
814
  const extension = setupEditorExtension(options);
768
- return Editor.create(new EditorInstance(extension));
815
+ const instance = new EditorInstance(extension);
816
+ return new Editor(instance);
769
817
  }
770
818
  var EditorInstance = class {
771
819
  constructor(extension) {
772
820
  this.view = null;
773
821
  this.commands = {};
822
+ this.afterMounted = [];
774
823
  this.getState = () => {
775
824
  var _a;
776
825
  return ((_a = this.view) == null ? void 0 : _a.state) || this.directEditorProps.state;
@@ -798,6 +847,21 @@ var EditorInstance = class {
798
847
  this.directEditorProps.state = state;
799
848
  }
800
849
  }
850
+ setContent(content, selection) {
851
+ const doc = getEditorContentDoc(this.schema, content);
852
+ doc.check();
853
+ const sel = getEditorSelection(doc, selection || "start");
854
+ const oldState = this.getState();
855
+ if (doc.eq(oldState.doc) && (!selection || sel.eq(oldState.selection))) {
856
+ return;
857
+ }
858
+ const newState = EditorState2.create({
859
+ doc,
860
+ selection: sel,
861
+ plugins: oldState.plugins
862
+ });
863
+ this.updateState(newState);
864
+ }
801
865
  updateExtension(extension, add) {
802
866
  var _a, _b, _c, _d;
803
867
  const view = this.view;
@@ -829,19 +893,33 @@ var EditorInstance = class {
829
893
  }
830
894
  }
831
895
  }
896
+ use(extension) {
897
+ if (!this.mounted) {
898
+ let canceled = false;
899
+ let lazyRemove = null;
900
+ const lazyCreate = () => {
901
+ if (!canceled) {
902
+ lazyRemove = this.use(extension);
903
+ }
904
+ };
905
+ this.afterMounted.push(lazyCreate);
906
+ return () => {
907
+ canceled = true;
908
+ lazyRemove == null ? void 0 : lazyRemove();
909
+ };
910
+ }
911
+ this.updateExtension(extension, true);
912
+ return () => this.updateExtension(extension, false);
913
+ }
832
914
  mount(place) {
833
915
  if (this.view) {
834
916
  throw new ProseKitError("Editor is already mounted");
835
917
  }
836
- if (!place) {
837
- throw new ProseKitError("Can't mount editor without a place");
838
- }
839
918
  this.view = new EditorView({ mount: place }, this.directEditorProps);
919
+ this.afterMounted.forEach((callback) => callback());
840
920
  }
841
921
  unmount() {
842
- if (!this.view) {
843
- throw new ProseKitError("Editor is not mounted yet");
844
- }
922
+ if (!this.view) return;
845
923
  this.directEditorProps.state = this.view.state;
846
924
  this.view.destroy();
847
925
  this.view = null;
@@ -891,25 +969,81 @@ var EditorInstance = class {
891
969
  delete this.commands[name];
892
970
  }
893
971
  };
894
- var Editor = class _Editor {
972
+ var Editor = class {
895
973
  /**
896
974
  * @internal
897
975
  */
898
976
  constructor(instance) {
899
- this.afterMounted = [];
900
- this.instance = instance;
901
- this.mount = this.mount.bind(this);
902
- this.unmount = this.unmount.bind(this);
903
- this.use = this.use.bind(this);
904
- }
905
- /**
906
- * @internal
907
- */
908
- static create(instance) {
977
+ /**
978
+ * Mount the editor to the given HTML element.
979
+ * Pass `null` or `undefined` to unmount the editor.
980
+ */
981
+ this.mount = (place) => {
982
+ if (place) {
983
+ this.instance.mount(place);
984
+ } else {
985
+ this.instance.unmount();
986
+ }
987
+ };
988
+ /**
989
+ * Unmount the editor. This is equivalent to `mount(null)`.
990
+ */
991
+ this.unmount = () => {
992
+ this.instance.unmount();
993
+ };
994
+ /**
995
+ * Focus the editor.
996
+ */
997
+ this.focus = () => {
998
+ var _a;
999
+ (_a = this.instance.view) == null ? void 0 : _a.focus();
1000
+ };
1001
+ /**
1002
+ * Blur the editor.
1003
+ */
1004
+ this.blur = () => {
1005
+ var _a;
1006
+ (_a = this.instance.view) == null ? void 0 : _a.dom.blur();
1007
+ };
1008
+ /**
1009
+ * Register an extension to the editor. Return a function to unregister the
1010
+ * extension.
1011
+ */
1012
+ this.use = (extension) => {
1013
+ return this.instance.use(extension);
1014
+ };
1015
+ /**
1016
+ * Update the editor's state.
1017
+ *
1018
+ * @remarks
1019
+ *
1020
+ * This is an advanced method. Use it only if you have a specific reason to
1021
+ * directly manipulate the editor's state.
1022
+ */
1023
+ this.updateState = (state) => {
1024
+ this.instance.updateState(state);
1025
+ };
1026
+ /**
1027
+ * Update the editor's document and selection.
1028
+ *
1029
+ * @param content - The new document to set. It can be one of the following:
1030
+ * - A ProseMirror node instance
1031
+ * - A ProseMirror node JSON object
1032
+ * - An HTML string
1033
+ * - An HTML element instance
1034
+ * @param selection - Optional. Specifies the new selection. It can be one of the following:
1035
+ * - A ProseMirror selection instance
1036
+ * - A ProseMirror selection JSON object
1037
+ * - The string "start" (to set selection at the beginning, default value)
1038
+ * - The string "end" (to set selection at the end)
1039
+ */
1040
+ this.setContent = (content, selection) => {
1041
+ return this.instance.setContent(content, selection);
1042
+ };
909
1043
  if (!(instance instanceof EditorInstance)) {
910
1044
  throw new TypeError("Invalid EditorInstance");
911
1045
  }
912
- return new _Editor(instance);
1046
+ this.instance = instance;
913
1047
  }
914
1048
  /**
915
1049
  * Whether the editor is mounted.
@@ -929,68 +1063,6 @@ var Editor = class _Editor {
929
1063
  get schema() {
930
1064
  return this.instance.schema;
931
1065
  }
932
- /**
933
- * Whether the editor is focused.
934
- */
935
- get focused() {
936
- var _a, _b;
937
- return (_b = (_a = this.instance.view) == null ? void 0 : _a.hasFocus()) != null ? _b : false;
938
- }
939
- /**
940
- * Mount the editor to the given HTML element.
941
- * Pass `null` or `undefined` to unmount the editor.
942
- */
943
- mount(place) {
944
- if (!place) {
945
- return this.unmount();
946
- }
947
- this.instance.mount(place);
948
- this.afterMounted.forEach((callback) => callback());
949
- }
950
- /**
951
- * Unmount the editor. This is equivalent to `mount(null)`.
952
- */
953
- unmount() {
954
- if (this.mounted) {
955
- this.instance.unmount();
956
- }
957
- }
958
- /**
959
- * Focus the editor.
960
- */
961
- focus() {
962
- var _a;
963
- (_a = this.instance.view) == null ? void 0 : _a.focus();
964
- }
965
- /**
966
- * Blur the editor.
967
- */
968
- blur() {
969
- var _a;
970
- (_a = this.instance.view) == null ? void 0 : _a.dom.blur();
971
- }
972
- /**
973
- * Register an extension to the editor. Return a function to unregister the
974
- * extension.
975
- */
976
- use(extension) {
977
- if (!this.mounted) {
978
- let canceled = false;
979
- let lazyRemove = null;
980
- const lazyCreate = () => {
981
- if (!canceled) {
982
- lazyRemove = this.use(extension);
983
- }
984
- };
985
- this.afterMounted.push(lazyCreate);
986
- return () => {
987
- canceled = true;
988
- lazyRemove == null ? void 0 : lazyRemove();
989
- };
990
- }
991
- this.instance.updateExtension(extension, true);
992
- return () => this.instance.updateExtension(extension, false);
993
- }
994
1066
  /**
995
1067
  * The editor's current state.
996
1068
  */
@@ -998,15 +1070,11 @@ var Editor = class _Editor {
998
1070
  return this.instance.getState();
999
1071
  }
1000
1072
  /**
1001
- * Update the editor's state.
1002
- *
1003
- * @remarks
1004
- *
1005
- * This is an advanced method. Use it only if you have a specific reason to
1006
- * directly manipulate the editor's state.
1073
+ * Whether the editor is focused.
1007
1074
  */
1008
- updateState(state) {
1009
- this.instance.updateState(state);
1075
+ get focused() {
1076
+ var _a, _b;
1077
+ return (_b = (_a = this.instance.view) == null ? void 0 : _a.hasFocus()) != null ? _b : false;
1010
1078
  }
1011
1079
  /**
1012
1080
  * All {@link CommandAction}s defined by the editor.
@@ -1043,6 +1111,7 @@ export {
1043
1111
  schemaFacet,
1044
1112
  defineFacetPayload,
1045
1113
  stateFacet,
1114
+ isElement,
1046
1115
  jsonFromState,
1047
1116
  stateFromJSON,
1048
1117
  jsonFromNode,
@@ -1054,14 +1123,15 @@ export {
1054
1123
  elementFromJSON,
1055
1124
  jsonFromHTML,
1056
1125
  htmlFromJSON,
1057
- defineDefaultState,
1058
- isMarkAbsent,
1059
- isMarkActive,
1060
1126
  isProseMirrorNode,
1061
1127
  isMark,
1128
+ isSelection,
1062
1129
  isTextSelection,
1063
1130
  isNodeSelection,
1064
1131
  isAllSelection,
1132
+ defineDefaultState,
1133
+ isMarkAbsent,
1134
+ isMarkActive,
1065
1135
  createNodeActions,
1066
1136
  createMarkActions,
1067
1137
  union,
@@ -4,11 +4,12 @@ import {
4
4
  assert,
5
5
  createMarkActions,
6
6
  createNodeActions,
7
+ isProseMirrorNode,
7
8
  setupEditorExtension
8
- } from "./chunk-MOSGJZHV.js";
9
+ } from "./chunk-MDJ2B4IL.js";
9
10
 
10
11
  // src/test/test-editor.ts
11
- import { EditorState, NodeSelection, TextSelection } from "@prosekit/pm/state";
12
+ import { NodeSelection, TextSelection } from "@prosekit/pm/state";
12
13
 
13
14
  // src/test/test-builder.ts
14
15
  var createNodeForTest = (type, attrs, children) => {
@@ -53,7 +54,7 @@ var createNodeForTest = (type, attrs, children) => {
53
54
  };
54
55
  var applyMarkForTest = (mark, children) => {
55
56
  return children.map((node) => {
56
- const newNode = node.mark([mark]);
57
+ const newNode = node.mark(mark.addToSet(node.marks));
57
58
  newNode.tags = node.tags;
58
59
  return newNode;
59
60
  });
@@ -85,6 +86,12 @@ var TestEditorInstance = class extends EditorInstance {
85
86
  this.nodes = createNodeActions(this.schema, this.getState, createNodeForTest);
86
87
  this.marks = createMarkActions(this.schema, this.getState, applyMarkForTest);
87
88
  }
89
+ setContent(content, selection) {
90
+ return super.setContent(
91
+ content,
92
+ isProseMirrorNode(content) && !selection ? getSelection(content) : selection
93
+ );
94
+ }
88
95
  };
89
96
  var TestEditor = class extends Editor {
90
97
  constructor(instance) {
@@ -104,21 +111,7 @@ var TestEditor = class extends Editor {
104
111
  * ```
105
112
  */
106
113
  set(doc) {
107
- assert(
108
- doc.type.schema === this.schema,
109
- "Document schema does not match editor schema"
110
- );
111
- assert(
112
- doc.type === this.schema.topNodeType,
113
- "Document type does not match editor top node type"
114
- );
115
- const selection = getSelection(doc);
116
- const state = EditorState.create({
117
- doc,
118
- selection,
119
- plugins: this.state.plugins
120
- });
121
- this.updateState(state);
114
+ return this.setContent(doc);
122
115
  }
123
116
  dispatchEvent(event) {
124
117
  this.view.dispatchEvent(event);
@@ -126,7 +119,8 @@ var TestEditor = class extends Editor {
126
119
  };
127
120
  function createTestEditor(options) {
128
121
  const extension = setupEditorExtension(options);
129
- return new TestEditor(new TestEditorInstance(extension));
122
+ const instance = new TestEditorInstance(extension);
123
+ return new TestEditor(instance);
130
124
  }
131
125
  export {
132
126
  createTestEditor
@@ -174,6 +174,7 @@ export { isAllSelection } from './_tsup-dts-rollup';
174
174
  export { isMark } from './_tsup-dts-rollup';
175
175
  export { isNodeSelection } from './_tsup-dts-rollup';
176
176
  export { isProseMirrorNode } from './_tsup-dts-rollup';
177
+ export { isSelection } from './_tsup-dts-rollup';
177
178
  export { isTextSelection } from './_tsup-dts-rollup';
178
179
  export { withSkipCodeBlock } from './_tsup-dts-rollup';
179
180
  export { OBJECT_REPLACEMENT_CHARACTER } from './_tsup-dts-rollup';
@@ -15,6 +15,7 @@ import {
15
15
  htmlFromJSON,
16
16
  htmlFromNode,
17
17
  isAllSelection,
18
+ isElement,
18
19
  isMark,
19
20
  isMarkAbsent,
20
21
  isMarkActive,
@@ -22,6 +23,7 @@ import {
22
23
  isNodeSelection,
23
24
  isNotNull,
24
25
  isProseMirrorNode,
26
+ isSelection,
25
27
  isTextSelection,
26
28
  jsonFromHTML,
27
29
  jsonFromNode,
@@ -35,7 +37,7 @@ import {
35
37
  stateFromJSON,
36
38
  toReversed,
37
39
  union
38
- } from "./chunk-MOSGJZHV.js";
40
+ } from "./chunk-MDJ2B4IL.js";
39
41
 
40
42
  // src/commands/add-mark.ts
41
43
  import "@prosekit/pm/model";
@@ -524,12 +526,6 @@ var schemaSpecFacet = defineFacet({
524
526
  singleton: true
525
527
  });
526
528
 
527
- // src/utils/is-element.ts
528
- var hasElement = typeof Element !== "undefined";
529
- function isElement(value) {
530
- return hasElement && value instanceof Element;
531
- }
532
-
533
529
  // src/extensions/node-spec.ts
534
530
  function defineNodeSpec(options) {
535
531
  const payload = [options, void 0];
@@ -959,6 +955,7 @@ var isApple = typeof navigator !== "undefined" ? /Mac|iP(hone|[ao]d)/.test(navig
959
955
  import { chainCommands } from "@prosekit/pm/commands";
960
956
  import { keydownHandler } from "@prosekit/pm/keymap";
961
957
  import { Plugin as Plugin2, PluginKey as PluginKey4 } from "@prosekit/pm/state";
958
+ import mapValues from "just-map-values";
962
959
  function defineKeymap(keymap2) {
963
960
  return defineFacetPayload(keymapFacet, [keymap2]);
964
961
  }
@@ -994,12 +991,10 @@ function mergeKeymaps(keymaps) {
994
991
  commands2.push(command);
995
992
  }
996
993
  }
997
- return Object.fromEntries(
998
- Object.entries(bindings).map(([key, commands2]) => [
999
- key,
1000
- chainCommands(...commands2)
1001
- ])
1002
- );
994
+ return mapValues(bindings, mergeCommands);
995
+ }
996
+ function mergeCommands(commands2) {
997
+ return chainCommands(...commands2);
1003
998
  }
1004
999
  var keymapPluginKey = new PluginKey4("prosekit-keymap");
1005
1000
 
@@ -1399,6 +1394,7 @@ export {
1399
1394
  isMarkActive,
1400
1395
  isNodeSelection,
1401
1396
  isProseMirrorNode,
1397
+ isSelection,
1402
1398
  isTextSelection,
1403
1399
  jsonFromHTML,
1404
1400
  jsonFromNode,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@prosekit/core",
3
3
  "type": "module",
4
- "version": "0.7.6",
4
+ "version": "0.7.7",
5
5
  "private": false,
6
6
  "author": {
7
7
  "name": "ocavue",
@@ -41,6 +41,7 @@
41
41
  ],
42
42
  "dependencies": {
43
43
  "clsx": "^2.1.1",
44
+ "just-map-values": "^3.2.0",
44
45
  "orderedmap": "^2.1.1",
45
46
  "prosemirror-splittable": "^0.1.1",
46
47
  "type-fest": "^4.23.0",