suneditor 3.1.3 → 3.2.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.
- 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 +480 -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 +136 -23
- 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 +9 -2
- package/src/core/event/handlers/handler_ww_key.js +86 -17
- package/src/core/event/handlers/handler_ww_mouse.js +45 -8
- package/src/core/event/ports.js +23 -5
- package/src/core/event/reducers/keydown.reducer.js +15 -2
- 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 +357 -87
- 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 +61 -19
- package/src/core/section/constructor.js +537 -103
- 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 +68 -23
- package/src/modules/contract/ColorPicker.js +12 -4
- package/src/modules/contract/Controller.js +37 -7
- package/src/modules/contract/Figure.js +159 -36
- package/src/modules/contract/HueSlider.js +27 -4
- package/src/modules/contract/Modal.js +62 -11
- package/src/modules/manager/FileManager.js +50 -8
- package/src/modules/ui/CommandMenu.js +597 -0
- package/src/modules/ui/ModalAnchorEditor.js +41 -9
- package/src/modules/ui/SelectMenu.js +481 -36
- package/src/modules/ui/index.js +1 -0
- package/src/plugins/browser/audioGallery.js +8 -1
- package/src/plugins/browser/fileBrowser.js +15 -2
- package/src/plugins/browser/fileGallery.js +8 -1
- package/src/plugins/browser/imageGallery.js +24 -3
- package/src/plugins/browser/videoGallery.js +19 -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 +132 -22
- package/src/plugins/modal/image/index.js +115 -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 +6 -1
- 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 +7 -2
- 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 +110 -37
- 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/Browser.d.ts +7 -7
- 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/ModalAnchorEditor.d.ts +6 -1
- 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 +17 -1
- package/types/plugins/browser/fileBrowser.d.ts +17 -1
- package/types/plugins/browser/fileGallery.d.ts +17 -1
- package/types/plugins/browser/imageGallery.d.ts +17 -1
- package/types/plugins/browser/videoGallery.d.ts +17 -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/embed.d.ts +34 -0
- package/types/plugins/modal/link.d.ts +4 -1
- package/types/typedef.d.ts +48 -23
|
@@ -77,18 +77,10 @@ class HTML {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
const stylesMap = new Map();
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
line: options.get('_lineStylesRegExp'),
|
|
83
|
-
};
|
|
84
|
-
this.#textStyleTags.forEach((v) => {
|
|
85
|
-
stylesObj[v] = options.get('_textStylesRegExp');
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
for (const key in stylesObj) {
|
|
89
|
-
stylesMap.set(new RegExp(`^(${key})$`), stylesObj[key]);
|
|
80
|
+
for (const key in splitTagStyles) {
|
|
81
|
+
stylesMap.set(new RegExp(`^(${key})$`), splitTagStyles[key]);
|
|
90
82
|
}
|
|
91
|
-
this.#cleanStyleTagKeyRegExp = new RegExp(`^(${Object.keys(
|
|
83
|
+
this.#cleanStyleTagKeyRegExp = new RegExp(`^(${Object.keys(splitTagStyles).join('|')})$`, 'i');
|
|
92
84
|
this.#cleanStyleRegExpMap = stylesMap;
|
|
93
85
|
|
|
94
86
|
// font size unit
|
|
@@ -97,7 +89,10 @@ class HTML {
|
|
|
97
89
|
// extra tags
|
|
98
90
|
const allowedExtraTags = options.get('_allowedExtraTag');
|
|
99
91
|
const disallowedExtraTags = options.get('_disallowedExtraTag');
|
|
100
|
-
this.#disallowedTagsRegExp = new RegExp(
|
|
92
|
+
this.#disallowedTagsRegExp = new RegExp(
|
|
93
|
+
`<(${disallowedExtraTags})[^>]*>([\\s\\S]*?)<\\/\\1>|<(${disallowedExtraTags})[^>]*\\/?>`,
|
|
94
|
+
'gi',
|
|
95
|
+
);
|
|
101
96
|
this.#disallowedTagNameRegExp = new RegExp(`^(${disallowedExtraTags})$`, 'i');
|
|
102
97
|
this.#allowedTagNameRegExp = new RegExp(`^(${allowedExtraTags})$`, 'i');
|
|
103
98
|
|
|
@@ -112,18 +107,29 @@ class HTML {
|
|
|
112
107
|
for (let i = 0; i < allowStyleNodes.length; i++) {
|
|
113
108
|
disallowStyleNodes.splice(disallowStyleNodes.indexOf(allowStyleNodes[i].toLowerCase()), 1);
|
|
114
109
|
}
|
|
115
|
-
this.#disallowedStyleNodesRegExp =
|
|
110
|
+
this.#disallowedStyleNodesRegExp =
|
|
111
|
+
disallowStyleNodes.length === 0
|
|
112
|
+
? null
|
|
113
|
+
: new RegExp('(<\\/?)(' + disallowStyleNodes.join('|') + ')\\b\\s*([^>^<]+)?\\s*(?=>)', 'gi');
|
|
116
114
|
|
|
117
115
|
// whitelist
|
|
118
116
|
// tags
|
|
119
117
|
const defaultAttr = options.get('__defaultAttributeWhitelist');
|
|
120
|
-
this.#allowHTMLComment =
|
|
118
|
+
this.#allowHTMLComment =
|
|
119
|
+
options.get('_editorElementWhitelist').includes('//') || options.get('_editorElementWhitelist') === '*';
|
|
121
120
|
// html check
|
|
122
|
-
this.#htmlCheckWhitelistRegExp = new RegExp(
|
|
121
|
+
this.#htmlCheckWhitelistRegExp = new RegExp(
|
|
122
|
+
'^(' + GetRegList(options.get('_editorElementWhitelist').replace('|//', ''), '') + ')$',
|
|
123
|
+
'i',
|
|
124
|
+
);
|
|
123
125
|
this.#htmlCheckBlacklistRegExp = new RegExp('^(' + (options.get('elementBlacklist') || '^') + ')$', 'i');
|
|
124
126
|
// elements
|
|
125
|
-
this.#elementWhitelistRegExp = converter.createElementWhitelist(
|
|
126
|
-
|
|
127
|
+
this.#elementWhitelistRegExp = converter.createElementWhitelist(
|
|
128
|
+
GetRegList(options.get('_editorElementWhitelist').replace('|//', '|<!--|-->'), ''),
|
|
129
|
+
);
|
|
130
|
+
this.#elementBlacklistRegExp = converter.createElementBlacklist(
|
|
131
|
+
options.get('elementBlacklist').replace('|//', '|<!--|-->'),
|
|
132
|
+
);
|
|
127
133
|
// attributes
|
|
128
134
|
const regEndStr = '\\s*=\\s*(")[^"]*\\1';
|
|
129
135
|
const _wAttr = options.get('attributeWhitelist');
|
|
@@ -142,7 +148,16 @@ class HTML {
|
|
|
142
148
|
}
|
|
143
149
|
}
|
|
144
150
|
|
|
145
|
-
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
|
+
);
|
|
146
161
|
this.#attributeWhitelist = tagsAttr;
|
|
147
162
|
|
|
148
163
|
// blacklist
|
|
@@ -174,7 +189,7 @@ class HTML {
|
|
|
174
189
|
* @param {Object} params - Filtering parameters.
|
|
175
190
|
* @param {string} [params.tagWhitelist] - Allowed tags, specified as a string with tags separated by `'|'`. (e.g. `"div|p|span"`).
|
|
176
191
|
* @param {string} [params.tagBlacklist] - Disallowed tags, specified as a string with tags separated by `'|'`. (e.g. `"script|iframe"`).
|
|
177
|
-
* @param {(node:
|
|
192
|
+
* @param {(node: *) => Node | string | null} [params.validate] - Function to validate and modify individual nodes.
|
|
178
193
|
* - Return `null` to remove the node.
|
|
179
194
|
* - Return a `Node` to replace the current node.
|
|
180
195
|
* - Return a `string` to replace the node's `outerHTML`.
|
|
@@ -252,14 +267,18 @@ class HTML {
|
|
|
252
267
|
* });
|
|
253
268
|
*/
|
|
254
269
|
clean(html, { forceFormat, whitelist, blacklist, _freeCodeViewMode } = {}) {
|
|
255
|
-
const { tagFilter, formatFilter, classFilter, textStyleTagFilter, attrFilter, styleFilter } =
|
|
270
|
+
const { tagFilter, formatFilter, classFilter, textStyleTagFilter, attrFilter, styleFilter } =
|
|
271
|
+
this.#options.get('strictMode');
|
|
256
272
|
let cleanData = '';
|
|
257
273
|
|
|
258
274
|
html = this.compress(html);
|
|
259
275
|
|
|
260
276
|
if (tagFilter) {
|
|
261
277
|
html = html.replace(this.#disallowedTagsRegExp, '');
|
|
262
|
-
html = this.#deleteDisallowedTags(html, this.#elementWhitelistRegExp, this.#elementBlacklistRegExp).replace(
|
|
278
|
+
html = this.#deleteDisallowedTags(html, this.#elementWhitelistRegExp, this.#elementBlacklistRegExp).replace(
|
|
279
|
+
/<br\/?>$/i,
|
|
280
|
+
'',
|
|
281
|
+
);
|
|
263
282
|
}
|
|
264
283
|
|
|
265
284
|
if (this.#autoStyleify) {
|
|
@@ -277,7 +296,15 @@ class HTML {
|
|
|
277
296
|
|
|
278
297
|
if (tagFilter) {
|
|
279
298
|
try {
|
|
280
|
-
this.#consistencyCheckOfHTML(
|
|
299
|
+
this.#consistencyCheckOfHTML(
|
|
300
|
+
domParser,
|
|
301
|
+
this.#htmlCheckWhitelistRegExp,
|
|
302
|
+
this.#htmlCheckBlacklistRegExp,
|
|
303
|
+
tagFilter,
|
|
304
|
+
formatFilter,
|
|
305
|
+
classFilter,
|
|
306
|
+
_freeCodeViewMode,
|
|
307
|
+
);
|
|
281
308
|
} catch (error) {
|
|
282
309
|
console.warn('[SUNEDITOR.html.clean.fail]', error.message);
|
|
283
310
|
}
|
|
@@ -322,8 +349,16 @@ class HTML {
|
|
|
322
349
|
|
|
323
350
|
// whitelist, blacklist
|
|
324
351
|
if (tagFilter) {
|
|
325
|
-
if (whitelist)
|
|
326
|
-
|
|
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
|
+
);
|
|
327
362
|
}
|
|
328
363
|
|
|
329
364
|
if (textStyleTagFilter) {
|
|
@@ -353,7 +388,8 @@ class HTML {
|
|
|
353
388
|
* editor.html.insert('<div class="custom">Content</div>', { skipCleaning: true });
|
|
354
389
|
*/
|
|
355
390
|
insert(html, { selectInserted, skipCharCount, skipCleaning } = {}) {
|
|
356
|
-
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();
|
|
357
393
|
|
|
358
394
|
this.remove();
|
|
359
395
|
this.#$.focusManager.focus();
|
|
@@ -372,7 +408,8 @@ class HTML {
|
|
|
372
408
|
const domTree = domParser.childNodes;
|
|
373
409
|
|
|
374
410
|
if (!skipCharCount) {
|
|
375
|
-
const type =
|
|
411
|
+
const type =
|
|
412
|
+
this.#frameOptions.get('charCounter_type') === 'byte-html' ? 'outerHTML' : 'textContent';
|
|
376
413
|
let checkHTML = '';
|
|
377
414
|
for (let i = 0, len = domTree.length; i < len; i++) {
|
|
378
415
|
checkHTML += domTree[i][type];
|
|
@@ -470,13 +507,18 @@ class HTML {
|
|
|
470
507
|
let range = null;
|
|
471
508
|
|
|
472
509
|
if (afterNode) {
|
|
473
|
-
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;
|
|
474
514
|
range = this.#$.selection.setRange(afterNewLine, 1, afterNewLine, 1);
|
|
475
515
|
} else {
|
|
476
516
|
range = this.#$.selection.getRange();
|
|
477
517
|
}
|
|
478
518
|
|
|
479
|
-
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);
|
|
480
522
|
let insertListCell = dom.check.isListCell(line) && (dom.check.isListCell(oNode) || dom.check.isList(oNode));
|
|
481
523
|
|
|
482
524
|
let parentNode,
|
|
@@ -484,7 +526,8 @@ class HTML {
|
|
|
484
526
|
tempAfterNode,
|
|
485
527
|
tempParentNode = null;
|
|
486
528
|
const freeFormat = this.#$.format.isBrLine(line);
|
|
487
|
-
const isFormats =
|
|
529
|
+
const isFormats =
|
|
530
|
+
this.#$.format.isLine(oNode) || this.#$.format.isBlock(oNode) || this.#$.component.isBasic(oNode);
|
|
488
531
|
|
|
489
532
|
if (insertListCell) {
|
|
490
533
|
tempAfterNode = afterNode || dom.check.isList(oNode) ? line.lastChild : line.nextElementSibling;
|
|
@@ -519,7 +562,11 @@ class HTML {
|
|
|
519
562
|
const depthFormat = dom.query.getParentElement(container, (current) => {
|
|
520
563
|
return this.#$.format.isBlock(current) || dom.check.isListCell(current);
|
|
521
564
|
});
|
|
522
|
-
afterNode = this.#$.nodeTransform.split(
|
|
565
|
+
afterNode = this.#$.nodeTransform.split(
|
|
566
|
+
container,
|
|
567
|
+
r.offset,
|
|
568
|
+
!depthFormat ? 0 : dom.query.getNodeDepth(depthFormat) + 1,
|
|
569
|
+
);
|
|
523
570
|
if (!afterNode) {
|
|
524
571
|
if (!dom.check.isListCell(line)) {
|
|
525
572
|
tempAfterNode = afterNode = line;
|
|
@@ -530,7 +577,11 @@ class HTML {
|
|
|
530
577
|
let newCell = null;
|
|
531
578
|
if (!isEdge) {
|
|
532
579
|
newCell = line.cloneNode(false);
|
|
533
|
-
newCell.appendChild(
|
|
580
|
+
newCell.appendChild(
|
|
581
|
+
afterNode.textContent.trim()
|
|
582
|
+
? afterNode
|
|
583
|
+
: dom.utils.createTextNode(unicode.zeroWidthSpace),
|
|
584
|
+
);
|
|
534
585
|
}
|
|
535
586
|
if (subList) {
|
|
536
587
|
if (!newCell) {
|
|
@@ -550,13 +601,22 @@ class HTML {
|
|
|
550
601
|
}
|
|
551
602
|
}
|
|
552
603
|
|
|
553
|
-
range =
|
|
604
|
+
range =
|
|
605
|
+
!afterNode && !isFormats
|
|
606
|
+
? this.#$.selection.getRangeAndAddLine(this.#$.selection.getRange(), null)
|
|
607
|
+
: this.#$.selection.getRange();
|
|
554
608
|
const commonCon = range.commonAncestorContainer;
|
|
555
609
|
const startOff = range.startOffset;
|
|
556
610
|
const endOff = range.endOffset;
|
|
557
611
|
const formatRange = range.startContainer === commonCon && this.#$.format.isLine(commonCon);
|
|
558
|
-
const startCon = formatRange
|
|
559
|
-
|
|
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;
|
|
560
620
|
|
|
561
621
|
if (!insertListCell) {
|
|
562
622
|
if (!afterNode) {
|
|
@@ -568,18 +628,25 @@ class HTML {
|
|
|
568
628
|
/** No Select range node */
|
|
569
629
|
if (range.collapsed) {
|
|
570
630
|
if (commonCon.nodeType === 3) {
|
|
571
|
-
if (commonCon.textContent.length > endOff)
|
|
631
|
+
if (commonCon.textContent.length > endOff)
|
|
632
|
+
afterNode = /** @type {Text} */ (commonCon).splitText(endOff);
|
|
572
633
|
else afterNode = commonCon.nextSibling;
|
|
573
634
|
} else {
|
|
574
635
|
if (!dom.check.isBreak(parentNode)) {
|
|
575
636
|
const c = parentNode.childNodes[startOff];
|
|
576
|
-
const focusNode =
|
|
637
|
+
const focusNode =
|
|
638
|
+
c?.nodeType === 3 && dom.check.isZeroWidth(c) && dom.check.isBreak(c.nextSibling)
|
|
639
|
+
? c.nextSibling
|
|
640
|
+
: c;
|
|
577
641
|
if (focusNode) {
|
|
578
642
|
if (!focusNode.nextSibling && dom.check.isBreak(focusNode)) {
|
|
579
643
|
parentNode.removeChild(focusNode);
|
|
580
644
|
afterNode = null;
|
|
581
645
|
} else {
|
|
582
|
-
afterNode =
|
|
646
|
+
afterNode =
|
|
647
|
+
dom.check.isBreak(focusNode) && !dom.check.isBreak(oNode)
|
|
648
|
+
? focusNode
|
|
649
|
+
: focusNode.nextSibling;
|
|
583
650
|
}
|
|
584
651
|
} else {
|
|
585
652
|
afterNode = null;
|
|
@@ -598,7 +665,8 @@ class HTML {
|
|
|
598
665
|
else afterNode = /** @type {Text} */ (endCon).splitText(endOff);
|
|
599
666
|
|
|
600
667
|
let removeNode = startCon;
|
|
601
|
-
if (!dom.check.isEdgePoint(startCon, startOff))
|
|
668
|
+
if (!dom.check.isEdgePoint(startCon, startOff))
|
|
669
|
+
removeNode = /** @type {Text} */ (startCon).splitText(startOff);
|
|
602
670
|
|
|
603
671
|
parentNode.removeChild(removeNode);
|
|
604
672
|
if (parentNode.childNodes.length === 0 && isFormats) {
|
|
@@ -613,7 +681,12 @@ class HTML {
|
|
|
613
681
|
if (this.#$.format.isLine(container)) {
|
|
614
682
|
container.innerHTML = '<br>';
|
|
615
683
|
} else if (this.#$.format.isBlock(container)) {
|
|
616
|
-
container.innerHTML =
|
|
684
|
+
container.innerHTML =
|
|
685
|
+
'<' +
|
|
686
|
+
this.#options.get('defaultLine') +
|
|
687
|
+
'><br></' +
|
|
688
|
+
this.#options.get('defaultLine') +
|
|
689
|
+
'>';
|
|
617
690
|
}
|
|
618
691
|
}
|
|
619
692
|
|
|
@@ -634,10 +707,16 @@ class HTML {
|
|
|
634
707
|
afterNode = null;
|
|
635
708
|
}
|
|
636
709
|
} else if (dom.check.isWysiwygFrame(container) && !this.#$.format.isLine(oNode)) {
|
|
637
|
-
parentNode = container.appendChild(
|
|
710
|
+
parentNode = container.appendChild(
|
|
711
|
+
dom.utils.createElement(this.#options.get('defaultLine')),
|
|
712
|
+
);
|
|
638
713
|
afterNode = null;
|
|
639
714
|
} else {
|
|
640
|
-
afterNode = isFormats
|
|
715
|
+
afterNode = isFormats
|
|
716
|
+
? endCon
|
|
717
|
+
: container === prevContainer
|
|
718
|
+
? container.nextSibling
|
|
719
|
+
: container;
|
|
641
720
|
parentNode = !afterNode || !afterNode.parentNode ? commonCon : afterNode.parentNode;
|
|
642
721
|
}
|
|
643
722
|
|
|
@@ -663,13 +742,22 @@ class HTML {
|
|
|
663
742
|
afterNode = null;
|
|
664
743
|
}
|
|
665
744
|
|
|
666
|
-
if (
|
|
745
|
+
if (
|
|
746
|
+
this.#$.format.isLine(oNode) ||
|
|
747
|
+
this.#$.format.isBlock(oNode) ||
|
|
748
|
+
(!dom.check.isListCell(parentNode) && this.#$.component.isBasic(oNode))
|
|
749
|
+
) {
|
|
667
750
|
const oldParent = parentNode;
|
|
668
751
|
if (dom.check.isListCell(afterNode)) {
|
|
669
752
|
parentNode = afterNode.previousElementSibling || afterNode;
|
|
670
753
|
} else if (!originAfter && !afterNode) {
|
|
671
754
|
const r = this.remove();
|
|
672
|
-
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;
|
|
673
761
|
const rangeCon = dom.check.isWysiwygFrame(container) || this.#$.format.isBlock(container);
|
|
674
762
|
parentNode = rangeCon ? container : container.parentNode;
|
|
675
763
|
afterNode = rangeCon ? null : container.nextSibling;
|
|
@@ -678,7 +766,13 @@ class HTML {
|
|
|
678
766
|
if (oldParent.childNodes.length === 0 && parentNode !== oldParent) dom.utils.removeItem(oldParent);
|
|
679
767
|
}
|
|
680
768
|
|
|
681
|
-
if (
|
|
769
|
+
if (
|
|
770
|
+
isFormats &&
|
|
771
|
+
!freeFormat &&
|
|
772
|
+
!this.#$.format.isBlock(parentNode) &&
|
|
773
|
+
!dom.check.isListCell(parentNode) &&
|
|
774
|
+
!dom.check.isWysiwygFrame(parentNode)
|
|
775
|
+
) {
|
|
682
776
|
afterNode = /** @type {HTMLElement} */ (parentNode).nextElementSibling;
|
|
683
777
|
parentNode = parentNode.parentNode;
|
|
684
778
|
}
|
|
@@ -770,7 +864,11 @@ class HTML {
|
|
|
770
864
|
}
|
|
771
865
|
}
|
|
772
866
|
|
|
773
|
-
if (
|
|
867
|
+
if (
|
|
868
|
+
freeFormat &&
|
|
869
|
+
!dom.check.isList(oNode) &&
|
|
870
|
+
(this.#$.format.isLine(oNode) || this.#$.format.isBlock(oNode))
|
|
871
|
+
) {
|
|
774
872
|
oNode = this.#setIntoFreeFormat(oNode);
|
|
775
873
|
}
|
|
776
874
|
|
|
@@ -779,7 +877,11 @@ class HTML {
|
|
|
779
877
|
if (oNode.nodeType === 3) {
|
|
780
878
|
offset = oNode.textContent.length;
|
|
781
879
|
this.#$.selection.setRange(oNode, offset, oNode, offset);
|
|
782
|
-
} else if (
|
|
880
|
+
} else if (
|
|
881
|
+
!dom.check.isBreak(oNode) &&
|
|
882
|
+
!dom.check.isListCell(oNode) &&
|
|
883
|
+
this.#$.format.isLine(parentNode)
|
|
884
|
+
) {
|
|
783
885
|
let zeroWidth = null;
|
|
784
886
|
if (!oNode.previousSibling || dom.check.isBreak(oNode.previousSibling)) {
|
|
785
887
|
zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
@@ -839,7 +941,12 @@ class HTML {
|
|
|
839
941
|
let endCon = range.endContainer;
|
|
840
942
|
let startOff = range.startOffset;
|
|
841
943
|
let endOff = range.endOffset;
|
|
842
|
-
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
|
+
);
|
|
843
950
|
|
|
844
951
|
if (dom.check.isWysiwygFrame(startCon) && dom.check.isWysiwygFrame(endCon)) {
|
|
845
952
|
this.set('');
|
|
@@ -860,7 +967,8 @@ class HTML {
|
|
|
860
967
|
const next = compContainer.nextSibling || compContainer.previousSibling;
|
|
861
968
|
const nextOffset = next === compContainer.previousSibling ? next?.textContent?.length || 1 : 0;
|
|
862
969
|
const parentNext = parent.nextElementSibling || parent.previousElementSibling;
|
|
863
|
-
const parentNextOffset =
|
|
970
|
+
const parentNextOffset =
|
|
971
|
+
parentNext === parent.previousElementSibling ? parentNext?.textContent?.length || 1 : 0;
|
|
864
972
|
|
|
865
973
|
dom.utils.removeItem(compContainer);
|
|
866
974
|
|
|
@@ -887,7 +995,10 @@ class HTML {
|
|
|
887
995
|
};
|
|
888
996
|
}
|
|
889
997
|
} else {
|
|
890
|
-
if (
|
|
998
|
+
if (
|
|
999
|
+
(commonCon.nodeType === 1 && startOff === 0 && endOff === 1) ||
|
|
1000
|
+
(commonCon.nodeType === 3 && startOff === 0 && endOff === commonCon.textContent.length)
|
|
1001
|
+
) {
|
|
891
1002
|
const nextEl = dom.query.getNextDeepestNode(commonCon, this.#frameContext.get('wysiwyg'));
|
|
892
1003
|
const prevEl = dom.query.getPreviousDeepestNode(commonCon, this.#frameContext.get('wysiwyg'));
|
|
893
1004
|
const line = this.#$.format.getLine(commonCon);
|
|
@@ -946,7 +1057,11 @@ class HTML {
|
|
|
946
1057
|
|
|
947
1058
|
if (childNodes.length > 0 && startIndex > -1 && endIndex > -1) {
|
|
948
1059
|
for (let i = startIndex + 1, startNode = startCon; i >= 0; i--) {
|
|
949
|
-
if (
|
|
1060
|
+
if (
|
|
1061
|
+
childNodes[i] === startNode.parentNode &&
|
|
1062
|
+
childNodes[i].firstChild === startNode &&
|
|
1063
|
+
startOff === 0
|
|
1064
|
+
) {
|
|
950
1065
|
startIndex = i;
|
|
951
1066
|
startNode = startNode.parentNode;
|
|
952
1067
|
}
|
|
@@ -961,7 +1076,13 @@ class HTML {
|
|
|
961
1076
|
}
|
|
962
1077
|
} else {
|
|
963
1078
|
if (childNodes.length === 0) {
|
|
964
|
-
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
|
+
) {
|
|
965
1086
|
return {
|
|
966
1087
|
container: commonCon,
|
|
967
1088
|
offset: 0,
|
|
@@ -1010,7 +1131,9 @@ class HTML {
|
|
|
1010
1131
|
const sc = /** @type {Text} */ (startCon);
|
|
1011
1132
|
const ec = /** @type {Text} */ (endCon);
|
|
1012
1133
|
if (item === endCon) {
|
|
1013
|
-
beforeNode = dom.utils.createTextNode(
|
|
1134
|
+
beforeNode = dom.utils.createTextNode(
|
|
1135
|
+
sc.substringData(0, startOff) + ec.substringData(endOff, ec.length - endOff),
|
|
1136
|
+
);
|
|
1014
1137
|
offset = startOff;
|
|
1015
1138
|
} else {
|
|
1016
1139
|
beforeNode = dom.utils.createTextNode(sc.substringData(0, startOff));
|
|
@@ -1053,7 +1176,12 @@ class HTML {
|
|
|
1053
1176
|
container = endUl.previousSibling;
|
|
1054
1177
|
offset = container.textContent.length;
|
|
1055
1178
|
} else {
|
|
1056
|
-
container =
|
|
1179
|
+
container =
|
|
1180
|
+
endCon && endCon.parentNode
|
|
1181
|
+
? endCon
|
|
1182
|
+
: startCon && startCon.parentNode
|
|
1183
|
+
? startCon
|
|
1184
|
+
: range.endContainer || range.startContainer;
|
|
1057
1185
|
if (isStartEdge || isEndEdge) {
|
|
1058
1186
|
if (isEndEdge) {
|
|
1059
1187
|
if (container.nodeType === 1 && container.childNodes.length === 0) {
|
|
@@ -1083,7 +1211,10 @@ class HTML {
|
|
|
1083
1211
|
if (rc) container = rc.sc || rc.ec || this.#frameContext.get('wysiwyg');
|
|
1084
1212
|
}
|
|
1085
1213
|
|
|
1086
|
-
if (
|
|
1214
|
+
if (
|
|
1215
|
+
!container ||
|
|
1216
|
+
(container.nodeType === 1 && !this.#$.format.isLine(container) && !dom.check.isBreak(container))
|
|
1217
|
+
) {
|
|
1087
1218
|
container = nextFocusNodes?.sc || nextFocusNodes?.ec;
|
|
1088
1219
|
offset = container?.nodeType === 3 ? container.textContent.length : 1;
|
|
1089
1220
|
}
|
|
@@ -1120,7 +1251,18 @@ class HTML {
|
|
|
1120
1251
|
for (let i = 0, len = rootKey.length, r; i < len; i++) {
|
|
1121
1252
|
this.#$.facade.changeFrameContext(rootKey[i]);
|
|
1122
1253
|
|
|
1123
|
-
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
|
+
}
|
|
1124
1266
|
|
|
1125
1267
|
const isTableCell = dom.check.isTableCell;
|
|
1126
1268
|
const isEmptyLine = dom.check.isEmptyLine;
|
|
@@ -1155,13 +1297,17 @@ class HTML {
|
|
|
1155
1297
|
const content = renderHTML.innerHTML;
|
|
1156
1298
|
if (this.#frameOptions.get('iframe_fullPage')) {
|
|
1157
1299
|
if (includeFullPage) {
|
|
1158
|
-
const attrs = dom.utils.getAttributesToString(this.#frameContext.get('_wd').body, [
|
|
1300
|
+
const attrs = dom.utils.getAttributesToString(this.#frameContext.get('_wd').body, [
|
|
1301
|
+
'contenteditable',
|
|
1302
|
+
]);
|
|
1159
1303
|
r = `<!DOCTYPE html><html>${this.#frameContext.get('_wd').head.outerHTML}<body ${attrs}>${content}</body></html>`;
|
|
1160
1304
|
} else {
|
|
1161
1305
|
r = content;
|
|
1162
1306
|
}
|
|
1163
1307
|
} else {
|
|
1164
|
-
r = withFrame
|
|
1308
|
+
r = withFrame
|
|
1309
|
+
? `<div class="${this.#options.get('_editableClass') + '' + (this.#options.get('_rtl') ? ' se-rtl' : '')}">${content}</div>`
|
|
1310
|
+
: renderHTML.innerHTML;
|
|
1165
1311
|
}
|
|
1166
1312
|
|
|
1167
1313
|
resultValue[rootKey[i]] = r;
|
|
@@ -1183,7 +1329,10 @@ class HTML {
|
|
|
1183
1329
|
set(html, { rootKey } = {}) {
|
|
1184
1330
|
this.#$.ui.offCurrentController();
|
|
1185
1331
|
this.#$.selection.removeRange();
|
|
1186
|
-
const convertValue =
|
|
1332
|
+
const convertValue =
|
|
1333
|
+
html === null || html === undefined
|
|
1334
|
+
? ''
|
|
1335
|
+
: this.clean(html, { forceFormat: true, whitelist: null, blacklist: null });
|
|
1187
1336
|
|
|
1188
1337
|
if (!rootKey) rootKey = [this.#store.get('rootKey')];
|
|
1189
1338
|
else if (!Array.isArray(rootKey)) rootKey = [rootKey];
|
|
@@ -1233,7 +1382,9 @@ class HTML {
|
|
|
1233
1382
|
this.#$.history.push(false, rootKey[i]);
|
|
1234
1383
|
this.#$.selection.scrollTo(children.at(-1));
|
|
1235
1384
|
} else {
|
|
1236
|
-
this.#$.viewer._setCodeView(
|
|
1385
|
+
this.#$.viewer._setCodeView(
|
|
1386
|
+
this.#$.viewer._getCodeView() + '\n' + this._convertToCode(convertValue, false),
|
|
1387
|
+
);
|
|
1237
1388
|
}
|
|
1238
1389
|
}
|
|
1239
1390
|
}
|
|
@@ -1276,10 +1427,15 @@ class HTML {
|
|
|
1276
1427
|
*/
|
|
1277
1428
|
async copy(content) {
|
|
1278
1429
|
try {
|
|
1279
|
-
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;
|
|
1280
1432
|
|
|
1281
1433
|
if ((await clipboard.write(content)) === false) {
|
|
1282
|
-
this.#$.ui.showToast(
|
|
1434
|
+
this.#$.ui.showToast(
|
|
1435
|
+
this.#$.lang.message_copy_fail,
|
|
1436
|
+
this.#options.get('toastMessageTime').copy,
|
|
1437
|
+
'error',
|
|
1438
|
+
);
|
|
1283
1439
|
return false;
|
|
1284
1440
|
}
|
|
1285
1441
|
this.#$.ui.showToast(this.#$.lang.message_copy_success, this.#options.get('toastMessageTime').copy);
|
|
@@ -1305,8 +1461,14 @@ class HTML {
|
|
|
1305
1461
|
|
|
1306
1462
|
for (let i = 0; i < rootKey.length; i++) {
|
|
1307
1463
|
this.#$.facade.changeFrameContext(rootKey[i]);
|
|
1308
|
-
if (ctx.head)
|
|
1309
|
-
|
|
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
|
+
});
|
|
1310
1472
|
this.#$.pluginManager.resetFileInfo();
|
|
1311
1473
|
}
|
|
1312
1474
|
}
|
|
@@ -1330,7 +1492,10 @@ class HTML {
|
|
|
1330
1492
|
_convertToCode(html, comp) {
|
|
1331
1493
|
let returnHTML = '';
|
|
1332
1494
|
const wRegExp = RegExp;
|
|
1333
|
-
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
|
+
);
|
|
1334
1499
|
const wDoc = typeof html === 'string' ? _d.createRange().createContextualFragment(html) : html;
|
|
1335
1500
|
const isFormat = (current) => {
|
|
1336
1501
|
return this.#$.format.isLine(current) || this.#$.component.is(current);
|
|
@@ -1358,11 +1523,20 @@ class HTML {
|
|
|
1358
1523
|
continue;
|
|
1359
1524
|
}
|
|
1360
1525
|
if (node.nodeType === 3) {
|
|
1361
|
-
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
|
+
);
|
|
1362
1530
|
continue;
|
|
1363
1531
|
}
|
|
1364
1532
|
if (node.childNodes.length === 0) {
|
|
1365
|
-
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;
|
|
1366
1540
|
continue;
|
|
1367
1541
|
}
|
|
1368
1542
|
|
|
@@ -1371,9 +1545,18 @@ class HTML {
|
|
|
1371
1545
|
} else {
|
|
1372
1546
|
tag = node.nodeName.toLowerCase();
|
|
1373
1547
|
tagIndent = elementIndent || nodeRegTest ? indent : '';
|
|
1374
|
-
returnHTML +=
|
|
1548
|
+
returnHTML +=
|
|
1549
|
+
(lineBR || (elementRegTest ? '' : br)) +
|
|
1550
|
+
tagIndent +
|
|
1551
|
+
/** @type {HTMLElement} */ (node).outerHTML.match(wRegExp('<' + tag + '[^>]*>', 'i'))[0] +
|
|
1552
|
+
br;
|
|
1375
1553
|
recursionFunc(node, indent + indentSize + '');
|
|
1376
|
-
returnHTML +=
|
|
1554
|
+
returnHTML +=
|
|
1555
|
+
(/\n$/.test(returnHTML) ? tagIndent : '') +
|
|
1556
|
+
'</' +
|
|
1557
|
+
tag +
|
|
1558
|
+
'>' +
|
|
1559
|
+
(lineBR || br || elementRegTest ? brChar : /^(TH|TD)$/i.test(node.nodeName) ? brChar : '');
|
|
1377
1560
|
}
|
|
1378
1561
|
}
|
|
1379
1562
|
})(wDoc, '');
|
|
@@ -1451,7 +1634,10 @@ class HTML {
|
|
|
1451
1634
|
dom.query.getListChildNodes(
|
|
1452
1635
|
node,
|
|
1453
1636
|
(current) => {
|
|
1454
|
-
return
|
|
1637
|
+
return (
|
|
1638
|
+
dom.check.isSpanWithoutAttr(current) &&
|
|
1639
|
+
!dom.query.getParentElement(current, dom.check.isExcludeFormat)
|
|
1640
|
+
);
|
|
1455
1641
|
},
|
|
1456
1642
|
null,
|
|
1457
1643
|
) || [];
|
|
@@ -1473,7 +1659,15 @@ class HTML {
|
|
|
1473
1659
|
return dom.check.isSpanWithoutAttr(node) ? n.innerHTML : n.outerHTML;
|
|
1474
1660
|
} else {
|
|
1475
1661
|
const n = /** @type {HTMLElement} */ (node);
|
|
1476
|
-
return
|
|
1662
|
+
return (
|
|
1663
|
+
'<' +
|
|
1664
|
+
defaultLine +
|
|
1665
|
+
'>' +
|
|
1666
|
+
(dom.check.isSpanWithoutAttr(node) ? n.innerHTML : n.outerHTML) +
|
|
1667
|
+
'</' +
|
|
1668
|
+
defaultLine +
|
|
1669
|
+
'>'
|
|
1670
|
+
);
|
|
1477
1671
|
}
|
|
1478
1672
|
}
|
|
1479
1673
|
// text
|
|
@@ -1483,7 +1677,8 @@ class HTML {
|
|
|
1483
1677
|
let html = '';
|
|
1484
1678
|
for (let i = 0, tLen = textArray.length, text; i < tLen; i++) {
|
|
1485
1679
|
text = textArray[i].trim();
|
|
1486
|
-
if (text.length > 0)
|
|
1680
|
+
if (text.length > 0)
|
|
1681
|
+
html += '<' + defaultLine + '>' + converter.htmlToEntity(text) + '</' + defaultLine + '>';
|
|
1487
1682
|
}
|
|
1488
1683
|
return html;
|
|
1489
1684
|
}
|
|
@@ -1495,6 +1690,23 @@ class HTML {
|
|
|
1495
1690
|
return '';
|
|
1496
1691
|
}
|
|
1497
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
|
+
|
|
1498
1710
|
/**
|
|
1499
1711
|
* @description Fix tags that do not fit the editor format.
|
|
1500
1712
|
* @param {DocumentFragment} documentFragment Document fragment `DOCUMENT_FRAGMENT_NODE` (nodeType === 11)
|
|
@@ -1505,7 +1717,15 @@ class HTML {
|
|
|
1505
1717
|
* @param {boolean} classFilter Class name filter option
|
|
1506
1718
|
* @param {boolean} _freeCodeViewMode Enforces strict HTML validation based on the editor`s policy
|
|
1507
1719
|
*/
|
|
1508
|
-
#consistencyCheckOfHTML(
|
|
1720
|
+
#consistencyCheckOfHTML(
|
|
1721
|
+
documentFragment,
|
|
1722
|
+
htmlCheckWhitelistRegExp,
|
|
1723
|
+
htmlCheckBlacklistRegExp,
|
|
1724
|
+
tagFilter,
|
|
1725
|
+
formatFilter,
|
|
1726
|
+
classFilter,
|
|
1727
|
+
_freeCodeViewMode,
|
|
1728
|
+
) {
|
|
1509
1729
|
const removeTags = [],
|
|
1510
1730
|
emptyTags = [],
|
|
1511
1731
|
wrongList = [],
|
|
@@ -1517,14 +1737,29 @@ class HTML {
|
|
|
1517
1737
|
(current) => {
|
|
1518
1738
|
if (current.nodeType !== 1) {
|
|
1519
1739
|
if (formatFilter && dom.check.isList(current.parentElement)) removeTags.push(current);
|
|
1520
|
-
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
|
+
}
|
|
1521
1751
|
return false;
|
|
1522
1752
|
}
|
|
1523
1753
|
|
|
1524
1754
|
// tag filter
|
|
1525
1755
|
if (tagFilter) {
|
|
1526
1756
|
// white list
|
|
1527
|
-
if (
|
|
1757
|
+
if (
|
|
1758
|
+
htmlCheckBlacklistRegExp.test(current.nodeName) ||
|
|
1759
|
+
(!htmlCheckWhitelistRegExp.test(current.nodeName) &&
|
|
1760
|
+
current.childNodes.length === 0 &&
|
|
1761
|
+
dom.check.isExcludeFormat(current))
|
|
1762
|
+
) {
|
|
1528
1763
|
removeTags.push(current);
|
|
1529
1764
|
return false;
|
|
1530
1765
|
}
|
|
@@ -1542,7 +1777,9 @@ class HTML {
|
|
|
1542
1777
|
!dom.check.isTableElements(current) &&
|
|
1543
1778
|
!dom.check.isListCell(current) &&
|
|
1544
1779
|
!dom.check.isAnchor(current) &&
|
|
1545
|
-
(this.#$.format.isLine(current) ||
|
|
1780
|
+
(this.#$.format.isLine(current) ||
|
|
1781
|
+
this.#$.format.isBlock(current) ||
|
|
1782
|
+
this.#$.format.isTextStyleNode(current)) &&
|
|
1546
1783
|
current.childNodes.length === 0 &&
|
|
1547
1784
|
nrtag
|
|
1548
1785
|
) {
|
|
@@ -1551,7 +1788,11 @@ class HTML {
|
|
|
1551
1788
|
}
|
|
1552
1789
|
|
|
1553
1790
|
// wrong list
|
|
1554
|
-
if (
|
|
1791
|
+
if (
|
|
1792
|
+
dom.check.isList(current.parentNode) &&
|
|
1793
|
+
!dom.check.isList(current) &&
|
|
1794
|
+
!dom.check.isListCell(current)
|
|
1795
|
+
) {
|
|
1555
1796
|
wrongList.push(current);
|
|
1556
1797
|
return false;
|
|
1557
1798
|
}
|
|
@@ -1585,7 +1826,9 @@ class HTML {
|
|
|
1585
1826
|
current.parentNode !== documentFragment &&
|
|
1586
1827
|
nrtag &&
|
|
1587
1828
|
((dom.check.isListCell(current) && !dom.check.isList(current.parentNode)) ||
|
|
1588
|
-
((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))));
|
|
1589
1832
|
|
|
1590
1833
|
return result;
|
|
1591
1834
|
},
|
|
@@ -1709,7 +1952,13 @@ class HTML {
|
|
|
1709
1952
|
|
|
1710
1953
|
if (n.nodeType === 8) {
|
|
1711
1954
|
value += '<!-- ' + n.textContent + ' -->';
|
|
1712
|
-
} 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
|
+
) {
|
|
1713
1962
|
f ||= dom.utils.createElement(this.#options.get('defaultLine'));
|
|
1714
1963
|
if (this.#$.format.isTextStyleNode(n)) {
|
|
1715
1964
|
/** @type {HTMLElement} */
|
|
@@ -1774,7 +2023,12 @@ class HTML {
|
|
|
1774
2023
|
|
|
1775
2024
|
for (let i = 0, len = domTree.length, t; i < len; i++) {
|
|
1776
2025
|
t = domTree[i];
|
|
1777
|
-
if (
|
|
2026
|
+
if (
|
|
2027
|
+
t.nodeType === 1 &&
|
|
2028
|
+
!this.#$.format.isTextStyleNode(t) &&
|
|
2029
|
+
!dom.check.isBreak(t) &&
|
|
2030
|
+
!this.#disallowedTagNameRegExp.test(t.nodeName)
|
|
2031
|
+
) {
|
|
1778
2032
|
requireFormat = true;
|
|
1779
2033
|
break;
|
|
1780
2034
|
}
|
|
@@ -1798,7 +2052,12 @@ class HTML {
|
|
|
1798
2052
|
const face = (m.match(_RE_FACE_ATTR) || [])[1];
|
|
1799
2053
|
const color = (m.match(_RE_COLOR_ATTR) || [])[1];
|
|
1800
2054
|
if (size || face || color) {
|
|
1801
|
-
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
|
+
'"';
|
|
1802
2061
|
}
|
|
1803
2062
|
}
|
|
1804
2063
|
|
|
@@ -1831,7 +2090,10 @@ class HTML {
|
|
|
1831
2090
|
case 'fontSize':
|
|
1832
2091
|
if (!this.#$.plugins.fontSize) continue;
|
|
1833
2092
|
if (!this.#fontSizeUnitRegExp.test(r[0])) {
|
|
1834
|
-
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
|
+
);
|
|
1835
2097
|
}
|
|
1836
2098
|
break;
|
|
1837
2099
|
case 'color':
|
|
@@ -1966,12 +2228,12 @@ class HTML {
|
|
|
1966
2228
|
v.push(sv[0]);
|
|
1967
2229
|
}
|
|
1968
2230
|
} else if (!v || !_RE_STYLE_EQ.test(v.toString())) {
|
|
1969
|
-
if (this.#
|
|
2231
|
+
if (this.#cleanStyleTagKeyRegExp.test(tagName)) {
|
|
1970
2232
|
v = this.#cleanStyle(m, v, tagName);
|
|
1971
2233
|
} else if (this.#$.format.isLine(tagName)) {
|
|
1972
|
-
v = this.#cleanStyle(m, v, 'line');
|
|
1973
|
-
} else if (this.#
|
|
1974
|
-
v = this.#cleanStyle(m, v,
|
|
2234
|
+
v = this.#cleanStyle(m, v, '@line');
|
|
2235
|
+
} else if (this.#textStyleTags.includes(tagName)) {
|
|
2236
|
+
v = this.#cleanStyle(m, v, '@text');
|
|
1975
2237
|
}
|
|
1976
2238
|
}
|
|
1977
2239
|
|
|
@@ -2011,10 +2273,16 @@ class HTML {
|
|
|
2011
2273
|
styleToTag.italic = { regex: /font-style\s*:\s*italic/i, tag: convertTextTags.italic };
|
|
2012
2274
|
break;
|
|
2013
2275
|
case 'underline':
|
|
2014
|
-
styleToTag.underline = {
|
|
2276
|
+
styleToTag.underline = {
|
|
2277
|
+
regex: /text-decoration\s*:\s*underline/i,
|
|
2278
|
+
tag: convertTextTags.underline,
|
|
2279
|
+
};
|
|
2015
2280
|
break;
|
|
2016
2281
|
case 'strike':
|
|
2017
|
-
styleToTag.strike = {
|
|
2282
|
+
styleToTag.strike = {
|
|
2283
|
+
regex: /text-decoration\s*:\s*line-through/i,
|
|
2284
|
+
tag: convertTextTags.strike,
|
|
2285
|
+
};
|
|
2018
2286
|
break;
|
|
2019
2287
|
}
|
|
2020
2288
|
});
|
|
@@ -2092,6 +2360,8 @@ const _RE_LEADING_SPACE = /^\s/;
|
|
|
2092
2360
|
|
|
2093
2361
|
// #cleanStyle
|
|
2094
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]+$/;
|
|
2095
2365
|
const _RE_SIZE_ATTR = /\ssize="([^"]+)"/i;
|
|
2096
2366
|
const _RE_FACE_ATTR = /\sface="([^"]+)"/i;
|
|
2097
2367
|
const _RE_COLOR_ATTR = /\scolor="([^"]+)"/i;
|