@milkdown/preset-commonmark 6.5.1 → 6.5.3

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 (88) hide show
  1. package/lib/index.d.ts +1 -1
  2. package/lib/index.d.ts.map +1 -1
  3. package/lib/index.es.js +453 -412
  4. package/lib/index.es.js.map +1 -1
  5. package/lib/mark/code-inline.d.ts +1 -1
  6. package/lib/mark/code-inline.d.ts.map +1 -1
  7. package/lib/mark/em.d.ts +1 -1
  8. package/lib/mark/em.d.ts.map +1 -1
  9. package/lib/mark/index.d.ts.map +1 -1
  10. package/lib/mark/link.d.ts +4 -3
  11. package/lib/mark/link.d.ts.map +1 -1
  12. package/lib/mark/strong.d.ts +1 -1
  13. package/lib/mark/strong.d.ts.map +1 -1
  14. package/lib/node/blockquote.d.ts +1 -1
  15. package/lib/node/blockquote.d.ts.map +1 -1
  16. package/lib/node/bullet-list.d.ts +1 -1
  17. package/lib/node/bullet-list.d.ts.map +1 -1
  18. package/lib/node/code-fence.d.ts.map +1 -1
  19. package/lib/node/doc.d.ts +1 -1
  20. package/lib/node/doc.d.ts.map +1 -1
  21. package/lib/node/hardbreak.d.ts.map +1 -1
  22. package/lib/node/heading.d.ts +2 -2
  23. package/lib/node/heading.d.ts.map +1 -1
  24. package/lib/node/hr.d.ts +1 -1
  25. package/lib/node/hr.d.ts.map +1 -1
  26. package/lib/node/image.d.ts +2 -2
  27. package/lib/node/image.d.ts.map +1 -1
  28. package/lib/node/index.d.ts +1 -1
  29. package/lib/node/index.d.ts.map +1 -1
  30. package/lib/node/list-item.d.ts +2 -2
  31. package/lib/node/list-item.d.ts.map +1 -1
  32. package/lib/node/ordered-list.d.ts +1 -1
  33. package/lib/node/ordered-list.d.ts.map +1 -1
  34. package/lib/node/paragraph.d.ts +1 -1
  35. package/lib/node/paragraph.d.ts.map +1 -1
  36. package/lib/node/text.d.ts +1 -1
  37. package/lib/node/text.d.ts.map +1 -1
  38. package/lib/plugin/add-order-in-list.d.ts +1 -1
  39. package/lib/plugin/add-order-in-list.d.ts.map +1 -1
  40. package/lib/plugin/filter-html.d.ts +1 -1
  41. package/lib/plugin/filter-html.d.ts.map +1 -1
  42. package/lib/plugin/index.d.ts +1 -1
  43. package/lib/plugin/index.d.ts.map +1 -1
  44. package/lib/plugin/inline-nodes-cursor.d.ts.map +1 -1
  45. package/lib/plugin/inline-sync/config.d.ts +8 -8
  46. package/lib/plugin/inline-sync/config.d.ts.map +1 -1
  47. package/lib/plugin/inline-sync/context.d.ts +5 -5
  48. package/lib/plugin/inline-sync/context.d.ts.map +1 -1
  49. package/lib/plugin/inline-sync/index.d.ts +1 -1
  50. package/lib/plugin/inline-sync/index.d.ts.map +1 -1
  51. package/lib/plugin/inline-sync/regexp.d.ts.map +1 -1
  52. package/lib/plugin/inline-sync/replacer.d.ts +3 -3
  53. package/lib/plugin/inline-sync/replacer.d.ts.map +1 -1
  54. package/lib/plugin/inline-sync/utils.d.ts +2 -2
  55. package/lib/plugin/inline-sync/utils.d.ts.map +1 -1
  56. package/lib/supported-keys.d.ts +1 -1
  57. package/lib/supported-keys.d.ts.map +1 -1
  58. package/package.json +17 -17
  59. package/src/index.ts +52 -52
  60. package/src/mark/code-inline.ts +56 -55
  61. package/src/mark/em.ts +36 -36
  62. package/src/mark/index.ts +9 -9
  63. package/src/mark/link.ts +250 -218
  64. package/src/mark/strong.ts +37 -37
  65. package/src/node/blockquote.ts +35 -35
  66. package/src/node/bullet-list.ts +65 -65
  67. package/src/node/code-fence.ts +236 -229
  68. package/src/node/doc.ts +21 -21
  69. package/src/node/hardbreak.ts +108 -107
  70. package/src/node/heading.ts +275 -272
  71. package/src/node/hr.ts +55 -55
  72. package/src/node/image.ts +216 -210
  73. package/src/node/index.ts +38 -38
  74. package/src/node/list-item.ts +139 -140
  75. package/src/node/ordered-list.ts +71 -71
  76. package/src/node/paragraph.ts +55 -53
  77. package/src/node/text.ts +18 -18
  78. package/src/plugin/add-order-in-list.ts +15 -15
  79. package/src/plugin/filter-html.ts +31 -33
  80. package/src/plugin/index.ts +13 -13
  81. package/src/plugin/inline-nodes-cursor.ts +78 -79
  82. package/src/plugin/inline-sync/config.ts +46 -45
  83. package/src/plugin/inline-sync/context.ts +88 -83
  84. package/src/plugin/inline-sync/index.ts +46 -42
  85. package/src/plugin/inline-sync/regexp.ts +2 -2
  86. package/src/plugin/inline-sync/replacer.ts +33 -31
  87. package/src/plugin/inline-sync/utils.ts +53 -55
  88. package/src/supported-keys.ts +22 -21
@@ -1,19 +1,23 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { createCmd, createCmdKey, Ctx, editorViewCtx, getPalette, schemaCtx } from '@milkdown/core';
3
- import { expectDomTypeError } from '@milkdown/exception';
4
- import { cloneTr } from '@milkdown/prose';
5
- import { setBlockType } from '@milkdown/prose/commands';
6
- import { textblockTypeInputRule } from '@milkdown/prose/inputrules';
7
- import { Fragment, Node, NodeType } from '@milkdown/prose/model';
8
- import { EditorState, Plugin, PluginKey, Transaction } from '@milkdown/prose/state';
9
- import { Decoration, DecorationSet } from '@milkdown/prose/view';
10
- import { createNode, createShortcut, ThemeUtils } from '@milkdown/utils';
2
+ import type { Ctx } from '@milkdown/core'
3
+ import { createCmd, createCmdKey, editorViewCtx, getPalette, schemaCtx } from '@milkdown/core'
4
+ import { expectDomTypeError } from '@milkdown/exception'
5
+ import { cloneTr } from '@milkdown/prose'
6
+ import { setBlockType } from '@milkdown/prose/commands'
7
+ import { textblockTypeInputRule } from '@milkdown/prose/inputrules'
8
+ import type { Node, NodeType } from '@milkdown/prose/model'
9
+ import { Fragment } from '@milkdown/prose/model'
10
+ import type { EditorState, Transaction } from '@milkdown/prose/state'
11
+ import { Plugin, PluginKey } from '@milkdown/prose/state'
12
+ import { Decoration, DecorationSet } from '@milkdown/prose/view'
13
+ import type { ThemeUtils } from '@milkdown/utils'
14
+ import { createNode, createShortcut } from '@milkdown/utils'
11
15
 
12
- import { SupportedKeys } from '../supported-keys';
16
+ import { SupportedKeys } from '../supported-keys'
13
17
 
14
18
  const headingIndex = Array(6)
15
- .fill(0)
16
- .map((_, i) => i + 1);
19
+ .fill(0)
20
+ .map((_, i) => i + 1)
17
21
 
18
22
  type Keys =
19
23
  | SupportedKeys['H1']
@@ -22,291 +26,290 @@ type Keys =
22
26
  | SupportedKeys['H4']
23
27
  | SupportedKeys['H5']
24
28
  | SupportedKeys['H6']
25
- | SupportedKeys['DowngradeHeading'];
29
+ | SupportedKeys['DowngradeHeading']
26
30
 
27
- export const TurnIntoHeading = createCmdKey<number>('TurnIntoHeading');
28
- export const DowngradeHeading = createCmdKey('DowngradeHeading');
31
+ export const TurnIntoHeading = createCmdKey<number>('TurnIntoHeading')
32
+ export const DowngradeHeading = createCmdKey('DowngradeHeading')
29
33
 
30
- export const headingIdPluginKey = new PluginKey('MILKDOWN_HEADING_ID');
31
- export const headingHashPluginKey = new PluginKey('MILKDOWN_HEADING_HASH');
34
+ export const headingIdPluginKey = new PluginKey('MILKDOWN_HEADING_ID')
35
+ export const headingHashPluginKey = new PluginKey('MILKDOWN_HEADING_HASH')
32
36
 
33
37
  const createId = (node: Node) =>
34
- node.textContent
35
- .replace(/[\p{P}\p{S}]/gu, '')
36
- .replace(/\s/g, '-')
37
- .toLowerCase()
38
- .trim();
38
+ node.textContent
39
+ .replace(/[\p{P}\p{S}]/gu, '')
40
+ .replace(/\s/g, '-')
41
+ .toLowerCase()
42
+ .trim()
39
43
 
40
44
  const headingIdPlugin = (ctx: Ctx, type: NodeType, getId: (node: Node) => string): Plugin => {
41
- let lock = false;
42
- const walkThrough = (state: EditorState, callback: (tr: Transaction) => void) => {
43
- const tr = state.tr.setMeta('addToHistory', false);
44
- let found = false;
45
- state.doc.descendants((node, pos) => {
46
- if (node.type === type && !lock) {
47
- if (node.textContent.trim().length === 0) {
48
- return;
49
- }
50
- const attrs = node.attrs;
51
- const id = getId(node);
45
+ let lock = false
46
+ const walkThrough = (state: EditorState, callback: (tr: Transaction) => void) => {
47
+ const tr = state.tr.setMeta('addToHistory', false)
48
+ let found = false
49
+ state.doc.descendants((node, pos) => {
50
+ if (node.type === type && !lock) {
51
+ if (node.textContent.trim().length === 0)
52
+ return
52
53
 
53
- if (attrs['id'] !== id) {
54
- found = true;
55
- tr.setMeta(headingIdPluginKey, true).setNodeMarkup(pos, undefined, {
56
- ...attrs,
57
- id,
58
- });
59
- }
60
- }
61
- });
62
- if (found) {
63
- callback(tr);
54
+ const attrs = node.attrs
55
+ const id = getId(node)
56
+
57
+ if (attrs.id !== id) {
58
+ found = true
59
+ tr.setMeta(headingIdPluginKey, true).setNodeMarkup(pos, undefined, {
60
+ ...attrs,
61
+ id,
62
+ })
64
63
  }
65
- };
66
- return new Plugin({
67
- key: headingIdPluginKey,
68
- props: {
69
- handleDOMEvents: {
70
- compositionstart: () => {
71
- lock = true;
72
- return false;
73
- },
74
- compositionend: () => {
75
- lock = false;
76
- const view = ctx.get(editorViewCtx);
77
- setTimeout(() => {
78
- walkThrough(view.state, (tr) => view.dispatch(tr));
79
- }, 0);
80
- return false;
81
- },
82
- },
64
+ }
65
+ })
66
+ if (found)
67
+ callback(tr)
68
+ }
69
+ return new Plugin({
70
+ key: headingIdPluginKey,
71
+ props: {
72
+ handleDOMEvents: {
73
+ compositionstart: () => {
74
+ lock = true
75
+ return false
76
+ },
77
+ compositionend: () => {
78
+ lock = false
79
+ const view = ctx.get(editorViewCtx)
80
+ setTimeout(() => {
81
+ walkThrough(view.state, tr => view.dispatch(tr))
82
+ }, 0)
83
+ return false
83
84
  },
84
- appendTransaction: (transactions, _, nextState) => {
85
- let tr: Transaction | null = null;
85
+ },
86
+ },
87
+ appendTransaction: (transactions, _, nextState) => {
88
+ let tr: Transaction | null = null
86
89
 
87
- if (
88
- transactions.every((transaction) => !transaction.getMeta(headingIdPluginKey)) &&
89
- transactions.some((transaction) => transaction.docChanged)
90
- ) {
91
- walkThrough(nextState, (t) => {
92
- tr = t;
93
- });
94
- }
90
+ if (
91
+ transactions.every(transaction => !transaction.getMeta(headingIdPluginKey))
92
+ && transactions.some(transaction => transaction.docChanged)
93
+ ) {
94
+ walkThrough(nextState, (t) => {
95
+ tr = t
96
+ })
97
+ }
95
98
 
96
- return tr;
97
- },
98
- view: (view) => {
99
- const doc = view.state.doc;
100
- let tr = view.state.tr.setMeta('addToHistory', false);
101
- doc.descendants((node, pos) => {
102
- if (node.type.name === 'heading' && node.attrs['level']) {
103
- if (!node.attrs['id']) {
104
- tr = tr.setNodeMarkup(pos, undefined, {
105
- ...node.attrs,
106
- id: getId(node),
107
- });
108
- }
109
- }
110
- });
111
- view.dispatch(tr);
112
- return {};
113
- },
114
- });
115
- };
99
+ return tr
100
+ },
101
+ view: (view) => {
102
+ const doc = view.state.doc
103
+ let tr = view.state.tr.setMeta('addToHistory', false)
104
+ doc.descendants((node, pos) => {
105
+ if (node.type.name === 'heading' && node.attrs.level) {
106
+ if (!node.attrs.id) {
107
+ tr = tr.setNodeMarkup(pos, undefined, {
108
+ ...node.attrs,
109
+ id: getId(node),
110
+ })
111
+ }
112
+ }
113
+ })
114
+ view.dispatch(tr)
115
+ return {}
116
+ },
117
+ })
118
+ }
116
119
 
117
120
  const headingHashPlugin = (ctx: Ctx, type: NodeType, utils: ThemeUtils): Plugin => {
118
- return new Plugin({
119
- key: headingHashPluginKey,
120
- state: {
121
- init: () => {
122
- return DecorationSet.empty;
123
- },
124
- apply: (tr) => {
125
- const view = ctx.get(editorViewCtx);
126
- if (!view.hasFocus?.() || !view.editable) return DecorationSet.empty;
121
+ return new Plugin({
122
+ key: headingHashPluginKey,
123
+ state: {
124
+ init: () => {
125
+ return DecorationSet.empty
126
+ },
127
+ apply: (tr) => {
128
+ const view = ctx.get(editorViewCtx)
129
+ if (!view.hasFocus?.() || !view.editable)
130
+ return DecorationSet.empty
127
131
 
128
- const { $from } = tr.selection;
129
- const node = $from.node();
130
- if (node.type !== type) {
131
- return DecorationSet.empty;
132
- }
132
+ const { $from } = tr.selection
133
+ const node = $from.node()
134
+ if (node.type !== type)
135
+ return DecorationSet.empty
133
136
 
134
- const level = node.attrs['level'];
135
- const getHashes = (level: number) => {
136
- return Array(level)
137
- .fill(0)
138
- .map((_) => `#`)
139
- .join('');
140
- };
141
- const widget = document.createElement('span');
142
- widget.textContent = getHashes(level);
143
- widget.contentEditable = 'false';
144
- utils.themeManager.onFlush(() => {
145
- const style = utils.getStyle(({ css }) => {
146
- const palette = getPalette(utils.themeManager);
147
- return css`
137
+ const level = node.attrs.level
138
+ const getHashes = (level: number) => {
139
+ return Array(level)
140
+ .fill(0)
141
+ .map(_ => '#')
142
+ .join('')
143
+ }
144
+ const widget = document.createElement('span')
145
+ widget.textContent = getHashes(level)
146
+ widget.contentEditable = 'false'
147
+ utils.themeManager.onFlush(() => {
148
+ const style = utils.getStyle(({ css }) => {
149
+ const palette = getPalette(utils.themeManager)
150
+ return css`
148
151
  margin-right: 4px;
149
152
  color: ${palette('primary')};
150
- `;
151
- });
152
- if (style) {
153
- widget.className = style;
154
- }
155
- });
153
+ `
154
+ })
155
+ if (style)
156
+ widget.className = style
157
+ })
156
158
 
157
- const deco = Decoration.widget($from.before() + 1, widget, { side: -1 });
158
- return DecorationSet.create(tr.doc, [deco]);
159
- },
160
- },
161
- props: {
162
- handleDOMEvents: {
163
- focus: (view) => {
164
- const tr = cloneTr(view.state.tr);
165
- view.dispatch(tr);
166
- return false;
167
- },
168
- },
169
- decorations(this: Plugin, state) {
170
- return this.getState(state);
171
- },
159
+ const deco = Decoration.widget($from.before() + 1, widget, { side: -1 })
160
+ return DecorationSet.create(tr.doc, [deco])
161
+ },
162
+ },
163
+ props: {
164
+ handleDOMEvents: {
165
+ focus: (view) => {
166
+ const tr = cloneTr(view.state.tr)
167
+ view.dispatch(tr)
168
+ return false
172
169
  },
173
- });
174
- };
170
+ },
171
+ decorations(this: Plugin, state) {
172
+ return this.getState(state)
173
+ },
174
+ },
175
+ })
176
+ }
175
177
 
176
178
  export const heading = createNode<Keys, { getId: (node: Node) => string; displayHashtag: boolean }>(
177
- (utils, options) => {
178
- const id = 'heading';
179
+ (utils, options) => {
180
+ const id = 'heading'
179
181
 
180
- const getId = options?.getId ?? createId;
181
- const displayHashtag = options?.displayHashtag ?? true;
182
+ const getId = options?.getId ?? createId
183
+ const displayHashtag = options?.displayHashtag ?? true
182
184
 
183
- return {
184
- id,
185
- schema: () => ({
186
- content: 'inline*',
187
- group: 'block',
188
- defining: true,
189
- attrs: {
190
- id: {
191
- default: '',
192
- },
193
- level: {
194
- default: 1,
195
- },
196
- },
197
- parseDOM: headingIndex.map((x) => ({
198
- tag: `h${x}`,
199
- getAttrs: (node) => {
200
- if (!(node instanceof HTMLElement)) {
201
- throw expectDomTypeError(node);
202
- }
203
- return { level: x, id: node.id };
204
- },
205
- })),
206
- toDOM: (node) => {
207
- return [
208
- `h${node.attrs['level']}`,
185
+ return {
186
+ id,
187
+ schema: () => ({
188
+ content: 'inline*',
189
+ group: 'block',
190
+ defining: true,
191
+ attrs: {
192
+ id: {
193
+ default: '',
194
+ },
195
+ level: {
196
+ default: 1,
197
+ },
198
+ },
199
+ parseDOM: headingIndex.map(x => ({
200
+ tag: `h${x}`,
201
+ getAttrs: (node) => {
202
+ if (!(node instanceof HTMLElement))
203
+ throw expectDomTypeError(node)
204
+
205
+ return { level: x, id: node.id }
206
+ },
207
+ })),
208
+ toDOM: (node) => {
209
+ return [
210
+ `h${node.attrs.level}`,
209
211
  {
210
- id: node.attrs['id'] || getId(node),
211
- class: utils.getClassName(node.attrs, `heading h${node.attrs['level']}`),
212
+ id: node.attrs.id || getId(node),
213
+ class: utils.getClassName(node.attrs, `heading h${node.attrs.level}`),
212
214
  },
213
215
  0,
214
- ];
215
- },
216
- parseMarkdown: {
217
- match: ({ type }) => type === id,
218
- runner: (state, node, type) => {
219
- const depth = node['depth'] as number;
220
- state.openNode(type, { level: depth });
221
- state.next(node.children);
222
- state.closeNode();
223
- },
224
- },
225
- toMarkdown: {
226
- match: (node) => node.type.name === id,
227
- runner: (state, node) => {
228
- state.openNode('heading', undefined, { depth: node.attrs['level'] });
229
- const lastIsHardbreak = node.childCount >= 1 && node.lastChild?.type.name === 'hardbreak';
230
- if (lastIsHardbreak) {
231
- const contentArr: Node[] = [];
232
- node.content.forEach((n, _, i) => {
233
- if (i === node.childCount - 1) {
234
- return;
235
- }
236
- contentArr.push(n);
237
- });
238
- state.next(Fragment.fromArray(contentArr));
239
- } else {
240
- state.next(node.content);
241
- }
242
- state.closeNode();
243
- },
244
- },
245
- }),
246
- inputRules: (type, ctx) =>
247
- headingIndex.map((x) =>
248
- textblockTypeInputRule(new RegExp(`^(#{1,${x}})\\s$`), type, () => {
249
- const view = ctx.get(editorViewCtx);
250
- const { $from } = view.state.selection;
251
- const node = $from.node();
252
- if (node.type.name === 'heading') {
253
- let level = Number(node.attrs['level']) + Number(x);
254
- if (level > 6) {
255
- level = 6;
256
- }
257
- return {
258
- level,
259
- };
260
- }
261
- return {
262
- level: x,
263
- };
264
- }),
265
- ),
266
- commands: (type, ctx) => [
267
- createCmd(TurnIntoHeading, (level = 1) => {
268
- if (level < 1) {
269
- return setBlockType(level === 0 ? ctx.get(schemaCtx).nodes['paragraph'] || type : type);
270
- }
271
- return setBlockType(level === 0 ? ctx.get(schemaCtx).nodes['paragraph'] || type : type, { level });
272
- }),
273
- createCmd(DowngradeHeading, () => {
274
- return (state, dispatch, view) => {
275
- const { $from } = state.selection;
276
- const node = $from.node();
277
- if (node.type !== type || !state.selection.empty || $from.parentOffset !== 0) return false;
216
+ ]
217
+ },
218
+ parseMarkdown: {
219
+ match: ({ type }) => type === id,
220
+ runner: (state, node, type) => {
221
+ const depth = node.depth as number
222
+ state.openNode(type, { level: depth })
223
+ state.next(node.children)
224
+ state.closeNode()
225
+ },
226
+ },
227
+ toMarkdown: {
228
+ match: node => node.type.name === id,
229
+ runner: (state, node) => {
230
+ state.openNode('heading', undefined, { depth: node.attrs.level })
231
+ const lastIsHardbreak = node.childCount >= 1 && node.lastChild?.type.name === 'hardbreak'
232
+ if (lastIsHardbreak) {
233
+ const contentArr: Node[] = []
234
+ node.content.forEach((n, _, i) => {
235
+ if (i === node.childCount - 1)
236
+ return
278
237
 
279
- const level = node.attrs['level'] - 1;
280
- if (!level) {
281
- return setBlockType(ctx.get(schemaCtx).nodes['paragraph'] || type)(state, dispatch, view);
282
- }
238
+ contentArr.push(n)
239
+ })
240
+ state.next(Fragment.fromArray(contentArr))
241
+ }
242
+ else {
243
+ state.next(node.content)
244
+ }
245
+ state.closeNode()
246
+ },
247
+ },
248
+ }),
249
+ inputRules: (type, ctx) =>
250
+ headingIndex.map(x =>
251
+ textblockTypeInputRule(new RegExp(`^(#{1,${x}})\\s$`), type, () => {
252
+ const view = ctx.get(editorViewCtx)
253
+ const { $from } = view.state.selection
254
+ const node = $from.node()
255
+ if (node.type.name === 'heading') {
256
+ let level = Number(node.attrs.level) + Number(x)
257
+ if (level > 6)
258
+ level = 6
283
259
 
284
- dispatch?.(
285
- state.tr.setNodeMarkup(state.selection.$from.before(), undefined, {
286
- ...node.attrs,
287
- level,
288
- }),
289
- );
290
- return true;
291
- };
292
- }),
293
- ],
294
- shortcuts: {
295
- [SupportedKeys.H1]: createShortcut(TurnIntoHeading, 'Mod-Alt-1', 1),
296
- [SupportedKeys.H2]: createShortcut(TurnIntoHeading, 'Mod-Alt-2', 2),
297
- [SupportedKeys.H3]: createShortcut(TurnIntoHeading, 'Mod-Alt-3', 3),
298
- [SupportedKeys.H4]: createShortcut(TurnIntoHeading, 'Mod-Alt-4', 4),
299
- [SupportedKeys.H5]: createShortcut(TurnIntoHeading, 'Mod-Alt-5', 5),
300
- [SupportedKeys.H6]: createShortcut(TurnIntoHeading, 'Mod-Alt-6', 6),
301
- [SupportedKeys.DowngradeHeading]: createShortcut(DowngradeHeading, ['Backspace', 'Delete']),
302
- },
303
- prosePlugins: (type, ctx) => {
304
- const plugins = [headingIdPlugin(ctx, type, getId)];
305
- if (displayHashtag) {
306
- plugins.push(headingHashPlugin(ctx, type, utils));
307
- }
308
- return plugins;
309
- },
310
- };
311
- },
312
- );
260
+ return {
261
+ level,
262
+ }
263
+ }
264
+ return {
265
+ level: x,
266
+ }
267
+ }),
268
+ ),
269
+ commands: (type, ctx) => [
270
+ createCmd(TurnIntoHeading, (level = 1) => {
271
+ if (level < 1)
272
+ return setBlockType(level === 0 ? ctx.get(schemaCtx).nodes.paragraph || type : type)
273
+
274
+ return setBlockType(level === 0 ? ctx.get(schemaCtx).nodes.paragraph || type : type, { level })
275
+ }),
276
+ createCmd(DowngradeHeading, () => {
277
+ return (state, dispatch, view) => {
278
+ const { $from } = state.selection
279
+ const node = $from.node()
280
+ if (node.type !== type || !state.selection.empty || $from.parentOffset !== 0)
281
+ return false
282
+
283
+ const level = node.attrs.level - 1
284
+ if (!level)
285
+ return setBlockType(ctx.get(schemaCtx).nodes.paragraph || type)(state, dispatch, view)
286
+
287
+ dispatch?.(
288
+ state.tr.setNodeMarkup(state.selection.$from.before(), undefined, {
289
+ ...node.attrs,
290
+ level,
291
+ }),
292
+ )
293
+ return true
294
+ }
295
+ }),
296
+ ],
297
+ shortcuts: {
298
+ [SupportedKeys.H1]: createShortcut(TurnIntoHeading, 'Mod-Alt-1', 1),
299
+ [SupportedKeys.H2]: createShortcut(TurnIntoHeading, 'Mod-Alt-2', 2),
300
+ [SupportedKeys.H3]: createShortcut(TurnIntoHeading, 'Mod-Alt-3', 3),
301
+ [SupportedKeys.H4]: createShortcut(TurnIntoHeading, 'Mod-Alt-4', 4),
302
+ [SupportedKeys.H5]: createShortcut(TurnIntoHeading, 'Mod-Alt-5', 5),
303
+ [SupportedKeys.H6]: createShortcut(TurnIntoHeading, 'Mod-Alt-6', 6),
304
+ [SupportedKeys.DowngradeHeading]: createShortcut(DowngradeHeading, ['Backspace', 'Delete']),
305
+ },
306
+ prosePlugins: (type, ctx) => {
307
+ const plugins = [headingIdPlugin(ctx, type, getId)]
308
+ if (displayHashtag)
309
+ plugins.push(headingHashPlugin(ctx, type, utils))
310
+
311
+ return plugins
312
+ },
313
+ }
314
+ },
315
+ )