@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.
Files changed (168) hide show
  1. package/dist/editor-CfkZ4TNU.d.ts +748 -0
  2. package/dist/editor-CfkZ4TNU.d.ts.map +1 -0
  3. package/dist/{editor-DbMrpnmL.js → editor-CizSwUN8.js} +102 -192
  4. package/dist/editor-CizSwUN8.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 +4 -5
  8. package/dist/prosekit-core-test.js.map +1 -0
  9. package/dist/prosekit-core.d.ts +782 -757
  10. package/dist/prosekit-core.d.ts.map +1 -0
  11. package/dist/prosekit-core.js +30 -45
  12. package/dist/prosekit-core.js.map +1 -0
  13. package/package.json +14 -11
  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 +89 -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.ts +91 -0
  68. package/src/extensions/text.ts +34 -0
  69. package/src/facets/base-extension.ts +54 -0
  70. package/src/facets/command.ts +21 -0
  71. package/src/facets/facet-extension.spec.ts +173 -0
  72. package/src/facets/facet-extension.ts +53 -0
  73. package/src/facets/facet-node.spec.ts +265 -0
  74. package/src/facets/facet-node.ts +185 -0
  75. package/src/facets/facet-types.ts +9 -0
  76. package/src/facets/facet.spec.ts +76 -0
  77. package/src/facets/facet.ts +84 -0
  78. package/src/facets/root.ts +44 -0
  79. package/src/facets/schema-spec.ts +30 -0
  80. package/src/facets/schema.ts +26 -0
  81. package/src/facets/state.ts +57 -0
  82. package/src/facets/union-extension.ts +41 -0
  83. package/src/index.ts +302 -0
  84. package/src/test/index.ts +4 -0
  85. package/src/test/test-builder.ts +68 -0
  86. package/src/test/test-editor.spec.ts +104 -0
  87. package/src/test/test-editor.ts +113 -0
  88. package/src/testing/index.ts +283 -0
  89. package/src/testing/keyboard.ts +5 -0
  90. package/src/types/any-function.ts +4 -0
  91. package/src/types/assert-type-equal.ts +8 -0
  92. package/src/types/attrs.ts +32 -0
  93. package/src/types/base-node-view-options.ts +33 -0
  94. package/src/types/dom-node.ts +1 -0
  95. package/src/types/extension-command.ts +52 -0
  96. package/src/types/extension-mark.ts +15 -0
  97. package/src/types/extension-node.ts +15 -0
  98. package/src/types/extension.spec.ts +56 -0
  99. package/src/types/extension.ts +168 -0
  100. package/src/types/model.ts +54 -0
  101. package/src/types/object-entries.ts +13 -0
  102. package/src/types/pick-string-literal.spec.ts +10 -0
  103. package/src/types/pick-string-literal.ts +6 -0
  104. package/src/types/pick-sub-type.spec.ts +20 -0
  105. package/src/types/pick-sub-type.ts +6 -0
  106. package/src/types/priority.ts +12 -0
  107. package/src/types/setter.ts +4 -0
  108. package/src/types/simplify-deeper.spec.ts +40 -0
  109. package/src/types/simplify-deeper.ts +6 -0
  110. package/src/types/simplify-union.spec.ts +21 -0
  111. package/src/types/simplify-union.ts +11 -0
  112. package/src/utils/array-grouping.spec.ts +29 -0
  113. package/src/utils/array-grouping.ts +25 -0
  114. package/src/utils/array.ts +21 -0
  115. package/src/utils/assert.ts +13 -0
  116. package/src/utils/attrs-match.ts +20 -0
  117. package/src/utils/can-use-regex-lookbehind.ts +12 -0
  118. package/src/utils/clsx.spec.ts +14 -0
  119. package/src/utils/clsx.ts +12 -0
  120. package/src/utils/collect-children.ts +21 -0
  121. package/src/utils/collect-nodes.ts +37 -0
  122. package/src/utils/combine-event-handlers.spec.ts +27 -0
  123. package/src/utils/combine-event-handlers.ts +27 -0
  124. package/src/utils/contains-inline-node.ts +17 -0
  125. package/src/utils/deep-equals.spec.ts +26 -0
  126. package/src/utils/deep-equals.ts +29 -0
  127. package/src/utils/default-block-at.ts +15 -0
  128. package/src/utils/editor-content.spec.ts +47 -0
  129. package/src/utils/editor-content.ts +77 -0
  130. package/src/utils/env.ts +6 -0
  131. package/src/utils/find-parent-node-of-type.ts +29 -0
  132. package/src/utils/find-parent-node.spec.ts +68 -0
  133. package/src/utils/find-parent-node.ts +55 -0
  134. package/src/utils/get-custom-selection.ts +19 -0
  135. package/src/utils/get-dom-api.ts +56 -0
  136. package/src/utils/get-id.spec.ts +14 -0
  137. package/src/utils/get-id.ts +13 -0
  138. package/src/utils/get-mark-type.ts +20 -0
  139. package/src/utils/get-node-type.ts +20 -0
  140. package/src/utils/get-node-types.ts +19 -0
  141. package/src/utils/includes-mark.ts +18 -0
  142. package/src/utils/is-at-block-start.ts +26 -0
  143. package/src/utils/is-in-code-block.ts +18 -0
  144. package/src/utils/is-mark-absent.spec.ts +53 -0
  145. package/src/utils/is-mark-absent.ts +42 -0
  146. package/src/utils/is-mark-active.ts +27 -0
  147. package/src/utils/is-node-active.ts +25 -0
  148. package/src/utils/is-subset.spec.ts +12 -0
  149. package/src/utils/is-subset.ts +11 -0
  150. package/src/utils/maybe-run.spec.ts +39 -0
  151. package/src/utils/maybe-run.ts +11 -0
  152. package/src/utils/merge-objects.spec.ts +30 -0
  153. package/src/utils/merge-objects.ts +11 -0
  154. package/src/utils/merge-specs.ts +35 -0
  155. package/src/utils/object-equal.spec.ts +26 -0
  156. package/src/utils/object-equal.ts +28 -0
  157. package/src/utils/output-spec.test.ts +95 -0
  158. package/src/utils/output-spec.ts +130 -0
  159. package/src/utils/parse.spec.ts +46 -0
  160. package/src/utils/parse.ts +321 -0
  161. package/src/utils/remove-undefined-values.spec.ts +15 -0
  162. package/src/utils/remove-undefined-values.ts +9 -0
  163. package/src/utils/set-selection-around.ts +11 -0
  164. package/src/utils/type-assertion.ts +91 -0
  165. package/src/utils/unicode.spec.ts +10 -0
  166. package/src/utils/unicode.ts +4 -0
  167. package/src/utils/with-skip-code-block.ts +15 -0
  168. package/dist/editor-CjVyjJqw.d.ts +0 -739
@@ -0,0 +1,283 @@
1
+ import '@prosekit/pm/view/style/prosemirror.css'
2
+
3
+ import type { Attrs } from '@prosekit/pm/model'
4
+
5
+ import { union } from '../editor/union'
6
+ import { withPriority } from '../editor/with-priority'
7
+ import { defineBaseCommands } from '../extensions/command'
8
+ import { defineHistory } from '../extensions/history'
9
+ import { defineBaseKeymap } from '../extensions/keymap-base'
10
+ import { defineMarkSpec } from '../extensions/mark-spec'
11
+ import { defineNodeSpec } from '../extensions/node-spec'
12
+ import {
13
+ createTestEditor,
14
+ type TestEditor,
15
+ } from '../test'
16
+ import type {
17
+ Extension,
18
+ ExtractMarkActions,
19
+ ExtractNodeActions,
20
+ } from '../types/extension'
21
+ import { Priority } from '../types/priority'
22
+
23
+ type DocExtension = Extension<{ Nodes: { doc: Attrs } }>
24
+
25
+ /**
26
+ * @internal
27
+ */
28
+ export function defineDoc(): DocExtension {
29
+ return defineNodeSpec({
30
+ name: 'doc',
31
+ content: 'block+',
32
+ topNode: true,
33
+ })
34
+ }
35
+
36
+ type ParagraphExtension = Extension<{
37
+ Nodes: {
38
+ paragraph: Attrs
39
+ }
40
+ }>
41
+
42
+ /**
43
+ * @internal
44
+ */
45
+ function defineParagraphSpec(): ParagraphExtension {
46
+ return defineNodeSpec({
47
+ name: 'paragraph',
48
+ content: 'inline*',
49
+ group: 'block',
50
+ parseDOM: [{ tag: 'p' }],
51
+ toDOM() {
52
+ return ['p', 0]
53
+ },
54
+ })
55
+ }
56
+
57
+ /**
58
+ * @internal
59
+ */
60
+ export function defineParagraph(): ParagraphExtension {
61
+ return withPriority(defineParagraphSpec(), Priority.highest)
62
+ }
63
+
64
+ type TextExtension = Extension<{
65
+ Nodes: {
66
+ text: Attrs
67
+ }
68
+ }>
69
+
70
+ /**
71
+ * @internal
72
+ */
73
+ export function defineText(): TextExtension {
74
+ return defineNodeSpec({
75
+ name: 'text',
76
+ group: 'inline',
77
+ })
78
+ }
79
+
80
+ type BoldExtension = Extension<{
81
+ Marks: {
82
+ bold: Attrs
83
+ }
84
+ }>
85
+
86
+ /**
87
+ * @internal
88
+ */
89
+ function defineBold(): BoldExtension {
90
+ return defineMarkSpec({
91
+ name: 'bold',
92
+ parseDOM: [{ tag: 'strong' }],
93
+ toDOM() {
94
+ return ['strong', 0]
95
+ },
96
+ })
97
+ }
98
+
99
+ type ItalicExtension = Extension<{
100
+ Marks: {
101
+ italic: Attrs
102
+ }
103
+ }>
104
+
105
+ /**
106
+ * @internal
107
+ */
108
+ function defineItalic(): ItalicExtension {
109
+ return defineMarkSpec({
110
+ name: 'italic',
111
+ parseDOM: [{ tag: 'em' }],
112
+ toDOM() {
113
+ return ['em', 0]
114
+ },
115
+ })
116
+ }
117
+
118
+ interface LinkAttrs {
119
+ href: string
120
+ target?: string | null
121
+ rel?: string | null
122
+ }
123
+
124
+ type LinkExtension = Extension<{
125
+ Marks: {
126
+ link: LinkAttrs
127
+ }
128
+ }>
129
+
130
+ /**
131
+ * @internal
132
+ */
133
+ function defineLink(): LinkExtension {
134
+ return defineMarkSpec<'link', LinkAttrs>({
135
+ name: 'link',
136
+ inclusive: false,
137
+ attrs: {
138
+ href: { validate: 'string' },
139
+ target: { default: null, validate: 'string|null' },
140
+ rel: { default: null, validate: 'string|null' },
141
+ },
142
+ parseDOM: [
143
+ {
144
+ tag: 'a[href]',
145
+ getAttrs: (dom: HTMLElement) => {
146
+ return {
147
+ href: dom.getAttribute('href') || '',
148
+ target: dom.getAttribute('target') || null,
149
+ rel: dom.getAttribute('rel') || null,
150
+ }
151
+ },
152
+ },
153
+ ],
154
+ toDOM(node) {
155
+ const { href, target, rel } = node.attrs as LinkAttrs
156
+ return ['a', { href, target, rel }, 0]
157
+ },
158
+ })
159
+ }
160
+
161
+ type HeadingExtension = Extension<{
162
+ Nodes: {
163
+ heading: Attrs
164
+ }
165
+ }>
166
+
167
+ /**
168
+ * @internal
169
+ */
170
+ function defineHeading(): HeadingExtension {
171
+ return defineNodeSpec({
172
+ name: 'heading',
173
+ content: 'inline*',
174
+ group: 'block',
175
+ defining: true,
176
+ parseDOM: [{ tag: 'h1' }],
177
+ toDOM() {
178
+ return ['h1', 0]
179
+ },
180
+ })
181
+ }
182
+
183
+ type CodeBlockExtension = Extension<{
184
+ Nodes: {
185
+ codeBlock: { language: string }
186
+ }
187
+ }>
188
+
189
+ /**
190
+ * @internal
191
+ */
192
+ function defineCodeBlock(): CodeBlockExtension {
193
+ return defineNodeSpec({
194
+ name: 'codeBlock',
195
+ content: 'text*',
196
+ group: 'block',
197
+ code: true,
198
+ defining: true,
199
+ marks: '',
200
+ attrs: { language: { default: '', validate: 'string' } },
201
+ toDOM() {
202
+ return ['pre', ['code', 0]]
203
+ },
204
+ })
205
+ }
206
+
207
+ type BlockquoteExtension = Extension<{
208
+ Nodes: {
209
+ blockquote: Attrs
210
+ }
211
+ }>
212
+
213
+ /**
214
+ * @internal
215
+ */
216
+ function defineBlockquote(): BlockquoteExtension {
217
+ return defineNodeSpec({
218
+ name: 'blockquote',
219
+ content: 'block+',
220
+ group: 'block',
221
+ defining: true,
222
+ parseDOM: [{ tag: 'blockquote' }],
223
+ toDOM() {
224
+ return ['blockquote', 0]
225
+ },
226
+ })
227
+ }
228
+
229
+ /**
230
+ * @internal
231
+ */
232
+ export function defineTestExtension() {
233
+ return union(
234
+ defineBaseCommands(),
235
+ defineBaseKeymap(),
236
+ defineDoc(),
237
+ defineHistory(),
238
+ defineParagraph(),
239
+ defineText(),
240
+ defineBold(),
241
+ defineItalic(),
242
+ defineLink(),
243
+ defineHeading(),
244
+ defineCodeBlock(),
245
+ defineBlockquote(),
246
+ )
247
+ }
248
+
249
+ /**
250
+ * @internal
251
+ */
252
+ export function setupTestFromExtension<E extends Extension>(
253
+ extension: E,
254
+ ): {
255
+ editor: TestEditor<E>
256
+ n: ExtractNodeActions<E>
257
+ m: ExtractMarkActions<E>
258
+ } {
259
+ const editor = createTestEditor({ extension })
260
+
261
+ const div = document.body.appendChild(document.createElement('div'))
262
+ div.style.minWidth = '200px'
263
+ div.style.minHeight = '200px'
264
+ editor.mount(div)
265
+ editor.view.dom.focus()
266
+
267
+ const n = editor.nodes
268
+ const m = editor.marks
269
+ return { editor, n, m }
270
+ }
271
+
272
+ /**
273
+ * @internal
274
+ */
275
+ export function setupTest() {
276
+ const { editor, m, n } = setupTestFromExtension(defineTestExtension())
277
+
278
+ return {
279
+ editor,
280
+ m,
281
+ n: { ...n, p: n.paragraph },
282
+ }
283
+ }
@@ -0,0 +1,5 @@
1
+ import { userEvent } from '@vitest/browser/context'
2
+
3
+ export async function inputText(input: string): Promise<void> {
4
+ return await userEvent.keyboard(input)
5
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export type AnyFunction = (...args: any[]) => any
@@ -0,0 +1,8 @@
1
+ import type { IsEqual } from 'type-fest'
2
+
3
+ /**
4
+ * Utility function assert that two types are equal in tests.
5
+ */
6
+ export function assertTypeEqual<T, U>(_val: IsEqual<T, U>): void {
7
+ // noop
8
+ }
@@ -0,0 +1,32 @@
1
+ import type { Attrs } from '@prosekit/pm/model'
2
+
3
+ /**
4
+ * An object holding the attributes of a node.
5
+
6
+ * @public
7
+ */
8
+ export type AnyAttrs = Attrs
9
+
10
+ /**
11
+ * @public
12
+ */
13
+ export type AttrSpec<AttrType = any> = {
14
+ /**
15
+ * The default value for this attribute, to use when no explicit value is
16
+ * provided. Attributes that have no default must be provided whenever a node
17
+ * or mark of a type that has them is created.
18
+ */
19
+ default?: AttrType
20
+
21
+ /**
22
+ * A function or type name used to validate values of this attribute. This
23
+ * will be used when deserializing the attribute from JSON, and when running
24
+ * [`Node.check`](https://prosemirror.net/docs/ref/#model.Node.check). When a
25
+ * function, it should raise an exception if the value isn't of the expected
26
+ * type or shape. When a string, it should be a `|`-separated string of
27
+ * primitive types (`"number"`, `"string"`, `"boolean"`, `"null"`, and
28
+ * `"undefined"`), and the library will raise an error when the value is not
29
+ * one of those types.
30
+ */
31
+ validate?: string | ((value: unknown) => void)
32
+ }
@@ -0,0 +1,33 @@
1
+ import type { ProseMirrorNode } from '@prosekit/pm/model'
2
+ import type { NodeView } from '@prosekit/pm/view'
3
+
4
+ // This should be synced with the type `CoreNodeViewUserOptions` from `@prosemirror-adapter/core`
5
+
6
+ /**
7
+ * Some basic props for custom node views.
8
+ *
9
+ * @deprecated - This is no longer needed. Use `CoreNodeViewUserOptions` from `@prosemirror-adapter/core` instead.
10
+ *
11
+ * @hidden
12
+ */
13
+ export interface BaseNodeViewOptions {
14
+ /**
15
+ * The wrapping DOM element for the node view. Defaults to `div` for block nodes and `span` for inline nodes.
16
+ */
17
+ as?: string | HTMLElement | ((node: ProseMirrorNode) => HTMLElement)
18
+
19
+ /**
20
+ * The wrapping DOM element for the node view's content. Defaults to `div` for block nodes and `span` for inline nodes.
21
+ */
22
+ contentAs?: string | HTMLElement | ((node: ProseMirrorNode) => HTMLElement)
23
+
24
+ update?: NodeView['update']
25
+ ignoreMutation?: NodeView['ignoreMutation']
26
+ selectNode?: NodeView['selectNode']
27
+ deselectNode?: NodeView['deselectNode']
28
+ setSelection?: NodeView['setSelection']
29
+ stopEvent?: NodeView['stopEvent']
30
+ destroy?: NodeView['destroy']
31
+
32
+ onUpdate?: () => void
33
+ }
@@ -0,0 +1 @@
1
+ export type DOMNode = InstanceType<typeof window.Node>
@@ -0,0 +1,52 @@
1
+ import type { Command } from '@prosekit/pm/state'
2
+
3
+ /**
4
+ * A function to apply a command to the editor. It will return `true` if the command was applied, and `false` otherwise.
5
+ *
6
+ * It also has a `canExec` method to check if the command can be applied.
7
+ *
8
+ * @public
9
+ */
10
+ export interface CommandAction<Args extends any[] = any[]> {
11
+ /**
12
+ * Execute the current command. Return `true` if the command was successfully
13
+ * executed, otherwise `false`.
14
+ */
15
+ (...args: Args): boolean
16
+
17
+ /**
18
+ * Check if the current command can be executed. Return `true` if the command
19
+ * can be executed, otherwise `false`.
20
+ */
21
+ canExec(...args: Args): boolean
22
+
23
+ /**
24
+ * An alias for `canExec`.
25
+ *
26
+ * @deprecated Use `canExec` instead.
27
+ */
28
+ canApply(...args: Args): boolean
29
+ }
30
+
31
+ export type CommandCreator<Args extends any[] = any[]> = (
32
+ ...arg: Args
33
+ ) => Command
34
+
35
+ /**
36
+ * @internal
37
+ */
38
+ export interface CommandTyping {
39
+ [name: string]: any[]
40
+ }
41
+
42
+ export interface CommandCreators {
43
+ [name: string]: CommandCreator
44
+ }
45
+
46
+ export type ToCommandCreators<T extends CommandTyping> = {
47
+ [K in keyof T]: CommandCreator<T[K]>
48
+ }
49
+
50
+ export type ToCommandAction<T extends CommandTyping> = {
51
+ [K in keyof T]: CommandAction<T[K]>
52
+ }
@@ -0,0 +1,15 @@
1
+ import type { MarkAction } from '../editor/action'
2
+
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface MarkTyping {
7
+ [name: string]: Record<string, any>
8
+ }
9
+
10
+ /**
11
+ * @internal
12
+ */
13
+ export type ToMarkAction<T extends MarkTyping> = {
14
+ [K in keyof T]: MarkAction<T[K]>
15
+ }
@@ -0,0 +1,15 @@
1
+ import type { NodeAction } from '../editor/action'
2
+
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface NodeTyping {
7
+ [name: string]: Record<string, any>
8
+ }
9
+
10
+ /**
11
+ * @internal
12
+ */
13
+ export type ToNodeAction<T extends NodeTyping> = {
14
+ [K in keyof T]: NodeAction<T[K]>
15
+ }
@@ -0,0 +1,56 @@
1
+ import { test } from 'vitest'
2
+
3
+ import { assertTypeEqual } from './assert-type-equal'
4
+ import type {
5
+ Extension,
6
+ Union,
7
+ } from './extension'
8
+
9
+ test('ExtractTyping', () => {
10
+ type E1 = Extension<{
11
+ Nodes: { foo: { attr1: string } }
12
+ }>
13
+ type E2 = Extension<{
14
+ Nodes: { foo: { attr2: number } }
15
+ }>
16
+ type E3 = Extension<{
17
+ Marks: { bar: { attr3: boolean } }
18
+ }>
19
+ type E4 = Extension<{
20
+ Commands: { a: [''] }
21
+ }>
22
+ type E5 = Extension<{
23
+ Nodes: { baz: { attr4: null } }
24
+
25
+ Commands: { b: [string, number]; c: [{ c: boolean }] }
26
+ }>
27
+ type E6 = Extension<{
28
+ Nodes: never
29
+ Marks: never
30
+ Commands: never
31
+ }>
32
+ type E7 = Extension<{
33
+ Nodes: any
34
+ Marks: any
35
+ Commands: any
36
+ }>
37
+ type E = [E1, E2, E3, E4, E5, E6, E7]
38
+
39
+ type Received = Union<E>
40
+ type Expected = Extension<{
41
+ Nodes: {
42
+ foo: { attr1: string; attr2: number }
43
+ baz: { attr4: null }
44
+ }
45
+ Marks: {
46
+ bar: { attr3: boolean }
47
+ }
48
+ Commands: {
49
+ a: ['']
50
+ b: [string, number]
51
+ c: [{ c: boolean }]
52
+ }
53
+ }>
54
+
55
+ assertTypeEqual<Received, Expected>(true)
56
+ })
@@ -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