suneditor 3.1.4 → 3.2.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/dist/suneditor-contents.min.css +1 -1
- package/dist/suneditor.min.css +28 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +2 -1
- package/src/assets/design/color.css +12 -0
- package/src/assets/design/size.css +9 -2
- package/src/assets/icons/defaultIcons.js +96 -47
- package/src/assets/suneditor-contents.css +3 -2
- package/src/assets/suneditor.css +481 -31
- package/src/core/config/contextProvider.js +2 -1
- package/src/core/config/eventManager.js +41 -2
- package/src/core/config/optionProvider.js +23 -2
- package/src/core/editor.js +32 -14
- package/src/core/event/actions/index.js +76 -9
- package/src/core/event/effects/common.registry.js +2 -1
- package/src/core/event/effects/keydown.registry.js +169 -33
- package/src/core/event/effects/ruleHelpers.js +20 -6
- package/src/core/event/eventOrchestrator.js +162 -30
- package/src/core/event/handlers/handler_toolbar.js +4 -2
- package/src/core/event/handlers/handler_ww_dragDrop.js +10 -0
- package/src/core/event/handlers/handler_ww_input.js +84 -2
- package/src/core/event/handlers/handler_ww_key.js +82 -21
- package/src/core/event/handlers/handler_ww_mouse.js +45 -8
- package/src/core/event/ports.js +27 -13
- package/src/core/event/reducers/keydown.reducer.js +33 -5
- package/src/core/event/rules/keydown.rule.arrow.js +12 -2
- package/src/core/event/rules/keydown.rule.backspace.js +110 -15
- package/src/core/event/rules/keydown.rule.delete.js +62 -7
- package/src/core/event/rules/keydown.rule.enter.js +62 -31
- package/src/core/event/support/defaultLineManager.js +9 -2
- package/src/core/event/support/selectionState.js +13 -3
- package/src/core/kernel/coreKernel.js +1 -0
- package/src/core/logic/dom/char.js +13 -3
- package/src/core/logic/dom/format.js +171 -39
- package/src/core/logic/dom/html.js +350 -72
- package/src/core/logic/dom/inline.js +229 -34
- package/src/core/logic/dom/listFormat.js +111 -20
- package/src/core/logic/dom/nodeTransform.js +36 -11
- package/src/core/logic/dom/offset.js +116 -31
- package/src/core/logic/dom/selection.js +147 -29
- package/src/core/logic/panel/blockHandle.js +785 -0
- package/src/core/logic/panel/blockResolver.js +278 -0
- package/src/core/logic/panel/finder.js +16 -6
- package/src/core/logic/panel/menu.js +119 -18
- package/src/core/logic/panel/toolbar.js +75 -19
- package/src/core/logic/panel/viewer.js +76 -20
- package/src/core/logic/shell/_commandExecutor.js +44 -9
- package/src/core/logic/shell/commandDispatcher.js +46 -4
- package/src/core/logic/shell/component.js +102 -25
- package/src/core/logic/shell/focusManager.js +13 -3
- package/src/core/logic/shell/history.js +21 -6
- package/src/core/logic/shell/pluginManager.js +21 -13
- package/src/core/logic/shell/shortcuts.js +9 -1
- package/src/core/logic/shell/ui.js +139 -37
- package/src/core/schema/frameContext.js +34 -3
- package/src/core/schema/options.js +46 -4
- package/src/core/section/constructor.js +537 -106
- package/src/core/section/documentType.js +35 -6
- package/src/helper/converter.js +24 -7
- package/src/helper/dom/domCheck.js +25 -5
- package/src/helper/dom/domQuery.js +2 -1
- package/src/helper/dom/domUtils.js +17 -4
- package/src/helper/env.js +11 -2
- package/src/helper/keyCodeMap.js +6 -2
- package/src/helper/markdown.js +24 -5
- package/src/helper/msOffice.js +9 -2
- package/src/interfaces/plugins.js +1 -1
- package/src/langs/ckb.js +0 -1
- package/src/langs/cs.js +0 -1
- package/src/langs/da.js +0 -1
- package/src/langs/de.js +0 -1
- package/src/langs/en.js +0 -1
- package/src/langs/es.js +0 -1
- package/src/langs/fa.js +0 -1
- package/src/langs/fr.js +0 -1
- package/src/langs/he.js +0 -1
- package/src/langs/hu.js +0 -1
- package/src/langs/index.js +27 -1
- package/src/langs/it.js +0 -1
- package/src/langs/ja.js +0 -1
- package/src/langs/km.js +0 -1
- package/src/langs/ko.js +0 -1
- package/src/langs/lv.js +0 -1
- package/src/langs/nl.js +0 -1
- package/src/langs/pl.js +0 -1
- package/src/langs/pt_br.js +0 -1
- package/src/langs/ro.js +0 -1
- package/src/langs/ru.js +0 -1
- package/src/langs/se.js +0 -1
- package/src/langs/tr.js +0 -1
- package/src/langs/uk.js +0 -1
- package/src/langs/ur.js +0 -1
- package/src/langs/zh_cn.js +0 -1
- package/src/modules/contract/Browser.js +58 -14
- package/src/modules/contract/ColorPicker.js +12 -4
- package/src/modules/contract/Controller.js +37 -7
- package/src/modules/contract/Figure.js +156 -36
- package/src/modules/contract/HueSlider.js +27 -4
- package/src/modules/contract/Modal.js +50 -10
- package/src/modules/manager/FileManager.js +50 -8
- package/src/modules/ui/CommandMenu.js +597 -0
- package/src/modules/ui/ModalAnchorEditor.js +33 -6
- package/src/modules/ui/SelectMenu.js +481 -36
- package/src/modules/ui/index.js +1 -0
- package/src/plugins/browser/audioGallery.js +2 -1
- package/src/plugins/browser/fileBrowser.js +9 -2
- package/src/plugins/browser/fileGallery.js +2 -1
- package/src/plugins/browser/imageGallery.js +18 -3
- package/src/plugins/browser/videoGallery.js +13 -4
- package/src/plugins/command/blockquote.js +6 -1
- package/src/plugins/command/codeBlock.js +43 -5
- package/src/plugins/command/exportPDF.js +20 -4
- package/src/plugins/command/fileUpload.js +46 -11
- package/src/plugins/command/list_bulleted.js +6 -1
- package/src/plugins/command/list_numbered.js +6 -1
- package/src/plugins/dropdown/align.js +21 -33
- package/src/plugins/dropdown/backgroundColor.js +10 -2
- package/src/plugins/dropdown/blockStyle.js +17 -22
- package/src/plugins/dropdown/font.js +34 -34
- package/src/plugins/dropdown/hr.js +15 -43
- package/src/plugins/dropdown/layout.js +10 -27
- package/src/plugins/dropdown/lineHeight.js +10 -33
- package/src/plugins/dropdown/list.js +19 -25
- package/src/plugins/dropdown/paragraphStyle.js +16 -24
- package/src/plugins/dropdown/table/index.js +72 -17
- package/src/plugins/dropdown/table/render/table.html.js +3 -1
- package/src/plugins/dropdown/table/services/table.cell.js +33 -7
- package/src/plugins/dropdown/table/services/table.clipboard.js +5 -1
- package/src/plugins/dropdown/table/services/table.grid.js +40 -9
- package/src/plugins/dropdown/table/services/table.resize.js +55 -11
- package/src/plugins/dropdown/table/services/table.selection.js +27 -7
- package/src/plugins/dropdown/table/services/table.style.js +120 -20
- package/src/plugins/dropdown/template.js +13 -29
- package/src/plugins/dropdown/textStyle.js +22 -35
- package/src/plugins/field/autocomplete.js +8 -4
- package/src/plugins/field/slashCommand.js +297 -0
- package/src/plugins/index.js +3 -0
- package/src/plugins/input/fontSize.js +37 -8
- package/src/plugins/input/pageNavigator.js +7 -1
- package/src/plugins/modal/audio.js +71 -17
- package/src/plugins/modal/drawing.js +41 -11
- package/src/plugins/modal/embed.js +92 -22
- package/src/plugins/modal/image/index.js +114 -28
- package/src/plugins/modal/image/services/image.size.js +9 -2
- package/src/plugins/modal/image/services/image.upload.js +38 -4
- package/src/plugins/modal/link.js +9 -2
- package/src/plugins/modal/math.js +10 -2
- package/src/plugins/modal/video/index.js +112 -26
- package/src/plugins/modal/video/render/video.html.js +4 -1
- package/src/plugins/modal/video/services/video.size.js +15 -4
- package/src/plugins/modal/video/services/video.upload.js +10 -2
- package/src/plugins/popup/anchor.js +14 -2
- package/src/suneditor.js +8 -2
- package/src/themes/cobalt.css +12 -0
- package/src/themes/cream.css +12 -0
- package/src/themes/dark.css +12 -0
- package/src/themes/midnight.css +12 -0
- package/src/typedef.js +32 -21
- package/types/assets/icons/defaultIcons.d.ts +1 -0
- package/types/core/config/contextProvider.d.ts +7 -1
- package/types/core/config/eventManager.d.ts +37 -4
- package/types/core/config/optionProvider.d.ts +5 -1
- package/types/core/event/actions/index.d.ts +44 -6
- package/types/core/event/effects/keydown.registry.d.ts +37 -7
- package/types/core/event/effects/ruleHelpers.d.ts +6 -1
- package/types/core/event/eventOrchestrator.d.ts +13 -3
- package/types/core/event/handlers/handler_ww_clipboard.d.ts +15 -3
- package/types/core/event/handlers/handler_ww_dragDrop.d.ts +14 -2
- package/types/core/event/handlers/handler_ww_input.d.ts +10 -2
- package/types/core/event/handlers/handler_ww_key.d.ts +10 -2
- package/types/core/event/handlers/handler_ww_mouse.d.ts +25 -5
- package/types/core/event/ports.d.ts +11 -4
- package/types/core/event/reducers/keydown.reducer.d.ts +12 -3
- package/types/core/event/rules/keydown.rule.backspace.d.ts +6 -1
- package/types/core/kernel/store.d.ts +4 -1
- package/types/core/logic/dom/format.d.ts +32 -14
- package/types/core/logic/dom/html.d.ts +11 -3
- package/types/core/logic/dom/nodeTransform.d.ts +6 -6
- package/types/core/logic/panel/blockHandle.d.ts +64 -0
- package/types/core/logic/panel/blockResolver.d.ts +50 -0
- package/types/core/logic/panel/menu.d.ts +72 -3
- package/types/core/logic/shell/commandDispatcher.d.ts +8 -0
- package/types/core/logic/shell/component.d.ts +5 -3
- package/types/core/logic/shell/shortcuts.d.ts +10 -1
- package/types/core/logic/shell/ui.d.ts +7 -1
- package/types/core/schema/context.d.ts +7 -1
- package/types/core/schema/frameContext.d.ts +36 -4
- package/types/core/schema/options.d.ts +83 -2
- package/types/core/section/constructor.d.ts +38 -1
- package/types/events.d.ts +208 -32
- package/types/helper/converter.d.ts +4 -2
- package/types/helper/dom/domCheck.d.ts +12 -2
- package/types/helper/dom/domQuery.d.ts +35 -7
- package/types/helper/dom/domUtils.d.ts +4 -1
- package/types/interfaces/plugins.d.ts +2 -2
- package/types/langs/_Lang.d.ts +0 -1
- package/types/modules/contract/ColorPicker.d.ts +2 -2
- package/types/modules/contract/Controller.d.ts +7 -0
- package/types/modules/contract/Figure.d.ts +31 -4
- package/types/modules/ui/CommandMenu.d.ts +262 -0
- package/types/modules/ui/SelectMenu.d.ts +56 -3
- package/types/modules/ui/index.d.ts +1 -0
- package/types/plugins/browser/audioGallery.d.ts +1 -1
- package/types/plugins/browser/fileBrowser.d.ts +1 -1
- package/types/plugins/browser/fileGallery.d.ts +1 -1
- package/types/plugins/browser/imageGallery.d.ts +1 -1
- package/types/plugins/browser/videoGallery.d.ts +1 -1
- package/types/plugins/dropdown/align.d.ts +1 -1
- package/types/plugins/dropdown/blockStyle.d.ts +3 -1
- package/types/plugins/dropdown/table/index.d.ts +4 -1
- package/types/plugins/dropdown/table/services/table.clipboard.d.ts +5 -1
- package/types/plugins/dropdown/table/services/table.grid.d.ts +10 -2
- package/types/plugins/field/autocomplete.d.ts +0 -1
- package/types/plugins/field/slashCommand.d.ts +165 -0
- package/types/plugins/index.d.ts +3 -0
- package/types/plugins/modal/link.d.ts +4 -1
- package/types/typedef.d.ts +48 -23
|
@@ -89,7 +89,10 @@ class HTML {
|
|
|
89
89
|
// extra tags
|
|
90
90
|
const allowedExtraTags = options.get('_allowedExtraTag');
|
|
91
91
|
const disallowedExtraTags = options.get('_disallowedExtraTag');
|
|
92
|
-
this.#disallowedTagsRegExp = new RegExp(
|
|
92
|
+
this.#disallowedTagsRegExp = new RegExp(
|
|
93
|
+
`<(${disallowedExtraTags})[^>]*>([\\s\\S]*?)<\\/\\1>|<(${disallowedExtraTags})[^>]*\\/?>`,
|
|
94
|
+
'gi',
|
|
95
|
+
);
|
|
93
96
|
this.#disallowedTagNameRegExp = new RegExp(`^(${disallowedExtraTags})$`, 'i');
|
|
94
97
|
this.#allowedTagNameRegExp = new RegExp(`^(${allowedExtraTags})$`, 'i');
|
|
95
98
|
|
|
@@ -104,18 +107,29 @@ class HTML {
|
|
|
104
107
|
for (let i = 0; i < allowStyleNodes.length; i++) {
|
|
105
108
|
disallowStyleNodes.splice(disallowStyleNodes.indexOf(allowStyleNodes[i].toLowerCase()), 1);
|
|
106
109
|
}
|
|
107
|
-
this.#disallowedStyleNodesRegExp =
|
|
110
|
+
this.#disallowedStyleNodesRegExp =
|
|
111
|
+
disallowStyleNodes.length === 0
|
|
112
|
+
? null
|
|
113
|
+
: new RegExp('(<\\/?)(' + disallowStyleNodes.join('|') + ')\\b\\s*([^>^<]+)?\\s*(?=>)', 'gi');
|
|
108
114
|
|
|
109
115
|
// whitelist
|
|
110
116
|
// tags
|
|
111
117
|
const defaultAttr = options.get('__defaultAttributeWhitelist');
|
|
112
|
-
this.#allowHTMLComment =
|
|
118
|
+
this.#allowHTMLComment =
|
|
119
|
+
options.get('_editorElementWhitelist').includes('//') || options.get('_editorElementWhitelist') === '*';
|
|
113
120
|
// html check
|
|
114
|
-
this.#htmlCheckWhitelistRegExp = new RegExp(
|
|
121
|
+
this.#htmlCheckWhitelistRegExp = new RegExp(
|
|
122
|
+
'^(' + GetRegList(options.get('_editorElementWhitelist').replace('|//', ''), '') + ')$',
|
|
123
|
+
'i',
|
|
124
|
+
);
|
|
115
125
|
this.#htmlCheckBlacklistRegExp = new RegExp('^(' + (options.get('elementBlacklist') || '^') + ')$', 'i');
|
|
116
126
|
// elements
|
|
117
|
-
this.#elementWhitelistRegExp = converter.createElementWhitelist(
|
|
118
|
-
|
|
127
|
+
this.#elementWhitelistRegExp = converter.createElementWhitelist(
|
|
128
|
+
GetRegList(options.get('_editorElementWhitelist').replace('|//', '|<!--|-->'), ''),
|
|
129
|
+
);
|
|
130
|
+
this.#elementBlacklistRegExp = converter.createElementBlacklist(
|
|
131
|
+
options.get('elementBlacklist').replace('|//', '|<!--|-->'),
|
|
132
|
+
);
|
|
119
133
|
// attributes
|
|
120
134
|
const regEndStr = '\\s*=\\s*(")[^"]*\\1';
|
|
121
135
|
const _wAttr = options.get('attributeWhitelist');
|
|
@@ -134,7 +148,16 @@ class HTML {
|
|
|
134
148
|
}
|
|
135
149
|
}
|
|
136
150
|
|
|
137
|
-
this.#attributeWhitelistRegExp = new RegExp(
|
|
151
|
+
this.#attributeWhitelistRegExp = new RegExp(
|
|
152
|
+
'\\s(?:' +
|
|
153
|
+
(allAttr || defaultAttr) +
|
|
154
|
+
'|' +
|
|
155
|
+
REQUIRED_DATA_ATTRS +
|
|
156
|
+
(options.get('v2Migration') ? V2_MIG_DATA_ATTRS : '') +
|
|
157
|
+
')' +
|
|
158
|
+
regEndStr,
|
|
159
|
+
'ig',
|
|
160
|
+
);
|
|
138
161
|
this.#attributeWhitelist = tagsAttr;
|
|
139
162
|
|
|
140
163
|
// blacklist
|
|
@@ -166,7 +189,7 @@ class HTML {
|
|
|
166
189
|
* @param {Object} params - Filtering parameters.
|
|
167
190
|
* @param {string} [params.tagWhitelist] - Allowed tags, specified as a string with tags separated by `'|'`. (e.g. `"div|p|span"`).
|
|
168
191
|
* @param {string} [params.tagBlacklist] - Disallowed tags, specified as a string with tags separated by `'|'`. (e.g. `"script|iframe"`).
|
|
169
|
-
* @param {(node:
|
|
192
|
+
* @param {(node: *) => Node | string | null} [params.validate] - Function to validate and modify individual nodes.
|
|
170
193
|
* - Return `null` to remove the node.
|
|
171
194
|
* - Return a `Node` to replace the current node.
|
|
172
195
|
* - Return a `string` to replace the node's `outerHTML`.
|
|
@@ -244,14 +267,18 @@ class HTML {
|
|
|
244
267
|
* });
|
|
245
268
|
*/
|
|
246
269
|
clean(html, { forceFormat, whitelist, blacklist, _freeCodeViewMode } = {}) {
|
|
247
|
-
const { tagFilter, formatFilter, classFilter, textStyleTagFilter, attrFilter, styleFilter } =
|
|
270
|
+
const { tagFilter, formatFilter, classFilter, textStyleTagFilter, attrFilter, styleFilter } =
|
|
271
|
+
this.#options.get('strictMode');
|
|
248
272
|
let cleanData = '';
|
|
249
273
|
|
|
250
274
|
html = this.compress(html);
|
|
251
275
|
|
|
252
276
|
if (tagFilter) {
|
|
253
277
|
html = html.replace(this.#disallowedTagsRegExp, '');
|
|
254
|
-
html = this.#deleteDisallowedTags(html, this.#elementWhitelistRegExp, this.#elementBlacklistRegExp).replace(
|
|
278
|
+
html = this.#deleteDisallowedTags(html, this.#elementWhitelistRegExp, this.#elementBlacklistRegExp).replace(
|
|
279
|
+
/<br\/?>$/i,
|
|
280
|
+
'',
|
|
281
|
+
);
|
|
255
282
|
}
|
|
256
283
|
|
|
257
284
|
if (this.#autoStyleify) {
|
|
@@ -269,7 +296,15 @@ class HTML {
|
|
|
269
296
|
|
|
270
297
|
if (tagFilter) {
|
|
271
298
|
try {
|
|
272
|
-
this.#consistencyCheckOfHTML(
|
|
299
|
+
this.#consistencyCheckOfHTML(
|
|
300
|
+
domParser,
|
|
301
|
+
this.#htmlCheckWhitelistRegExp,
|
|
302
|
+
this.#htmlCheckBlacklistRegExp,
|
|
303
|
+
tagFilter,
|
|
304
|
+
formatFilter,
|
|
305
|
+
classFilter,
|
|
306
|
+
_freeCodeViewMode,
|
|
307
|
+
);
|
|
273
308
|
} catch (error) {
|
|
274
309
|
console.warn('[SUNEDITOR.html.clean.fail]', error.message);
|
|
275
310
|
}
|
|
@@ -314,8 +349,16 @@ class HTML {
|
|
|
314
349
|
|
|
315
350
|
// whitelist, blacklist
|
|
316
351
|
if (tagFilter) {
|
|
317
|
-
if (whitelist)
|
|
318
|
-
|
|
352
|
+
if (whitelist)
|
|
353
|
+
cleanData = cleanData.replace(
|
|
354
|
+
typeof whitelist === 'string' ? converter.createElementWhitelist(whitelist) : whitelist,
|
|
355
|
+
'',
|
|
356
|
+
);
|
|
357
|
+
if (blacklist)
|
|
358
|
+
cleanData = cleanData.replace(
|
|
359
|
+
typeof blacklist === 'string' ? converter.createElementBlacklist(blacklist) : blacklist,
|
|
360
|
+
'',
|
|
361
|
+
);
|
|
319
362
|
}
|
|
320
363
|
|
|
321
364
|
if (textStyleTagFilter) {
|
|
@@ -345,7 +388,8 @@ class HTML {
|
|
|
345
388
|
* editor.html.insert('<div class="custom">Content</div>', { skipCleaning: true });
|
|
346
389
|
*/
|
|
347
390
|
insert(html, { selectInserted, skipCharCount, skipCleaning } = {}) {
|
|
348
|
-
if (!this.#frameContext.get('wysiwyg').contains(this.#$.selection.get().focusNode))
|
|
391
|
+
if (!this.#frameContext.get('wysiwyg').contains(this.#$.selection.get().focusNode))
|
|
392
|
+
this.#$.focusManager.focus();
|
|
349
393
|
|
|
350
394
|
this.remove();
|
|
351
395
|
this.#$.focusManager.focus();
|
|
@@ -364,7 +408,8 @@ class HTML {
|
|
|
364
408
|
const domTree = domParser.childNodes;
|
|
365
409
|
|
|
366
410
|
if (!skipCharCount) {
|
|
367
|
-
const type =
|
|
411
|
+
const type =
|
|
412
|
+
this.#frameOptions.get('charCounter_type') === 'byte-html' ? 'outerHTML' : 'textContent';
|
|
368
413
|
let checkHTML = '';
|
|
369
414
|
for (let i = 0, len = domTree.length; i < len; i++) {
|
|
370
415
|
checkHTML += domTree[i][type];
|
|
@@ -462,13 +507,18 @@ class HTML {
|
|
|
462
507
|
let range = null;
|
|
463
508
|
|
|
464
509
|
if (afterNode) {
|
|
465
|
-
const afterNewLine =
|
|
510
|
+
const afterNewLine =
|
|
511
|
+
this.#$.format.isLine(afterNode) || this.#$.format.isBlock(afterNode) || this.#$.component.is(afterNode)
|
|
512
|
+
? this.#$.format.addLine(afterNode, null)
|
|
513
|
+
: afterNode;
|
|
466
514
|
range = this.#$.selection.setRange(afterNewLine, 1, afterNewLine, 1);
|
|
467
515
|
} else {
|
|
468
516
|
range = this.#$.selection.getRange();
|
|
469
517
|
}
|
|
470
518
|
|
|
471
|
-
let line = dom.check.isListCell(range.commonAncestorContainer)
|
|
519
|
+
let line = dom.check.isListCell(range.commonAncestorContainer)
|
|
520
|
+
? range.commonAncestorContainer
|
|
521
|
+
: this.#$.format.getLine(this.#$.selection.getNode(), null);
|
|
472
522
|
let insertListCell = dom.check.isListCell(line) && (dom.check.isListCell(oNode) || dom.check.isList(oNode));
|
|
473
523
|
|
|
474
524
|
let parentNode,
|
|
@@ -476,7 +526,8 @@ class HTML {
|
|
|
476
526
|
tempAfterNode,
|
|
477
527
|
tempParentNode = null;
|
|
478
528
|
const freeFormat = this.#$.format.isBrLine(line);
|
|
479
|
-
const isFormats =
|
|
529
|
+
const isFormats =
|
|
530
|
+
this.#$.format.isLine(oNode) || this.#$.format.isBlock(oNode) || this.#$.component.isBasic(oNode);
|
|
480
531
|
|
|
481
532
|
if (insertListCell) {
|
|
482
533
|
tempAfterNode = afterNode || dom.check.isList(oNode) ? line.lastChild : line.nextElementSibling;
|
|
@@ -511,7 +562,11 @@ class HTML {
|
|
|
511
562
|
const depthFormat = dom.query.getParentElement(container, (current) => {
|
|
512
563
|
return this.#$.format.isBlock(current) || dom.check.isListCell(current);
|
|
513
564
|
});
|
|
514
|
-
afterNode = this.#$.nodeTransform.split(
|
|
565
|
+
afterNode = this.#$.nodeTransform.split(
|
|
566
|
+
container,
|
|
567
|
+
r.offset,
|
|
568
|
+
!depthFormat ? 0 : dom.query.getNodeDepth(depthFormat) + 1,
|
|
569
|
+
);
|
|
515
570
|
if (!afterNode) {
|
|
516
571
|
if (!dom.check.isListCell(line)) {
|
|
517
572
|
tempAfterNode = afterNode = line;
|
|
@@ -522,7 +577,11 @@ class HTML {
|
|
|
522
577
|
let newCell = null;
|
|
523
578
|
if (!isEdge) {
|
|
524
579
|
newCell = line.cloneNode(false);
|
|
525
|
-
newCell.appendChild(
|
|
580
|
+
newCell.appendChild(
|
|
581
|
+
afterNode.textContent.trim()
|
|
582
|
+
? afterNode
|
|
583
|
+
: dom.utils.createTextNode(unicode.zeroWidthSpace),
|
|
584
|
+
);
|
|
526
585
|
}
|
|
527
586
|
if (subList) {
|
|
528
587
|
if (!newCell) {
|
|
@@ -542,13 +601,22 @@ class HTML {
|
|
|
542
601
|
}
|
|
543
602
|
}
|
|
544
603
|
|
|
545
|
-
range =
|
|
604
|
+
range =
|
|
605
|
+
!afterNode && !isFormats
|
|
606
|
+
? this.#$.selection.getRangeAndAddLine(this.#$.selection.getRange(), null)
|
|
607
|
+
: this.#$.selection.getRange();
|
|
546
608
|
const commonCon = range.commonAncestorContainer;
|
|
547
609
|
const startOff = range.startOffset;
|
|
548
610
|
const endOff = range.endOffset;
|
|
549
611
|
const formatRange = range.startContainer === commonCon && this.#$.format.isLine(commonCon);
|
|
550
|
-
const startCon = formatRange
|
|
551
|
-
|
|
612
|
+
const startCon = formatRange
|
|
613
|
+
? commonCon.childNodes[startOff] || commonCon.childNodes[0] || range.startContainer
|
|
614
|
+
: range.startContainer;
|
|
615
|
+
const endCon = formatRange
|
|
616
|
+
? commonCon.childNodes[endOff] ||
|
|
617
|
+
commonCon.childNodes[commonCon.childNodes.length - 1] ||
|
|
618
|
+
range.endContainer
|
|
619
|
+
: range.endContainer;
|
|
552
620
|
|
|
553
621
|
if (!insertListCell) {
|
|
554
622
|
if (!afterNode) {
|
|
@@ -560,18 +628,25 @@ class HTML {
|
|
|
560
628
|
/** No Select range node */
|
|
561
629
|
if (range.collapsed) {
|
|
562
630
|
if (commonCon.nodeType === 3) {
|
|
563
|
-
if (commonCon.textContent.length > endOff)
|
|
631
|
+
if (commonCon.textContent.length > endOff)
|
|
632
|
+
afterNode = /** @type {Text} */ (commonCon).splitText(endOff);
|
|
564
633
|
else afterNode = commonCon.nextSibling;
|
|
565
634
|
} else {
|
|
566
635
|
if (!dom.check.isBreak(parentNode)) {
|
|
567
636
|
const c = parentNode.childNodes[startOff];
|
|
568
|
-
const focusNode =
|
|
637
|
+
const focusNode =
|
|
638
|
+
c?.nodeType === 3 && dom.check.isZeroWidth(c) && dom.check.isBreak(c.nextSibling)
|
|
639
|
+
? c.nextSibling
|
|
640
|
+
: c;
|
|
569
641
|
if (focusNode) {
|
|
570
642
|
if (!focusNode.nextSibling && dom.check.isBreak(focusNode)) {
|
|
571
643
|
parentNode.removeChild(focusNode);
|
|
572
644
|
afterNode = null;
|
|
573
645
|
} else {
|
|
574
|
-
afterNode =
|
|
646
|
+
afterNode =
|
|
647
|
+
dom.check.isBreak(focusNode) && !dom.check.isBreak(oNode)
|
|
648
|
+
? focusNode
|
|
649
|
+
: focusNode.nextSibling;
|
|
575
650
|
}
|
|
576
651
|
} else {
|
|
577
652
|
afterNode = null;
|
|
@@ -590,7 +665,8 @@ class HTML {
|
|
|
590
665
|
else afterNode = /** @type {Text} */ (endCon).splitText(endOff);
|
|
591
666
|
|
|
592
667
|
let removeNode = startCon;
|
|
593
|
-
if (!dom.check.isEdgePoint(startCon, startOff))
|
|
668
|
+
if (!dom.check.isEdgePoint(startCon, startOff))
|
|
669
|
+
removeNode = /** @type {Text} */ (startCon).splitText(startOff);
|
|
594
670
|
|
|
595
671
|
parentNode.removeChild(removeNode);
|
|
596
672
|
if (parentNode.childNodes.length === 0 && isFormats) {
|
|
@@ -605,7 +681,12 @@ class HTML {
|
|
|
605
681
|
if (this.#$.format.isLine(container)) {
|
|
606
682
|
container.innerHTML = '<br>';
|
|
607
683
|
} else if (this.#$.format.isBlock(container)) {
|
|
608
|
-
container.innerHTML =
|
|
684
|
+
container.innerHTML =
|
|
685
|
+
'<' +
|
|
686
|
+
this.#options.get('defaultLine') +
|
|
687
|
+
'><br></' +
|
|
688
|
+
this.#options.get('defaultLine') +
|
|
689
|
+
'>';
|
|
609
690
|
}
|
|
610
691
|
}
|
|
611
692
|
|
|
@@ -626,10 +707,16 @@ class HTML {
|
|
|
626
707
|
afterNode = null;
|
|
627
708
|
}
|
|
628
709
|
} else if (dom.check.isWysiwygFrame(container) && !this.#$.format.isLine(oNode)) {
|
|
629
|
-
parentNode = container.appendChild(
|
|
710
|
+
parentNode = container.appendChild(
|
|
711
|
+
dom.utils.createElement(this.#options.get('defaultLine')),
|
|
712
|
+
);
|
|
630
713
|
afterNode = null;
|
|
631
714
|
} else {
|
|
632
|
-
afterNode = isFormats
|
|
715
|
+
afterNode = isFormats
|
|
716
|
+
? endCon
|
|
717
|
+
: container === prevContainer
|
|
718
|
+
? container.nextSibling
|
|
719
|
+
: container;
|
|
633
720
|
parentNode = !afterNode || !afterNode.parentNode ? commonCon : afterNode.parentNode;
|
|
634
721
|
}
|
|
635
722
|
|
|
@@ -655,13 +742,22 @@ class HTML {
|
|
|
655
742
|
afterNode = null;
|
|
656
743
|
}
|
|
657
744
|
|
|
658
|
-
if (
|
|
745
|
+
if (
|
|
746
|
+
this.#$.format.isLine(oNode) ||
|
|
747
|
+
this.#$.format.isBlock(oNode) ||
|
|
748
|
+
(!dom.check.isListCell(parentNode) && this.#$.component.isBasic(oNode))
|
|
749
|
+
) {
|
|
659
750
|
const oldParent = parentNode;
|
|
660
751
|
if (dom.check.isListCell(afterNode)) {
|
|
661
752
|
parentNode = afterNode.previousElementSibling || afterNode;
|
|
662
753
|
} else if (!originAfter && !afterNode) {
|
|
663
754
|
const r = this.remove();
|
|
664
|
-
const container =
|
|
755
|
+
const container =
|
|
756
|
+
r.container.nodeType === 3
|
|
757
|
+
? dom.check.isListCell(this.#$.format.getLine(r.container, null))
|
|
758
|
+
? r.container
|
|
759
|
+
: this.#$.format.getLine(r.container, null) || r.container.parentNode
|
|
760
|
+
: r.container;
|
|
665
761
|
const rangeCon = dom.check.isWysiwygFrame(container) || this.#$.format.isBlock(container);
|
|
666
762
|
parentNode = rangeCon ? container : container.parentNode;
|
|
667
763
|
afterNode = rangeCon ? null : container.nextSibling;
|
|
@@ -670,7 +766,13 @@ class HTML {
|
|
|
670
766
|
if (oldParent.childNodes.length === 0 && parentNode !== oldParent) dom.utils.removeItem(oldParent);
|
|
671
767
|
}
|
|
672
768
|
|
|
673
|
-
if (
|
|
769
|
+
if (
|
|
770
|
+
isFormats &&
|
|
771
|
+
!freeFormat &&
|
|
772
|
+
!this.#$.format.isBlock(parentNode) &&
|
|
773
|
+
!dom.check.isListCell(parentNode) &&
|
|
774
|
+
!dom.check.isWysiwygFrame(parentNode)
|
|
775
|
+
) {
|
|
674
776
|
afterNode = /** @type {HTMLElement} */ (parentNode).nextElementSibling;
|
|
675
777
|
parentNode = parentNode.parentNode;
|
|
676
778
|
}
|
|
@@ -762,7 +864,11 @@ class HTML {
|
|
|
762
864
|
}
|
|
763
865
|
}
|
|
764
866
|
|
|
765
|
-
if (
|
|
867
|
+
if (
|
|
868
|
+
freeFormat &&
|
|
869
|
+
!dom.check.isList(oNode) &&
|
|
870
|
+
(this.#$.format.isLine(oNode) || this.#$.format.isBlock(oNode))
|
|
871
|
+
) {
|
|
766
872
|
oNode = this.#setIntoFreeFormat(oNode);
|
|
767
873
|
}
|
|
768
874
|
|
|
@@ -771,7 +877,11 @@ class HTML {
|
|
|
771
877
|
if (oNode.nodeType === 3) {
|
|
772
878
|
offset = oNode.textContent.length;
|
|
773
879
|
this.#$.selection.setRange(oNode, offset, oNode, offset);
|
|
774
|
-
} else if (
|
|
880
|
+
} else if (
|
|
881
|
+
!dom.check.isBreak(oNode) &&
|
|
882
|
+
!dom.check.isListCell(oNode) &&
|
|
883
|
+
this.#$.format.isLine(parentNode)
|
|
884
|
+
) {
|
|
775
885
|
let zeroWidth = null;
|
|
776
886
|
if (!oNode.previousSibling || dom.check.isBreak(oNode.previousSibling)) {
|
|
777
887
|
zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
@@ -831,7 +941,12 @@ class HTML {
|
|
|
831
941
|
let endCon = range.endContainer;
|
|
832
942
|
let startOff = range.startOffset;
|
|
833
943
|
let endOff = range.endOffset;
|
|
834
|
-
const commonCon = /** @type {HTMLElement} */ (
|
|
944
|
+
const commonCon = /** @type {HTMLElement} */ (
|
|
945
|
+
range.commonAncestorContainer.nodeType === 3 &&
|
|
946
|
+
range.commonAncestorContainer.parentNode === startCon.parentNode
|
|
947
|
+
? startCon.parentNode
|
|
948
|
+
: range.commonAncestorContainer
|
|
949
|
+
);
|
|
835
950
|
|
|
836
951
|
if (dom.check.isWysiwygFrame(startCon) && dom.check.isWysiwygFrame(endCon)) {
|
|
837
952
|
this.set('');
|
|
@@ -852,7 +967,8 @@ class HTML {
|
|
|
852
967
|
const next = compContainer.nextSibling || compContainer.previousSibling;
|
|
853
968
|
const nextOffset = next === compContainer.previousSibling ? next?.textContent?.length || 1 : 0;
|
|
854
969
|
const parentNext = parent.nextElementSibling || parent.previousElementSibling;
|
|
855
|
-
const parentNextOffset =
|
|
970
|
+
const parentNextOffset =
|
|
971
|
+
parentNext === parent.previousElementSibling ? parentNext?.textContent?.length || 1 : 0;
|
|
856
972
|
|
|
857
973
|
dom.utils.removeItem(compContainer);
|
|
858
974
|
|
|
@@ -879,7 +995,10 @@ class HTML {
|
|
|
879
995
|
};
|
|
880
996
|
}
|
|
881
997
|
} else {
|
|
882
|
-
if (
|
|
998
|
+
if (
|
|
999
|
+
(commonCon.nodeType === 1 && startOff === 0 && endOff === 1) ||
|
|
1000
|
+
(commonCon.nodeType === 3 && startOff === 0 && endOff === commonCon.textContent.length)
|
|
1001
|
+
) {
|
|
883
1002
|
const nextEl = dom.query.getNextDeepestNode(commonCon, this.#frameContext.get('wysiwyg'));
|
|
884
1003
|
const prevEl = dom.query.getPreviousDeepestNode(commonCon, this.#frameContext.get('wysiwyg'));
|
|
885
1004
|
const line = this.#$.format.getLine(commonCon);
|
|
@@ -938,7 +1057,11 @@ class HTML {
|
|
|
938
1057
|
|
|
939
1058
|
if (childNodes.length > 0 && startIndex > -1 && endIndex > -1) {
|
|
940
1059
|
for (let i = startIndex + 1, startNode = startCon; i >= 0; i--) {
|
|
941
|
-
if (
|
|
1060
|
+
if (
|
|
1061
|
+
childNodes[i] === startNode.parentNode &&
|
|
1062
|
+
childNodes[i].firstChild === startNode &&
|
|
1063
|
+
startOff === 0
|
|
1064
|
+
) {
|
|
942
1065
|
startIndex = i;
|
|
943
1066
|
startNode = startNode.parentNode;
|
|
944
1067
|
}
|
|
@@ -953,7 +1076,13 @@ class HTML {
|
|
|
953
1076
|
}
|
|
954
1077
|
} else {
|
|
955
1078
|
if (childNodes.length === 0) {
|
|
956
|
-
if (
|
|
1079
|
+
if (
|
|
1080
|
+
this.#$.format.isLine(commonCon) ||
|
|
1081
|
+
this.#$.format.isBlock(commonCon) ||
|
|
1082
|
+
dom.check.isWysiwygFrame(commonCon) ||
|
|
1083
|
+
dom.check.isBreak(commonCon) ||
|
|
1084
|
+
dom.check.isMedia(commonCon)
|
|
1085
|
+
) {
|
|
957
1086
|
return {
|
|
958
1087
|
container: commonCon,
|
|
959
1088
|
offset: 0,
|
|
@@ -1002,7 +1131,9 @@ class HTML {
|
|
|
1002
1131
|
const sc = /** @type {Text} */ (startCon);
|
|
1003
1132
|
const ec = /** @type {Text} */ (endCon);
|
|
1004
1133
|
if (item === endCon) {
|
|
1005
|
-
beforeNode = dom.utils.createTextNode(
|
|
1134
|
+
beforeNode = dom.utils.createTextNode(
|
|
1135
|
+
sc.substringData(0, startOff) + ec.substringData(endOff, ec.length - endOff),
|
|
1136
|
+
);
|
|
1006
1137
|
offset = startOff;
|
|
1007
1138
|
} else {
|
|
1008
1139
|
beforeNode = dom.utils.createTextNode(sc.substringData(0, startOff));
|
|
@@ -1045,7 +1176,12 @@ class HTML {
|
|
|
1045
1176
|
container = endUl.previousSibling;
|
|
1046
1177
|
offset = container.textContent.length;
|
|
1047
1178
|
} else {
|
|
1048
|
-
container =
|
|
1179
|
+
container =
|
|
1180
|
+
endCon && endCon.parentNode
|
|
1181
|
+
? endCon
|
|
1182
|
+
: startCon && startCon.parentNode
|
|
1183
|
+
? startCon
|
|
1184
|
+
: range.endContainer || range.startContainer;
|
|
1049
1185
|
if (isStartEdge || isEndEdge) {
|
|
1050
1186
|
if (isEndEdge) {
|
|
1051
1187
|
if (container.nodeType === 1 && container.childNodes.length === 0) {
|
|
@@ -1075,7 +1211,10 @@ class HTML {
|
|
|
1075
1211
|
if (rc) container = rc.sc || rc.ec || this.#frameContext.get('wysiwyg');
|
|
1076
1212
|
}
|
|
1077
1213
|
|
|
1078
|
-
if (
|
|
1214
|
+
if (
|
|
1215
|
+
!container ||
|
|
1216
|
+
(container.nodeType === 1 && !this.#$.format.isLine(container) && !dom.check.isBreak(container))
|
|
1217
|
+
) {
|
|
1079
1218
|
container = nextFocusNodes?.sc || nextFocusNodes?.ec;
|
|
1080
1219
|
offset = container?.nodeType === 3 ? container.textContent.length : 1;
|
|
1081
1220
|
}
|
|
@@ -1112,7 +1251,18 @@ class HTML {
|
|
|
1112
1251
|
for (let i = 0, len = rootKey.length, r; i < len; i++) {
|
|
1113
1252
|
this.#$.facade.changeFrameContext(rootKey[i]);
|
|
1114
1253
|
|
|
1115
|
-
const renderHTML = dom.utils.createElement(
|
|
1254
|
+
const renderHTML = dom.utils.createElement(
|
|
1255
|
+
'DIV',
|
|
1256
|
+
null,
|
|
1257
|
+
this._convertToCode(this.#frameContext.get('wysiwyg'), true),
|
|
1258
|
+
);
|
|
1259
|
+
|
|
1260
|
+
const phLines = renderHTML.querySelectorAll('.se-placeholder-line');
|
|
1261
|
+
for (let j = 0, jlen = phLines.length; j < jlen; j++) {
|
|
1262
|
+
phLines[j].classList.remove('se-placeholder-line');
|
|
1263
|
+
phLines[j].removeAttribute('data-se-placeholder-line');
|
|
1264
|
+
if (!phLines[j].getAttribute('class')) phLines[j].removeAttribute('class');
|
|
1265
|
+
}
|
|
1116
1266
|
|
|
1117
1267
|
const isTableCell = dom.check.isTableCell;
|
|
1118
1268
|
const isEmptyLine = dom.check.isEmptyLine;
|
|
@@ -1147,13 +1297,17 @@ class HTML {
|
|
|
1147
1297
|
const content = renderHTML.innerHTML;
|
|
1148
1298
|
if (this.#frameOptions.get('iframe_fullPage')) {
|
|
1149
1299
|
if (includeFullPage) {
|
|
1150
|
-
const attrs = dom.utils.getAttributesToString(this.#frameContext.get('_wd').body, [
|
|
1300
|
+
const attrs = dom.utils.getAttributesToString(this.#frameContext.get('_wd').body, [
|
|
1301
|
+
'contenteditable',
|
|
1302
|
+
]);
|
|
1151
1303
|
r = `<!DOCTYPE html><html>${this.#frameContext.get('_wd').head.outerHTML}<body ${attrs}>${content}</body></html>`;
|
|
1152
1304
|
} else {
|
|
1153
1305
|
r = content;
|
|
1154
1306
|
}
|
|
1155
1307
|
} else {
|
|
1156
|
-
r = withFrame
|
|
1308
|
+
r = withFrame
|
|
1309
|
+
? `<div class="${this.#options.get('_editableClass') + '' + (this.#options.get('_rtl') ? ' se-rtl' : '')}">${content}</div>`
|
|
1310
|
+
: renderHTML.innerHTML;
|
|
1157
1311
|
}
|
|
1158
1312
|
|
|
1159
1313
|
resultValue[rootKey[i]] = r;
|
|
@@ -1175,7 +1329,10 @@ class HTML {
|
|
|
1175
1329
|
set(html, { rootKey } = {}) {
|
|
1176
1330
|
this.#$.ui.offCurrentController();
|
|
1177
1331
|
this.#$.selection.removeRange();
|
|
1178
|
-
const convertValue =
|
|
1332
|
+
const convertValue =
|
|
1333
|
+
html === null || html === undefined
|
|
1334
|
+
? ''
|
|
1335
|
+
: this.clean(html, { forceFormat: true, whitelist: null, blacklist: null });
|
|
1179
1336
|
|
|
1180
1337
|
if (!rootKey) rootKey = [this.#store.get('rootKey')];
|
|
1181
1338
|
else if (!Array.isArray(rootKey)) rootKey = [rootKey];
|
|
@@ -1225,7 +1382,9 @@ class HTML {
|
|
|
1225
1382
|
this.#$.history.push(false, rootKey[i]);
|
|
1226
1383
|
this.#$.selection.scrollTo(children.at(-1));
|
|
1227
1384
|
} else {
|
|
1228
|
-
this.#$.viewer._setCodeView(
|
|
1385
|
+
this.#$.viewer._setCodeView(
|
|
1386
|
+
this.#$.viewer._getCodeView() + '\n' + this._convertToCode(convertValue, false),
|
|
1387
|
+
);
|
|
1229
1388
|
}
|
|
1230
1389
|
}
|
|
1231
1390
|
}
|
|
@@ -1268,10 +1427,15 @@ class HTML {
|
|
|
1268
1427
|
*/
|
|
1269
1428
|
async copy(content) {
|
|
1270
1429
|
try {
|
|
1271
|
-
if (typeof content !== 'string' && !dom.check.isElement(content) && !dom.check.isText(content))
|
|
1430
|
+
if (typeof content !== 'string' && !dom.check.isElement(content) && !dom.check.isText(content))
|
|
1431
|
+
return false;
|
|
1272
1432
|
|
|
1273
1433
|
if ((await clipboard.write(content)) === false) {
|
|
1274
|
-
this.#$.ui.showToast(
|
|
1434
|
+
this.#$.ui.showToast(
|
|
1435
|
+
this.#$.lang.message_copy_fail,
|
|
1436
|
+
this.#options.get('toastMessageTime').copy,
|
|
1437
|
+
'error',
|
|
1438
|
+
);
|
|
1275
1439
|
return false;
|
|
1276
1440
|
}
|
|
1277
1441
|
this.#$.ui.showToast(this.#$.lang.message_copy_success, this.#options.get('toastMessageTime').copy);
|
|
@@ -1297,8 +1461,14 @@ class HTML {
|
|
|
1297
1461
|
|
|
1298
1462
|
for (let i = 0; i < rootKey.length; i++) {
|
|
1299
1463
|
this.#$.facade.changeFrameContext(rootKey[i]);
|
|
1300
|
-
if (ctx.head)
|
|
1301
|
-
|
|
1464
|
+
if (ctx.head)
|
|
1465
|
+
this.#frameContext.get('_wd').head.innerHTML = ctx.head.replace(this.#disallowedTagsRegExp, '');
|
|
1466
|
+
if (ctx.body)
|
|
1467
|
+
this.#frameContext.get('_wd').body.innerHTML = this.clean(ctx.body, {
|
|
1468
|
+
forceFormat: true,
|
|
1469
|
+
whitelist: null,
|
|
1470
|
+
blacklist: null,
|
|
1471
|
+
});
|
|
1302
1472
|
this.#$.pluginManager.resetFileInfo();
|
|
1303
1473
|
}
|
|
1304
1474
|
}
|
|
@@ -1322,7 +1492,10 @@ class HTML {
|
|
|
1322
1492
|
_convertToCode(html, comp) {
|
|
1323
1493
|
let returnHTML = '';
|
|
1324
1494
|
const wRegExp = RegExp;
|
|
1325
|
-
const brReg = new wRegExp(
|
|
1495
|
+
const brReg = new wRegExp(
|
|
1496
|
+
'^(BLOCKQUOTE|PRE|TABLE|THEAD|TBODY|TR|TH|TD|OL|UL|IMG|IFRAME|VIDEO|AUDIO|FIGURE|FIGCAPTION|HR|BR|CANVAS|SELECT)$',
|
|
1497
|
+
'i',
|
|
1498
|
+
);
|
|
1326
1499
|
const wDoc = typeof html === 'string' ? _d.createRange().createContextualFragment(html) : html;
|
|
1327
1500
|
const isFormat = (current) => {
|
|
1328
1501
|
return this.#$.format.isLine(current) || this.#$.component.is(current);
|
|
@@ -1350,11 +1523,20 @@ class HTML {
|
|
|
1350
1523
|
continue;
|
|
1351
1524
|
}
|
|
1352
1525
|
if (node.nodeType === 3) {
|
|
1353
|
-
if (!dom.check.isList(node.parentElement))
|
|
1526
|
+
if (!dom.check.isList(node.parentElement))
|
|
1527
|
+
returnHTML += converter.htmlToEntity(
|
|
1528
|
+
/^\n+$/.test(/** @type {Text} */ (node).data) ? '' : /** @type {Text} */ (node).data,
|
|
1529
|
+
);
|
|
1354
1530
|
continue;
|
|
1355
1531
|
}
|
|
1356
1532
|
if (node.childNodes.length === 0) {
|
|
1357
|
-
returnHTML +=
|
|
1533
|
+
returnHTML +=
|
|
1534
|
+
(/^HR$/i.test(node.nodeName) ? brChar : '') +
|
|
1535
|
+
(/^PRE$/i.test(node.parentElement.nodeName) && /^BR$/i.test(node.nodeName)
|
|
1536
|
+
? ''
|
|
1537
|
+
: elementIndent) +
|
|
1538
|
+
/** @type {HTMLElement} */ (node).outerHTML +
|
|
1539
|
+
br;
|
|
1358
1540
|
continue;
|
|
1359
1541
|
}
|
|
1360
1542
|
|
|
@@ -1363,9 +1545,18 @@ class HTML {
|
|
|
1363
1545
|
} else {
|
|
1364
1546
|
tag = node.nodeName.toLowerCase();
|
|
1365
1547
|
tagIndent = elementIndent || nodeRegTest ? indent : '';
|
|
1366
|
-
returnHTML +=
|
|
1548
|
+
returnHTML +=
|
|
1549
|
+
(lineBR || (elementRegTest ? '' : br)) +
|
|
1550
|
+
tagIndent +
|
|
1551
|
+
/** @type {HTMLElement} */ (node).outerHTML.match(wRegExp('<' + tag + '[^>]*>', 'i'))[0] +
|
|
1552
|
+
br;
|
|
1367
1553
|
recursionFunc(node, indent + indentSize + '');
|
|
1368
|
-
returnHTML +=
|
|
1554
|
+
returnHTML +=
|
|
1555
|
+
(/\n$/.test(returnHTML) ? tagIndent : '') +
|
|
1556
|
+
'</' +
|
|
1557
|
+
tag +
|
|
1558
|
+
'>' +
|
|
1559
|
+
(lineBR || br || elementRegTest ? brChar : /^(TH|TD)$/i.test(node.nodeName) ? brChar : '');
|
|
1369
1560
|
}
|
|
1370
1561
|
}
|
|
1371
1562
|
})(wDoc, '');
|
|
@@ -1443,7 +1634,10 @@ class HTML {
|
|
|
1443
1634
|
dom.query.getListChildNodes(
|
|
1444
1635
|
node,
|
|
1445
1636
|
(current) => {
|
|
1446
|
-
return
|
|
1637
|
+
return (
|
|
1638
|
+
dom.check.isSpanWithoutAttr(current) &&
|
|
1639
|
+
!dom.query.getParentElement(current, dom.check.isExcludeFormat)
|
|
1640
|
+
);
|
|
1447
1641
|
},
|
|
1448
1642
|
null,
|
|
1449
1643
|
) || [];
|
|
@@ -1465,7 +1659,15 @@ class HTML {
|
|
|
1465
1659
|
return dom.check.isSpanWithoutAttr(node) ? n.innerHTML : n.outerHTML;
|
|
1466
1660
|
} else {
|
|
1467
1661
|
const n = /** @type {HTMLElement} */ (node);
|
|
1468
|
-
return
|
|
1662
|
+
return (
|
|
1663
|
+
'<' +
|
|
1664
|
+
defaultLine +
|
|
1665
|
+
'>' +
|
|
1666
|
+
(dom.check.isSpanWithoutAttr(node) ? n.innerHTML : n.outerHTML) +
|
|
1667
|
+
'</' +
|
|
1668
|
+
defaultLine +
|
|
1669
|
+
'>'
|
|
1670
|
+
);
|
|
1469
1671
|
}
|
|
1470
1672
|
}
|
|
1471
1673
|
// text
|
|
@@ -1475,7 +1677,8 @@ class HTML {
|
|
|
1475
1677
|
let html = '';
|
|
1476
1678
|
for (let i = 0, tLen = textArray.length, text; i < tLen; i++) {
|
|
1477
1679
|
text = textArray[i].trim();
|
|
1478
|
-
if (text.length > 0)
|
|
1680
|
+
if (text.length > 0)
|
|
1681
|
+
html += '<' + defaultLine + '>' + converter.htmlToEntity(text) + '</' + defaultLine + '>';
|
|
1479
1682
|
}
|
|
1480
1683
|
return html;
|
|
1481
1684
|
}
|
|
@@ -1487,6 +1690,23 @@ class HTML {
|
|
|
1487
1690
|
return '';
|
|
1488
1691
|
}
|
|
1489
1692
|
|
|
1693
|
+
/**
|
|
1694
|
+
* @description Checks whether a node is a block-level container in which whitespace-only text
|
|
1695
|
+
* children are insignificant formatting whitespace (safe to drop), as opposed to an inline/line
|
|
1696
|
+
* @param {?Node} node Parent node of the whitespace text node (may be a `DocumentFragment`).
|
|
1697
|
+
* @returns {boolean} `true` if the node is a block-level container.
|
|
1698
|
+
*/
|
|
1699
|
+
#isBlockLevelWhitespaceContext(node) {
|
|
1700
|
+
return (
|
|
1701
|
+
!node ||
|
|
1702
|
+
node.nodeType === 11 ||
|
|
1703
|
+
dom.check.isWysiwygFrame(node) ||
|
|
1704
|
+
dom.check.isList(node) ||
|
|
1705
|
+
dom.check.isTableElements(node) ||
|
|
1706
|
+
this.#$.format.isBlock(node)
|
|
1707
|
+
);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1490
1710
|
/**
|
|
1491
1711
|
* @description Fix tags that do not fit the editor format.
|
|
1492
1712
|
* @param {DocumentFragment} documentFragment Document fragment `DOCUMENT_FRAGMENT_NODE` (nodeType === 11)
|
|
@@ -1497,7 +1717,15 @@ class HTML {
|
|
|
1497
1717
|
* @param {boolean} classFilter Class name filter option
|
|
1498
1718
|
* @param {boolean} _freeCodeViewMode Enforces strict HTML validation based on the editor`s policy
|
|
1499
1719
|
*/
|
|
1500
|
-
#consistencyCheckOfHTML(
|
|
1720
|
+
#consistencyCheckOfHTML(
|
|
1721
|
+
documentFragment,
|
|
1722
|
+
htmlCheckWhitelistRegExp,
|
|
1723
|
+
htmlCheckBlacklistRegExp,
|
|
1724
|
+
tagFilter,
|
|
1725
|
+
formatFilter,
|
|
1726
|
+
classFilter,
|
|
1727
|
+
_freeCodeViewMode,
|
|
1728
|
+
) {
|
|
1501
1729
|
const removeTags = [],
|
|
1502
1730
|
emptyTags = [],
|
|
1503
1731
|
wrongList = [],
|
|
@@ -1509,14 +1737,29 @@ class HTML {
|
|
|
1509
1737
|
(current) => {
|
|
1510
1738
|
if (current.nodeType !== 1) {
|
|
1511
1739
|
if (formatFilter && dom.check.isList(current.parentElement)) removeTags.push(current);
|
|
1512
|
-
if (current.nodeType === 3
|
|
1740
|
+
if (current.nodeType === 3) {
|
|
1741
|
+
// Remove empty text nodes, and collapsible whitespace-only nodes that render nothing
|
|
1742
|
+
if (
|
|
1743
|
+
!current.textContent ||
|
|
1744
|
+
(_RE_INSIGNIFICANT_WS.test(current.textContent) &&
|
|
1745
|
+
(this.#isBlockLevelWhitespaceContext(current.parentNode) ||
|
|
1746
|
+
!current.previousSibling !== !current.nextSibling))
|
|
1747
|
+
) {
|
|
1748
|
+
removeTags.push(current);
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1513
1751
|
return false;
|
|
1514
1752
|
}
|
|
1515
1753
|
|
|
1516
1754
|
// tag filter
|
|
1517
1755
|
if (tagFilter) {
|
|
1518
1756
|
// white list
|
|
1519
|
-
if (
|
|
1757
|
+
if (
|
|
1758
|
+
htmlCheckBlacklistRegExp.test(current.nodeName) ||
|
|
1759
|
+
(!htmlCheckWhitelistRegExp.test(current.nodeName) &&
|
|
1760
|
+
current.childNodes.length === 0 &&
|
|
1761
|
+
dom.check.isExcludeFormat(current))
|
|
1762
|
+
) {
|
|
1520
1763
|
removeTags.push(current);
|
|
1521
1764
|
return false;
|
|
1522
1765
|
}
|
|
@@ -1534,7 +1777,9 @@ class HTML {
|
|
|
1534
1777
|
!dom.check.isTableElements(current) &&
|
|
1535
1778
|
!dom.check.isListCell(current) &&
|
|
1536
1779
|
!dom.check.isAnchor(current) &&
|
|
1537
|
-
(this.#$.format.isLine(current) ||
|
|
1780
|
+
(this.#$.format.isLine(current) ||
|
|
1781
|
+
this.#$.format.isBlock(current) ||
|
|
1782
|
+
this.#$.format.isTextStyleNode(current)) &&
|
|
1538
1783
|
current.childNodes.length === 0 &&
|
|
1539
1784
|
nrtag
|
|
1540
1785
|
) {
|
|
@@ -1543,7 +1788,11 @@ class HTML {
|
|
|
1543
1788
|
}
|
|
1544
1789
|
|
|
1545
1790
|
// wrong list
|
|
1546
|
-
if (
|
|
1791
|
+
if (
|
|
1792
|
+
dom.check.isList(current.parentNode) &&
|
|
1793
|
+
!dom.check.isList(current) &&
|
|
1794
|
+
!dom.check.isListCell(current)
|
|
1795
|
+
) {
|
|
1547
1796
|
wrongList.push(current);
|
|
1548
1797
|
return false;
|
|
1549
1798
|
}
|
|
@@ -1577,7 +1826,9 @@ class HTML {
|
|
|
1577
1826
|
current.parentNode !== documentFragment &&
|
|
1578
1827
|
nrtag &&
|
|
1579
1828
|
((dom.check.isListCell(current) && !dom.check.isList(current.parentNode)) ||
|
|
1580
|
-
((this.#$.format.isLine(current) || this.#$.component.is(current)) &&
|
|
1829
|
+
((this.#$.format.isLine(current) || this.#$.component.is(current)) &&
|
|
1830
|
+
!this.#$.format.isBlock(current.parentNode) &&
|
|
1831
|
+
!dom.query.getParentElement(current, this.#$.component.is.bind(this.#$.component))));
|
|
1581
1832
|
|
|
1582
1833
|
return result;
|
|
1583
1834
|
},
|
|
@@ -1701,7 +1952,13 @@ class HTML {
|
|
|
1701
1952
|
|
|
1702
1953
|
if (n.nodeType === 8) {
|
|
1703
1954
|
value += '<!-- ' + n.textContent + ' -->';
|
|
1704
|
-
} else if (
|
|
1955
|
+
} else if (
|
|
1956
|
+
!/meta/i.test(n.nodeName) &&
|
|
1957
|
+
!this.#$.format.isLine(n) &&
|
|
1958
|
+
!this.#$.format.isBlock(n) &&
|
|
1959
|
+
!this.#$.component.is(n) &&
|
|
1960
|
+
!dom.check.isExcludeFormat(n)
|
|
1961
|
+
) {
|
|
1705
1962
|
f ||= dom.utils.createElement(this.#options.get('defaultLine'));
|
|
1706
1963
|
if (this.#$.format.isTextStyleNode(n)) {
|
|
1707
1964
|
/** @type {HTMLElement} */
|
|
@@ -1766,7 +2023,12 @@ class HTML {
|
|
|
1766
2023
|
|
|
1767
2024
|
for (let i = 0, len = domTree.length, t; i < len; i++) {
|
|
1768
2025
|
t = domTree[i];
|
|
1769
|
-
if (
|
|
2026
|
+
if (
|
|
2027
|
+
t.nodeType === 1 &&
|
|
2028
|
+
!this.#$.format.isTextStyleNode(t) &&
|
|
2029
|
+
!dom.check.isBreak(t) &&
|
|
2030
|
+
!this.#disallowedTagNameRegExp.test(t.nodeName)
|
|
2031
|
+
) {
|
|
1770
2032
|
requireFormat = true;
|
|
1771
2033
|
break;
|
|
1772
2034
|
}
|
|
@@ -1790,7 +2052,12 @@ class HTML {
|
|
|
1790
2052
|
const face = (m.match(_RE_FACE_ATTR) || [])[1];
|
|
1791
2053
|
const color = (m.match(_RE_COLOR_ATTR) || [])[1];
|
|
1792
2054
|
if (size || face || color) {
|
|
1793
|
-
sv =
|
|
2055
|
+
sv =
|
|
2056
|
+
'style="' +
|
|
2057
|
+
(size ? 'font-size:' + numbers.get(Number(size) / 3.333, 1) + 'rem;' : '') +
|
|
2058
|
+
(face ? 'font-family:' + face + ';' : '') +
|
|
2059
|
+
(color ? 'color:' + color + ';' : '') +
|
|
2060
|
+
'"';
|
|
1794
2061
|
}
|
|
1795
2062
|
}
|
|
1796
2063
|
|
|
@@ -1823,7 +2090,10 @@ class HTML {
|
|
|
1823
2090
|
case 'fontSize':
|
|
1824
2091
|
if (!this.#$.plugins.fontSize) continue;
|
|
1825
2092
|
if (!this.#fontSizeUnitRegExp.test(r[0])) {
|
|
1826
|
-
r[0] = r[0].replace(
|
|
2093
|
+
r[0] = r[0].replace(
|
|
2094
|
+
(r[0].match(_RE_CSS_VALUE) || [])[1],
|
|
2095
|
+
converter.toFontUnit.bind(null, this.#options.get('fontSizeUnits')[0]),
|
|
2096
|
+
);
|
|
1827
2097
|
}
|
|
1828
2098
|
break;
|
|
1829
2099
|
case 'color':
|
|
@@ -2003,10 +2273,16 @@ class HTML {
|
|
|
2003
2273
|
styleToTag.italic = { regex: /font-style\s*:\s*italic/i, tag: convertTextTags.italic };
|
|
2004
2274
|
break;
|
|
2005
2275
|
case 'underline':
|
|
2006
|
-
styleToTag.underline = {
|
|
2276
|
+
styleToTag.underline = {
|
|
2277
|
+
regex: /text-decoration\s*:\s*underline/i,
|
|
2278
|
+
tag: convertTextTags.underline,
|
|
2279
|
+
};
|
|
2007
2280
|
break;
|
|
2008
2281
|
case 'strike':
|
|
2009
|
-
styleToTag.strike = {
|
|
2282
|
+
styleToTag.strike = {
|
|
2283
|
+
regex: /text-decoration\s*:\s*line-through/i,
|
|
2284
|
+
tag: convertTextTags.strike,
|
|
2285
|
+
};
|
|
2010
2286
|
break;
|
|
2011
2287
|
}
|
|
2012
2288
|
});
|
|
@@ -2084,6 +2360,8 @@ const _RE_LEADING_SPACE = /^\s/;
|
|
|
2084
2360
|
|
|
2085
2361
|
// #cleanStyle
|
|
2086
2362
|
const _RE_TAG_ATTRS = /<[^\s]+\s(.+)/;
|
|
2363
|
+
// #consistencyCheckOfHTML: collapsible ASCII whitespace only (excludes /zero-width, which are meaningful content)
|
|
2364
|
+
const _RE_INSIGNIFICANT_WS = /^[ \t\n\r\f\v]+$/;
|
|
2087
2365
|
const _RE_SIZE_ATTR = /\ssize="([^"]+)"/i;
|
|
2088
2366
|
const _RE_FACE_ATTR = /\sface="([^"]+)"/i;
|
|
2089
2367
|
const _RE_COLOR_ATTR = /\scolor="([^"]+)"/i;
|