suneditor 3.1.4 → 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.
Files changed (216) hide show
  1. package/dist/suneditor-contents.min.css +1 -1
  2. package/dist/suneditor.min.css +28 -1
  3. package/dist/suneditor.min.js +1 -1
  4. package/package.json +2 -1
  5. package/src/assets/design/color.css +12 -0
  6. package/src/assets/design/size.css +9 -2
  7. package/src/assets/icons/defaultIcons.js +96 -47
  8. package/src/assets/suneditor-contents.css +3 -2
  9. package/src/assets/suneditor.css +480 -31
  10. package/src/core/config/contextProvider.js +2 -1
  11. package/src/core/config/eventManager.js +41 -2
  12. package/src/core/config/optionProvider.js +23 -2
  13. package/src/core/editor.js +32 -14
  14. package/src/core/event/actions/index.js +76 -9
  15. package/src/core/event/effects/common.registry.js +2 -1
  16. package/src/core/event/effects/keydown.registry.js +169 -33
  17. package/src/core/event/effects/ruleHelpers.js +20 -6
  18. package/src/core/event/eventOrchestrator.js +136 -23
  19. package/src/core/event/handlers/handler_toolbar.js +4 -2
  20. package/src/core/event/handlers/handler_ww_dragDrop.js +10 -0
  21. package/src/core/event/handlers/handler_ww_input.js +9 -2
  22. package/src/core/event/handlers/handler_ww_key.js +86 -17
  23. package/src/core/event/handlers/handler_ww_mouse.js +45 -8
  24. package/src/core/event/ports.js +23 -5
  25. package/src/core/event/reducers/keydown.reducer.js +15 -2
  26. package/src/core/event/rules/keydown.rule.arrow.js +12 -2
  27. package/src/core/event/rules/keydown.rule.backspace.js +110 -15
  28. package/src/core/event/rules/keydown.rule.delete.js +62 -7
  29. package/src/core/event/rules/keydown.rule.enter.js +62 -31
  30. package/src/core/event/support/defaultLineManager.js +9 -2
  31. package/src/core/event/support/selectionState.js +13 -3
  32. package/src/core/kernel/coreKernel.js +1 -0
  33. package/src/core/logic/dom/char.js +13 -3
  34. package/src/core/logic/dom/format.js +171 -39
  35. package/src/core/logic/dom/html.js +350 -72
  36. package/src/core/logic/dom/inline.js +229 -34
  37. package/src/core/logic/dom/listFormat.js +111 -20
  38. package/src/core/logic/dom/nodeTransform.js +36 -11
  39. package/src/core/logic/dom/offset.js +116 -31
  40. package/src/core/logic/dom/selection.js +147 -29
  41. package/src/core/logic/panel/blockHandle.js +785 -0
  42. package/src/core/logic/panel/blockResolver.js +278 -0
  43. package/src/core/logic/panel/finder.js +16 -6
  44. package/src/core/logic/panel/menu.js +119 -18
  45. package/src/core/logic/panel/toolbar.js +75 -19
  46. package/src/core/logic/panel/viewer.js +76 -20
  47. package/src/core/logic/shell/_commandExecutor.js +44 -9
  48. package/src/core/logic/shell/commandDispatcher.js +46 -4
  49. package/src/core/logic/shell/component.js +102 -25
  50. package/src/core/logic/shell/focusManager.js +13 -3
  51. package/src/core/logic/shell/history.js +21 -6
  52. package/src/core/logic/shell/pluginManager.js +21 -13
  53. package/src/core/logic/shell/shortcuts.js +9 -1
  54. package/src/core/logic/shell/ui.js +139 -37
  55. package/src/core/schema/frameContext.js +34 -3
  56. package/src/core/schema/options.js +46 -4
  57. package/src/core/section/constructor.js +537 -93
  58. package/src/core/section/documentType.js +35 -6
  59. package/src/helper/converter.js +24 -7
  60. package/src/helper/dom/domCheck.js +25 -5
  61. package/src/helper/dom/domQuery.js +2 -1
  62. package/src/helper/dom/domUtils.js +17 -4
  63. package/src/helper/env.js +11 -2
  64. package/src/helper/keyCodeMap.js +6 -2
  65. package/src/helper/markdown.js +24 -5
  66. package/src/helper/msOffice.js +9 -2
  67. package/src/interfaces/plugins.js +1 -1
  68. package/src/langs/ckb.js +0 -1
  69. package/src/langs/cs.js +0 -1
  70. package/src/langs/da.js +0 -1
  71. package/src/langs/de.js +0 -1
  72. package/src/langs/en.js +0 -1
  73. package/src/langs/es.js +0 -1
  74. package/src/langs/fa.js +0 -1
  75. package/src/langs/fr.js +0 -1
  76. package/src/langs/he.js +0 -1
  77. package/src/langs/hu.js +0 -1
  78. package/src/langs/index.js +27 -1
  79. package/src/langs/it.js +0 -1
  80. package/src/langs/ja.js +0 -1
  81. package/src/langs/km.js +0 -1
  82. package/src/langs/ko.js +0 -1
  83. package/src/langs/lv.js +0 -1
  84. package/src/langs/nl.js +0 -1
  85. package/src/langs/pl.js +0 -1
  86. package/src/langs/pt_br.js +0 -1
  87. package/src/langs/ro.js +0 -1
  88. package/src/langs/ru.js +0 -1
  89. package/src/langs/se.js +0 -1
  90. package/src/langs/tr.js +0 -1
  91. package/src/langs/uk.js +0 -1
  92. package/src/langs/ur.js +0 -1
  93. package/src/langs/zh_cn.js +0 -1
  94. package/src/modules/contract/Browser.js +58 -14
  95. package/src/modules/contract/ColorPicker.js +12 -4
  96. package/src/modules/contract/Controller.js +37 -7
  97. package/src/modules/contract/Figure.js +156 -36
  98. package/src/modules/contract/HueSlider.js +27 -4
  99. package/src/modules/contract/Modal.js +50 -10
  100. package/src/modules/manager/FileManager.js +50 -8
  101. package/src/modules/ui/CommandMenu.js +597 -0
  102. package/src/modules/ui/ModalAnchorEditor.js +33 -6
  103. package/src/modules/ui/SelectMenu.js +481 -36
  104. package/src/modules/ui/index.js +1 -0
  105. package/src/plugins/browser/audioGallery.js +2 -1
  106. package/src/plugins/browser/fileBrowser.js +9 -2
  107. package/src/plugins/browser/fileGallery.js +2 -1
  108. package/src/plugins/browser/imageGallery.js +18 -3
  109. package/src/plugins/browser/videoGallery.js +13 -4
  110. package/src/plugins/command/blockquote.js +6 -1
  111. package/src/plugins/command/codeBlock.js +43 -5
  112. package/src/plugins/command/exportPDF.js +20 -4
  113. package/src/plugins/command/fileUpload.js +46 -11
  114. package/src/plugins/command/list_bulleted.js +6 -1
  115. package/src/plugins/command/list_numbered.js +6 -1
  116. package/src/plugins/dropdown/align.js +21 -33
  117. package/src/plugins/dropdown/backgroundColor.js +10 -2
  118. package/src/plugins/dropdown/blockStyle.js +17 -22
  119. package/src/plugins/dropdown/font.js +34 -34
  120. package/src/plugins/dropdown/hr.js +15 -43
  121. package/src/plugins/dropdown/layout.js +10 -27
  122. package/src/plugins/dropdown/lineHeight.js +10 -33
  123. package/src/plugins/dropdown/list.js +19 -25
  124. package/src/plugins/dropdown/paragraphStyle.js +16 -24
  125. package/src/plugins/dropdown/table/index.js +72 -17
  126. package/src/plugins/dropdown/table/render/table.html.js +3 -1
  127. package/src/plugins/dropdown/table/services/table.cell.js +33 -7
  128. package/src/plugins/dropdown/table/services/table.clipboard.js +5 -1
  129. package/src/plugins/dropdown/table/services/table.grid.js +40 -9
  130. package/src/plugins/dropdown/table/services/table.resize.js +55 -11
  131. package/src/plugins/dropdown/table/services/table.selection.js +27 -7
  132. package/src/plugins/dropdown/table/services/table.style.js +120 -20
  133. package/src/plugins/dropdown/template.js +13 -29
  134. package/src/plugins/dropdown/textStyle.js +22 -35
  135. package/src/plugins/field/autocomplete.js +8 -4
  136. package/src/plugins/field/slashCommand.js +297 -0
  137. package/src/plugins/index.js +3 -0
  138. package/src/plugins/input/fontSize.js +37 -8
  139. package/src/plugins/input/pageNavigator.js +7 -1
  140. package/src/plugins/modal/audio.js +71 -17
  141. package/src/plugins/modal/drawing.js +41 -11
  142. package/src/plugins/modal/embed.js +92 -22
  143. package/src/plugins/modal/image/index.js +114 -28
  144. package/src/plugins/modal/image/services/image.size.js +9 -2
  145. package/src/plugins/modal/image/services/image.upload.js +38 -4
  146. package/src/plugins/modal/link.js +9 -2
  147. package/src/plugins/modal/math.js +10 -2
  148. package/src/plugins/modal/video/index.js +112 -26
  149. package/src/plugins/modal/video/render/video.html.js +4 -1
  150. package/src/plugins/modal/video/services/video.size.js +15 -4
  151. package/src/plugins/modal/video/services/video.upload.js +10 -2
  152. package/src/plugins/popup/anchor.js +14 -2
  153. package/src/suneditor.js +8 -2
  154. package/src/themes/cobalt.css +12 -0
  155. package/src/themes/cream.css +12 -0
  156. package/src/themes/dark.css +12 -0
  157. package/src/themes/midnight.css +12 -0
  158. package/src/typedef.js +32 -21
  159. package/types/assets/icons/defaultIcons.d.ts +1 -0
  160. package/types/core/config/contextProvider.d.ts +7 -1
  161. package/types/core/config/eventManager.d.ts +37 -4
  162. package/types/core/config/optionProvider.d.ts +5 -1
  163. package/types/core/event/actions/index.d.ts +44 -6
  164. package/types/core/event/effects/keydown.registry.d.ts +37 -7
  165. package/types/core/event/effects/ruleHelpers.d.ts +6 -1
  166. package/types/core/event/eventOrchestrator.d.ts +6 -1
  167. package/types/core/event/handlers/handler_ww_clipboard.d.ts +15 -3
  168. package/types/core/event/handlers/handler_ww_dragDrop.d.ts +14 -2
  169. package/types/core/event/handlers/handler_ww_input.d.ts +10 -2
  170. package/types/core/event/handlers/handler_ww_key.d.ts +10 -2
  171. package/types/core/event/handlers/handler_ww_mouse.d.ts +25 -5
  172. package/types/core/event/ports.d.ts +7 -2
  173. package/types/core/event/rules/keydown.rule.backspace.d.ts +6 -1
  174. package/types/core/kernel/store.d.ts +4 -1
  175. package/types/core/logic/dom/format.d.ts +32 -14
  176. package/types/core/logic/dom/html.d.ts +11 -3
  177. package/types/core/logic/dom/nodeTransform.d.ts +6 -6
  178. package/types/core/logic/panel/blockHandle.d.ts +64 -0
  179. package/types/core/logic/panel/blockResolver.d.ts +50 -0
  180. package/types/core/logic/panel/menu.d.ts +72 -3
  181. package/types/core/logic/shell/commandDispatcher.d.ts +8 -0
  182. package/types/core/logic/shell/component.d.ts +5 -3
  183. package/types/core/logic/shell/shortcuts.d.ts +10 -1
  184. package/types/core/logic/shell/ui.d.ts +7 -1
  185. package/types/core/schema/context.d.ts +7 -1
  186. package/types/core/schema/frameContext.d.ts +36 -4
  187. package/types/core/schema/options.d.ts +83 -2
  188. package/types/core/section/constructor.d.ts +38 -1
  189. package/types/events.d.ts +208 -32
  190. package/types/helper/converter.d.ts +4 -2
  191. package/types/helper/dom/domCheck.d.ts +12 -2
  192. package/types/helper/dom/domQuery.d.ts +35 -7
  193. package/types/helper/dom/domUtils.d.ts +4 -1
  194. package/types/interfaces/plugins.d.ts +2 -2
  195. package/types/langs/_Lang.d.ts +0 -1
  196. package/types/modules/contract/ColorPicker.d.ts +2 -2
  197. package/types/modules/contract/Controller.d.ts +7 -0
  198. package/types/modules/contract/Figure.d.ts +31 -4
  199. package/types/modules/ui/CommandMenu.d.ts +262 -0
  200. package/types/modules/ui/SelectMenu.d.ts +56 -3
  201. package/types/modules/ui/index.d.ts +1 -0
  202. package/types/plugins/browser/audioGallery.d.ts +1 -1
  203. package/types/plugins/browser/fileBrowser.d.ts +1 -1
  204. package/types/plugins/browser/fileGallery.d.ts +1 -1
  205. package/types/plugins/browser/imageGallery.d.ts +1 -1
  206. package/types/plugins/browser/videoGallery.d.ts +1 -1
  207. package/types/plugins/dropdown/align.d.ts +1 -1
  208. package/types/plugins/dropdown/blockStyle.d.ts +3 -1
  209. package/types/plugins/dropdown/table/index.d.ts +4 -1
  210. package/types/plugins/dropdown/table/services/table.clipboard.d.ts +5 -1
  211. package/types/plugins/dropdown/table/services/table.grid.d.ts +10 -2
  212. package/types/plugins/field/autocomplete.d.ts +0 -1
  213. package/types/plugins/field/slashCommand.d.ts +165 -0
  214. package/types/plugins/index.d.ts +3 -0
  215. package/types/plugins/modal/link.d.ts +4 -1
  216. package/types/typedef.d.ts +48 -23
@@ -152,7 +152,10 @@ class DocumentType {
152
152
  this.#rePageTimeout = _w.setTimeout(async () => {
153
153
  await dom.utils.waitForMediaLoad(this.#mirror, 1500);
154
154
 
155
- const heightGap = this.#ww.scrollHeight > this.#mirror.scrollHeight ? this.#ww.scrollHeight - this.#mirror.scrollHeight : 0;
155
+ const heightGap =
156
+ this.#ww.scrollHeight > this.#mirror.scrollHeight
157
+ ? this.#ww.scrollHeight - this.#mirror.scrollHeight
158
+ : 0;
156
159
  const mirrorHeight = this.#mirror.scrollHeight + heightGap;
157
160
  const pageBreaks = /** @type { NodeListOf<HTMLElement>} */ (this.#ww.querySelectorAll('.se-page-break'));
158
161
  if (!force && this.#pageHeight === mirrorHeight && this.#pageBreaksCnt === pageBreaks.length) return;
@@ -166,7 +169,10 @@ class DocumentType {
166
169
  if (pageBreaks.length > 0) {
167
170
  pageBreakHeight = pageBreaks[0].offsetHeight;
168
171
  for (let i = 0; i < pageBreaks.length; i++) {
169
- breakPoints.push({ top: pageBreaks[i].offsetTop, end: pageBreaks[i].offsetTop + pageBreakHeight / 2 });
172
+ breakPoints.push({
173
+ top: pageBreaks[i].offsetTop,
174
+ end: pageBreaks[i].offsetTop + pageBreakHeight / 2,
175
+ });
170
176
  }
171
177
  }
172
178
 
@@ -238,6 +244,7 @@ class DocumentType {
238
244
 
239
245
  this.#pagesLine = this.#page.querySelectorAll('.se-document-page-line');
240
246
  this.#totalPages = this.#pages.length;
247
+ this.#updatePageVisibility();
241
248
  this._displayCurrentPage();
242
249
  }, 400);
243
250
  }
@@ -382,14 +389,29 @@ class DocumentType {
382
389
  if (prevScrollTop === scrollTop) return;
383
390
 
384
391
  const pages = this.#pages;
392
+ const delta = scrollTop - prevScrollTop;
385
393
  for (let i = 0, len = pages.length; i < len; i++) {
386
- pages[i].style.top = `${numbers.get(pages[i].style.top) - (scrollTop - prevScrollTop)}px`;
394
+ pages[i].style.top = `${numbers.get(pages[i].style.top) - delta}px`;
387
395
  }
396
+ this.#updatePageVisibility();
388
397
 
389
398
  this.#prevScrollTop = scrollTop;
390
399
  this._displayCurrentPage();
391
400
  }
392
401
 
402
+ /**
403
+ * @description Hide page indicators whose `top` has scrolled past the wysiwyg
404
+ */
405
+ #updatePageVisibility() {
406
+ const pages = this.#pages;
407
+ if (!pages?.length) return;
408
+ const wwHeight = this.#wwFrame.offsetHeight;
409
+ for (let i = 0, len = pages.length; i < len; i++) {
410
+ const top = numbers.get(pages[i].style.top);
411
+ pages[i].style.display = top < 0 || top > wwHeight ? 'none' : '';
412
+ }
413
+ }
414
+
393
415
  /**
394
416
  * @description Scrolls the window to a specific position.
395
417
  */
@@ -508,15 +530,22 @@ class DocumentType {
508
530
  const globalTop = this._getGlobalTop();
509
531
  const isScrollable = this.#isScrollable(this.#fc);
510
532
  const children = converter.nodeListToArray(this.#ww.children);
511
- const pageTop = this.#page.offsetTop + numbers.get(this.#pages[pageNum - 1].style.top) + (!isScrollable ? 0 : this._getWWScrollTop());
533
+ const pageTop =
534
+ this.#page.offsetTop +
535
+ numbers.get(this.#pages[pageNum - 1].style.top) +
536
+ (!isScrollable ? 0 : this._getWWScrollTop());
512
537
  for (let i = 0, len = children.length, c; i < len; i++) {
513
538
  c = children[i];
514
539
  if (c.offsetTop >= pageTop) {
515
540
  if (!force) this.#selection.setRange(c, 0, c, 0);
516
- const scrollTop = i === 0 && isScrollable ? 0 : c.offsetTop - this.#page.offsetTop - c.offsetHeight + globalTop;
541
+ const scrollTop =
542
+ i === 0 && isScrollable ? 0 : c.offsetTop - this.#page.offsetTop - c.offsetHeight + globalTop;
517
543
  this._applyPageScroll(scrollTop, () => {
518
544
  if (this.#toolbar.isSticky && !this.#store.mode.isBottom) {
519
- this._getDisplayPage().scrollTo({ top: scrollTop - this.#context.get('toolbar_main').offsetHeight, behavior: 'smooth' });
545
+ this._getDisplayPage().scrollTo({
546
+ top: scrollTop - this.#context.get('toolbar_main').offsetHeight,
547
+ behavior: 'smooth',
548
+ });
520
549
  }
521
550
  });
522
551
 
@@ -137,26 +137,35 @@ export function entityToHTML(content) {
137
137
  }
138
138
 
139
139
  /**
140
- * @description Debounce function
140
+ * @description Debounce function. The returned function exposes a `cancel()` method that clears any
141
+ * pending invocation (useful when an event — e.g. ESC — should abort a scheduled callback).
141
142
  * @param {(...args: *) => void} func function
142
143
  * @param {number} wait delay ms
143
- * @returns {*} executedFunction
144
+ * @returns {*} executedFunction — the debounced function, with a `cancel()` method attached
144
145
  * @example
145
146
  * const debouncedSave = converter.debounce(() => save(), 300);
146
147
  * input.addEventListener('input', debouncedSave);
148
+ * // later: debouncedSave.cancel();
147
149
  */
148
150
  export function debounce(func, wait) {
149
151
  let timeout;
150
152
 
151
- return function executedFunction(...args) {
153
+ function executedFunction(...args) {
152
154
  const later = () => {
153
- _w.clearTimeout(timeout);
155
+ timeout = null;
154
156
  func(...args);
155
157
  };
156
158
 
157
159
  _w.clearTimeout(timeout);
158
160
  timeout = _w.setTimeout(later, wait);
161
+ }
162
+
163
+ executedFunction.cancel = () => {
164
+ _w.clearTimeout(timeout);
165
+ timeout = null;
159
166
  };
167
+
168
+ return executedFunction;
160
169
  }
161
170
 
162
171
  /**
@@ -435,7 +444,11 @@ export function textToAnchor(node) {
435
444
  * @param {Node} node Node
436
445
  */
437
446
  export function spanToStyleNode(styleToTag, node) {
438
- if (node.nodeType === 1 && /^SPAN$/i.test(node.nodeName) && /** @type {HTMLElement} */ (node).hasAttribute('style')) {
447
+ if (
448
+ node.nodeType === 1 &&
449
+ /^SPAN$/i.test(node.nodeName) &&
450
+ /** @type {HTMLElement} */ (node).hasAttribute('style')
451
+ ) {
439
452
  const style = /** @type {HTMLElement} */ (node).getAttribute('style');
440
453
  const tags = [];
441
454
  Object.keys(styleToTag).forEach((key) => {
@@ -572,7 +585,9 @@ export function _setIframeStyleLinks(linkNames) {
572
585
  }
573
586
 
574
587
  if (!path || path.length === 0) {
575
- throw new Error('[SUNEDITOR.constructor.iframe.fail] The suneditor CSS files installation path could not be automatically detected. Please set the option property "iframe_cssFileName" before creating editor instances.');
588
+ throw new Error(
589
+ '[SUNEDITOR.constructor.iframe.fail] The suneditor CSS files installation path could not be automatically detected. Please set the option property "iframe_cssFileName" before creating editor instances.',
590
+ );
576
591
  }
577
592
 
578
593
  for (let i = 0, pLen = path.length; i < pLen; i++) {
@@ -590,7 +605,9 @@ export function _setIframeStyleLinks(linkNames) {
590
605
  * @returns {string} `"<style>...</style>"`
591
606
  */
592
607
  export function _setAutoHeightStyle(frameHeight) {
593
- return frameHeight === 'auto' ? '<style>\n/** Iframe height auto */\nbody{height: min-content; overflow: hidden;}\n</style>' : '';
608
+ return frameHeight === 'auto'
609
+ ? '<style>\n/** Iframe height auto */\nbody{height: min-content; overflow: hidden;}\n</style>'
610
+ : '';
594
611
  }
595
612
 
596
613
  const converter = {
@@ -31,7 +31,11 @@ export function isZeroWidth(text) {
31
31
  * @returns {boolean}
32
32
  */
33
33
  export function isEdgePoint(container, offset, dir) {
34
- return (dir !== 'end' && offset === 0) || ((!dir || dir !== 'front') && !container.nodeValue && offset <= 1) || ((!dir || dir === 'end') && container.nodeValue && offset >= container.nodeValue.length);
34
+ return (
35
+ (dir !== 'end' && offset === 0) ||
36
+ ((!dir || dir !== 'front') && !container.nodeValue && offset <= 1) ||
37
+ ((!dir || dir === 'end') && container.nodeValue && offset >= container.nodeValue.length)
38
+ );
35
39
  }
36
40
 
37
41
  /**
@@ -175,7 +179,9 @@ export function isFigure(node) {
175
179
  * @returns {boolean}
176
180
  */
177
181
  export function isContentLess(node) {
178
- return /^(BR|COLGROUP|COL|THEAD|TBODY|TFOOT|TR|AREA|BASE|EMBED|HR|IMG|INPUT|KEYGEN|LINK|META|PARAM|SOURCE|TRACK|WBR)$/i.test(typeof node === 'string' ? node : node?.nodeName);
182
+ return /^(BR|COLGROUP|COL|THEAD|TBODY|TFOOT|TR|AREA|BASE|EMBED|HR|IMG|INPUT|KEYGEN|LINK|META|PARAM|SOURCE|TRACK|WBR)$/i.test(
183
+ typeof node === 'string' ? node : node?.nodeName,
184
+ );
179
185
  }
180
186
 
181
187
  /**
@@ -186,7 +192,11 @@ export function isContentLess(node) {
186
192
  export function isEmptyLine(node) {
187
193
  if (!node?.parentNode) return true;
188
194
  const el = /** @type {HTMLElement} */ (node);
189
- return !el.querySelector('IMG, IFRAME, AUDIO, VIDEO, CANVAS, TABLE') && (el.children.length <= 1 || isBreak(el.firstElementChild)) && isZeroWidth(el.textContent);
195
+ return (
196
+ !el.querySelector('IMG, IFRAME, AUDIO, VIDEO, CANVAS, TABLE') &&
197
+ (el.children.length <= 1 || isBreak(el.firstElementChild)) &&
198
+ isZeroWidth(el.textContent)
199
+ );
190
200
  }
191
201
 
192
202
  /**
@@ -216,7 +226,12 @@ export function isWysiwygFrame(node) {
216
226
  const cls = el.classList;
217
227
 
218
228
  if (!cls) return false;
219
- return node.nodeName.toUpperCase() === 'BODY' || cls.contains('se-wrapper-wysiwyg') || cls.contains('sun-editor-carrier-wrapper') || cls.contains('se-wrapper');
229
+ return (
230
+ node.nodeName.toUpperCase() === 'BODY' ||
231
+ cls.contains('se-wrapper-wysiwyg') ||
232
+ cls.contains('sun-editor-carrier-wrapper') ||
233
+ cls.contains('se-wrapper')
234
+ );
220
235
  }
221
236
 
222
237
  /**
@@ -267,7 +282,12 @@ export function isSameAttributes(a, b) {
267
282
  if (class_b.contains(class_a[i])) compClass++;
268
283
  }
269
284
 
270
- return compStyle === style_b.length && compStyle === style_a.length && compClass === class_b.length && compClass === class_a.length;
285
+ return (
286
+ compStyle === style_b.length &&
287
+ compStyle === style_a.length &&
288
+ compClass === class_b.length &&
289
+ compClass === class_a.length
290
+ );
271
291
  }
272
292
 
273
293
  /**
@@ -501,7 +501,8 @@ export function getEdgeChildNodes(first, last) {
501
501
  if (!first) return;
502
502
  last ||= first;
503
503
 
504
- while (first && first.nodeType === 1 && first.childNodes.length > 0 && !domCheck.isBreak(first)) first = first.firstChild;
504
+ while (first && first.nodeType === 1 && first.childNodes.length > 0 && !domCheck.isBreak(first))
505
+ first = first.firstChild;
505
506
  while (last && last.nodeType === 1 && last.childNodes.length > 0 && !domCheck.isBreak(last)) last = last.lastChild;
506
507
 
507
508
  return {
@@ -224,6 +224,9 @@ export function prevIndex(array, item) {
224
224
  return idx - 1;
225
225
  }
226
226
 
227
+ // Block-handle transient markers — never persisted to cloned/split elements.
228
+ const TRANSIENT_CLASSES_RE = /(\s|^)(se-block-hover|se-block-dragging)(?=\s|$)/g;
229
+
227
230
  /**
228
231
  * @description Add style and className of copyEl to originEl
229
232
  * @param {Node} originEl Origin element
@@ -246,7 +249,15 @@ export function copyTagAttributes(originEl, copyEl, blacklist) {
246
249
  for (let i = 0, len = attrs.length, name; i < len; i++) {
247
250
  name = attrs[i].name.toLowerCase();
248
251
  if (blacklist?.includes(name) || !attrs[i].value) o.removeAttribute(name);
249
- else if (name !== 'style') o.setAttribute(attrs[i].name, attrs[i].value);
252
+ else if (name !== 'style') {
253
+ if (name === 'class') {
254
+ const classNames = attrs[i].value.replace(TRANSIENT_CLASSES_RE, ' ').replace(/\s+/g, ' ').trim();
255
+ if (classNames) o.setAttribute('class', classNames);
256
+ else o.removeAttribute('class');
257
+ } else {
258
+ o.setAttribute(attrs[i].name, attrs[i].value);
259
+ }
260
+ }
250
261
  }
251
262
  }
252
263
 
@@ -580,9 +591,11 @@ export function waitForMediaLoad(target, timeout = 5000) {
580
591
  });
581
592
  });
582
593
 
583
- Promise.race([Promise.all(mediaPromises), new Promise((resolve) => _w.setTimeout(resolve, timeout))]).then(() => {
584
- resolveAll();
585
- });
594
+ Promise.race([Promise.all(mediaPromises), new Promise((resolve) => _w.setTimeout(resolve, timeout))]).then(
595
+ () => {
596
+ resolveAll();
597
+ },
598
+ );
586
599
  });
587
600
  }
588
601
 
package/src/helper/env.js CHANGED
@@ -88,13 +88,22 @@ export function getIncludePath(nameArray, extension) {
88
88
  }
89
89
 
90
90
  if (!path) {
91
- throw new Error('[SUNEDITOR.helper.env.getIncludePath.fail] The SUNEDITOR installation path could not be automatically detected. (path: +' + path + ', extension: ' + extension + ')');
91
+ throw new Error(
92
+ '[SUNEDITOR.helper.env.getIncludePath.fail] The SUNEDITOR installation path could not be automatically detected. (path: +' +
93
+ path +
94
+ ', extension: ' +
95
+ extension +
96
+ ')',
97
+ );
92
98
  }
93
99
 
94
100
  if (path === '') path = pathList.length > 0 ? pathList[0][src] : '';
95
101
 
96
102
  if (!path.includes(':/') && '//' !== path.slice(0, 2)) {
97
- path = false === path.includes('/') ? location.href.match(/^.*?:\/\/[^/]*/)[0] + path : location.href.match(/^[^?]*\/(?:)/)[0] + path;
103
+ path =
104
+ false === path.includes('/')
105
+ ? location.href.match(/^.*?:\/\/[^/]*/)[0] + path
106
+ : location.href.match(/^[^?]*\/(?:)/)[0] + path;
98
107
  }
99
108
 
100
109
  return path;
@@ -5,13 +5,17 @@ const DIR_KEYCODE = _arrow.split('|');
5
5
  // const DELETE_KEYCODE = /^(8|46)$/;
6
6
  const DELETE_KEYCODE = 'Backspace|Delete'.split('|');
7
7
  // const NON_TEXT_KEYCODE = /^(8|9|13|1[6-9]|20|27|3[3-9]|40|45|46|11[2-9]|12[0-3]|144|145|229)$/;
8
- const NON_TEXT_KEYCODE = `Backspace|Tab|Enter|ShiftLeft|ShiftRight|ControlLeft|ControlRight|AltLeft|AltRight|Pause|CapsLock|Escape|PageUp|PageDown|End|Home|${_arrow}|Insert|Delete|${_fN}|NumLock|ScrollLock`.split('|');
8
+ const NON_TEXT_KEYCODE =
9
+ `Backspace|Tab|Enter|ShiftLeft|ShiftRight|ControlLeft|ControlRight|AltLeft|AltRight|Pause|CapsLock|Escape|PageUp|PageDown|End|Home|${_arrow}|Insert|Delete|${_fN}|NumLock|ScrollLock`.split(
10
+ '|',
11
+ );
9
12
  // const HISTORY_RELEVANT_KEYS = /^(9|13|46)$/;
10
13
  const HISTORY_RELEVANT_KEYS = `Backspace|Enter|Delete`.split('|');
11
14
  // const DOCUMENT_TYPE_OBSERVER_KEYCODE = /^(8|13|46)$/;
12
15
  const DOCUMENT_TYPE_OBSERVER_KEYCODE = 'Backspace|Enter|Delete'.split('|');
13
16
  // const NON_RESPONSE_KEYCODE = /^(1[7-9]|20|27|45|11[2-9]|12[0-3]|144|145)$/;
14
- const NON_RESPONSE_CODE = `ControlLeft|ControlRight|AltLeft|AltRight|Pause|CapsLock|Escape|Insert|${_fN}|NumLock|ScrollLock`.split('|');
17
+ const NON_RESPONSE_CODE =
18
+ `ControlLeft|ControlRight|AltLeft|AltRight|Pause|CapsLock|Escape|Insert|${_fN}|NumLock|ScrollLock`.split('|');
15
19
 
16
20
  /** ------------------------------------------------------- [meta] ------------------------------------------------------- */
17
21
  /**
@@ -60,7 +60,13 @@ function childrenToInline(children) {
60
60
  // the previous part doesn't end with space and current doesn't start with space
61
61
  if (parts.length > 0) {
62
62
  const prev = parts[parts.length - 1];
63
- if (prev && !prev.endsWith(' ') && !prev.endsWith('\n') && !part.startsWith(' ') && !part.startsWith('\n')) {
63
+ if (
64
+ prev &&
65
+ !prev.endsWith(' ') &&
66
+ !prev.endsWith('\n') &&
67
+ !part.startsWith(' ') &&
68
+ !part.startsWith('\n')
69
+ ) {
64
70
  parts.push(' ');
65
71
  }
66
72
  }
@@ -143,7 +149,12 @@ function listToMarkdown(node, indent, isOrdered) {
143
149
  // GFM task list: check for checkbox input
144
150
  let taskPrefix = '';
145
151
  const firstChild = liChildren[0];
146
- if (firstChild && firstChild.type === 'element' && firstChild.tag === 'input' && firstChild.attributes?.type === 'checkbox') {
152
+ if (
153
+ firstChild &&
154
+ firstChild.type === 'element' &&
155
+ firstChild.tag === 'input' &&
156
+ firstChild.attributes?.type === 'checkbox'
157
+ ) {
147
158
  taskPrefix = firstChild.attributes.checked !== undefined ? '[x] ' : '[ ] ';
148
159
  }
149
160
 
@@ -537,7 +548,9 @@ function parseInline(text) {
537
548
 
538
549
  // 5. Autolinks: <https://url> or <email@example.com>
539
550
  text = text.replace(/<(https?:\/\/[^>]+)>/g, (_, url) => hold(`<a href="${url}">${url}</a>`));
540
- text = text.replace(/<([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})>/g, (_, email) => hold(`<a href="mailto:${email}">${email}</a>`));
551
+ text = text.replace(/<([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})>/g, (_, email) =>
552
+ hold(`<a href="mailto:${email}">${email}</a>`),
553
+ );
541
554
 
542
555
  // 6. GFM autolink: bare URLs (only when not already inside a tag attribute)
543
556
  text = text.replace(/(?<![="'\w/])(https?:\/\/[^\s<>\])"]+)/g, (_, url) => hold(`<a href="${url}">${url}</a>`));
@@ -695,7 +708,11 @@ export function markdownToHtml(md, defaultLine) {
695
708
 
696
709
  // Paragraph (default)
697
710
  const paraLines = [];
698
- while (i < lines.length && !isBlankLine(lines[i]) && !/^(#{1,6}\s|`{3,}|~{3,}|>|\||(\s*)([-*+]|\d+\.)\s|(\*{3,}|-{3,}|_{3,})\s*$)/.test(lines[i])) {
711
+ while (
712
+ i < lines.length &&
713
+ !isBlankLine(lines[i]) &&
714
+ !/^(#{1,6}\s|`{3,}|~{3,}|>|\||(\s*)([-*+]|\d+\.)\s|(\*{3,}|-{3,}|_{3,})\s*$)/.test(lines[i])
715
+ ) {
699
716
  paraLines.push(lines[i]);
700
717
  i++;
701
718
  }
@@ -859,7 +876,9 @@ function parseList(lines, startIndex, ordered) {
859
876
  }
860
877
 
861
878
  if (isTask) {
862
- const checkbox = taskChecked ? '<input type="checkbox" checked disabled> ' : '<input type="checkbox" disabled> ';
879
+ const checkbox = taskChecked
880
+ ? '<input type="checkbox" checked disabled> '
881
+ : '<input type="checkbox" disabled> ';
863
882
  html += `<li class="task-list-item">${checkbox}${parseInline(displayContent)}${nestedHtml}</li>`;
864
883
  } else {
865
884
  html += `<li>${parseInline(content)}${nestedHtml}</li>`;
@@ -212,7 +212,13 @@ function _cleanStyles(el) {
212
212
  cleaned += ';background-color:' + highlightMatch[1].trim();
213
213
  }
214
214
 
215
- cleaned = cleaned.replace(_RE_MSO_STYLE, '').replace(_RE_TAB_STOPS, '').replace(_RE_ZERO_MARGIN, '').replace(_RE_TEXT_INDENT, '').replace(_RE_LINE_HEIGHT_NORMAL, '').trim();
215
+ cleaned = cleaned
216
+ .replace(_RE_MSO_STYLE, '')
217
+ .replace(_RE_TAB_STOPS, '')
218
+ .replace(_RE_ZERO_MARGIN, '')
219
+ .replace(_RE_TEXT_INDENT, '')
220
+ .replace(_RE_LINE_HEIGHT_NORMAL, '')
221
+ .trim();
216
222
 
217
223
  // Remove trailing/leading semicolons
218
224
  cleaned = cleaned
@@ -297,7 +303,8 @@ function _convertLists(doc, listStyles) {
297
303
 
298
304
  for (const item of items) {
299
305
  const prevSibling = _getPrevSiblingElement(item.el);
300
- const isConsecutive = currentGroup && currentGroup.length > 0 && prevSibling === currentGroup[currentGroup.length - 1].el;
306
+ const isConsecutive =
307
+ currentGroup && currentGroup.length > 0 && prevSibling === currentGroup[currentGroup.length - 1].el;
301
308
 
302
309
  if (isConsecutive) {
303
310
  currentGroup.push(item);
@@ -65,7 +65,7 @@ export class PluginBrowser extends Base {
65
65
  /**
66
66
  * @abstract
67
67
  * @description Executes the method that is called when a `Browser` module is opened.
68
- * @param {?(target: Node) => *} [onSelectfunction] - Method to be executed after selecting an item in the gallery
68
+ * @param {?(target: *) => *} [onSelectfunction] - Method to be executed after selecting an item in the gallery
69
69
  * @returns {void}
70
70
  */
71
71
  open(onSelectfunction) {
package/src/langs/ckb.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'بیركاری',
135
135
  maxSize: 'گه‌وره‌ترین قه‌باره‌',
136
136
  mediaGallery: 'گەلەری میدیا',
137
- autocomplete: 'تەواوکردنی ئۆتۆماتیکی',
138
137
  mention: 'تنويه ب',
139
138
  menu_bordered: 'لێواری هه‌بێت',
140
139
  menu_code: 'كۆد',
package/src/langs/cs.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Matematika',
135
135
  maxSize: 'Max. velikost',
136
136
  mediaGallery: 'Galerie médií',
137
- autocomplete: 'Automatické doplňování',
138
137
  mention: 'Zmínka',
139
138
  menu_bordered: 'Ohraničené',
140
139
  menu_code: 'Kód',
package/src/langs/da.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Math',
135
135
  maxSize: 'Max størrelse',
136
136
  mediaGallery: 'Mediegalleri',
137
- autocomplete: 'Autofuldførelse',
138
137
  mention: 'Nævne',
139
138
  menu_bordered: 'Afgrænsningslinje',
140
139
  menu_code: 'Code',
package/src/langs/de.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Mathematik',
135
135
  maxSize: 'Maximale Größe',
136
136
  mediaGallery: 'Mediengalerie',
137
- autocomplete: 'Autovervollständigung',
138
137
  mention: 'Erwähnen',
139
138
  menu_bordered: 'Umrandet',
140
139
  menu_code: 'Quellcode',
package/src/langs/en.js CHANGED
@@ -133,7 +133,6 @@
133
133
  math_modal_title: 'Math',
134
134
  maxSize: 'Max size',
135
135
  mediaGallery: 'Media gallery',
136
- autocomplete: 'Autocomplete',
137
136
  menu_bordered: 'Bordered',
138
137
  menu_code: 'Code',
139
138
  menu_neon: 'Neon',
package/src/langs/es.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Matemáticas',
135
135
  maxSize: 'Tamaño máximo',
136
136
  mediaGallery: 'Galería de medios',
137
- autocomplete: 'Autocompletar',
138
137
  mention: 'Mencionar',
139
138
  menu_bordered: 'Bordeado',
140
139
  menu_code: 'Código',
package/src/langs/fa.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'فرمول ریاضی',
135
135
  maxSize: 'حداکثر اندازه',
136
136
  mediaGallery: 'گالری رسانه',
137
- autocomplete: 'تکمیل خودکار',
138
137
  mention: 'ذکر کردن',
139
138
  menu_bordered: 'لبه‌دار',
140
139
  menu_code: 'کُد',
package/src/langs/fr.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Math',
135
135
  maxSize: 'Taille max',
136
136
  mediaGallery: 'Galerie multimédia',
137
- autocomplete: 'Saisie semi-automatique',
138
137
  mention: 'Mention',
139
138
  menu_bordered: 'Ligne de démarcation',
140
139
  menu_code: 'Code',
package/src/langs/he.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'נוסחה',
135
135
  maxSize: 'גודל מרבי',
136
136
  mediaGallery: 'גלריית מדיה',
137
- autocomplete: 'השלמה אוטומטית',
138
137
  mention: 'הזכר',
139
138
  menu_bordered: 'בעל מיתאר',
140
139
  menu_code: 'קוד',
package/src/langs/hu.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Matematika',
135
135
  maxSize: 'Maximális méret',
136
136
  mediaGallery: 'Média galéria',
137
- autocomplete: 'Automatikus kiegészítés',
138
137
  mention: 'Említés',
139
138
  menu_bordered: 'Keretezett',
140
139
  menu_code: 'Kód',
@@ -25,4 +25,30 @@ import ur from './ur';
25
25
  import zh_cn from './zh_cn';
26
26
 
27
27
  export { ckb, cs, da, de, en, es, fa, fr, he, hu, it, ja, ko, km, lv, nl, pl, pt_br, ro, ru, se, tr, uk, ur, zh_cn };
28
- export default { ckb, cs, da, de, en, es, fa, fr, he, hu, it, ja, ko, km, lv, nl, pl, pt_br, ro, ru, se, tr, uk, ur, zh_cn };
28
+ export default {
29
+ ckb,
30
+ cs,
31
+ da,
32
+ de,
33
+ en,
34
+ es,
35
+ fa,
36
+ fr,
37
+ he,
38
+ hu,
39
+ it,
40
+ ja,
41
+ ko,
42
+ km,
43
+ lv,
44
+ nl,
45
+ pl,
46
+ pt_br,
47
+ ro,
48
+ ru,
49
+ se,
50
+ tr,
51
+ uk,
52
+ ur,
53
+ zh_cn,
54
+ };
package/src/langs/it.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Matematica',
135
135
  maxSize: 'Dimensione massima',
136
136
  mediaGallery: 'Galleria multimediale',
137
- autocomplete: 'Completamento automatico',
138
137
  mention: 'Menzione',
139
138
  menu_bordered: 'Bordato',
140
139
  menu_code: 'Codice',
package/src/langs/ja.js CHANGED
@@ -133,7 +133,6 @@
133
133
  math_modal_title: '数学',
134
134
  maxSize: '最大サイズ',
135
135
  mediaGallery: 'メディア ギャラリー',
136
- autocomplete: 'オートコンプリート',
137
136
  mention: '言及する',
138
137
  menu_bordered: '境界線',
139
138
  menu_code: 'コード',
package/src/langs/km.js CHANGED
@@ -133,7 +133,6 @@
133
133
  math_modal_title: 'គណិត',
134
134
  maxSize: 'ទំហំធំ',
135
135
  mediaGallery: 'វិចិត្រសាលមេឌៀ',
136
- autocomplete: 'បំពេញដោយស្វ័យប្រវត្តិ',
137
136
  mention: 'លើកឡើង',
138
137
  menu_bordered: 'មានស៊ុម',
139
138
  menu_code: 'កូដ',
package/src/langs/ko.js CHANGED
@@ -133,7 +133,6 @@
133
133
  math_modal_title: '수식',
134
134
  maxSize: '최대화',
135
135
  mediaGallery: '미디어 갤러리',
136
- autocomplete: '자동 완성',
137
136
  mention: '멘션',
138
137
  menu_bordered: '경계선',
139
138
  menu_code: '코드',
package/src/langs/lv.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Matemātika',
135
135
  maxSize: 'Maksimālais izmērs',
136
136
  mediaGallery: 'Mediju galerija',
137
- autocomplete: 'Automātiskā pabeigšana',
138
137
  mention: 'Pieminēt',
139
138
  menu_bordered: 'Robežojās',
140
139
  menu_code: 'Kods',
package/src/langs/nl.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Wiskunde',
135
135
  maxSize: 'Maximale grootte',
136
136
  mediaGallery: 'Mediagalerij',
137
- autocomplete: 'Automatisch aanvullen',
138
137
  mention: 'Vermelding',
139
138
  menu_bordered: 'Omlijnd',
140
139
  menu_code: 'Code',
package/src/langs/pl.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Matematyczne',
135
135
  maxSize: 'Maksymalny rozmiar',
136
136
  mediaGallery: 'Galeria multimediów',
137
- autocomplete: 'Automatyczne uzupełnianie',
138
137
  mention: 'Wzmianka',
139
138
  menu_bordered: 'Z obwódką',
140
139
  menu_code: 'Kod',
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Matemática',
135
135
  maxSize: 'Tam máx',
136
136
  mediaGallery: 'Galeria de mídia',
137
- autocomplete: 'Preenchimento automático',
138
137
  mention: 'Menção',
139
138
  menu_bordered: 'Com borda',
140
139
  menu_code: 'Código',
package/src/langs/ro.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Matematică',
135
135
  maxSize: 'Dimensiune maximă',
136
136
  mediaGallery: 'Galeria media',
137
- autocomplete: 'Completare automată',
138
137
  mention: 'Mentiune',
139
138
  menu_bordered: 'Mărginit',
140
139
  menu_code: 'Citat',
package/src/langs/ru.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'математический',
135
135
  maxSize: 'Ширина по размеру страницы',
136
136
  mediaGallery: 'Галерея мультимедиа',
137
- autocomplete: 'Автозаполнение',
138
137
  mention: 'Упоминание',
139
138
  menu_bordered: 'Граничная Линия',
140
139
  menu_code: 'Код',
package/src/langs/se.js CHANGED
@@ -134,7 +134,6 @@
134
134
  math_modal_title: 'Math',
135
135
  maxSize: 'Maxstorlek',
136
136
  mediaGallery: 'Rel attribut',
137
- autocomplete: 'Autoslutför',
138
137
  mention: 'Namn',
139
138
  menu_bordered: 'Avgränsningslinje',
140
139
  menu_code: 'Kod',