@20minutes/draft-convert 3.0.0 → 3.0.1
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/README.md +29 -0
- package/dist/draft-convert.js +440 -0
- package/dist/draft-convert.min.js +1 -0
- package/esm/blockEntities.js +67 -0
- package/esm/blockInlineStyles.js +98 -0
- package/esm/convertFromHTML.js +537 -0
- package/esm/convertToHTML.js +107 -0
- package/esm/default/defaultBlockHTML.js +31 -0
- package/esm/default/defaultInlineHTML.js +18 -0
- package/esm/encodeBlock.js +44 -0
- package/esm/index.js +4 -0
- package/esm/util/accumulateFunction.js +9 -0
- package/esm/util/blockTypeObjectFunction.js +9 -0
- package/esm/util/getBlockTags.js +27 -0
- package/esm/util/getElementHTML.js +36 -0
- package/esm/util/getElementTagLength.js +20 -0
- package/esm/util/getNestedBlockTags.js +29 -0
- package/esm/util/parseHTML.js +18 -0
- package/esm/util/rangeSort.js +6 -0
- package/esm/util/splitReactElement.js +18 -0
- package/esm/util/styleObjectFunction.js +8 -0
- package/esm/util/updateMutation.js +48 -0
- package/lib/blockEntities.js +74 -0
- package/lib/blockInlineStyles.js +105 -0
- package/lib/convertFromHTML.js +544 -0
- package/lib/convertToHTML.js +114 -0
- package/lib/default/defaultBlockHTML.js +37 -0
- package/lib/default/defaultInlineHTML.js +25 -0
- package/lib/encodeBlock.js +51 -0
- package/lib/index.js +27 -0
- package/lib/util/accumulateFunction.js +15 -0
- package/lib/util/blockTypeObjectFunction.js +15 -0
- package/lib/util/getBlockTags.js +34 -0
- package/lib/util/getElementHTML.js +43 -0
- package/lib/util/getElementTagLength.js +27 -0
- package/lib/util/getNestedBlockTags.js +36 -0
- package/lib/util/parseHTML.js +24 -0
- package/lib/util/rangeSort.js +12 -0
- package/lib/util/splitReactElement.js +24 -0
- package/lib/util/styleObjectFunction.js +14 -0
- package/lib/util/updateMutation.js +55 -0
- package/package.json +1 -1
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports["default"] = void 0;
|
|
8
|
+
var _immutable = require("immutable");
|
|
9
|
+
var _draftJs = require("draft-js");
|
|
10
|
+
var _parseHTML = _interopRequireDefault(require("./util/parseHTML"));
|
|
11
|
+
var _rangeSort = _interopRequireDefault(require("./util/rangeSort"));
|
|
12
|
+
/**
|
|
13
|
+
* Copyright (c) 2013-present, Facebook, Inc.
|
|
14
|
+
* All rights reserved.
|
|
15
|
+
*
|
|
16
|
+
* Copyright (c) 2013-present, Facebook, Inc.
|
|
17
|
+
* All rights reserved.
|
|
18
|
+
*
|
|
19
|
+
* This source code is licensed under the BSD-style license found in the
|
|
20
|
+
* LICENSE file in the /src directory of this source tree. An additional grant
|
|
21
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
var SPACE = ' ';
|
|
25
|
+
|
|
26
|
+
// Arbitrary max indent
|
|
27
|
+
var MAX_DEPTH = 4;
|
|
28
|
+
|
|
29
|
+
// used for replacing characters in HTML
|
|
30
|
+
var REGEX_CR = /\r/g;
|
|
31
|
+
var REGEX_LF = /\n/g;
|
|
32
|
+
var REGEX_NBSP = / /g;
|
|
33
|
+
var REGEX_BLOCK_DELIMITER = /\r/g;
|
|
34
|
+
|
|
35
|
+
// Block tag flow is different because LIs do not have
|
|
36
|
+
// a deterministic style ;_;
|
|
37
|
+
var blockTags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'blockquote', 'pre'];
|
|
38
|
+
var inlineTags = {
|
|
39
|
+
b: 'BOLD',
|
|
40
|
+
code: 'CODE',
|
|
41
|
+
del: 'STRIKETHROUGH',
|
|
42
|
+
em: 'ITALIC',
|
|
43
|
+
i: 'ITALIC',
|
|
44
|
+
s: 'STRIKETHROUGH',
|
|
45
|
+
strike: 'STRIKETHROUGH',
|
|
46
|
+
strong: 'BOLD',
|
|
47
|
+
u: 'UNDERLINE'
|
|
48
|
+
};
|
|
49
|
+
var handleMiddleware = function handleMiddleware(maybeMiddleware, base) {
|
|
50
|
+
if (maybeMiddleware && maybeMiddleware.__isMiddleware === true) {
|
|
51
|
+
return maybeMiddleware(base);
|
|
52
|
+
}
|
|
53
|
+
return maybeMiddleware;
|
|
54
|
+
};
|
|
55
|
+
var defaultHTMLToBlock = function defaultHTMLToBlock(nodeName, node, lastList) {
|
|
56
|
+
return undefined;
|
|
57
|
+
};
|
|
58
|
+
var defaultHTMLToStyle = function defaultHTMLToStyle(nodeName, node, currentStyle) {
|
|
59
|
+
return currentStyle;
|
|
60
|
+
};
|
|
61
|
+
var defaultHTMLToEntity = function defaultHTMLToEntity(nodeName, node) {
|
|
62
|
+
return undefined;
|
|
63
|
+
};
|
|
64
|
+
var defaultTextToEntity = function defaultTextToEntity(text) {
|
|
65
|
+
return [];
|
|
66
|
+
};
|
|
67
|
+
var nullthrows = function nullthrows(x) {
|
|
68
|
+
if (x != null) {
|
|
69
|
+
return x;
|
|
70
|
+
}
|
|
71
|
+
throw new Error('Got unexpected null or undefined');
|
|
72
|
+
};
|
|
73
|
+
var sanitizeDraftText = function sanitizeDraftText(input) {
|
|
74
|
+
return input.replace(REGEX_BLOCK_DELIMITER, '');
|
|
75
|
+
};
|
|
76
|
+
function getEmptyChunk() {
|
|
77
|
+
return {
|
|
78
|
+
text: '',
|
|
79
|
+
inlines: [],
|
|
80
|
+
entities: [],
|
|
81
|
+
blocks: []
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function getWhitespaceChunk(inEntity) {
|
|
85
|
+
var entities = new Array(1);
|
|
86
|
+
if (inEntity) {
|
|
87
|
+
entities[0] = inEntity;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
text: SPACE,
|
|
91
|
+
inlines: [(0, _immutable.OrderedSet)()],
|
|
92
|
+
entities: entities,
|
|
93
|
+
blocks: []
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function getSoftNewlineChunk(block, depth) {
|
|
97
|
+
var flat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
98
|
+
var data = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : (0, _immutable.Map)();
|
|
99
|
+
if (flat === true) {
|
|
100
|
+
return {
|
|
101
|
+
text: '\r',
|
|
102
|
+
inlines: [(0, _immutable.OrderedSet)()],
|
|
103
|
+
entities: new Array(1),
|
|
104
|
+
blocks: [{
|
|
105
|
+
type: block,
|
|
106
|
+
data: data,
|
|
107
|
+
depth: Math.max(0, Math.min(MAX_DEPTH, depth))
|
|
108
|
+
}],
|
|
109
|
+
isNewline: true
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
text: '\n',
|
|
114
|
+
inlines: [(0, _immutable.OrderedSet)()],
|
|
115
|
+
entities: new Array(1),
|
|
116
|
+
blocks: []
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function getBlockDividerChunk(block, depth) {
|
|
120
|
+
var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : (0, _immutable.Map)();
|
|
121
|
+
return {
|
|
122
|
+
text: '\r',
|
|
123
|
+
inlines: [(0, _immutable.OrderedSet)()],
|
|
124
|
+
entities: new Array(1),
|
|
125
|
+
blocks: [{
|
|
126
|
+
type: block,
|
|
127
|
+
data: data,
|
|
128
|
+
depth: Math.max(0, Math.min(MAX_DEPTH, depth))
|
|
129
|
+
}]
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function getBlockTypeForTag(tag, lastList) {
|
|
133
|
+
switch (tag) {
|
|
134
|
+
case 'h1':
|
|
135
|
+
return 'header-one';
|
|
136
|
+
case 'h2':
|
|
137
|
+
return 'header-two';
|
|
138
|
+
case 'h3':
|
|
139
|
+
return 'header-three';
|
|
140
|
+
case 'h4':
|
|
141
|
+
return 'header-four';
|
|
142
|
+
case 'h5':
|
|
143
|
+
return 'header-five';
|
|
144
|
+
case 'h6':
|
|
145
|
+
return 'header-six';
|
|
146
|
+
case 'li':
|
|
147
|
+
if (lastList === 'ol') {
|
|
148
|
+
return 'ordered-list-item';
|
|
149
|
+
}
|
|
150
|
+
return 'unordered-list-item';
|
|
151
|
+
case 'blockquote':
|
|
152
|
+
return 'blockquote';
|
|
153
|
+
case 'pre':
|
|
154
|
+
return 'code-block';
|
|
155
|
+
case 'div':
|
|
156
|
+
case 'p':
|
|
157
|
+
return 'unstyled';
|
|
158
|
+
default:
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function baseCheckBlockType(nodeName, node, lastList) {
|
|
163
|
+
return getBlockTypeForTag(nodeName, lastList);
|
|
164
|
+
}
|
|
165
|
+
function processInlineTag(tag, node, currentStyle) {
|
|
166
|
+
var styleToCheck = inlineTags[tag];
|
|
167
|
+
if (styleToCheck) {
|
|
168
|
+
currentStyle = currentStyle.add(styleToCheck).toOrderedSet();
|
|
169
|
+
} else if (node instanceof HTMLElement) {
|
|
170
|
+
var htmlElement = node;
|
|
171
|
+
currentStyle = currentStyle.withMutations(function (style) {
|
|
172
|
+
if (htmlElement.style.fontWeight === 'bold') {
|
|
173
|
+
style.add('BOLD');
|
|
174
|
+
}
|
|
175
|
+
if (htmlElement.style.fontStyle === 'italic') {
|
|
176
|
+
style.add('ITALIC');
|
|
177
|
+
}
|
|
178
|
+
if (htmlElement.style.textDecoration === 'underline') {
|
|
179
|
+
style.add('UNDERLINE');
|
|
180
|
+
}
|
|
181
|
+
if (htmlElement.style.textDecoration === 'line-through') {
|
|
182
|
+
style.add('STRIKETHROUGH');
|
|
183
|
+
}
|
|
184
|
+
}).toOrderedSet();
|
|
185
|
+
}
|
|
186
|
+
return currentStyle;
|
|
187
|
+
}
|
|
188
|
+
function baseProcessInlineTag(tag, node) {
|
|
189
|
+
var inlineStyles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : (0, _immutable.OrderedSet)();
|
|
190
|
+
return processInlineTag(tag, node, inlineStyles);
|
|
191
|
+
}
|
|
192
|
+
function joinChunks(A, B) {
|
|
193
|
+
var flat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
194
|
+
// Sometimes two blocks will touch in the DOM and we need to strip the
|
|
195
|
+
// extra delimiter to preserve niceness.
|
|
196
|
+
var firstInB = B.text.slice(0, 1);
|
|
197
|
+
var lastInA = A.text.slice(-1);
|
|
198
|
+
var adjacentDividers = lastInA === '\r' && firstInB === '\r';
|
|
199
|
+
var isJoiningBlocks = A.text !== '\r' && B.text !== '\r'; // when joining two full blocks like this we want to pop one divider
|
|
200
|
+
var addingNewlineToEmptyBlock = A.text === '\r' && !A.isNewline && B.isNewline; // when joining a newline to an empty block we want to remove the newline
|
|
201
|
+
|
|
202
|
+
if (adjacentDividers && (isJoiningBlocks || addingNewlineToEmptyBlock)) {
|
|
203
|
+
A.text = A.text.slice(0, -1);
|
|
204
|
+
A.inlines.pop();
|
|
205
|
+
A.entities.pop();
|
|
206
|
+
A.blocks.pop();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Kill whitespace after blocks if flat mode is on
|
|
210
|
+
if (A.text.slice(-1) === '\r' && flat === true) {
|
|
211
|
+
if (B.text === SPACE || B.text === '\n') {
|
|
212
|
+
return A;
|
|
213
|
+
}
|
|
214
|
+
if (firstInB === SPACE || firstInB === '\n') {
|
|
215
|
+
B.text = B.text.slice(1);
|
|
216
|
+
B.inlines.shift();
|
|
217
|
+
B.entities.shift();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
var isNewline = A.text.length === 0 && B.isNewline;
|
|
221
|
+
return {
|
|
222
|
+
text: A.text + B.text,
|
|
223
|
+
inlines: A.inlines.concat(B.inlines),
|
|
224
|
+
entities: A.entities.concat(B.entities),
|
|
225
|
+
blocks: A.blocks.concat(B.blocks),
|
|
226
|
+
isNewline: isNewline
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/*
|
|
231
|
+
* Check to see if we have anything like <p> <blockquote> <h1>... to create
|
|
232
|
+
* block tags from. If we do, we can use those and ignore <div> tags. If we
|
|
233
|
+
* don't, we can treat <div> tags as meaningful (unstyled) blocks.
|
|
234
|
+
*/
|
|
235
|
+
function containsSemanticBlockMarkup(html) {
|
|
236
|
+
return blockTags.some(function (tag) {
|
|
237
|
+
return html.indexOf("<".concat(tag)) !== -1;
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function genFragment(node, inlineStyle, lastList, inBlock, fragmentBlockTags, depth, processCustomInlineStyles, checkEntityNode, checkEntityText, checkBlockType, createEntity, getEntity, mergeEntityData, replaceEntityData, options, inEntity) {
|
|
241
|
+
var nodeName = node.nodeName.toLowerCase();
|
|
242
|
+
var newBlock = false;
|
|
243
|
+
var nextBlockType = 'unstyled';
|
|
244
|
+
|
|
245
|
+
// Base Case
|
|
246
|
+
if (nodeName === '#text') {
|
|
247
|
+
var text = node.textContent;
|
|
248
|
+
if (text.trim() === '' && inBlock === null) {
|
|
249
|
+
return getEmptyChunk();
|
|
250
|
+
}
|
|
251
|
+
if (text.trim() === '' && inBlock !== 'code-block') {
|
|
252
|
+
return getWhitespaceChunk(inEntity);
|
|
253
|
+
}
|
|
254
|
+
if (inBlock !== 'code-block') {
|
|
255
|
+
// Can't use empty string because MSWord
|
|
256
|
+
text = text.replace(REGEX_LF, SPACE);
|
|
257
|
+
}
|
|
258
|
+
var entities = Array(text.length).fill(inEntity);
|
|
259
|
+
var offsetChange = 0;
|
|
260
|
+
var textEntities = checkEntityText(text, createEntity, getEntity, mergeEntityData, replaceEntityData).sort(_rangeSort["default"]);
|
|
261
|
+
textEntities.forEach(function (_ref) {
|
|
262
|
+
var entity = _ref.entity,
|
|
263
|
+
offset = _ref.offset,
|
|
264
|
+
length = _ref.length,
|
|
265
|
+
result = _ref.result;
|
|
266
|
+
var adjustedOffset = offset + offsetChange;
|
|
267
|
+
if (result === null || result === undefined) {
|
|
268
|
+
result = text.substr(adjustedOffset, length);
|
|
269
|
+
}
|
|
270
|
+
var textArray = text.split('');
|
|
271
|
+
textArray.splice.bind(textArray, adjustedOffset, length).apply(textArray, result.split(''));
|
|
272
|
+
text = textArray.join('');
|
|
273
|
+
entities.splice.bind(entities, adjustedOffset, length).apply(entities, Array(result.length).fill(entity));
|
|
274
|
+
offsetChange += result.length - length;
|
|
275
|
+
});
|
|
276
|
+
return {
|
|
277
|
+
text: text,
|
|
278
|
+
inlines: Array(text.length).fill(inlineStyle),
|
|
279
|
+
entities: entities,
|
|
280
|
+
blocks: []
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// BR tags
|
|
285
|
+
if (nodeName === 'br') {
|
|
286
|
+
var _blockType = inBlock;
|
|
287
|
+
if (_blockType === null) {
|
|
288
|
+
// BR tag is at top level, treat it as an unstyled block
|
|
289
|
+
return getSoftNewlineChunk('unstyled', depth, true);
|
|
290
|
+
}
|
|
291
|
+
return getSoftNewlineChunk(_blockType || 'unstyled', depth, options.flat);
|
|
292
|
+
}
|
|
293
|
+
var chunk = getEmptyChunk();
|
|
294
|
+
var newChunk = null;
|
|
295
|
+
|
|
296
|
+
// Inline tags
|
|
297
|
+
inlineStyle = processInlineTag(nodeName, node, inlineStyle);
|
|
298
|
+
inlineStyle = processCustomInlineStyles(nodeName, node, inlineStyle);
|
|
299
|
+
|
|
300
|
+
// Handle lists
|
|
301
|
+
if (nodeName === 'ul' || nodeName === 'ol') {
|
|
302
|
+
if (lastList) {
|
|
303
|
+
depth += 1;
|
|
304
|
+
}
|
|
305
|
+
lastList = nodeName;
|
|
306
|
+
inBlock = null;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Block Tags
|
|
310
|
+
var blockInfo = checkBlockType(nodeName, node, lastList, inBlock);
|
|
311
|
+
var blockType;
|
|
312
|
+
var blockDataMap;
|
|
313
|
+
if (blockInfo === false) {
|
|
314
|
+
return getEmptyChunk();
|
|
315
|
+
}
|
|
316
|
+
blockInfo = blockInfo || {};
|
|
317
|
+
if (typeof blockInfo === 'string') {
|
|
318
|
+
blockType = blockInfo;
|
|
319
|
+
blockDataMap = (0, _immutable.Map)();
|
|
320
|
+
} else {
|
|
321
|
+
blockType = typeof blockInfo === 'string' ? blockInfo : blockInfo.type;
|
|
322
|
+
blockDataMap = blockInfo.data ? (0, _immutable.Map)(blockInfo.data) : (0, _immutable.Map)();
|
|
323
|
+
}
|
|
324
|
+
if (!inBlock && (fragmentBlockTags.indexOf(nodeName) !== -1 || blockType)) {
|
|
325
|
+
chunk = getBlockDividerChunk(blockType || getBlockTypeForTag(nodeName, lastList), depth, blockDataMap);
|
|
326
|
+
inBlock = blockType || getBlockTypeForTag(nodeName, lastList);
|
|
327
|
+
newBlock = true;
|
|
328
|
+
} else if (lastList && (inBlock === 'ordered-list-item' || inBlock === 'unordered-list-item') && nodeName === 'li') {
|
|
329
|
+
var listItemBlockType = getBlockTypeForTag(nodeName, lastList);
|
|
330
|
+
chunk = getBlockDividerChunk(listItemBlockType, depth);
|
|
331
|
+
inBlock = listItemBlockType;
|
|
332
|
+
newBlock = true;
|
|
333
|
+
nextBlockType = lastList === 'ul' ? 'unordered-list-item' : 'ordered-list-item';
|
|
334
|
+
} else if (inBlock && inBlock !== 'atomic' && blockType === 'atomic') {
|
|
335
|
+
inBlock = blockType;
|
|
336
|
+
newBlock = true;
|
|
337
|
+
chunk = getSoftNewlineChunk(blockType, depth, true,
|
|
338
|
+
// atomic blocks within non-atomic blocks must always be split out
|
|
339
|
+
blockDataMap);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Recurse through children
|
|
343
|
+
var child = node.firstChild;
|
|
344
|
+
|
|
345
|
+
// hack to allow conversion of atomic blocks from HTML (e.g. <figure><img
|
|
346
|
+
// src="..." /></figure>). since metadata must be stored on an entity text
|
|
347
|
+
// must exist for the entity to apply to. the way chunks are joined strips
|
|
348
|
+
// whitespace at the end so it cannot be a space character.
|
|
349
|
+
|
|
350
|
+
if (child == null && inEntity && (blockType === 'atomic' || inBlock === 'atomic')) {
|
|
351
|
+
child = document.createTextNode('a');
|
|
352
|
+
}
|
|
353
|
+
if (child != null) {
|
|
354
|
+
nodeName = child.nodeName.toLowerCase();
|
|
355
|
+
}
|
|
356
|
+
var entityId = null;
|
|
357
|
+
while (child) {
|
|
358
|
+
entityId = checkEntityNode(nodeName, child, createEntity, getEntity, mergeEntityData, replaceEntityData);
|
|
359
|
+
newChunk = genFragment(child, inlineStyle, lastList, inBlock, fragmentBlockTags, depth, processCustomInlineStyles, checkEntityNode, checkEntityText, checkBlockType, createEntity, getEntity, mergeEntityData, replaceEntityData, options, entityId || inEntity);
|
|
360
|
+
chunk = joinChunks(chunk, newChunk, options.flat);
|
|
361
|
+
var sibling = child.nextSibling;
|
|
362
|
+
|
|
363
|
+
// Put in a newline to break up blocks inside blocks
|
|
364
|
+
if (sibling && fragmentBlockTags.indexOf(nodeName) >= 0 && inBlock) {
|
|
365
|
+
var newBlockInfo = checkBlockType(nodeName, child, lastList, inBlock);
|
|
366
|
+
var newBlockType = void 0;
|
|
367
|
+
var newBlockData = void 0;
|
|
368
|
+
if (newBlockInfo !== false) {
|
|
369
|
+
newBlockInfo = newBlockInfo || {};
|
|
370
|
+
if (typeof newBlockInfo === 'string') {
|
|
371
|
+
newBlockType = newBlockInfo;
|
|
372
|
+
newBlockData = (0, _immutable.Map)();
|
|
373
|
+
} else {
|
|
374
|
+
newBlockType = newBlockInfo.type || getBlockTypeForTag(nodeName, lastList);
|
|
375
|
+
newBlockData = newBlockInfo.data ? (0, _immutable.Map)(newBlockInfo.data) : (0, _immutable.Map)();
|
|
376
|
+
}
|
|
377
|
+
chunk = joinChunks(chunk, getSoftNewlineChunk(newBlockType, depth, options.flat, newBlockData), options.flat);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (sibling) {
|
|
381
|
+
nodeName = sibling.nodeName.toLowerCase();
|
|
382
|
+
}
|
|
383
|
+
child = sibling;
|
|
384
|
+
}
|
|
385
|
+
if (newBlock) {
|
|
386
|
+
chunk = joinChunks(chunk, getBlockDividerChunk(nextBlockType, depth, (0, _immutable.Map)()), options.flat);
|
|
387
|
+
}
|
|
388
|
+
return chunk;
|
|
389
|
+
}
|
|
390
|
+
function getChunkForHTML(html, processCustomInlineStyles, checkEntityNode, checkEntityText, checkBlockType, createEntity, getEntity, mergeEntityData, replaceEntityData, options, DOMBuilder) {
|
|
391
|
+
html = html.trim().replace(REGEX_CR, '').replace(REGEX_NBSP, SPACE);
|
|
392
|
+
var safeBody = DOMBuilder(html);
|
|
393
|
+
if (!safeBody) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Sometimes we aren't dealing with content that contains nice semantic
|
|
398
|
+
// tags. In this case, use divs to separate everything out into paragraphs
|
|
399
|
+
// and hope for the best.
|
|
400
|
+
var workingBlocks = containsSemanticBlockMarkup(html) ? blockTags.concat(['div']) : ['div'];
|
|
401
|
+
|
|
402
|
+
// Start with -1 block depth to offset the fact that we are passing in a fake
|
|
403
|
+
// UL block to sta rt with.
|
|
404
|
+
var chunk = genFragment(safeBody, (0, _immutable.OrderedSet)(), 'ul', null, workingBlocks, -1, processCustomInlineStyles, checkEntityNode, checkEntityText, checkBlockType, createEntity, getEntity, mergeEntityData, replaceEntityData, options);
|
|
405
|
+
|
|
406
|
+
// join with previous block to prevent weirdness on paste
|
|
407
|
+
if (chunk.text.indexOf('\r') === 0) {
|
|
408
|
+
chunk = {
|
|
409
|
+
text: chunk.text.slice(1),
|
|
410
|
+
inlines: chunk.inlines.slice(1),
|
|
411
|
+
entities: chunk.entities.slice(1),
|
|
412
|
+
blocks: chunk.blocks
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Kill block delimiter at the end
|
|
417
|
+
if (chunk.text.slice(-1) === '\r') {
|
|
418
|
+
chunk.text = chunk.text.slice(0, -1);
|
|
419
|
+
chunk.inlines = chunk.inlines.slice(0, -1);
|
|
420
|
+
chunk.entities = chunk.entities.slice(0, -1);
|
|
421
|
+
chunk.blocks.pop();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// If we saw no block tags, put an unstyled one in
|
|
425
|
+
if (chunk.blocks.length === 0) {
|
|
426
|
+
chunk.blocks.push({
|
|
427
|
+
type: 'unstyled',
|
|
428
|
+
data: (0, _immutable.Map)(),
|
|
429
|
+
depth: 0
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Sometimes we start with text that isn't in a block, which is then
|
|
434
|
+
// followed by blocks. Need to fix up the blocks to add in
|
|
435
|
+
// an unstyled block for this content
|
|
436
|
+
if (chunk.text.split('\r').length === chunk.blocks.length + 1) {
|
|
437
|
+
chunk.blocks.unshift({
|
|
438
|
+
type: 'unstyled',
|
|
439
|
+
data: (0, _immutable.Map)(),
|
|
440
|
+
depth: 0
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
return chunk;
|
|
444
|
+
}
|
|
445
|
+
function convertFromHTMLtoContentBlocks(html, processCustomInlineStyles, checkEntityNode, checkEntityText, checkBlockType, createEntity, getEntity, mergeEntityData, replaceEntityData, options, DOMBuilder, generateKey) {
|
|
446
|
+
// Be ABSOLUTELY SURE that the dom builder you pass hare won't execute
|
|
447
|
+
// arbitrary code in whatever environment you're running this in. For an
|
|
448
|
+
// example of how we try to do this in-browser, see getSafeBodyFromHTML.
|
|
449
|
+
|
|
450
|
+
var chunk = getChunkForHTML(html, processCustomInlineStyles, checkEntityNode, checkEntityText, checkBlockType, createEntity, getEntity, mergeEntityData, replaceEntityData, options, DOMBuilder, generateKey);
|
|
451
|
+
if (chunk == null) {
|
|
452
|
+
return [];
|
|
453
|
+
}
|
|
454
|
+
var start = 0;
|
|
455
|
+
return chunk.text.split('\r').map(function (textBlock, blockIndex) {
|
|
456
|
+
// Make absolutely certain that our text is acceptable.
|
|
457
|
+
textBlock = sanitizeDraftText(textBlock);
|
|
458
|
+
var end = start + textBlock.length;
|
|
459
|
+
var inlines = nullthrows(chunk).inlines.slice(start, end);
|
|
460
|
+
var entities = nullthrows(chunk).entities.slice(start, end);
|
|
461
|
+
var characterList = (0, _immutable.List)(inlines.map(function (style, entityIndex) {
|
|
462
|
+
var data = {
|
|
463
|
+
style: style,
|
|
464
|
+
entity: null
|
|
465
|
+
};
|
|
466
|
+
if (entities[entityIndex]) {
|
|
467
|
+
data.entity = entities[entityIndex];
|
|
468
|
+
}
|
|
469
|
+
return _draftJs.CharacterMetadata.create(data);
|
|
470
|
+
}));
|
|
471
|
+
start = end + 1;
|
|
472
|
+
return new _draftJs.ContentBlock({
|
|
473
|
+
key: generateKey(),
|
|
474
|
+
type: nullthrows(chunk).blocks[blockIndex].type,
|
|
475
|
+
data: nullthrows(chunk).blocks[blockIndex].data,
|
|
476
|
+
depth: nullthrows(chunk).blocks[blockIndex].depth,
|
|
477
|
+
text: textBlock,
|
|
478
|
+
characterList: characterList
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
var convertFromHTML = function convertFromHTML(_ref2) {
|
|
483
|
+
var _ref2$htmlToStyle = _ref2.htmlToStyle,
|
|
484
|
+
htmlToStyle = _ref2$htmlToStyle === void 0 ? defaultHTMLToStyle : _ref2$htmlToStyle,
|
|
485
|
+
_ref2$htmlToEntity = _ref2.htmlToEntity,
|
|
486
|
+
htmlToEntity = _ref2$htmlToEntity === void 0 ? defaultHTMLToEntity : _ref2$htmlToEntity,
|
|
487
|
+
_ref2$textToEntity = _ref2.textToEntity,
|
|
488
|
+
textToEntity = _ref2$textToEntity === void 0 ? defaultTextToEntity : _ref2$textToEntity,
|
|
489
|
+
_ref2$htmlToBlock = _ref2.htmlToBlock,
|
|
490
|
+
htmlToBlock = _ref2$htmlToBlock === void 0 ? defaultHTMLToBlock : _ref2$htmlToBlock;
|
|
491
|
+
return function (html) {
|
|
492
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
493
|
+
flat: false
|
|
494
|
+
};
|
|
495
|
+
var DOMBuilder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _parseHTML["default"];
|
|
496
|
+
var generateKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _draftJs.genKey;
|
|
497
|
+
var contentState = _draftJs.ContentState.createFromText('');
|
|
498
|
+
var createEntityWithContentState = function createEntityWithContentState() {
|
|
499
|
+
if (contentState.createEntity) {
|
|
500
|
+
var _contentState;
|
|
501
|
+
contentState = (_contentState = contentState).createEntity.apply(_contentState, arguments);
|
|
502
|
+
return contentState.getLastCreatedEntityKey();
|
|
503
|
+
}
|
|
504
|
+
return _draftJs.Entity.create.apply(_draftJs.Entity, arguments);
|
|
505
|
+
};
|
|
506
|
+
var getEntityWithContentState = function getEntityWithContentState() {
|
|
507
|
+
if (contentState.getEntity) {
|
|
508
|
+
var _contentState2;
|
|
509
|
+
return (_contentState2 = contentState).getEntity.apply(_contentState2, arguments);
|
|
510
|
+
}
|
|
511
|
+
return _draftJs.Entity.get.apply(_draftJs.Entity, arguments);
|
|
512
|
+
};
|
|
513
|
+
var mergeEntityDataWithContentState = function mergeEntityDataWithContentState() {
|
|
514
|
+
if (contentState.mergeEntityData) {
|
|
515
|
+
var _contentState3;
|
|
516
|
+
contentState = (_contentState3 = contentState).mergeEntityData.apply(_contentState3, arguments);
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
_draftJs.Entity.mergeData.apply(_draftJs.Entity, arguments);
|
|
520
|
+
};
|
|
521
|
+
var replaceEntityDataWithContentState = function replaceEntityDataWithContentState() {
|
|
522
|
+
if (contentState.replaceEntityData) {
|
|
523
|
+
var _contentState4;
|
|
524
|
+
contentState = (_contentState4 = contentState).replaceEntityData.apply(_contentState4, arguments);
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
_draftJs.Entity.replaceData.apply(_draftJs.Entity, arguments);
|
|
528
|
+
};
|
|
529
|
+
var contentBlocks = convertFromHTMLtoContentBlocks(html, handleMiddleware(htmlToStyle, baseProcessInlineTag), handleMiddleware(htmlToEntity, defaultHTMLToEntity), handleMiddleware(textToEntity, defaultTextToEntity), handleMiddleware(htmlToBlock, baseCheckBlockType), createEntityWithContentState, getEntityWithContentState, mergeEntityDataWithContentState, replaceEntityDataWithContentState, options, DOMBuilder, generateKey);
|
|
530
|
+
var blockMap = _draftJs.BlockMapBuilder.createFromArray(contentBlocks);
|
|
531
|
+
var firstBlockKey = contentBlocks[0].getKey();
|
|
532
|
+
return contentState.merge({
|
|
533
|
+
blockMap: blockMap,
|
|
534
|
+
selectionBefore: _draftJs.SelectionState.createEmpty(firstBlockKey),
|
|
535
|
+
selectionAfter: _draftJs.SelectionState.createEmpty(firstBlockKey)
|
|
536
|
+
});
|
|
537
|
+
};
|
|
538
|
+
};
|
|
539
|
+
var _default = exports["default"] = function _default() {
|
|
540
|
+
if (arguments.length >= 1 && typeof (arguments.length <= 0 ? undefined : arguments[0]) === 'string') {
|
|
541
|
+
return convertFromHTML({}).apply(void 0, arguments);
|
|
542
|
+
}
|
|
543
|
+
return convertFromHTML.apply(void 0, arguments);
|
|
544
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports["default"] = void 0;
|
|
8
|
+
var _invariant = _interopRequireDefault(require("invariant"));
|
|
9
|
+
var _react = _interopRequireDefault(require("react"));
|
|
10
|
+
var _server = _interopRequireDefault(require("react-dom/server"));
|
|
11
|
+
var _draftJs = require("draft-js");
|
|
12
|
+
var _encodeBlock = _interopRequireDefault(require("./encodeBlock"));
|
|
13
|
+
var _blockEntities = _interopRequireDefault(require("./blockEntities"));
|
|
14
|
+
var _blockInlineStyles = _interopRequireDefault(require("./blockInlineStyles"));
|
|
15
|
+
var _accumulateFunction = _interopRequireDefault(require("./util/accumulateFunction"));
|
|
16
|
+
var _blockTypeObjectFunction = _interopRequireDefault(require("./util/blockTypeObjectFunction"));
|
|
17
|
+
var _getBlockTags = _interopRequireDefault(require("./util/getBlockTags"));
|
|
18
|
+
var _getNestedBlockTags = _interopRequireDefault(require("./util/getNestedBlockTags"));
|
|
19
|
+
var _defaultBlockHTML = _interopRequireDefault(require("./default/defaultBlockHTML"));
|
|
20
|
+
var defaultEntityToHTML = function defaultEntityToHTML(entity, originalText) {
|
|
21
|
+
return originalText;
|
|
22
|
+
};
|
|
23
|
+
var defaultValidateHTML = function defaultValidateHTML(html) {
|
|
24
|
+
return true;
|
|
25
|
+
};
|
|
26
|
+
var convertToHTML = function convertToHTML(_ref) {
|
|
27
|
+
var _ref$styleToHTML = _ref.styleToHTML,
|
|
28
|
+
styleToHTML = _ref$styleToHTML === void 0 ? {} : _ref$styleToHTML,
|
|
29
|
+
_ref$blockToHTML = _ref.blockToHTML,
|
|
30
|
+
blockToHTML = _ref$blockToHTML === void 0 ? {} : _ref$blockToHTML,
|
|
31
|
+
_ref$entityToHTML = _ref.entityToHTML,
|
|
32
|
+
entityToHTML = _ref$entityToHTML === void 0 ? defaultEntityToHTML : _ref$entityToHTML,
|
|
33
|
+
_ref$validateHTML = _ref.validateHTML,
|
|
34
|
+
validateHTML = _ref$validateHTML === void 0 ? defaultValidateHTML : _ref$validateHTML;
|
|
35
|
+
return function (contentState) {
|
|
36
|
+
(0, _invariant["default"])(contentState !== null && contentState !== undefined, 'Expected contentState to be non-null');
|
|
37
|
+
var getBlockHTML;
|
|
38
|
+
if (blockToHTML.__isMiddleware === true) {
|
|
39
|
+
getBlockHTML = blockToHTML((0, _blockTypeObjectFunction["default"])(_defaultBlockHTML["default"]));
|
|
40
|
+
} else {
|
|
41
|
+
getBlockHTML = (0, _accumulateFunction["default"])((0, _blockTypeObjectFunction["default"])(blockToHTML), (0, _blockTypeObjectFunction["default"])(_defaultBlockHTML["default"]));
|
|
42
|
+
}
|
|
43
|
+
var rawState = (0, _draftJs.convertToRaw)(contentState);
|
|
44
|
+
var listStack = [];
|
|
45
|
+
var result = rawState.blocks.map(function (block) {
|
|
46
|
+
var type = block.type,
|
|
47
|
+
depth = block.depth;
|
|
48
|
+
var closeNestTags = '';
|
|
49
|
+
var openNestTags = '';
|
|
50
|
+
var blockHTMLResult = getBlockHTML(block);
|
|
51
|
+
if (!blockHTMLResult) {
|
|
52
|
+
throw new Error("convertToHTML: missing HTML definition for block with type ".concat(block.type));
|
|
53
|
+
}
|
|
54
|
+
if (!blockHTMLResult.nest) {
|
|
55
|
+
// this block can't be nested, so reset all nesting if necessary
|
|
56
|
+
closeNestTags = listStack.reduceRight(function (string, nestedBlock) {
|
|
57
|
+
return string + (0, _getNestedBlockTags["default"])(getBlockHTML(nestedBlock), depth).nestEnd;
|
|
58
|
+
}, '');
|
|
59
|
+
listStack = [];
|
|
60
|
+
} else {
|
|
61
|
+
while (depth + 1 !== listStack.length || type !== listStack[depth].type) {
|
|
62
|
+
if (depth + 1 === listStack.length) {
|
|
63
|
+
// depth is right but doesn't match type
|
|
64
|
+
var blockToClose = listStack[depth];
|
|
65
|
+
closeNestTags += (0, _getNestedBlockTags["default"])(getBlockHTML(blockToClose), depth).nestEnd;
|
|
66
|
+
openNestTags += (0, _getNestedBlockTags["default"])(getBlockHTML(block), depth).nestStart;
|
|
67
|
+
listStack[depth] = block;
|
|
68
|
+
} else if (depth + 1 < listStack.length) {
|
|
69
|
+
var _blockToClose = listStack[listStack.length - 1];
|
|
70
|
+
closeNestTags += (0, _getNestedBlockTags["default"])(getBlockHTML(_blockToClose), depth).nestEnd;
|
|
71
|
+
listStack = listStack.slice(0, -1);
|
|
72
|
+
} else {
|
|
73
|
+
openNestTags += (0, _getNestedBlockTags["default"])(getBlockHTML(block), depth).nestStart;
|
|
74
|
+
listStack.push(block);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
var innerHTML = (0, _blockInlineStyles["default"])((0, _blockEntities["default"])((0, _encodeBlock["default"])(block), rawState.entityMap, entityToHTML), styleToHTML);
|
|
79
|
+
var blockHTML = (0, _getBlockTags["default"])(getBlockHTML(block));
|
|
80
|
+
var html;
|
|
81
|
+
if (typeof blockHTML === 'string') {
|
|
82
|
+
html = blockHTML;
|
|
83
|
+
} else {
|
|
84
|
+
html = blockHTML.start + innerHTML + blockHTML.end;
|
|
85
|
+
}
|
|
86
|
+
if (innerHTML.length === 0 && Object.prototype.hasOwnProperty.call(blockHTML, 'empty')) {
|
|
87
|
+
if ( /*#__PURE__*/_react["default"].isValidElement(blockHTML.empty)) {
|
|
88
|
+
html = _server["default"].renderToStaticMarkup(blockHTML.empty);
|
|
89
|
+
} else {
|
|
90
|
+
html = blockHTML.empty;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
var finalHtml = closeNestTags + openNestTags + html;
|
|
94
|
+
if (!validateHTML(finalHtml)) {
|
|
95
|
+
return '';
|
|
96
|
+
}
|
|
97
|
+
return finalHtml;
|
|
98
|
+
}).join('');
|
|
99
|
+
result = listStack.reduce(function (res, nestBlock) {
|
|
100
|
+
return res + (0, _getNestedBlockTags["default"])(getBlockHTML(nestBlock), nestBlock.depth).nestEnd;
|
|
101
|
+
}, result);
|
|
102
|
+
return result;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
var _default = exports["default"] = function _default() {
|
|
106
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
107
|
+
args[_key] = arguments[_key];
|
|
108
|
+
}
|
|
109
|
+
if (args.length === 1 && Object.prototype.hasOwnProperty.call(args[0], '_map') && args[0].getBlockMap != null) {
|
|
110
|
+
// skip higher-order function and use defaults
|
|
111
|
+
return convertToHTML({}).apply(void 0, args);
|
|
112
|
+
}
|
|
113
|
+
return convertToHTML.apply(void 0, args);
|
|
114
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports["default"] = void 0;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
// based on Draft.js' custom list depth styling
|
|
10
|
+
var ORDERED_LIST_TYPES = ['1', 'a', 'i'];
|
|
11
|
+
var _default = exports["default"] = {
|
|
12
|
+
unstyled: /*#__PURE__*/_react["default"].createElement("p", null),
|
|
13
|
+
paragraph: /*#__PURE__*/_react["default"].createElement("p", null),
|
|
14
|
+
'header-one': /*#__PURE__*/_react["default"].createElement("h1", null),
|
|
15
|
+
'header-two': /*#__PURE__*/_react["default"].createElement("h2", null),
|
|
16
|
+
'header-three': /*#__PURE__*/_react["default"].createElement("h3", null),
|
|
17
|
+
'header-four': /*#__PURE__*/_react["default"].createElement("h4", null),
|
|
18
|
+
'header-five': /*#__PURE__*/_react["default"].createElement("h5", null),
|
|
19
|
+
'header-six': /*#__PURE__*/_react["default"].createElement("h6", null),
|
|
20
|
+
'code-block': /*#__PURE__*/_react["default"].createElement("pre", null),
|
|
21
|
+
blockquote: /*#__PURE__*/_react["default"].createElement("blockquote", null),
|
|
22
|
+
'unordered-list-item': {
|
|
23
|
+
element: /*#__PURE__*/_react["default"].createElement("li", null),
|
|
24
|
+
nest: /*#__PURE__*/_react["default"].createElement("ul", null)
|
|
25
|
+
},
|
|
26
|
+
'ordered-list-item': {
|
|
27
|
+
element: /*#__PURE__*/_react["default"].createElement("li", null),
|
|
28
|
+
nest: function nest(depth) {
|
|
29
|
+
var type = ORDERED_LIST_TYPES[depth % 3];
|
|
30
|
+
return /*#__PURE__*/_react["default"].createElement("ol", {
|
|
31
|
+
type: type
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
media: /*#__PURE__*/_react["default"].createElement("figure", null),
|
|
36
|
+
atomic: /*#__PURE__*/_react["default"].createElement("figure", null)
|
|
37
|
+
};
|