suneditor 3.0.0-alpha.9 → 3.0.0-beta.2

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 (315) hide show
  1. package/CONTRIBUTING.md +170 -22
  2. package/{LICENSE.txt → LICENSE} +9 -9
  3. package/README.md +168 -30
  4. package/dist/suneditor.min.css +1 -1
  5. package/dist/suneditor.min.js +1 -1
  6. package/package.json +47 -21
  7. package/src/assets/design/color.css +121 -0
  8. package/src/assets/design/index.css +3 -0
  9. package/src/assets/design/size.css +35 -0
  10. package/src/assets/design/typography.css +37 -0
  11. package/src/assets/icons/defaultIcons.js +232 -0
  12. package/src/assets/suneditor-contents.css +181 -46
  13. package/src/assets/suneditor.css +1403 -650
  14. package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
  15. package/src/core/base/eventHandlers/handler_ww_clipboard.js +23 -4
  16. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +49 -10
  17. package/src/core/base/eventHandlers/handler_ww_key_input.js +422 -224
  18. package/src/core/base/eventHandlers/handler_ww_mouse.js +83 -36
  19. package/src/core/base/eventManager.js +520 -179
  20. package/src/core/base/history.js +95 -41
  21. package/src/core/class/char.js +26 -11
  22. package/src/core/class/component.js +345 -137
  23. package/src/core/class/format.js +683 -519
  24. package/src/core/class/html.js +485 -305
  25. package/src/core/class/menu.js +133 -47
  26. package/src/core/class/nodeTransform.js +90 -71
  27. package/src/core/class/offset.js +408 -92
  28. package/src/core/class/selection.js +216 -106
  29. package/src/core/class/shortcuts.js +68 -8
  30. package/src/core/class/toolbar.js +106 -116
  31. package/src/core/class/ui.js +422 -0
  32. package/src/core/class/viewer.js +178 -74
  33. package/src/core/editor.js +496 -389
  34. package/src/core/section/actives.js +123 -27
  35. package/src/core/section/constructor.js +615 -206
  36. package/src/core/section/context.js +28 -23
  37. package/src/core/section/documentType.js +561 -0
  38. package/src/editorInjector/_classes.js +19 -5
  39. package/src/editorInjector/_core.js +71 -7
  40. package/src/editorInjector/index.js +63 -1
  41. package/src/events.js +622 -0
  42. package/src/helper/clipboard.js +59 -0
  43. package/src/helper/converter.js +202 -26
  44. package/src/helper/dom/domCheck.js +304 -0
  45. package/src/helper/dom/domQuery.js +669 -0
  46. package/src/helper/dom/domUtils.js +557 -0
  47. package/src/helper/dom/index.js +12 -0
  48. package/src/helper/env.js +46 -56
  49. package/src/helper/index.js +10 -4
  50. package/src/helper/keyCodeMap.js +183 -0
  51. package/src/helper/numbers.js +12 -8
  52. package/src/helper/unicode.js +9 -5
  53. package/src/langs/ckb.js +74 -4
  54. package/src/langs/cs.js +72 -2
  55. package/src/langs/da.js +73 -3
  56. package/src/langs/de.js +73 -4
  57. package/src/langs/en.js +23 -3
  58. package/src/langs/es.js +73 -4
  59. package/src/langs/fa.js +75 -3
  60. package/src/langs/fr.js +73 -3
  61. package/src/langs/he.js +73 -4
  62. package/src/langs/hu.js +230 -0
  63. package/src/langs/index.js +7 -3
  64. package/src/langs/it.js +70 -1
  65. package/src/langs/ja.js +72 -4
  66. package/src/langs/km.js +230 -0
  67. package/src/langs/ko.js +22 -2
  68. package/src/langs/lv.js +74 -5
  69. package/src/langs/nl.js +73 -4
  70. package/src/langs/pl.js +73 -4
  71. package/src/langs/pt_br.js +70 -1
  72. package/src/langs/ro.js +74 -5
  73. package/src/langs/ru.js +73 -4
  74. package/src/langs/se.js +73 -4
  75. package/src/langs/tr.js +73 -1
  76. package/src/langs/{ua.js → uk.js} +75 -6
  77. package/src/langs/ur.js +77 -8
  78. package/src/langs/zh_cn.js +74 -5
  79. package/src/modules/ApiManager.js +77 -54
  80. package/src/modules/Browser.js +667 -0
  81. package/src/modules/ColorPicker.js +162 -102
  82. package/src/modules/Controller.js +273 -142
  83. package/src/modules/Figure.js +925 -484
  84. package/src/modules/FileManager.js +121 -69
  85. package/src/modules/HueSlider.js +113 -61
  86. package/src/modules/Modal.js +291 -122
  87. package/src/modules/ModalAnchorEditor.js +383 -234
  88. package/src/modules/SelectMenu.js +270 -168
  89. package/src/modules/_DragHandle.js +2 -1
  90. package/src/modules/index.js +3 -3
  91. package/src/plugins/browser/audioGallery.js +83 -0
  92. package/src/plugins/browser/fileBrowser.js +103 -0
  93. package/src/plugins/browser/fileGallery.js +83 -0
  94. package/src/plugins/browser/imageGallery.js +81 -0
  95. package/src/plugins/browser/videoGallery.js +103 -0
  96. package/src/plugins/command/blockquote.js +40 -27
  97. package/src/plugins/command/exportPDF.js +134 -0
  98. package/src/plugins/command/fileUpload.js +229 -162
  99. package/src/plugins/command/list_bulleted.js +83 -47
  100. package/src/plugins/command/list_numbered.js +83 -47
  101. package/src/plugins/dropdown/align.js +66 -54
  102. package/src/plugins/dropdown/backgroundColor.js +63 -49
  103. package/src/plugins/dropdown/font.js +71 -47
  104. package/src/plugins/dropdown/fontColor.js +63 -48
  105. package/src/plugins/dropdown/formatBlock.js +70 -33
  106. package/src/plugins/dropdown/hr.js +92 -51
  107. package/src/plugins/dropdown/layout.js +37 -26
  108. package/src/plugins/dropdown/lineHeight.js +54 -38
  109. package/src/plugins/dropdown/list.js +60 -45
  110. package/src/plugins/dropdown/paragraphStyle.js +51 -30
  111. package/src/plugins/dropdown/table.js +2003 -813
  112. package/src/plugins/dropdown/template.js +38 -26
  113. package/src/plugins/dropdown/textStyle.js +43 -31
  114. package/src/plugins/field/mention.js +147 -86
  115. package/src/plugins/index.js +32 -6
  116. package/src/plugins/input/fontSize.js +161 -108
  117. package/src/plugins/input/pageNavigator.js +70 -0
  118. package/src/plugins/modal/audio.js +358 -173
  119. package/src/plugins/modal/drawing.js +531 -0
  120. package/src/plugins/modal/embed.js +886 -0
  121. package/src/plugins/modal/image.js +674 -362
  122. package/src/plugins/modal/link.js +100 -71
  123. package/src/plugins/modal/math.js +367 -167
  124. package/src/plugins/modal/video.js +691 -335
  125. package/src/plugins/popup/anchor.js +222 -0
  126. package/src/suneditor.js +50 -13
  127. package/src/themes/dark.css +122 -0
  128. package/src/typedef.js +130 -0
  129. package/types/assets/icons/defaultIcons.d.ts +153 -0
  130. package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
  131. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
  132. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
  133. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
  134. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
  135. package/types/core/base/eventManager.d.ts +385 -0
  136. package/types/core/base/history.d.ts +81 -0
  137. package/types/core/class/char.d.ts +60 -0
  138. package/types/core/class/component.d.ts +212 -0
  139. package/types/core/class/format.d.ts +616 -0
  140. package/types/core/class/html.d.ts +422 -0
  141. package/types/core/class/menu.d.ts +126 -0
  142. package/types/core/class/nodeTransform.d.ts +93 -0
  143. package/types/core/class/offset.d.ts +522 -0
  144. package/types/core/class/selection.d.ts +188 -0
  145. package/types/core/class/shortcuts.d.ts +142 -0
  146. package/types/core/class/toolbar.d.ts +189 -0
  147. package/types/core/class/ui.d.ts +164 -0
  148. package/types/core/class/viewer.d.ts +140 -0
  149. package/types/core/editor.d.ts +610 -0
  150. package/types/core/section/actives.d.ts +46 -0
  151. package/types/core/section/constructor.d.ts +777 -0
  152. package/types/core/section/context.d.ts +45 -0
  153. package/types/core/section/documentType.d.ts +178 -0
  154. package/types/editorInjector/_classes.d.ts +41 -0
  155. package/types/editorInjector/_core.d.ts +92 -0
  156. package/types/editorInjector/index.d.ts +71 -0
  157. package/types/events.d.ts +273 -0
  158. package/types/helper/clipboard.d.ts +12 -0
  159. package/types/helper/converter.d.ts +197 -0
  160. package/types/helper/dom/domCheck.d.ts +189 -0
  161. package/types/helper/dom/domQuery.d.ts +223 -0
  162. package/types/helper/dom/domUtils.d.ts +226 -0
  163. package/types/helper/dom/index.d.ts +9 -0
  164. package/types/helper/env.d.ts +132 -0
  165. package/types/helper/index.d.ts +174 -0
  166. package/types/helper/keyCodeMap.d.ts +110 -0
  167. package/types/helper/numbers.d.ts +46 -0
  168. package/types/helper/unicode.d.ts +28 -0
  169. package/types/index.d.ts +120 -0
  170. package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +173 -103
  171. package/types/langs/ckb.d.ts +3 -0
  172. package/types/langs/cs.d.ts +3 -0
  173. package/types/langs/da.d.ts +3 -0
  174. package/types/langs/de.d.ts +3 -0
  175. package/types/langs/en.d.ts +3 -0
  176. package/types/langs/es.d.ts +3 -0
  177. package/types/langs/fa.d.ts +3 -0
  178. package/types/langs/fr.d.ts +3 -0
  179. package/types/langs/he.d.ts +3 -0
  180. package/types/langs/hu.d.ts +3 -0
  181. package/types/langs/index.d.ts +54 -0
  182. package/types/langs/it.d.ts +3 -0
  183. package/types/langs/ja.d.ts +3 -0
  184. package/types/langs/km.d.ts +3 -0
  185. package/types/langs/ko.d.ts +3 -0
  186. package/types/langs/lv.d.ts +3 -0
  187. package/types/langs/nl.d.ts +3 -0
  188. package/types/langs/pl.d.ts +3 -0
  189. package/types/langs/pt_br.d.ts +3 -0
  190. package/types/langs/ro.d.ts +3 -0
  191. package/types/langs/ru.d.ts +3 -0
  192. package/types/langs/se.d.ts +3 -0
  193. package/types/langs/tr.d.ts +3 -0
  194. package/types/langs/uk.d.ts +3 -0
  195. package/types/langs/ur.d.ts +3 -0
  196. package/types/langs/zh_cn.d.ts +3 -0
  197. package/types/modules/ApiManager.d.ts +125 -0
  198. package/types/modules/Browser.d.ts +326 -0
  199. package/types/modules/ColorPicker.d.ts +131 -0
  200. package/types/modules/Controller.d.ts +251 -0
  201. package/types/modules/Figure.d.ts +517 -0
  202. package/types/modules/FileManager.d.ts +202 -0
  203. package/types/modules/HueSlider.d.ts +136 -0
  204. package/types/modules/Modal.d.ts +111 -0
  205. package/types/modules/ModalAnchorEditor.d.ts +236 -0
  206. package/types/modules/SelectMenu.d.ts +194 -0
  207. package/types/modules/_DragHandle.d.ts +7 -0
  208. package/types/modules/index.d.ts +26 -0
  209. package/types/plugins/browser/audioGallery.d.ts +55 -0
  210. package/types/plugins/browser/fileBrowser.d.ts +64 -0
  211. package/types/plugins/browser/fileGallery.d.ts +55 -0
  212. package/types/plugins/browser/imageGallery.d.ts +51 -0
  213. package/types/plugins/browser/videoGallery.d.ts +57 -0
  214. package/types/plugins/command/blockquote.d.ts +28 -0
  215. package/types/plugins/command/exportPDF.d.ts +46 -0
  216. package/types/plugins/command/fileUpload.d.ts +156 -0
  217. package/types/plugins/command/list_bulleted.d.ts +46 -0
  218. package/types/plugins/command/list_numbered.d.ts +46 -0
  219. package/types/plugins/dropdown/align.d.ts +60 -0
  220. package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
  221. package/types/plugins/dropdown/font.d.ts +54 -0
  222. package/types/plugins/dropdown/fontColor.d.ts +63 -0
  223. package/types/plugins/dropdown/formatBlock.d.ts +54 -0
  224. package/types/plugins/dropdown/hr.d.ts +71 -0
  225. package/types/plugins/dropdown/layout.d.ts +40 -0
  226. package/types/plugins/dropdown/lineHeight.d.ts +50 -0
  227. package/types/plugins/dropdown/list.d.ts +39 -0
  228. package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
  229. package/types/plugins/dropdown/table.d.ts +627 -0
  230. package/types/plugins/dropdown/template.d.ts +40 -0
  231. package/types/plugins/dropdown/textStyle.d.ts +41 -0
  232. package/types/plugins/field/mention.d.ts +102 -0
  233. package/types/plugins/index.d.ts +107 -0
  234. package/types/plugins/input/fontSize.d.ts +170 -0
  235. package/types/plugins/input/pageNavigator.d.ts +28 -0
  236. package/types/plugins/modal/audio.d.ts +269 -0
  237. package/types/plugins/modal/drawing.d.ts +246 -0
  238. package/types/plugins/modal/embed.d.ts +387 -0
  239. package/types/plugins/modal/image.d.ts +451 -0
  240. package/types/plugins/modal/link.d.ts +128 -0
  241. package/types/plugins/modal/math.d.ts +193 -0
  242. package/types/plugins/modal/video.d.ts +485 -0
  243. package/types/plugins/popup/anchor.d.ts +56 -0
  244. package/types/suneditor.d.ts +51 -0
  245. package/types/typedef.d.ts +233 -0
  246. package/.eslintignore +0 -7
  247. package/.eslintrc.json +0 -64
  248. package/src/assets/icons/_default.js +0 -194
  249. package/src/core/base/events.js +0 -320
  250. package/src/core/class/notice.js +0 -42
  251. package/src/helper/domUtils.js +0 -1177
  252. package/src/modules/FileBrowser.js +0 -271
  253. package/src/plugins/command/exportPdf.js +0 -168
  254. package/src/plugins/fileBrowser/imageGallery.js +0 -81
  255. package/src/themes/test.css +0 -61
  256. package/typings/CommandPlugin.d.ts +0 -8
  257. package/typings/DialogPlugin.d.ts +0 -20
  258. package/typings/FileBrowserPlugin.d.ts +0 -30
  259. package/typings/Module.d.ts +0 -15
  260. package/typings/Plugin.d.ts +0 -42
  261. package/typings/SubmenuPlugin.d.ts +0 -8
  262. package/typings/_classes.d.ts +0 -17
  263. package/typings/_colorPicker.d.ts +0 -60
  264. package/typings/_core.d.ts +0 -55
  265. package/typings/align.d.ts +0 -5
  266. package/typings/audio.d.ts +0 -5
  267. package/typings/backgroundColor.d.ts +0 -5
  268. package/typings/blockquote.d.ts +0 -5
  269. package/typings/char.d.ts +0 -39
  270. package/typings/component.d.ts +0 -38
  271. package/typings/context.d.ts +0 -39
  272. package/typings/converter.d.ts +0 -33
  273. package/typings/dialog.d.ts +0 -28
  274. package/typings/domUtils.d.ts +0 -361
  275. package/typings/editor.d.ts +0 -7
  276. package/typings/editor.ts +0 -542
  277. package/typings/env.d.ts +0 -70
  278. package/typings/eventManager.d.ts +0 -37
  279. package/typings/events.d.ts +0 -262
  280. package/typings/fileBrowser.d.ts +0 -42
  281. package/typings/fileManager.d.ts +0 -67
  282. package/typings/font.d.ts +0 -5
  283. package/typings/fontColor.d.ts +0 -5
  284. package/typings/fontSize.d.ts +0 -5
  285. package/typings/format.d.ts +0 -191
  286. package/typings/formatBlock.d.ts +0 -5
  287. package/typings/history.d.ts +0 -48
  288. package/typings/horizontalRule.d.ts +0 -5
  289. package/typings/image.d.ts +0 -5
  290. package/typings/imageGallery.d.ts +0 -5
  291. package/typings/index.d.ts +0 -21
  292. package/typings/index.modules.d.ts +0 -11
  293. package/typings/index.plugins.d.ts +0 -58
  294. package/typings/lineHeight.d.ts +0 -5
  295. package/typings/link.d.ts +0 -5
  296. package/typings/list.d.ts +0 -5
  297. package/typings/math.d.ts +0 -5
  298. package/typings/mediaContainer.d.ts +0 -25
  299. package/typings/mention.d.ts +0 -5
  300. package/typings/node.d.ts +0 -57
  301. package/typings/notice.d.ts +0 -16
  302. package/typings/numbers.d.ts +0 -29
  303. package/typings/offset.d.ts +0 -24
  304. package/typings/options.d.ts +0 -589
  305. package/typings/paragraphStyle.d.ts +0 -5
  306. package/typings/resizing.d.ts +0 -141
  307. package/typings/selection.d.ts +0 -94
  308. package/typings/shortcuts.d.ts +0 -13
  309. package/typings/suneditor.d.ts +0 -9
  310. package/typings/table.d.ts +0 -5
  311. package/typings/template.d.ts +0 -5
  312. package/typings/textStyle.d.ts +0 -5
  313. package/typings/toolbar.d.ts +0 -32
  314. package/typings/unicode.d.ts +0 -25
  315. package/typings/video.d.ts +0 -5
@@ -0,0 +1,557 @@
1
+ import { _d, _w } from '../env';
2
+ import check from './domCheck';
3
+
4
+ /**
5
+ * @template {Node} T
6
+ * @description Clones a node while preserving its type.
7
+ * @param {T} node - The node to clone.
8
+ * @param {boolean} [deep=false] - Whether to perform a deep clone.
9
+ * @returns {T} - The cloned node.
10
+ */
11
+ export function clone(node, deep = false) {
12
+ return /** @type {T} */ (node.cloneNode(deep));
13
+ }
14
+
15
+ /**
16
+ * @template {HTMLElement} T
17
+ * @description Create Element node
18
+ * @param {string} elementName Element name
19
+ * @param {?Object<string, string>=} attributes The attributes of the tag. {style: 'font-size:12px;..', class: 'el_class',..}
20
+ * @param {?string|Node=} inner A innerHTML string or inner node.
21
+ * @returns {T}
22
+ */
23
+ export function createElement(elementName, attributes, inner) {
24
+ const el = _d.createElement(elementName);
25
+
26
+ if (attributes) {
27
+ for (const key in attributes) {
28
+ if (attributes[key] !== undefined && attributes[key] !== null) el.setAttribute(key, attributes[key]);
29
+ }
30
+ }
31
+
32
+ if (inner) {
33
+ if (typeof inner === 'string') {
34
+ el.innerHTML = inner;
35
+ } else if (typeof inner === 'object') {
36
+ el.appendChild(inner);
37
+ }
38
+ }
39
+
40
+ return /** @type {T} */ (el);
41
+ }
42
+
43
+ /**
44
+ * @description Create text node
45
+ * @param {string} text text content
46
+ * @returns {Text}
47
+ */
48
+ export function createTextNode(text) {
49
+ return _d.createTextNode(text || '');
50
+ }
51
+
52
+ /**
53
+ * @description Get attributes of argument element to string ('class="---" name="---" ')
54
+ * @param {Node} element Element object
55
+ * @param {Array<string>|null} exceptAttrs Array of attribute names to exclude from the result
56
+ * @returns {string}
57
+ */
58
+ export function getAttributesToString(element, exceptAttrs) {
59
+ const attrs = /** @type {HTMLElement} */ (element).attributes;
60
+ if (!attrs) return '';
61
+
62
+ let attrString = '';
63
+ for (let i = 0, len = attrs.length; i < len; i++) {
64
+ if (exceptAttrs?.includes(attrs[i].name)) continue;
65
+ attrString += attrs[i].name + '="' + attrs[i].value + '" ';
66
+ }
67
+
68
+ return attrString;
69
+ }
70
+
71
+ /**
72
+ * @description Get the items array from the array that matches the condition.
73
+ * @param {__se__NodeCollection} array Array to get item
74
+ * @param {?(current: *) => boolean} validation Conditional function
75
+ * @returns {Array<Node>|null}
76
+ */
77
+ export function arrayFilter(array, validation) {
78
+ if (!array || array.length === 0) return null;
79
+
80
+ validation =
81
+ validation ||
82
+ function () {
83
+ return true;
84
+ };
85
+ const arr = [];
86
+
87
+ for (let i = 0, len = array.length, a; i < len; i++) {
88
+ a = array[i];
89
+ if (validation(a)) {
90
+ arr.push(a);
91
+ }
92
+ }
93
+
94
+ return arr;
95
+ }
96
+
97
+ /**
98
+ * @description Get the item from the array that matches the condition.
99
+ * @param {__se__NodeCollection} array Array to get item
100
+ * @param {?(current: *) => boolean} validation Conditional function
101
+ * @returns {Node|null}
102
+ */
103
+ export function arrayFind(array, validation) {
104
+ if (!array || array.length === 0) return null;
105
+
106
+ validation =
107
+ validation ||
108
+ function () {
109
+ return true;
110
+ };
111
+
112
+ for (let i = 0, len = array.length, a; i < len; i++) {
113
+ a = array[i];
114
+ if (validation(a)) {
115
+ return a;
116
+ }
117
+ }
118
+
119
+ return null;
120
+ }
121
+
122
+ /**
123
+ * @description Check if an array contains an element
124
+ * @param {__se__NodeCollection} array element array
125
+ * @param {Node} node The node to check for
126
+ * @returns {boolean}
127
+ */
128
+ export function arrayIncludes(array, node) {
129
+ for (let i = 0; i < array.length; i++) {
130
+ if (array[i] === node) {
131
+ return true;
132
+ }
133
+ }
134
+ return false;
135
+ }
136
+
137
+ /**
138
+ * @description Get the index of the argument value in the element array
139
+ * @param {__se__NodeCollection} array element array
140
+ * @param {Node} node The element to find index
141
+ * @returns {number}
142
+ */
143
+ export function getArrayIndex(array, node) {
144
+ let idx = -1;
145
+ for (let i = 0, len = array.length; i < len; i++) {
146
+ if (array[i] === node) {
147
+ idx = i;
148
+ break;
149
+ }
150
+ }
151
+
152
+ return idx;
153
+ }
154
+
155
+ /**
156
+ * @description Get the next index of the argument value in the element array
157
+ * @param {__se__NodeCollection} array element array
158
+ * @param {Node} item The element to find index
159
+ * @returns {number}
160
+ */
161
+ export function nextIndex(array, item) {
162
+ const idx = getArrayIndex(array, item);
163
+ if (idx === -1) return -1;
164
+ return idx + 1;
165
+ }
166
+
167
+ /**
168
+ * @description Get the previous index of the argument value in the element array
169
+ * @param {__se__NodeCollection} array Element array
170
+ * @param {Node} item The element to find index
171
+ * @returns {number}
172
+ */
173
+ export function prevIndex(array, item) {
174
+ const idx = getArrayIndex(array, item);
175
+ if (idx === -1) return -1;
176
+ return idx - 1;
177
+ }
178
+
179
+ /**
180
+ * @description Add style and className of copyEl to originEl
181
+ * @param {Node} originEl Origin element
182
+ * @param {Node} copyEl Element to copy
183
+ * @param {?Array<string>=} blacklist Blacklist array(LowerCase)
184
+ */
185
+ export function copyTagAttributes(originEl, copyEl, blacklist) {
186
+ const o = /** @type {HTMLElement} */ (originEl);
187
+ const c = /** @type {HTMLElement} */ (copyEl);
188
+ if (c.style.cssText) {
189
+ const copyStyles = c.style;
190
+ for (let i = 0, len = copyStyles.length; i < len; i++) {
191
+ o.style[copyStyles[i]] = copyStyles[copyStyles[i]];
192
+ }
193
+ }
194
+
195
+ const attrs = c.attributes;
196
+ for (let i = 0, len = attrs.length, name; i < len; i++) {
197
+ name = attrs[i].name.toLowerCase();
198
+ if (blacklist?.includes(name) || !attrs[i].value) o.removeAttribute(name);
199
+ else if (name !== 'style') o.setAttribute(attrs[i].name, attrs[i].value);
200
+ }
201
+ }
202
+
203
+ /**
204
+ * @description Copy and apply attributes of format tag that should be maintained. (style, class) Ignore "__se__format__" class
205
+ * @param {Node} originEl Origin element
206
+ * @param {Node} copyEl Element to copy
207
+ */
208
+ export function copyFormatAttributes(originEl, copyEl) {
209
+ const c = /** @type {HTMLElement} */ (copyEl.cloneNode(false));
210
+ c.className = c.className.replace(/(\s|^)__se__format__[^\s]+/g, '');
211
+ copyTagAttributes(originEl, c);
212
+ }
213
+
214
+ /**
215
+ * @description Delete argumenu value element
216
+ * @param {Node} item Node to be remove
217
+ */
218
+ export function removeItem(item) {
219
+ if (!item) return;
220
+ if ('remove' in item && typeof item.remove === 'function') item.remove();
221
+ else if (item.parentNode) item.parentNode.removeChild(item);
222
+ }
223
+
224
+ /**
225
+ * @description Replace element
226
+ * @param {Node} element Target element
227
+ * @param {string|Node} newElement String or element of the new element to apply
228
+ */
229
+ export function changeElement(element, newElement) {
230
+ if (!element) return;
231
+
232
+ if (typeof newElement === 'string') {
233
+ if ('outerHTML' in element) {
234
+ element.outerHTML = newElement;
235
+ } else {
236
+ const doc = createElement('DIV');
237
+ doc.innerHTML = newElement;
238
+ element.parentNode.replaceChild(doc.firstChild, element);
239
+ }
240
+ } else if (newElement?.nodeType === 1) {
241
+ element.parentNode.replaceChild(newElement, element);
242
+ }
243
+ }
244
+
245
+ /**
246
+ * @description Set the text content value of the argument value element
247
+ * @param {Node} node Element to replace text content
248
+ * @param {string} txt Text to be applied
249
+ */
250
+ export function changeTxt(node, txt) {
251
+ if (!node || !txt) return;
252
+ node.textContent = txt;
253
+ }
254
+
255
+ /**
256
+ * @description Set style, if all styles are deleted, the style properties are deleted.
257
+ * @param {Node|Node[]} elements Element to set style
258
+ * @param {string} styleName Style attribute name (marginLeft, textAlign...)
259
+ * @param {string|number} value Style value
260
+ */
261
+ export function setStyle(elements, styleName, value) {
262
+ elements = Array.isArray(elements) ? elements : [elements];
263
+
264
+ for (let i = 0, len = elements.length, e; i < len; i++) {
265
+ e = /** @type {HTMLElement} */ (elements[i]);
266
+ e.style[styleName] = value;
267
+ if (!value && !e.style.cssText) {
268
+ e.removeAttribute('style');
269
+ }
270
+ }
271
+ }
272
+
273
+ /**
274
+ * @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
276
+ * @param {boolean} disabled Disabled value
277
+ * @param {boolean} [important=false] If priveleged mode should be used (Necessary to switch importantDisabled buttons)
278
+ */
279
+ export function setDisabled(buttonList, disabled, important) {
280
+ for (let i = 0, len = buttonList.length; i < len; i++) {
281
+ const button = buttonList[i];
282
+ if (important || !check.isImportantDisabled(button)) button.disabled = disabled;
283
+ if (important) {
284
+ if (disabled) {
285
+ button.setAttribute('data-important-disabled', '');
286
+ } else {
287
+ button.removeAttribute('data-important-disabled');
288
+ }
289
+ }
290
+ }
291
+ }
292
+
293
+ /**
294
+ * @description Determine whether any of the matched elements are assigned the given class
295
+ * @param {?Node} element Elements to search class name
296
+ * @param {string} className Class name to search for
297
+ * @returns {boolean}
298
+ */
299
+ export function hasClass(element, className) {
300
+ if (!element || element.nodeType !== 1) return;
301
+ const valid = new RegExp(`(\\s|^)${className}(\\s|$)`);
302
+ return valid.test(/** @type {HTMLElement} */ (element).className);
303
+ }
304
+
305
+ /**
306
+ * @description Append the className value of the argument value element
307
+ * @param {Node|__se__NodeCollection} element Elements to add class name
308
+ * @param {string} className Class name to be add
309
+ */
310
+ export function addClass(element, className) {
311
+ if (!element) return;
312
+
313
+ const elements = element instanceof HTMLCollection || element instanceof NodeList || element instanceof Array ? element : [element];
314
+ const classNames = className.split('|');
315
+
316
+ for (let i = 0, len = elements.length; i < len; i++) {
317
+ const e = elements[i];
318
+ if (!e || e.nodeType !== 1) continue;
319
+ for (const c of classNames) {
320
+ if (c) /** @type {HTMLElement} */ (e).classList.add(c);
321
+ }
322
+ }
323
+ }
324
+
325
+ /**
326
+ * @description Delete the className value of the argument value element
327
+ * @param {Node|__se__NodeCollection} element Elements to remove class name
328
+ * @param {string} className Class name to be remove
329
+ */
330
+ export function removeClass(element, className) {
331
+ if (!element) return;
332
+
333
+ const elements = element instanceof HTMLCollection || element instanceof NodeList || element instanceof Array ? element : [element];
334
+ const classNames = className.split('|');
335
+
336
+ for (let i = 0, len = elements.length; i < len; i++) {
337
+ const e = elements[i];
338
+ if (!e || e.nodeType !== 1) continue;
339
+ for (const c of classNames) {
340
+ if (c) /** @type {HTMLElement} */ (e).classList.remove(c);
341
+ }
342
+ }
343
+ }
344
+
345
+ /**
346
+ * @description Argument value If there is no class name, insert it and delete the class name if it exists
347
+ * @param {Node} element Element to replace class name
348
+ * @param {string} className Class name to be change
349
+ * @returns {boolean|undefined}
350
+ */
351
+ export function toggleClass(element, className) {
352
+ if (!element || element.nodeType !== 1) return;
353
+
354
+ const el = /** @type {HTMLElement} */ (element);
355
+
356
+ let result = false;
357
+ const valid = new RegExp(`(\\s|^)${className}(\\s|$)`);
358
+ if (valid.test(el.className)) {
359
+ el.className = el.className.replace(valid, ' ').trim();
360
+ } else {
361
+ el.className += ' ' + className;
362
+ result = true;
363
+ }
364
+
365
+ if (!el.className.trim()) el.removeAttribute('class');
366
+
367
+ return result;
368
+ }
369
+
370
+ /**
371
+ * @description Flash the class name of the argument value element for a certain time
372
+ * @param {Node} element Element to flash class name
373
+ * @param {string} className class name
374
+ * @param {number} [duration=120] duration milliseconds
375
+ */
376
+ export function flashClass(element, className, duration = 120) {
377
+ addClass(element, className);
378
+ _w.setTimeout(() => {
379
+ removeClass(element, className);
380
+ }, duration);
381
+ }
382
+
383
+ /**
384
+ * @description Gets the size of the documentElement client size.
385
+ * @param {Document} doc Document object
386
+ * @returns {{w: number, h: number}} documentElement.clientWidth, documentElement.clientHeight
387
+ */
388
+ export function getClientSize(doc = _d) {
389
+ return {
390
+ w: doc.documentElement.clientWidth,
391
+ h: doc.documentElement.clientHeight
392
+ };
393
+ }
394
+
395
+ /**
396
+ * @description Gets the size of the window visualViewport size
397
+ * @returns {{top: number, left: number, scale: number}}
398
+ */
399
+ export function getViewportSize() {
400
+ if ('visualViewport' in _w) {
401
+ return {
402
+ top: _w.visualViewport.pageTop,
403
+ left: _w.visualViewport.pageLeft,
404
+ scale: _w.visualViewport.scale
405
+ };
406
+ }
407
+
408
+ return {
409
+ top: 0,
410
+ left: 0,
411
+ scale: 1
412
+ };
413
+ }
414
+
415
+ /**
416
+ * @description Copies the "wwTarget" element and returns it with inline all styles applied.
417
+ * @param {Node} wwTarget Target element to copy(.sun-editor.sun-editor-editable)
418
+ * @param {boolean} includeWW Include the "wwTarget" element in the copy
419
+ * @param {Array<string>} styles Style list - kamel case
420
+ * @returns
421
+ */
422
+ export function applyInlineStylesAll(wwTarget, includeWW, styles) {
423
+ if (!wwTarget) {
424
+ console.warn('"parentTarget" is not exist');
425
+ return null;
426
+ }
427
+
428
+ let ww = /** @type {HTMLElement} */ (wwTarget);
429
+ const tempTarget = _d.createElement('DIV');
430
+ tempTarget.style.display = 'none';
431
+
432
+ if (/body/i.test(ww.nodeName)) {
433
+ const wwDiv = _d.createElement('DIV');
434
+ const attrs = ww.attributes;
435
+ for (let i = 0, len = attrs.length; i < len; i++) {
436
+ wwDiv.setAttribute(attrs[i].name, attrs[i].value);
437
+ }
438
+ wwDiv.innerHTML = ww.innerHTML;
439
+ ww = wwDiv;
440
+ } else {
441
+ ww = /** @type {HTMLElement} */ (ww.cloneNode(true));
442
+ }
443
+
444
+ tempTarget.appendChild(ww);
445
+ _d.body.appendChild(tempTarget);
446
+
447
+ /** @type {HTMLElement[]} */
448
+ const allElements = Array.from(ww.querySelectorAll('*'));
449
+ const elements = includeWW ? [ww].concat(allElements) : allElements;
450
+ for (let i = 0, el; (el = elements[i]); i++) {
451
+ if (el.nodeType !== 1) continue;
452
+ const computedStyle = _w.getComputedStyle(el);
453
+ const els = el.style;
454
+ for (const props of styles) {
455
+ els.setProperty(props, computedStyle.getPropertyValue(props) || '');
456
+ }
457
+ }
458
+
459
+ _d.body.removeChild(tempTarget);
460
+
461
+ return ww;
462
+ }
463
+
464
+ /**
465
+ * @description Wait for media elements to load
466
+ * @param {Node} target Target element
467
+ * @param {number} timeout Timeout milliseconds
468
+ * @returns {Promise<void>}
469
+ */
470
+ export function waitForMediaLoad(target, timeout = 5000) {
471
+ const doc = /** @type {HTMLElement|Document} */ (target || _d);
472
+ return new Promise((resolveAll) => {
473
+ const selectors = ['img', 'video', 'audio', 'iframe'];
474
+ const mediaElements = selectors.flatMap((selector) => Array.from(doc.querySelectorAll(selector)));
475
+
476
+ if (mediaElements.length === 0) {
477
+ resolveAll();
478
+ return;
479
+ }
480
+
481
+ const mediaPromises = mediaElements.map((element) => {
482
+ // image
483
+ if (element instanceof HTMLImageElement) {
484
+ if (element.complete) {
485
+ return Promise.resolve();
486
+ }
487
+ }
488
+ // video, audio
489
+ else if (element instanceof HTMLMediaElement) {
490
+ if (element.readyState >= 2) {
491
+ return Promise.resolve();
492
+ }
493
+ }
494
+ // iframe
495
+ else if (element instanceof HTMLIFrameElement) {
496
+ try {
497
+ if (element.contentDocument?.readyState === 'complete') {
498
+ return Promise.resolve();
499
+ }
500
+ } catch (e) {
501
+ console.warn(['[SUNEDITOR] Iframe load error', e]);
502
+ }
503
+ }
504
+
505
+ // load event
506
+ return new Promise((resolve) => {
507
+ element.addEventListener('load', resolve, { once: true });
508
+ element.addEventListener('error', resolve, { once: true });
509
+ });
510
+ });
511
+
512
+ Promise.race([Promise.all(mediaPromises), new Promise((resolve) => _w.setTimeout(resolve, timeout))]).then(() => {
513
+ resolveAll();
514
+ });
515
+ });
516
+ }
517
+
518
+ /**
519
+ * @description Create tooltip HTML
520
+ * @param {string} text Tooltip text
521
+ * @returns {string} Tooltip HTML
522
+ */
523
+ export function createTooltipInner(text) {
524
+ return `<span class="se-tooltip-inner"><span class="se-tooltip-text">${text}</span></span>`;
525
+ }
526
+
527
+ const utils = {
528
+ clone,
529
+ createElement,
530
+ createTextNode,
531
+ getAttributesToString,
532
+ arrayFilter,
533
+ arrayFind,
534
+ arrayIncludes,
535
+ getArrayIndex,
536
+ nextIndex,
537
+ prevIndex,
538
+ copyTagAttributes,
539
+ copyFormatAttributes,
540
+ removeItem,
541
+ changeElement,
542
+ changeTxt,
543
+ setStyle,
544
+ setDisabled,
545
+ hasClass,
546
+ addClass,
547
+ removeClass,
548
+ toggleClass,
549
+ flashClass,
550
+ getClientSize,
551
+ getViewportSize,
552
+ applyInlineStylesAll,
553
+ waitForMediaLoad,
554
+ createTooltipInner
555
+ };
556
+
557
+ export default utils;
@@ -0,0 +1,12 @@
1
+ // index.js
2
+ import query from './domQuery';
3
+ import check from './domCheck';
4
+ import utils from './domUtils';
5
+
6
+ const dom = {
7
+ query,
8
+ check,
9
+ utils
10
+ };
11
+
12
+ export default dom;