@prosekit/core 0.8.3 → 0.8.5
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/dist/editor-KZlceNQ1.d.ts +722 -0
- package/dist/editor-KZlceNQ1.d.ts.map +1 -0
- package/dist/{editor-DlGlYOp-.js → editor-TvRTsFdO.js} +102 -196
- package/dist/editor-TvRTsFdO.js.map +1 -0
- package/dist/prosekit-core-test.d.ts +20 -19
- package/dist/prosekit-core-test.d.ts.map +1 -0
- package/dist/prosekit-core-test.js +5 -8
- package/dist/prosekit-core-test.js.map +1 -0
- package/dist/prosekit-core.d.ts +797 -792
- package/dist/prosekit-core.d.ts.map +1 -0
- package/dist/prosekit-core.js +42 -79
- package/dist/prosekit-core.js.map +1 -0
- package/package.json +14 -12
- package/src/commands/add-mark.ts +53 -0
- package/src/commands/expand-mark.ts +96 -0
- package/src/commands/insert-default-block.spec.ts +102 -0
- package/src/commands/insert-default-block.ts +49 -0
- package/src/commands/insert-node.ts +71 -0
- package/src/commands/insert-text.ts +24 -0
- package/src/commands/remove-mark.ts +54 -0
- package/src/commands/remove-node.ts +43 -0
- package/src/commands/select-all.ts +16 -0
- package/src/commands/set-block-type.ts +64 -0
- package/src/commands/set-node-attrs.ts +68 -0
- package/src/commands/toggle-mark.ts +65 -0
- package/src/commands/toggle-node.ts +47 -0
- package/src/commands/toggle-wrap.spec.ts +35 -0
- package/src/commands/toggle-wrap.ts +42 -0
- package/src/commands/unset-block-type.spec.ts +49 -0
- package/src/commands/unset-block-type.ts +84 -0
- package/src/commands/unset-mark.spec.ts +35 -0
- package/src/commands/unset-mark.ts +38 -0
- package/src/commands/wrap.ts +50 -0
- package/src/editor/action.spec.ts +143 -0
- package/src/editor/action.ts +248 -0
- package/src/editor/editor.spec.ts +186 -0
- package/src/editor/editor.ts +563 -0
- package/src/editor/union.spec.ts +108 -0
- package/src/editor/union.ts +47 -0
- package/src/editor/with-priority.ts +25 -0
- package/src/error.ts +28 -0
- package/src/extensions/clipboard-serializer.ts +107 -0
- package/src/extensions/command.ts +121 -0
- package/src/extensions/default-state.spec.ts +60 -0
- package/src/extensions/default-state.ts +76 -0
- package/src/extensions/doc.ts +31 -0
- package/src/extensions/events/doc-change.ts +34 -0
- package/src/extensions/events/dom-event.spec.ts +70 -0
- package/src/extensions/events/dom-event.ts +117 -0
- package/src/extensions/events/editor-event.ts +293 -0
- package/src/extensions/events/focus.spec.ts +50 -0
- package/src/extensions/events/focus.ts +28 -0
- package/src/extensions/events/plugin-view.ts +132 -0
- package/src/extensions/history.ts +81 -0
- package/src/extensions/keymap-base.ts +60 -0
- package/src/extensions/keymap.spec.ts +125 -0
- package/src/extensions/keymap.ts +96 -0
- package/src/extensions/mark-spec.spec.ts +177 -0
- package/src/extensions/mark-spec.ts +181 -0
- package/src/extensions/mark-view-effect.ts +85 -0
- package/src/extensions/mark-view.ts +43 -0
- package/src/extensions/node-spec.spec.ts +224 -0
- package/src/extensions/node-spec.ts +199 -0
- package/src/extensions/node-view-effect.ts +85 -0
- package/src/extensions/node-view.ts +43 -0
- package/src/extensions/paragraph.ts +61 -0
- package/src/extensions/plugin.spec.ts +153 -0
- package/src/extensions/plugin.ts +81 -0
- package/src/extensions/text.ts +34 -0
- package/src/facets/base-extension.ts +54 -0
- package/src/facets/command.ts +21 -0
- package/src/facets/facet-extension.spec.ts +173 -0
- package/src/facets/facet-extension.ts +53 -0
- package/src/facets/facet-node.spec.ts +265 -0
- package/src/facets/facet-node.ts +185 -0
- package/src/facets/facet-types.ts +9 -0
- package/src/facets/facet.spec.ts +76 -0
- package/src/facets/facet.ts +84 -0
- package/src/facets/root.ts +44 -0
- package/src/facets/schema-spec.ts +30 -0
- package/src/facets/schema.ts +26 -0
- package/src/facets/state.spec.ts +53 -0
- package/src/facets/state.ts +85 -0
- package/src/facets/union-extension.ts +41 -0
- package/src/index.ts +302 -0
- package/src/test/index.ts +4 -0
- package/src/test/test-builder.ts +68 -0
- package/src/test/test-editor.spec.ts +104 -0
- package/src/test/test-editor.ts +113 -0
- package/src/testing/index.ts +283 -0
- package/src/testing/keyboard.ts +5 -0
- package/src/types/any-function.ts +4 -0
- package/src/types/assert-type-equal.ts +8 -0
- package/src/types/attrs.ts +32 -0
- package/src/types/base-node-view-options.ts +33 -0
- package/src/types/dom-node.ts +1 -0
- package/src/types/extension-command.ts +52 -0
- package/src/types/extension-mark.ts +15 -0
- package/src/types/extension-node.ts +15 -0
- package/src/types/extension.spec.ts +56 -0
- package/src/types/extension.ts +168 -0
- package/src/types/model.ts +54 -0
- package/src/types/object-entries.ts +13 -0
- package/src/types/pick-string-literal.spec.ts +10 -0
- package/src/types/pick-string-literal.ts +6 -0
- package/src/types/pick-sub-type.spec.ts +20 -0
- package/src/types/pick-sub-type.ts +6 -0
- package/src/types/priority.ts +12 -0
- package/src/types/setter.ts +4 -0
- package/src/types/simplify-deeper.spec.ts +40 -0
- package/src/types/simplify-deeper.ts +6 -0
- package/src/types/simplify-union.spec.ts +21 -0
- package/src/types/simplify-union.ts +11 -0
- package/src/utils/array-grouping.spec.ts +29 -0
- package/src/utils/array-grouping.ts +25 -0
- package/src/utils/array.ts +21 -0
- package/src/utils/assert.ts +13 -0
- package/src/utils/attrs-match.ts +20 -0
- package/src/utils/can-use-regex-lookbehind.ts +12 -0
- package/src/utils/clsx.spec.ts +14 -0
- package/src/utils/clsx.ts +14 -0
- package/src/utils/collect-children.ts +21 -0
- package/src/utils/collect-nodes.ts +37 -0
- package/src/utils/combine-event-handlers.spec.ts +27 -0
- package/src/utils/combine-event-handlers.ts +27 -0
- package/src/utils/contains-inline-node.ts +17 -0
- package/src/utils/deep-equals.spec.ts +26 -0
- package/src/utils/deep-equals.ts +29 -0
- package/src/utils/default-block-at.ts +15 -0
- package/src/utils/editor-content.spec.ts +47 -0
- package/src/utils/editor-content.ts +77 -0
- package/src/utils/env.ts +6 -0
- package/src/utils/find-parent-node-of-type.ts +29 -0
- package/src/utils/find-parent-node.spec.ts +68 -0
- package/src/utils/find-parent-node.ts +55 -0
- package/src/utils/get-custom-selection.ts +19 -0
- package/src/utils/get-dom-api.ts +56 -0
- package/src/utils/get-id.spec.ts +14 -0
- package/src/utils/get-id.ts +13 -0
- package/src/utils/get-mark-type.ts +20 -0
- package/src/utils/get-node-type.ts +20 -0
- package/src/utils/get-node-types.ts +19 -0
- package/src/utils/includes-mark.ts +18 -0
- package/src/utils/is-at-block-start.ts +26 -0
- package/src/utils/is-in-code-block.ts +18 -0
- package/src/utils/is-mark-absent.spec.ts +53 -0
- package/src/utils/is-mark-absent.ts +42 -0
- package/src/utils/is-mark-active.ts +27 -0
- package/src/utils/is-node-active.ts +25 -0
- package/src/utils/is-subset.spec.ts +12 -0
- package/src/utils/is-subset.ts +11 -0
- package/src/utils/maybe-run.spec.ts +39 -0
- package/src/utils/maybe-run.ts +11 -0
- package/src/utils/merge-objects.spec.ts +30 -0
- package/src/utils/merge-objects.ts +11 -0
- package/src/utils/merge-specs.ts +35 -0
- package/src/utils/object-equal.spec.ts +26 -0
- package/src/utils/object-equal.ts +28 -0
- package/src/utils/output-spec.test.ts +95 -0
- package/src/utils/output-spec.ts +130 -0
- package/src/utils/parse.spec.ts +46 -0
- package/src/utils/parse.ts +321 -0
- package/src/utils/remove-undefined-values.spec.ts +15 -0
- package/src/utils/remove-undefined-values.ts +9 -0
- package/src/utils/set-selection-around.ts +11 -0
- package/src/utils/type-assertion.ts +91 -0
- package/src/utils/unicode.spec.ts +10 -0
- package/src/utils/unicode.ts +4 -0
- package/src/utils/with-skip-code-block.ts +15 -0
- package/dist/editor-OUH5V8BA.d.ts +0 -754
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describe,
|
|
3
|
+
expect,
|
|
4
|
+
it,
|
|
5
|
+
} from 'vitest'
|
|
6
|
+
|
|
7
|
+
import { union } from '../editor/union'
|
|
8
|
+
import { withPriority } from '../editor/with-priority'
|
|
9
|
+
import { defineDefaultState } from '../extensions/default-state'
|
|
10
|
+
import {
|
|
11
|
+
defineTestExtension,
|
|
12
|
+
setupTestFromExtension,
|
|
13
|
+
} from '../testing'
|
|
14
|
+
import type { NodeJSON } from '../types/model'
|
|
15
|
+
import { Priority } from '../types/priority'
|
|
16
|
+
|
|
17
|
+
describe('state', () => {
|
|
18
|
+
it('uses doc from extension with highest priority', () => {
|
|
19
|
+
const doc1: NodeJSON = { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'default priority' }] }] }
|
|
20
|
+
const doc2: NodeJSON = { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'highest priority' }] }] }
|
|
21
|
+
const doc3: NodeJSON = { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'lowest priority' }] }] }
|
|
22
|
+
|
|
23
|
+
const extension1 = defineDefaultState({ defaultDoc: doc1 }) // default priority
|
|
24
|
+
const extension2 = withPriority(defineDefaultState({ defaultDoc: doc2 }), Priority.highest)
|
|
25
|
+
const extension3 = withPriority(defineDefaultState({ defaultDoc: doc3 }), Priority.lowest)
|
|
26
|
+
|
|
27
|
+
const combinedExtension = union(defineTestExtension(), extension1, extension2, extension3)
|
|
28
|
+
const { editor } = setupTestFromExtension(combinedExtension)
|
|
29
|
+
|
|
30
|
+
const docText = editor.state.doc.textContent
|
|
31
|
+
|
|
32
|
+
// The extension with the highest priority should set the doc
|
|
33
|
+
expect(docText).toEqual('highest priority')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('uses doc from last extension when all have same priority', () => {
|
|
37
|
+
const doc1 = { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'first' }] }] }
|
|
38
|
+
const doc2 = { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'second' }] }] }
|
|
39
|
+
const doc3 = { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'third' }] }] }
|
|
40
|
+
|
|
41
|
+
const extension1 = defineDefaultState({ defaultDoc: doc1 })
|
|
42
|
+
const extension2 = defineDefaultState({ defaultDoc: doc2 })
|
|
43
|
+
const extension3 = defineDefaultState({ defaultDoc: doc3 })
|
|
44
|
+
|
|
45
|
+
const combinedExtension = union(defineTestExtension(), extension1, extension2, extension3)
|
|
46
|
+
const { editor } = setupTestFromExtension(combinedExtension)
|
|
47
|
+
|
|
48
|
+
const docText = editor.state.doc.textContent
|
|
49
|
+
|
|
50
|
+
// When all have same priority, later extensions override earlier ones
|
|
51
|
+
expect(docText).toEqual('third')
|
|
52
|
+
})
|
|
53
|
+
})
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Mark,
|
|
3
|
+
ProseMirrorNode,
|
|
4
|
+
Schema,
|
|
5
|
+
} from '@prosekit/pm/model'
|
|
6
|
+
import type { EditorStateConfig } from '@prosekit/pm/state'
|
|
7
|
+
import type {
|
|
8
|
+
Plugin,
|
|
9
|
+
Selection,
|
|
10
|
+
} from '@prosekit/pm/state'
|
|
11
|
+
|
|
12
|
+
import { toReversed } from '../utils/array'
|
|
13
|
+
import { assert } from '../utils/assert'
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
defineFacet,
|
|
17
|
+
type Facet,
|
|
18
|
+
} from './facet'
|
|
19
|
+
import {
|
|
20
|
+
rootFacet,
|
|
21
|
+
type RootPayload,
|
|
22
|
+
} from './root'
|
|
23
|
+
|
|
24
|
+
export type StatePayload = (ctx: { schema: Schema }) => EditorStateConfig
|
|
25
|
+
|
|
26
|
+
export const stateFacet: Facet<StatePayload, RootPayload> = defineFacet({
|
|
27
|
+
reduce: () => {
|
|
28
|
+
// An array of state payloads from lower to higher priority.
|
|
29
|
+
let callbacks: StatePayload[] = []
|
|
30
|
+
|
|
31
|
+
const state: StatePayload = (ctx) => {
|
|
32
|
+
let doc: ProseMirrorNode | undefined
|
|
33
|
+
let selection: Selection | undefined
|
|
34
|
+
let schema: Schema | undefined = ctx.schema
|
|
35
|
+
const markSet = new Set<Mark>()
|
|
36
|
+
const pluginSet = new Set<Plugin>()
|
|
37
|
+
|
|
38
|
+
// An array of state payloads from higher to lower priority. This matches the
|
|
39
|
+
// order of plugins required by ProseMirror.
|
|
40
|
+
const reversedCallbacks = toReversed(callbacks)
|
|
41
|
+
|
|
42
|
+
for (const callback of reversedCallbacks) {
|
|
43
|
+
const config = callback(ctx)
|
|
44
|
+
|
|
45
|
+
doc ||= config.doc
|
|
46
|
+
selection ||= config.selection
|
|
47
|
+
schema ||= config.schema
|
|
48
|
+
|
|
49
|
+
for (const mark of (config.storedMarks ?? [])) {
|
|
50
|
+
markSet.add(mark)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (const plugin of (config.plugins ?? [])) {
|
|
54
|
+
// `config.plugins` is an array of plugins from higher to lower priority.
|
|
55
|
+
pluginSet.add(plugin)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// If both doc and schema are provided, the schema is not needed.
|
|
60
|
+
if (doc && schema) {
|
|
61
|
+
schema = undefined
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
assert(
|
|
65
|
+
doc || schema,
|
|
66
|
+
"Can't create state without a schema nor a document",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
doc,
|
|
71
|
+
selection,
|
|
72
|
+
schema,
|
|
73
|
+
storedMarks: Array.from(markSet),
|
|
74
|
+
plugins: Array.from(pluginSet),
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return function reducer(inputs) {
|
|
79
|
+
callbacks = inputs
|
|
80
|
+
return { state }
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
singleton: true,
|
|
84
|
+
parent: rootFacet,
|
|
85
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Extension,
|
|
3
|
+
ExtensionTyping,
|
|
4
|
+
} from '../types/extension'
|
|
5
|
+
import type { Priority } from '../types/priority'
|
|
6
|
+
import { assert } from '../utils/assert'
|
|
7
|
+
|
|
8
|
+
import { BaseExtension } from './base-extension'
|
|
9
|
+
import {
|
|
10
|
+
unionFacetNode,
|
|
11
|
+
type FacetNode,
|
|
12
|
+
} from './facet-node'
|
|
13
|
+
|
|
14
|
+
export class UnionExtensionImpl<T extends ExtensionTyping = ExtensionTyping> extends BaseExtension<T> implements Extension<T> {
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
constructor(public extension: BaseExtension[] = []) {
|
|
19
|
+
super()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
createTree(priority: Priority): FacetNode {
|
|
26
|
+
const pri = this.priority ?? priority
|
|
27
|
+
|
|
28
|
+
const extensions = [...this.extension]
|
|
29
|
+
extensions.sort((a, b) => (a.priority ?? pri) - (b.priority ?? pri))
|
|
30
|
+
|
|
31
|
+
const children: FacetNode[] = extensions.map((ext) => ext.getTree(pri))
|
|
32
|
+
|
|
33
|
+
assert(children.length > 0)
|
|
34
|
+
|
|
35
|
+
let node = children[0]
|
|
36
|
+
for (let i = 1; i < children.length; i++) {
|
|
37
|
+
node = unionFacetNode(node, children[i])
|
|
38
|
+
}
|
|
39
|
+
return node
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
export {
|
|
2
|
+
addMark,
|
|
3
|
+
type AddMarkOptions,
|
|
4
|
+
} from './commands/add-mark'
|
|
5
|
+
export {
|
|
6
|
+
expandMark,
|
|
7
|
+
type ExpandMarkOptions,
|
|
8
|
+
} from './commands/expand-mark'
|
|
9
|
+
export {
|
|
10
|
+
insertDefaultBlock,
|
|
11
|
+
type InsertDefaultBlockOptions,
|
|
12
|
+
} from './commands/insert-default-block'
|
|
13
|
+
export {
|
|
14
|
+
insertNode,
|
|
15
|
+
type InsertNodeOptions,
|
|
16
|
+
} from './commands/insert-node'
|
|
17
|
+
export {
|
|
18
|
+
removeMark,
|
|
19
|
+
type RemoveMarkOptions,
|
|
20
|
+
} from './commands/remove-mark'
|
|
21
|
+
export {
|
|
22
|
+
removeNode,
|
|
23
|
+
type RemoveNodeOptions,
|
|
24
|
+
} from './commands/remove-node'
|
|
25
|
+
export {
|
|
26
|
+
setBlockType,
|
|
27
|
+
type SetBlockTypeOptions,
|
|
28
|
+
} from './commands/set-block-type'
|
|
29
|
+
export {
|
|
30
|
+
setNodeAttrs,
|
|
31
|
+
type SetNodeAttrsOptions,
|
|
32
|
+
} from './commands/set-node-attrs'
|
|
33
|
+
export {
|
|
34
|
+
toggleMark,
|
|
35
|
+
type ToggleMarkOptions,
|
|
36
|
+
} from './commands/toggle-mark'
|
|
37
|
+
export {
|
|
38
|
+
toggleNode,
|
|
39
|
+
type ToggleNodeOptions,
|
|
40
|
+
} from './commands/toggle-node'
|
|
41
|
+
export {
|
|
42
|
+
toggleWrap,
|
|
43
|
+
type ToggleWrapOptions,
|
|
44
|
+
} from './commands/toggle-wrap'
|
|
45
|
+
export {
|
|
46
|
+
unsetBlockType,
|
|
47
|
+
type UnsetBlockTypeOptions,
|
|
48
|
+
} from './commands/unset-block-type'
|
|
49
|
+
export {
|
|
50
|
+
unsetMark,
|
|
51
|
+
type UnsetMarkOptions,
|
|
52
|
+
} from './commands/unset-mark'
|
|
53
|
+
export {
|
|
54
|
+
wrap,
|
|
55
|
+
type WrapOptions,
|
|
56
|
+
} from './commands/wrap'
|
|
57
|
+
export type {
|
|
58
|
+
MarkAction,
|
|
59
|
+
MarkBuilder,
|
|
60
|
+
NodeAction,
|
|
61
|
+
NodeBuilder,
|
|
62
|
+
NodeChild,
|
|
63
|
+
} from './editor/action'
|
|
64
|
+
export {
|
|
65
|
+
createEditor,
|
|
66
|
+
Editor,
|
|
67
|
+
type EditorOptions,
|
|
68
|
+
} from './editor/editor'
|
|
69
|
+
export { union } from './editor/union'
|
|
70
|
+
export { withPriority } from './editor/with-priority'
|
|
71
|
+
export {
|
|
72
|
+
EditorNotFoundError,
|
|
73
|
+
ProseKitError,
|
|
74
|
+
} from './error'
|
|
75
|
+
export {
|
|
76
|
+
defineClipboardSerializer,
|
|
77
|
+
type ClipboardSerializerOptions,
|
|
78
|
+
} from './extensions/clipboard-serializer'
|
|
79
|
+
export {
|
|
80
|
+
defineBaseCommands,
|
|
81
|
+
defineCommands,
|
|
82
|
+
type BaseCommandsExtension,
|
|
83
|
+
} from './extensions/command'
|
|
84
|
+
export {
|
|
85
|
+
defineDefaultState,
|
|
86
|
+
type DefaultStateOptions,
|
|
87
|
+
} from './extensions/default-state'
|
|
88
|
+
export {
|
|
89
|
+
defineDoc,
|
|
90
|
+
type DocExtension,
|
|
91
|
+
} from './extensions/doc'
|
|
92
|
+
export {
|
|
93
|
+
defineDocChangeHandler,
|
|
94
|
+
type DocChangeHandler,
|
|
95
|
+
} from './extensions/events/doc-change'
|
|
96
|
+
export {
|
|
97
|
+
defineDOMEventHandler,
|
|
98
|
+
type DOMEventHandler,
|
|
99
|
+
} from './extensions/events/dom-event'
|
|
100
|
+
export {
|
|
101
|
+
defineClickHandler,
|
|
102
|
+
defineClickOnHandler,
|
|
103
|
+
defineDoubleClickHandler,
|
|
104
|
+
defineDoubleClickOnHandler,
|
|
105
|
+
defineDropHandler,
|
|
106
|
+
defineKeyDownHandler,
|
|
107
|
+
defineKeyPressHandler,
|
|
108
|
+
definePasteHandler,
|
|
109
|
+
defineScrollToSelectionHandler,
|
|
110
|
+
defineTextInputHandler,
|
|
111
|
+
defineTripleClickHandler,
|
|
112
|
+
defineTripleClickOnHandler,
|
|
113
|
+
editorEventFacet,
|
|
114
|
+
type ClickHandler,
|
|
115
|
+
type ClickOnHandler,
|
|
116
|
+
type DoubleClickHandler,
|
|
117
|
+
type DoubleClickOnHandler,
|
|
118
|
+
type DropHandler,
|
|
119
|
+
type EditorEventPayload,
|
|
120
|
+
type KeyDownHandler,
|
|
121
|
+
type KeyPressHandler,
|
|
122
|
+
type PasteHandler,
|
|
123
|
+
type ScrollToSelectionHandler,
|
|
124
|
+
type TextInputHandler,
|
|
125
|
+
type TripleClickHandler,
|
|
126
|
+
type TripleClickOnHandler,
|
|
127
|
+
} from './extensions/events/editor-event'
|
|
128
|
+
export {
|
|
129
|
+
defineFocusChangeHandler,
|
|
130
|
+
type FocusChangeHandler,
|
|
131
|
+
} from './extensions/events/focus'
|
|
132
|
+
export {
|
|
133
|
+
defineMountHandler,
|
|
134
|
+
defineUnmountHandler,
|
|
135
|
+
defineUpdateHandler,
|
|
136
|
+
type MountHandler,
|
|
137
|
+
type UnmountHandler,
|
|
138
|
+
type UpdateHandler,
|
|
139
|
+
} from './extensions/events/plugin-view'
|
|
140
|
+
export {
|
|
141
|
+
defineHistory,
|
|
142
|
+
type HistoryExtension,
|
|
143
|
+
type HistoryOptions,
|
|
144
|
+
} from './extensions/history'
|
|
145
|
+
export {
|
|
146
|
+
defineKeymap,
|
|
147
|
+
keymapFacet,
|
|
148
|
+
type Keymap,
|
|
149
|
+
type KeymapPayload,
|
|
150
|
+
} from './extensions/keymap'
|
|
151
|
+
export {
|
|
152
|
+
defineBaseKeymap,
|
|
153
|
+
type BaseKeymapExtension,
|
|
154
|
+
} from './extensions/keymap-base'
|
|
155
|
+
export {
|
|
156
|
+
defineMarkAttr,
|
|
157
|
+
defineMarkSpec,
|
|
158
|
+
type MarkAttrOptions,
|
|
159
|
+
type MarkSpecOptions,
|
|
160
|
+
} from './extensions/mark-spec'
|
|
161
|
+
export {
|
|
162
|
+
defineMarkView,
|
|
163
|
+
type MarkViewOptions,
|
|
164
|
+
} from './extensions/mark-view'
|
|
165
|
+
export {
|
|
166
|
+
defineMarkViewComponent,
|
|
167
|
+
defineMarkViewFactory,
|
|
168
|
+
type MarkViewComponentOptions,
|
|
169
|
+
type MarkViewFactoryOptions,
|
|
170
|
+
} from './extensions/mark-view-effect'
|
|
171
|
+
export {
|
|
172
|
+
defineNodeAttr,
|
|
173
|
+
defineNodeSpec,
|
|
174
|
+
type NodeAttrOptions,
|
|
175
|
+
type NodeSpecOptions,
|
|
176
|
+
} from './extensions/node-spec'
|
|
177
|
+
export {
|
|
178
|
+
defineNodeView,
|
|
179
|
+
type NodeViewOptions,
|
|
180
|
+
} from './extensions/node-view'
|
|
181
|
+
export {
|
|
182
|
+
defineNodeViewComponent,
|
|
183
|
+
defineNodeViewFactory,
|
|
184
|
+
type NodeViewComponentOptions,
|
|
185
|
+
type NodeViewFactoryOptions,
|
|
186
|
+
} from './extensions/node-view-effect'
|
|
187
|
+
export {
|
|
188
|
+
defineParagraph,
|
|
189
|
+
type ParagraphExtension,
|
|
190
|
+
} from './extensions/paragraph'
|
|
191
|
+
export {
|
|
192
|
+
definePlugin,
|
|
193
|
+
pluginFacet,
|
|
194
|
+
type PluginPayload,
|
|
195
|
+
} from './extensions/plugin'
|
|
196
|
+
export {
|
|
197
|
+
defineText,
|
|
198
|
+
type TextExtension,
|
|
199
|
+
} from './extensions/text'
|
|
200
|
+
export {
|
|
201
|
+
defineFacet,
|
|
202
|
+
type Facet,
|
|
203
|
+
} from './facets/facet'
|
|
204
|
+
export { defineFacetPayload } from './facets/facet-extension'
|
|
205
|
+
export type { AnyFunction } from './types/any-function'
|
|
206
|
+
export type {
|
|
207
|
+
AnyAttrs,
|
|
208
|
+
AttrSpec,
|
|
209
|
+
} from './types/attrs'
|
|
210
|
+
export type { BaseNodeViewOptions } from './types/base-node-view-options'
|
|
211
|
+
export type {
|
|
212
|
+
Extension,
|
|
213
|
+
ExtensionTyping,
|
|
214
|
+
ExtractCommandActions,
|
|
215
|
+
ExtractCommandAppliers,
|
|
216
|
+
ExtractCommandCreators,
|
|
217
|
+
ExtractCommands,
|
|
218
|
+
ExtractMarkActions,
|
|
219
|
+
ExtractMarks,
|
|
220
|
+
ExtractNodeActions,
|
|
221
|
+
ExtractNodes,
|
|
222
|
+
ExtractTyping,
|
|
223
|
+
PlainExtension,
|
|
224
|
+
Union,
|
|
225
|
+
UnionExtension,
|
|
226
|
+
} from './types/extension'
|
|
227
|
+
export type {
|
|
228
|
+
CommandAction,
|
|
229
|
+
CommandTyping,
|
|
230
|
+
} from './types/extension-command'
|
|
231
|
+
export type {
|
|
232
|
+
MarkTyping,
|
|
233
|
+
ToMarkAction,
|
|
234
|
+
} from './types/extension-mark'
|
|
235
|
+
export type {
|
|
236
|
+
NodeTyping,
|
|
237
|
+
ToNodeAction,
|
|
238
|
+
} from './types/extension-node'
|
|
239
|
+
export type {
|
|
240
|
+
NodeJSON,
|
|
241
|
+
SelectionJSON,
|
|
242
|
+
StateJSON,
|
|
243
|
+
StepJSON,
|
|
244
|
+
} from './types/model'
|
|
245
|
+
export type { PickSubType } from './types/pick-sub-type'
|
|
246
|
+
export { Priority } from './types/priority'
|
|
247
|
+
export type { SimplifyDeeper } from './types/simplify-deeper'
|
|
248
|
+
export type { SimplifyUnion } from './types/simplify-union'
|
|
249
|
+
export { assert } from './utils/assert'
|
|
250
|
+
export { canUseRegexLookbehind } from './utils/can-use-regex-lookbehind'
|
|
251
|
+
export { clsx } from './utils/clsx'
|
|
252
|
+
export { collectChildren } from './utils/collect-children'
|
|
253
|
+
export {
|
|
254
|
+
collectNodes,
|
|
255
|
+
type NodeContent,
|
|
256
|
+
} from './utils/collect-nodes'
|
|
257
|
+
export { containsInlineNode } from './utils/contains-inline-node'
|
|
258
|
+
export { defaultBlockAt } from './utils/default-block-at'
|
|
259
|
+
export { isApple } from './utils/env'
|
|
260
|
+
export {
|
|
261
|
+
findParentNode,
|
|
262
|
+
type FindParentNodeResult,
|
|
263
|
+
} from './utils/find-parent-node'
|
|
264
|
+
export { findParentNodeOfType } from './utils/find-parent-node-of-type'
|
|
265
|
+
export { getId as _getId } from './utils/get-id'
|
|
266
|
+
export { getMarkType } from './utils/get-mark-type'
|
|
267
|
+
export { getNodeType } from './utils/get-node-type'
|
|
268
|
+
export { isAtBlockStart } from './utils/is-at-block-start'
|
|
269
|
+
export { isInCodeBlock } from './utils/is-in-code-block'
|
|
270
|
+
export { isMarkAbsent } from './utils/is-mark-absent'
|
|
271
|
+
export { isMarkActive } from './utils/is-mark-active'
|
|
272
|
+
export { maybeRun } from './utils/maybe-run'
|
|
273
|
+
export {
|
|
274
|
+
elementFromJSON,
|
|
275
|
+
elementFromNode,
|
|
276
|
+
htmlFromJSON,
|
|
277
|
+
htmlFromNode,
|
|
278
|
+
jsonFromHTML,
|
|
279
|
+
jsonFromNode,
|
|
280
|
+
jsonFromState,
|
|
281
|
+
nodeFromElement,
|
|
282
|
+
nodeFromHTML,
|
|
283
|
+
nodeFromJSON,
|
|
284
|
+
stateFromJSON,
|
|
285
|
+
type DOMDocumentOptions,
|
|
286
|
+
type DOMParserOptions,
|
|
287
|
+
type DOMSerializerOptions,
|
|
288
|
+
type JSONParserOptions,
|
|
289
|
+
} from './utils/parse'
|
|
290
|
+
export { setSelectionAround } from './utils/set-selection-around'
|
|
291
|
+
export {
|
|
292
|
+
isAllSelection,
|
|
293
|
+
isFragment,
|
|
294
|
+
isMark,
|
|
295
|
+
isNodeSelection,
|
|
296
|
+
isProseMirrorNode,
|
|
297
|
+
isSelection,
|
|
298
|
+
isSlice,
|
|
299
|
+
isTextSelection,
|
|
300
|
+
} from './utils/type-assertion'
|
|
301
|
+
export * from './utils/unicode'
|
|
302
|
+
export { withSkipCodeBlock } from './utils/with-skip-code-block'
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ProseMirrorNode } from '@prosekit/pm/model'
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
ApplyMarkFunction,
|
|
5
|
+
CreateNodeFunction,
|
|
6
|
+
} from '../editor/action'
|
|
7
|
+
import { assert } from '../utils/assert'
|
|
8
|
+
|
|
9
|
+
type Tags = Record<string, number>
|
|
10
|
+
export type TaggedProseMirrorNode = ProseMirrorNode & { tags?: Tags }
|
|
11
|
+
|
|
12
|
+
export const createNodeForTest: CreateNodeFunction = (
|
|
13
|
+
type,
|
|
14
|
+
attrs,
|
|
15
|
+
children: TaggedProseMirrorNode[],
|
|
16
|
+
): TaggedProseMirrorNode => {
|
|
17
|
+
const tags: Tags = {}
|
|
18
|
+
const isTopNode = type === type.schema.topNodeType
|
|
19
|
+
let pos = isTopNode ? 0 : 1
|
|
20
|
+
const normalizedChildren: TaggedProseMirrorNode[] = []
|
|
21
|
+
|
|
22
|
+
for (const child of children) {
|
|
23
|
+
if (child.tags) {
|
|
24
|
+
for (const [key, value] of Object.entries(child.tags)) {
|
|
25
|
+
tags[key] = pos + value
|
|
26
|
+
}
|
|
27
|
+
normalizedChildren.push(child)
|
|
28
|
+
pos += child.nodeSize
|
|
29
|
+
} else if (child.isText) {
|
|
30
|
+
const text = child.text!
|
|
31
|
+
const re = /<(a|b)>/g
|
|
32
|
+
let i = 0
|
|
33
|
+
let out = ''
|
|
34
|
+
for (const match of text.matchAll(re)) {
|
|
35
|
+
out += text.slice(i, match.index)
|
|
36
|
+
tags[match[1]] = pos + out.length
|
|
37
|
+
i = match.index + match[0].length
|
|
38
|
+
}
|
|
39
|
+
out += text.slice(i)
|
|
40
|
+
if (out) {
|
|
41
|
+
normalizedChildren.push(child.type.schema.text(out).mark(child.marks))
|
|
42
|
+
pos += out.length
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
normalizedChildren.push(child)
|
|
46
|
+
pos += child.nodeSize
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const node: TaggedProseMirrorNode | null = type.createAndFill(
|
|
51
|
+
attrs,
|
|
52
|
+
normalizedChildren,
|
|
53
|
+
)
|
|
54
|
+
assert(node, `Failed to create node ${type.name}`)
|
|
55
|
+
node.tags = tags
|
|
56
|
+
return node
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const applyMarkForTest: ApplyMarkFunction = (
|
|
60
|
+
mark,
|
|
61
|
+
children: TaggedProseMirrorNode[],
|
|
62
|
+
): TaggedProseMirrorNode[] => {
|
|
63
|
+
return children.map((node) => {
|
|
64
|
+
const newNode: TaggedProseMirrorNode = node.mark(mark.addToSet(node.marks))
|
|
65
|
+
newNode.tags = node.tags
|
|
66
|
+
return newNode
|
|
67
|
+
})
|
|
68
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describe,
|
|
3
|
+
expect,
|
|
4
|
+
it,
|
|
5
|
+
} from 'vitest'
|
|
6
|
+
|
|
7
|
+
import { setupTest } from '../testing'
|
|
8
|
+
|
|
9
|
+
describe('TestEditor', () => {
|
|
10
|
+
it('should create nodes and marks', () => {
|
|
11
|
+
const { editor, m, n } = setupTest()
|
|
12
|
+
|
|
13
|
+
const doc = n.doc(n.paragraph('Hello ', m.bold('world!')))
|
|
14
|
+
editor.set(doc)
|
|
15
|
+
expect(editor.state.doc.toJSON()).toMatchInlineSnapshot(`
|
|
16
|
+
{
|
|
17
|
+
"content": [
|
|
18
|
+
{
|
|
19
|
+
"content": [
|
|
20
|
+
{
|
|
21
|
+
"text": "Hello ",
|
|
22
|
+
"type": "text",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"marks": [
|
|
26
|
+
{
|
|
27
|
+
"type": "bold",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
"text": "world!",
|
|
31
|
+
"type": "text",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
"type": "paragraph",
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
"type": "doc",
|
|
38
|
+
}
|
|
39
|
+
`)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('should set text selection', () => {
|
|
43
|
+
const { editor, m, n } = setupTest()
|
|
44
|
+
|
|
45
|
+
editor.set(n.doc(n.paragraph('Hello ', m.bold('<a>world<b>!'))))
|
|
46
|
+
expect(editor.state.selection.toJSON()).toMatchInlineSnapshot(`
|
|
47
|
+
{
|
|
48
|
+
"anchor": 7,
|
|
49
|
+
"head": 12,
|
|
50
|
+
"type": "text",
|
|
51
|
+
}
|
|
52
|
+
`)
|
|
53
|
+
expect(
|
|
54
|
+
editor.state.selection.content().content.toString(),
|
|
55
|
+
).toMatchInlineSnapshot(`"<paragraph(bold("world"))>"`)
|
|
56
|
+
|
|
57
|
+
editor.set(n.doc(n.paragraph('Hello ', m.bold('<b>world<a>!'))))
|
|
58
|
+
expect(editor.state.selection.toJSON()).toMatchInlineSnapshot(`
|
|
59
|
+
{
|
|
60
|
+
"anchor": 12,
|
|
61
|
+
"head": 7,
|
|
62
|
+
"type": "text",
|
|
63
|
+
}
|
|
64
|
+
`)
|
|
65
|
+
expect(
|
|
66
|
+
editor.state.selection.content().content.toString(),
|
|
67
|
+
).toMatchInlineSnapshot(`"<paragraph(bold("world"))>"`)
|
|
68
|
+
|
|
69
|
+
editor.set(n.doc(n.paragraph('Hello ', m.bold('<a>world!'))))
|
|
70
|
+
expect(editor.state.selection.toJSON()).toMatchInlineSnapshot(`
|
|
71
|
+
{
|
|
72
|
+
"anchor": 7,
|
|
73
|
+
"head": 7,
|
|
74
|
+
"type": "text",
|
|
75
|
+
}
|
|
76
|
+
`)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should set node selection', () => {
|
|
80
|
+
const { editor, n } = setupTest()
|
|
81
|
+
|
|
82
|
+
editor.set(n.doc('<a>', n.paragraph('foo')))
|
|
83
|
+
expect(editor.state.selection.toJSON()).toMatchInlineSnapshot(`
|
|
84
|
+
{
|
|
85
|
+
"anchor": 0,
|
|
86
|
+
"type": "node",
|
|
87
|
+
}
|
|
88
|
+
`)
|
|
89
|
+
expect(
|
|
90
|
+
editor.state.selection.content().content.toString(),
|
|
91
|
+
).toMatchInlineSnapshot(`"<paragraph("foo")>"`)
|
|
92
|
+
|
|
93
|
+
editor.set(n.doc(n.paragraph('foo'), '<a>', n.paragraph('bar')))
|
|
94
|
+
expect(editor.state.selection.toJSON()).toMatchInlineSnapshot(`
|
|
95
|
+
{
|
|
96
|
+
"anchor": 5,
|
|
97
|
+
"type": "node",
|
|
98
|
+
}
|
|
99
|
+
`)
|
|
100
|
+
expect(
|
|
101
|
+
editor.state.selection.content().content.toString(),
|
|
102
|
+
).toMatchInlineSnapshot(`"<paragraph("bar")>"`)
|
|
103
|
+
})
|
|
104
|
+
})
|