@progress/kendo-editor-common 1.6.1-dev.202112152003 → 1.7.0-dev.202201030643
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/dist/cdn/js/kendo-editor-common.js +2 -2
- package/dist/cdn/main.js +1 -1
- package/dist/es/config/constants.js +2 -0
- package/dist/es/config/schema.js +115 -37
- package/dist/es/main.js +1 -1
- package/dist/es/source.js +53 -1
- package/dist/es/table.js +49 -0
- package/dist/es2015/config/constants.js +2 -0
- package/dist/es2015/config/schema.js +115 -37
- package/dist/es2015/main.js +1 -1
- package/dist/es2015/source.js +53 -1
- package/dist/es2015/table.js +47 -0
- package/dist/npm/config/constants.d.ts +2 -0
- package/dist/npm/config/constants.js +4 -0
- package/dist/npm/config/schema.js +115 -37
- package/dist/npm/main.d.ts +1 -1
- package/dist/npm/main.js +6 -2
- package/dist/npm/source.js +53 -1
- package/dist/npm/table.d.ts +5 -0
- package/dist/npm/table.js +50 -0
- package/dist/systemjs/kendo-editor-common.js +1 -1
- package/package.json +4 -3
package/dist/es/source.js
CHANGED
|
@@ -1,9 +1,58 @@
|
|
|
1
1
|
import { DOMSerializer, DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
|
|
2
2
|
import { AllSelection } from 'prosemirror-state';
|
|
3
|
+
import { rowTypeAttr, colgroupAttr } from './config/constants';
|
|
3
4
|
var blockWrappers = [
|
|
4
5
|
'div', 'ol', 'ul', 'li', 'table', 'tbody', 'thead', 'tfoot', 'td', 'th', 'p',
|
|
5
6
|
'tr', 'col', 'colgroup', 'article', 'main', 'nav', 'header', 'footer', 'aside', 'section'
|
|
6
7
|
];
|
|
8
|
+
var removeRowType = function (table, nodeName) {
|
|
9
|
+
var wrapper = (table.ownerDocument || document).createElement(nodeName);
|
|
10
|
+
Array.from(table.rows).filter(function (r) { return r.getAttribute(rowTypeAttr) === nodeName; }).forEach(function (row) {
|
|
11
|
+
row.removeAttribute(rowTypeAttr);
|
|
12
|
+
wrapper.appendChild(row);
|
|
13
|
+
});
|
|
14
|
+
if (wrapper.children.length) {
|
|
15
|
+
table.appendChild(wrapper);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var restoreTables = function (fragment) {
|
|
19
|
+
Array.from(fragment.querySelectorAll('table')).forEach(function (table) {
|
|
20
|
+
removeRowType(table, 'thead');
|
|
21
|
+
removeRowType(table, 'tbody');
|
|
22
|
+
removeRowType(table, 'tfoot');
|
|
23
|
+
var emptyElement = Array.from(table.children).find(function (el) { return el.children.length === 0; });
|
|
24
|
+
if (emptyElement) {
|
|
25
|
+
emptyElement.remove();
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
var setRowType = function (children, nodeName) {
|
|
30
|
+
var tag = nodeName.toUpperCase();
|
|
31
|
+
children.filter(function (c) { return c.nodeName === tag; }).forEach(function (rowsWrapper) {
|
|
32
|
+
Array.from(rowsWrapper.children).forEach(function (row) {
|
|
33
|
+
row.setAttribute(rowTypeAttr, nodeName);
|
|
34
|
+
if (rowsWrapper.parentNode) {
|
|
35
|
+
rowsWrapper.parentNode.insertBefore(row, rowsWrapper);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
rowsWrapper.remove();
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
var validateTablesToPmSchema = function (fragment) {
|
|
42
|
+
Array.from(fragment.querySelectorAll('table')).forEach(function (table) {
|
|
43
|
+
var children = Array.from(table.children);
|
|
44
|
+
if (children.some(function (e) { return e.nodeName === 'THEAD' || e.nodeName === 'TFOOT'; })) {
|
|
45
|
+
setRowType(children, 'thead');
|
|
46
|
+
setRowType(children, 'tbody');
|
|
47
|
+
setRowType(children, 'tfoot');
|
|
48
|
+
}
|
|
49
|
+
var colgroup = children.find(function (c) { return c.nodeName === 'COLGROUP'; });
|
|
50
|
+
if (colgroup) {
|
|
51
|
+
table.setAttribute(colgroupAttr, colgroup.outerHTML);
|
|
52
|
+
colgroup.remove();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
};
|
|
7
56
|
/**
|
|
8
57
|
* Trims the whitespace around the provided block nodes.
|
|
9
58
|
*
|
|
@@ -52,7 +101,9 @@ export var htmlToFragment = function (html) {
|
|
|
52
101
|
* @returns DocumentFragment
|
|
53
102
|
*/
|
|
54
103
|
export var pmDocToFragment = function (doc) {
|
|
55
|
-
|
|
104
|
+
var fragment = DOMSerializer.fromSchema(doc.type.schema).serializeFragment(doc.content);
|
|
105
|
+
restoreTables(fragment);
|
|
106
|
+
return fragment;
|
|
56
107
|
};
|
|
57
108
|
/**
|
|
58
109
|
* Creates a ProseMirrorNode from the given DOM element.
|
|
@@ -75,6 +126,7 @@ export var domToPmDoc = function (dom, schema, parseOptions) {
|
|
|
75
126
|
*/
|
|
76
127
|
export var parseContent = function (content, schema, parseOptions) {
|
|
77
128
|
var dom = htmlToFragment(content);
|
|
129
|
+
validateTablesToPmSchema(dom);
|
|
78
130
|
return domToPmDoc(dom, schema, parseOptions);
|
|
79
131
|
};
|
|
80
132
|
/**
|
package/dist/es/table.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { addRowAfter as pmAddRowAfter, addRowBefore as pmAddRowBefore } from 'prosemirror-tables';
|
|
2
|
+
import { rowTypeAttr } from './config/constants';
|
|
1
3
|
/**
|
|
2
4
|
* Creates a table.
|
|
3
5
|
* @returns Node
|
|
@@ -15,3 +17,50 @@ export var createTable = function (nodes, rows, columns) {
|
|
|
15
17
|
}
|
|
16
18
|
return table.createAndFill(undefined, tableRows);
|
|
17
19
|
};
|
|
20
|
+
var closest = function (selection, name) {
|
|
21
|
+
var pos = selection.$head;
|
|
22
|
+
for (var i = pos.depth; i > 0; i--) {
|
|
23
|
+
var node = pos.node(i);
|
|
24
|
+
if (node.type.name === name) {
|
|
25
|
+
return {
|
|
26
|
+
pos: pos.before(i),
|
|
27
|
+
node: node
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
33
|
+
export var addRowBefore = function (state, dispatch) {
|
|
34
|
+
var cmdDispatch = dispatch && (function (tr) {
|
|
35
|
+
var _a;
|
|
36
|
+
var row = closest(tr.selection, 'table_row');
|
|
37
|
+
var table = closest(tr.selection, 'table');
|
|
38
|
+
if (row && table && row.node.attrs[rowTypeAttr]) {
|
|
39
|
+
var index = 0;
|
|
40
|
+
for (var i = 0; i < table.node.nodeSize; i++) {
|
|
41
|
+
if (table.node.child(i).eq(row.node)) {
|
|
42
|
+
index = i;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
var next = table.node.child(index - 1);
|
|
47
|
+
var from = row.pos - next.nodeSize;
|
|
48
|
+
tr.setNodeMarkup(from, undefined, (_a = {}, _a[rowTypeAttr] = row.node.attrs[rowTypeAttr], _a));
|
|
49
|
+
}
|
|
50
|
+
return dispatch(tr);
|
|
51
|
+
});
|
|
52
|
+
return pmAddRowBefore(state, cmdDispatch);
|
|
53
|
+
};
|
|
54
|
+
export var addRowAfter = function (state, dispatch) {
|
|
55
|
+
var cmdDispatch = dispatch && (function (tr) {
|
|
56
|
+
var _a;
|
|
57
|
+
var row = closest(tr.selection, 'table_row');
|
|
58
|
+
if (row && row.node.attrs[rowTypeAttr]) {
|
|
59
|
+
var from = row.pos + row.node.nodeSize;
|
|
60
|
+
tr.setNodeMarkup(from, undefined, (_a = {}, _a[rowTypeAttr] = row.node.attrs[rowTypeAttr], _a));
|
|
61
|
+
}
|
|
62
|
+
return dispatch(tr);
|
|
63
|
+
});
|
|
64
|
+
return pmAddRowAfter(state, cmdDispatch);
|
|
65
|
+
};
|
|
66
|
+
export { pmAddRowBefore, pmAddRowAfter };
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { Schema } from 'prosemirror-model';
|
|
1
2
|
import { tableNodes } from 'prosemirror-tables';
|
|
3
|
+
import { domToPmDoc, htmlToFragment, pmDocToFragment } from '../source';
|
|
4
|
+
import { rowTypeAttr, colgroupAttr } from './constants';
|
|
2
5
|
const hole = 0;
|
|
3
6
|
const blockquoteDOM = ['blockquote', hole], hrDOM = ['hr'], preDOM = ['pre', ['code', hole]];
|
|
4
7
|
const olDOM = ['ol', 0], ulDOM = ['ul', 0], liDOM = ['li', 0];
|
|
5
|
-
const
|
|
8
|
+
const domAttributes = (dom) => {
|
|
6
9
|
const result = {};
|
|
7
10
|
let attributes = dom.attributes, attr;
|
|
8
11
|
for (let i = 0; i < attributes.length; i++) {
|
|
@@ -11,13 +14,14 @@ const getAttributes = (dom) => {
|
|
|
11
14
|
}
|
|
12
15
|
return result;
|
|
13
16
|
};
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const defaultAttrs = (attrs) => {
|
|
18
|
+
const nodeAttrs = {};
|
|
19
|
+
attrs.forEach(attr => {
|
|
20
|
+
nodeAttrs[attr] = { default: null };
|
|
21
|
+
});
|
|
22
|
+
return nodeAttrs;
|
|
20
23
|
};
|
|
24
|
+
const commonAttributes = () => defaultAttrs(['style', 'class', 'id']);
|
|
21
25
|
const hasAttrs = (attrs, exclude) => {
|
|
22
26
|
for (let attr in attrs) {
|
|
23
27
|
if (attr && attrs[attr] !== null && attr !== exclude) {
|
|
@@ -26,7 +30,7 @@ const hasAttrs = (attrs, exclude) => {
|
|
|
26
30
|
}
|
|
27
31
|
return false;
|
|
28
32
|
};
|
|
29
|
-
const
|
|
33
|
+
const pmAttributes = (attrs, exclude) => {
|
|
30
34
|
const result = {};
|
|
31
35
|
for (let attr in attrs) {
|
|
32
36
|
if (attr && attrs[attr] !== null && attr !== exclude) {
|
|
@@ -52,17 +56,91 @@ const marks = Object.assign({
|
|
|
52
56
|
link: {
|
|
53
57
|
attrs: Object.assign({}, commonAttributes(), { href: { default: null }, target: { default: null }, title: { default: null } }),
|
|
54
58
|
inclusive: false,
|
|
55
|
-
parseDOM: [{ tag: 'a', getAttrs:
|
|
56
|
-
toDOM: (node) => ['a',
|
|
59
|
+
parseDOM: [{ tag: 'a', getAttrs: domAttributes }],
|
|
60
|
+
toDOM: (node) => ['a', pmAttributes(node.attrs), hole]
|
|
57
61
|
} }, tagMark('strong'), tagMark('b'), tagMark('em'), tagMark('i'), tagMark('u'), tagMark('del'), tagMark('sub'), tagMark('sup'), tagMark('code'), { style: {
|
|
58
62
|
attrs: Object.assign({}, commonAttributes()),
|
|
59
63
|
parseDOM: [{
|
|
60
64
|
tag: 'span',
|
|
61
|
-
getAttrs:
|
|
65
|
+
getAttrs: domAttributes
|
|
62
66
|
}],
|
|
63
67
|
toDOM: node => hasAttrs(node.attrs) ?
|
|
64
|
-
['span',
|
|
68
|
+
['span', pmAttributes(node.attrs), hole] : ['span', hole]
|
|
65
69
|
} });
|
|
70
|
+
const cellAttribute = (name) => {
|
|
71
|
+
return {
|
|
72
|
+
[name]: {
|
|
73
|
+
default: null,
|
|
74
|
+
getFromDOM: (cell) => cell.getAttribute(name),
|
|
75
|
+
setDOMAttr: (value, attrs) => { attrs[name] = value; }
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
const cellAttributes = Object.assign({}, cellAttribute('style'), cellAttribute('class'), cellAttribute('id'), cellAttribute('headers'));
|
|
80
|
+
const colgroupNodes = {
|
|
81
|
+
doc: { content: 'colgroup*' },
|
|
82
|
+
col: {
|
|
83
|
+
attrs: defaultAttrs(['id', 'class', 'style', 'span']),
|
|
84
|
+
parseDOM: [{ getAttrs: domAttributes, tag: 'col' }],
|
|
85
|
+
toDOM: node => ['col', node.attrs]
|
|
86
|
+
},
|
|
87
|
+
colgroup: {
|
|
88
|
+
attrs: defaultAttrs(['id', 'class', 'style', 'span']),
|
|
89
|
+
content: 'col*',
|
|
90
|
+
parseDOM: [{ getAttrs: domAttributes, tag: 'colgroup' }],
|
|
91
|
+
toDOM: node => ['colgroup', node.attrs, 0]
|
|
92
|
+
},
|
|
93
|
+
text: { inline: true, group: 'inline' }
|
|
94
|
+
};
|
|
95
|
+
const colgroupSchema = new Schema({ nodes: colgroupNodes, marks: {} });
|
|
96
|
+
// will be removed when we implement our own columnResizing
|
|
97
|
+
const shouldSkipColgroup = (node) => {
|
|
98
|
+
let shouldSkip = false;
|
|
99
|
+
const row = node.child(0);
|
|
100
|
+
for (let r = 0; r < row.childCount; r++) {
|
|
101
|
+
const cell = row.child(r);
|
|
102
|
+
if (cell.attrs.colwidth) {
|
|
103
|
+
shouldSkip = true;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return shouldSkip;
|
|
108
|
+
};
|
|
109
|
+
const tNodes = tableNodes({ tableGroup: 'block', cellContent: 'block+', cellAttributes });
|
|
110
|
+
tNodes.table_row.attrs = Object.assign({}, tNodes.table_row.attrs, defaultAttrs([rowTypeAttr, 'style', 'class', 'id']));
|
|
111
|
+
tNodes.table_row.toDOM = node => ['tr', pmAttributes(node.attrs), 0];
|
|
112
|
+
tNodes.table_row.parseDOM = [{ tag: 'tr', getAttrs: domAttributes }];
|
|
113
|
+
tNodes.table.attrs = Object.assign({}, tNodes.table.attrs, defaultAttrs(['style', 'class', 'id', colgroupAttr]));
|
|
114
|
+
tNodes.table.toDOM = (node) => {
|
|
115
|
+
const tableAttrs = hasAttrs(node.attrs) ? pmAttributes(node.attrs, colgroupAttr) : {};
|
|
116
|
+
let colgroup = null;
|
|
117
|
+
if (node.attrs[colgroupAttr] && !shouldSkipColgroup(node)) {
|
|
118
|
+
const doc = domToPmDoc(htmlToFragment(node.attrs[colgroupAttr]), colgroupSchema, { preserveWhitespace: false });
|
|
119
|
+
const fragment = pmDocToFragment(doc);
|
|
120
|
+
const colgroupEl = fragment.firstChild;
|
|
121
|
+
if (colgroupEl) {
|
|
122
|
+
const cols = Array.from(colgroupEl.children).map((c) => ['col', domAttributes(c)]);
|
|
123
|
+
colgroup = [
|
|
124
|
+
'colgroup',
|
|
125
|
+
domAttributes(colgroupEl),
|
|
126
|
+
...cols
|
|
127
|
+
];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return colgroup ? ['table', tableAttrs, colgroup, ['tbody', 0]] :
|
|
131
|
+
['table', tableAttrs, ['tbody', 0]];
|
|
132
|
+
};
|
|
133
|
+
tNodes.table.parseDOM = [{
|
|
134
|
+
tag: 'table',
|
|
135
|
+
getAttrs: (node) => {
|
|
136
|
+
const attrs = domAttributes(node);
|
|
137
|
+
const colgroup = Array.from(node.childNodes).find(c => c.nodeName === 'COLGROUP');
|
|
138
|
+
if (colgroup) {
|
|
139
|
+
attrs[colgroupAttr] = colgroup.outerHTML;
|
|
140
|
+
}
|
|
141
|
+
return attrs;
|
|
142
|
+
}
|
|
143
|
+
}];
|
|
66
144
|
const nodes = Object.assign({
|
|
67
145
|
// :: NodeSpec The top level document node.
|
|
68
146
|
doc: {
|
|
@@ -76,9 +154,9 @@ const nodes = Object.assign({
|
|
|
76
154
|
attrs: Object.assign({}, commonAttributes()),
|
|
77
155
|
parseDOM: [{
|
|
78
156
|
tag: 'p',
|
|
79
|
-
getAttrs:
|
|
157
|
+
getAttrs: domAttributes
|
|
80
158
|
}],
|
|
81
|
-
toDOM: node => hasAttrs(node.attrs) ? ['p',
|
|
159
|
+
toDOM: node => hasAttrs(node.attrs) ? ['p', pmAttributes(node.attrs), hole] : ['p', hole]
|
|
82
160
|
}, div: {
|
|
83
161
|
// Uncaught SyntaxError: Mixing inline and block content (in content expression '(block | inline)*')
|
|
84
162
|
// content: '(block | inline)*',
|
|
@@ -87,9 +165,9 @@ const nodes = Object.assign({
|
|
|
87
165
|
attrs: Object.assign({}, commonAttributes()),
|
|
88
166
|
parseDOM: [{
|
|
89
167
|
tag: 'div',
|
|
90
|
-
getAttrs:
|
|
168
|
+
getAttrs: domAttributes
|
|
91
169
|
}],
|
|
92
|
-
toDOM: node => hasAttrs(node.attrs) ? ['div',
|
|
170
|
+
toDOM: node => hasAttrs(node.attrs) ? ['div', pmAttributes(node.attrs), hole] : ['div', hole]
|
|
93
171
|
},
|
|
94
172
|
// :: NodeSpec A blockquote (`<blockquote>`) wrapping one or more blocks.
|
|
95
173
|
blockquote: {
|
|
@@ -99,9 +177,9 @@ const nodes = Object.assign({
|
|
|
99
177
|
defining: true,
|
|
100
178
|
parseDOM: [{
|
|
101
179
|
tag: 'blockquote',
|
|
102
|
-
getAttrs:
|
|
180
|
+
getAttrs: domAttributes
|
|
103
181
|
}],
|
|
104
|
-
toDOM: node => hasAttrs(node.attrs) ? ['blockquote',
|
|
182
|
+
toDOM: node => hasAttrs(node.attrs) ? ['blockquote', pmAttributes(node.attrs), hole] : blockquoteDOM
|
|
105
183
|
},
|
|
106
184
|
// :: NodeSpec A horizontal rule (`<hr>`).
|
|
107
185
|
horizontal_rule: {
|
|
@@ -118,15 +196,15 @@ const nodes = Object.assign({
|
|
|
118
196
|
group: 'block',
|
|
119
197
|
defining: true,
|
|
120
198
|
parseDOM: [
|
|
121
|
-
{ tag: 'h1', getAttrs: node => (Object.assign({},
|
|
122
|
-
{ tag: 'h2', getAttrs: node => (Object.assign({},
|
|
123
|
-
{ tag: 'h3', getAttrs: node => (Object.assign({},
|
|
124
|
-
{ tag: 'h4', getAttrs: node => (Object.assign({},
|
|
125
|
-
{ tag: 'h5', getAttrs: node => (Object.assign({},
|
|
126
|
-
{ tag: 'h6', getAttrs: node => (Object.assign({},
|
|
199
|
+
{ tag: 'h1', getAttrs: node => (Object.assign({}, domAttributes(node), { level: 1 })) },
|
|
200
|
+
{ tag: 'h2', getAttrs: node => (Object.assign({}, domAttributes(node), { level: 2 })) },
|
|
201
|
+
{ tag: 'h3', getAttrs: node => (Object.assign({}, domAttributes(node), { level: 3 })) },
|
|
202
|
+
{ tag: 'h4', getAttrs: node => (Object.assign({}, domAttributes(node), { level: 4 })) },
|
|
203
|
+
{ tag: 'h5', getAttrs: node => (Object.assign({}, domAttributes(node), { level: 5 })) },
|
|
204
|
+
{ tag: 'h6', getAttrs: node => (Object.assign({}, domAttributes(node), { level: 6 })) }
|
|
127
205
|
],
|
|
128
206
|
toDOM: node => hasAttrs(node.attrs, 'level') ?
|
|
129
|
-
['h' + node.attrs.level,
|
|
207
|
+
['h' + node.attrs.level, pmAttributes(node.attrs, 'level'), hole] :
|
|
130
208
|
['h' + node.attrs.level, hole]
|
|
131
209
|
},
|
|
132
210
|
// :: NodeSpec A code listing. Disallows marks or non-text inline
|
|
@@ -154,8 +232,8 @@ const nodes = Object.assign({
|
|
|
154
232
|
attrs: Object.assign({ src: { default: null }, alt: { default: null }, title: { default: null }, width: { default: null }, height: { default: null } }, commonAttributes()),
|
|
155
233
|
group: 'inline',
|
|
156
234
|
draggable: true,
|
|
157
|
-
parseDOM: [{ tag: 'img', getAttrs:
|
|
158
|
-
toDOM: node => hasAttrs(node.attrs) ? ['img',
|
|
235
|
+
parseDOM: [{ tag: 'img', getAttrs: domAttributes }],
|
|
236
|
+
toDOM: node => hasAttrs(node.attrs) ? ['img', pmAttributes(node.attrs)] : ['img']
|
|
159
237
|
},
|
|
160
238
|
// :: NodeSpec A hard line break represented in the DOM as a `<br>` element.
|
|
161
239
|
hard_break: {
|
|
@@ -165,9 +243,9 @@ const nodes = Object.assign({
|
|
|
165
243
|
selectable: false,
|
|
166
244
|
parseDOM: [{
|
|
167
245
|
tag: 'br',
|
|
168
|
-
getAttrs:
|
|
246
|
+
getAttrs: domAttributes
|
|
169
247
|
}],
|
|
170
|
-
toDOM: node => hasAttrs(node.attrs) ? ['br',
|
|
248
|
+
toDOM: node => hasAttrs(node.attrs) ? ['br', pmAttributes(node.attrs)] : ['br']
|
|
171
249
|
},
|
|
172
250
|
// :: NodeSpec
|
|
173
251
|
// An ordered list [node spec](#model.NodeSpec). Has a single
|
|
@@ -179,12 +257,12 @@ const nodes = Object.assign({
|
|
|
179
257
|
group: 'block',
|
|
180
258
|
attrs: Object.assign({}, commonAttributes(), { type: { default: null }, order: { default: 1 } }),
|
|
181
259
|
parseDOM: [{ tag: 'ol', getAttrs: (dom) => {
|
|
182
|
-
return Object.assign({},
|
|
260
|
+
return Object.assign({}, domAttributes(dom), { order: dom.hasAttribute('start') ? parseInt(dom.getAttribute('start') || '1', 10) : 1 });
|
|
183
261
|
} }],
|
|
184
262
|
toDOM: node => {
|
|
185
263
|
return node.attrs.order === 1 ?
|
|
186
|
-
(hasAttrs(node.attrs, 'order') ? ['ol',
|
|
187
|
-
['ol', Object.assign({},
|
|
264
|
+
(hasAttrs(node.attrs, 'order') ? ['ol', pmAttributes(node.attrs, 'order'), hole] : olDOM) :
|
|
265
|
+
['ol', Object.assign({}, pmAttributes(node.attrs, 'order'), { start: node.attrs.order }), hole];
|
|
188
266
|
}
|
|
189
267
|
},
|
|
190
268
|
// :: NodeSpec
|
|
@@ -193,16 +271,16 @@ const nodes = Object.assign({
|
|
|
193
271
|
content: 'list_item+',
|
|
194
272
|
group: 'block',
|
|
195
273
|
attrs: Object.assign({}, commonAttributes()),
|
|
196
|
-
parseDOM: [{ tag: 'ul', getAttrs:
|
|
197
|
-
toDOM: node => hasAttrs(node.attrs) ? ['ul',
|
|
274
|
+
parseDOM: [{ tag: 'ul', getAttrs: domAttributes }],
|
|
275
|
+
toDOM: node => hasAttrs(node.attrs) ? ['ul', pmAttributes(node.attrs), hole] : ulDOM
|
|
198
276
|
},
|
|
199
277
|
// :: NodeSpec
|
|
200
278
|
// A list item (`<li>`) specification.
|
|
201
279
|
list_item: {
|
|
202
280
|
content: '(paragraph | heading) block*',
|
|
203
281
|
attrs: Object.assign({}, commonAttributes()),
|
|
204
|
-
parseDOM: [{ tag: 'li', getAttrs:
|
|
205
|
-
toDOM: node => hasAttrs(node.attrs) ? ['li',
|
|
282
|
+
parseDOM: [{ tag: 'li', getAttrs: domAttributes }],
|
|
283
|
+
toDOM: node => hasAttrs(node.attrs) ? ['li', pmAttributes(node.attrs), hole] : liDOM,
|
|
206
284
|
defining: true
|
|
207
|
-
} },
|
|
285
|
+
} }, tNodes);
|
|
208
286
|
export { nodes, marks };
|
package/dist/es2015/main.js
CHANGED
|
@@ -18,7 +18,6 @@ export { buildKeymap, buildListKeymap } from './config/keymap';
|
|
|
18
18
|
export { bold, italic, underline, strikethrough, subscript, superscript, link } from './config/commands';
|
|
19
19
|
export { sanitize, removeComments, removeTag, pasteCleanup, sanitizeClassAttr, sanitizeStyleAttr, removeAttribute, replaceImageSourcesFromRtf } from './paste';
|
|
20
20
|
export { convertMsLists } from './listConvert';
|
|
21
|
-
export { createTable } from './table';
|
|
22
21
|
export { find, findAt, findAll, replace, replaceAll } from './find-replace';
|
|
23
22
|
export { placeholder } from './plugins/placeholder';
|
|
24
23
|
export { spacesFix } from './plugins/spaces-fix';
|
|
@@ -37,3 +36,4 @@ export * from 'prosemirror-state';
|
|
|
37
36
|
export * from 'prosemirror-tables';
|
|
38
37
|
export * from 'prosemirror-transform';
|
|
39
38
|
export * from 'prosemirror-view';
|
|
39
|
+
export { createTable, addRowAfter, addRowBefore, pmAddRowAfter, pmAddRowBefore } from './table';
|
package/dist/es2015/source.js
CHANGED
|
@@ -1,9 +1,58 @@
|
|
|
1
1
|
import { DOMSerializer, DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
|
|
2
2
|
import { AllSelection } from 'prosemirror-state';
|
|
3
|
+
import { rowTypeAttr, colgroupAttr } from './config/constants';
|
|
3
4
|
const blockWrappers = [
|
|
4
5
|
'div', 'ol', 'ul', 'li', 'table', 'tbody', 'thead', 'tfoot', 'td', 'th', 'p',
|
|
5
6
|
'tr', 'col', 'colgroup', 'article', 'main', 'nav', 'header', 'footer', 'aside', 'section'
|
|
6
7
|
];
|
|
8
|
+
const removeRowType = (table, nodeName) => {
|
|
9
|
+
const wrapper = (table.ownerDocument || document).createElement(nodeName);
|
|
10
|
+
Array.from(table.rows).filter(r => r.getAttribute(rowTypeAttr) === nodeName).forEach(row => {
|
|
11
|
+
row.removeAttribute(rowTypeAttr);
|
|
12
|
+
wrapper.appendChild(row);
|
|
13
|
+
});
|
|
14
|
+
if (wrapper.children.length) {
|
|
15
|
+
table.appendChild(wrapper);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const restoreTables = (fragment) => {
|
|
19
|
+
Array.from(fragment.querySelectorAll('table')).forEach((table) => {
|
|
20
|
+
removeRowType(table, 'thead');
|
|
21
|
+
removeRowType(table, 'tbody');
|
|
22
|
+
removeRowType(table, 'tfoot');
|
|
23
|
+
const emptyElement = Array.from(table.children).find(el => el.children.length === 0);
|
|
24
|
+
if (emptyElement) {
|
|
25
|
+
emptyElement.remove();
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const setRowType = (children, nodeName) => {
|
|
30
|
+
const tag = nodeName.toUpperCase();
|
|
31
|
+
children.filter(c => c.nodeName === tag).forEach(rowsWrapper => {
|
|
32
|
+
Array.from(rowsWrapper.children).forEach(row => {
|
|
33
|
+
row.setAttribute(rowTypeAttr, nodeName);
|
|
34
|
+
if (rowsWrapper.parentNode) {
|
|
35
|
+
rowsWrapper.parentNode.insertBefore(row, rowsWrapper);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
rowsWrapper.remove();
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const validateTablesToPmSchema = (fragment) => {
|
|
42
|
+
Array.from(fragment.querySelectorAll('table')).forEach((table) => {
|
|
43
|
+
const children = Array.from(table.children);
|
|
44
|
+
if (children.some(e => e.nodeName === 'THEAD' || e.nodeName === 'TFOOT')) {
|
|
45
|
+
setRowType(children, 'thead');
|
|
46
|
+
setRowType(children, 'tbody');
|
|
47
|
+
setRowType(children, 'tfoot');
|
|
48
|
+
}
|
|
49
|
+
const colgroup = children.find(c => c.nodeName === 'COLGROUP');
|
|
50
|
+
if (colgroup) {
|
|
51
|
+
table.setAttribute(colgroupAttr, colgroup.outerHTML);
|
|
52
|
+
colgroup.remove();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
};
|
|
7
56
|
/**
|
|
8
57
|
* Trims the whitespace around the provided block nodes.
|
|
9
58
|
*
|
|
@@ -51,7 +100,9 @@ export const htmlToFragment = (html) => {
|
|
|
51
100
|
* @returns DocumentFragment
|
|
52
101
|
*/
|
|
53
102
|
export const pmDocToFragment = (doc) => {
|
|
54
|
-
|
|
103
|
+
const fragment = DOMSerializer.fromSchema(doc.type.schema).serializeFragment(doc.content);
|
|
104
|
+
restoreTables(fragment);
|
|
105
|
+
return fragment;
|
|
55
106
|
};
|
|
56
107
|
/**
|
|
57
108
|
* Creates a ProseMirrorNode from the given DOM element.
|
|
@@ -74,6 +125,7 @@ export const domToPmDoc = (dom, schema, parseOptions) => {
|
|
|
74
125
|
*/
|
|
75
126
|
export const parseContent = (content, schema, parseOptions) => {
|
|
76
127
|
const dom = htmlToFragment(content);
|
|
128
|
+
validateTablesToPmSchema(dom);
|
|
77
129
|
return domToPmDoc(dom, schema, parseOptions);
|
|
78
130
|
};
|
|
79
131
|
/**
|
package/dist/es2015/table.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { addRowAfter as pmAddRowAfter, addRowBefore as pmAddRowBefore } from 'prosemirror-tables';
|
|
2
|
+
import { rowTypeAttr } from './config/constants';
|
|
1
3
|
/**
|
|
2
4
|
* Creates a table.
|
|
3
5
|
* @returns Node
|
|
@@ -15,3 +17,48 @@ export const createTable = (nodes, rows, columns) => {
|
|
|
15
17
|
}
|
|
16
18
|
return table.createAndFill(undefined, tableRows);
|
|
17
19
|
};
|
|
20
|
+
const closest = (selection, name) => {
|
|
21
|
+
const pos = selection.$head;
|
|
22
|
+
for (let i = pos.depth; i > 0; i--) {
|
|
23
|
+
const node = pos.node(i);
|
|
24
|
+
if (node.type.name === name) {
|
|
25
|
+
return {
|
|
26
|
+
pos: pos.before(i),
|
|
27
|
+
node
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
33
|
+
export const addRowBefore = (state, dispatch) => {
|
|
34
|
+
const cmdDispatch = dispatch && (tr => {
|
|
35
|
+
const row = closest(tr.selection, 'table_row');
|
|
36
|
+
const table = closest(tr.selection, 'table');
|
|
37
|
+
if (row && table && row.node.attrs[rowTypeAttr]) {
|
|
38
|
+
let index = 0;
|
|
39
|
+
for (let i = 0; i < table.node.nodeSize; i++) {
|
|
40
|
+
if (table.node.child(i).eq(row.node)) {
|
|
41
|
+
index = i;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const next = table.node.child(index - 1);
|
|
46
|
+
const from = row.pos - next.nodeSize;
|
|
47
|
+
tr.setNodeMarkup(from, undefined, { [rowTypeAttr]: row.node.attrs[rowTypeAttr] });
|
|
48
|
+
}
|
|
49
|
+
return dispatch(tr);
|
|
50
|
+
});
|
|
51
|
+
return pmAddRowBefore(state, cmdDispatch);
|
|
52
|
+
};
|
|
53
|
+
export const addRowAfter = (state, dispatch) => {
|
|
54
|
+
const cmdDispatch = dispatch && (tr => {
|
|
55
|
+
const row = closest(tr.selection, 'table_row');
|
|
56
|
+
if (row && row.node.attrs[rowTypeAttr]) {
|
|
57
|
+
const from = row.pos + row.node.nodeSize;
|
|
58
|
+
tr.setNodeMarkup(from, undefined, { [rowTypeAttr]: row.node.attrs[rowTypeAttr] });
|
|
59
|
+
}
|
|
60
|
+
return dispatch(tr);
|
|
61
|
+
});
|
|
62
|
+
return pmAddRowAfter(state, cmdDispatch);
|
|
63
|
+
};
|
|
64
|
+
export { pmAddRowBefore, pmAddRowAfter };
|