@milkdown/preset-gfm 6.5.2 → 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 (94) hide show
  1. package/lib/footnote/definition.d.ts +1 -1
  2. package/lib/footnote/definition.d.ts.map +1 -1
  3. package/lib/footnote/index.d.ts.map +1 -1
  4. package/lib/footnote/reference.d.ts +1 -1
  5. package/lib/footnote/reference.d.ts.map +1 -1
  6. package/lib/footnote/utils.d.ts.map +1 -1
  7. package/lib/index.d.ts +1 -1
  8. package/lib/index.d.ts.map +1 -1
  9. package/lib/index.es.js +649 -607
  10. package/lib/index.es.js.map +1 -1
  11. package/lib/strike-through.d.ts +1 -1
  12. package/lib/strike-through.d.ts.map +1 -1
  13. package/lib/supported-keys.d.ts +1 -1
  14. package/lib/supported-keys.d.ts.map +1 -1
  15. package/lib/table/command.d.ts +2 -2
  16. package/lib/table/command.d.ts.map +1 -1
  17. package/lib/table/index.d.ts +1 -1
  18. package/lib/table/index.d.ts.map +1 -1
  19. package/lib/table/nodes/index.d.ts +1 -1
  20. package/lib/table/nodes/index.d.ts.map +1 -1
  21. package/lib/table/operator-plugin/actions.d.ts +5 -5
  22. package/lib/table/operator-plugin/actions.d.ts.map +1 -1
  23. package/lib/table/operator-plugin/calc-pos.d.ts +1 -1
  24. package/lib/table/operator-plugin/calc-pos.d.ts.map +1 -1
  25. package/lib/table/operator-plugin/constant.d.ts.map +1 -1
  26. package/lib/table/operator-plugin/helper.d.ts +3 -3
  27. package/lib/table/operator-plugin/helper.d.ts.map +1 -1
  28. package/lib/table/operator-plugin/index.d.ts +2 -2
  29. package/lib/table/operator-plugin/index.d.ts.map +1 -1
  30. package/lib/table/operator-plugin/style.d.ts +1 -1
  31. package/lib/table/operator-plugin/style.d.ts.map +1 -1
  32. package/lib/table/operator-plugin/widget.d.ts +2 -2
  33. package/lib/table/operator-plugin/widget.d.ts.map +1 -1
  34. package/lib/table/plugin/auto-insert-zero-space.d.ts.map +1 -1
  35. package/lib/table/plugin/cell-selection.d.ts +5 -3
  36. package/lib/table/plugin/cell-selection.d.ts.map +1 -1
  37. package/lib/table/plugin/column-resizing.d.ts +2 -1
  38. package/lib/table/plugin/column-resizing.d.ts.map +1 -1
  39. package/lib/table/plugin/commands.d.ts +2 -2
  40. package/lib/table/plugin/commands.d.ts.map +1 -1
  41. package/lib/table/plugin/copy-paste.d.ts +6 -5
  42. package/lib/table/plugin/copy-paste.d.ts.map +1 -1
  43. package/lib/table/plugin/fix-tables.d.ts +3 -2
  44. package/lib/table/plugin/fix-tables.d.ts.map +1 -1
  45. package/lib/table/plugin/index.d.ts.map +1 -1
  46. package/lib/table/plugin/schema.d.ts +1 -1
  47. package/lib/table/plugin/schema.d.ts.map +1 -1
  48. package/lib/table/plugin/table-editing.d.ts +1 -1
  49. package/lib/table/plugin/table-editing.d.ts.map +1 -1
  50. package/lib/table/plugin/table-map.d.ts +2 -2
  51. package/lib/table/plugin/table-map.d.ts.map +1 -1
  52. package/lib/table/plugin/table-view.d.ts +2 -2
  53. package/lib/table/plugin/table-view.d.ts.map +1 -1
  54. package/lib/table/plugin/types.d.ts +2 -2
  55. package/lib/table/plugin/types.d.ts.map +1 -1
  56. package/lib/table/plugin/util.d.ts +2 -2
  57. package/lib/table/plugin/util.d.ts.map +1 -1
  58. package/lib/table/utils.d.ts +5 -5
  59. package/lib/table/utils.d.ts.map +1 -1
  60. package/lib/task-list-item.d.ts +2 -2
  61. package/lib/task-list-item.d.ts.map +1 -1
  62. package/package.json +17 -17
  63. package/src/footnote/definition.ts +172 -166
  64. package/src/footnote/index.ts +2 -2
  65. package/src/footnote/reference.ts +166 -162
  66. package/src/footnote/utils.ts +2 -2
  67. package/src/index.ts +83 -83
  68. package/src/strike-through.ts +36 -36
  69. package/src/supported-keys.ts +9 -8
  70. package/src/table/command.ts +17 -16
  71. package/src/table/index.ts +9 -9
  72. package/src/table/nodes/index.ts +177 -174
  73. package/src/table/operator-plugin/actions.ts +103 -102
  74. package/src/table/operator-plugin/calc-pos.ts +31 -34
  75. package/src/table/operator-plugin/constant.ts +3 -3
  76. package/src/table/operator-plugin/helper.ts +31 -32
  77. package/src/table/operator-plugin/index.ts +104 -95
  78. package/src/table/operator-plugin/style.ts +10 -9
  79. package/src/table/operator-plugin/widget.ts +47 -45
  80. package/src/table/plugin/auto-insert-zero-space.ts +41 -41
  81. package/src/table/plugin/cell-selection.ts +325 -296
  82. package/src/table/plugin/column-resizing.ts +226 -198
  83. package/src/table/plugin/commands.ts +464 -421
  84. package/src/table/plugin/copy-paste.ts +256 -240
  85. package/src/table/plugin/fix-tables.ts +103 -88
  86. package/src/table/plugin/index.ts +3 -3
  87. package/src/table/plugin/schema.ts +100 -94
  88. package/src/table/plugin/table-editing.ts +324 -230
  89. package/src/table/plugin/table-map.ts +294 -229
  90. package/src/table/plugin/table-view.ts +66 -62
  91. package/src/table/plugin/types.ts +8 -8
  92. package/src/table/plugin/util.ts +78 -66
  93. package/src/table/utils.ts +141 -138
  94. package/src/task-list-item.ts +151 -146
@@ -1,162 +1,165 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { cloneTr, findParentNode } from '@milkdown/prose';
3
- import { Node as ProsemirrorNode, Schema } from '@milkdown/prose/model';
4
- import { Selection, Transaction } from '@milkdown/prose/state';
5
-
6
- import { CellSelection } from './plugin/cell-selection';
7
- import { tableNodeTypes } from './plugin/schema';
8
- import { Rect, TableMap } from './plugin/table-map';
9
-
10
- export type CellPos = {
11
- pos: number;
12
- start: number;
13
- node: ProsemirrorNode;
14
- };
2
+ import { cloneTr, findParentNode } from '@milkdown/prose'
3
+ import type { Node as ProsemirrorNode, Schema } from '@milkdown/prose/model'
4
+ import type { Selection, Transaction } from '@milkdown/prose/state'
5
+
6
+ import { CellSelection } from './plugin/cell-selection'
7
+ import { tableNodeTypes } from './plugin/schema'
8
+ import type { Rect } from './plugin/table-map'
9
+ import { TableMap } from './plugin/table-map'
10
+
11
+ export interface CellPos {
12
+ pos: number
13
+ start: number
14
+ node: ProsemirrorNode
15
+ }
15
16
 
16
17
  export const findTable = (selection: Selection) =>
17
- findParentNode((node) => node.type.spec['tableRole'] === 'table')(selection);
18
-
19
- export const getCellsInColumn =
20
- (columnIndex: number) =>
21
- (selection: Selection): CellPos[] | undefined => {
22
- const table = findTable(selection);
23
- if (!table) return undefined;
24
- const map = TableMap.get(table.node);
25
- if (columnIndex < 0 || columnIndex >= map.width) {
26
- return undefined;
27
- }
18
+ findParentNode(node => node.type.spec.tableRole === 'table')(selection)
19
+
20
+ export const getCellsInColumn
21
+ = (columnIndex: number) =>
22
+ (selection: Selection): CellPos[] | undefined => {
23
+ const table = findTable(selection)
24
+ if (!table)
25
+ return undefined
26
+ const map = TableMap.get(table.node)
27
+ if (columnIndex < 0 || columnIndex >= map.width)
28
+ return undefined
28
29
 
29
30
  return map
30
- .cellsInRect({ left: columnIndex, right: columnIndex + 1, top: 0, bottom: map.height })
31
- .map((pos) => {
32
- const node = table.node.nodeAt(pos);
33
- if (!node) return;
34
- const start = pos + table.start;
35
- return {
36
- pos: start,
37
- start: start + 1,
38
- node,
39
- };
40
- })
41
- .filter((x): x is CellPos => x != null);
42
- };
43
-
44
- export const getCellsInRow =
45
- (rowIndex: number) =>
46
- (selection: Selection): CellPos[] | undefined => {
47
- const table = findTable(selection);
48
- if (!table) return undefined;
49
- const map = TableMap.get(table.node);
50
- if (rowIndex < 0 || rowIndex >= map.height) {
51
- return undefined;
52
- }
31
+ .cellsInRect({ left: columnIndex, right: columnIndex + 1, top: 0, bottom: map.height })
32
+ .map((pos) => {
33
+ const node = table.node.nodeAt(pos)
34
+ if (!node)
35
+ return undefined
36
+ const start = pos + table.start
37
+ return {
38
+ pos: start,
39
+ start: start + 1,
40
+ node,
41
+ }
42
+ })
43
+ .filter((x): x is CellPos => x != null)
44
+ }
45
+
46
+ export const getCellsInRow
47
+ = (rowIndex: number) =>
48
+ (selection: Selection): CellPos[] | undefined => {
49
+ const table = findTable(selection)
50
+ if (!table)
51
+ return undefined
52
+ const map = TableMap.get(table.node)
53
+ if (rowIndex < 0 || rowIndex >= map.height)
54
+ return undefined
53
55
 
54
56
  return map
55
- .cellsInRect({ left: 0, right: map.width, top: rowIndex, bottom: rowIndex + 1 })
56
- .map((pos) => {
57
- const node = table.node.nodeAt(pos);
58
- if (!node) return;
59
- const start = pos + table.start;
60
- return {
61
- pos: start,
62
- start: start + 1,
63
- node,
64
- };
65
- })
66
- .filter((x): x is CellPos => x != null);
67
- };
57
+ .cellsInRect({ left: 0, right: map.width, top: rowIndex, bottom: rowIndex + 1 })
58
+ .map((pos) => {
59
+ const node = table.node.nodeAt(pos)
60
+ if (!node)
61
+ return undefined
62
+ const start = pos + table.start
63
+ return {
64
+ pos: start,
65
+ start: start + 1,
66
+ node,
67
+ }
68
+ })
69
+ .filter((x): x is CellPos => x != null)
70
+ }
68
71
 
69
72
  export const createTable = (schema: Schema, rowsCount = 3, colsCount = 3) => {
70
- const { cell: tableCell, header_cell: tableHeader, row: tableRow, table } = tableNodeTypes(schema);
73
+ const { cell: tableCell, header_cell: tableHeader, row: tableRow, table } = tableNodeTypes(schema)
71
74
 
72
- const cells = Array(colsCount)
73
- .fill(0)
74
- .map(() => tableCell.createAndFill(null) as ProsemirrorNode);
75
+ const cells = Array(colsCount)
76
+ .fill(0)
77
+ .map(() => tableCell.createAndFill(null) as ProsemirrorNode)
75
78
 
76
- const headerCells = Array(colsCount)
77
- .fill(0)
78
- .map(() => tableHeader.createAndFill(null) as ProsemirrorNode);
79
+ const headerCells = Array(colsCount)
80
+ .fill(0)
81
+ .map(() => tableHeader.createAndFill(null) as ProsemirrorNode)
79
82
 
80
- const rows = Array(rowsCount)
81
- .fill(0)
82
- .map((_, i) => tableRow.create(null, i === 0 ? headerCells : cells));
83
+ const rows = Array(rowsCount)
84
+ .fill(0)
85
+ .map((_, i) => tableRow.create(null, i === 0 ? headerCells : cells))
83
86
 
84
- return table.create(null, rows);
85
- };
87
+ return table.create(null, rows)
88
+ }
86
89
 
87
90
  export const selectLine = (type: 'row' | 'col') => (index: number) => (tr: Transaction) => {
88
- const table = findTable(tr.selection);
89
- const isRowSelection = type === 'row';
90
- if (table) {
91
- const map = TableMap.get(table.node);
92
-
93
- // Check if the index is valid
94
- if (index >= 0 && index < (isRowSelection ? map.height : map.width)) {
95
- const lastCell = map.positionAt(
96
- isRowSelection ? index : map.height - 1,
97
- isRowSelection ? map.width - 1 : index,
98
- table.node,
99
- );
100
- const $lastCell = tr.doc.resolve(table.start + lastCell);
101
-
102
- const createCellSelection = isRowSelection ? CellSelection.rowSelection : CellSelection.colSelection;
103
-
104
- const firstCell = map.positionAt(isRowSelection ? index : 0, isRowSelection ? 0 : index, table.node);
105
- const $firstCell = tr.doc.resolve(table.start + firstCell);
106
- return cloneTr(tr.setSelection(createCellSelection($lastCell, $firstCell) as unknown as Selection));
107
- }
91
+ const table = findTable(tr.selection)
92
+ const isRowSelection = type === 'row'
93
+ if (table) {
94
+ const map = TableMap.get(table.node)
95
+
96
+ // Check if the index is valid
97
+ if (index >= 0 && index < (isRowSelection ? map.height : map.width)) {
98
+ const lastCell = map.positionAt(
99
+ isRowSelection ? index : map.height - 1,
100
+ isRowSelection ? map.width - 1 : index,
101
+ table.node,
102
+ )
103
+ const $lastCell = tr.doc.resolve(table.start + lastCell)
104
+
105
+ const createCellSelection = isRowSelection ? CellSelection.rowSelection : CellSelection.colSelection
106
+
107
+ const firstCell = map.positionAt(isRowSelection ? index : 0, isRowSelection ? 0 : index, table.node)
108
+ const $firstCell = tr.doc.resolve(table.start + firstCell)
109
+ return cloneTr(tr.setSelection(createCellSelection($lastCell, $firstCell) as unknown as Selection))
108
110
  }
109
- return tr;
110
- };
111
+ }
112
+ return tr
113
+ }
111
114
 
112
115
  export const getCellsInTable = (selection: Selection) => {
113
- const table = findTable(selection);
114
- if (!table) {
115
- return;
116
- }
117
- const map = TableMap.get(table.node);
118
- const cells = map.cellsInRect({
119
- left: 0,
120
- right: map.width,
121
- top: 0,
122
- bottom: map.height,
123
- });
124
- return cells.map((nodePos) => {
125
- const node = table.node.nodeAt(nodePos);
126
- const pos = nodePos + table.start;
127
- return { pos, start: pos + 1, node };
128
- });
129
- };
116
+ const table = findTable(selection)
117
+ if (!table)
118
+ return
119
+
120
+ const map = TableMap.get(table.node)
121
+ const cells = map.cellsInRect({
122
+ left: 0,
123
+ right: map.width,
124
+ top: 0,
125
+ bottom: map.height,
126
+ })
127
+ return cells.map((nodePos) => {
128
+ const node = table.node.nodeAt(nodePos)
129
+ const pos = nodePos + table.start
130
+ return { pos, start: pos + 1, node }
131
+ })
132
+ }
130
133
 
131
134
  export const selectTable = (tr: Transaction) => {
132
- const cells = getCellsInTable(tr.selection);
133
- if (cells && cells[0]) {
134
- const $firstCell = tr.doc.resolve(cells[0].pos);
135
- const last = cells[cells.length - 1];
136
- if (last) {
137
- const $lastCell = tr.doc.resolve(last.pos);
138
- return cloneTr(tr.setSelection(new CellSelection($lastCell, $firstCell) as unknown as Selection));
139
- }
135
+ const cells = getCellsInTable(tr.selection)
136
+ if (cells && cells[0]) {
137
+ const $firstCell = tr.doc.resolve(cells[0].pos)
138
+ const last = cells[cells.length - 1]
139
+ if (last) {
140
+ const $lastCell = tr.doc.resolve(last.pos)
141
+ return cloneTr(tr.setSelection(new CellSelection($lastCell, $firstCell) as unknown as Selection))
140
142
  }
141
- return tr;
142
- };
143
+ }
144
+ return tr
145
+ }
143
146
 
144
147
  export function addRowWithAlignment(tr: Transaction, { map, tableStart, table }: Required<Rect>, row: number) {
145
- const rowPos = Array(row)
146
- .fill(0)
147
- .reduce((acc, _, i) => {
148
- return acc + table.child(i).nodeSize;
149
- }, tableStart);
150
-
151
- const { cell: cellType, row: rowType } = tableNodeTypes(table.type.schema);
152
-
153
- const cells = Array(map.width)
154
- .fill(0)
155
- .map((_, col) => {
156
- const headerCol = table.nodeAt(map.map[col] as number);
157
- return cellType.createAndFill({ alignment: headerCol?.attrs['alignment'] }) as ProsemirrorNode;
158
- });
159
-
160
- tr.insert(rowPos, rowType.create(null, cells));
161
- return tr;
148
+ const rowPos = Array(row)
149
+ .fill(0)
150
+ .reduce((acc, _, i) => {
151
+ return acc + table.child(i).nodeSize
152
+ }, tableStart)
153
+
154
+ const { cell: cellType, row: rowType } = tableNodeTypes(table.type.schema)
155
+
156
+ const cells = Array(map.width)
157
+ .fill(0)
158
+ .map((_, col) => {
159
+ const headerCol = table.nodeAt(map.map[col] as number)
160
+ return cellType.createAndFill({ alignment: headerCol?.attrs.alignment }) as ProsemirrorNode
161
+ })
162
+
163
+ tr.insert(rowPos, rowType.create(null, cells))
164
+ return tr
162
165
  }
@@ -1,154 +1,159 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { createCmd, createCmdKey, editorViewCtx, ThemeTaskListItemType } from '@milkdown/core';
3
- import { expectDomTypeError } from '@milkdown/exception';
4
- import { wrapIn } from '@milkdown/prose/commands';
5
- import { wrappingInputRule } from '@milkdown/prose/inputrules';
6
- import { liftListItem, sinkListItem, splitListItem } from '@milkdown/prose/schema-list';
7
- import { NodeView } from '@milkdown/prose/view';
8
- import { createNode, createShortcut } from '@milkdown/utils';
2
+ import type { ThemeTaskListItemType } from '@milkdown/core'
3
+ import { createCmd, createCmdKey, editorViewCtx } from '@milkdown/core'
4
+ import { expectDomTypeError } from '@milkdown/exception'
5
+ import { wrapIn } from '@milkdown/prose/commands'
6
+ import { wrappingInputRule } from '@milkdown/prose/inputrules'
7
+ import { liftListItem, sinkListItem, splitListItem } from '@milkdown/prose/schema-list'
8
+ import type { NodeView } from '@milkdown/prose/view'
9
+ import { createNode, createShortcut } from '@milkdown/utils'
9
10
 
10
- import { SupportedKeys } from './supported-keys';
11
+ import { SupportedKeys } from './supported-keys'
11
12
 
12
- type Keys = Extract<keyof SupportedKeys, 'SinkListItem' | 'LiftListItem' | 'NextListItem' | 'TaskList'>;
13
+ type Keys = Extract<keyof SupportedKeys, 'SinkListItem' | 'LiftListItem' | 'NextListItem' | 'TaskList'>
13
14
 
14
- export const SplitTaskListItem = createCmdKey('SplitTaskListItem');
15
- export const SinkTaskListItem = createCmdKey('SinkTaskListItem');
16
- export const LiftTaskListItem = createCmdKey('LiftTaskListItem');
17
- export const TurnIntoTaskList = createCmdKey('TurnIntoTaskList');
15
+ export const SplitTaskListItem = createCmdKey('SplitTaskListItem')
16
+ export const SinkTaskListItem = createCmdKey('SinkTaskListItem')
17
+ export const LiftTaskListItem = createCmdKey('LiftTaskListItem')
18
+ export const TurnIntoTaskList = createCmdKey('TurnIntoTaskList')
18
19
 
19
20
  export const taskListItem = createNode<Keys>((utils) => {
20
- const id = 'task_list_item';
21
-
22
- return {
23
- id,
24
- schema: (ctx) => ({
25
- group: 'listItem',
26
- content: 'paragraph block*',
27
- defining: true,
28
- priority: 60,
29
- attrs: {
30
- checked: {
31
- default: false,
32
- },
33
- },
34
- parseDOM: [
35
- {
36
- tag: 'li[data-type="task-item"]',
37
- getAttrs: (dom) => {
38
- if (!(dom instanceof HTMLElement)) {
39
- throw expectDomTypeError(dom);
40
- }
41
- return { checked: dom.dataset['checked'] === 'true' };
42
- },
43
- },
44
- ],
45
- toDOM: (node) => {
46
- const checkbox = document.createElement('input');
47
- checkbox.type = 'checkbox';
48
- checkbox.checked = node.attrs['checked'];
49
- checkbox.className = utils.getClassName(node.attrs, 'task-list-item_checkbox');
50
- checkbox.onchange = (event) => {
51
- const target = event.target;
52
- if (!(target instanceof HTMLInputElement)) return;
53
- const view = ctx.get(editorViewCtx);
54
-
55
- if (!view.editable) {
56
- checkbox.checked = !checkbox.checked;
57
-
58
- return;
59
- }
60
-
61
- const { top, left } = target.getBoundingClientRect();
62
- const result = view.posAtCoords({ top, left });
63
- if (!result) return;
64
-
65
- const { tr } = view.state;
66
-
67
- view.dispatch(
68
- tr.setNodeMarkup(result.inside, undefined, {
69
- checked: target.checked,
70
- }),
71
- );
72
- };
73
- return [
74
- 'li',
75
- {
76
- 'data-type': 'task-item',
77
- 'data-checked': node.attrs['checked'] ? 'true' : 'false',
78
- class: utils.getClassName(node.attrs, 'task-list-item'),
79
- },
80
- checkbox,
81
- ['span', { class: utils.getClassName(node.attrs, 'task-list-item_body') }, 0],
82
- ];
83
- },
84
- parseMarkdown: {
85
- match: ({ type, checked }) => {
86
- return type === 'listItem' && checked !== null;
87
- },
88
- runner: (state, node, type) => {
89
- state.openNode(type, { checked: node['checked'] as boolean });
90
- state.next(node.children);
91
- state.closeNode();
92
- },
93
- },
94
- toMarkdown: {
95
- match: (node) => node.type.name === id,
96
- runner: (state, node) => {
97
- state.openNode('listItem', undefined, { checked: node.attrs['checked'] });
98
- state.next(node.content);
99
- state.closeNode();
100
- },
101
- },
102
- }),
103
- inputRules: (nodeType) => [
104
- wrappingInputRule(/^\s*(\[([ |x])\])\s$/, nodeType, (match) => ({
105
- checked: match[match.length - 1] === 'x',
106
- })),
107
- ],
108
- commands: (nodeType) => [
109
- createCmd(SplitTaskListItem, () => splitListItem(nodeType)),
110
- createCmd(SinkTaskListItem, () => sinkListItem(nodeType)),
111
- createCmd(LiftTaskListItem, () => liftListItem(nodeType)),
112
- createCmd(TurnIntoTaskList, () => wrapIn(nodeType)),
113
- ],
114
- shortcuts: {
115
- [SupportedKeys.NextListItem]: createShortcut(SplitTaskListItem, 'Enter'),
116
- [SupportedKeys.SinkListItem]: createShortcut(SinkTaskListItem, 'Mod-]'),
117
- [SupportedKeys.LiftListItem]: createShortcut(LiftTaskListItem, 'Mod-['),
118
- [SupportedKeys.TaskList]: createShortcut(TurnIntoTaskList, 'Mod-Alt-9'),
21
+ const id = 'task_list_item'
22
+
23
+ return {
24
+ id,
25
+ schema: ctx => ({
26
+ group: 'listItem',
27
+ content: 'paragraph block*',
28
+ defining: true,
29
+ priority: 60,
30
+ attrs: {
31
+ checked: {
32
+ default: false,
119
33
  },
120
- view: () => (node, view, getPos) => {
121
- let currNode = node;
122
-
123
- const renderer = utils.themeManager.get<ThemeTaskListItemType>('task-list-item', {
124
- editable: () => view.editable,
125
- onChange: (selected) => {
126
- const { tr } = view.state;
127
- view.dispatch(
128
- tr.setNodeMarkup(getPos(), undefined, {
129
- checked: selected,
130
- }),
131
- );
132
- },
133
- });
134
-
135
- if (!renderer) return {} as NodeView;
136
-
137
- const { dom, contentDOM, onUpdate } = renderer;
138
- onUpdate(currNode);
139
-
140
- return {
141
- dom,
142
- contentDOM,
143
- update: (updatedNode) => {
144
- if (updatedNode.type.name !== id) return false;
145
-
146
- currNode = updatedNode;
147
- onUpdate(currNode);
148
-
149
- return true;
150
- },
151
- };
34
+ },
35
+ parseDOM: [
36
+ {
37
+ tag: 'li[data-type="task-item"]',
38
+ getAttrs: (dom) => {
39
+ if (!(dom instanceof HTMLElement))
40
+ throw expectDomTypeError(dom)
41
+
42
+ return { checked: dom.dataset.checked === 'true' }
43
+ },
152
44
  },
153
- };
154
- });
45
+ ],
46
+ toDOM: (node) => {
47
+ const checkbox = document.createElement('input')
48
+ checkbox.type = 'checkbox'
49
+ checkbox.checked = node.attrs.checked
50
+ checkbox.className = utils.getClassName(node.attrs, 'task-list-item_checkbox')
51
+ checkbox.onchange = (event) => {
52
+ const target = event.target
53
+ if (!(target instanceof HTMLInputElement))
54
+ return
55
+ const view = ctx.get(editorViewCtx)
56
+
57
+ if (!view.editable) {
58
+ checkbox.checked = !checkbox.checked
59
+
60
+ return
61
+ }
62
+
63
+ const { top, left } = target.getBoundingClientRect()
64
+ const result = view.posAtCoords({ top, left })
65
+ if (!result)
66
+ return
67
+
68
+ const { tr } = view.state
69
+
70
+ view.dispatch(
71
+ tr.setNodeMarkup(result.inside, undefined, {
72
+ checked: target.checked,
73
+ }),
74
+ )
75
+ }
76
+ return [
77
+ 'li',
78
+ {
79
+ 'data-type': 'task-item',
80
+ 'data-checked': node.attrs.checked ? 'true' : 'false',
81
+ 'class': utils.getClassName(node.attrs, 'task-list-item'),
82
+ },
83
+ checkbox,
84
+ ['span', { class: utils.getClassName(node.attrs, 'task-list-item_body') }, 0],
85
+ ]
86
+ },
87
+ parseMarkdown: {
88
+ match: ({ type, checked }) => {
89
+ return type === 'listItem' && checked !== null
90
+ },
91
+ runner: (state, node, type) => {
92
+ state.openNode(type, { checked: node.checked as boolean })
93
+ state.next(node.children)
94
+ state.closeNode()
95
+ },
96
+ },
97
+ toMarkdown: {
98
+ match: node => node.type.name === id,
99
+ runner: (state, node) => {
100
+ state.openNode('listItem', undefined, { checked: node.attrs.checked })
101
+ state.next(node.content)
102
+ state.closeNode()
103
+ },
104
+ },
105
+ }),
106
+ inputRules: nodeType => [
107
+ wrappingInputRule(/^\s*(\[([ |x])\])\s$/, nodeType, match => ({
108
+ checked: match[match.length - 1] === 'x',
109
+ })),
110
+ ],
111
+ commands: nodeType => [
112
+ createCmd(SplitTaskListItem, () => splitListItem(nodeType)),
113
+ createCmd(SinkTaskListItem, () => sinkListItem(nodeType)),
114
+ createCmd(LiftTaskListItem, () => liftListItem(nodeType)),
115
+ createCmd(TurnIntoTaskList, () => wrapIn(nodeType)),
116
+ ],
117
+ shortcuts: {
118
+ [SupportedKeys.NextListItem]: createShortcut(SplitTaskListItem, 'Enter'),
119
+ [SupportedKeys.SinkListItem]: createShortcut(SinkTaskListItem, 'Mod-]'),
120
+ [SupportedKeys.LiftListItem]: createShortcut(LiftTaskListItem, 'Mod-['),
121
+ [SupportedKeys.TaskList]: createShortcut(TurnIntoTaskList, 'Mod-Alt-9'),
122
+ },
123
+ view: () => (node, view, getPos) => {
124
+ let currNode = node
125
+
126
+ const renderer = utils.themeManager.get<ThemeTaskListItemType>('task-list-item', {
127
+ editable: () => view.editable,
128
+ onChange: (selected) => {
129
+ const { tr } = view.state
130
+ view.dispatch(
131
+ tr.setNodeMarkup(getPos(), undefined, {
132
+ checked: selected,
133
+ }),
134
+ )
135
+ },
136
+ })
137
+
138
+ if (!renderer)
139
+ return {} as NodeView
140
+
141
+ const { dom, contentDOM, onUpdate } = renderer
142
+ onUpdate(currNode)
143
+
144
+ return {
145
+ dom,
146
+ contentDOM,
147
+ update: (updatedNode) => {
148
+ if (updatedNode.type.name !== id)
149
+ return false
150
+
151
+ currNode = updatedNode
152
+ onUpdate(currNode)
153
+
154
+ return true
155
+ },
156
+ }
157
+ },
158
+ }
159
+ })