@prosekit/core 0.8.2 → 0.8.4
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-CfkZ4TNU.d.ts +748 -0
- package/dist/editor-CfkZ4TNU.d.ts.map +1 -0
- package/dist/{editor-DbMrpnmL.js → editor-CizSwUN8.js} +102 -192
- package/dist/editor-CizSwUN8.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 +4 -5
- package/dist/prosekit-core-test.js.map +1 -0
- package/dist/prosekit-core.d.ts +782 -757
- package/dist/prosekit-core.d.ts.map +1 -0
- package/dist/prosekit-core.js +30 -45
- package/dist/prosekit-core.js.map +1 -0
- package/package.json +14 -11
- 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 +89 -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.ts +91 -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.ts +57 -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 +12 -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-CjVyjJqw.d.ts +0 -739
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A JSON representation of the prosemirror node.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export interface NodeJSON {
|
|
7
|
+
type: string
|
|
8
|
+
marks?: Array<{ type: string; attrs?: Record<string, any> }>
|
|
9
|
+
text?: string
|
|
10
|
+
content?: NodeJSON[]
|
|
11
|
+
attrs?: Record<string, any>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A JSON representation of the prosemirror selection.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export interface SelectionJSON {
|
|
20
|
+
anchor: number
|
|
21
|
+
head: number
|
|
22
|
+
type: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A JSON representation of the prosemirror state.
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export interface StateJSON {
|
|
31
|
+
/**
|
|
32
|
+
* The main `ProseMirror` doc.
|
|
33
|
+
*/
|
|
34
|
+
doc: NodeJSON
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The current selection.
|
|
38
|
+
*/
|
|
39
|
+
selection: SelectionJSON
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A JSON representation of the prosemirror step.
|
|
44
|
+
*
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
export interface StepJSON {
|
|
48
|
+
/**
|
|
49
|
+
* The type of the step.
|
|
50
|
+
*/
|
|
51
|
+
stepType: string
|
|
52
|
+
|
|
53
|
+
[x: string]: unknown
|
|
54
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* type MyObject = { a: 1; b: 'B' }
|
|
8
|
+
* type MyEntries = ObjectEntries<MyObject>
|
|
9
|
+
* // ^ ["a", 1] | ["b", "B"]
|
|
10
|
+
*/
|
|
11
|
+
export type ObjectEntries<T extends Record<string, any>> = {
|
|
12
|
+
[K in keyof T]: [K, T[K]]
|
|
13
|
+
}[keyof T]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { assertTypeEqual } from './assert-type-equal'
|
|
4
|
+
import type { PickStringLiteral } from './pick-string-literal'
|
|
5
|
+
|
|
6
|
+
test('PickStringLiteral', () => {
|
|
7
|
+
assertTypeEqual<PickStringLiteral<'foo'>, 'foo'>(true)
|
|
8
|
+
assertTypeEqual<PickStringLiteral<'foo' | 'bar'>, 'foo' | 'bar'>(true)
|
|
9
|
+
assertTypeEqual<PickStringLiteral<string>, never>(true)
|
|
10
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { assertTypeEqual } from './assert-type-equal'
|
|
4
|
+
import type { PickSubType } from './pick-sub-type'
|
|
5
|
+
|
|
6
|
+
test('PickSubType', () => {
|
|
7
|
+
assertTypeEqual<PickSubType<'abc', string>, 'abc'>(true)
|
|
8
|
+
assertTypeEqual<PickSubType<'abc' | 'def', string>, 'abc' | 'def'>(true)
|
|
9
|
+
assertTypeEqual<PickSubType<123, string>, never>(true)
|
|
10
|
+
assertTypeEqual<PickSubType<string, string>, never>(true)
|
|
11
|
+
|
|
12
|
+
assertTypeEqual<PickSubType<{ foo: 1 }, Record<string, number>>, { foo: 1 }>(
|
|
13
|
+
true,
|
|
14
|
+
)
|
|
15
|
+
assertTypeEqual<PickSubType<{ foo: 1 }, Record<string, string>>, never>(true)
|
|
16
|
+
assertTypeEqual<
|
|
17
|
+
PickSubType<Record<string, number>, Record<string, string>>,
|
|
18
|
+
never
|
|
19
|
+
>(true)
|
|
20
|
+
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Simplify } from 'type-fest'
|
|
2
|
+
import { test } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import { assertTypeEqual } from './assert-type-equal'
|
|
5
|
+
import type { SimplifyDeeper } from './simplify-deeper'
|
|
6
|
+
|
|
7
|
+
test('SimplifyDeeper', () => {
|
|
8
|
+
type T1 = {
|
|
9
|
+
nodeA: {
|
|
10
|
+
attr1: string
|
|
11
|
+
} & {
|
|
12
|
+
attr2: string
|
|
13
|
+
}
|
|
14
|
+
} & {
|
|
15
|
+
nodeB: {
|
|
16
|
+
attr3: string
|
|
17
|
+
} & {
|
|
18
|
+
attr4: string
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
interface T2 {
|
|
22
|
+
nodeA: {
|
|
23
|
+
attr1: string
|
|
24
|
+
attr2: string
|
|
25
|
+
}
|
|
26
|
+
nodeB: {
|
|
27
|
+
attr3: string
|
|
28
|
+
attr4: string
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
assertTypeEqual<T1, T1>(true)
|
|
33
|
+
assertTypeEqual<T1, T2>(false)
|
|
34
|
+
|
|
35
|
+
assertTypeEqual<T1, SimplifyDeeper<T1>>(false)
|
|
36
|
+
assertTypeEqual<T2, SimplifyDeeper<T1>>(true)
|
|
37
|
+
|
|
38
|
+
assertTypeEqual<T1, Simplify<T1>>(false)
|
|
39
|
+
assertTypeEqual<T2, Simplify<T1>>(false)
|
|
40
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { assertTypeEqual } from './assert-type-equal'
|
|
4
|
+
import type { SimplifyUnion } from './simplify-union'
|
|
5
|
+
|
|
6
|
+
test('SimplifyUnion', () => {
|
|
7
|
+
type T1 = { a: string } | { b: string }
|
|
8
|
+
|
|
9
|
+
interface T2 {
|
|
10
|
+
a: string
|
|
11
|
+
b: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type T3 = SimplifyUnion<T1>
|
|
15
|
+
|
|
16
|
+
assertTypeEqual<T1, T1>(true)
|
|
17
|
+
assertTypeEqual<T1, T2>(false)
|
|
18
|
+
|
|
19
|
+
assertTypeEqual<T1, T3>(false)
|
|
20
|
+
assertTypeEqual<T2, T3>(true)
|
|
21
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
expect,
|
|
3
|
+
test,
|
|
4
|
+
} from 'vitest'
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
groupBy,
|
|
8
|
+
groupEntries,
|
|
9
|
+
} from './array-grouping'
|
|
10
|
+
|
|
11
|
+
test('groupEntries', () => {
|
|
12
|
+
expect(
|
|
13
|
+
groupEntries([
|
|
14
|
+
['a', 1],
|
|
15
|
+
['b', 2],
|
|
16
|
+
['a', 3],
|
|
17
|
+
]),
|
|
18
|
+
).toEqual({
|
|
19
|
+
a: [1, 3],
|
|
20
|
+
b: [2],
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('groupBy', () => {
|
|
25
|
+
expect(groupBy([1, 2, 3, 4, 5], (n) => n % 2)).toEqual({
|
|
26
|
+
0: [2, 4],
|
|
27
|
+
1: [1, 3, 5],
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ObjectEntries } from '../types/object-entries'
|
|
2
|
+
|
|
3
|
+
export function groupBy<K extends PropertyKey, T>(
|
|
4
|
+
items: Iterable<T>,
|
|
5
|
+
keySelector: (item: T) => K,
|
|
6
|
+
): Partial<Record<K, T[]>> {
|
|
7
|
+
const result: Partial<Record<K, T[]>> = {}
|
|
8
|
+
for (const item of items) {
|
|
9
|
+
const key = keySelector(item)
|
|
10
|
+
const values = (result[key] ||= [])
|
|
11
|
+
values.push(item)
|
|
12
|
+
}
|
|
13
|
+
return result
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function groupEntries<T extends Record<string, any>>(
|
|
17
|
+
entries: ObjectEntries<T>[],
|
|
18
|
+
): { [K in keyof T]?: T[K][] } {
|
|
19
|
+
const result: { [K in keyof T]?: T[K][] } = {}
|
|
20
|
+
for (const [key, value] of entries) {
|
|
21
|
+
const values = (result[key] ||= [])
|
|
22
|
+
values.push(value)
|
|
23
|
+
}
|
|
24
|
+
return result
|
|
25
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function uniqPush<T>(prev: readonly T[], next: readonly T[]): T[] {
|
|
2
|
+
const result = [...prev]
|
|
3
|
+
|
|
4
|
+
for (const item of next) {
|
|
5
|
+
if (!result.includes(item)) {
|
|
6
|
+
result.push(item)
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return result
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export function arraySubtract<T>(a: T[], b: T[]): T[] {
|
|
16
|
+
return a.filter((x) => !b.includes(x))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function toReversed<T>(arr: T[]): T[] {
|
|
20
|
+
return arr.toReversed?.() ?? [...arr].reverse()
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Attrs,
|
|
3
|
+
Mark,
|
|
4
|
+
ProseMirrorNode,
|
|
5
|
+
} from '@prosekit/pm/model'
|
|
6
|
+
|
|
7
|
+
export function attrsMatch(
|
|
8
|
+
nodeOrMark: ProseMirrorNode | Mark,
|
|
9
|
+
attrs: Attrs,
|
|
10
|
+
): boolean {
|
|
11
|
+
const currentAttrs = nodeOrMark.attrs
|
|
12
|
+
|
|
13
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
14
|
+
if (currentAttrs[key] !== value) {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return true
|
|
20
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { once } from '@ocavue/utils'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checks if the browser supports [regex lookbehind assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookbehind_assertion).
|
|
5
|
+
*/
|
|
6
|
+
export const canUseRegexLookbehind: () => boolean = once(() => {
|
|
7
|
+
try {
|
|
8
|
+
return 'ab'.replace(new RegExp('(?<=a)b', 'g'), 'c') === 'ac'
|
|
9
|
+
} catch {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
expect,
|
|
3
|
+
test,
|
|
4
|
+
} from 'vitest'
|
|
5
|
+
|
|
6
|
+
import { clsx } from './clsx'
|
|
7
|
+
|
|
8
|
+
test('joins class names', () => {
|
|
9
|
+
expect(clsx('foo', 'bar')).toBe('foo bar')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('filters falsy values', () => {
|
|
13
|
+
expect(clsx('foo', false, null, undefined, 'baz')).toBe('foo baz')
|
|
14
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import clsxLite from 'clsx/lite'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A utility for constructing `className` strings conditionally.
|
|
5
|
+
*
|
|
6
|
+
* It is a re-export of [clsx/lite](https://www.npmjs.com/package/clsx) with stricter types.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export const clsx: (
|
|
11
|
+
...args: Array<string | boolean | null | undefined>
|
|
12
|
+
) => string = clsxLite
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Fragment,
|
|
3
|
+
ProseMirrorNode,
|
|
4
|
+
} from '@prosekit/pm/model'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Collects all children of a node or a fragment, and returns them as an array.
|
|
8
|
+
*
|
|
9
|
+
* @deprecated Use `node.children` or `fragment.content` instead.
|
|
10
|
+
*
|
|
11
|
+
* @hidden
|
|
12
|
+
*/
|
|
13
|
+
export function collectChildren(
|
|
14
|
+
parent: ProseMirrorNode | Fragment,
|
|
15
|
+
): ProseMirrorNode[] {
|
|
16
|
+
const children: ProseMirrorNode[] = []
|
|
17
|
+
for (let i = 0; i < parent.childCount; i++) {
|
|
18
|
+
children.push(parent.child(i))
|
|
19
|
+
}
|
|
20
|
+
return children
|
|
21
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ProseMirrorFragment,
|
|
3
|
+
ProseMirrorNode,
|
|
4
|
+
} from '@prosekit/pm/model'
|
|
5
|
+
|
|
6
|
+
import { ProseKitError } from '../error'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @hidden
|
|
10
|
+
*
|
|
11
|
+
* @deprecated
|
|
12
|
+
*/
|
|
13
|
+
export type NodeContent = ProseMirrorNode | ProseMirrorFragment | NodeContent[]
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Collects all nodes from a given content.
|
|
17
|
+
*
|
|
18
|
+
* @deprecated Use `collectChildren` instead.
|
|
19
|
+
*
|
|
20
|
+
* @hidden
|
|
21
|
+
*/
|
|
22
|
+
export function collectNodes(content: NodeContent): ProseMirrorNode[] {
|
|
23
|
+
if (Array.isArray(content)) {
|
|
24
|
+
return content.flatMap(collectNodes)
|
|
25
|
+
}
|
|
26
|
+
if (content instanceof ProseMirrorNode) {
|
|
27
|
+
return [content]
|
|
28
|
+
}
|
|
29
|
+
if (content instanceof ProseMirrorFragment) {
|
|
30
|
+
const nodes: ProseMirrorNode[] = []
|
|
31
|
+
for (let i = 0; i < content.childCount; i++) {
|
|
32
|
+
nodes.push(content.child(i))
|
|
33
|
+
}
|
|
34
|
+
return nodes
|
|
35
|
+
}
|
|
36
|
+
throw new ProseKitError(`Invalid node content: ${typeof content}`)
|
|
37
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
expect,
|
|
3
|
+
test,
|
|
4
|
+
vi,
|
|
5
|
+
} from 'vitest'
|
|
6
|
+
|
|
7
|
+
import { combineEventHandlers } from './combine-event-handlers'
|
|
8
|
+
|
|
9
|
+
test('runs handlers in reverse order and stops on true', () => {
|
|
10
|
+
const handler1 = vi.fn(() => false)
|
|
11
|
+
const handler2 = vi.fn(() => true)
|
|
12
|
+
const handler3 = vi.fn(() => false)
|
|
13
|
+
const [setHandlers, run] = combineEventHandlers<() => boolean>()
|
|
14
|
+
setHandlers([handler1, handler2, handler3])
|
|
15
|
+
expect(run()).toBe(true)
|
|
16
|
+
expect(handler3).toHaveBeenCalled()
|
|
17
|
+
expect(handler2).toHaveBeenCalled()
|
|
18
|
+
expect(handler1).not.toHaveBeenCalled()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('returns false when all handlers return false', () => {
|
|
22
|
+
const handler1 = vi.fn(() => false)
|
|
23
|
+
const handler2 = vi.fn(() => false)
|
|
24
|
+
const [setHandlers, run] = combineEventHandlers<() => boolean>()
|
|
25
|
+
setHandlers([handler1, handler2])
|
|
26
|
+
expect(run()).toBe(false)
|
|
27
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { toReversed } from './array'
|
|
2
|
+
|
|
3
|
+
export function combineEventHandlers<
|
|
4
|
+
Handler extends (...args: any[]) => boolean | void,
|
|
5
|
+
Args extends Parameters<Handler> = Parameters<Handler>,
|
|
6
|
+
>(): [
|
|
7
|
+
setHandlers: (eventHandlers: Handler[]) => void,
|
|
8
|
+
combinedEventHandler: (...args: Args) => boolean,
|
|
9
|
+
] {
|
|
10
|
+
let handlers: Handler[] = []
|
|
11
|
+
|
|
12
|
+
function setHandlers(eventHandlers: Handler[]): void {
|
|
13
|
+
// The handlers at the end have a higher priority.
|
|
14
|
+
handlers = toReversed(eventHandlers)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function combinedEventHandler(...args: Args): boolean {
|
|
18
|
+
for (const handler of handlers) {
|
|
19
|
+
if (handler(...args)) {
|
|
20
|
+
return true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return [setHandlers, combinedEventHandler] as const
|
|
27
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ProseMirrorNode } from '@prosekit/pm/model'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export function containsInlineNode(
|
|
7
|
+
doc: ProseMirrorNode,
|
|
8
|
+
from: number,
|
|
9
|
+
to: number,
|
|
10
|
+
): boolean {
|
|
11
|
+
let found = false
|
|
12
|
+
doc.nodesBetween(from, to, (node) => {
|
|
13
|
+
if (found) return false
|
|
14
|
+
if (node.isInline) found = true
|
|
15
|
+
})
|
|
16
|
+
return found
|
|
17
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import OrderedMap from 'orderedmap'
|
|
2
|
+
import {
|
|
3
|
+
expect,
|
|
4
|
+
test,
|
|
5
|
+
} from 'vitest'
|
|
6
|
+
|
|
7
|
+
import { deepEquals } from './deep-equals'
|
|
8
|
+
|
|
9
|
+
test('arrays with equal values are equal', () => {
|
|
10
|
+
expect(deepEquals([1, 2], [1, 2])).toBe(true)
|
|
11
|
+
expect(deepEquals([1, 2], [2, 1])).toBe(false)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('nested objects', () => {
|
|
15
|
+
const a = { a: 1, b: { c: 3 } }
|
|
16
|
+
const b = { a: 1, b: { c: 3 } }
|
|
17
|
+
const c = { a: 1, b: { c: 4 } }
|
|
18
|
+
expect(deepEquals(a, b)).toBe(true)
|
|
19
|
+
expect(deepEquals(a, c)).toBe(false)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('ordered maps', () => {
|
|
23
|
+
const map1 = OrderedMap.from({ a: 1, b: 2 })
|
|
24
|
+
const map2 = OrderedMap.from({ a: 1, b: 2 })
|
|
25
|
+
expect(deepEquals(map1, map2)).toBe(true)
|
|
26
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import OrderedMap from 'orderedmap'
|
|
2
|
+
|
|
3
|
+
export function deepEquals<T>(a: T, b: T): boolean {
|
|
4
|
+
if (a === b) {
|
|
5
|
+
return true
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (!a || !b) {
|
|
9
|
+
return false
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
13
|
+
return a.length === b.length && a.every((x, i) => deepEquals(x, b[i]))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (a instanceof OrderedMap && b instanceof OrderedMap) {
|
|
17
|
+
return a.size === b.size && deepEquals(a.toObject(), b.toObject())
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
21
|
+
const aKeys = Object.keys(a)
|
|
22
|
+
const bKeys = Object.keys(b)
|
|
23
|
+
return (
|
|
24
|
+
aKeys.length === bKeys.length
|
|
25
|
+
&& aKeys.every((key) => deepEquals(a[key as keyof T], b[key as keyof T]))
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ContentMatch,
|
|
3
|
+
NodeType,
|
|
4
|
+
} from '@prosekit/pm/model'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export function defaultBlockAt(match: ContentMatch): NodeType | null {
|
|
10
|
+
for (let i = 0; i < match.edgeCount; i++) {
|
|
11
|
+
const { type } = match.edge(i)
|
|
12
|
+
if (type.isTextblock && !type.hasRequiredAttrs()) return type
|
|
13
|
+
}
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AllSelection } from '@prosekit/pm/state'
|
|
2
|
+
import {
|
|
3
|
+
expect,
|
|
4
|
+
test,
|
|
5
|
+
} from 'vitest'
|
|
6
|
+
|
|
7
|
+
import { setupTest } from '../testing'
|
|
8
|
+
|
|
9
|
+
import { getEditorSelection } from './editor-content'
|
|
10
|
+
|
|
11
|
+
test('getEditorSelection', () => {
|
|
12
|
+
const { n } = setupTest()
|
|
13
|
+
const doc = n.doc(n.paragraph('hello world'))
|
|
14
|
+
expect(getEditorSelection(doc, 'start').toJSON()).toMatchInlineSnapshot(`
|
|
15
|
+
{
|
|
16
|
+
"anchor": 1,
|
|
17
|
+
"head": 1,
|
|
18
|
+
"type": "text",
|
|
19
|
+
}
|
|
20
|
+
`)
|
|
21
|
+
expect(getEditorSelection(doc, 'end').toJSON()).toMatchInlineSnapshot(`
|
|
22
|
+
{
|
|
23
|
+
"anchor": 12,
|
|
24
|
+
"head": 12,
|
|
25
|
+
"type": "text",
|
|
26
|
+
}
|
|
27
|
+
`)
|
|
28
|
+
expect(
|
|
29
|
+
getEditorSelection(doc, {
|
|
30
|
+
anchor: 4,
|
|
31
|
+
head: 8,
|
|
32
|
+
type: 'text',
|
|
33
|
+
}).toJSON(),
|
|
34
|
+
).toMatchInlineSnapshot(`
|
|
35
|
+
{
|
|
36
|
+
"anchor": 4,
|
|
37
|
+
"head": 8,
|
|
38
|
+
"type": "text",
|
|
39
|
+
}
|
|
40
|
+
`)
|
|
41
|
+
expect(getEditorSelection(doc, new AllSelection(doc)).toJSON())
|
|
42
|
+
.toMatchInlineSnapshot(`
|
|
43
|
+
{
|
|
44
|
+
"type": "all",
|
|
45
|
+
}
|
|
46
|
+
`)
|
|
47
|
+
})
|