@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.
Files changed (170) hide show
  1. package/dist/editor-KZlceNQ1.d.ts +722 -0
  2. package/dist/editor-KZlceNQ1.d.ts.map +1 -0
  3. package/dist/{editor-DlGlYOp-.js → editor-TvRTsFdO.js} +102 -196
  4. package/dist/editor-TvRTsFdO.js.map +1 -0
  5. package/dist/prosekit-core-test.d.ts +20 -19
  6. package/dist/prosekit-core-test.d.ts.map +1 -0
  7. package/dist/prosekit-core-test.js +5 -8
  8. package/dist/prosekit-core-test.js.map +1 -0
  9. package/dist/prosekit-core.d.ts +797 -792
  10. package/dist/prosekit-core.d.ts.map +1 -0
  11. package/dist/prosekit-core.js +42 -79
  12. package/dist/prosekit-core.js.map +1 -0
  13. package/package.json +14 -12
  14. package/src/commands/add-mark.ts +53 -0
  15. package/src/commands/expand-mark.ts +96 -0
  16. package/src/commands/insert-default-block.spec.ts +102 -0
  17. package/src/commands/insert-default-block.ts +49 -0
  18. package/src/commands/insert-node.ts +71 -0
  19. package/src/commands/insert-text.ts +24 -0
  20. package/src/commands/remove-mark.ts +54 -0
  21. package/src/commands/remove-node.ts +43 -0
  22. package/src/commands/select-all.ts +16 -0
  23. package/src/commands/set-block-type.ts +64 -0
  24. package/src/commands/set-node-attrs.ts +68 -0
  25. package/src/commands/toggle-mark.ts +65 -0
  26. package/src/commands/toggle-node.ts +47 -0
  27. package/src/commands/toggle-wrap.spec.ts +35 -0
  28. package/src/commands/toggle-wrap.ts +42 -0
  29. package/src/commands/unset-block-type.spec.ts +49 -0
  30. package/src/commands/unset-block-type.ts +84 -0
  31. package/src/commands/unset-mark.spec.ts +35 -0
  32. package/src/commands/unset-mark.ts +38 -0
  33. package/src/commands/wrap.ts +50 -0
  34. package/src/editor/action.spec.ts +143 -0
  35. package/src/editor/action.ts +248 -0
  36. package/src/editor/editor.spec.ts +186 -0
  37. package/src/editor/editor.ts +563 -0
  38. package/src/editor/union.spec.ts +108 -0
  39. package/src/editor/union.ts +47 -0
  40. package/src/editor/with-priority.ts +25 -0
  41. package/src/error.ts +28 -0
  42. package/src/extensions/clipboard-serializer.ts +107 -0
  43. package/src/extensions/command.ts +121 -0
  44. package/src/extensions/default-state.spec.ts +60 -0
  45. package/src/extensions/default-state.ts +76 -0
  46. package/src/extensions/doc.ts +31 -0
  47. package/src/extensions/events/doc-change.ts +34 -0
  48. package/src/extensions/events/dom-event.spec.ts +70 -0
  49. package/src/extensions/events/dom-event.ts +117 -0
  50. package/src/extensions/events/editor-event.ts +293 -0
  51. package/src/extensions/events/focus.spec.ts +50 -0
  52. package/src/extensions/events/focus.ts +28 -0
  53. package/src/extensions/events/plugin-view.ts +132 -0
  54. package/src/extensions/history.ts +81 -0
  55. package/src/extensions/keymap-base.ts +60 -0
  56. package/src/extensions/keymap.spec.ts +125 -0
  57. package/src/extensions/keymap.ts +96 -0
  58. package/src/extensions/mark-spec.spec.ts +177 -0
  59. package/src/extensions/mark-spec.ts +181 -0
  60. package/src/extensions/mark-view-effect.ts +85 -0
  61. package/src/extensions/mark-view.ts +43 -0
  62. package/src/extensions/node-spec.spec.ts +224 -0
  63. package/src/extensions/node-spec.ts +199 -0
  64. package/src/extensions/node-view-effect.ts +85 -0
  65. package/src/extensions/node-view.ts +43 -0
  66. package/src/extensions/paragraph.ts +61 -0
  67. package/src/extensions/plugin.spec.ts +153 -0
  68. package/src/extensions/plugin.ts +81 -0
  69. package/src/extensions/text.ts +34 -0
  70. package/src/facets/base-extension.ts +54 -0
  71. package/src/facets/command.ts +21 -0
  72. package/src/facets/facet-extension.spec.ts +173 -0
  73. package/src/facets/facet-extension.ts +53 -0
  74. package/src/facets/facet-node.spec.ts +265 -0
  75. package/src/facets/facet-node.ts +185 -0
  76. package/src/facets/facet-types.ts +9 -0
  77. package/src/facets/facet.spec.ts +76 -0
  78. package/src/facets/facet.ts +84 -0
  79. package/src/facets/root.ts +44 -0
  80. package/src/facets/schema-spec.ts +30 -0
  81. package/src/facets/schema.ts +26 -0
  82. package/src/facets/state.spec.ts +53 -0
  83. package/src/facets/state.ts +85 -0
  84. package/src/facets/union-extension.ts +41 -0
  85. package/src/index.ts +302 -0
  86. package/src/test/index.ts +4 -0
  87. package/src/test/test-builder.ts +68 -0
  88. package/src/test/test-editor.spec.ts +104 -0
  89. package/src/test/test-editor.ts +113 -0
  90. package/src/testing/index.ts +283 -0
  91. package/src/testing/keyboard.ts +5 -0
  92. package/src/types/any-function.ts +4 -0
  93. package/src/types/assert-type-equal.ts +8 -0
  94. package/src/types/attrs.ts +32 -0
  95. package/src/types/base-node-view-options.ts +33 -0
  96. package/src/types/dom-node.ts +1 -0
  97. package/src/types/extension-command.ts +52 -0
  98. package/src/types/extension-mark.ts +15 -0
  99. package/src/types/extension-node.ts +15 -0
  100. package/src/types/extension.spec.ts +56 -0
  101. package/src/types/extension.ts +168 -0
  102. package/src/types/model.ts +54 -0
  103. package/src/types/object-entries.ts +13 -0
  104. package/src/types/pick-string-literal.spec.ts +10 -0
  105. package/src/types/pick-string-literal.ts +6 -0
  106. package/src/types/pick-sub-type.spec.ts +20 -0
  107. package/src/types/pick-sub-type.ts +6 -0
  108. package/src/types/priority.ts +12 -0
  109. package/src/types/setter.ts +4 -0
  110. package/src/types/simplify-deeper.spec.ts +40 -0
  111. package/src/types/simplify-deeper.ts +6 -0
  112. package/src/types/simplify-union.spec.ts +21 -0
  113. package/src/types/simplify-union.ts +11 -0
  114. package/src/utils/array-grouping.spec.ts +29 -0
  115. package/src/utils/array-grouping.ts +25 -0
  116. package/src/utils/array.ts +21 -0
  117. package/src/utils/assert.ts +13 -0
  118. package/src/utils/attrs-match.ts +20 -0
  119. package/src/utils/can-use-regex-lookbehind.ts +12 -0
  120. package/src/utils/clsx.spec.ts +14 -0
  121. package/src/utils/clsx.ts +14 -0
  122. package/src/utils/collect-children.ts +21 -0
  123. package/src/utils/collect-nodes.ts +37 -0
  124. package/src/utils/combine-event-handlers.spec.ts +27 -0
  125. package/src/utils/combine-event-handlers.ts +27 -0
  126. package/src/utils/contains-inline-node.ts +17 -0
  127. package/src/utils/deep-equals.spec.ts +26 -0
  128. package/src/utils/deep-equals.ts +29 -0
  129. package/src/utils/default-block-at.ts +15 -0
  130. package/src/utils/editor-content.spec.ts +47 -0
  131. package/src/utils/editor-content.ts +77 -0
  132. package/src/utils/env.ts +6 -0
  133. package/src/utils/find-parent-node-of-type.ts +29 -0
  134. package/src/utils/find-parent-node.spec.ts +68 -0
  135. package/src/utils/find-parent-node.ts +55 -0
  136. package/src/utils/get-custom-selection.ts +19 -0
  137. package/src/utils/get-dom-api.ts +56 -0
  138. package/src/utils/get-id.spec.ts +14 -0
  139. package/src/utils/get-id.ts +13 -0
  140. package/src/utils/get-mark-type.ts +20 -0
  141. package/src/utils/get-node-type.ts +20 -0
  142. package/src/utils/get-node-types.ts +19 -0
  143. package/src/utils/includes-mark.ts +18 -0
  144. package/src/utils/is-at-block-start.ts +26 -0
  145. package/src/utils/is-in-code-block.ts +18 -0
  146. package/src/utils/is-mark-absent.spec.ts +53 -0
  147. package/src/utils/is-mark-absent.ts +42 -0
  148. package/src/utils/is-mark-active.ts +27 -0
  149. package/src/utils/is-node-active.ts +25 -0
  150. package/src/utils/is-subset.spec.ts +12 -0
  151. package/src/utils/is-subset.ts +11 -0
  152. package/src/utils/maybe-run.spec.ts +39 -0
  153. package/src/utils/maybe-run.ts +11 -0
  154. package/src/utils/merge-objects.spec.ts +30 -0
  155. package/src/utils/merge-objects.ts +11 -0
  156. package/src/utils/merge-specs.ts +35 -0
  157. package/src/utils/object-equal.spec.ts +26 -0
  158. package/src/utils/object-equal.ts +28 -0
  159. package/src/utils/output-spec.test.ts +95 -0
  160. package/src/utils/output-spec.ts +130 -0
  161. package/src/utils/parse.spec.ts +46 -0
  162. package/src/utils/parse.ts +321 -0
  163. package/src/utils/remove-undefined-values.spec.ts +15 -0
  164. package/src/utils/remove-undefined-values.ts +9 -0
  165. package/src/utils/set-selection-around.ts +11 -0
  166. package/src/utils/type-assertion.ts +91 -0
  167. package/src/utils/unicode.spec.ts +10 -0
  168. package/src/utils/unicode.ts +4 -0
  169. package/src/utils/with-skip-code-block.ts +15 -0
  170. package/dist/editor-OUH5V8BA.d.ts +0 -754
@@ -0,0 +1,168 @@
1
+ import type { Schema } from '@prosekit/pm/model'
2
+
3
+ import type {
4
+ CommandTyping,
5
+ ToCommandAction,
6
+ ToCommandCreators,
7
+ } from './extension-command'
8
+ import type {
9
+ MarkTyping,
10
+ ToMarkAction,
11
+ } from './extension-mark'
12
+ import type {
13
+ NodeTyping,
14
+ ToNodeAction,
15
+ } from './extension-node'
16
+ import type { PickStringLiteral } from './pick-string-literal'
17
+ import type { PickSubType } from './pick-sub-type'
18
+ import type { Priority } from './priority'
19
+ import type { SimplifyDeeper } from './simplify-deeper'
20
+ import type { SimplifyUnion } from './simplify-union'
21
+
22
+ /**
23
+ * @internal
24
+ */
25
+ export interface ExtensionTyping<
26
+ N extends NodeTyping = never,
27
+ M extends MarkTyping = never,
28
+ C extends CommandTyping = never,
29
+ > {
30
+ Nodes?: N
31
+ Marks?: M
32
+ Commands?: C
33
+ }
34
+
35
+ /**
36
+ * @public
37
+ */
38
+ export interface Extension<
39
+ T extends ExtensionTyping<any, any, any> = ExtensionTyping<any, any, any>,
40
+ > {
41
+ extension: Extension | Extension[]
42
+ priority?: Priority
43
+
44
+ /**
45
+ * @public
46
+ *
47
+ * The schema that this extension represents.
48
+ */
49
+ schema: Schema | null
50
+
51
+ /** @internal */
52
+ _type?: T
53
+ }
54
+
55
+ /**
56
+ * @internal
57
+ */
58
+ export type ExtractTyping<E extends Extension> = E extends Extension<ExtensionTyping<infer N, infer M, infer C>> ? ExtensionTyping<
59
+ PickSubType<N, NodeTyping>,
60
+ PickSubType<M, MarkTyping>,
61
+ PickSubType<C, CommandTyping>
62
+ >
63
+ : never
64
+
65
+ /**
66
+ * An extension that does not define any nodes, marks, or commands.
67
+ *
68
+ * @internal
69
+ */
70
+ export type PlainExtension = Extension<{
71
+ Nodes: never
72
+ Marks: never
73
+ Commands: never
74
+ }>
75
+
76
+ /**
77
+ * @public
78
+ */
79
+ export type ExtractNodes<E extends Extension> = SimplifyDeeper<
80
+ SimplifyUnion<ExtractTyping<E>['Nodes']>
81
+ >
82
+
83
+ /**
84
+ * @public
85
+ */
86
+ export type ExtractNodeNames<E extends Extension> = PickStringLiteral<
87
+ keyof ExtractNodes<E>
88
+ >
89
+
90
+ /**
91
+ * @public
92
+ */
93
+ export type ExtractMarks<E extends Extension> = SimplifyDeeper<
94
+ SimplifyUnion<ExtractTyping<E>['Marks']>
95
+ >
96
+
97
+ /**
98
+ * @public
99
+ */
100
+ export type ExtractMarkNames<E extends Extension> = PickStringLiteral<
101
+ keyof ExtractMarks<E>
102
+ >
103
+
104
+ /**
105
+ * @internal
106
+ */
107
+ export type ExtractCommands<E extends Extension> = SimplifyUnion<
108
+ ExtractTyping<E>['Commands']
109
+ >
110
+
111
+ /**
112
+ * @public
113
+ */
114
+ export type ExtractCommandCreators<E extends Extension> = ToCommandCreators<
115
+ ExtractCommands<E>
116
+ >
117
+
118
+ /**
119
+ * Extracts the {@link CommandAction}s from an extension type.
120
+ *
121
+ * @public
122
+ */
123
+ export type ExtractCommandActions<E extends Extension> = ToCommandAction<
124
+ ExtractCommands<E>
125
+ >
126
+
127
+ /**
128
+ * Extracts the {@link NodeAction}s from an extension type.
129
+ *
130
+ * @public
131
+ */
132
+ export type ExtractNodeActions<E extends Extension> = ToNodeAction<
133
+ ExtractNodes<E>
134
+ >
135
+
136
+ /**
137
+ * Extracts the {@link MarkAction}s from an extension type.
138
+ *
139
+ * @public
140
+ */
141
+ export type ExtractMarkActions<E extends Extension> = ToMarkAction<
142
+ ExtractMarks<E>
143
+ >
144
+
145
+ /**
146
+ * @deprecated Use `ExtractCommandActions` instead.
147
+ */
148
+ export type ExtractCommandAppliers<E extends Extension> = ExtractCommandActions<E>
149
+
150
+ /**
151
+ * @internal
152
+ */
153
+ export type Union<E extends readonly Extension[]> = Extension<{
154
+ Nodes: ExtractNodes<E[number]>
155
+ Marks: ExtractMarks<E[number]>
156
+ Commands: ExtractCommands<E[number]>
157
+ }>
158
+
159
+ /**
160
+ * @deprecated Use `Union` instead.
161
+ * @internal
162
+ */
163
+ export type UnionExtension<E extends Extension | readonly Extension[]> = E extends readonly Extension[] ? Extension<{
164
+ Nodes: ExtractNodes<E[number]>
165
+ Marks: ExtractMarks<E[number]>
166
+ Commands: ExtractCommands<E[number]>
167
+ }>
168
+ : E
@@ -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,6 @@
1
+ import type { PickSubType } from './pick-sub-type'
2
+
3
+ /**
4
+ * @internal
5
+ */
6
+ export type PickStringLiteral<T> = PickSubType<T, string>
@@ -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,6 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export type PickSubType<Type, ParentType> = Type extends ParentType ? [ParentType] extends [Type] ? never
5
+ : Type
6
+ : never
@@ -0,0 +1,12 @@
1
+ /**
2
+ * ProseKit extension priority.
3
+ *
4
+ * @public
5
+ */
6
+ export enum Priority {
7
+ lowest = 0,
8
+ low = 1,
9
+ default = 2,
10
+ high = 3,
11
+ highest = 4,
12
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export type Setter<T> = (value: T) => void
@@ -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,6 @@
1
+ import type { Simplify } from 'type-fest'
2
+
3
+ /**
4
+ * @internal
5
+ */
6
+ export type SimplifyDeeper<T> = { [KeyType in keyof T]: Simplify<T[KeyType]> }
@@ -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,11 @@
1
+ import type {
2
+ Simplify,
3
+ UnionToIntersection,
4
+ } from 'type-fest'
5
+
6
+ /**
7
+ * @internal
8
+ */
9
+ export type SimplifyUnion<T> = Simplify<
10
+ UnionToIntersection<T extends undefined ? never : T>
11
+ >
@@ -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,13 @@
1
+ import { ProseKitError } from '../error'
2
+
3
+ /**
4
+ * @internal
5
+ */
6
+ export function assert(
7
+ condition: unknown,
8
+ message = 'Assertion failed',
9
+ ): asserts condition {
10
+ if (!condition) {
11
+ throw new ProseKitError(message)
12
+ }
13
+ }
@@ -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,14 @@
1
+ import clsxLite from 'clsx/lite'
2
+
3
+ // This type declaration can be removed if https://github.com/lukeed/clsx/pull/110 gets merged and released
4
+
5
+ /**
6
+ * A utility for constructing `className` strings conditionally.
7
+ *
8
+ * It is a re-export of [clsx/lite](https://www.npmjs.com/package/clsx) with stricter types.
9
+ *
10
+ * @public
11
+ */
12
+ export const clsx: (
13
+ ...args: Array<string | boolean | null | undefined>
14
+ ) => 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
+ }