@pie-lib/editable-html-tip-tap 1.0.2 → 1.0.4
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/lib/components/CharacterPicker.js +221 -0
- package/lib/components/CharacterPicker.js.map +1 -0
- package/lib/components/EditableHtml.js +323 -0
- package/lib/components/EditableHtml.js.map +1 -0
- package/lib/components/MenuBar.js +694 -0
- package/lib/components/MenuBar.js.map +1 -0
- package/lib/components/TiptapContainer.js +90 -0
- package/lib/components/TiptapContainer.js.map +1 -0
- package/lib/components/buttons/done-button.js +53 -0
- package/lib/components/characters/characterUtils.js +112 -0
- package/lib/components/characters/characterUtils.js.map +1 -0
- package/lib/components/characters/custom-popper.js +73 -0
- package/lib/components/characters/custom-popper.js.map +1 -0
- package/lib/components/common/done-button.js +53 -0
- package/lib/components/common/done-button.js.map +1 -0
- package/lib/components/common/toolbar-buttons.js +194 -0
- package/lib/components/icons/CssIcon.js +37 -0
- package/lib/components/icons/CssIcon.js.map +1 -0
- package/lib/components/icons/RespArea.js +95 -0
- package/lib/components/icons/RespArea.js.map +1 -0
- package/lib/components/icons/TableIcons.js +69 -0
- package/lib/components/icons/TableIcons.js.map +1 -0
- package/lib/components/icons/TextAlign.js +194 -0
- package/lib/components/icons/TextAlign.js.map +1 -0
- package/lib/components/icons/index.js +194 -0
- package/lib/components/image/AltDialog.js +129 -0
- package/lib/components/image/ImageToolbar.js +177 -0
- package/lib/components/image/ImageToolbar.js.map +1 -0
- package/lib/components/image/InsertImageHandler.js +115 -0
- package/lib/components/image/InsertImageHandler.js.map +1 -0
- package/lib/components/image/alt-dialog.js +2 -0
- package/lib/components/media/MediaDialog.js +709 -0
- package/lib/components/media/MediaDialog.js.map +1 -0
- package/lib/components/media/MediaToolbar.js +101 -0
- package/lib/components/media/MediaToolbar.js.map +1 -0
- package/lib/components/media/MediaWrapper.js +93 -0
- package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js +94 -0
- package/lib/components/respArea/DragInTheBlank/DragInTheBlank.js.map +1 -0
- package/lib/components/respArea/DragInTheBlank/choice.js +289 -0
- package/lib/components/respArea/DragInTheBlank/choice.js.map +1 -0
- package/lib/components/respArea/DragInTheBlank.js +94 -0
- package/lib/components/respArea/ExplicitConstructedResponse.js +120 -0
- package/lib/components/respArea/ExplicitConstructedResponse.js.map +1 -0
- package/lib/components/respArea/InlineDropdown.js +126 -0
- package/lib/components/respArea/InlineDropdown.js.map +1 -0
- package/lib/components/respArea/ToolbarIcon.js +105 -0
- package/lib/components/respArea/ToolbarIcon.js.map +1 -0
- package/lib/components/respArea/choice.js +2 -0
- package/lib/constants.js.map +1 -0
- package/lib/extensions/component.js +5 -5
- package/lib/extensions/component.js.map +1 -0
- package/lib/extensions/css.js.map +1 -0
- package/lib/extensions/custom-toolbar-wrapper.js +2 -4
- package/lib/extensions/custom-toolbar-wrapper.js.map +1 -0
- package/lib/extensions/extended-table.js +30 -0
- package/lib/extensions/extended-table.js.map +1 -0
- package/lib/extensions/image.js +2 -8
- package/lib/extensions/image.js.map +1 -0
- package/lib/extensions/index.js +52 -0
- package/lib/extensions/index.js.map +1 -0
- package/lib/extensions/math.js.map +1 -0
- package/lib/extensions/media.js +7 -7
- package/lib/extensions/media.js.map +1 -0
- package/lib/extensions/responseArea.js +7 -7
- package/lib/extensions/responseArea.js.map +1 -0
- package/lib/index.js +16 -1481
- package/lib/index.js.map +1 -0
- package/lib/plugins/index.js +8 -80
- package/lib/styles/editorContainerStyles.js +200 -0
- package/lib/styles/editorContainerStyles.js.map +1 -0
- package/lib/theme.js.map +1 -0
- package/lib/utils/size.js +34 -0
- package/lib/utils/size.js.map +1 -0
- package/package.json +1 -1
- package/src/components/CharacterPicker.jsx +185 -0
- package/src/components/EditableHtml.jsx +306 -0
- package/src/components/MenuBar.jsx +630 -0
- package/src/components/TiptapContainer.jsx +96 -0
- package/src/components/characters/characterUtils.js +127 -0
- package/src/{plugins/image/image-toolbar.jsx → components/image/ImageToolbar.jsx} +2 -2
- package/src/{plugins/image/insert-image-handler.js → components/image/InsertImageHandler.js} +0 -1
- package/src/{plugins/media/media-dialog.js → components/media/MediaDialog.js} +2 -2
- package/src/{plugins/respArea/drag-in-the-blank → components/respArea/DragInTheBlank}/choice.jsx +1 -1
- package/src/{plugins/respArea/inline-dropdown/index.jsx → components/respArea/InlineDropdown.jsx} +1 -1
- package/src/components/respArea/ToolbarIcon.jsx +68 -0
- package/src/extensions/component.jsx +2 -2
- package/src/extensions/custom-toolbar-wrapper.jsx +6 -7
- package/src/extensions/extended-table.js +27 -0
- package/src/extensions/image.js +2 -2
- package/src/extensions/index.js +76 -0
- package/src/extensions/media.js +12 -7
- package/src/extensions/responseArea.js +7 -7
- package/src/index.jsx +3 -1440
- package/src/styles/editorContainerStyles.js +203 -0
- package/src/utils/size.js +32 -0
- package/src/__tests__/editor.test.jsx +0 -363
- package/src/__tests__/serialization.test.js +0 -291
- package/src/block-tags.js +0 -17
- package/src/editor.jsx +0 -1197
- package/src/extensions/characters.js +0 -46
- package/src/old-index.jsx +0 -162
- package/src/parse-html.js +0 -8
- package/src/plugins/README.md +0 -27
- package/src/plugins/characters/index.jsx +0 -284
- package/src/plugins/characters/utils.js +0 -447
- package/src/plugins/css/index.jsx +0 -340
- package/src/plugins/customPlugin/index.jsx +0 -85
- package/src/plugins/html/icons/index.jsx +0 -19
- package/src/plugins/html/index.jsx +0 -72
- package/src/plugins/image/__tests__/__snapshots__/component.test.jsx.snap +0 -51
- package/src/plugins/image/__tests__/__snapshots__/image-toolbar-logic.test.jsx.snap +0 -27
- package/src/plugins/image/__tests__/__snapshots__/image-toolbar.test.jsx.snap +0 -44
- package/src/plugins/image/__tests__/component.test.jsx +0 -41
- package/src/plugins/image/__tests__/image-toolbar-logic.test.jsx +0 -42
- package/src/plugins/image/__tests__/image-toolbar.test.jsx +0 -11
- package/src/plugins/image/__tests__/index.test.js +0 -95
- package/src/plugins/image/__tests__/insert-image-handler.test.js +0 -113
- package/src/plugins/image/__tests__/mock-change.js +0 -15
- package/src/plugins/image/component.jsx +0 -343
- package/src/plugins/image/index.jsx +0 -227
- package/src/plugins/index.jsx +0 -377
- package/src/plugins/list/__tests__/index.test.js +0 -54
- package/src/plugins/list/index.jsx +0 -305
- package/src/plugins/math/__tests__/__snapshots__/index.test.jsx.snap +0 -48
- package/src/plugins/math/__tests__/index.test.jsx +0 -245
- package/src/plugins/math/index.jsx +0 -379
- package/src/plugins/media/__tests__/index.test.js +0 -75
- package/src/plugins/media/index.jsx +0 -325
- package/src/plugins/rendering/index.js +0 -31
- package/src/plugins/respArea/index.jsx +0 -299
- package/src/plugins/respArea/math-templated/index.jsx +0 -104
- package/src/plugins/respArea/utils.jsx +0 -90
- package/src/plugins/table/CustomTablePlugin.js +0 -113
- package/src/plugins/table/__tests__/__snapshots__/table-toolbar.test.jsx.snap +0 -44
- package/src/plugins/table/__tests__/index.test.jsx +0 -401
- package/src/plugins/table/__tests__/table-toolbar.test.jsx +0 -42
- package/src/plugins/table/index.jsx +0 -427
- package/src/plugins/table/table-toolbar.jsx +0 -136
- package/src/plugins/textAlign/index.jsx +0 -23
- package/src/plugins/toolbar/__tests__/__snapshots__/default-toolbar.test.jsx.snap +0 -923
- package/src/plugins/toolbar/__tests__/__snapshots__/editor-and-toolbar.test.jsx.snap +0 -20
- package/src/plugins/toolbar/__tests__/__snapshots__/toolbar-buttons.test.jsx.snap +0 -36
- package/src/plugins/toolbar/__tests__/__snapshots__/toolbar.test.jsx.snap +0 -46
- package/src/plugins/toolbar/__tests__/default-toolbar.test.jsx +0 -94
- package/src/plugins/toolbar/__tests__/editor-and-toolbar.test.jsx +0 -37
- package/src/plugins/toolbar/__tests__/toolbar-buttons.test.jsx +0 -51
- package/src/plugins/toolbar/__tests__/toolbar.test.jsx +0 -106
- package/src/plugins/toolbar/default-toolbar.jsx +0 -206
- package/src/plugins/toolbar/editor-and-toolbar.jsx +0 -257
- package/src/plugins/toolbar/index.jsx +0 -23
- package/src/plugins/toolbar/toolbar.jsx +0 -338
- package/src/plugins/utils.js +0 -31
- package/src/serialization.jsx +0 -621
- /package/src/{plugins → components}/characters/custom-popper.js +0 -0
- /package/src/{plugins/toolbar → components/common}/done-button.jsx +0 -0
- /package/src/{plugins/toolbar → components/common}/toolbar-buttons.jsx +0 -0
- /package/src/{plugins/css/icons/index.jsx → components/icons/CssIcon.jsx} +0 -0
- /package/src/{plugins/respArea/icons/index.jsx → components/icons/RespArea.jsx} +0 -0
- /package/src/{plugins/table/icons/index.jsx → components/icons/TableIcons.jsx} +0 -0
- /package/src/{plugins/textAlign/icons/index.jsx → components/icons/TextAlign.jsx} +0 -0
- /package/src/{plugins/image/alt-dialog.jsx → components/image/AltDialog.jsx} +0 -0
- /package/src/{plugins/media/media-toolbar.jsx → components/media/MediaToolbar.jsx} +0 -0
- /package/src/{plugins/media/media-wrapper.jsx → components/media/MediaWrapper.jsx} +0 -0
- /package/src/{plugins/respArea/drag-in-the-blank/index.jsx → components/respArea/DragInTheBlank/DragInTheBlank.jsx} +0 -0
- /package/src/{plugins/respArea/explicit-constructed-response/index.jsx → components/respArea/ExplicitConstructedResponse.jsx} +0 -0
package/src/serialization.jsx
DELETED
|
@@ -1,621 +0,0 @@
|
|
|
1
|
-
import Html from 'slate-html-serializer';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import debug from 'debug';
|
|
4
|
-
import { object as toStyleObject } from 'to-style';
|
|
5
|
-
import isEmpty from 'lodash/isEmpty';
|
|
6
|
-
|
|
7
|
-
import { serialization as imgSerialization } from './plugins/image';
|
|
8
|
-
import { serialization as mathSerialization } from './plugins/math';
|
|
9
|
-
import { serialization as mediaSerialization } from './plugins/media';
|
|
10
|
-
import { serialization as listSerialization } from './plugins/list';
|
|
11
|
-
import { serialization as tableSerialization } from './plugins/table';
|
|
12
|
-
import { serialization as responseAreaSerialization } from './plugins/respArea';
|
|
13
|
-
import { Mark, Value } from 'slate';
|
|
14
|
-
import { BLOCK_TAGS } from './block-tags';
|
|
15
|
-
|
|
16
|
-
const log = debug('@pie-lib:editable-html:serialization');
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Tags to marks.
|
|
20
|
-
*
|
|
21
|
-
* @type {Object}
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
const MARK_TAGS = {
|
|
25
|
-
b: 'bold',
|
|
26
|
-
em: 'italic',
|
|
27
|
-
u: 'underline',
|
|
28
|
-
s: 'strikethrough',
|
|
29
|
-
code: 'code',
|
|
30
|
-
strong: 'bold',
|
|
31
|
-
blockquote: 'blockquote',
|
|
32
|
-
h3: 'h3',
|
|
33
|
-
sup: 'sup',
|
|
34
|
-
sub: 'sub',
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const parseStyleString = (s) => {
|
|
38
|
-
const regex = /([\w-]*)\s*:\s*([^;]*)/g;
|
|
39
|
-
let match;
|
|
40
|
-
const result = {};
|
|
41
|
-
while ((match = regex.exec(s))) {
|
|
42
|
-
result[match[1]] = match[2].trim();
|
|
43
|
-
}
|
|
44
|
-
return result;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const getBase64 = (file) => {
|
|
48
|
-
return new Promise((resolve, reject) => {
|
|
49
|
-
const reader = new FileReader();
|
|
50
|
-
reader.readAsDataURL(file);
|
|
51
|
-
reader.onload = () => resolve(reader.result);
|
|
52
|
-
reader.onerror = (error) => reject(error);
|
|
53
|
-
});
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export const reactAttributes = (o) => toStyleObject(o, { camelize: true, addUnits: false });
|
|
57
|
-
|
|
58
|
-
const attributesToMap = (el) => (acc, attribute) => {
|
|
59
|
-
const value = el.getAttribute(attribute);
|
|
60
|
-
if (value) {
|
|
61
|
-
if (attribute === 'style') {
|
|
62
|
-
const styleString = el.getAttribute(attribute);
|
|
63
|
-
const reactStyleObject = reactAttributes(parseStyleString(styleString));
|
|
64
|
-
acc['style'] = reactStyleObject;
|
|
65
|
-
} else {
|
|
66
|
-
acc[attribute] = el.getAttribute(attribute);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return acc;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const attributes = ['border', 'cellpadding', 'cellspacing', 'class', 'style', 'align'];
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Serializer rules.
|
|
76
|
-
*
|
|
77
|
-
* @type {Array}
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
const blocks = {
|
|
81
|
-
deserialize(el, next) {
|
|
82
|
-
log('[blocks:deserialize] block: ', el);
|
|
83
|
-
const block = BLOCK_TAGS[el.tagName.toLowerCase()];
|
|
84
|
-
if (!block) return;
|
|
85
|
-
log('[blocks:deserialize] block: ', block);
|
|
86
|
-
|
|
87
|
-
if (el.childNodes.length === 1) {
|
|
88
|
-
const cn = el.childNodes[0];
|
|
89
|
-
if (cn && cn.tagName && cn.tagName.toLowerCase() === block) {
|
|
90
|
-
log('[we have a child node of the same]...');
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
object: 'block',
|
|
97
|
-
type: block,
|
|
98
|
-
/**
|
|
99
|
-
* Here for rendering styles for all block elements
|
|
100
|
-
*/
|
|
101
|
-
data: { attributes: attributes.reduce(attributesToMap(el), {}) },
|
|
102
|
-
nodes: next(el.childNodes),
|
|
103
|
-
};
|
|
104
|
-
},
|
|
105
|
-
serialize: (object, children) => {
|
|
106
|
-
if (object.object !== 'block') return;
|
|
107
|
-
|
|
108
|
-
const jsonData = object.data.toJSON();
|
|
109
|
-
|
|
110
|
-
log('[blocks:serialize] object: ', object, children);
|
|
111
|
-
let key;
|
|
112
|
-
|
|
113
|
-
for (key in BLOCK_TAGS) {
|
|
114
|
-
if (BLOCK_TAGS[key] === object.type) {
|
|
115
|
-
const Tag = key;
|
|
116
|
-
|
|
117
|
-
return <Tag {...jsonData.attributes}>{children}</Tag>;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
export const INLINE_TAGS = {
|
|
124
|
-
span: 'span',
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const inlines = {
|
|
128
|
-
deserialize(el, next) {
|
|
129
|
-
log('[inlines:deserialize] inline: ', el);
|
|
130
|
-
const inlineTag = INLINE_TAGS[el.tagName.toLowerCase()];
|
|
131
|
-
if (!inlineTag) return;
|
|
132
|
-
log('[inlines:deserialize] inline: ', inlineTag);
|
|
133
|
-
|
|
134
|
-
if (el.childNodes.length === 1) {
|
|
135
|
-
const cn = el.childNodes[0];
|
|
136
|
-
if (cn && cn.tagName && cn.tagName.toLowerCase() === inlineTag) {
|
|
137
|
-
log('[we have a child node of the same]...');
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
object: 'inline',
|
|
144
|
-
type: inlineTag,
|
|
145
|
-
/**
|
|
146
|
-
* Here for rendering styles for all inline elements
|
|
147
|
-
*/
|
|
148
|
-
data: { attributes: attributes.reduce(attributesToMap(el), {}) },
|
|
149
|
-
nodes: next(el.childNodes),
|
|
150
|
-
};
|
|
151
|
-
},
|
|
152
|
-
serialize: (object, children) => {
|
|
153
|
-
if (object.object !== 'inline') return;
|
|
154
|
-
|
|
155
|
-
const jsonData = object.data.toJSON();
|
|
156
|
-
|
|
157
|
-
log('[inlines:serialize] object: ', object, children);
|
|
158
|
-
let key;
|
|
159
|
-
|
|
160
|
-
for (key in INLINE_TAGS) {
|
|
161
|
-
if (INLINE_TAGS[key] === object.type) {
|
|
162
|
-
const Tag = key;
|
|
163
|
-
|
|
164
|
-
return <Tag {...jsonData.attributes}>{children}</Tag>;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
export const extraCSSRulesOpts = {};
|
|
171
|
-
|
|
172
|
-
const STYLES_MAP = {
|
|
173
|
-
h3: {
|
|
174
|
-
fontSize: 'inherit',
|
|
175
|
-
fontWeight: 'inherit',
|
|
176
|
-
},
|
|
177
|
-
blockquote: {
|
|
178
|
-
background: '#f9f9f9',
|
|
179
|
-
borderLeft: '5px solid #ccc',
|
|
180
|
-
margin: '1.5em 10px',
|
|
181
|
-
padding: '.5em 10px',
|
|
182
|
-
},
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const reactToHTMLAttributesMap = {
|
|
186
|
-
class: 'className',
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
const marks = {
|
|
190
|
-
deserialize(el, next) {
|
|
191
|
-
const mark = MARK_TAGS[el.tagName.toLowerCase()];
|
|
192
|
-
const elClasses = el.getAttribute('class') || '';
|
|
193
|
-
const hasCSSRule = (extraCSSRulesOpts?.names || []).find((name) => elClasses?.includes(name));
|
|
194
|
-
|
|
195
|
-
if (!mark && !hasCSSRule) {
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
log('[deserialize] mark: ', mark);
|
|
200
|
-
const attrs = attributes.reduce(attributesToMap(el), {});
|
|
201
|
-
const data = isEmpty(attrs) ? undefined : { attributes: attrs };
|
|
202
|
-
|
|
203
|
-
return {
|
|
204
|
-
object: 'mark',
|
|
205
|
-
type: hasCSSRule ? 'css' : mark,
|
|
206
|
-
/**
|
|
207
|
-
* Here for rendering styles for all elements
|
|
208
|
-
*/
|
|
209
|
-
data,
|
|
210
|
-
nodes: next(el.childNodes),
|
|
211
|
-
};
|
|
212
|
-
},
|
|
213
|
-
serialize(object, children) {
|
|
214
|
-
const jsonData = object.data?.toJSON() || {};
|
|
215
|
-
const elClasses = jsonData.attributes?.class || '';
|
|
216
|
-
const hasCSSRule = (extraCSSRulesOpts?.names || []).find((name) => elClasses?.includes(name));
|
|
217
|
-
|
|
218
|
-
if (hasCSSRule) {
|
|
219
|
-
const htmlAttrs = Object.keys(jsonData.attributes).reduce((obj, key) => {
|
|
220
|
-
obj[reactToHTMLAttributesMap[key] || key] = jsonData.attributes[key];
|
|
221
|
-
return obj;
|
|
222
|
-
}, {});
|
|
223
|
-
|
|
224
|
-
return <span {...htmlAttrs}>{children}</span>;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (Mark.isMark(object)) {
|
|
228
|
-
for (var key in MARK_TAGS) {
|
|
229
|
-
if (MARK_TAGS[key] === object.type) {
|
|
230
|
-
const Tag = key;
|
|
231
|
-
const additionalStyles = STYLES_MAP[Tag];
|
|
232
|
-
|
|
233
|
-
if (additionalStyles) {
|
|
234
|
-
if (!jsonData.attributes) {
|
|
235
|
-
jsonData.attributes = {};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
jsonData.attributes.style = {
|
|
239
|
-
...jsonData.attributes.style,
|
|
240
|
-
...additionalStyles,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return <Tag {...jsonData.attributes}>{children}</Tag>;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
},
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
// eslint-disable-next-line no-unused-vars
|
|
252
|
-
const findPreviousText = (el) => {
|
|
253
|
-
if (el.nodeName === '#text') {
|
|
254
|
-
return el;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if (el.previousSibling) {
|
|
258
|
-
return findPreviousText(el.previousSibling);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return null;
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
export const TEXT_RULE = {
|
|
265
|
-
deserialize(el) {
|
|
266
|
-
/**
|
|
267
|
-
* This needs to be called on the dom element in order to merge the adjacent text nodes together
|
|
268
|
-
* */
|
|
269
|
-
el.normalize();
|
|
270
|
-
|
|
271
|
-
if (el.tagName && el.tagName.toLowerCase() === 'br') {
|
|
272
|
-
return {
|
|
273
|
-
object: 'text',
|
|
274
|
-
leaves: [
|
|
275
|
-
{
|
|
276
|
-
object: 'leaf',
|
|
277
|
-
text: '\n',
|
|
278
|
-
},
|
|
279
|
-
],
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if (el.nodeName === '#text') {
|
|
284
|
-
if (el.nodeValue && el.nodeValue.match(/<!--.*?-->/)) return;
|
|
285
|
-
|
|
286
|
-
log('[text:deserialize] return text object..');
|
|
287
|
-
return {
|
|
288
|
-
object: 'text',
|
|
289
|
-
leaves: [
|
|
290
|
-
{
|
|
291
|
-
object: 'leaf',
|
|
292
|
-
text: el.nodeValue,
|
|
293
|
-
},
|
|
294
|
-
],
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
},
|
|
298
|
-
|
|
299
|
-
serialize(obj, children) {
|
|
300
|
-
if (obj.object === 'string') {
|
|
301
|
-
return children.split('\n').reduce((array, text, i) => {
|
|
302
|
-
if (i !== 0) array.push(<br />);
|
|
303
|
-
array.push(text);
|
|
304
|
-
return array;
|
|
305
|
-
}, []);
|
|
306
|
-
}
|
|
307
|
-
},
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
const RULES = [
|
|
311
|
-
listSerialization,
|
|
312
|
-
mathSerialization,
|
|
313
|
-
mediaSerialization,
|
|
314
|
-
imgSerialization,
|
|
315
|
-
tableSerialization,
|
|
316
|
-
responseAreaSerialization,
|
|
317
|
-
TEXT_RULE,
|
|
318
|
-
inlines,
|
|
319
|
-
blocks,
|
|
320
|
-
marks,
|
|
321
|
-
];
|
|
322
|
-
|
|
323
|
-
function allWhitespace(node) {
|
|
324
|
-
// Use ECMA-262 Edition 3 String and RegExp features
|
|
325
|
-
return !/[^\t\n\r ]/.test(node.textContent);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
function defaultParseHtml(html) {
|
|
329
|
-
if (typeof DOMParser === 'undefined') {
|
|
330
|
-
throw new Error(
|
|
331
|
-
'The native `DOMParser` global which the `Html` serializer uses by default is not present in this environment. You must supply the `options.parseHtml` function instead.',
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
const parsed = new DOMParser().parseFromString(html, 'text/html');
|
|
336
|
-
|
|
337
|
-
const { body } = parsed;
|
|
338
|
-
var textNodes = document.createTreeWalker(body, NodeFilter.SHOW_TEXT, null, null);
|
|
339
|
-
var n = textNodes.nextNode();
|
|
340
|
-
|
|
341
|
-
while (n) {
|
|
342
|
-
const isWhiteSpace = allWhitespace(n);
|
|
343
|
-
const isNotNearMarkup =
|
|
344
|
-
!MARK_TAGS[n.nextSibling?.tagName?.toLowerCase()] && !MARK_TAGS[n.previousSibling?.tagName?.toLowerCase()];
|
|
345
|
-
|
|
346
|
-
if ((isWhiteSpace && isNotNearMarkup) || n.nodeValue === '\u200B') {
|
|
347
|
-
n.parentNode.removeChild(n);
|
|
348
|
-
}
|
|
349
|
-
n = textNodes.nextNode();
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
return body;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
/** If this lib is used on the server side, we need to bypass using the DOMParser - just put in a stub. */
|
|
356
|
-
const parseHtml =
|
|
357
|
-
typeof window === 'undefined'
|
|
358
|
-
? () => ({
|
|
359
|
-
childNodes: [],
|
|
360
|
-
})
|
|
361
|
-
: defaultParseHtml;
|
|
362
|
-
|
|
363
|
-
const serializer = new Html({
|
|
364
|
-
defaultBlock: 'div',
|
|
365
|
-
rules: RULES,
|
|
366
|
-
parseHtml,
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
const _extends =
|
|
370
|
-
Object.assign ||
|
|
371
|
-
function(target) {
|
|
372
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
373
|
-
var source = arguments[i];
|
|
374
|
-
|
|
375
|
-
for (var key in source) {
|
|
376
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
377
|
-
target[key] = source[key];
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
return target;
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* This is needed in order to override the function that eventually leads
|
|
387
|
-
* to the max iteration of 12, which in most cases it's not enough. The newer versions
|
|
388
|
-
* have a different way to calculate this, but updating to a newer version of slate
|
|
389
|
-
* requires a lot of work fixing other issues. So we just increase the rules by 1000,
|
|
390
|
-
* which means a lot of iterations.
|
|
391
|
-
* Below is the code that calculates the max iterations.
|
|
392
|
-
* var max = schema.stack.plugins.length + schema.rules.length + 1;
|
|
393
|
-
*/
|
|
394
|
-
serializer.deserialize = function deserialize(html) {
|
|
395
|
-
const options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
396
|
-
const _options$toJSON = options.toJSON;
|
|
397
|
-
const toJSON = _options$toJSON === undefined ? false : _options$toJSON;
|
|
398
|
-
const defaultBlock = this.defaultBlock;
|
|
399
|
-
const parseHtml = this.parseHtml;
|
|
400
|
-
|
|
401
|
-
const fragment = parseHtml(html);
|
|
402
|
-
const children = Array.from(fragment.childNodes);
|
|
403
|
-
let nodes = this.deserializeElements(children);
|
|
404
|
-
|
|
405
|
-
// COMPAT: ensure that all top-level inline nodes are wrapped into a block.
|
|
406
|
-
nodes = nodes.reduce(function(memo, node, i, original) {
|
|
407
|
-
if (node.object === 'block') {
|
|
408
|
-
memo.push(node);
|
|
409
|
-
return memo;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
if (i > 0 && original[i - 1].object !== 'block') {
|
|
413
|
-
const _block = memo[memo.length - 1];
|
|
414
|
-
|
|
415
|
-
_block.nodes.push(node);
|
|
416
|
-
return memo;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
const block = _extends({ object: 'block', data: {}, isVoid: false }, defaultBlock, {
|
|
420
|
-
nodes: [node],
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
memo.push(block);
|
|
424
|
-
return memo;
|
|
425
|
-
}, []);
|
|
426
|
-
|
|
427
|
-
if (nodes.length === 0) {
|
|
428
|
-
nodes = [
|
|
429
|
-
_extends({ object: 'block', data: {}, isVoid: false }, defaultBlock, {
|
|
430
|
-
nodes: [{ object: 'text', leaves: [{ object: 'leaf', text: '', marks: [] }] }],
|
|
431
|
-
}),
|
|
432
|
-
];
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
const json = {
|
|
436
|
-
object: 'value',
|
|
437
|
-
document: {
|
|
438
|
-
object: 'document',
|
|
439
|
-
data: {},
|
|
440
|
-
nodes: nodes,
|
|
441
|
-
},
|
|
442
|
-
schema: {
|
|
443
|
-
rules: [],
|
|
444
|
-
},
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
let i;
|
|
448
|
-
|
|
449
|
-
for (i = 0; i < 3000; i++) {
|
|
450
|
-
json.schema.rules.push({
|
|
451
|
-
match: { object: 'document' },
|
|
452
|
-
nodes: [{ match: { object: 'block' } }],
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
const ret = toJSON ? json : Value.fromJSON(json);
|
|
457
|
-
|
|
458
|
-
if (ret) {
|
|
459
|
-
return ret;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
return null;
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
export const reduceMultipleBrs = (markup) => {
|
|
466
|
-
try {
|
|
467
|
-
return markup.replace(/(<br\s*\/?>){3,}/gi, '<br>');
|
|
468
|
-
} catch (e) {
|
|
469
|
-
// eslint-disable-next-line no-console
|
|
470
|
-
console.log("Couldn't remove <br/> tags: ", e);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
return markup;
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
const reduceRedundantNewLineCharacters = (markup) => {
|
|
477
|
-
try {
|
|
478
|
-
return markup.replace(/\n/gi, '');
|
|
479
|
-
} catch (e) {
|
|
480
|
-
// eslint-disable-next-line no-console
|
|
481
|
-
console.log("Couldn't remove <br/> tags: ", e);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return markup;
|
|
485
|
-
};
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* Makes sure that the html provided respects the schema
|
|
489
|
-
* rules for the slate editor.
|
|
490
|
-
* @param markup
|
|
491
|
-
* @returns {string}
|
|
492
|
-
*/
|
|
493
|
-
const fixHtmlCode = (markup) => {
|
|
494
|
-
const wrapperEl = document.createElement('div');
|
|
495
|
-
|
|
496
|
-
wrapperEl.innerHTML = markup;
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* DIV elements that are at the same level as paragraphs
|
|
500
|
-
* are replaced with P elements for normalizing purposes
|
|
501
|
-
* @param child
|
|
502
|
-
*/
|
|
503
|
-
const fixParagraphs = (child) => {
|
|
504
|
-
const p = document.createElement('p');
|
|
505
|
-
|
|
506
|
-
p.innerHTML = child.innerHTML;
|
|
507
|
-
|
|
508
|
-
Array.from(child.attributes).forEach((attr) => {
|
|
509
|
-
p.setAttribute(attr.name, attr.value);
|
|
510
|
-
});
|
|
511
|
-
child.replaceWith(p);
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
/**
|
|
515
|
-
* @summary Makes sure that tables are placed in the root document.
|
|
516
|
-
* @description This function removes the tables from the nodes that are
|
|
517
|
-
* placed inside the root element and places them exactly near
|
|
518
|
-
* the parent element.
|
|
519
|
-
* @param tableArray
|
|
520
|
-
*/
|
|
521
|
-
const fixTables = (tableArray) => {
|
|
522
|
-
tableArray.forEach((el) => {
|
|
523
|
-
const { index, child, parent } = el;
|
|
524
|
-
const nodesBefore = [];
|
|
525
|
-
const nodesAfter = [];
|
|
526
|
-
const allNodes = Array.from(parent.childNodes);
|
|
527
|
-
let i;
|
|
528
|
-
|
|
529
|
-
for (i = 0; i < allNodes.length; i++) {
|
|
530
|
-
const node = allNodes[i];
|
|
531
|
-
|
|
532
|
-
if (i < index) {
|
|
533
|
-
nodesBefore.push(node);
|
|
534
|
-
} else if (i > index) {
|
|
535
|
-
nodesAfter.push(node);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
// creating the element that is going to be placed instead of the parent
|
|
540
|
-
const beforeEl = document.createElement(parent.nodeName);
|
|
541
|
-
|
|
542
|
-
beforeEl.append(...nodesBefore);
|
|
543
|
-
|
|
544
|
-
// replacing parent with the beforeElement
|
|
545
|
-
parent.replaceWith(beforeEl);
|
|
546
|
-
|
|
547
|
-
// adding the table right after the before element
|
|
548
|
-
beforeEl.after(child);
|
|
549
|
-
|
|
550
|
-
// creating the element that is going to be placed after the table
|
|
551
|
-
const afterEl = document.createElement(parent.nodeName);
|
|
552
|
-
|
|
553
|
-
afterEl.append(...nodesAfter);
|
|
554
|
-
|
|
555
|
-
// adding the after element near the table
|
|
556
|
-
child.after(afterEl);
|
|
557
|
-
});
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
const emptyBlockCheck = (node) =>
|
|
561
|
-
(node.nodeName === 'DIV' || node.nodeName === 'P' || node.nodeName === 'LI') && node.childNodes.length === 0;
|
|
562
|
-
|
|
563
|
-
const parseNode = (el) => {
|
|
564
|
-
const childArray = Array.from(el.childNodes);
|
|
565
|
-
const hasParagraphs = childArray.find((child) => child.nodeName === 'P');
|
|
566
|
-
const tables = [];
|
|
567
|
-
|
|
568
|
-
childArray.forEach((child, index) => {
|
|
569
|
-
// removing empty blocks
|
|
570
|
-
if (emptyBlockCheck(child)) {
|
|
571
|
-
child.remove();
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
if (hasParagraphs && child.nodeName === 'DIV') {
|
|
576
|
-
fixParagraphs(child);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
if (wrapperEl !== el && child.nodeName === 'TABLE') {
|
|
580
|
-
// we don't need to fix tables in the root element
|
|
581
|
-
tables.push({
|
|
582
|
-
index,
|
|
583
|
-
child,
|
|
584
|
-
parent: el,
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
parseNode(child);
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
if (tables.length) {
|
|
592
|
-
fixTables(tables);
|
|
593
|
-
}
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
parseNode(wrapperEl);
|
|
597
|
-
|
|
598
|
-
return wrapperEl.innerHTML;
|
|
599
|
-
};
|
|
600
|
-
|
|
601
|
-
export const handleHtml = (html) => fixHtmlCode(reduceRedundantNewLineCharacters(reduceMultipleBrs(html)));
|
|
602
|
-
|
|
603
|
-
export const htmlToValue = (html) => {
|
|
604
|
-
try {
|
|
605
|
-
return serializer.deserialize(handleHtml(html));
|
|
606
|
-
} catch (e) {
|
|
607
|
-
// eslint-disable-next-line no-console
|
|
608
|
-
console.log("Couldn't parse html: ", e);
|
|
609
|
-
return {};
|
|
610
|
-
}
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
export const valueToHtml = (value) => serializer.serialize(value);
|
|
614
|
-
|
|
615
|
-
/**
|
|
616
|
-
*
|
|
617
|
-
* <div><div>a</div></div> -> <div>a</div>
|
|
618
|
-
*
|
|
619
|
-
* <div><div>a</div><div>b</div></div> -> <div>a</div><div>b</div>
|
|
620
|
-
* <div><div>a</div>4444<div>b</div></div> -> <div>a</div>4444<div>b</div>
|
|
621
|
-
*/
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|