@progress/kendo-editor-common 1.10.3-dev.202309121208 → 1.10.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 (39) hide show
  1. package/dist/cdn/js/kendo-editor-common.js +1 -1
  2. package/dist/cdn/main.js +1 -1
  3. package/dist/es/DOMSerializer.js +188 -0
  4. package/dist/es/main.js +1 -0
  5. package/dist/es/plugins/csp-fix.js +51 -0
  6. package/dist/es/plugins/table-resize/column-resize.js +2 -1
  7. package/dist/es/plugins/table-resize/row-resize.js +2 -1
  8. package/dist/es/plugins/table-resize/table-resize.js +2 -1
  9. package/dist/es/plugins/table-resize/table-view.js +3 -17
  10. package/dist/es/plugins/table-resize/utils.js +0 -8
  11. package/dist/es/source.js +29 -19
  12. package/dist/es/utils.js +31 -0
  13. package/dist/es2015/DOMSerializer.js +181 -0
  14. package/dist/es2015/main.js +1 -0
  15. package/dist/es2015/plugins/csp-fix.js +48 -0
  16. package/dist/es2015/plugins/table-resize/column-resize.js +2 -1
  17. package/dist/es2015/plugins/table-resize/row-resize.js +2 -1
  18. package/dist/es2015/plugins/table-resize/table-resize.js +2 -1
  19. package/dist/es2015/plugins/table-resize/table-view.js +3 -17
  20. package/dist/es2015/plugins/table-resize/utils.js +0 -7
  21. package/dist/es2015/source.js +27 -19
  22. package/dist/es2015/utils.js +30 -0
  23. package/dist/npm/DOMSerializer.d.ts +35 -0
  24. package/dist/npm/DOMSerializer.js +191 -0
  25. package/dist/npm/main.d.ts +1 -0
  26. package/dist/npm/main.js +4 -2
  27. package/dist/npm/plugins/csp-fix.d.ts +2 -0
  28. package/dist/npm/plugins/csp-fix.js +55 -0
  29. package/dist/npm/plugins/table-resize/column-resize.js +23 -22
  30. package/dist/npm/plugins/table-resize/row-resize.js +3 -2
  31. package/dist/npm/plugins/table-resize/table-resize.js +7 -6
  32. package/dist/npm/plugins/table-resize/table-view.js +3 -17
  33. package/dist/npm/plugins/table-resize/utils.d.ts +0 -3
  34. package/dist/npm/plugins/table-resize/utils.js +1 -10
  35. package/dist/npm/source.js +29 -19
  36. package/dist/npm/utils.d.ts +4 -0
  37. package/dist/npm/utils.js +34 -1
  38. package/dist/systemjs/kendo-editor-common.js +1 -1
  39. package/package.json +1 -1
@@ -0,0 +1,188 @@
1
+ import { setAttribute } from "./utils";
2
+ var DOMSerializer = /** @class */ (function () {
3
+ /// Create a serializer. `nodes` should map node names to functions
4
+ /// that take a node and return a description of the corresponding
5
+ /// DOM. `marks` does the same for mark names, but also gets an
6
+ /// argument that tells it whether the mark's content is block or
7
+ /// inline content (for typical use, it'll always be inline). A mark
8
+ /// serializer may be `null` to indicate that marks of that type
9
+ /// should not be serialized.
10
+ function DOMSerializer(
11
+ /// The node serialization functions.
12
+ nodes,
13
+ /// The mark serialization functions.
14
+ marks) {
15
+ this.nodes = nodes;
16
+ this.marks = marks;
17
+ }
18
+ /// Render an [output spec](#model.DOMOutputSpec) to a DOM node. If
19
+ /// the spec has a hole (zero) in it, `contentDOM` will point at the
20
+ /// node with the hole.
21
+ DOMSerializer.renderSpec = function (docum, structure, xmlNS) {
22
+ if (xmlNS === void 0) { xmlNS = null; }
23
+ if (typeof structure === "string") {
24
+ return { dom: docum.createTextNode(structure) };
25
+ }
26
+ if (structure.nodeType != null) {
27
+ return { dom: structure };
28
+ }
29
+ if (structure.dom && structure.dom.nodeType != null) {
30
+ return structure;
31
+ }
32
+ var tagName = structure[0], space = tagName.indexOf(" ");
33
+ if (space > 0) {
34
+ xmlNS = tagName.slice(0, space);
35
+ tagName = tagName.slice(space + 1);
36
+ }
37
+ var contentDOM;
38
+ var dom = (xmlNS ? docum.createElementNS(xmlNS, tagName) : docum.createElement(tagName));
39
+ var attrs = structure[1], start = 1;
40
+ if (attrs && typeof attrs === "object" && attrs.nodeType == null && !Array.isArray(attrs)) {
41
+ start = 2;
42
+ for (var name_1 in attrs) {
43
+ if (attrs[name_1] != null) {
44
+ space = name_1.indexOf(" ");
45
+ if (space > 0) {
46
+ dom.setAttributeNS(name_1.slice(0, space), name_1.slice(space + 1), attrs[name_1]);
47
+ }
48
+ else {
49
+ setAttribute(dom, name_1, attrs[name_1]);
50
+ }
51
+ }
52
+ }
53
+ }
54
+ for (var i = start; i < structure.length; i++) {
55
+ var child = structure[i];
56
+ if (child === 0) {
57
+ if (i < structure.length - 1 || i > start) {
58
+ throw new RangeError("Content hole must be the only child of its parent node");
59
+ }
60
+ return { dom: dom, contentDOM: dom };
61
+ }
62
+ else {
63
+ var _a = DOMSerializer.renderSpec(docum, child, xmlNS), inner = _a.dom, innerContent = _a.contentDOM;
64
+ dom.appendChild(inner);
65
+ if (innerContent) {
66
+ if (contentDOM) {
67
+ throw new RangeError("Multiple content holes");
68
+ }
69
+ contentDOM = innerContent;
70
+ }
71
+ }
72
+ }
73
+ return { dom: dom, contentDOM: contentDOM };
74
+ };
75
+ /// Build a serializer using the [`toDOM`](#model.NodeSpec.toDOM)
76
+ /// properties in a schema's node and mark specs.
77
+ DOMSerializer.fromSchema = function (schema) {
78
+ return schema.cached.domSerializer ||
79
+ (schema.cached.domSerializer = new DOMSerializer(this.nodesFromSchema(schema), this.marksFromSchema(schema)));
80
+ };
81
+ /// Gather the serializers in a schema's node specs into an object.
82
+ /// This can be useful as a base to build a custom serializer from.
83
+ DOMSerializer.nodesFromSchema = function (schema) {
84
+ var result = gatherToDOM(schema.nodes);
85
+ if (!result.text) {
86
+ result.text = function (node) { return node.text; };
87
+ }
88
+ return result;
89
+ };
90
+ /// Gather the serializers in a schema's mark specs into an object.
91
+ DOMSerializer.marksFromSchema = function (schema) {
92
+ return gatherToDOM(schema.marks);
93
+ };
94
+ /// Serialize the content of this fragment to a DOM fragment. When
95
+ /// not in the browser, the `document` option, containing a DOM
96
+ /// document, should be passed so that the serializer can create
97
+ /// nodes.
98
+ DOMSerializer.prototype.serializeFragment = function (fragment, options, target) {
99
+ var _this = this;
100
+ if (options === void 0) { options = {}; }
101
+ if (!target) {
102
+ target = doc(options).createDocumentFragment();
103
+ }
104
+ var top = target, active = [];
105
+ fragment.forEach(function (node) {
106
+ if (active.length || node.marks.length) {
107
+ var keep = 0, rendered = 0;
108
+ while (keep < active.length && rendered < node.marks.length) {
109
+ var next = node.marks[rendered];
110
+ if (!_this.marks[next.type.name]) {
111
+ rendered++;
112
+ continue;
113
+ }
114
+ if (!next.eq(active[keep][0]) || next.type.spec.spanning === false) {
115
+ break;
116
+ }
117
+ keep++;
118
+ rendered++;
119
+ }
120
+ while (keep < active.length) {
121
+ top = active.pop()[1];
122
+ }
123
+ while (rendered < node.marks.length) {
124
+ var add = node.marks[rendered++];
125
+ var markDOM = _this.serializeMark(add, node.isInline, options);
126
+ if (markDOM) {
127
+ active.push([add, top]);
128
+ top.appendChild(markDOM.dom);
129
+ top = markDOM.contentDOM || markDOM.dom;
130
+ }
131
+ }
132
+ }
133
+ top.appendChild(_this.serializeNodeInner(node, options));
134
+ });
135
+ return target;
136
+ };
137
+ /// Serialize this node to a DOM node. This can be useful when you
138
+ /// need to serialize a part of a document, as opposed to the whole
139
+ /// document. To serialize a whole document, use
140
+ /// [`serializeFragment`](#model.DOMSerializer.serializeFragment) on
141
+ /// its [content](#model.Node.content).
142
+ DOMSerializer.prototype.serializeNode = function (node, options) {
143
+ if (options === void 0) { options = {}; }
144
+ var dom = this.serializeNodeInner(node, options);
145
+ for (var i = node.marks.length - 1; i >= 0; i--) {
146
+ var wrap = this.serializeMark(node.marks[i], node.isInline, options);
147
+ if (wrap) {
148
+ (wrap.contentDOM || wrap.dom).appendChild(dom);
149
+ dom = wrap.dom;
150
+ }
151
+ }
152
+ return dom;
153
+ };
154
+ /// @internal
155
+ DOMSerializer.prototype.serializeMark = function (mark, inline, options) {
156
+ if (options === void 0) { options = {}; }
157
+ var toDOM = this.marks[mark.type.name];
158
+ return toDOM && DOMSerializer.renderSpec(doc(options), toDOM(mark, inline));
159
+ };
160
+ /// @internal
161
+ DOMSerializer.prototype.serializeNodeInner = function (node, options) {
162
+ var _a = DOMSerializer.renderSpec(doc(options), this.nodes[node.type.name](node)), dom = _a.dom, contentDOM = _a.contentDOM;
163
+ if (contentDOM) {
164
+ if (node.isLeaf) {
165
+ throw new RangeError("Content hole not allowed in a leaf node spec");
166
+ }
167
+ this.serializeFragment(node.content, options, contentDOM);
168
+ }
169
+ return dom;
170
+ };
171
+ return DOMSerializer;
172
+ }());
173
+ export { DOMSerializer };
174
+ function gatherToDOM(obj) {
175
+ var result = {};
176
+ for (var name_2 in obj) {
177
+ if (obj[name_2]) {
178
+ var toDOM = obj[name_2].spec.toDOM;
179
+ if (toDOM) {
180
+ result[name_2] = toDOM;
181
+ }
182
+ }
183
+ }
184
+ return result;
185
+ }
186
+ function doc(options) {
187
+ return options.document || window.document;
188
+ }
package/dist/es/main.js CHANGED
@@ -21,6 +21,7 @@ export { convertMsLists } from './listConvert';
21
21
  export { find, findAt, findAll, replace, replaceAll } from './find-replace';
22
22
  export { placeholder } from './plugins/placeholder';
23
23
  export { spacesFix } from './plugins/spaces-fix';
24
+ export { cspFix } from './plugins/csp-fix';
24
25
  export { textHighlight, textHighlightKey } from './plugins/highlight';
25
26
  export { imageResizing, imageResizeKey } from './plugins/image-resize';
26
27
  export { caretColor, caretColorKey } from './plugins/caret-color';
@@ -0,0 +1,51 @@
1
+ import { Plugin, PluginKey } from "prosemirror-state";
2
+ import { setAttribute } from "../utils";
3
+ var setAttributes = function (dom, attrs) {
4
+ for (var attrName in attrs) {
5
+ if (attrName) {
6
+ setAttribute(dom, attrName, attrs[attrName]);
7
+ }
8
+ }
9
+ };
10
+ var CustomNodeView = /** @class */ (function () {
11
+ function CustomNodeView(node, view, nodeName, isLeaf) {
12
+ if (isLeaf === void 0) { isLeaf = false; }
13
+ this.node = node;
14
+ this.view = view;
15
+ this.dom = document.createElement(nodeName);
16
+ setAttributes(this.dom, node.attrs);
17
+ this.contentDOM = !isLeaf ? this.dom : undefined;
18
+ }
19
+ return CustomNodeView;
20
+ }());
21
+ var StyleView = /** @class */ (function () {
22
+ function StyleView(mark, view, _inline) {
23
+ this.mark = mark;
24
+ this.view = view;
25
+ this.dom = document.createElement('span');
26
+ setAttributes(this.dom, mark.attrs);
27
+ this.contentDOM = this.dom;
28
+ }
29
+ return StyleView;
30
+ }());
31
+ export var cspFix = function () {
32
+ return new Plugin({
33
+ key: new PluginKey('csp-fix'),
34
+ props: {
35
+ nodeViews: {
36
+ paragraph: function (node, view) { return new CustomNodeView(node, view, 'p'); },
37
+ div: function (node, view) { return new CustomNodeView(node, view, 'div'); },
38
+ table_wrapper: function (node, view) { return new CustomNodeView(node, view, 'div'); },
39
+ table_caption_external: function (node, view) { return new CustomNodeView(node, view, 'div'); },
40
+ table: function (node, view) { return new CustomNodeView(node, view, 'table'); },
41
+ table_row: function (node, view) { return new CustomNodeView(node, view, 'tr'); },
42
+ table_cell: function (node, view) { return new CustomNodeView(node, view, 'td'); },
43
+ table_header: function (node, view) { return new CustomNodeView(node, view, 'th'); },
44
+ image: function (node, view) { return new CustomNodeView(node, view, 'img', true); }
45
+ },
46
+ markViews: {
47
+ style: function (mark, view, inline) { return new StyleView(mark, view, inline); }
48
+ }
49
+ }
50
+ });
51
+ };
@@ -4,7 +4,8 @@ import { TableMap } from 'prosemirror-tables';
4
4
  import { Decoration, DecorationSet } from 'prosemirror-view';
5
5
  import { colgroupAttr } from '../../config/constants';
6
6
  import { TableView, TableWrapperView } from './table-view';
7
- import { cellIndexes, domCellAround, otherResizeHandle, otherResizing, edgeCell, parseStyle, setNodeStyle, tableColumnResizeKey as key } from './utils';
7
+ import { parseStyle } from './../../utils';
8
+ import { cellIndexes, domCellAround, otherResizeHandle, otherResizing, edgeCell, setNodeStyle, tableColumnResizeKey as key } from './utils';
8
9
  export function columnResizing() {
9
10
  var handleWidth = 5, cellMinWidth = 25;
10
11
  var plugin = new Plugin({
@@ -1,7 +1,8 @@
1
1
  import { Plugin } from 'prosemirror-state';
2
2
  import { TableMap, tableNodeTypes } from 'prosemirror-tables';
3
3
  import { Decoration, DecorationSet } from 'prosemirror-view';
4
- import { cellIndexes, domCellAround, otherResizeHandle, otherResizing, parseStyle, setNodeStyle, tableRowResizeKey as key, edgeCell } from './utils';
4
+ import { cellIndexes, domCellAround, otherResizeHandle, otherResizing, setNodeStyle, tableRowResizeKey as key, edgeCell } from './utils';
5
+ import { parseStyle } from './../../utils';
5
6
  var TableRowView = /** @class */ (function () {
6
7
  function TableRowView() {
7
8
  }
@@ -1,7 +1,8 @@
1
1
  import { __assign } from "tslib";
2
2
  import { NodeSelection, Plugin } from 'prosemirror-state';
3
3
  import { colgroupAttr, dataResizeDirTable, resizableAttr } from '../../config/constants';
4
- import { getTable, parentNode, parseStyle, setNodeStyle, tableResizeKey as key } from './utils';
4
+ import { getTable, parentNode, setNodeStyle, tableResizeKey as key } from './utils';
5
+ import { parseStyle } from './../../utils';
5
6
  import { directions } from './../resize-utils';
6
7
  var commonDir = {
7
8
  'southeast': true,
@@ -1,7 +1,7 @@
1
1
  import { colgroupAttr, dataResizeDirTable, resizableAttr, resizableWrap, resizeHandle } from '../../config/constants';
2
2
  import { parseStrColgroup } from '../../config/schema';
3
3
  import { handles } from './../resize-utils';
4
- import { parseStyle } from './utils';
4
+ import { parseStyle, setAttribute } from './../../utils';
5
5
  var TableView = /** @class */ (function () {
6
6
  function TableView(node, view) {
7
7
  this.node = node;
@@ -72,14 +72,7 @@ var TableView = /** @class */ (function () {
72
72
  var skip = [colgroupAttr, resizableAttr];
73
73
  for (var attrName in attrs) {
74
74
  if (attrName && skip.indexOf(attrName) === -1) {
75
- var current = table.getAttribute(attrName);
76
- var next = attrs[attrName];
77
- if (next && next !== current) {
78
- table.setAttribute(attrName, next);
79
- }
80
- else if (!next) {
81
- table.removeAttribute(attrName);
82
- }
75
+ setAttribute(table, attrName, attrs[attrName]);
83
76
  }
84
77
  }
85
78
  if (/%$/.test(table.style.width)) {
@@ -119,14 +112,7 @@ var TableWrapperView = /** @class */ (function () {
119
112
  TableWrapperView.prototype.setAttributes = function (dom, attrs) {
120
113
  for (var attrName in attrs) {
121
114
  if (attrName) {
122
- var current = dom.getAttribute(attrName);
123
- var next = attrs[attrName];
124
- if (next && next !== current) {
125
- dom.setAttribute(attrName, next);
126
- }
127
- else if (!next) {
128
- dom.removeAttribute(attrName);
129
- }
115
+ setAttribute(dom, attrName, attrs[attrName]);
130
116
  }
131
117
  }
132
118
  dom.setAttribute('table', '');
@@ -3,14 +3,6 @@ import { PluginKey } from 'prosemirror-state';
3
3
  import { TableMap } from 'prosemirror-tables';
4
4
  import { changeStylesString } from '../../utils';
5
5
  export var reAnyValue = /^.+$/;
6
- export var parseStyle = function (styleText) {
7
- var styles = (styleText || '').split(/\s*;\s*/).filter(Boolean).map(function (s) {
8
- var _a;
9
- var nameValue = s.split(/\s*:\s*/);
10
- return _a = {}, _a[nameValue[0]] = nameValue[1], _a;
11
- }).reduce(function (acc, val) { return (__assign(__assign({}, acc), val)); }, {});
12
- return styles;
13
- };
14
6
  export function setNodeStyle(nodeAttrs, styleType, value) {
15
7
  var attrs;
16
8
  if (new RegExp('[^-]?' + styleType + ':').test(nodeAttrs.style || '')) {
package/dist/es/source.js CHANGED
@@ -1,6 +1,7 @@
1
- import { DOMSerializer, DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
1
+ import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
2
2
  import { AllSelection } from 'prosemirror-state';
3
3
  import { rowTypeAttr, colgroupAttr } from './config/constants';
4
+ import { DOMSerializer } from './DOMSerializer';
4
5
  var blockWrappers = [
5
6
  'div', 'ol', 'ul', 'li', 'table', 'tbody', 'thead', 'tfoot', 'caption', 'td', 'th', 'p',
6
7
  'tr', 'col', 'colgroup', 'article', 'main', 'nav', 'header', 'footer', 'aside', 'section'
@@ -128,6 +129,29 @@ export var trimWhitespace = function (html, trimAroundTags) {
128
129
  return html.replace(new RegExp('\\s*(<(?:' + tags + ')(?:\\s[^>]*?)?>)', 'g'), '$1')
129
130
  .replace(new RegExp('(<\\/(?:' + tags + ')(?:\\s[^>]*?)?>)\\s*', 'g'), '$1');
130
131
  };
132
+ var styleAttr = 'data-style';
133
+ var styleReplace = ' ' + styleAttr + '=';
134
+ var reTag = /<[^>]+>/gm;
135
+ var reStyle = /\sstyle=/gm;
136
+ var replacer = function (match) {
137
+ return match.replace(reStyle, styleReplace);
138
+ };
139
+ var replaceStyleAttr = function (html) {
140
+ return html.replace(reTag, replacer);
141
+ };
142
+ var applyStyle = function (styleString, element) {
143
+ return styleString.split(';').filter(function (s) { return s !== ''; }).forEach(function (s) {
144
+ var parts = s.split(':');
145
+ element.style[parts[0].trim()] = parts[1].trim();
146
+ });
147
+ };
148
+ var restoreStyleAttr = function (container) {
149
+ Array.from(container.querySelectorAll('[' + styleAttr + ']')).forEach(function (element) {
150
+ var styleString = element.getAttribute(styleAttr);
151
+ element.removeAttribute(styleAttr);
152
+ applyStyle(styleString, element);
153
+ });
154
+ };
131
155
  /**
132
156
  * Creates a DocumentFragment from the given HTML content.
133
157
  *
@@ -136,21 +160,9 @@ export var trimWhitespace = function (html, trimAroundTags) {
136
160
  */
137
161
  export var htmlToFragment = function (html) {
138
162
  var template = document.createElement('template');
139
- var fragment;
140
- if ('content' in template) {
141
- template.innerHTML = html;
142
- fragment = template.content;
143
- }
144
- else {
145
- // Internet Explorer
146
- var parsedDocument = new DOMParser().parseFromString(html, 'text/html');
147
- fragment = document.createDocumentFragment();
148
- var dom = parsedDocument.body;
149
- while (dom && dom.firstChild) {
150
- fragment.appendChild(dom.firstChild);
151
- }
152
- }
153
- return fragment;
163
+ template.innerHTML = replaceStyleAttr(html);
164
+ restoreStyleAttr(template.content);
165
+ return template.content;
154
166
  };
155
167
  /**
156
168
  * @hidden
@@ -200,9 +212,7 @@ export var parseContent = function (content, schema, parseOptions) {
200
212
  */
201
213
  export var getHtml = function (state) {
202
214
  var fragment = pmDocToFragment(state.doc);
203
- var container = document.createElement('div');
204
- container.appendChild(fragment);
205
- return container.innerHTML;
215
+ return fragmentToHtml(fragment);
206
216
  };
207
217
  /**
208
218
  * Replaces the content of the editor with a new one.
package/dist/es/utils.js CHANGED
@@ -232,3 +232,34 @@ export var expandToWordWrap = function (command, options) {
232
232
  return command(options)(cmdState, cmdDispatch);
233
233
  };
234
234
  };
235
+ export var parseStyle = function (styleText) {
236
+ var styles = (styleText || '').split(/\s*;\s*/).filter(Boolean).map(function (s) {
237
+ var _a;
238
+ var nameValue = s.split(/\s*:\s*/);
239
+ return _a = {}, _a[nameValue[0]] = nameValue[1], _a;
240
+ }).reduce(function (acc, val) { return (__assign(__assign({}, acc), val)); }, {});
241
+ return styles;
242
+ };
243
+ var setStyleAttr = function (element, styleString) {
244
+ var styles = parseStyle(styleString);
245
+ for (var style in styles) {
246
+ if (style && typeof element.style[style] !== 'undefined') {
247
+ element.style[style] = styles[style];
248
+ }
249
+ }
250
+ };
251
+ export var setAttribute = function (node, attrName, value) {
252
+ var current = node.getAttribute(attrName);
253
+ if (value !== undefined && value !== current) {
254
+ if (attrName === 'style') {
255
+ node.removeAttribute(attrName);
256
+ setStyleAttr(node, value);
257
+ }
258
+ else {
259
+ node.setAttribute(attrName, value);
260
+ }
261
+ }
262
+ else if (value === undefined) {
263
+ node.removeAttribute(attrName);
264
+ }
265
+ };
@@ -0,0 +1,181 @@
1
+ import { setAttribute } from "./utils";
2
+ export class DOMSerializer {
3
+ /// Create a serializer. `nodes` should map node names to functions
4
+ /// that take a node and return a description of the corresponding
5
+ /// DOM. `marks` does the same for mark names, but also gets an
6
+ /// argument that tells it whether the mark's content is block or
7
+ /// inline content (for typical use, it'll always be inline). A mark
8
+ /// serializer may be `null` to indicate that marks of that type
9
+ /// should not be serialized.
10
+ constructor(
11
+ /// The node serialization functions.
12
+ nodes,
13
+ /// The mark serialization functions.
14
+ marks) {
15
+ this.nodes = nodes;
16
+ this.marks = marks;
17
+ }
18
+ /// Render an [output spec](#model.DOMOutputSpec) to a DOM node. If
19
+ /// the spec has a hole (zero) in it, `contentDOM` will point at the
20
+ /// node with the hole.
21
+ static renderSpec(docum, structure, xmlNS = null) {
22
+ if (typeof structure === "string") {
23
+ return { dom: docum.createTextNode(structure) };
24
+ }
25
+ if (structure.nodeType != null) {
26
+ return { dom: structure };
27
+ }
28
+ if (structure.dom && structure.dom.nodeType != null) {
29
+ return structure;
30
+ }
31
+ let tagName = structure[0], space = tagName.indexOf(" ");
32
+ if (space > 0) {
33
+ xmlNS = tagName.slice(0, space);
34
+ tagName = tagName.slice(space + 1);
35
+ }
36
+ let contentDOM;
37
+ let dom = (xmlNS ? docum.createElementNS(xmlNS, tagName) : docum.createElement(tagName));
38
+ let attrs = structure[1], start = 1;
39
+ if (attrs && typeof attrs === "object" && attrs.nodeType == null && !Array.isArray(attrs)) {
40
+ start = 2;
41
+ for (let name in attrs) {
42
+ if (attrs[name] != null) {
43
+ space = name.indexOf(" ");
44
+ if (space > 0) {
45
+ dom.setAttributeNS(name.slice(0, space), name.slice(space + 1), attrs[name]);
46
+ }
47
+ else {
48
+ setAttribute(dom, name, attrs[name]);
49
+ }
50
+ }
51
+ }
52
+ }
53
+ for (let i = start; i < structure.length; i++) {
54
+ let child = structure[i];
55
+ if (child === 0) {
56
+ if (i < structure.length - 1 || i > start) {
57
+ throw new RangeError("Content hole must be the only child of its parent node");
58
+ }
59
+ return { dom, contentDOM: dom };
60
+ }
61
+ else {
62
+ let { dom: inner, contentDOM: innerContent } = DOMSerializer.renderSpec(docum, child, xmlNS);
63
+ dom.appendChild(inner);
64
+ if (innerContent) {
65
+ if (contentDOM) {
66
+ throw new RangeError("Multiple content holes");
67
+ }
68
+ contentDOM = innerContent;
69
+ }
70
+ }
71
+ }
72
+ return { dom, contentDOM };
73
+ }
74
+ /// Build a serializer using the [`toDOM`](#model.NodeSpec.toDOM)
75
+ /// properties in a schema's node and mark specs.
76
+ static fromSchema(schema) {
77
+ return schema.cached.domSerializer ||
78
+ (schema.cached.domSerializer = new DOMSerializer(this.nodesFromSchema(schema), this.marksFromSchema(schema)));
79
+ }
80
+ /// Gather the serializers in a schema's node specs into an object.
81
+ /// This can be useful as a base to build a custom serializer from.
82
+ static nodesFromSchema(schema) {
83
+ let result = gatherToDOM(schema.nodes);
84
+ if (!result.text) {
85
+ result.text = node => node.text;
86
+ }
87
+ return result;
88
+ }
89
+ /// Gather the serializers in a schema's mark specs into an object.
90
+ static marksFromSchema(schema) {
91
+ return gatherToDOM(schema.marks);
92
+ }
93
+ /// Serialize the content of this fragment to a DOM fragment. When
94
+ /// not in the browser, the `document` option, containing a DOM
95
+ /// document, should be passed so that the serializer can create
96
+ /// nodes.
97
+ serializeFragment(fragment, options = {}, target) {
98
+ if (!target) {
99
+ target = doc(options).createDocumentFragment();
100
+ }
101
+ let top = target, active = [];
102
+ fragment.forEach(node => {
103
+ if (active.length || node.marks.length) {
104
+ let keep = 0, rendered = 0;
105
+ while (keep < active.length && rendered < node.marks.length) {
106
+ let next = node.marks[rendered];
107
+ if (!this.marks[next.type.name]) {
108
+ rendered++;
109
+ continue;
110
+ }
111
+ if (!next.eq(active[keep][0]) || next.type.spec.spanning === false) {
112
+ break;
113
+ }
114
+ keep++;
115
+ rendered++;
116
+ }
117
+ while (keep < active.length) {
118
+ top = active.pop()[1];
119
+ }
120
+ while (rendered < node.marks.length) {
121
+ let add = node.marks[rendered++];
122
+ let markDOM = this.serializeMark(add, node.isInline, options);
123
+ if (markDOM) {
124
+ active.push([add, top]);
125
+ top.appendChild(markDOM.dom);
126
+ top = markDOM.contentDOM || markDOM.dom;
127
+ }
128
+ }
129
+ }
130
+ top.appendChild(this.serializeNodeInner(node, options));
131
+ });
132
+ return target;
133
+ }
134
+ /// Serialize this node to a DOM node. This can be useful when you
135
+ /// need to serialize a part of a document, as opposed to the whole
136
+ /// document. To serialize a whole document, use
137
+ /// [`serializeFragment`](#model.DOMSerializer.serializeFragment) on
138
+ /// its [content](#model.Node.content).
139
+ serializeNode(node, options = {}) {
140
+ let dom = this.serializeNodeInner(node, options);
141
+ for (let i = node.marks.length - 1; i >= 0; i--) {
142
+ let wrap = this.serializeMark(node.marks[i], node.isInline, options);
143
+ if (wrap) {
144
+ (wrap.contentDOM || wrap.dom).appendChild(dom);
145
+ dom = wrap.dom;
146
+ }
147
+ }
148
+ return dom;
149
+ }
150
+ /// @internal
151
+ serializeMark(mark, inline, options = {}) {
152
+ let toDOM = this.marks[mark.type.name];
153
+ return toDOM && DOMSerializer.renderSpec(doc(options), toDOM(mark, inline));
154
+ }
155
+ /// @internal
156
+ serializeNodeInner(node, options) {
157
+ let { dom, contentDOM } = DOMSerializer.renderSpec(doc(options), this.nodes[node.type.name](node));
158
+ if (contentDOM) {
159
+ if (node.isLeaf) {
160
+ throw new RangeError("Content hole not allowed in a leaf node spec");
161
+ }
162
+ this.serializeFragment(node.content, options, contentDOM);
163
+ }
164
+ return dom;
165
+ }
166
+ }
167
+ function gatherToDOM(obj) {
168
+ let result = {};
169
+ for (let name in obj) {
170
+ if (obj[name]) {
171
+ let toDOM = obj[name].spec.toDOM;
172
+ if (toDOM) {
173
+ result[name] = toDOM;
174
+ }
175
+ }
176
+ }
177
+ return result;
178
+ }
179
+ function doc(options) {
180
+ return options.document || window.document;
181
+ }
@@ -21,6 +21,7 @@ export { convertMsLists } from './listConvert';
21
21
  export { find, findAt, findAll, replace, replaceAll } from './find-replace';
22
22
  export { placeholder } from './plugins/placeholder';
23
23
  export { spacesFix } from './plugins/spaces-fix';
24
+ export { cspFix } from './plugins/csp-fix';
24
25
  export { textHighlight, textHighlightKey } from './plugins/highlight';
25
26
  export { imageResizing, imageResizeKey } from './plugins/image-resize';
26
27
  export { caretColor, caretColorKey } from './plugins/caret-color';