suneditor 3.0.0-beta.3 → 3.0.0-beta.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/CONTRIBUTING.md +8 -8
  2. package/README.md +44 -49
  3. package/dist/suneditor.min.css +1 -1
  4. package/dist/suneditor.min.js +1 -1
  5. package/package.json +95 -53
  6. package/src/assets/design/color.css +2 -2
  7. package/src/assets/design/size.css +2 -0
  8. package/src/assets/icons/defaultIcons.js +16 -1
  9. package/src/assets/suneditor-contents.css +9 -8
  10. package/src/assets/suneditor.css +29 -26
  11. package/src/core/{section → base}/actives.js +20 -12
  12. package/src/core/base/history.js +4 -4
  13. package/src/core/class/char.js +10 -10
  14. package/src/core/class/component.js +146 -57
  15. package/src/core/class/format.js +94 -2458
  16. package/src/core/class/html.js +187 -129
  17. package/src/core/class/inline.js +1853 -0
  18. package/src/core/class/listFormat.js +582 -0
  19. package/src/core/class/menu.js +14 -3
  20. package/src/core/class/nodeTransform.js +9 -14
  21. package/src/core/class/offset.js +162 -197
  22. package/src/core/class/selection.js +137 -34
  23. package/src/core/class/toolbar.js +73 -52
  24. package/src/core/class/ui.js +11 -11
  25. package/src/core/class/viewer.js +56 -55
  26. package/src/core/config/context.js +122 -0
  27. package/src/core/config/frameContext.js +204 -0
  28. package/src/core/config/options.js +639 -0
  29. package/src/core/editor.js +181 -108
  30. package/src/core/event/actions/index.js +229 -0
  31. package/src/core/event/effects/common.registry.js +60 -0
  32. package/src/core/event/effects/keydown.registry.js +551 -0
  33. package/src/core/event/effects/ruleHelpers.js +145 -0
  34. package/src/core/{base → event}/eventManager.js +119 -201
  35. package/src/core/event/executor.js +21 -0
  36. package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +4 -4
  37. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +2 -2
  38. package/src/core/event/handlers/handler_ww_input.js +77 -0
  39. package/src/core/event/handlers/handler_ww_key.js +228 -0
  40. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.js +3 -3
  41. package/src/core/event/ports.js +211 -0
  42. package/src/core/event/reducers/keydown.reducer.js +89 -0
  43. package/src/core/event/rules/keydown.rule.arrow.js +54 -0
  44. package/src/core/event/rules/keydown.rule.backspace.js +202 -0
  45. package/src/core/event/rules/keydown.rule.delete.js +126 -0
  46. package/src/core/event/rules/keydown.rule.enter.js +144 -0
  47. package/src/core/event/rules/keydown.rule.tab.js +29 -0
  48. package/src/core/section/constructor.js +79 -388
  49. package/src/core/section/documentType.js +47 -26
  50. package/src/core/util/instanceCheck.js +59 -0
  51. package/src/editorInjector/_classes.js +4 -0
  52. package/src/editorInjector/_core.js +17 -7
  53. package/src/editorInjector/index.js +10 -2
  54. package/src/events.js +6 -0
  55. package/src/helper/clipboard.js +24 -10
  56. package/src/helper/converter.js +17 -12
  57. package/src/helper/dom/domCheck.js +22 -3
  58. package/src/helper/dom/domQuery.js +91 -45
  59. package/src/helper/dom/domUtils.js +93 -19
  60. package/src/helper/dom/index.js +4 -0
  61. package/src/helper/env.js +11 -7
  62. package/src/helper/keyCodeMap.js +4 -3
  63. package/src/langs/ckb.js +1 -1
  64. package/src/langs/cs.js +1 -1
  65. package/src/langs/da.js +1 -1
  66. package/src/langs/de.js +1 -1
  67. package/src/langs/en.js +1 -1
  68. package/src/langs/es.js +1 -1
  69. package/src/langs/fa.js +1 -1
  70. package/src/langs/fr.js +1 -1
  71. package/src/langs/he.js +1 -1
  72. package/src/langs/hu.js +1 -1
  73. package/src/langs/it.js +1 -1
  74. package/src/langs/ja.js +1 -1
  75. package/src/langs/km.js +1 -1
  76. package/src/langs/ko.js +1 -1
  77. package/src/langs/lv.js +1 -1
  78. package/src/langs/nl.js +1 -1
  79. package/src/langs/pl.js +1 -1
  80. package/src/langs/pt_br.js +10 -10
  81. package/src/langs/ro.js +1 -1
  82. package/src/langs/ru.js +1 -1
  83. package/src/langs/se.js +1 -1
  84. package/src/langs/tr.js +1 -1
  85. package/src/langs/uk.js +1 -1
  86. package/src/langs/ur.js +1 -1
  87. package/src/langs/zh_cn.js +1 -1
  88. package/src/modules/ApiManager.js +25 -18
  89. package/src/modules/Browser.js +52 -61
  90. package/src/modules/ColorPicker.js +37 -38
  91. package/src/modules/Controller.js +85 -79
  92. package/src/modules/Figure.js +275 -187
  93. package/src/modules/FileManager.js +86 -92
  94. package/src/modules/HueSlider.js +67 -35
  95. package/src/modules/Modal.js +84 -77
  96. package/src/modules/ModalAnchorEditor.js +62 -79
  97. package/src/modules/SelectMenu.js +89 -86
  98. package/src/plugins/browser/audioGallery.js +9 -5
  99. package/src/plugins/browser/fileBrowser.js +10 -6
  100. package/src/plugins/browser/fileGallery.js +9 -5
  101. package/src/plugins/browser/imageGallery.js +9 -5
  102. package/src/plugins/browser/videoGallery.js +11 -6
  103. package/src/plugins/command/blockquote.js +1 -0
  104. package/src/plugins/command/exportPDF.js +11 -8
  105. package/src/plugins/command/fileUpload.js +41 -29
  106. package/src/plugins/command/list_bulleted.js +2 -1
  107. package/src/plugins/command/list_numbered.js +2 -1
  108. package/src/plugins/dropdown/align.js +8 -2
  109. package/src/plugins/dropdown/backgroundColor.js +19 -11
  110. package/src/plugins/dropdown/font.js +15 -9
  111. package/src/plugins/dropdown/fontColor.js +19 -11
  112. package/src/plugins/dropdown/formatBlock.js +7 -2
  113. package/src/plugins/dropdown/hr.js +7 -3
  114. package/src/plugins/dropdown/layout.js +6 -2
  115. package/src/plugins/dropdown/lineHeight.js +8 -3
  116. package/src/plugins/dropdown/list.js +2 -1
  117. package/src/plugins/dropdown/paragraphStyle.js +15 -11
  118. package/src/plugins/dropdown/{table.js → table/index.js} +514 -362
  119. package/src/plugins/dropdown/template.js +6 -2
  120. package/src/plugins/dropdown/textStyle.js +7 -3
  121. package/src/plugins/field/mention.js +33 -27
  122. package/src/plugins/input/fontSize.js +44 -37
  123. package/src/plugins/input/pageNavigator.js +3 -2
  124. package/src/plugins/modal/audio.js +90 -85
  125. package/src/plugins/modal/drawing.js +58 -66
  126. package/src/plugins/modal/embed.js +193 -180
  127. package/src/plugins/modal/image.js +441 -439
  128. package/src/plugins/modal/link.js +31 -8
  129. package/src/plugins/modal/math.js +23 -22
  130. package/src/plugins/modal/video.js +233 -230
  131. package/src/plugins/popup/anchor.js +24 -18
  132. package/src/suneditor.js +69 -24
  133. package/src/typedef.js +42 -19
  134. package/types/assets/icons/defaultIcons.d.ts +8 -0
  135. package/types/core/class/char.d.ts +1 -1
  136. package/types/core/class/component.d.ts +29 -7
  137. package/types/core/class/format.d.ts +4 -354
  138. package/types/core/class/html.d.ts +13 -4
  139. package/types/core/class/inline.d.ts +263 -0
  140. package/types/core/class/listFormat.d.ts +135 -0
  141. package/types/core/class/menu.d.ts +10 -2
  142. package/types/core/class/offset.d.ts +24 -26
  143. package/types/core/class/selection.d.ts +2 -0
  144. package/types/core/class/toolbar.d.ts +24 -11
  145. package/types/core/class/ui.d.ts +1 -1
  146. package/types/core/class/viewer.d.ts +1 -1
  147. package/types/core/config/context.d.ts +157 -0
  148. package/types/core/config/frameContext.d.ts +367 -0
  149. package/types/core/config/options.d.ts +1119 -0
  150. package/types/core/editor.d.ts +101 -66
  151. package/types/core/event/actions/index.d.ts +47 -0
  152. package/types/core/event/effects/common.registry.d.ts +50 -0
  153. package/types/core/event/effects/keydown.registry.d.ts +73 -0
  154. package/types/core/event/effects/ruleHelpers.d.ts +31 -0
  155. package/types/core/{base → event}/eventManager.d.ts +15 -46
  156. package/types/core/event/executor.d.ts +6 -0
  157. package/types/core/event/handlers/handler_ww_input.d.ts +41 -0
  158. package/types/core/{base/eventHandlers/handler_ww_key_input.d.ts → event/handlers/handler_ww_key.d.ts} +4 -6
  159. package/types/core/event/ports.d.ts +255 -0
  160. package/types/core/event/reducers/keydown.reducer.d.ts +75 -0
  161. package/types/core/event/rules/keydown.rule.arrow.d.ts +8 -0
  162. package/types/core/event/rules/keydown.rule.backspace.d.ts +9 -0
  163. package/types/core/event/rules/keydown.rule.delete.d.ts +9 -0
  164. package/types/core/event/rules/keydown.rule.enter.d.ts +9 -0
  165. package/types/core/event/rules/keydown.rule.tab.d.ts +9 -0
  166. package/types/core/section/constructor.d.ts +101 -631
  167. package/types/core/section/documentType.d.ts +14 -4
  168. package/types/core/util/instanceCheck.d.ts +50 -0
  169. package/types/editorInjector/_classes.d.ts +4 -0
  170. package/types/editorInjector/_core.d.ts +17 -7
  171. package/types/editorInjector/index.d.ts +10 -2
  172. package/types/events.d.ts +1 -0
  173. package/types/helper/clipboard.d.ts +2 -2
  174. package/types/helper/converter.d.ts +6 -9
  175. package/types/helper/dom/domCheck.d.ts +7 -0
  176. package/types/helper/dom/domQuery.d.ts +19 -8
  177. package/types/helper/dom/domUtils.d.ts +24 -2
  178. package/types/helper/dom/index.d.ts +86 -1
  179. package/types/helper/env.d.ts +6 -1
  180. package/types/helper/index.d.ts +7 -1
  181. package/types/helper/keyCodeMap.d.ts +3 -3
  182. package/types/index.d.ts +23 -117
  183. package/types/langs/index.d.ts +2 -2
  184. package/types/modules/ApiManager.d.ts +1 -8
  185. package/types/modules/Browser.d.ts +4 -62
  186. package/types/modules/ColorPicker.d.ts +4 -21
  187. package/types/modules/Controller.d.ts +8 -64
  188. package/types/modules/Figure.d.ts +54 -50
  189. package/types/modules/FileManager.d.ts +1 -13
  190. package/types/modules/HueSlider.d.ts +13 -3
  191. package/types/modules/Modal.d.ts +0 -43
  192. package/types/modules/ModalAnchorEditor.d.ts +0 -73
  193. package/types/modules/SelectMenu.d.ts +0 -85
  194. package/types/modules/index.d.ts +3 -3
  195. package/types/plugins/browser/audioGallery.d.ts +29 -18
  196. package/types/plugins/browser/fileBrowser.d.ts +38 -27
  197. package/types/plugins/browser/fileGallery.d.ts +29 -18
  198. package/types/plugins/browser/imageGallery.d.ts +24 -16
  199. package/types/plugins/browser/videoGallery.d.ts +29 -18
  200. package/types/plugins/command/blockquote.d.ts +1 -0
  201. package/types/plugins/command/exportPDF.d.ts +18 -18
  202. package/types/plugins/command/fileUpload.d.ts +65 -45
  203. package/types/plugins/command/list_bulleted.d.ts +1 -0
  204. package/types/plugins/command/list_numbered.d.ts +1 -0
  205. package/types/plugins/dropdown/align.d.ts +13 -8
  206. package/types/plugins/dropdown/backgroundColor.d.ts +30 -19
  207. package/types/plugins/dropdown/font.d.ts +13 -12
  208. package/types/plugins/dropdown/fontColor.d.ts +30 -19
  209. package/types/plugins/dropdown/formatBlock.d.ts +13 -8
  210. package/types/plugins/dropdown/hr.d.ts +15 -11
  211. package/types/plugins/dropdown/layout.d.ts +15 -11
  212. package/types/plugins/dropdown/lineHeight.d.ts +16 -11
  213. package/types/plugins/dropdown/list.d.ts +1 -0
  214. package/types/plugins/dropdown/paragraphStyle.d.ts +31 -27
  215. package/types/plugins/dropdown/table/index.d.ts +582 -0
  216. package/types/plugins/dropdown/table.d.ts +41 -86
  217. package/types/plugins/dropdown/template.d.ts +15 -11
  218. package/types/plugins/dropdown/textStyle.d.ts +19 -11
  219. package/types/plugins/field/mention.d.ts +58 -56
  220. package/types/plugins/index.d.ts +38 -38
  221. package/types/plugins/input/fontSize.d.ts +46 -50
  222. package/types/plugins/modal/audio.d.ts +26 -56
  223. package/types/plugins/modal/drawing.d.ts +0 -85
  224. package/types/plugins/modal/embed.d.ts +15 -79
  225. package/types/plugins/modal/image.d.ts +24 -136
  226. package/types/plugins/modal/link.d.ts +34 -15
  227. package/types/plugins/modal/math.d.ts +0 -16
  228. package/types/plugins/modal/video.d.ts +17 -86
  229. package/types/plugins/popup/anchor.d.ts +1 -8
  230. package/types/suneditor.d.ts +70 -19
  231. package/types/typedef.d.ts +60 -46
  232. package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
  233. package/src/core/section/context.js +0 -102
  234. package/types/core/section/context.d.ts +0 -45
  235. package/types/langs/_Lang.d.ts +0 -194
  236. /package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +0 -0
  237. /package/types/core/{section → base}/actives.d.ts +0 -0
  238. /package/types/core/{base/eventHandlers → event/handlers}/handler_toolbar.d.ts +0 -0
  239. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.d.ts +0 -0
  240. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.d.ts +0 -0
  241. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.d.ts +0 -0
@@ -126,7 +126,7 @@ function HTML(editor) {
126
126
  if (k === '*') {
127
127
  allAttr = GetRegList(_wAttr[k], defaultAttr);
128
128
  } else {
129
- tagsAttr[k] = new RegExp('\\s(?:' + GetRegList(_wAttr[k], '') + ')' + regEndStr, 'ig');
129
+ tagsAttr[k] = new RegExp('\\s(?:' + GetRegList(_wAttr[k], defaultAttr) + ')' + regEndStr, 'ig');
130
130
  }
131
131
  }
132
132
  }
@@ -186,7 +186,7 @@ HTML.prototype = {
186
186
  const result = validate(node);
187
187
  if (result === null) {
188
188
  node.remove();
189
- } else if (result instanceof Node) {
189
+ } else if (this.instanceCheck.isNode(result)) {
190
190
  node.replaceWith(result);
191
191
  } else if (typeof result === 'string') {
192
192
  node.outerHTML = result;
@@ -203,7 +203,7 @@ HTML.prototype = {
203
203
  const result = validate(node);
204
204
  if (result === null) {
205
205
  node.remove();
206
- } else if (result instanceof Node) {
206
+ } else if (this.instanceCheck.isNode(result)) {
207
207
  node.replaceWith(result);
208
208
  } else if (typeof result === 'string') {
209
209
  node.outerHTML = result;
@@ -230,7 +230,7 @@ HTML.prototype = {
230
230
  * @returns {string} Cleaned and compressed HTML string
231
231
  */
232
232
  clean(html, { forceFormat, whitelist, blacklist, _freeCodeViewMode } = {}) {
233
- const { tagFilter, formatFilter, classFilter, styleNodeFilter, attrFilter, styleFilter } = this.options.get('strictMode');
233
+ const { tagFilter, formatFilter, classFilter, textStyleTagFilter, attrFilter, styleFilter } = this.options.get('strictMode');
234
234
  let cleanData = '';
235
235
 
236
236
  html = this.compress(html);
@@ -242,7 +242,7 @@ HTML.prototype = {
242
242
 
243
243
  if (this._autoStyleify) {
244
244
  const domParser = new DOMParser().parseFromString(html, 'text/html');
245
- dom.query.getListChildNodes(domParser.body, converter.spanToStyleNode.bind(null, this._autoStyleify));
245
+ dom.query.getListChildNodes(domParser.body, converter.spanToStyleNode.bind(null, this._autoStyleify), null);
246
246
  html = domParser.body.innerHTML;
247
247
  }
248
248
 
@@ -275,18 +275,19 @@ HTML.prototype = {
275
275
  iframePlaceholders[i].replaceWith(iframe);
276
276
  }
277
277
 
278
- if (this.options.get('__pluginRetainFilter')) {
279
- this.editor._MELInfo.forEach((method, query) => {
278
+ let retainFilter;
279
+ if ((retainFilter = this.options.get('__pluginRetainFilter'))) {
280
+ this.editor._MELInfo.forEach((plugin, query) => {
280
281
  const infoLst = domParser.querySelectorAll(query);
281
282
  for (let i = 0, len = infoLst.length; i < len; i++) {
282
- method(infoLst[i]);
283
+ if (retainFilter === true || retainFilter[plugin.key] !== false) plugin.method(infoLst[i]);
283
284
  }
284
285
  });
285
286
  }
286
287
 
287
288
  if (formatFilter) {
288
289
  let domTree = domParser.childNodes;
289
- if (!forceFormat) forceFormat = this._isFormatData(domTree);
290
+ forceFormat ||= this._isFormatData(domTree);
290
291
  if (forceFormat) domTree = this._editFormat(domParser).childNodes;
291
292
 
292
293
  for (let i = 0, len = domTree.length, t; i < len; i++) {
@@ -300,7 +301,7 @@ HTML.prototype = {
300
301
  }
301
302
 
302
303
  // set clean data
303
- if (!cleanData) cleanData = html;
304
+ cleanData ||= html;
304
305
 
305
306
  // whitelist, blacklist
306
307
  if (tagFilter) {
@@ -308,7 +309,7 @@ HTML.prototype = {
308
309
  if (blacklist) cleanData = cleanData.replace(typeof blacklist === 'string' ? converter.createElementBlacklist(blacklist) : blacklist, '');
309
310
  }
310
311
 
311
- if (styleNodeFilter) {
312
+ if (textStyleTagFilter) {
312
313
  cleanData = this._styleNodeConvertor(cleanData);
313
314
  }
314
315
 
@@ -327,8 +328,12 @@ HTML.prototype = {
327
328
  * @returns {HTMLElement|null} The inserted element or null if insertion failed
328
329
  */
329
330
  insert(html, { selectInserted, skipCharCount, skipCleaning } = {}) {
330
- if (!this.editor.frameContext.get('wysiwyg').contains(this.selection.get().focusNode)) this.editor.focus();
331
+ if (!this.frameContext.get('wysiwyg').contains(this.selection.get().focusNode)) this.editor.focus();
331
332
 
333
+ this.remove();
334
+ this.editor.focus();
335
+
336
+ let focusNode = null;
332
337
  if (typeof html === 'string') {
333
338
  if (!skipCleaning) html = this.clean(html, { forceFormat: false, whitelist: null, blacklist: null });
334
339
  try {
@@ -342,7 +347,7 @@ HTML.prototype = {
342
347
  const domTree = domParser.childNodes;
343
348
 
344
349
  if (!skipCharCount) {
345
- const type = this.editor.frameOptions.get('charCounter_type') === 'byte-html' ? 'outerHTML' : 'textContent';
350
+ const type = this.frameOptions.get('charCounter_type') === 'byte-html' ? 'outerHTML' : 'textContent';
346
351
  let checkHTML = '';
347
352
  for (let i = 0, len = domTree.length; i < len; i++) {
348
353
  checkHTML += domTree[i][type];
@@ -359,12 +364,13 @@ HTML.prototype = {
359
364
  }
360
365
  t = this.insertNode(c, { afterNode: a, skipCharCount: true });
361
366
  a = t.container || t;
362
- if (!firstCon) firstCon = t;
367
+ firstCon ||= t;
363
368
  prev = c;
364
369
  }
365
370
 
366
371
  if (prev?.nodeType === 3 && a?.nodeType === 1) a = prev;
367
372
  const offset = a.nodeType === 3 ? t.endOffset || a.textContent.length : a.childNodes.length;
373
+ focusNode = a;
368
374
 
369
375
  if (selectInserted) {
370
376
  this.selection.setRange(firstCon.container || firstCon, firstCon.startOffset || 0, a, offset);
@@ -372,12 +378,12 @@ HTML.prototype = {
372
378
  this.selection.setRange(a, offset, a, offset);
373
379
  }
374
380
  } catch (error) {
375
- if (this.editor.frameContext.get('isReadOnly') || this.editor.frameContext.get('isDisabled')) return;
381
+ if (this.frameContext.get('isReadOnly') || this.frameContext.get('isDisabled')) return;
376
382
  throw Error(`[SUNEDITOR.html.insert.error] ${error.message}`);
377
383
  }
378
384
  } else {
379
385
  if (this.component.is(html)) {
380
- this.component.insert(html, { skipCharCount, skipSelection: false, skipHistory: false });
386
+ this.component.insert(html, { skipCharCount, insertBehavior: 'none' });
381
387
  } else {
382
388
  let afterNode = null;
383
389
  if (this.format.isLine(html) || dom.check.isMedia(html)) {
@@ -387,8 +393,22 @@ HTML.prototype = {
387
393
  }
388
394
  }
389
395
 
396
+ // focus
390
397
  this.editor.effectNode = null;
391
- this.editor.focus();
398
+
399
+ if (focusNode) {
400
+ const children = dom.query.getListChildNodes(focusNode, null, null);
401
+ if (children.length > 0) {
402
+ focusNode = children.at(-1);
403
+ const offset = focusNode?.nodeType === 3 ? focusNode.textContent.length : 1;
404
+ this.selection.setRange(focusNode, offset, focusNode, offset);
405
+ } else {
406
+ this.editor.focus();
407
+ }
408
+ } else {
409
+ this.editor.focus();
410
+ }
411
+
392
412
  this.history.push(false);
393
413
  },
394
414
 
@@ -405,12 +425,20 @@ HTML.prototype = {
405
425
  */
406
426
  insertNode(oNode, { afterNode, skipCharCount } = {}) {
407
427
  let result = null;
408
- if (this.editor.frameContext.get('isReadOnly') || (!skipCharCount && !this.char.check(oNode))) {
428
+ if (this.frameContext.get('isReadOnly') || (!skipCharCount && !this.char.check(oNode))) {
409
429
  return result;
410
430
  }
411
431
 
412
432
  let fNode = null;
413
- let range = this.selection.getRange();
433
+ let range = null;
434
+
435
+ if (afterNode) {
436
+ const afterNewLine = this.format.isLine(afterNode) || this.format.isBlock(afterNode) || this.component.is(afterNode) ? this.format.addLine(afterNode, null) : afterNode;
437
+ range = this.selection.setRange(afterNewLine, 1, afterNewLine, 1);
438
+ } else {
439
+ range = this.selection.getRange();
440
+ }
441
+
414
442
  let line = dom.check.isListCell(range.commonAncestorContainer) ? range.commonAncestorContainer : this.format.getLine(this.selection.getNode(), null);
415
443
  let insertListCell = dom.check.isListCell(line) && (dom.check.isListCell(oNode) || dom.check.isList(oNode));
416
444
 
@@ -419,7 +447,7 @@ HTML.prototype = {
419
447
  tempAfterNode,
420
448
  tempParentNode = null;
421
449
  const freeFormat = this.format.isBrLine(line);
422
- const isFormats = (!freeFormat && (this.format.isLine(oNode) || this.format.isBlock(oNode))) || this.component.isBasic(oNode);
450
+ const isFormats = this.format.isLine(oNode) || this.format.isBlock(oNode) || this.component.isBasic(oNode);
423
451
 
424
452
  if (insertListCell) {
425
453
  tempAfterNode = afterNode || dom.check.isList(oNode) ? line.lastChild : line.nextElementSibling;
@@ -456,7 +484,9 @@ HTML.prototype = {
456
484
  });
457
485
  afterNode = this.nodeTransform.split(container, r.offset, !depthFormat ? 0 : dom.query.getNodeDepth(depthFormat) + 1);
458
486
  if (!afterNode) {
459
- tempAfterNode = afterNode = line;
487
+ if (!dom.check.isListCell(line)) {
488
+ tempAfterNode = afterNode = line;
489
+ }
460
490
  } else if (insertListCell) {
461
491
  if (line.contains(container)) {
462
492
  const subList = dom.check.isList(line.lastElementChild);
@@ -589,7 +619,7 @@ HTML.prototype = {
589
619
 
590
620
  try {
591
621
  // set node
592
- const wysiwyg = this.editor.frameContext.get('wysiwyg');
622
+ const wysiwyg = this.frameContext.get('wysiwyg');
593
623
  if (!insertListCell) {
594
624
  if (dom.check.isWysiwygFrame(afterNode) || parentNode === wysiwyg.parentNode) {
595
625
  parentNode = wysiwyg;
@@ -598,10 +628,7 @@ HTML.prototype = {
598
628
 
599
629
  if (this.format.isLine(oNode) || this.format.isBlock(oNode) || (!dom.check.isListCell(parentNode) && this.component.isBasic(oNode))) {
600
630
  const oldParent = parentNode;
601
- if (dom.check.isList(afterNode)) {
602
- parentNode = afterNode;
603
- afterNode = null;
604
- } else if (dom.check.isListCell(afterNode)) {
631
+ if (dom.check.isListCell(afterNode)) {
605
632
  parentNode = afterNode.previousElementSibling || afterNode;
606
633
  } else if (!originAfter && !afterNode) {
607
634
  const r = this.remove();
@@ -706,7 +733,7 @@ HTML.prototype = {
706
733
  }
707
734
  }
708
735
 
709
- if (freeFormat && (this.format.isLine(oNode) || this.format.isBlock(oNode))) {
736
+ if (freeFormat && !dom.check.isList(oNode) && (this.format.isLine(oNode) || this.format.isBlock(oNode))) {
710
737
  oNode = this._setIntoFreeFormat(oNode);
711
738
  }
712
739
 
@@ -727,7 +754,7 @@ HTML.prototype = {
727
754
  oNode.parentNode.insertBefore(zeroWidth, oNode.nextSibling);
728
755
  }
729
756
 
730
- if (this.format._isIgnoreNodeChange(oNode)) {
757
+ if (this.inline._isIgnoreNodeChange(oNode)) {
731
758
  oNode = oNode.nextSibling;
732
759
  offset = 0;
733
760
  }
@@ -814,8 +841,8 @@ HTML.prototype = {
814
841
  }
815
842
  } else {
816
843
  if ((commonCon.nodeType === 1 && startOff === 0 && endOff === 1) || (commonCon.nodeType === 3 && startOff === 0 && endOff === commonCon.textContent.length)) {
817
- const nextEl = dom.query.getNextDeepestNode(commonCon, this.editor.frameContext.get('wysiwyg'));
818
- const prevEl = dom.query.getPreviousDeepestNode(commonCon, this.editor.frameContext.get('wysiwyg'));
844
+ const nextEl = dom.query.getNextDeepestNode(commonCon, this.frameContext.get('wysiwyg'));
845
+ const prevEl = dom.query.getPreviousDeepestNode(commonCon, this.frameContext.get('wysiwyg'));
819
846
  const line = this.format.getLine(commonCon);
820
847
  dom.utils.removeItem(commonCon);
821
848
 
@@ -866,7 +893,7 @@ HTML.prototype = {
866
893
  let beforeNode = null;
867
894
  let afterNode = null;
868
895
 
869
- const childNodes = dom.query.getListChildNodes(commonCon, null);
896
+ const childNodes = dom.query.getListChildNodes(commonCon, null, null);
870
897
  let startIndex = dom.utils.getArrayIndex(childNodes, startCon);
871
898
  let endIndex = dom.utils.getArrayIndex(childNodes, endCon);
872
899
 
@@ -918,11 +945,13 @@ HTML.prototype = {
918
945
 
919
946
  const _isText = dom.check.isText;
920
947
  const _isElement = dom.check.isElement;
948
+ const _isSingleItem = startIndex === endIndex;
949
+ let nextFocusNodes = null;
921
950
  for (let i = startIndex; i <= endIndex; i++) {
922
951
  const item = /** @type {Text} */ (childNodes[i]);
923
952
 
924
953
  if (_isText(item) && (item.data === undefined || item.length === 0)) {
925
- this._nodeRemoveListItem(item);
954
+ nextFocusNodes = this._nodeRemoveListItem(item, _isSingleItem);
926
955
  continue;
927
956
  }
928
957
 
@@ -944,7 +973,7 @@ HTML.prototype = {
944
973
  if (beforeNode.length > 0) {
945
974
  /** @type {Text} */ (startCon).data = beforeNode.data;
946
975
  } else {
947
- this._nodeRemoveListItem(startCon);
976
+ nextFocusNodes = this._nodeRemoveListItem(startCon, _isSingleItem);
948
977
  }
949
978
 
950
979
  if (item === endCon) break;
@@ -962,13 +991,13 @@ HTML.prototype = {
962
991
  if (afterNode.length > 0) {
963
992
  /** @type {Text} */ (endCon).data = afterNode.data;
964
993
  } else {
965
- this._nodeRemoveListItem(endCon);
994
+ nextFocusNodes = this._nodeRemoveListItem(endCon, _isSingleItem);
966
995
  }
967
996
 
968
997
  continue;
969
998
  }
970
999
 
971
- this._nodeRemoveListItem(item);
1000
+ nextFocusNodes = this._nodeRemoveListItem(item, _isSingleItem);
972
1001
  }
973
1002
 
974
1003
  const endUl = dom.query.getParentElement(endCon, 'ul');
@@ -1004,7 +1033,12 @@ HTML.prototype = {
1004
1033
 
1005
1034
  if (!dom.check.isWysiwygFrame(container) && container.childNodes.length === 0) {
1006
1035
  const rc = this.nodeTransform.removeAllParents(container, null, null);
1007
- if (rc) container = rc.sc || rc.ec || this.editor.frameContext.get('wysiwyg');
1036
+ if (rc) container = rc.sc || rc.ec || this.frameContext.get('wysiwyg');
1037
+ }
1038
+
1039
+ if (!container || (container.nodeType === 1 && !this.format.isLine(container) && !dom.check.isBreak(container))) {
1040
+ container = nextFocusNodes?.sc || nextFocusNodes?.ec;
1041
+ offset = container?.nodeType === 3 ? container.textContent.length : 1;
1008
1042
  }
1009
1043
 
1010
1044
  // set range
@@ -1014,7 +1048,7 @@ HTML.prototype = {
1014
1048
  container,
1015
1049
  offset,
1016
1050
  prevContainer,
1017
- commonCon
1051
+ commonCon: commonCon?.parentElement ? commonCon : null
1018
1052
  };
1019
1053
  },
1020
1054
 
@@ -1037,24 +1071,28 @@ HTML.prototype = {
1037
1071
  for (let i = 0, len = rootKey.length, r; i < len; i++) {
1038
1072
  this.editor.changeFrameContext(rootKey[i]);
1039
1073
 
1040
- const fc = this.editor.frameContext;
1074
+ const fc = this.frameContext;
1041
1075
  const renderHTML = dom.utils.createElement('DIV', null, this._convertToCode(fc.get('wysiwyg'), true));
1042
1076
 
1043
1077
  const isTableCell = dom.check.isTableCell;
1044
1078
  const isEmptyLine = dom.check.isEmptyLine;
1045
1079
  const editableEls = [];
1046
1080
  const emptyCells = [];
1047
- dom.query.getListChildren(renderHTML, (current) => {
1048
- if (current.hasAttribute('contenteditable')) {
1049
- editableEls.push(current);
1050
- }
1081
+ dom.query.getListChildren(
1082
+ renderHTML,
1083
+ (current) => {
1084
+ if (current.hasAttribute('contenteditable')) {
1085
+ editableEls.push(current);
1086
+ }
1051
1087
 
1052
- const parent = current.parentElement;
1053
- if (isTableCell(parent) && parent.children.length <= 1 && isEmptyLine(current)) {
1054
- emptyCells.push(parent);
1055
- }
1056
- return false;
1057
- });
1088
+ const parent = current.parentElement;
1089
+ if (isTableCell(parent) && parent.children.length <= 1 && isEmptyLine(current)) {
1090
+ emptyCells.push(parent);
1091
+ }
1092
+ return false;
1093
+ },
1094
+ null
1095
+ );
1058
1096
 
1059
1097
  for (let j = 0, jlen = editableEls.length; j < jlen; j++) {
1060
1098
  editableEls[j].removeAttribute('contenteditable');
@@ -1064,7 +1102,7 @@ HTML.prototype = {
1064
1102
  }
1065
1103
 
1066
1104
  const content = renderHTML.innerHTML;
1067
- if (this.editor.frameOptions.get('iframe_fullPage')) {
1105
+ if (this.frameOptions.get('iframe_fullPage')) {
1068
1106
  if (includeFullPage) {
1069
1107
  const attrs = dom.utils.getAttributesToString(fc.get('_wd').body, ['contenteditable']);
1070
1108
  r = `<!DOCTYPE html><html>${fc.get('_wd').head.outerHTML}<body ${attrs}>${content}</body></html>`;
@@ -1090,6 +1128,7 @@ HTML.prototype = {
1090
1128
  * @param {number|Array<number>} [options.rootKey=null] Root index
1091
1129
  */
1092
1130
  set(html, { rootKey } = {}) {
1131
+ this.ui._offCurrentController();
1093
1132
  this.selection.removeRange();
1094
1133
  const convertValue = html === null || html === undefined ? '' : this.clean(html, { forceFormat: true, whitelist: null, blacklist: null });
1095
1134
 
@@ -1099,8 +1138,8 @@ HTML.prototype = {
1099
1138
  for (let i = 0; i < rootKey.length; i++) {
1100
1139
  this.editor.changeFrameContext(rootKey[i]);
1101
1140
 
1102
- if (!this.editor.frameContext.get('isCodeView')) {
1103
- this.editor.frameContext.get('wysiwyg').innerHTML = convertValue;
1141
+ if (!this.frameContext.get('isCodeView')) {
1142
+ this.frameContext.get('wysiwyg').innerHTML = convertValue;
1104
1143
  this.editor._resetComponents();
1105
1144
  this.history.push(false, rootKey[i]);
1106
1145
  } else {
@@ -1118,6 +1157,8 @@ HTML.prototype = {
1118
1157
  * @param {number|Array<number>} [options.rootKey=null] Root index
1119
1158
  */
1120
1159
  add(html, { rootKey } = {}) {
1160
+ this.ui._offCurrentController();
1161
+
1121
1162
  if (!rootKey) rootKey = [this.status.rootKey];
1122
1163
  else if (!Array.isArray(rootKey)) rootKey = [rootKey];
1123
1164
 
@@ -1125,13 +1166,13 @@ HTML.prototype = {
1125
1166
  this.editor.changeFrameContext(rootKey[i]);
1126
1167
  const convertValue = this.clean(html, { forceFormat: true, whitelist: null, blacklist: null });
1127
1168
 
1128
- if (!this.editor.frameContext.get('isCodeView')) {
1169
+ if (!this.frameContext.get('isCodeView')) {
1129
1170
  const temp = dom.utils.createElement('DIV', null, convertValue);
1130
1171
  const children = temp.children;
1131
1172
  const len = children.length;
1132
1173
  for (let j = 0; j < len; j++) {
1133
1174
  if (!children[j]) continue;
1134
- this.editor.frameContext.get('wysiwyg').appendChild(children[j]);
1175
+ this.frameContext.get('wysiwyg').appendChild(children[j]);
1135
1176
  }
1136
1177
  this.history.push(false, rootKey[i]);
1137
1178
  this.selection.scrollTo(children[len - 1]);
@@ -1167,12 +1208,17 @@ HTML.prototype = {
1167
1208
  /**
1168
1209
  * @this {HTMLThis}
1169
1210
  * @description Call "clipboard.write" to copy the contents and display a success/failure toast message.
1170
- * @param {Element|Text|string} content Content to be copied to the clipboard
1211
+ * @param {Node|Element|Text|string} content Content to be copied to the clipboard
1171
1212
  * @returns {Promise<boolean>} Success or failure
1172
1213
  */
1173
1214
  async copy(content) {
1174
1215
  try {
1175
- await clipboard.write(content);
1216
+ if (typeof content !== 'string' && !dom.check.isElement(content) && !dom.check.isText(content)) return false;
1217
+
1218
+ if ((await clipboard.write(content)) === false) {
1219
+ this.editor.ui.showToast(this.lang.message_copy_fail, this.options.get('toastMessageTime').copy, 'error');
1220
+ return false;
1221
+ }
1176
1222
  this.editor.ui.showToast(this.lang.message_copy_success, this.options.get('toastMessageTime').copy);
1177
1223
  return true;
1178
1224
  } catch (err) {
@@ -1190,15 +1236,15 @@ HTML.prototype = {
1190
1236
  * @param {number|Array<number>} [options.rootKey=null] Root index
1191
1237
  */
1192
1238
  setFullPage(ctx, { rootKey } = {}) {
1193
- if (!this.editor.frameOptions.get('iframe')) return false;
1239
+ if (!this.frameOptions.get('iframe')) return false;
1194
1240
 
1195
1241
  if (!rootKey) rootKey = [this.status.rootKey];
1196
1242
  else if (!Array.isArray(rootKey)) rootKey = [rootKey];
1197
1243
 
1198
1244
  for (let i = 0; i < rootKey.length; i++) {
1199
1245
  this.editor.changeFrameContext(rootKey[i]);
1200
- if (ctx.head) this.editor.frameContext.get('_wd').head.innerHTML = ctx.head.replace(this.__disallowedTagsRegExp, '');
1201
- if (ctx.body) this.editor.frameContext.get('_wd').body.innerHTML = this.clean(ctx.body, { forceFormat: true, whitelist: null, blacklist: null });
1246
+ if (ctx.head) this.frameContext.get('_wd').head.innerHTML = ctx.head.replace(this.__disallowedTagsRegExp, '');
1247
+ if (ctx.body) this.frameContext.get('_wd').body.innerHTML = this.clean(ctx.body, { forceFormat: true, whitelist: null, blacklist: null });
1202
1248
  this.editor._resetComponents();
1203
1249
  }
1204
1250
  },
@@ -1217,7 +1263,7 @@ HTML.prototype = {
1217
1263
  * @private
1218
1264
  * @this {HTMLThis}
1219
1265
  * @description construct wysiwyg area element to html string
1220
- * @param {Node|string} html WYSIWYG element (this.editor.frameContext.get('wysiwyg')) or HTML string.
1266
+ * @param {Node|string} html WYSIWYG element (this.frameContext.get('wysiwyg')) or HTML string.
1221
1267
  * @param {boolean} comp If true, does not line break and indentation of tags.
1222
1268
  * @returns {string}
1223
1269
  */
@@ -1278,18 +1324,22 @@ HTML.prototype = {
1278
1324
  * @this {HTMLThis}
1279
1325
  * @description Checks whether the given list item node should be removed and handles necessary clean-up.
1280
1326
  * @param {Node} item The list item node to be checked.
1327
+ * @param {boolean} isSingleItem Single item
1328
+ * @returns {{sc:Node, ec:Node}|null} An object containing the start and end containers if any transformations were made, otherwise null.
1281
1329
  */
1282
- _nodeRemoveListItem(item) {
1330
+ _nodeRemoveListItem(item, isSingleItem) {
1283
1331
  const line = this.format.getLine(item, null);
1284
1332
  dom.utils.removeItem(item);
1285
1333
 
1286
- if (!dom.check.isListCell(line)) return;
1334
+ if (!dom.check.isListCell(line) || isSingleItem) return;
1287
1335
 
1288
- this.nodeTransform.removeAllParents(line, null, null);
1336
+ const result = this.nodeTransform.removeAllParents(line, null, null);
1289
1337
 
1290
1338
  if (dom.check.isList(line?.firstChild)) {
1291
1339
  line.insertBefore(dom.utils.createTextNode(unicode.zeroWidthSpace), line.firstChild);
1292
1340
  }
1341
+
1342
+ return result ? { sc: result.sc, ec: result.ec } : null;
1293
1343
  },
1294
1344
 
1295
1345
  /**
@@ -1342,9 +1392,13 @@ HTML.prototype = {
1342
1392
  if (dom.check.isExcludeFormat(node)) return node.outerHTML;
1343
1393
 
1344
1394
  const ch =
1345
- dom.query.getListChildNodes(node, (current) => {
1346
- return dom.check.isSpanWithoutAttr(current) && !dom.query.getParentElement(current, dom.check.isExcludeFormat);
1347
- }) || [];
1395
+ dom.query.getListChildNodes(
1396
+ node,
1397
+ (current) => {
1398
+ return dom.check.isSpanWithoutAttr(current) && !dom.query.getParentElement(current, dom.check.isExcludeFormat);
1399
+ },
1400
+ null
1401
+ ) || [];
1348
1402
  for (let i = ch.length - 1, c; i >= 0; i--) {
1349
1403
  c = /** @type {HTMLElement} */ (ch[i]);
1350
1404
  c.outerHTML = c.innerHTML;
@@ -1404,77 +1458,82 @@ HTML.prototype = {
1404
1458
  withoutFormatCells = [];
1405
1459
 
1406
1460
  // wrong position
1407
- const wrongTags = dom.query.getListChildNodes(documentFragment, (current) => {
1408
- if (formatFilter && current.nodeType !== 1) {
1409
- if (dom.check.isList(current.parentElement)) removeTags.push(current);
1410
- return false;
1411
- }
1412
-
1413
- // tag filter
1414
- if (tagFilter) {
1415
- // white list
1416
- if (htmlCheckBlacklistRegExp.test(current.nodeName) || (!htmlCheckWhitelistRegExp.test(current.nodeName) && current.childNodes.length === 0 && dom.check.isExcludeFormat(current))) {
1417
- removeTags.push(current);
1461
+ const wrongTags = dom.query.getListChildNodes(
1462
+ documentFragment,
1463
+ (current) => {
1464
+ if (current.nodeType !== 1) {
1465
+ if (formatFilter && dom.check.isList(current.parentElement)) removeTags.push(current);
1466
+ if (current.nodeType === 3 && !current.textContent.trim()) removeTags.push(current);
1418
1467
  return false;
1419
1468
  }
1420
- }
1421
1469
 
1422
- const nrtag = !dom.query.getParentElement(current, dom.check.isExcludeFormat);
1423
-
1424
- // formatFilter
1425
- if (formatFilter) {
1426
- // empty tags
1427
- if (
1428
- !dom.check.isTableElements(current) &&
1429
- !dom.check.isListCell(current) &&
1430
- !dom.check.isAnchor(current) &&
1431
- (this.format.isLine(current) || this.format.isBlock(current) || this.format.isTextStyleNode(current)) &&
1432
- current.childNodes.length === 0 &&
1433
- nrtag
1434
- ) {
1435
- emptyTags.push(current);
1436
- return false;
1470
+ // tag filter
1471
+ if (tagFilter) {
1472
+ // white list
1473
+ if (htmlCheckBlacklistRegExp.test(current.nodeName) || (!htmlCheckWhitelistRegExp.test(current.nodeName) && current.childNodes.length === 0 && dom.check.isExcludeFormat(current))) {
1474
+ removeTags.push(current);
1475
+ return false;
1476
+ }
1437
1477
  }
1438
1478
 
1439
- // wrong list
1440
- if (dom.check.isList(current.parentNode) && !dom.check.isList(current) && !dom.check.isListCell(current)) {
1441
- wrongList.push(current);
1442
- return false;
1443
- }
1479
+ const nrtag = !dom.query.getParentElement(current, dom.check.isExcludeFormat);
1480
+
1481
+ // formatFilter
1482
+ if (formatFilter) {
1483
+ // empty tags
1484
+ if (
1485
+ !dom.check.isTableElements(current) &&
1486
+ !dom.check.isListCell(current) &&
1487
+ !dom.check.isAnchor(current) &&
1488
+ (this.format.isLine(current) || this.format.isBlock(current) || this.format.isTextStyleNode(current)) &&
1489
+ current.childNodes.length === 0 &&
1490
+ nrtag
1491
+ ) {
1492
+ emptyTags.push(current);
1493
+ return false;
1494
+ }
1444
1495
 
1445
- // table cells
1446
- if (dom.check.isTableCell(current)) {
1447
- const fel = current.firstElementChild;
1448
- if (!this.format.isLine(fel) && !this.format.isBlock(fel) && !this.component.is(fel)) {
1449
- withoutFormatCells.push(current);
1496
+ // wrong list
1497
+ if (dom.check.isList(current.parentNode) && !dom.check.isList(current) && !dom.check.isListCell(current)) {
1498
+ wrongList.push(current);
1450
1499
  return false;
1451
1500
  }
1501
+
1502
+ // table cells
1503
+ if (dom.check.isTableCell(current)) {
1504
+ const fel = current.firstElementChild;
1505
+ if (!this.format.isLine(fel) && !this.format.isBlock(fel) && !this.component.is(fel)) {
1506
+ withoutFormatCells.push(current);
1507
+ return false;
1508
+ }
1509
+ }
1452
1510
  }
1453
- }
1454
1511
 
1455
- // class filter
1456
- if (classFilter) {
1457
- if (nrtag && current.className) {
1458
- const className = new Array(current.classList).map(this._isAllowedClassName).join(' ').trim();
1459
- if (className) current.className = className;
1460
- else current.removeAttribute('class');
1512
+ // class filter
1513
+ if (classFilter) {
1514
+ if (nrtag && current.className) {
1515
+ const className = new Array(current.classList).map(this._isAllowedClassName).join(' ').trim();
1516
+ if (className) current.className = className;
1517
+ else current.removeAttribute('class');
1518
+ }
1461
1519
  }
1462
- }
1463
1520
 
1464
- // format filter
1465
- if (!formatFilter) {
1466
- return false;
1467
- }
1521
+ // format filter
1522
+ if (!formatFilter) {
1523
+ return false;
1524
+ }
1468
1525
 
1469
- const result =
1470
- !_freeCodeViewMode &&
1471
- current.parentNode !== documentFragment &&
1472
- nrtag &&
1473
- ((dom.check.isListCell(current) && !dom.check.isList(current.parentNode)) ||
1474
- ((this.format.isLine(current) || this.component.is(current)) && !this.format.isBlock(current.parentNode) && !dom.query.getParentElement(current, this.component.is.bind(this.component))));
1526
+ const result =
1527
+ !_freeCodeViewMode &&
1528
+ current.parentNode !== documentFragment &&
1529
+ nrtag &&
1530
+ ((dom.check.isListCell(current) && !dom.check.isList(current.parentNode)) ||
1531
+ ((this.format.isLine(current) || this.component.is(current)) && !this.format.isBlock(current.parentNode) && !dom.query.getParentElement(current, this.component.is.bind(this.component))));
1475
1532
 
1476
- return result;
1477
- });
1533
+ return result;
1534
+ },
1535
+ null
1536
+ );
1478
1537
 
1479
1538
  for (let i = 0, len = removeTags.length; i < len; i++) {
1480
1539
  dom.utils.removeItem(removeTags[i]);
@@ -1576,7 +1635,7 @@ HTML.prototype = {
1576
1635
  if (n.nodeType === 8) {
1577
1636
  value += '<!-- ' + n.textContent + ' -->';
1578
1637
  } else if (!/meta/i.test(n.nodeName) && !this.format.isLine(n) && !this.format.isBlock(n) && !this.component.is(n) && !dom.check.isExcludeFormat(n)) {
1579
- if (!f) f = dom.utils.createElement(this.options.get('defaultLine'));
1638
+ f ||= dom.utils.createElement(this.options.get('defaultLine'));
1580
1639
  if (this.format.isTextStyleNode(n)) {
1581
1640
  /** @type {HTMLElement} */
1582
1641
  (n).removeAttribute('style');
@@ -1675,7 +1734,7 @@ HTML.prototype = {
1675
1734
  }
1676
1735
 
1677
1736
  if (sv) {
1678
- if (!v) v = [];
1737
+ v ||= [];
1679
1738
 
1680
1739
  let mv;
1681
1740
  for (const [key, value] of this._cleanStyleRegExpMap) {
@@ -1694,7 +1753,7 @@ HTML.prototype = {
1694
1753
  r = style[i].match(/([a-zA-Z0-9-]+)(:)([^"']+)/);
1695
1754
  if (r && !/inherit|initial|revert|unset/i.test(r[3])) {
1696
1755
  const k = converter.kebabToCamelCase(r[1].trim());
1697
- const cs = this.editor.frameContext.get('wwComputedStyle')[k]?.replace(/"/g, '');
1756
+ const cs = this.frameContext.get('wwComputedStyle')[k]?.replace(/"/g, '');
1698
1757
  const c = r[3].trim();
1699
1758
  switch (k) {
1700
1759
  case 'fontFamily':
@@ -1748,7 +1807,6 @@ HTML.prototype = {
1748
1807
  * @param {Node} parentNode The parent node where the duplicate check occurs.
1749
1808
  */
1750
1809
  _checkDuplicateNode(oNode, parentNode) {
1751
- // eslint-disable-next-line @typescript-eslint/no-this-alias
1752
1810
  const inst = this;
1753
1811
  (function recursionFunc(current) {
1754
1812
  inst._dupleCheck(current, parentNode);
@@ -1802,7 +1860,7 @@ HTML.prototype = {
1802
1860
  oNode.setAttribute('style', '');
1803
1861
  oNode.removeAttribute('style');
1804
1862
  }
1805
- if (!oNode.attributes.length) {
1863
+ if (oNode.attributes.length === 0) {
1806
1864
  oNode.setAttribute('data-duple', 'true');
1807
1865
  }
1808
1866
  }
@@ -1879,7 +1937,7 @@ function CleanElements(attrFilter, styleFilter, m, t) {
1879
1937
  if (tagName === 'a') {
1880
1938
  const sv = m.match(/(?:(?:id|name)\s*=\s*(?:"|')[^"']*(?:"|'))/g);
1881
1939
  if (sv) {
1882
- if (!v) v = [];
1940
+ v ||= [];
1883
1941
  v.push(sv[0]);
1884
1942
  }
1885
1943
  } else if (!v || !/style=/i.test(v.toString())) {
@@ -1895,7 +1953,7 @@ function CleanElements(attrFilter, styleFilter, m, t) {
1895
1953
  // figure
1896
1954
  if (dom.check.isMedia(tagName) || dom.check.isFigure(tagName)) {
1897
1955
  const sv = m.match(/style\s*=\s*(?:"|')[^"']*(?:"|')/);
1898
- if (!v) v = [];
1956
+ v ||= [];
1899
1957
  if (sv) v.push(sv[0]);
1900
1958
  }
1901
1959