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
@@ -2,6 +2,7 @@
2
2
  * @fileoverview Implements Helper for querying the DOM.
3
3
  */
4
4
 
5
+ import { _w } from '../env';
5
6
  import { zeroWidthRegExp } from '../unicode';
6
7
  import domUtils from './domUtils';
7
8
  import domCheck from './domCheck';
@@ -96,38 +97,72 @@ export function getNodeFromPath(offsets, parentNode) {
96
97
  return /** @type {T} */ (current);
97
98
  }
98
99
 
100
+ /**
101
+ * @template {HTMLElement} T
102
+ * @description Get all "child node" of the argument value element
103
+ * @param {Node} element element to get child node
104
+ * @param {?(current: *) => boolean} validation Conditional function
105
+ * @returns {T|null}
106
+ */
107
+ export function getChildNode(element, validation) {
108
+ let child = null;
109
+ if (!element) return child;
110
+
111
+ const el = /** @type {Element} */ (element);
112
+ if (!el.children || el.children.length === 0) return child;
113
+
114
+ validation ||= () => true;
115
+
116
+ (function recursionFunc(current) {
117
+ if (el !== current && validation(current)) {
118
+ child = current;
119
+ return true;
120
+ }
121
+
122
+ if (current.children) {
123
+ for (let i = 0, len = current.children.length; i < len; i++) {
124
+ recursionFunc(current.children[i]);
125
+ }
126
+ }
127
+ })(el);
128
+
129
+ return /** @type {T} */ (child);
130
+ }
131
+
99
132
  /**
100
133
  * @template {HTMLElement} T
101
134
  * @description Get all "children" of the argument value element (Without text nodes)
102
135
  * @param {Node} element element to get child node
103
136
  * @param {?(current: *) => boolean} validation Conditional function
137
+ * @param {?number} depth Number of child levels to depth.
104
138
  * @returns {Array<T>}
105
139
  */
106
- export function getListChildren(element, validation) {
140
+ export function getListChildren(element, validation, depth) {
107
141
  /** @type {Array<T>} */
108
142
  const children = [];
109
- if (!element) return children;
143
+ depth ??= Infinity;
144
+ if (!element || depth <= 0) return /** @type {Array<T>} */ (children);
110
145
 
111
146
  const el = /** @type {Element} */ (element);
112
147
  if (!el.children || el.children.length === 0) return children;
113
148
 
114
- validation =
115
- validation ||
116
- function () {
117
- return true;
118
- };
149
+ validation ||= () => true;
119
150
 
120
- (function recursionFunc(current) {
121
- if (el !== current && validation(current)) {
151
+ (function recursionFunc(current, level) {
152
+ if (level > depth) return;
153
+
154
+ if (level > 0 && el !== current && validation(current)) {
122
155
  children.push(/** @type {T} */ (current));
123
156
  }
124
157
 
158
+ if (level === depth) return;
159
+
125
160
  if (current.children) {
126
161
  for (let i = 0, len = current.children.length; i < len; i++) {
127
- recursionFunc(current.children[i]);
162
+ recursionFunc(current.children[i], level + 1);
128
163
  }
129
164
  }
130
- })(el);
165
+ })(el, 0);
131
166
 
132
167
  return /** @type {Array<T>} */ (children);
133
168
  }
@@ -137,27 +172,30 @@ export function getListChildren(element, validation) {
137
172
  * @description Get all "childNodes" of the argument value element (Include text nodes)
138
173
  * @param {Node} element element to get child node
139
174
  * @param {?(current: *) => boolean} validation Conditional function
175
+ * @param {?number} depth Number of child levels to depth.
140
176
  * @returns {Array<T>}
141
177
  */
142
- export function getListChildNodes(element, validation) {
178
+ export function getListChildNodes(element, validation, depth) {
143
179
  const children = [];
144
- if (!element || element.childNodes.length === 0) return children;
180
+ depth ??= Infinity;
181
+ if (!element || depth <= 0 || element.childNodes.length === 0) return /** @type {Array<T>} */ (children);
145
182
 
146
- validation =
147
- validation ||
148
- function () {
149
- return true;
150
- };
183
+ validation ||= () => true;
151
184
 
152
- (function recursionFunc(current) {
153
- if (element !== current && validation(current)) {
185
+ (function recursionFunc(current, level) {
186
+ if (level > depth) return;
187
+
188
+ if (level > 0 && validation(current)) {
154
189
  children.push(current);
155
190
  }
156
191
 
157
- for (let i = 0, len = current.childNodes.length; i < len; i++) {
158
- recursionFunc(current.childNodes[i]);
192
+ if (level === depth) return;
193
+
194
+ const nodes = current.childNodes;
195
+ for (let i = 0, len = nodes.length; i < len; i++) {
196
+ recursionFunc(nodes[i], level + 1);
159
197
  }
160
- })(element);
198
+ })(element, 0);
161
199
 
162
200
  return /** @type {Array<T>} */ (children);
163
201
  }
@@ -214,7 +252,7 @@ export function compareElements(a, b) {
214
252
  bNode = bNode.parentElement;
215
253
  }
216
254
 
217
- if (!aNode || !bNode)
255
+ if (!aNode?.parentNode || !bNode?.parentNode)
218
256
  return {
219
257
  ancestor: null,
220
258
  a: a,
@@ -274,7 +312,7 @@ export function getParentElement(element, query, depth) {
274
312
  valid = (el) => regExp.test(el[attr]);
275
313
  }
276
314
 
277
- if (!depth) depth = Infinity;
315
+ depth ||= Infinity;
278
316
  let index = 0;
279
317
  while (element && !valid(element)) {
280
318
  if (index >= depth || domCheck.isWysiwygFrame(element)) {
@@ -328,7 +366,7 @@ export function getParentElements(element, query, depth) {
328
366
  }
329
367
 
330
368
  const elementList = [];
331
- if (!depth) depth = Infinity;
369
+ depth ||= Infinity;
332
370
  let index = 0;
333
371
  while (index <= depth && element && !domCheck.isWysiwygFrame(element)) {
334
372
  if (valid(element)) {
@@ -409,7 +447,7 @@ export function getEdgeChild(node, query, last) {
409
447
  };
410
448
  }
411
449
 
412
- const childList = getListChildNodes(node, (current) => valid(current));
450
+ const childList = getListChildNodes(node, (current) => valid(current), null);
413
451
 
414
452
  return /** @type {T} */ (childList[last ? childList.length - 1 : 0]);
415
453
  }
@@ -425,7 +463,7 @@ export function getEdgeChild(node, query, last) {
425
463
  */
426
464
  export function getEdgeChildNodes(first, last) {
427
465
  if (!first) return;
428
- if (!last) last = first;
466
+ last ||= first;
429
467
 
430
468
  while (first && first.nodeType === 1 && first.childNodes.length > 0 && !domCheck.isBreak(first)) first = first.firstChild;
431
469
  while (last && last.nodeType === 1 && last.childNodes.length > 0 && !domCheck.isBreak(last)) last = last.lastChild;
@@ -500,7 +538,7 @@ export function getNextDeepestNode(node, ceiling) {
500
538
  */
501
539
  export function findTextIndexOnLine(line, offsetContainer, offset, validate) {
502
540
  if (!line) return 0;
503
- if (!validate) validate = () => true;
541
+ validate ||= () => true;
504
542
 
505
543
  let index = 0;
506
544
  let found = false;
@@ -583,7 +621,7 @@ export function findVisualLastCell(cells) {
583
621
  const colSpan = cell.colSpan || 1;
584
622
 
585
623
  // 현재 행에서 visual column index 찾기
586
- if (!occupied[rowIndex]) occupied[rowIndex] = [];
624
+ occupied[rowIndex] ||= [];
587
625
 
588
626
  let colIndex = 0;
589
627
  const rowOcc = occupied[rowIndex];
@@ -595,7 +633,7 @@ export function findVisualLastCell(cells) {
595
633
 
596
634
  for (let r = 1; r < rowSpan; r++) {
597
635
  const nextRow = rowIndex + r;
598
- if (!occupied[nextRow]) occupied[nextRow] = [];
636
+ occupied[nextRow] ||= [];
599
637
  for (let i = 0; i < colSpan; i++) {
600
638
  occupied[nextRow][colIndex + i] = true;
601
639
  }
@@ -616,26 +654,33 @@ export function findVisualLastCell(cells) {
616
654
  }
617
655
 
618
656
  /**
619
- * @description Get nearest scrollable parent
620
- * @param {Node} element Element
621
- * @returns {HTMLElement|null}
657
+ * @description Finds and returns parent containers that are scrollable.
658
+ * @param {HTMLElement} element - Element to start with
659
+ * @returns {HTMLElement[]} - Array (in descending order)
622
660
  */
623
- export function getScrollParent(element) {
624
- if (!element || /^(body|html)$/i.test(element.nodeName)) {
625
- return null;
626
- }
661
+ export function getScrollParents(element) {
662
+ const scrollable = [];
663
+ let parent = element?.parentElement;
627
664
 
628
- const el = /** @type {HTMLElement} */ (element);
629
- if (el.scrollHeight > el.clientHeight) {
630
- return el;
631
- } else {
632
- return getScrollParent(el.parentNode);
665
+ while (parent && !/^(body|html)$/i.test(parent.nodeName)) {
666
+ const style = _w.getComputedStyle(parent);
667
+ const { overflow, overflowX, overflowY } = style;
668
+
669
+ const canScroll = [overflow, overflowX, overflowY].some((prop) => ['auto', 'scroll', 'overlay'].includes(prop));
670
+
671
+ if (canScroll) {
672
+ scrollable.push(parent);
673
+ }
674
+
675
+ parent = parent.parentElement;
633
676
  }
677
+
678
+ return scrollable;
634
679
  }
635
680
 
636
681
  /**
637
682
  * @description Get the argument iframe's document object if use the "iframe" or "fullPage" options
638
- * @param {HTMLIFrameElement} iframe Iframe element (this.editor.frameContext.get('wysiwygFrame'))
683
+ * @param {HTMLIFrameElement} iframe Iframe element (this.frameContext.get('wysiwygFrame'))
639
684
  * @returns {Document}
640
685
  */
641
686
  export function getIframeDocument(iframe) {
@@ -646,6 +691,7 @@ const query = {
646
691
  getPositionIndex,
647
692
  getNodePath,
648
693
  getNodeFromPath,
694
+ getChildNode,
649
695
  getListChildren,
650
696
  getListChildNodes,
651
697
  getNodeDepth,
@@ -662,7 +708,7 @@ const query = {
662
708
  findTextIndexOnLine,
663
709
  findTabEndIndex,
664
710
  findVisualLastCell,
665
- getScrollParent,
711
+ getScrollParents,
666
712
  getIframeDocument
667
713
  };
668
714
 
@@ -1,6 +1,52 @@
1
1
  import { _d, _w } from '../env';
2
2
  import check from './domCheck';
3
3
 
4
+ // ----- iframe-safe type check [START] -----
5
+ /**
6
+ * @private
7
+ * @description iframe-safe : Node type [HTMLCollection, NodeList, Array] check.
8
+ * @param {*} element
9
+ * @returns {element is HTMLCollection|NodeList|Array}
10
+ */
11
+ function IsElementArray(element) {
12
+ const type = Object.prototype.toString.call(element);
13
+ return type === '[object HTMLCollection]' || type === '[object NodeList]' || type === '[object Array]';
14
+ }
15
+
16
+ /**
17
+ * @private
18
+ * @description iframe-safe: check if element is an HTMLImageElement
19
+ * @param {*} element
20
+ * @returns {element is HTMLImageElement}
21
+ */
22
+ function IsHTMLImageElement(element) {
23
+ const type = Object.prototype.toString.call(element);
24
+ return type === '[object HTMLImageElement]';
25
+ }
26
+
27
+ /**
28
+ * @private
29
+ * @description iframe-safe: check if element is an HTMLMediaElement (video or audio)
30
+ * @param {*} element
31
+ * @returns {element is HTMLMediaElement}
32
+ */
33
+ function IsHTMLMediaElement(element) {
34
+ const type = Object.prototype.toString.call(element);
35
+ return type === '[object HTMLVideoElement]' || type === '[object HTMLAudioElement]';
36
+ }
37
+
38
+ /**
39
+ * @private
40
+ * @description iframe-safe: check if element is an HTMLIFrameElement
41
+ * @param {*} element
42
+ * @returns {element is HTMLIFrameElement}
43
+ */
44
+ function IsHTMLIFrameElement(element) {
45
+ const type = Object.prototype.toString.call(element);
46
+ return type === '[object HTMLIFrameElement]';
47
+ }
48
+ // ----- iframe-safe type check [END] -----
49
+
4
50
  /**
5
51
  * @template {Node} T
6
52
  * @description Clones a node while preserving its type.
@@ -77,11 +123,8 @@ export function getAttributesToString(element, exceptAttrs) {
77
123
  export function arrayFilter(array, validation) {
78
124
  if (!array || array.length === 0) return null;
79
125
 
80
- validation =
81
- validation ||
82
- function () {
83
- return true;
84
- };
126
+ validation ||= () => true;
127
+
85
128
  const arr = [];
86
129
 
87
130
  for (let i = 0, len = array.length, a; i < len; i++) {
@@ -103,11 +146,7 @@ export function arrayFilter(array, validation) {
103
146
  export function arrayFind(array, validation) {
104
147
  if (!array || array.length === 0) return null;
105
148
 
106
- validation =
107
- validation ||
108
- function () {
109
- return true;
110
- };
149
+ validation ||= () => true;
111
150
 
112
151
  for (let i = 0, len = array.length, a; i < len; i++) {
113
152
  a = array[i];
@@ -185,7 +224,7 @@ export function prevIndex(array, item) {
185
224
  export function copyTagAttributes(originEl, copyEl, blacklist) {
186
225
  const o = /** @type {HTMLElement} */ (originEl);
187
226
  const c = /** @type {HTMLElement} */ (copyEl);
188
- if (c.style.cssText) {
227
+ if (c.style.length > 0) {
189
228
  const copyStyles = c.style;
190
229
  for (let i = 0, len = copyStyles.length; i < len; i++) {
191
230
  o.style[copyStyles[i]] = copyStyles[copyStyles[i]];
@@ -264,21 +303,35 @@ export function setStyle(elements, styleName, value) {
264
303
  for (let i = 0, len = elements.length, e; i < len; i++) {
265
304
  e = /** @type {HTMLElement} */ (elements[i]);
266
305
  e.style[styleName] = value;
267
- if (!value && !e.style.cssText) {
306
+ if (e.style.length === 0) {
268
307
  e.removeAttribute('style');
269
308
  }
270
309
  }
271
310
  }
272
311
 
312
+ /**
313
+ * @description Gets the style value of the element. If the elements is an array, the style of the first element is returned.
314
+ * @param {Node} element Element to get style from.
315
+ * @param {string} styleName Style attribute name (e.g., 'marginLeft', 'textAlign').
316
+ * @returns {string | undefined} The value of the style attribute, or undefined if the element does not exist.
317
+ */
318
+ export function getStyle(element, styleName) {
319
+ if (element?.nodeType !== 1) {
320
+ return undefined;
321
+ }
322
+
323
+ return /** @type {HTMLElement} */ (element).style[styleName];
324
+ }
325
+
273
326
  /**
274
327
  * @description In the predefined code view mode, the buttons except the executable button are changed to the 'disabled' state.
275
- * @param {Array<HTMLButtonElement|HTMLInputElement>} buttonList (Button | Input) Element array
328
+ * @param {__se__NodeCollection} buttonList (Button | Input) Element array
276
329
  * @param {boolean} disabled Disabled value
277
330
  * @param {boolean} [important=false] If priveleged mode should be used (Necessary to switch importantDisabled buttons)
278
331
  */
279
332
  export function setDisabled(buttonList, disabled, important) {
280
333
  for (let i = 0, len = buttonList.length; i < len; i++) {
281
- const button = buttonList[i];
334
+ const button = /** @type {HTMLButtonElement|HTMLInputElement} */ (buttonList[i]);
282
335
  if (important || !check.isImportantDisabled(button)) button.disabled = disabled;
283
336
  if (important) {
284
337
  if (disabled) {
@@ -310,7 +363,7 @@ export function hasClass(element, className) {
310
363
  export function addClass(element, className) {
311
364
  if (!element) return;
312
365
 
313
- const elements = element instanceof HTMLCollection || element instanceof NodeList || element instanceof Array ? element : [element];
366
+ const elements = IsElementArray(element) ? element : [element];
314
367
  const classNames = className.split('|');
315
368
 
316
369
  for (let i = 0, len = elements.length; i < len; i++) {
@@ -330,7 +383,7 @@ export function addClass(element, className) {
330
383
  export function removeClass(element, className) {
331
384
  if (!element) return;
332
385
 
333
- const elements = element instanceof HTMLCollection || element instanceof NodeList || element instanceof Array ? element : [element];
386
+ const elements = IsElementArray(element) ? element : [element];
334
387
  const classNames = className.split('|');
335
388
 
336
389
  for (let i = 0, len = elements.length; i < len; i++) {
@@ -480,19 +533,19 @@ export function waitForMediaLoad(target, timeout = 5000) {
480
533
 
481
534
  const mediaPromises = mediaElements.map((element) => {
482
535
  // image
483
- if (element instanceof HTMLImageElement) {
536
+ if (IsHTMLImageElement(element)) {
484
537
  if (element.complete) {
485
538
  return Promise.resolve();
486
539
  }
487
540
  }
488
541
  // video, audio
489
- else if (element instanceof HTMLMediaElement) {
542
+ else if (IsHTMLMediaElement(element)) {
490
543
  if (element.readyState >= 2) {
491
544
  return Promise.resolve();
492
545
  }
493
546
  }
494
547
  // iframe
495
- else if (element instanceof HTMLIFrameElement) {
548
+ else if (IsHTMLIFrameElement(element)) {
496
549
  try {
497
550
  if (element.contentDocument?.readyState === 'complete') {
498
551
  return Promise.resolve();
@@ -515,6 +568,24 @@ export function waitForMediaLoad(target, timeout = 5000) {
515
568
  });
516
569
  }
517
570
 
571
+ /**
572
+ * @description Gets a CSS variable on the root element of the editor.
573
+ * @param {string} name - The CSS variable name (e.g. `--se-color-primary`)
574
+ * @return {string} The value of the CSS variable
575
+ */
576
+ export function getRootCssVar(name) {
577
+ return _d.documentElement.style.getPropertyValue(name);
578
+ }
579
+
580
+ /**
581
+ * @description Sets a CSS variable on the root element of the editor.
582
+ * @param {string} name - The CSS variable name (e.g. `--se-color-primary`)
583
+ * @param {string} value - The CSS variable value
584
+ */
585
+ export function setRootCssVar(name, value) {
586
+ _d.documentElement.style.setProperty(name, value);
587
+ }
588
+
518
589
  /**
519
590
  * @description Create tooltip HTML
520
591
  * @param {string} text Tooltip text
@@ -541,6 +612,7 @@ const utils = {
541
612
  changeElement,
542
613
  changeTxt,
543
614
  setStyle,
615
+ getStyle,
544
616
  setDisabled,
545
617
  hasClass,
546
618
  addClass,
@@ -551,6 +623,8 @@ const utils = {
551
623
  getViewportSize,
552
624
  applyInlineStylesAll,
553
625
  waitForMediaLoad,
626
+ getRootCssVar,
627
+ setRootCssVar,
554
628
  createTooltipInner
555
629
  };
556
630
 
@@ -9,4 +9,8 @@ const dom = {
9
9
  utils
10
10
  };
11
11
 
12
+ export const domQuery = query;
13
+ export const domCheck = check;
14
+ export const domUtils = utils;
15
+
12
16
  export default dom;
package/src/helper/env.js CHANGED
@@ -40,13 +40,11 @@ export function getPageStyle(doc) {
40
40
  const sheets = (doc || _d).styleSheets;
41
41
 
42
42
  for (let i = 0, len = sheets.length, rules; i < len; i++) {
43
- /* eslint-disable @typescript-eslint/no-unused-vars */
44
43
  try {
45
44
  rules = sheets[i].cssRules;
46
- } catch (e) {
45
+ } catch {
47
46
  continue;
48
47
  }
49
- /* eslint-disable @typescript-eslint/no-unused-vars */
50
48
 
51
49
  if (rules) {
52
50
  for (let c = 0, cLen = rules.length; c < cLen; c++) {
@@ -120,7 +118,6 @@ export const isResizeObserverSupported = (() => {
120
118
  * @returns {boolean} Whether support navigator.clipboard or not.
121
119
  */
122
120
  export const isClipboardSupported = (() => {
123
- /* eslint-disable-next-line compat/compat */
124
121
  return typeof navigator.clipboard?.write === 'function';
125
122
  })();
126
123
 
@@ -174,12 +171,18 @@ export const isSafari = (() => {
174
171
 
175
172
  /**
176
173
  * @description Check if User Agent is Mobile device.
177
- * - when the device is touchable, it is judged as a mobile device.
178
174
  * @type {boolean}
179
175
  */
180
176
  export const isMobile = (() => {
181
- /* eslint-disable-next-line compat/compat */
182
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent) || (navigator.maxTouchPoints > 0 && 'ontouchstart' in _w);
177
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
178
+ })();
179
+
180
+ /**
181
+ * @description Check if the device is touchable.
182
+ * @type {boolean}
183
+ */
184
+ export const isTouchDevice = (() => {
185
+ return navigator.maxTouchPoints > 0 && 'ontouchstart' in _w;
183
186
  })();
184
187
 
185
188
  /**
@@ -230,6 +233,7 @@ const env = {
230
233
  isOSX_IOS,
231
234
  isAndroid,
232
235
  isMobile,
236
+ isTouchDevice,
233
237
  cmdIcon,
234
238
  shiftIcon,
235
239
  DPI,
@@ -48,12 +48,13 @@ export function isAlt(e) {
48
48
  }
49
49
 
50
50
  /**
51
- * @description event.isComposing check
52
- * @param {KeyboardEvent} e Event object
51
+ * @description Check if the event is related to IME composition (in-progress or commit).
52
+ * @param {KeyboardEvent|InputEvent} e Event object
53
53
  * @returns {boolean}
54
54
  */
55
55
  export function isComposing(e) {
56
- return e.isComposing || e.keyCode === 229;
56
+ // @ts-ignore
57
+ return e.isComposing || e.key === 'Process' || e.keyCode === 229;
57
58
  }
58
59
 
59
60
  /**
package/src/langs/ckb.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/cs.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/da.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/de.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/en.js CHANGED
@@ -8,7 +8,7 @@
8
8
  throw new Error('SUNEDITOR_LANG a window with a document');
9
9
  }
10
10
  return factory(w);
11
- };
11
+ };
12
12
  } else {
13
13
  factory(global);
14
14
  }
package/src/langs/es.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/fa.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/fr.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/he.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/hu.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG requires a window with a document');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/it.js CHANGED
@@ -9,7 +9,7 @@
9
9
  throw new Error('SUNEDITOR_LANG una finestra con un documento');
10
10
  }
11
11
  return factory(w);
12
- };
12
+ };
13
13
  } else {
14
14
  factory(global);
15
15
  }
package/src/langs/ja.js CHANGED
@@ -8,7 +8,7 @@
8
8
  throw new Error('SUNEDITOR_LANG a window with a document');
9
9
  }
10
10
  return factory(w);
11
- };
11
+ };
12
12
  } else {
13
13
  factory(global);
14
14
  }
package/src/langs/km.js CHANGED
@@ -8,7 +8,7 @@
8
8
  throw new Error('SUNEDITOR_LANG a window with a document');
9
9
  }
10
10
  return factory(w);
11
- };
11
+ };
12
12
  } else {
13
13
  factory(global);
14
14
  }