@kids-reporter/draft-editor 0.1.0

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 (55) hide show
  1. package/README.md +51 -0
  2. package/lib/.selector/align-selector.js +71 -0
  3. package/lib/.selector/audio-selector.js +268 -0
  4. package/lib/.selector/image-selector.js +430 -0
  5. package/lib/.selector/pagination.js +82 -0
  6. package/lib/.selector/post-selector.js +311 -0
  7. package/lib/.selector/search-box.js +46 -0
  8. package/lib/.selector/video-selector.js +285 -0
  9. package/lib/block-renderer/background-image-block.js +141 -0
  10. package/lib/block-renderer/background-video-block.js +151 -0
  11. package/lib/block-renderer/color-box-block.js +86 -0
  12. package/lib/block-renderer/info-box-block.js +86 -0
  13. package/lib/block-renderer/side-index-block.js +90 -0
  14. package/lib/block-renderer/table-block.js +408 -0
  15. package/lib/block-renderer-fn.js +131 -0
  16. package/lib/buttons/annotation.js +117 -0
  17. package/lib/buttons/audio.js +65 -0
  18. package/lib/buttons/background-color.js +122 -0
  19. package/lib/buttons/background-image.js +223 -0
  20. package/lib/buttons/background-video.js +223 -0
  21. package/lib/buttons/color-box.js +173 -0
  22. package/lib/buttons/divider.js +63 -0
  23. package/lib/buttons/embedded-code.js +109 -0
  24. package/lib/buttons/enlarge.js +24 -0
  25. package/lib/buttons/font-color.js +115 -0
  26. package/lib/buttons/image.js +70 -0
  27. package/lib/buttons/info-box.js +148 -0
  28. package/lib/buttons/link.js +107 -0
  29. package/lib/buttons/media.js +121 -0
  30. package/lib/buttons/related-post.js +71 -0
  31. package/lib/buttons/selector/align-selector.js +71 -0
  32. package/lib/buttons/selector/audio-selector.js +279 -0
  33. package/lib/buttons/selector/image-selector.js +417 -0
  34. package/lib/buttons/selector/pagination.js +82 -0
  35. package/lib/buttons/selector/post-selector.js +317 -0
  36. package/lib/buttons/selector/search-box.js +46 -0
  37. package/lib/buttons/selector/video-selector.js +281 -0
  38. package/lib/buttons/side-index.js +200 -0
  39. package/lib/buttons/slideshow.js +71 -0
  40. package/lib/buttons/table.js +67 -0
  41. package/lib/buttons/text-align.js +88 -0
  42. package/lib/buttons/video.js +65 -0
  43. package/lib/buttons/youtube.js +147 -0
  44. package/lib/const.js +18 -0
  45. package/lib/draft-converter/api-data-instance.js +58 -0
  46. package/lib/draft-converter/atomic-block-processor.js +233 -0
  47. package/lib/draft-converter/entities.js +76 -0
  48. package/lib/draft-converter/index.js +201 -0
  49. package/lib/draft-converter/inline-styles-processor.js +236 -0
  50. package/lib/draft-editor.js +918 -0
  51. package/lib/entity-decorator.js +20 -0
  52. package/lib/index.js +15 -0
  53. package/lib/modifier.js +68 -0
  54. package/lib/theme/index.js +39 -0
  55. package/package.json +41 -0
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _immutable = require("immutable");
9
+
10
+ var _lodash = _interopRequireDefault(require("lodash"));
11
+
12
+ var InlineStylesProcessor = _interopRequireWildcard(require("./inline-styles-processor"));
13
+
14
+ var _apiDataInstance = _interopRequireDefault(require("./api-data-instance"));
15
+
16
+ var _atomicBlockProcessor = _interopRequireDefault(require("./atomic-block-processor"));
17
+
18
+ var _entities = _interopRequireDefault(require("./entities"));
19
+
20
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
21
+
22
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
23
+
24
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
+
26
+ // Modified from https://github.com/dburrows/draft-js-basic-html-editor/blob/master/src/utils/draftRawToHtml.js
27
+ // 'use strict';
28
+ let defaultBlockTagMap = {
29
+ atomic: `<div>%content%</div>`,
30
+ blockquote: `<blockquote>%content%</blockquote>`,
31
+ 'code-block': `<code>%content%</code>`,
32
+ default: `<p>%content%</p>`,
33
+ 'header-two': `<h2>%content%</h2>`,
34
+ 'header-three': `<h3>%content%</h3>`,
35
+ 'header-four': `<h4>%content%</h4>`,
36
+ 'ordered-list-item': `<li>%content%</li>`,
37
+ paragraph: `<p>%content%</p>`,
38
+ 'unordered-list-item': `<li>%content%</li>`,
39
+ unstyled: `<p>%content%</p>`
40
+ };
41
+ let inlineTagMap = {
42
+ BOLD: ['<strong>', '</strong>'],
43
+ CODE: ['<code>', '</code>'],
44
+ default: ['<span>', '</span>'],
45
+ ITALIC: ['<em>', '</em>'],
46
+ UNDERLINE: ['<u>', '</u>']
47
+ };
48
+ let defaultEntityTagMap = {
49
+ [_entities.default.DIVIDER.type]: ['<hr>', ''],
50
+ [_entities.default.ANNOTATION.type]: ['<abbr title="<%= data.body %>"><%= data.text %>', '</abbr>'],
51
+ [_entities.default.AUDIO.type]: ['<div class="audio-container center"><div class="audio-title"><%= data.name %></div><!-- <div class="audio-desc"><%= data.description %></div> --><audio src="<%= data.url %>" />', '</div>'],
52
+ [_entities.default.BLOCKQUOTE.type]: ['<blockquote class="center"><div><%= data.quote %></div><div><%= data.quotedBy %></div>', '<blockquote>'],
53
+ [_entities.default.EMBEDDEDCODE.type]: ['<div class="embedded <%= data.alignment %>" title="<%= data.caption %>"><%= data.code%>', '</div>'],
54
+ [_entities.default.INFOBOX.type]: ['<div class="info-box-container center"><div class="info-box-title"><%= data.title %></div><div class="info-box-body"><%= data.body %></div>', '</div>'],
55
+ [_entities.default.STOREDIMAGE.type]: ['<img alt="<%= data.name %>" src="<%= data.url %>" srcset="<%= data.urlMobileSized %> 800w, <%= data.urlTabletSized %> 1280w, <%= data.urlDesktopSized %> 2400w" class="center">', '</img>'],
56
+ [_entities.default.IMAGE.type]: ['<img alt="<%=data.name%>" src="<%=data.url%>" srcset="<%= data.mobile.url %> 800w, <%= data.tablet.url %> 1280w, <%= data.desktop.url %> 2400w" class="center">', '</img>'],
57
+
58
+ /*[ENTITY.IMAGEDIFF.type]: ['<!-- imageDiff component start --> <ol class="image-diff-container"> <% _.forEach(data, function(image, index) { if (index > 1) { return; } %><li class="image-diff-item"><img src="<%- image.url %>" /></li><% }); %>', '</ol><!-- imageDiff component end-->'],
59
+ [ENTITY.IMAGELINK.type]: ['<img alt="<%= data.description %>" src="<%= data.url %>" class="<%= data.alignment %>">', '</img>'],*/
60
+ [_entities.default.LINK.type]: ['<a target="_blank" href="<%= data.url %>">', '</a>'],
61
+ [_entities.default.SLIDESHOW.type]: ['<!-- slideshow component start --> <ol class="slideshow-container"> <% _.forEach(data, function(image) { %><li class="slideshow-slide"><img alt="<%- image.name %>" src="<%- image.url %>" srcset="<%= image.mobile.url %> 800w, <%= image.tablet.url %> 1280w, <%= image.desktop.url %> 2400w" /></li><% }); %>', '</ol><!-- slideshow component end -->'],
62
+ [_entities.default.VIDEO.type]: ['<div controls class="video-container <%= data.alignment %>"><div class="video-name"><%= data.title %></div><div class="video-desc"><%= data.description %></div><video src="<%= data.url %>" />', '</div>'],
63
+ [_entities.default.YOUTUBE.type]: ['<iframe width="560" alt="<%= data.description %>" height="315" src="https://www.youtube.com/embed/<%= data.id %>" frameborder="0" allowfullscreen>', '</iframe>']
64
+ };
65
+ let nestedTagMap = {
66
+ 'ordered-list-item': ['<ol>', '</ol>'],
67
+ 'unordered-list-item': ['<ul>', '</ul>']
68
+ };
69
+
70
+ function _convertInlineStyle(block, entityMap, blockTagMap, entityTagMap) {
71
+ return blockTagMap[block.type] ? blockTagMap[block.type].replace('%content%', InlineStylesProcessor.convertToHtml(inlineTagMap, entityTagMap, entityMap, block)) : blockTagMap.default.replace('%content%', InlineStylesProcessor.convertToHtml(inlineTagMap, block));
72
+ }
73
+
74
+ function _convertBlocksToHtml(blocks, entityMap, blockTagMap, entityTagMap) {
75
+ let html = '';
76
+ let nestLevel = []; // store the list type of the previous item: null/ol/ul
77
+
78
+ blocks.forEach(block => {
79
+ // create tag for <ol> or <ul>: deal with ordered/unordered list item
80
+ // if the block is a list-item && the previous block is not a list-item
81
+ if (nestedTagMap[block.type] && nestLevel[0] !== block.type) {
82
+ html += nestedTagMap[block.type][0]; // start with <ol> or <ul>
83
+
84
+ nestLevel.unshift(block.type);
85
+ } // end tag with </ol> or </ul>: deal with ordered/unordered list item
86
+
87
+
88
+ if (nestLevel.length > 0 && nestLevel[0] !== block.type) {
89
+ html += nestedTagMap[nestLevel.shift()][1]; // close with </ol> or </ul>
90
+ }
91
+
92
+ html += _convertInlineStyle(block, entityMap, blockTagMap, entityTagMap);
93
+ }); // end tag with </ol> or </ul>: or if it is the last block
94
+
95
+ if (blocks.length > 0 && nestedTagMap[blocks[blocks.length - 1].type]) {
96
+ html += nestedTagMap[nestLevel.shift()][1]; // close with </ol> or </ul>
97
+ }
98
+
99
+ return html;
100
+ }
101
+
102
+ function convertBlocksToApiData(blocks, entityMap, entityTagMap) {
103
+ let apiDataArr = (0, _immutable.List)();
104
+ let content = [];
105
+ let nestLevel = [];
106
+ blocks.forEach(block => {
107
+ // block is not a list-item
108
+ if (!nestedTagMap[block.type]) {
109
+ // if previous block is a list-item
110
+ if (content.length > 0 && nestLevel.length > 0) {
111
+ apiDataArr = apiDataArr.push(new _apiDataInstance.default({
112
+ type: nestLevel[0],
113
+ content: [content]
114
+ }));
115
+ content = [];
116
+ nestLevel.shift();
117
+ }
118
+
119
+ if (block.type.startsWith('atomic') || block.type.startsWith('media')) {
120
+ try {
121
+ apiDataArr = apiDataArr.push(_atomicBlockProcessor.default.convertBlock(entityMap, block));
122
+ } catch (e) {
123
+ console.error(e);
124
+ }
125
+ } else {
126
+ var _block$data;
127
+
128
+ let converted = InlineStylesProcessor.convertToHtml(inlineTagMap, entityTagMap, entityMap, block);
129
+ const type = block.type;
130
+ const textAlign = (_block$data = block.data) === null || _block$data === void 0 ? void 0 : _block$data.textAlign;
131
+ apiDataArr = apiDataArr.push(new _apiDataInstance.default({
132
+ id: block.key,
133
+ type,
134
+ content: [converted],
135
+ textAlign
136
+ }));
137
+ }
138
+ } else {
139
+ let converted = InlineStylesProcessor.convertToHtml(inlineTagMap, entityTagMap, entityMap, block); // previous block is not an item-list block
140
+
141
+ if (nestLevel.length === 0) {
142
+ nestLevel.unshift(block.type);
143
+ content.push(converted);
144
+ } else if (nestLevel[0] === block.type) {
145
+ // previous block is a item-list and current block is the same item-list
146
+ content.push(converted);
147
+ } else if (nestLevel[0] !== block.type) {
148
+ // previous block is a different item-list.
149
+ apiDataArr = apiDataArr.push(new _apiDataInstance.default({
150
+ id: block.key,
151
+ type: nestLevel[0],
152
+ content: [content]
153
+ }));
154
+ content = [converted];
155
+ nestLevel[0] = block.type;
156
+ }
157
+ }
158
+ }); // last block is a item-list
159
+
160
+ if (blocks.length > 0 && nestLevel.length > 0) {
161
+ let block = blocks[blocks.length - 1];
162
+ apiDataArr = apiDataArr.push(new _apiDataInstance.default({
163
+ id: block.key,
164
+ type: block.type,
165
+ content: content
166
+ }));
167
+ }
168
+
169
+ return apiDataArr;
170
+ }
171
+
172
+ function convertRawToHtml(raw, blockTagMap, entityTagMap) {
173
+ blockTagMap = _lodash.default.merge({}, defaultBlockTagMap, blockTagMap);
174
+ entityTagMap = entityTagMap || defaultEntityTagMap;
175
+ let html = '';
176
+ raw = raw || {};
177
+ const blocks = Array.isArray(raw.blocks) ? raw.blocks : [];
178
+ const entityMap = typeof raw.entityMap === 'object' ? raw.entityMap : {};
179
+ html = _convertBlocksToHtml(blocks, entityMap, blockTagMap, entityTagMap);
180
+ return html;
181
+ }
182
+
183
+ function convertRawToApiData(raw) {
184
+ let apiData;
185
+ raw = raw || {};
186
+ const blocks = Array.isArray(raw.blocks) ? raw.blocks : [];
187
+ const entityMap = typeof raw.entityMap === 'object' ? raw.entityMap : {};
188
+
189
+ let entityTagMap = _lodash.default.merge({}, defaultEntityTagMap, {
190
+ [_entities.default.ANNOTATION.type]: [`<span data-entity-type="annotation" data-annotation-body="<%= data.bodyEscapedHTML %>">`, '</span>']
191
+ });
192
+
193
+ apiData = convertBlocksToApiData(blocks, entityMap, entityTagMap);
194
+ return apiData;
195
+ }
196
+
197
+ var _default = {
198
+ convertToHtml: convertRawToHtml,
199
+ convertToApiData: convertRawToApiData
200
+ };
201
+ exports.default = _default;
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.convertToHtml = convertToHtml;
7
+
8
+ var _lodash = _interopRequireDefault(require("lodash"));
9
+
10
+ var _const = require("../const");
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+
14
+ // Modified from https://github.com/dburrows/draft-js-basic-html-editor/blob/master/src/utils/processInlineStylesAndEntities.js
15
+ function tagForCustomInlineStyle(style) {
16
+ const customInlineStylePrefixs = [_const.CUSTOM_STYLE_PREFIX_FONT_COLOR, _const.CUSTOM_STYLE_PREFIX_BACKGROUND_COLOR];
17
+ const stylePrefix = customInlineStylePrefixs.find(prefix => style.startsWith(prefix));
18
+ let tag, value;
19
+
20
+ switch (stylePrefix) {
21
+ case _const.CUSTOM_STYLE_PREFIX_FONT_COLOR:
22
+ value = style.split(_const.CUSTOM_STYLE_PREFIX_FONT_COLOR)[1];
23
+ tag = [`<span style="color: ${value}">`, '</span>'];
24
+ break;
25
+
26
+ case _const.CUSTOM_STYLE_PREFIX_BACKGROUND_COLOR:
27
+ value = style.split(_const.CUSTOM_STYLE_PREFIX_BACKGROUND_COLOR)[1];
28
+ tag = [`<span style="background-color: ${value}">`, '</span>'];
29
+ break;
30
+
31
+ default:
32
+ break;
33
+ }
34
+
35
+ return tag;
36
+ }
37
+
38
+ function _fullfilIntersection(block) {
39
+ // SORT BEFORE PROCESSING
40
+ let sortedISRanges = _lodash.default.sortBy(block.inlineStyleRanges, 'offset');
41
+
42
+ let sortedEntityRanges = _lodash.default.sortBy(block.entityRanges, 'offset');
43
+
44
+ let splitedISInline = [];
45
+
46
+ for (let i = 0; i < sortedEntityRanges.length; i++) {
47
+ let entityRange = sortedEntityRanges[i];
48
+
49
+ for (let j = 0; j < sortedISRanges.length; j++) {
50
+ let entityOffset = _lodash.default.get(entityRange, 'offset', 0);
51
+
52
+ let entityLength = _lodash.default.get(entityRange, 'length', 0);
53
+
54
+ let inlineLength = _lodash.default.get(sortedISRanges, [j, 'length'], 0);
55
+
56
+ let inlineOffset = _lodash.default.get(sortedISRanges, [j, 'offset'], 0);
57
+
58
+ let inlineStyle = _lodash.default.get(sortedISRanges, [j, 'style'], '');
59
+
60
+ let nextEntityOffset = _lodash.default.get(sortedEntityRanges, [i + 1, 'offset'], 0);
61
+
62
+ let nextEntityLength = _lodash.default.get(sortedEntityRanges, [i + 1, 'length'], 0); // handle intersections of inline style and entity
63
+ // <a></a> is entity
64
+ // <abbr></abbr> is next entity
65
+ // <strong></strong> is inline style
66
+
67
+
68
+ if (nextEntityOffset >= inlineOffset && nextEntityOffset < inlineOffset + inlineLength && nextEntityOffset + nextEntityLength > inlineOffset + inlineLength && // <a><strong></a></strong>
69
+ entityOffset < inlineOffset && entityOffset + entityLength > inlineOffset && entityOffset + entityLength <= inlineOffset + inlineLength) {
70
+ // <strong><abbr></strong></abbr>
71
+ // situation: <a><strong></a><abbr></strong></abbr>
72
+ // should be: <a><strong></strong></a><strong></strong><abbr><strong></strong></abbr>
73
+ // skip next entity checking
74
+ i = i + 1;
75
+ splitedISInline.push({
76
+ index: j,
77
+ replace: [{
78
+ length: entityOffset + entityLength - inlineOffset,
79
+ offset: inlineOffset,
80
+ style: inlineStyle
81
+ }, {
82
+ length: nextEntityOffset - (entityOffset + entityLength),
83
+ offset: entityOffset + entityLength,
84
+ style: inlineStyle
85
+ }, {
86
+ length: inlineOffset + inlineLength - nextEntityOffset,
87
+ offset: nextEntityOffset,
88
+ style: inlineStyle
89
+ }]
90
+ });
91
+ } else if (entityOffset >= inlineOffset && entityOffset < inlineOffset + inlineLength && entityOffset + entityLength > inlineOffset + inlineLength) {
92
+ // situation: <strong><a></strong></a>
93
+ // should be: <strong></strong><a><strong></strong></a>
94
+ splitedISInline.push({
95
+ index: j,
96
+ replace: [{
97
+ length: entityOffset - inlineOffset,
98
+ offset: inlineOffset,
99
+ style: inlineStyle
100
+ }, {
101
+ length: inlineOffset + inlineLength - entityOffset,
102
+ offset: entityOffset,
103
+ style: inlineStyle
104
+ }]
105
+ });
106
+ } else if (entityOffset < inlineOffset && entityOffset + entityLength > inlineOffset && entityOffset + entityLength <= inlineOffset + inlineLength) {
107
+ // situation: <a><strong></a></strong>
108
+ // should be: <a><strong></strong></a><strong></strong>
109
+ splitedISInline.push({
110
+ index: j,
111
+ replace: [{
112
+ length: entityOffset + entityLength - inlineOffset,
113
+ offset: inlineOffset,
114
+ style: inlineStyle
115
+ }, {
116
+ length: inlineOffset + inlineLength - entityOffset - entityLength,
117
+ offset: entityOffset + entityLength,
118
+ style: inlineStyle
119
+ }]
120
+ });
121
+ }
122
+ }
123
+ }
124
+
125
+ _lodash.default.forEachRight(splitedISInline, ele => {
126
+ sortedISRanges.splice(ele.index, 1, ...ele.replace);
127
+ });
128
+
129
+ return sortedISRanges;
130
+ }
131
+
132
+ function _inlineTag(inlineTagMap, inlineStyleRanges, tagInsertMap = {}) {
133
+ // SORT BEFORE PROCESSING
134
+ let sortedRanges = _lodash.default.sortBy(inlineStyleRanges, 'offset'); // map all the tag insertions we're going to do
135
+
136
+
137
+ sortedRanges.forEach(function (range) {
138
+ let tag = inlineTagMap[range.style]; // handle dynamic inline style
139
+
140
+ if (!tag) {
141
+ tag = tagForCustomInlineStyle(range.style);
142
+ }
143
+
144
+ if (!tagInsertMap[range.offset]) {
145
+ tagInsertMap[range.offset] = [];
146
+ } // add starting tag to the end of the array to form the tag nesting
147
+
148
+
149
+ tagInsertMap[range.offset].push(tag[0]);
150
+
151
+ if (tag[1]) {
152
+ if (!tagInsertMap[range.offset + range.length]) {
153
+ tagInsertMap[range.offset + range.length] = [];
154
+ } // add closing tags to start of array, otherwise tag nesting will be invalid
155
+
156
+
157
+ tagInsertMap[range.offset + range.length].unshift(tag[1]);
158
+ }
159
+ });
160
+ return tagInsertMap;
161
+ }
162
+
163
+ function _entityTag(entityTagMap, entityMap, entityRanges, tagInsertMap = {}) {
164
+ _lodash.default.forEach(entityRanges, range => {
165
+ let entity = entityMap[range.key];
166
+ let type = entity.type && entity.type.toUpperCase();
167
+ let tag = entityTagMap[type];
168
+ let data = entity.data;
169
+
170
+ let compiledTag0 = _lodash.default.template(tag[0], {
171
+ variable: 'data'
172
+ })(data);
173
+
174
+ let compiledTag1 = _lodash.default.template(tag[1], {
175
+ variable: 'data'
176
+ })(data);
177
+
178
+ if (!tagInsertMap[range.offset]) {
179
+ tagInsertMap[range.offset] = [];
180
+ } // add starting tag
181
+
182
+
183
+ tagInsertMap[range.offset].push(compiledTag0);
184
+
185
+ if (tag[1]) {
186
+ if (!tagInsertMap[range.offset + range.length]) {
187
+ tagInsertMap[range.offset + range.length] = [];
188
+ } // add closing tags to start of array, otherwise tag nesting will be invalid
189
+
190
+
191
+ tagInsertMap[range.offset + range.length].unshift(compiledTag1);
192
+ }
193
+ });
194
+
195
+ return tagInsertMap;
196
+ }
197
+
198
+ function convertToHtml(inlineTagMap, entityTagMap, entityMap, block) {
199
+ // exit if there is no inlineStyleRanges/entityRanges or length === 0 as well
200
+ if (!block.inlineStyleRanges && !block.entityRanges || block.inlineStyleRanges.length === 0 && block.entityRanges.length === 0) {
201
+ return block.text;
202
+ }
203
+
204
+ let html = block.text;
205
+
206
+ let inlineStyleRanges = _fullfilIntersection(block);
207
+
208
+ let tagInsertMap = {};
209
+ tagInsertMap = _entityTag(entityTagMap, entityMap, block.entityRanges, tagInsertMap);
210
+ tagInsertMap = _inlineTag(inlineTagMap, inlineStyleRanges, tagInsertMap); // sort on position, as we'll need to keep track of offset
211
+
212
+ let orderedKeys = Object.keys(tagInsertMap).sort(function (a, b) {
213
+ a = Number(a);
214
+ b = Number(b);
215
+
216
+ if (a > b) {
217
+ return 1;
218
+ }
219
+
220
+ if (a < b) {
221
+ return -1;
222
+ }
223
+
224
+ return 0;
225
+ }); // insert tags into string, keep track of offset caused by our text insertions
226
+
227
+ let offset = 0;
228
+ orderedKeys.forEach(function (pos) {
229
+ let index = Number(pos);
230
+ tagInsertMap[pos].forEach(function (tag) {
231
+ html = html.substr(0, offset + index) + tag + html.substr(offset + index);
232
+ offset += tag.length;
233
+ });
234
+ });
235
+ return html;
236
+ }