@kerebron/editor 0.4.31 → 0.5.1

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.
Files changed (39) hide show
  1. package/README.md +3 -5
  2. package/esm/CoreEditor.d.ts +25 -7
  3. package/esm/CoreEditor.d.ts.map +1 -1
  4. package/esm/CoreEditor.js +93 -33
  5. package/esm/CoreEditor.js.map +1 -1
  6. package/esm/ExtensionManager.d.ts +6 -9
  7. package/esm/ExtensionManager.d.ts.map +1 -1
  8. package/esm/ExtensionManager.js +44 -50
  9. package/esm/ExtensionManager.js.map +1 -1
  10. package/esm/Node.d.ts +1 -1
  11. package/esm/Node.d.ts.map +1 -1
  12. package/esm/commands/CommandManager.d.ts +1 -2
  13. package/esm/commands/CommandManager.d.ts.map +1 -1
  14. package/esm/commands/CommandManager.js +2 -4
  15. package/esm/commands/CommandManager.js.map +1 -1
  16. package/esm/commands/baseCommandFactories.d.ts.map +1 -1
  17. package/esm/commands/baseCommandFactories.js +5 -3
  18. package/esm/commands/baseCommandFactories.js.map +1 -1
  19. package/esm/plugins/input-rules/InputRulesPlugin.d.ts +5 -4
  20. package/esm/plugins/input-rules/InputRulesPlugin.d.ts.map +1 -1
  21. package/esm/plugins/input-rules/InputRulesPlugin.js +88 -17
  22. package/esm/plugins/input-rules/InputRulesPlugin.js.map +1 -1
  23. package/esm/plugins/input-rules/rulebuilders.d.ts.map +1 -1
  24. package/esm/plugins/input-rules/rulebuilders.js +16 -9
  25. package/esm/plugins/input-rules/rulebuilders.js.map +1 -1
  26. package/esm/types.d.ts +4 -12
  27. package/esm/types.d.ts.map +1 -1
  28. package/esm/utilities/createNodeFromContent.js +1 -1
  29. package/esm/utilities/createNodeFromContent.js.map +1 -1
  30. package/package.json +1 -1
  31. package/src/CoreEditor.ts +144 -42
  32. package/src/ExtensionManager.ts +57 -60
  33. package/src/Node.ts +1 -1
  34. package/src/commands/CommandManager.ts +2 -5
  35. package/src/commands/baseCommandFactories.ts +6 -3
  36. package/src/plugins/input-rules/InputRulesPlugin.ts +126 -15
  37. package/src/plugins/input-rules/rulebuilders.ts +27 -10
  38. package/src/types.ts +4 -12
  39. package/src/utilities/createNodeFromContent.ts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;AACnD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG;IAC7C,QAAQ,EAAE,KAAK,CAAC,iBAAiB,GAAG,MAAM,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,WAAW,EAAE,GAAG,IAAI,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,EAAE,CAAC;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,KAAK,GAAG,GAAG,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,iBAAiB,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,eAAe,EAAgB,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,WAAW,SAAS;IACxB,aAAa,IAAI,iBAAiB,EAAE,CAAC;CACtC;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;AACnD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG;IAC7C,QAAQ,EAAE,KAAK,CAAC,iBAAiB,GAAG,MAAM,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,WAAW,EAAE,GAAG,IAAI,CAAC;AAEzD,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,EAAE,CAAC;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,KAAK,GAAG,GAAG,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,iBAAiB,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC"}
@@ -9,7 +9,7 @@ export function createNodeFromObject(content, schema, options) {
9
9
  }
10
10
  catch (error) {
11
11
  if (options?.errorOnInvalidContent) {
12
- throw new Error('Invalid JSON content', {
12
+ throw new Error('Invalid JSON content: ' + error.message, {
13
13
  cause: error,
14
14
  });
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createNodeFromContent.js","sourceRoot":"","sources":["../../src/utilities/createNodeFromContent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI,eAAe,EAAU,MAAM,mBAAmB,CAAC;AAQ9E,MAAM,UAAU,oBAAoB,CAClC,OAAiD,EACjD,MAAc,EACd,OAAsC;IAEtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAE1C,IAAI,OAAO,EAAE,qBAAqB,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,EAAE,qBAAqB,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,sBAAsB,EAAE;gBACtC,KAAK,EAAE,KAAc;aACtB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,CAAC,IAAI,CACV,kBAAkB,EAClB,eAAe,EACf,OAAO,EACP,QAAQ,EACR,KAAK,CACN,CAAC;QAEF,OAAO,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAE,CAAC;IACrD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAsB,EACtB,MAAc;IAEd,OAAO,QAAQ,CAAC,SAAS,CACvB,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CACjD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAiD,EACjD,MAAc,EACd,OAAsC;IAEtC,IAAI,OAAO,YAAY,eAAe,IAAI,OAAO,YAAY,QAAQ,EAAE,CAAC;QACtE,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC;IAEtE,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAE,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"createNodeFromContent.js","sourceRoot":"","sources":["../../src/utilities/createNodeFromContent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI,eAAe,EAAU,MAAM,mBAAmB,CAAC;AAQ9E,MAAM,UAAU,oBAAoB,CAClC,OAAiD,EACjD,MAAc,EACd,OAAsC;IAEtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAE1C,IAAI,OAAO,EAAE,qBAAqB,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,OAAO,EAAE,qBAAqB,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,KAAK,CAAC,OAAO,EAAE;gBACxD,KAAK,EAAE,KAAc;aACtB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,CAAC,IAAI,CACV,kBAAkB,EAClB,eAAe,EACf,OAAO,EACP,QAAQ,EACR,KAAK,CACN,CAAC;QAEF,OAAO,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAE,CAAC;IACrD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAsB,EACtB,MAAc;IAEd,OAAO,QAAQ,CAAC,SAAS,CACvB,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CACjD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAiD,EACjD,MAAc,EACd,OAAsC;IAEtC,IAAI,OAAO,YAAY,eAAe,IAAI,OAAO,YAAY,QAAQ,EAAE,CAAC;QACtE,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC;IAEtE,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAE,CAAC;AACrD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kerebron/editor",
3
- "version": "0.4.31",
3
+ "version": "0.5.1",
4
4
  "license": "MIT",
5
5
  "module": "./esm/mod.js",
6
6
  "exports": {
package/src/CoreEditor.ts CHANGED
@@ -1,16 +1,25 @@
1
1
  import { EditorView } from 'prosemirror-view';
2
- import { Node as ProseMirrorNode, Schema } from 'prosemirror-model';
2
+ import {
3
+ Node as ProseMirrorNode,
4
+ ParseOptions,
5
+ Schema,
6
+ } from 'prosemirror-model';
3
7
 
4
8
  import { ExtensionManager } from './ExtensionManager.js';
5
- import type { EditorConfig, JSONContent } from './types.js';
9
+ import type { Content, EditorKit, JSONContent } from './types.js';
6
10
  import { EditorState, Transaction } from 'prosemirror-state';
7
11
  import { CommandManager } from './commands/CommandManager.js';
8
12
  import { nodeToTreeString } from './nodeToTreeString.js';
9
13
  import { DummyEditorView } from './DummyEditorView.js';
10
- import { ChainedCommands } from './commands/mod.js';
11
14
  import { createNodeFromObject } from './utilities/createNodeFromContent.js';
12
15
  import { Extension } from './Extension.js';
13
16
  import { defaultUi, EditorUi } from './ui.js';
17
+ import { runInputRulesTexts } from './plugins/input-rules/InputRulesPlugin.js';
18
+ import {
19
+ ChainedCommands,
20
+ Command,
21
+ CommandFactories,
22
+ } from './commands/types.js';
14
23
 
15
24
  function ensureDocSchema(
16
25
  doc: ProseMirrorNode,
@@ -24,56 +33,83 @@ function ensureDocSchema(
24
33
  return ProseMirrorNode.fromJSON(schema, json);
25
34
  }
26
35
 
36
+ export interface EditorConfig {
37
+ element: HTMLElement;
38
+ content: Content;
39
+ parseOptions: ParseOptions;
40
+ // extensions: AnyExtensionOrReq[];
41
+ cdnUrl?: string;
42
+ uri?: string;
43
+ languageID?: string;
44
+ topNode?: string;
45
+ readOnly?: boolean;
46
+ }
47
+
27
48
  export class CoreEditor extends EventTarget {
28
- public readonly config: Partial<EditorConfig> = {
29
- element: undefined,
30
- extensions: [],
31
- };
32
- private extensionManager: ExtensionManager;
49
+ public readonly config: Partial<EditorConfig>;
33
50
  private commandManager: CommandManager;
34
51
  public view!: EditorView | DummyEditorView;
35
52
  public state!: EditorState;
36
53
  public ui: EditorUi = defaultUi(this);
37
-
38
- constructor(config: Partial<EditorConfig> = {}) {
54
+ private linkListener?: EventListenerOrEventListenerObject;
55
+ private linkSource?: CoreEditor;
56
+
57
+ private constructor(
58
+ config: Partial<EditorConfig>,
59
+ public readonly schema: Schema,
60
+ private extensionManager: ExtensionManager,
61
+ ) {
39
62
  super();
40
- this.config = {
41
- ...this.config,
42
- ...config,
43
- };
63
+
64
+ this.config = { ...config };
44
65
 
45
66
  this.commandManager = new CommandManager(
46
67
  this,
47
68
  );
69
+ }
48
70
 
49
- this.extensionManager = new ExtensionManager(
50
- this.config.extensions || [],
51
- this,
52
- this.commandManager,
71
+ static create(config: Partial<EditorConfig> & { editorKits: EditorKit[] }) {
72
+ const extensionManager = new ExtensionManager(config.editorKits);
73
+
74
+ const schema = extensionManager.getSchemaByResolvedExtensions();
75
+
76
+ const instance = new CoreEditor(config, schema, extensionManager);
77
+ extensionManager.created(instance, schema);
78
+
79
+ const content = config.content
80
+ ? config.content
81
+ : schema.topNodeType.spec.EMPTY_DOC;
82
+
83
+ instance.createView(content);
84
+ instance.setupPlugins();
85
+
86
+ return instance;
87
+ }
88
+
89
+ public clone(config?: EditorConfig): CoreEditor {
90
+ const extensionManager = new ExtensionManager(
91
+ this.extensionManager.editorKits,
92
+ );
93
+
94
+ const instance = new CoreEditor(
95
+ config || {},
96
+ this.schema,
97
+ extensionManager,
53
98
  );
99
+ extensionManager.created(instance, this.schema);
54
100
 
55
- this.extensionManager.created();
101
+ const content = this.getJSON();
56
102
 
57
- // const content = this.options.content ? this.options.content : {
58
- // type: this.extensionManager.schema.topNodeType.name,
59
- // content: this.extensionManager.schema.topNodeType.spec.EMPTY_DOC,
60
- // };
61
- const content = this.config.content
62
- ? this.config.content
63
- : this.extensionManager.schema.topNodeType.spec.EMPTY_DOC;
103
+ instance.createView(content);
104
+ instance.setupPlugins();
64
105
 
65
- this.createView(content);
66
- this.setupPlugins();
106
+ return instance;
67
107
  }
68
108
 
69
109
  getExtension<T extends Extension>(name: string): T | undefined {
70
110
  return this.extensionManager.getExtension<T>(name);
71
111
  }
72
112
 
73
- public get schema() {
74
- return this.extensionManager.schema;
75
- }
76
-
77
113
  public get run() {
78
114
  return this.commandManager.run;
79
115
  }
@@ -90,6 +126,63 @@ export class CoreEditor extends EventTarget {
90
126
  return this.commandManager.createCan();
91
127
  }
92
128
 
129
+ public link(source: CoreEditor): ChainedCommands {
130
+ if (source === this) {
131
+ throw new Error('You cannot chain editor to itself');
132
+ }
133
+
134
+ this.unlink();
135
+
136
+ this.state = EditorState.create({ doc: source.getDocument() });
137
+
138
+ const { commandFactories } = this.commandManager;
139
+ const commands: Command[] = [];
140
+
141
+ const chain = {
142
+ ...Object.fromEntries(
143
+ Object.entries(commandFactories).map(([name, commandFactory]) => {
144
+ const chainedCommand = (...args: never[]) => {
145
+ const command = commandFactory(...args);
146
+ commands.push(command);
147
+ return chain;
148
+ };
149
+ return [name, chainedCommand];
150
+ }),
151
+ ),
152
+ run: () => {
153
+ this.linkSource = source;
154
+ this.linkListener = () => {
155
+ let state = source.state;
156
+ const dispatch = (tr: Transaction) => {
157
+ state = state.apply(tr);
158
+ };
159
+
160
+ for (const command of commands) {
161
+ if (!command(state, dispatch)) {
162
+ return;
163
+ }
164
+ }
165
+
166
+ this.state = state;
167
+ if (this.view) {
168
+ this.view.updateState(this.state);
169
+ }
170
+ };
171
+ source.addEventListener('changed', this.linkListener);
172
+ },
173
+ } as unknown as ChainedCommands;
174
+
175
+ return chain;
176
+ }
177
+
178
+ public unlink() {
179
+ if (this.linkListener && this.linkSource) {
180
+ this.linkSource.removeEventListener('changed', this.linkListener);
181
+ this.linkListener = undefined;
182
+ this.linkSource = undefined;
183
+ }
184
+ }
185
+
93
186
  private createView(content: any) {
94
187
  const doc = createNodeFromObject(content, this.schema);
95
188
 
@@ -175,8 +268,8 @@ export class CoreEditor extends EventTarget {
175
268
 
176
269
  public clearDocument() {
177
270
  const content = {
178
- type: this.extensionManager.schema.topNodeType.name,
179
- content: this.extensionManager.schema.topNodeType.spec.EMPTY_DOC.content,
271
+ type: this.schema.topNodeType.name,
272
+ content: this.schema.topNodeType.spec.EMPTY_DOC.content,
180
273
  };
181
274
 
182
275
  this.setDocument(content);
@@ -216,7 +309,8 @@ export class CoreEditor extends EventTarget {
216
309
  if (!converter) {
217
310
  throw new Error('Converter not found for: ' + mediaType);
218
311
  }
219
- const doc = await converter.toDoc(content);
312
+ const parsedDoc = await converter.toDoc(content);
313
+ const doc = ProseMirrorNode.fromJSON(this.schema, parsedDoc.toJSON()); // TODO: WHY?!
220
314
 
221
315
  this.state = EditorState.create({
222
316
  doc,
@@ -224,6 +318,17 @@ export class CoreEditor extends EventTarget {
224
318
  storedMarks: this.state.storedMarks,
225
319
  });
226
320
 
321
+ const cmd = runInputRulesTexts();
322
+ let newState: EditorState | undefined;
323
+ const dispatch = (tr: Transaction) => {
324
+ newState = this.state.apply(tr);
325
+ };
326
+ const aa = cmd(this.state, dispatch);
327
+
328
+ if (newState) {
329
+ this.state = newState;
330
+ }
331
+
227
332
  if (this.view) {
228
333
  this.view.updateState(this.state);
229
334
  }
@@ -253,13 +358,6 @@ export class CoreEditor extends EventTarget {
253
358
  return this.state.doc.toJSON();
254
359
  }
255
360
 
256
- public clone(options: Partial<EditorConfig> = {}): CoreEditor {
257
- return new CoreEditor({
258
- ...options,
259
- extensions: [...(Array.from(this.extensionManager.extensions) || [])],
260
- });
261
- }
262
-
263
361
  public debug(doc?: ProseMirrorNode) {
264
362
  if (!doc) {
265
363
  doc = this.state.doc;
@@ -274,4 +372,8 @@ export class CoreEditor extends EventTarget {
274
372
  this.dispatchEvent(event);
275
373
  this.view.destroy();
276
374
  }
375
+
376
+ mergeCommandFactories(toInsert: Partial<CommandFactories>, name: string) {
377
+ this.commandManager.mergeCommandFactories(toInsert, name);
378
+ }
277
379
  }
@@ -3,8 +3,8 @@ import { Plugin } from 'prosemirror-state';
3
3
  import { NodeViewConstructor } from 'prosemirror-view';
4
4
 
5
5
  import { Converter, Extension } from './Extension.js';
6
- import { AnyExtension, AnyExtensionOrReq } from './types.js';
7
- import { CoreEditor } from './CoreEditor.js';
6
+ import type { AnyExtension, AnyExtensionOrReq, EditorKit } from './types.js';
7
+ import type { CoreEditor } from './CoreEditor.js';
8
8
  import { Mark } from './Mark.js';
9
9
  import { Node } from './Node.js';
10
10
  import {
@@ -43,8 +43,6 @@ export function splitExtensions(extensions: Iterable<AnyExtension>) {
43
43
  }
44
44
 
45
45
  export class ExtensionManager {
46
- public readonly schema: Schema;
47
-
48
46
  public readonly extensions: Set<AnyExtension> = new Set();
49
47
  readonly plugins: Plugin[] = [];
50
48
  readonly nodeViews: Record<string, NodeViewConstructor> = {};
@@ -53,21 +51,14 @@ export class ExtensionManager {
53
51
 
54
52
  private debug = true;
55
53
 
56
- constructor(
57
- extensions: AnyExtensionOrReq[],
58
- private editor: CoreEditor,
59
- private commandManager: CommandManager,
60
- ) {
54
+ constructor(public readonly editorKits: EditorKit[]) {
55
+ const extensions: AnyExtensionOrReq[] = editorKits
56
+ .reduce(
57
+ (prev: AnyExtensionOrReq[], cur) => prev.concat(cur.getExtensions()),
58
+ [],
59
+ );
60
+
61
61
  this.setupExtensions(new Set(extensions));
62
- this.schema = this.getSchemaByResolvedExtensions(editor);
63
-
64
- const event = new CustomEvent('schema:ready', {
65
- detail: {
66
- editor,
67
- schema: this.schema,
68
- },
69
- });
70
- editor.dispatchEvent(event);
71
62
  }
72
63
 
73
64
  getExtension<T extends Extension>(name: string): T | undefined {
@@ -82,7 +73,7 @@ export class ExtensionManager {
82
73
  }
83
74
  }
84
75
 
85
- private initPlugins() {
76
+ private initPlugins(editor: CoreEditor, schema: Schema) {
86
77
  const inputRules: InputRule[] = [];
87
78
  const keyBindings: Map<string, Command> = new Map();
88
79
 
@@ -95,8 +86,7 @@ export class ExtensionManager {
95
86
  continue;
96
87
  }
97
88
 
98
- const commandFactory =
99
- this.commandManager.commandFactories[toInsert[key]];
89
+ const commandFactory = editor.commandFactories[toInsert[key]];
100
90
  if (!commandFactory) {
101
91
  console.warn(`No command constructor: ${toInsert[key]}`);
102
92
  continue;
@@ -115,40 +105,40 @@ export class ExtensionManager {
115
105
  let converters = {};
116
106
 
117
107
  for (const extension of this.extensions) {
118
- extension.setEditor(this.editor);
108
+ extension.setEditor(editor);
119
109
 
120
110
  if (extension.type === 'node') {
121
- const nodeType = this.schema.nodes[extension.name];
111
+ const nodeType = schema.nodes[extension.name];
122
112
  inputRules.push(...extension.getInputRules(nodeType));
123
113
  this.plugins.push(
124
114
  ...extension.getProseMirrorPlugins(),
125
115
  );
126
- this.commandManager.mergeCommandFactories(
127
- extension.getCommandFactories(this.editor, nodeType),
116
+ editor.mergeCommandFactories(
117
+ extension.getCommandFactories(editor, nodeType),
128
118
  extension.name,
129
119
  );
130
120
  mergeShortcuts(
131
- extension.getKeyboardShortcuts(this.editor),
121
+ extension.getKeyboardShortcuts(editor),
132
122
  extension.name,
133
123
  );
134
124
  converters = {
135
125
  ...converters,
136
- ...extension.getConverters(this.editor, this.schema),
126
+ ...extension.getConverters(editor, schema),
137
127
  };
138
- const nodeView = extension.getNodeView(this.editor);
128
+ const nodeView = extension.getNodeView(editor);
139
129
  if (nodeView) {
140
130
  this.nodeViews[extension.name] = nodeView;
141
131
  }
142
132
  }
143
133
  if (extension.type === 'mark') {
144
- const markType = this.schema.marks[extension.name];
134
+ const markType = schema.marks[extension.name];
145
135
  inputRules.push(...extension.getInputRules(markType));
146
- this.commandManager.mergeCommandFactories(
147
- extension.getCommandFactories(this.editor, markType),
136
+ editor.mergeCommandFactories(
137
+ extension.getCommandFactories(editor, markType),
148
138
  extension.name,
149
139
  );
150
140
  mergeShortcuts(
151
- extension.getKeyboardShortcuts(this.editor),
141
+ extension.getKeyboardShortcuts(editor),
152
142
  extension.name,
153
143
  );
154
144
  }
@@ -156,17 +146,17 @@ export class ExtensionManager {
156
146
  this.plugins.push(
157
147
  ...extension.getProseMirrorPlugins(),
158
148
  );
159
- this.commandManager.mergeCommandFactories(
160
- extension.getCommandFactories(this.editor),
149
+ editor.mergeCommandFactories(
150
+ extension.getCommandFactories(editor),
161
151
  extension.name,
162
152
  );
163
153
  mergeShortcuts(
164
- extension.getKeyboardShortcuts(this.editor),
154
+ extension.getKeyboardShortcuts(editor),
165
155
  extension.name,
166
156
  );
167
157
  converters = {
168
158
  ...converters,
169
- ...extension.getConverters(this.editor, this.schema),
159
+ ...extension.getConverters(editor, schema),
170
160
  };
171
161
  }
172
162
  }
@@ -193,7 +183,7 @@ export class ExtensionManager {
193
183
 
194
184
  this.plugins.push(new InputRulesPlugin(inputRules));
195
185
  this.plugins.push(new KeymapPlugin(Object.fromEntries(keyBindings)));
196
- this.plugins.push(new TrackSelecionPlugin(this.editor));
186
+ this.plugins.push(new TrackSelecionPlugin(editor));
197
187
  }
198
188
 
199
189
  private setupExtensions(extensions: Set<AnyExtensionOrReq>) {
@@ -202,7 +192,9 @@ export class ExtensionManager {
202
192
  const createMap = (extensions: Set<AnyExtensionOrReq>) => {
203
193
  for (const extension of extensions) {
204
194
  if ('name' in extension) {
205
- allExtensions.set(extension.name, extension);
195
+ if (!allExtensions.has(extension.name)) {
196
+ allExtensions.set(extension.name, extension);
197
+ }
206
198
  }
207
199
  if ('requires' in extension) {
208
200
  const childExtensions = Array.from(extension.requires).filter((e) =>
@@ -268,24 +260,23 @@ export class ExtensionManager {
268
260
  }
269
261
  }
270
262
 
271
- getSchemaByResolvedExtensions(editor: CoreEditor): Schema {
263
+ getSchemaByResolvedExtensions(): Schema {
272
264
  const { nodeExtensions, markExtensions, baseExtensions } = splitExtensions(
273
265
  this.extensions,
274
266
  );
275
267
 
276
- for (const extension of baseExtensions) {
277
- if (Array.isArray(extension.conflicts)) {
278
- for (const name of extension.conflicts) {
279
- if (this.getExtension(name)) {
280
- throw new Error(`Extension conflict: ${extension.name} vs ${name}`);
281
- }
282
- }
283
- }
284
- }
285
-
286
268
  const nodes: { [name: string]: NodeSpec } = {};
269
+ let topNode = '';
287
270
  for (const extension of nodeExtensions) {
288
271
  nodes[extension.name] = extension.getNodeSpec();
272
+
273
+ if (nodes[extension.name].EMPTY_DOC) {
274
+ if (topNode) {
275
+ throw new Error(`Multiple topNodes: ${extension.name}, ${topNode}`);
276
+ }
277
+ topNode = extension.name;
278
+ }
279
+
289
280
  addAttributesToSchema(nodes[extension.name], extension);
290
281
  }
291
282
 
@@ -296,7 +287,7 @@ export class ExtensionManager {
296
287
  }
297
288
 
298
289
  const spec = {
299
- topNode: this.editor.config.topNode || 'doc',
290
+ topNode: topNode || 'doc',
300
291
  nodes,
301
292
  marks,
302
293
  };
@@ -307,19 +298,25 @@ export class ExtensionManager {
307
298
  }
308
299
  }
309
300
 
310
- const event = new CustomEvent('schema:spec', {
311
- detail: {
312
- editor,
313
- spec,
314
- },
315
- });
316
- editor.dispatchEvent(event);
317
-
318
301
  return new Schema(spec);
319
302
  }
320
303
 
321
- created() {
322
- this.initPlugins();
304
+ created(editor: CoreEditor, schema: Schema) {
305
+ const { nodeExtensions, markExtensions, baseExtensions } = splitExtensions(
306
+ this.extensions,
307
+ );
308
+
309
+ for (const extension of baseExtensions) {
310
+ if (Array.isArray(extension.conflicts)) {
311
+ for (const name of extension.conflicts) {
312
+ if (this.getExtension(name)) {
313
+ throw new Error(`Extension conflict: ${extension.name} vs ${name}`);
314
+ }
315
+ }
316
+ }
317
+ }
318
+
319
+ this.initPlugins(editor, schema);
323
320
 
324
321
  for (const extension of this.extensions) {
325
322
  extension.created();
package/src/Node.ts CHANGED
@@ -14,7 +14,7 @@ export interface NodeConfig {
14
14
  }
15
15
 
16
16
  export interface CommandFactories {
17
- [key: string]: () => Command;
17
+ [key: string]: (...args: any[]) => Command;
18
18
  }
19
19
 
20
20
  export abstract class Node {
@@ -80,10 +80,6 @@ export class CommandManager {
80
80
  };
81
81
  }
82
82
 
83
- get state(): EditorState {
84
- return this.editor.state;
85
- }
86
-
87
83
  get chain(): () => ChainedCommands {
88
84
  return () => this.createChain();
89
85
  }
@@ -96,7 +92,8 @@ export class CommandManager {
96
92
  startTr?: Transaction,
97
93
  shouldDispatch = true,
98
94
  ): ChainedCommands {
99
- const { commandFactories, editor, state } = this;
95
+ const { commandFactories, editor } = this;
96
+ const state = this.editor.state;
100
97
  const { view } = editor;
101
98
  const callbacks: boolean[] = [];
102
99
  const hasStartTransaction = !!startTr;
@@ -32,7 +32,8 @@ import { EditorView } from 'prosemirror-view';
32
32
 
33
33
  import { type Command, CommandFactory } from './types.js';
34
34
  import {
35
- runInputRules,
35
+ runInputRulesRange,
36
+ runInputRulesTexts,
36
37
  undoInputRuleCommand,
37
38
  } from '../plugins/input-rules/InputRulesPlugin.js';
38
39
 
@@ -54,7 +55,8 @@ const wrapInList = (
54
55
  if (!range) return false;
55
56
  // let tr = dispatch ? state.tr : null;
56
57
  const tr = state.tr;
57
- if (!wrapRangeInList(tr, range, listType, attrs)) return false;
58
+ const cmd = wrapRangeInList(tr, range, listType, attrs);
59
+ if (!cmd(state, dispatch)) return false;
58
60
  if (dispatch) dispatch(tr!.scrollIntoView());
59
61
  return true;
60
62
  };
@@ -1099,5 +1101,6 @@ export const baseCommandFactories: Record<string, CommandFactory> = {
1099
1101
  setBlockType,
1100
1102
  toggleMark,
1101
1103
  undoInputRule,
1102
- runInputRules,
1104
+ runInputRulesRange,
1105
+ runInputRulesTexts,
1103
1106
  };