@prosekit/core 0.0.0 → 0.0.2

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