@kerebron/extension-tables 0.4.28 → 0.4.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/ExtensionTables.js +1 -0
- package/esm/ExtensionTables.js.map +1 -0
- package/esm/NodeTable.js +1 -0
- package/esm/NodeTable.js.map +1 -0
- package/esm/NodeTableCell.js +1 -0
- package/esm/NodeTableCell.js.map +1 -0
- package/esm/NodeTableHeader.js +1 -0
- package/esm/NodeTableHeader.js.map +1 -0
- package/esm/NodeTableRow.js +1 -0
- package/esm/NodeTableRow.js.map +1 -0
- package/esm/_dnt.shims.js +1 -0
- package/esm/_dnt.shims.js.map +1 -0
- package/esm/utilities/CellSelection.js +1 -0
- package/esm/utilities/CellSelection.js.map +1 -0
- package/esm/utilities/TableMap.js +1 -0
- package/esm/utilities/TableMap.js.map +1 -0
- package/esm/utilities/TableView.js +1 -0
- package/esm/utilities/TableView.js.map +1 -0
- package/esm/utilities/columnResizing.js +1 -0
- package/esm/utilities/columnResizing.js.map +1 -0
- package/esm/utilities/commands.js +1 -0
- package/esm/utilities/commands.js.map +1 -0
- package/esm/utilities/copypaste.js +1 -0
- package/esm/utilities/copypaste.js.map +1 -0
- package/esm/utilities/createCell.js +1 -0
- package/esm/utilities/createCell.js.map +1 -0
- package/esm/utilities/createTable.js +1 -0
- package/esm/utilities/createTable.js.map +1 -0
- package/esm/utilities/fixTables.js +1 -0
- package/esm/utilities/fixTables.js.map +1 -0
- package/esm/utilities/getTableNodeTypes.js +1 -0
- package/esm/utilities/getTableNodeTypes.js.map +1 -0
- package/esm/utilities/input.js +1 -0
- package/esm/utilities/input.js.map +1 -0
- package/esm/utilities/tableEditing.js +1 -0
- package/esm/utilities/tableEditing.js.map +1 -0
- package/esm/utilities/tableNodeTypes.js +1 -0
- package/esm/utilities/tableNodeTypes.js.map +1 -0
- package/esm/utilities/util.js +1 -0
- package/esm/utilities/util.js.map +1 -0
- package/package.json +6 -2
- package/src/ExtensionTables.ts +16 -0
- package/src/NodeTable.ts +139 -0
- package/src/NodeTableCell.ts +70 -0
- package/src/NodeTableHeader.ts +49 -0
- package/src/NodeTableRow.ts +41 -0
- package/src/_dnt.shims.ts +60 -0
- package/src/utilities/CellSelection.ts +477 -0
- package/src/utilities/TableMap.ts +392 -0
- package/src/utilities/TableView.ts +102 -0
- package/src/utilities/columnResizing.ts +437 -0
- package/src/utilities/commands.ts +896 -0
- package/src/utilities/copypaste.ts +394 -0
- package/src/utilities/createCell.ts +12 -0
- package/src/utilities/createTable.ts +53 -0
- package/src/utilities/fixTables.ts +156 -0
- package/src/utilities/getTableNodeTypes.ts +21 -0
- package/src/utilities/input.ts +299 -0
- package/src/utilities/tableEditing.ts +90 -0
- package/src/utilities/tableNodeTypes.ts +32 -0
- package/src/utilities/util.ts +204 -0
- package/assets/tables.css +0 -85
package/src/NodeTable.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { TextSelection } from 'prosemirror-state';
|
|
2
|
+
import { NodeSpec, NodeType } from 'prosemirror-model';
|
|
3
|
+
import { Node as ProseMirrorNode } from 'prosemirror-model';
|
|
4
|
+
|
|
5
|
+
import { type CoreEditor, Node } from '@kerebron/editor';
|
|
6
|
+
import {
|
|
7
|
+
type CommandFactories,
|
|
8
|
+
type CommandShortcuts,
|
|
9
|
+
} from '@kerebron/editor/commands';
|
|
10
|
+
import { type InputRule } from '@kerebron/editor/plugins/input-rules';
|
|
11
|
+
import {
|
|
12
|
+
getHtmlAttributes,
|
|
13
|
+
setHtmlAttributes,
|
|
14
|
+
} from '@kerebron/editor/utilities';
|
|
15
|
+
|
|
16
|
+
import { createTable } from './utilities/createTable.js';
|
|
17
|
+
import { CellSelection } from './utilities/CellSelection.js';
|
|
18
|
+
import { columnResizing } from './utilities/columnResizing.js';
|
|
19
|
+
import { tableEditing } from './utilities/tableEditing.js';
|
|
20
|
+
import {
|
|
21
|
+
addColumnAfter,
|
|
22
|
+
addColumnBefore,
|
|
23
|
+
addRowAfter,
|
|
24
|
+
addRowBefore,
|
|
25
|
+
deleteColumn,
|
|
26
|
+
deleteRow,
|
|
27
|
+
deleteTable,
|
|
28
|
+
goToNextCell,
|
|
29
|
+
mergeCells,
|
|
30
|
+
setCellAttr,
|
|
31
|
+
splitCell,
|
|
32
|
+
toggleHeader,
|
|
33
|
+
toggleHeaderCell,
|
|
34
|
+
toggleHeaderColumn,
|
|
35
|
+
toggleHeaderRow,
|
|
36
|
+
} from './utilities/commands.js';
|
|
37
|
+
import { Plugin } from 'prosemirror-state';
|
|
38
|
+
import { Direction } from './utilities/input.js';
|
|
39
|
+
|
|
40
|
+
export class NodeTable extends Node {
|
|
41
|
+
override name = 'table';
|
|
42
|
+
requires = ['doc'];
|
|
43
|
+
|
|
44
|
+
override attributes = {
|
|
45
|
+
class: {
|
|
46
|
+
default: 'table',
|
|
47
|
+
fromDom(element: HTMLElement) {
|
|
48
|
+
return element.hasAttribute('class')
|
|
49
|
+
? element.getAttribute('class')!
|
|
50
|
+
: undefined;
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
override getNodeSpec(): NodeSpec {
|
|
56
|
+
return {
|
|
57
|
+
content: 'table_row+',
|
|
58
|
+
tableRole: 'table',
|
|
59
|
+
isolating: true,
|
|
60
|
+
group: 'block',
|
|
61
|
+
parseDOM: [{
|
|
62
|
+
tag: 'table',
|
|
63
|
+
getAttrs: (element) => setHtmlAttributes(this, element),
|
|
64
|
+
}],
|
|
65
|
+
toDOM: (
|
|
66
|
+
node: ProseMirrorNode,
|
|
67
|
+
) => ['table', getHtmlAttributes(this, node), ['tbody', 0]],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
override getCommandFactories(
|
|
72
|
+
editor: CoreEditor,
|
|
73
|
+
type: NodeType,
|
|
74
|
+
): Partial<CommandFactories> {
|
|
75
|
+
const commands: Partial<CommandFactories> = {
|
|
76
|
+
addColumnAfter: () => (state, dispatch) =>
|
|
77
|
+
addColumnAfter(state, dispatch),
|
|
78
|
+
addColumnBefore: () => (state, dispatch) =>
|
|
79
|
+
addColumnBefore(state, dispatch),
|
|
80
|
+
addRowAfter: () => (state, dispatch) => addRowAfter(state, dispatch),
|
|
81
|
+
addRowBefore: () => (state, dispatch) => addRowBefore(state, dispatch),
|
|
82
|
+
deleteColumn: () => (state, dispatch) => deleteColumn(state, dispatch),
|
|
83
|
+
deleteRow: () => (state, dispatch) => deleteRow(state, dispatch),
|
|
84
|
+
deleteTable: () => (state, dispatch) => deleteTable(state, dispatch),
|
|
85
|
+
goToNextCell: (direction: Direction) => goToNextCell(direction),
|
|
86
|
+
mergeCells: () => (state, dispatch) => mergeCells(state, dispatch),
|
|
87
|
+
setCellAttr: (...args) => setCellAttr(...args),
|
|
88
|
+
splitCell: () => (state, dispatch) => splitCell(state, dispatch),
|
|
89
|
+
toggleHeader: (...args) => toggleHeader(...args),
|
|
90
|
+
toggleHeaderCell: () => (state, dispatch) =>
|
|
91
|
+
toggleHeaderCell(state, dispatch),
|
|
92
|
+
toggleHeaderRow: () => (state, dispatch) =>
|
|
93
|
+
toggleHeaderRow(state, dispatch),
|
|
94
|
+
toggleHeaderColumn: () => (state, dispatch) =>
|
|
95
|
+
toggleHeaderColumn(state, dispatch),
|
|
96
|
+
insertTable:
|
|
97
|
+
({ rows = 3, cols = 3, withHeaderRow = true } = {}) =>
|
|
98
|
+
(state, dispatch) => {
|
|
99
|
+
const tr = state.tr;
|
|
100
|
+
const node = createTable(editor.schema, rows, cols, withHeaderRow);
|
|
101
|
+
|
|
102
|
+
if (dispatch) {
|
|
103
|
+
const offset = tr.selection.from + 1;
|
|
104
|
+
|
|
105
|
+
tr.replaceSelectionWith(node)
|
|
106
|
+
.scrollIntoView()
|
|
107
|
+
.setSelection(TextSelection.near(tr.doc.resolve(offset)));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return true;
|
|
111
|
+
},
|
|
112
|
+
setCellSelection: (position) => (state, dispatch) => {
|
|
113
|
+
if (dispatch) {
|
|
114
|
+
const selection = CellSelection.create(
|
|
115
|
+
state.doc,
|
|
116
|
+
position.anchorCell,
|
|
117
|
+
position.headCell,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
state.tr.setSelection(selection);
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
return commands;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
override getKeyboardShortcuts(): Partial<CommandShortcuts> {
|
|
129
|
+
const keys = {};
|
|
130
|
+
return keys;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
override getProseMirrorPlugins(): Plugin[] {
|
|
134
|
+
return [
|
|
135
|
+
columnResizing(),
|
|
136
|
+
tableEditing(),
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Attrs, Node as PmNode, NodeSpec, NodeType } from 'prosemirror-model';
|
|
2
|
+
|
|
3
|
+
import { type CoreEditor, Node } from '@kerebron/editor';
|
|
4
|
+
import {
|
|
5
|
+
type CommandFactories,
|
|
6
|
+
type CommandShortcuts,
|
|
7
|
+
} from '@kerebron/editor/commands';
|
|
8
|
+
import { type InputRule } from '@kerebron/editor/plugins/input-rules';
|
|
9
|
+
|
|
10
|
+
function getCellAttrs(dom: HTMLElement | string): Attrs {
|
|
11
|
+
if (typeof dom === 'string') {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const widthAttr = dom.getAttribute('data-colwidth');
|
|
16
|
+
const widths = widthAttr && /^\d+(,\d+)*$/.test(widthAttr)
|
|
17
|
+
? widthAttr.split(',').map((s) => Number(s))
|
|
18
|
+
: null;
|
|
19
|
+
const colspan = Number(dom.getAttribute('colspan') || 1);
|
|
20
|
+
return {
|
|
21
|
+
colspan,
|
|
22
|
+
rowspan: Number(dom.getAttribute('rowspan') || 1),
|
|
23
|
+
colwidth: widths && widths.length == colspan ? widths : null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function setCellAttrs(node: PmNode): Attrs {
|
|
28
|
+
return {
|
|
29
|
+
colspan: (node.attrs.colspan != 1) ? node.attrs.colspan : undefined,
|
|
30
|
+
rowspan: (node.attrs.rowspan != 1) ? node.attrs.rowspan : undefined,
|
|
31
|
+
'data-colwidth': node.attrs.colwidth?.join(','),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class NodeTableCell extends Node {
|
|
36
|
+
override name = 'table_cell';
|
|
37
|
+
requires = ['table_row'];
|
|
38
|
+
|
|
39
|
+
override getNodeSpec(): NodeSpec {
|
|
40
|
+
return {
|
|
41
|
+
content: 'block+',
|
|
42
|
+
attrs: {
|
|
43
|
+
colspan: { default: 1 },
|
|
44
|
+
rowspan: { default: 1 },
|
|
45
|
+
colwidth: { default: null },
|
|
46
|
+
},
|
|
47
|
+
tableRole: 'cell',
|
|
48
|
+
isolating: true,
|
|
49
|
+
parseDOM: [
|
|
50
|
+
{ tag: 'td', getAttrs: (dom) => getCellAttrs(dom) },
|
|
51
|
+
],
|
|
52
|
+
toDOM(node) {
|
|
53
|
+
return ['td', setCellAttrs(node), 0];
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override getCommandFactories(
|
|
59
|
+
editor: CoreEditor,
|
|
60
|
+
type: NodeType,
|
|
61
|
+
): Partial<CommandFactories> {
|
|
62
|
+
const commands = {};
|
|
63
|
+
return commands;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
override getKeyboardShortcuts(): Partial<CommandShortcuts> {
|
|
67
|
+
const keys = {};
|
|
68
|
+
return keys;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Attrs, Node as PmNode, NodeSpec } from 'prosemirror-model';
|
|
2
|
+
import { Node } from '@kerebron/editor';
|
|
3
|
+
|
|
4
|
+
function getCellAttrs(dom: HTMLElement | string): Attrs {
|
|
5
|
+
if (typeof dom === 'string') {
|
|
6
|
+
return {};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const widthAttr = dom.getAttribute('data-colwidth');
|
|
10
|
+
const widths = widthAttr && /^\d+(,\d+)*$/.test(widthAttr)
|
|
11
|
+
? widthAttr.split(',').map((s) => Number(s))
|
|
12
|
+
: null;
|
|
13
|
+
const colspan = Number(dom.getAttribute('colspan') || 1);
|
|
14
|
+
return {
|
|
15
|
+
colspan,
|
|
16
|
+
rowspan: Number(dom.getAttribute('rowspan') || 1),
|
|
17
|
+
colwidth: widths && widths.length == colspan ? widths : null,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function setCellAttrs(node: PmNode): Attrs {
|
|
22
|
+
return {
|
|
23
|
+
colspan: (node.attrs.colspan != 1) ? node.attrs.colspan : undefined,
|
|
24
|
+
rowspan: (node.attrs.rowspan != 1) ? node.attrs.rowspan : undefined,
|
|
25
|
+
'data-colwidth': node.attrs.colwidth?.join(','),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class NodeTableHeader extends Node {
|
|
30
|
+
override name = 'table_header';
|
|
31
|
+
requires = ['table'];
|
|
32
|
+
|
|
33
|
+
override getNodeSpec(): NodeSpec {
|
|
34
|
+
return {
|
|
35
|
+
content: 'block+',
|
|
36
|
+
attrs: {
|
|
37
|
+
colspan: { default: 1 },
|
|
38
|
+
rowspan: { default: 1 },
|
|
39
|
+
colwidth: { default: null },
|
|
40
|
+
},
|
|
41
|
+
tableRole: 'header_cell',
|
|
42
|
+
isolating: true,
|
|
43
|
+
parseDOM: [
|
|
44
|
+
{ tag: 'th', getAttrs: (dom) => getCellAttrs(dom) },
|
|
45
|
+
],
|
|
46
|
+
toDOM: (node) => ['th', setCellAttrs(node), 0],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { NodeSpec, NodeType } from 'prosemirror-model';
|
|
2
|
+
|
|
3
|
+
import { type CoreEditor, Node } from '@kerebron/editor';
|
|
4
|
+
import {
|
|
5
|
+
type CommandFactories,
|
|
6
|
+
type CommandShortcuts,
|
|
7
|
+
} from '@kerebron/editor/commands';
|
|
8
|
+
import {
|
|
9
|
+
type InputRule,
|
|
10
|
+
textblockTypeInputRule,
|
|
11
|
+
} from '@kerebron/editor/plugins/input-rules';
|
|
12
|
+
|
|
13
|
+
export class NodeTableRow extends Node {
|
|
14
|
+
override name = 'table_row';
|
|
15
|
+
requires = ['table'];
|
|
16
|
+
|
|
17
|
+
override getNodeSpec(): NodeSpec {
|
|
18
|
+
return {
|
|
19
|
+
content: '(table_cell | table_header)*',
|
|
20
|
+
tableRole: 'row',
|
|
21
|
+
parseDOM: [{ tag: 'tr' }],
|
|
22
|
+
toDOM() {
|
|
23
|
+
return ['tr', 0];
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override getCommandFactories(
|
|
29
|
+
editor: CoreEditor,
|
|
30
|
+
type: NodeType,
|
|
31
|
+
): Partial<CommandFactories> {
|
|
32
|
+
const commands = {};
|
|
33
|
+
|
|
34
|
+
return commands;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
override getKeyboardShortcuts(): Partial<CommandShortcuts> {
|
|
38
|
+
const keys = {};
|
|
39
|
+
return keys;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const dntGlobals = {
|
|
2
|
+
};
|
|
3
|
+
export const dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
|
|
4
|
+
|
|
5
|
+
function createMergeProxy<T extends object, U extends object>(
|
|
6
|
+
baseObj: T,
|
|
7
|
+
extObj: U,
|
|
8
|
+
): Omit<T, keyof U> & U {
|
|
9
|
+
return new Proxy(baseObj, {
|
|
10
|
+
get(_target, prop, _receiver) {
|
|
11
|
+
if (prop in extObj) {
|
|
12
|
+
return (extObj as any)[prop];
|
|
13
|
+
} else {
|
|
14
|
+
return (baseObj as any)[prop];
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
set(_target, prop, value) {
|
|
18
|
+
if (prop in extObj) {
|
|
19
|
+
delete (extObj as any)[prop];
|
|
20
|
+
}
|
|
21
|
+
(baseObj as any)[prop] = value;
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
deleteProperty(_target, prop) {
|
|
25
|
+
let success = false;
|
|
26
|
+
if (prop in extObj) {
|
|
27
|
+
delete (extObj as any)[prop];
|
|
28
|
+
success = true;
|
|
29
|
+
}
|
|
30
|
+
if (prop in baseObj) {
|
|
31
|
+
delete (baseObj as any)[prop];
|
|
32
|
+
success = true;
|
|
33
|
+
}
|
|
34
|
+
return success;
|
|
35
|
+
},
|
|
36
|
+
ownKeys(_target) {
|
|
37
|
+
const baseKeys = Reflect.ownKeys(baseObj);
|
|
38
|
+
const extKeys = Reflect.ownKeys(extObj);
|
|
39
|
+
const extKeysSet = new Set(extKeys);
|
|
40
|
+
return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
|
|
41
|
+
},
|
|
42
|
+
defineProperty(_target, prop, desc) {
|
|
43
|
+
if (prop in extObj) {
|
|
44
|
+
delete (extObj as any)[prop];
|
|
45
|
+
}
|
|
46
|
+
Reflect.defineProperty(baseObj, prop, desc);
|
|
47
|
+
return true;
|
|
48
|
+
},
|
|
49
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
50
|
+
if (prop in extObj) {
|
|
51
|
+
return Reflect.getOwnPropertyDescriptor(extObj, prop);
|
|
52
|
+
} else {
|
|
53
|
+
return Reflect.getOwnPropertyDescriptor(baseObj, prop);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
has(_target, prop) {
|
|
57
|
+
return prop in extObj || prop in baseObj;
|
|
58
|
+
},
|
|
59
|
+
}) as any;
|
|
60
|
+
}
|