@prosekit/core 0.8.7 → 0.10.0
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-M9OimMiI.d.ts → editor-BULC1zqX.d.ts} +31 -71
- package/dist/editor-BULC1zqX.d.ts.map +1 -0
- package/dist/{editor-B0L9BgMi.js → editor-g-Rqn-ZE.js} +119 -136
- package/dist/editor-g-Rqn-ZE.js.map +1 -0
- package/dist/prosekit-core-test.d.ts +1 -2
- package/dist/prosekit-core-test.d.ts.map +1 -1
- package/dist/prosekit-core-test.js +1 -1
- package/dist/prosekit-core-test.js.map +1 -1
- package/dist/prosekit-core.d.ts +182 -202
- package/dist/prosekit-core.d.ts.map +1 -1
- package/dist/prosekit-core.js +543 -549
- package/dist/prosekit-core.js.map +1 -1
- package/package.json +9 -12
- package/src/commands/add-mark.ts +1 -4
- package/src/commands/expand-mark.ts +2 -9
- package/src/commands/insert-default-block.spec.ts +1 -5
- package/src/commands/insert-default-block.ts +1 -4
- package/src/commands/insert-node.ts +4 -8
- package/src/commands/remove-mark.ts +1 -4
- package/src/commands/remove-node.ts +2 -2
- package/src/commands/select-all.ts +3 -8
- package/src/commands/select-block.spec.ts +81 -0
- package/src/commands/select-block.ts +56 -0
- package/src/commands/set-block-type.ts +1 -4
- package/src/commands/set-node-attrs-between.spec.ts +221 -0
- package/src/commands/set-node-attrs-between.ts +77 -0
- package/src/commands/set-node-attrs.spec.ts +129 -0
- package/src/commands/set-node-attrs.ts +25 -26
- package/src/commands/toggle-mark.ts +1 -4
- package/src/commands/toggle-node.ts +2 -5
- package/src/commands/toggle-wrap.spec.ts +1 -5
- package/src/commands/toggle-wrap.ts +1 -4
- package/src/commands/unset-block-type.spec.ts +1 -5
- package/src/commands/unset-block-type.ts +2 -8
- package/src/commands/unset-mark.spec.ts +1 -5
- package/src/commands/wrap.ts +2 -10
- package/src/editor/action.spec.ts +2 -6
- package/src/editor/action.ts +2 -19
- package/src/editor/editor.spec.ts +2 -9
- package/src/editor/editor.ts +31 -77
- package/src/editor/union.spec.ts +1 -5
- package/src/editor/union.ts +1 -4
- package/src/extensions/clipboard-serializer.ts +4 -16
- package/src/extensions/command.ts +20 -48
- package/src/extensions/default-state.spec.ts +1 -9
- package/src/extensions/default-state.ts +6 -32
- package/src/extensions/events/dom-event.spec.ts +1 -6
- package/src/extensions/events/dom-event.ts +5 -20
- package/src/extensions/events/editor-event.ts +5 -17
- package/src/extensions/events/focus.spec.ts +1 -6
- package/src/extensions/events/plugin-view.ts +2 -9
- package/src/extensions/history.ts +3 -10
- package/src/extensions/keymap-base.spec.ts +89 -0
- package/src/extensions/keymap-base.ts +34 -13
- package/src/extensions/keymap.spec.ts +12 -22
- package/src/extensions/keymap.ts +16 -69
- package/src/extensions/mark-spec.spec.ts +5 -20
- package/src/extensions/mark-spec.ts +33 -41
- package/src/extensions/mark-view-effect.ts +3 -9
- package/src/extensions/mark-view.ts +2 -8
- package/src/extensions/node-spec.spec.ts +5 -21
- package/src/extensions/node-spec.ts +31 -33
- package/src/extensions/node-view-effect.ts +3 -9
- package/src/extensions/node-view.ts +2 -8
- package/src/extensions/plugin.spec.ts +3 -16
- package/src/extensions/plugin.ts +4 -14
- package/src/facets/base-extension.ts +1 -4
- package/src/facets/command.ts +10 -10
- package/src/facets/facet-extension.spec.ts +4 -15
- package/src/facets/facet-node.spec.ts +2 -9
- package/src/facets/facet-node.ts +4 -9
- package/src/facets/facet.spec.ts +1 -4
- package/src/facets/schema-spec.ts +2 -9
- package/src/facets/schema.ts +3 -12
- package/src/facets/state.spec.ts +8 -15
- package/src/facets/state.ts +5 -20
- package/src/facets/union-extension.ts +2 -8
- package/src/index.ts +42 -188
- package/src/test/index.ts +1 -4
- package/src/test/test-builder.ts +1 -4
- package/src/test/test-editor.spec.ts +1 -5
- package/src/test/test-editor.ts +5 -24
- package/src/testing/index.ts +18 -14
- package/src/types/extension-command.ts +0 -7
- package/src/types/extension.spec.ts +1 -4
- package/src/types/extension.ts +3 -29
- package/src/types/simplify-union.ts +1 -4
- package/src/utils/array-grouping.spec.ts +2 -15
- package/src/utils/array-grouping.ts +1 -14
- package/src/utils/array.ts +0 -4
- package/src/utils/attrs-match.ts +1 -5
- package/src/utils/clsx.spec.ts +1 -4
- package/src/utils/combine-event-handlers.spec.ts +1 -5
- package/src/utils/combine-event-handlers.ts +4 -6
- package/src/utils/default-block-at.ts +1 -4
- package/src/utils/editor-content.spec.ts +1 -4
- package/src/utils/editor-content.ts +7 -19
- package/src/utils/find-node.ts +65 -0
- package/src/utils/find-parent-node-of-type.ts +6 -12
- package/src/utils/find-parent-node.spec.ts +1 -5
- package/src/utils/find-parent-node.ts +1 -4
- package/src/utils/get-custom-selection.ts +1 -5
- package/src/utils/get-mark-type.ts +1 -4
- package/src/utils/get-node-type.ts +1 -4
- package/src/utils/get-node-types.ts +1 -4
- package/src/utils/includes-mark.ts +1 -5
- package/src/utils/is-at-block-start.ts +1 -4
- package/src/utils/is-mark-absent.spec.ts +1 -4
- package/src/utils/is-mark-absent.ts +1 -5
- package/src/utils/is-mark-active.ts +1 -4
- package/src/utils/is-node-active.spec.ts +109 -0
- package/src/utils/is-node-active.ts +17 -8
- package/src/utils/is-subset.spec.ts +1 -4
- package/src/utils/maybe-run.spec.ts +1 -5
- package/src/utils/merge-objects.spec.ts +1 -4
- package/src/utils/merge-objects.ts +2 -1
- package/src/utils/merge-specs.ts +1 -4
- package/src/utils/object-equal.spec.ts +1 -4
- package/src/utils/output-spec.test.ts +1 -5
- package/src/utils/output-spec.ts +12 -9
- package/src/utils/parse.spec.ts +2 -11
- package/src/utils/parse.ts +12 -24
- package/src/utils/remove-undefined-values.spec.ts +1 -4
- package/src/utils/set-selection-around.ts +1 -4
- package/src/utils/type-assertion.ts +2 -21
- package/src/utils/unicode.spec.ts +1 -4
- package/dist/editor-B0L9BgMi.js.map +0 -1
- package/dist/editor-M9OimMiI.d.ts.map +0 -1
- package/src/extensions/doc.ts +0 -31
- package/src/extensions/paragraph.ts +0 -61
- package/src/extensions/text.ts +0 -34
- package/src/types/base-node-view-options.ts +0 -33
- package/src/types/object-entries.ts +0 -13
- package/src/utils/collect-children.ts +0 -21
- package/src/utils/collect-nodes.ts +0 -37
- package/src/utils/deep-equals.spec.ts +0 -26
- package/src/utils/deep-equals.ts +0 -29
- package/src/utils/get-id.spec.ts +0 -14
- package/src/utils/get-id.ts +0 -13
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
import { isElementLike } from '@ocavue/utils'
|
|
2
|
-
import type {
|
|
3
|
-
ProseMirrorNode,
|
|
4
|
-
Schema,
|
|
5
|
-
} from '@prosekit/pm/model'
|
|
2
|
+
import type { ProseMirrorNode, Schema } from '@prosekit/pm/model'
|
|
6
3
|
import { Selection } from '@prosekit/pm/state'
|
|
7
4
|
|
|
8
|
-
import type {
|
|
9
|
-
NodeJSON,
|
|
10
|
-
SelectionJSON,
|
|
11
|
-
} from '../types/model'
|
|
5
|
+
import type { NodeJSON, SelectionJSON } from '../types/model'
|
|
12
6
|
|
|
13
7
|
import { assert } from './assert'
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
jsonFromHTML,
|
|
17
|
-
} from './parse'
|
|
18
|
-
import {
|
|
19
|
-
isProseMirrorNode,
|
|
20
|
-
isSelection,
|
|
21
|
-
} from './type-assertion'
|
|
8
|
+
import { jsonFromElement, jsonFromHTML } from './parse'
|
|
9
|
+
import { isProseMirrorNode, isSelection } from './type-assertion'
|
|
22
10
|
|
|
23
11
|
export function getEditorContentJSON(
|
|
24
12
|
schema: Schema,
|
|
25
|
-
content: NodeJSON | string |
|
|
13
|
+
content: NodeJSON | string | Element,
|
|
26
14
|
): NodeJSON {
|
|
27
15
|
if (typeof content === 'string') {
|
|
28
16
|
return jsonFromHTML(content, { schema })
|
|
@@ -35,7 +23,7 @@ export function getEditorContentJSON(
|
|
|
35
23
|
|
|
36
24
|
function getEditorContentNode(
|
|
37
25
|
schema: Schema,
|
|
38
|
-
content: NodeJSON | string |
|
|
26
|
+
content: NodeJSON | string | Element | ProseMirrorNode,
|
|
39
27
|
): ProseMirrorNode {
|
|
40
28
|
if (isProseMirrorNode(content)) {
|
|
41
29
|
return content
|
|
@@ -45,7 +33,7 @@ function getEditorContentNode(
|
|
|
45
33
|
|
|
46
34
|
export function getEditorContentDoc(
|
|
47
35
|
schema: Schema,
|
|
48
|
-
content: NodeJSON | string |
|
|
36
|
+
content: NodeJSON | string | Element | ProseMirrorNode,
|
|
49
37
|
): ProseMirrorNode {
|
|
50
38
|
const doc = getEditorContentNode(schema, content)
|
|
51
39
|
assert(
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ProseMirrorNode } from '@prosekit/pm/model'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Finds the first node that satisfies the predicate from the given document.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export function findNode(
|
|
9
|
+
doc: ProseMirrorNode,
|
|
10
|
+
predicate: (node: ProseMirrorNode) => boolean,
|
|
11
|
+
): FindNodeResult | undefined {
|
|
12
|
+
let found: FindNodeResult | undefined
|
|
13
|
+
doc.descendants((node, pos, parent, index) => {
|
|
14
|
+
if (found) {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
if (predicate(node)) {
|
|
18
|
+
found = { node, pos, parent, index }
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
return found
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Finds all nodes that satisfy the predicate from the given document.
|
|
27
|
+
*
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export function findNodes(
|
|
31
|
+
doc: ProseMirrorNode,
|
|
32
|
+
predicate: (node: ProseMirrorNode) => boolean,
|
|
33
|
+
): FindNodeResult[] {
|
|
34
|
+
const results: FindNodeResult[] = []
|
|
35
|
+
doc.descendants((node, pos, parent, index) => {
|
|
36
|
+
if (predicate(node)) {
|
|
37
|
+
results.push({ node, pos, parent, index })
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
return results
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The result of the {@link findNode} function.
|
|
45
|
+
*
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
export interface FindNodeResult {
|
|
49
|
+
/**
|
|
50
|
+
* The node that satisfies the predicate.
|
|
51
|
+
*/
|
|
52
|
+
node: ProseMirrorNode
|
|
53
|
+
/**
|
|
54
|
+
* The position of the node.
|
|
55
|
+
*/
|
|
56
|
+
pos: number
|
|
57
|
+
/**
|
|
58
|
+
* The parent of the node.
|
|
59
|
+
*/
|
|
60
|
+
parent: ProseMirrorNode | null
|
|
61
|
+
/**
|
|
62
|
+
* The index of the node in the parent.
|
|
63
|
+
*/
|
|
64
|
+
index: number
|
|
65
|
+
}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
NodeType,
|
|
3
|
-
ResolvedPos,
|
|
4
|
-
} from '@prosekit/pm/model'
|
|
1
|
+
import type { NodeType, ResolvedPos } from '@prosekit/pm/model'
|
|
5
2
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
type FindParentNodeResult,
|
|
9
|
-
} from './find-parent-node'
|
|
10
|
-
import { getNodeType } from './get-node-type'
|
|
3
|
+
import { findParentNode, type FindParentNodeResult } from './find-parent-node'
|
|
4
|
+
import { getNodeTypes } from './get-node-types'
|
|
11
5
|
|
|
12
6
|
/**
|
|
13
7
|
* Finds the closest parent node that matches the given node type.
|
|
@@ -18,12 +12,12 @@ export function findParentNodeOfType(
|
|
|
18
12
|
/**
|
|
19
13
|
* The type of the node to find.
|
|
20
14
|
*/
|
|
21
|
-
type: NodeType | string,
|
|
15
|
+
type: string | NodeType | string[] | NodeType[],
|
|
22
16
|
/**
|
|
23
17
|
* The position to start searching from.
|
|
24
18
|
*/
|
|
25
19
|
$pos: ResolvedPos,
|
|
26
20
|
): FindParentNodeResult | undefined {
|
|
27
|
-
const
|
|
28
|
-
return findParentNode((node) => node.type
|
|
21
|
+
const nodeTypes = getNodeTypes($pos.doc.type.schema, type)
|
|
22
|
+
return findParentNode((node) => nodeTypes.includes(node.type), $pos)
|
|
29
23
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { ResolvedPos } from '@prosekit/pm/model'
|
|
2
|
-
import type {
|
|
3
|
-
EditorState,
|
|
4
|
-
TextSelection,
|
|
5
|
-
} from '@prosekit/pm/state'
|
|
2
|
+
import type { EditorState, TextSelection } from '@prosekit/pm/state'
|
|
6
3
|
import type { EditorView } from '@prosekit/pm/view'
|
|
7
4
|
|
|
8
5
|
/**
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { NodeSelection } from '@prosekit/pm/state'
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import { setupTest } from '../testing'
|
|
5
|
+
|
|
6
|
+
import { isNodeActive } from './is-node-active'
|
|
7
|
+
|
|
8
|
+
describe('isNodeActive', () => {
|
|
9
|
+
it('should return true when cursor is in a node of the specified type', () => {
|
|
10
|
+
const { editor, n } = setupTest()
|
|
11
|
+
editor.set(n.doc(n.p('Hello <a>world')))
|
|
12
|
+
|
|
13
|
+
expect(isNodeActive(editor.state, 'paragraph')).toBe(true)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should return false when cursor is not in a node of the specified type', () => {
|
|
17
|
+
const { editor, n } = setupTest()
|
|
18
|
+
editor.set(n.doc(n.p('Hello <a>world')))
|
|
19
|
+
|
|
20
|
+
expect(isNodeActive(editor.state, 'codeBlock')).toBe(false)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should return true when cursor is in a nested node of the specified type', () => {
|
|
24
|
+
const { editor, n } = setupTest()
|
|
25
|
+
editor.set(n.doc(n.blockquote(n.p('Hello <a>world'))))
|
|
26
|
+
|
|
27
|
+
expect(isNodeActive(editor.state, 'blockquote')).toBe(true)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should return true when cursor is in a node with matching attributes', () => {
|
|
31
|
+
const { editor, n } = setupTest()
|
|
32
|
+
editor.set(n.doc(n.codeBlock({ language: 'typescript' }, '<a>code')))
|
|
33
|
+
|
|
34
|
+
expect(isNodeActive(editor.state, 'codeBlock', { language: 'typescript' })).toBe(true)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should return false when cursor is in a node with non-matching attributes', () => {
|
|
38
|
+
const { editor, n } = setupTest()
|
|
39
|
+
editor.set(n.doc(n.codeBlock({ language: 'typescript' }, '<a>code')))
|
|
40
|
+
|
|
41
|
+
expect(isNodeActive(editor.state, 'codeBlock', { language: 'javascript' })).toBe(false)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('should return true when using NodeSelection with matching type', () => {
|
|
45
|
+
const { editor, n } = setupTest()
|
|
46
|
+
editor.set(n.doc(n.p('Hello world')))
|
|
47
|
+
|
|
48
|
+
const $pos = editor.state.doc.resolve(0)
|
|
49
|
+
const state = editor.state.apply(
|
|
50
|
+
editor.state.tr.setSelection(NodeSelection.create(editor.state.doc, $pos.pos)),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
expect(isNodeActive(state, 'paragraph')).toBe(true)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('should return true when using NodeSelection with matching type and attributes', () => {
|
|
57
|
+
const { editor, n } = setupTest()
|
|
58
|
+
editor.set(n.doc(n.codeBlock({ language: 'python' }, 'code')))
|
|
59
|
+
|
|
60
|
+
const $pos = editor.state.doc.resolve(0)
|
|
61
|
+
const state = editor.state.apply(
|
|
62
|
+
editor.state.tr.setSelection(NodeSelection.create(editor.state.doc, $pos.pos)),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
expect(isNodeActive(state, 'codeBlock', { language: 'python' })).toBe(true)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('should return false when using NodeSelection with non-matching attributes', () => {
|
|
69
|
+
const { editor, n } = setupTest()
|
|
70
|
+
editor.set(n.doc(n.codeBlock({ language: 'python' }, 'code')))
|
|
71
|
+
|
|
72
|
+
const $pos = editor.state.doc.resolve(0)
|
|
73
|
+
const state = editor.state.apply(
|
|
74
|
+
editor.state.tr.setSelection(NodeSelection.create(editor.state.doc, $pos.pos)),
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
expect(isNodeActive(state, 'codeBlock', { language: 'javascript' })).toBe(false)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('should work with NodeType instead of string', () => {
|
|
81
|
+
const { editor, n } = setupTest()
|
|
82
|
+
editor.set(n.doc(n.p('Hello <a>world')))
|
|
83
|
+
|
|
84
|
+
expect(isNodeActive(editor.state, editor.state.schema.nodes.paragraph)).toBe(true)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('should return true when node is at any depth in the hierarchy', () => {
|
|
88
|
+
const { editor, n } = setupTest()
|
|
89
|
+
editor.set(n.doc(n.blockquote(n.p('Hello <a>world'))))
|
|
90
|
+
|
|
91
|
+
expect(isNodeActive(editor.state, 'paragraph')).toBe(true)
|
|
92
|
+
expect(isNodeActive(editor.state, 'blockquote')).toBe(true)
|
|
93
|
+
expect(isNodeActive(editor.state, 'doc')).toBe(true)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('should return true when attributes is null', () => {
|
|
97
|
+
const { editor, n } = setupTest()
|
|
98
|
+
editor.set(n.doc(n.codeBlock({ language: 'typescript' }, '<a>code')))
|
|
99
|
+
|
|
100
|
+
expect(isNodeActive(editor.state, 'codeBlock', null)).toBe(true)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('should match partial attributes', () => {
|
|
104
|
+
const { editor, n } = setupTest()
|
|
105
|
+
editor.set(n.doc(n.codeBlock({ language: 'typescript', lineNumbers: true }, '<a>code')))
|
|
106
|
+
|
|
107
|
+
expect(isNodeActive(editor.state, 'codeBlock', { language: 'typescript' })).toBe(true)
|
|
108
|
+
})
|
|
109
|
+
})
|
|
@@ -1,25 +1,34 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Attrs,
|
|
3
|
-
NodeType,
|
|
4
|
-
} from '@prosekit/pm/model'
|
|
1
|
+
import type { Attrs, NodeType, ProseMirrorNode } from '@prosekit/pm/model'
|
|
5
2
|
import type { EditorState } from '@prosekit/pm/state'
|
|
6
3
|
|
|
7
4
|
import { attrsMatch } from './attrs-match'
|
|
8
5
|
import { getNodeType } from './get-node-type'
|
|
6
|
+
import { isNodeSelection } from './type-assertion'
|
|
9
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
10
11
|
export function isNodeActive(
|
|
11
12
|
state: EditorState,
|
|
12
13
|
type: string | NodeType,
|
|
13
14
|
attrs?: Attrs | null,
|
|
14
15
|
): boolean {
|
|
15
|
-
const
|
|
16
|
-
const
|
|
16
|
+
const { selection, schema } = state
|
|
17
|
+
const $pos = selection.$from
|
|
18
|
+
const nodeType = getNodeType(schema, type)
|
|
19
|
+
|
|
20
|
+
if (isNodeSelection(selection) && checkNode(selection.node, nodeType, attrs)) {
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
17
23
|
|
|
18
24
|
for (let depth = $pos.depth; depth >= 0; depth--) {
|
|
19
|
-
|
|
20
|
-
if (node.type === nodeType && (!attrs || attrsMatch(node, attrs))) {
|
|
25
|
+
if (checkNode($pos.node(depth), nodeType, attrs)) {
|
|
21
26
|
return true
|
|
22
27
|
}
|
|
23
28
|
}
|
|
24
29
|
return false
|
|
25
30
|
}
|
|
31
|
+
|
|
32
|
+
function checkNode(node: ProseMirrorNode, nodeType: NodeType, attrs?: Attrs | null): boolean {
|
|
33
|
+
return node.type === nodeType && (!attrs || attrsMatch(node, attrs))
|
|
34
|
+
}
|
package/src/utils/merge-specs.ts
CHANGED
package/src/utils/output-spec.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import { isElementLike } from '@ocavue/utils'
|
|
2
|
-
import type {
|
|
3
|
-
DOMOutputSpec,
|
|
4
|
-
Mark,
|
|
5
|
-
ProseMirrorNode,
|
|
6
|
-
TagParseRule,
|
|
7
|
-
} from '@prosekit/pm/model'
|
|
8
|
-
|
|
9
|
-
import { isNotNullish } from './type-assertion'
|
|
1
|
+
import { isElementLike, isNotNullish } from '@ocavue/utils'
|
|
2
|
+
import type { DOMOutputSpec, Mark, ParseRule, ProseMirrorNode, TagParseRule } from '@prosekit/pm/model'
|
|
10
3
|
|
|
11
4
|
interface AttrOptions {
|
|
12
5
|
attr: string
|
|
@@ -59,6 +52,16 @@ export function wrapTagParseRuleAttrs(
|
|
|
59
52
|
}
|
|
60
53
|
}
|
|
61
54
|
|
|
55
|
+
export function wrapParseRuleAttrs(
|
|
56
|
+
rule: ParseRule,
|
|
57
|
+
attrs: AttrOptions[],
|
|
58
|
+
): ParseRule {
|
|
59
|
+
if (rule.tag) {
|
|
60
|
+
return wrapTagParseRuleAttrs(rule, attrs)
|
|
61
|
+
}
|
|
62
|
+
return rule
|
|
63
|
+
}
|
|
64
|
+
|
|
62
65
|
export function insertOutputSpecAttrs(
|
|
63
66
|
dom: DOMOutputSpec,
|
|
64
67
|
attrs: Array<[key: string, value: string]>,
|
package/src/utils/parse.spec.ts
CHANGED
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
describe,
|
|
3
|
-
expect,
|
|
4
|
-
test,
|
|
5
|
-
} from 'vitest'
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
6
2
|
|
|
7
3
|
import { createEditor } from '../editor/editor'
|
|
8
4
|
import { defineTestExtension } from '../testing'
|
|
9
5
|
|
|
10
|
-
import {
|
|
11
|
-
elementFromHTML,
|
|
12
|
-
htmlFromNode,
|
|
13
|
-
nodeFromElement,
|
|
14
|
-
nodeFromHTML,
|
|
15
|
-
} from './parse'
|
|
6
|
+
import { elementFromHTML, htmlFromNode, nodeFromElement, nodeFromHTML } from './parse'
|
|
16
7
|
|
|
17
8
|
describe('parse', () => {
|
|
18
9
|
const extension = defineTestExtension()
|
package/src/utils/parse.ts
CHANGED
|
@@ -1,22 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DOMParser,
|
|
3
|
-
DOMSerializer,
|
|
4
|
-
type ParseOptions,
|
|
5
|
-
type ProseMirrorNode,
|
|
6
|
-
type Schema,
|
|
7
|
-
} from '@prosekit/pm/model'
|
|
1
|
+
import { DOMParser, DOMSerializer, type ParseOptions, type ProseMirrorNode, type Schema } from '@prosekit/pm/model'
|
|
8
2
|
import { EditorState } from '@prosekit/pm/state'
|
|
9
3
|
|
|
10
4
|
import type { DOMNode } from '../types/dom-node'
|
|
11
|
-
import type {
|
|
12
|
-
NodeJSON,
|
|
13
|
-
StateJSON,
|
|
14
|
-
} from '../types/model'
|
|
5
|
+
import type { NodeJSON, StateJSON } from '../types/model'
|
|
15
6
|
|
|
16
|
-
import {
|
|
17
|
-
getBrowserDocument,
|
|
18
|
-
getBrowserWindow,
|
|
19
|
-
} from './get-dom-api'
|
|
7
|
+
import { getBrowserDocument, getBrowserWindow } from './get-dom-api'
|
|
20
8
|
|
|
21
9
|
/** @public */
|
|
22
10
|
export interface DOMParserOptions extends ParseOptions {
|
|
@@ -123,7 +111,7 @@ export function nodeFromJSON(
|
|
|
123
111
|
/////////////// Node <=> Element ///////////////
|
|
124
112
|
|
|
125
113
|
/**
|
|
126
|
-
* Parse a
|
|
114
|
+
* Parse a DOM node to a ProseMirror node.
|
|
127
115
|
*
|
|
128
116
|
* @public
|
|
129
117
|
*
|
|
@@ -145,7 +133,7 @@ export function nodeFromElement(
|
|
|
145
133
|
}
|
|
146
134
|
|
|
147
135
|
/**
|
|
148
|
-
* Serialize a ProseMirror node to
|
|
136
|
+
* Serialize a ProseMirror node to an HTML element.
|
|
149
137
|
*
|
|
150
138
|
* @public
|
|
151
139
|
*
|
|
@@ -179,7 +167,7 @@ export function elementFromNode(
|
|
|
179
167
|
/////////////// Element <=> HTML ///////////////
|
|
180
168
|
|
|
181
169
|
/**
|
|
182
|
-
* Parse
|
|
170
|
+
* Parse an HTML string to an HTML element.
|
|
183
171
|
*
|
|
184
172
|
* @internal
|
|
185
173
|
*/
|
|
@@ -203,7 +191,7 @@ function htmlFromElement(element: HTMLElement): string {
|
|
|
203
191
|
/////////////// Node <=> HTML ///////////////
|
|
204
192
|
|
|
205
193
|
/**
|
|
206
|
-
* Parse
|
|
194
|
+
* Parse an HTML string to a ProseMirror node.
|
|
207
195
|
*
|
|
208
196
|
* @public
|
|
209
197
|
*
|
|
@@ -222,7 +210,7 @@ export function nodeFromHTML(
|
|
|
222
210
|
}
|
|
223
211
|
|
|
224
212
|
/**
|
|
225
|
-
* Serialize a ProseMirror node to
|
|
213
|
+
* Serialize a ProseMirror node to an HTML string
|
|
226
214
|
*
|
|
227
215
|
* @public
|
|
228
216
|
*
|
|
@@ -243,7 +231,7 @@ export function htmlFromNode(
|
|
|
243
231
|
/////////////// JSON <=> Element ///////////////
|
|
244
232
|
|
|
245
233
|
/**
|
|
246
|
-
* Serialize
|
|
234
|
+
* Serialize an HTML element to a ProseMirror document JSON object.
|
|
247
235
|
*
|
|
248
236
|
* @public
|
|
249
237
|
*
|
|
@@ -262,7 +250,7 @@ export function jsonFromElement(
|
|
|
262
250
|
}
|
|
263
251
|
|
|
264
252
|
/**
|
|
265
|
-
* Parse a ProseMirror document JSON object to
|
|
253
|
+
* Parse a ProseMirror document JSON object to an HTML element.
|
|
266
254
|
*
|
|
267
255
|
* @public
|
|
268
256
|
*
|
|
@@ -283,7 +271,7 @@ export function elementFromJSON(
|
|
|
283
271
|
/////////////// JSON <=> HTML ///////////////
|
|
284
272
|
|
|
285
273
|
/**
|
|
286
|
-
* Parse
|
|
274
|
+
* Parse an HTML string to a ProseMirror document JSON object.
|
|
287
275
|
*
|
|
288
276
|
* @public
|
|
289
277
|
*
|
|
@@ -302,7 +290,7 @@ export function jsonFromHTML(
|
|
|
302
290
|
}
|
|
303
291
|
|
|
304
292
|
/**
|
|
305
|
-
* Parse a ProseMirror document JSON object to
|
|
293
|
+
* Parse a ProseMirror document JSON object to an HTML string.
|
|
306
294
|
*
|
|
307
295
|
* @public
|
|
308
296
|
*
|