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
@@ -1,1177 +0,0 @@
1
- import { _d, _w } from './env';
2
- import { onlyZeroWidthRegExp, zeroWidthRegExp } from './unicode';
3
-
4
- /**
5
- * @description A method that checks If the text is blank or to see if it contains 'ZERO WIDTH SPACE' or empty (unicode.zeroWidthSpace)
6
- * @param {string|Node} text String value or Node
7
- * @returns {boolean}
8
- */
9
- export function isZeroWith(text) {
10
- if (text === null || text === undefined) return false;
11
- if (typeof text !== 'string') text = text.textContent;
12
- return text === '' || onlyZeroWidthRegExp.test(text);
13
- }
14
-
15
- /**
16
- * @description Create Element node
17
- * @param {string} elementName Element name
18
- * @param {Object.<string, string>|null|undefined} attributes The attributes of the tag. {style: 'font-size:12px;..', class: 'el_class',..}
19
- * @param {string|Node|null|undefined} inner A innerHTML string or inner node.
20
- * @returns {Element}
21
- */
22
- export function createElement(elementName, attributes, inner) {
23
- const el = _d.createElement(elementName);
24
-
25
- if (attributes) {
26
- for (const key in attributes) {
27
- if (attributes[key] !== undefined && attributes[key] !== null) el.setAttribute(key, attributes[key]);
28
- }
29
- }
30
-
31
- if (inner) {
32
- if (typeof inner === 'string') {
33
- el.innerHTML = inner;
34
- } else if (typeof inner === 'object') {
35
- el.appendChild(inner);
36
- }
37
- }
38
-
39
- return el;
40
- }
41
-
42
- /**
43
- * @description Create text node
44
- * @param {string} text text content
45
- * @returns {Text}
46
- */
47
- export function createTextNode(text) {
48
- return _d.createTextNode(text || '');
49
- }
50
-
51
- /**
52
- * @description Get the argument iframe's document object if use the "iframe" or "fullPage" options
53
- * @param {Element} iframe Iframe element (this.editor.frameContext.get('wysiwygFrame'))
54
- * @returns {Document}
55
- */
56
- export function getIframeDocument(iframe) {
57
- let wDocument = iframe.contentWindow || iframe.contentDocument;
58
- if (wDocument.document) wDocument = wDocument.document;
59
- return wDocument;
60
- }
61
-
62
- /**
63
- * @description Get attributes of argument element to string ('class="---" name="---" ')
64
- * @param {Element} element Element object
65
- * @param {Array.<string>|null} exceptAttrs Array of attribute names to exclude from the result
66
- * @returns {string}
67
- */
68
- export function getAttributesToString(element, exceptAttrs) {
69
- if (!element.attributes) return '';
70
-
71
- const attrs = element.attributes;
72
- let attrString = '';
73
-
74
- for (let i = 0, len = attrs.length; i < len; i++) {
75
- if (exceptAttrs?.includes(attrs[i].name)) continue;
76
- attrString += attrs[i].name + '="' + attrs[i].value + '" ';
77
- }
78
-
79
- return attrString;
80
- }
81
-
82
- /**
83
- * @description Returns the index compared to other sibling nodes.
84
- * @param {Node} node The Node to find index
85
- * @returns {number}
86
- */
87
- export function getPositionIndex(node) {
88
- let idx = 0;
89
- while ((node = node.previousSibling)) {
90
- idx += 1;
91
- }
92
- return idx;
93
- }
94
-
95
- /**
96
- * @description Returns the position of the "node" in the "parentNode" in a numerical array.
97
- * ex) <p><span>aa</span><span>bb</span></p> : getNodePath(node: "bb", parentNode: "<P>") -> [1, 0]
98
- * @param {Node} node The Node to find position path
99
- * @param {Node|null} parentNode Parent node. If null, wysiwyg div area
100
- * @param {{s: number, e: number}|null} _newOffsets If you send an object of the form "{s: 0, e: 0}", the text nodes that are attached together are merged into one, centered on the "node" argument.
101
- * "_newOffsets.s" stores the length of the combined characters after "node" and "_newOffsets.e" stores the length of the combined characters before "node".
102
- * Do not use unless absolutely necessary.
103
- * @returns {Array.<number>}
104
- */
105
- export function getNodePath(node, parentNode, _newOffsets) {
106
- const path = [];
107
- let finds = true;
108
-
109
- getParentElement(node, (el) => {
110
- if (el === parentNode) finds = false;
111
- if (finds && !isWysiwygFrame(el)) {
112
- // merge text nodes
113
- if (_newOffsets && el.nodeType === 3) {
114
- let temp = null,
115
- tempText = null;
116
- _newOffsets.s = _newOffsets.e = 0;
117
-
118
- let previous = el.previousSibling;
119
- while (previous?.nodeType === 3) {
120
- tempText = previous.textContent.replace(zeroWidthRegExp, '');
121
- _newOffsets.s += tempText.length;
122
- el.textContent = tempText + el.textContent;
123
- temp = previous;
124
- previous = previous.previousSibling;
125
- removeItem(temp);
126
- }
127
-
128
- let next = el.nextSibling;
129
- while (next?.nodeType === 3) {
130
- tempText = next.textContent.replace(zeroWidthRegExp, '');
131
- _newOffsets.e += tempText.length;
132
- el.textContent += tempText;
133
- temp = next;
134
- next = next.nextSibling;
135
- removeItem(temp);
136
- }
137
- }
138
-
139
- // index push
140
- path.push(el);
141
- }
142
- return false;
143
- });
144
-
145
- return path.map(getPositionIndex).reverse();
146
- }
147
-
148
- /**
149
- * @description Returns the node in the location of the path array obtained from "helper.dom.getNodePath".
150
- * @param {Array.<number>} offsets Position array, array obtained from "helper.dom.getNodePath"
151
- * @param {Node} parentNode Base parent element
152
- * @returns {Node}
153
- */
154
- export function getNodeFromPath(offsets, parentNode) {
155
- let current = parentNode;
156
- let nodes;
157
-
158
- for (let i = 0, len = offsets.length; i < len; i++) {
159
- nodes = current.childNodes;
160
- if (nodes.length === 0) break;
161
- if (nodes.length <= offsets[i]) {
162
- current = nodes[nodes.length - 1];
163
- } else {
164
- current = nodes[offsets[i]];
165
- }
166
- }
167
-
168
- return current;
169
- }
170
-
171
- /**
172
- * @description Get all "children" of the argument value element (Without text nodes)
173
- * @param {Element} element element to get child node
174
- * @param {Function|null} validation Conditional function
175
- * @returns {Array.<Element>}
176
- */
177
- export function getListChildren(element, validation) {
178
- const children = [];
179
- if (!element || !element.children || element.children.length === 0) return children;
180
-
181
- validation =
182
- validation ||
183
- function () {
184
- return true;
185
- };
186
-
187
- (function recursionFunc(current) {
188
- if (element !== current && validation(current)) {
189
- children.push(current);
190
- }
191
-
192
- if (current.children) {
193
- for (let i = 0, len = current.children.length; i < len; i++) {
194
- recursionFunc(current.children[i]);
195
- }
196
- }
197
- })(element);
198
-
199
- return children;
200
- }
201
-
202
- /**
203
- * @description Get all "childNodes" of the argument value element (Include text nodes)
204
- * @param {Node} element element to get child node
205
- * @param {Function|null} validation Conditional function
206
- * @returns {Array.<Node>}
207
- */
208
- export function getListChildNodes(element, validation) {
209
- const children = [];
210
- if (!element || element.childNodes.length === 0) return children;
211
-
212
- validation =
213
- validation ||
214
- function () {
215
- return true;
216
- };
217
-
218
- (function recursionFunc(current) {
219
- if (element !== current && validation(current)) {
220
- children.push(current);
221
- }
222
-
223
- for (let i = 0, len = current.childNodes.length; i < len; i++) {
224
- recursionFunc(current.childNodes[i]);
225
- }
226
- })(element);
227
-
228
- return children;
229
- }
230
-
231
- /**
232
- * @description Returns the number of parents nodes.
233
- * "0" when the parent node is the WYSIWYG area.
234
- * '-1' when the element argument is the WYSIWYG area.
235
- * @param {Node} node The element to check
236
- * @returns {number}
237
- */
238
- export function getNodeDepth(node) {
239
- if (!node || isWysiwygFrame(node)) return -1;
240
-
241
- let depth = 0;
242
- node = node.parentNode;
243
-
244
- while (node && !isWysiwygFrame(node)) {
245
- depth += 1;
246
- node = node.parentNode;
247
- }
248
-
249
- return depth;
250
- }
251
-
252
- /**
253
- * @description Sort a node array by depth of element.
254
- * @param {Array.<Node>} array Node array
255
- * @param {boolean} des true: descending order / false: ascending order
256
- */
257
- export function sortNodeByDepth(array, des) {
258
- const t = !des ? -1 : 1;
259
- const f = t * -1;
260
-
261
- array.sort(function (a, b) {
262
- if (!isListCell(a) || !isListCell(b)) return 0;
263
- a = getNodeDepth(a);
264
- b = getNodeDepth(b);
265
- return a > b ? t : a < b ? f : 0;
266
- });
267
- }
268
-
269
- /**
270
- * @description Compares two elements to find a common ancestor, and returns the order of the two elements.
271
- * @param {Node} a Node to compare.
272
- * @param {Node} b Node to compare.
273
- * @returns {{ancesstor: Node, a: Node, b: Node, ressult: number}} { ancesstor, a, b, result: (a > b ? 1 : a < b ? -1 : 0) };
274
- */
275
- export function compareElements(a, b) {
276
- let aNode = a,
277
- bNode = b;
278
- while (aNode && bNode && aNode.parentNode !== bNode.parentNode) {
279
- aNode = aNode.parentNode;
280
- bNode = bNode.parentNode;
281
- }
282
-
283
- if (!aNode || !bNode)
284
- return {
285
- ancestor: null,
286
- a: a,
287
- b: b,
288
- result: 0
289
- };
290
-
291
- const children = aNode.parentNode.childNodes;
292
- const aIndex = getArrayIndex(children, aNode);
293
- const bIndex = getArrayIndex(children, bNode);
294
-
295
- return {
296
- ancestor: aNode.parentNode,
297
- a: aNode,
298
- b: bNode,
299
- result: aIndex > bIndex ? 1 : aIndex < bIndex ? -1 : 0
300
- };
301
- }
302
-
303
- /**
304
- * @description Get the parent element of the argument value.
305
- * A tag that satisfies the query condition is imported.
306
- * Returns null if not found.
307
- * @param {Node} element Reference element
308
- * @param {string|Function|Node} query Query String (nodeName, .className, #ID, :name) or validation function.
309
- * Not use it like jquery.
310
- * Only one condition can be entered at a time.
311
- * @returns {Element|null}
312
- */
313
- export function getParentElement(element, query) {
314
- let check;
315
-
316
- if (typeof query === 'function') {
317
- check = query;
318
- } else if (typeof query === 'object') {
319
- check = function (current) {
320
- return current === query;
321
- };
322
- } else {
323
- let attr;
324
- if (/^\./.test(query)) {
325
- attr = 'className';
326
- query = '(\\s|^)' + query.split('.')[1] + '(\\s|$)';
327
- } else if (/^#/.test(query)) {
328
- attr = 'id';
329
- query = '^' + query.split('#')[1] + '$';
330
- } else if (/^:/.test(query)) {
331
- attr = 'name';
332
- query = '^' + query.split(':')[1] + '$';
333
- } else {
334
- attr = 'nodeName';
335
- query = '^' + query + '$';
336
- }
337
-
338
- const regExp = new RegExp(query, 'i');
339
- check = function (el) {
340
- return regExp.test(el[attr]);
341
- };
342
- }
343
-
344
- while (element && !check(element)) {
345
- if (isWysiwygFrame(element)) {
346
- return null;
347
- }
348
- element = element.parentNode;
349
- }
350
-
351
- return element;
352
- }
353
-
354
- /**
355
- * @description Gets all ancestors of the argument value.
356
- * Get all tags that satisfy the query condition.
357
- * Returned in an array in order.
358
- * @param {Node} element Reference element
359
- * @param {string|Function|Node} query Query String (nodeName, .className, #ID, :name) or validation function.
360
- * Not use it like jquery.
361
- * Only one condition can be entered at a time.
362
- * @returns {Element|null}
363
- */
364
- export function getParentElements(element, query) {
365
- let check;
366
-
367
- if (typeof query === 'function') {
368
- check = query;
369
- } else if (typeof query === 'object') {
370
- check = function (current) {
371
- return current === query;
372
- };
373
- } else {
374
- let attr;
375
- if (/^\./.test(query)) {
376
- attr = 'className';
377
- query = '(\\s|^)' + query.split('.')[1] + '(\\s|$)';
378
- } else if (/^#/.test(query)) {
379
- attr = 'id';
380
- query = '^' + query.split('#')[1] + '$';
381
- } else if (/^:/.test(query)) {
382
- attr = 'name';
383
- query = '^' + query.split(':')[1] + '$';
384
- } else {
385
- attr = 'nodeName';
386
- query = '^' + query + '$';
387
- }
388
-
389
- const regExp = new RegExp(query, 'i');
390
- check = function (el) {
391
- return regExp.test(el[attr]);
392
- };
393
- }
394
-
395
- const elementList = [];
396
- while (element && !isWysiwygFrame(element)) {
397
- if (check(element)) {
398
- elementList.push(element);
399
- }
400
- element = element.parentNode;
401
- }
402
-
403
- return elementList;
404
- }
405
-
406
- /**
407
- * @description Gets the element with "data-command" attribute among the parent elements.
408
- * @param {Element} target Target element
409
- * @returns {Element|null}
410
- */
411
- export function getCommandTarget(target) {
412
- while (!/^(UL|DIV)$/i.test(target.tagName)) {
413
- if (target.hasAttribute('data-command')) return target;
414
- target = target.parentNode;
415
- }
416
-
417
- return null;
418
- }
419
-
420
- /**
421
- * @description Get the child element of the argument value.
422
- * A tag that satisfies the query condition is imported.
423
- * Returns null if not found.
424
- * @param {Node} node Reference element
425
- * @param {string|Function|Node} query Query String (nodeName, .className, #ID, :name) or validation function.
426
- * @param {boolean} last If true returns the last node among the found child nodes. (default: first node)
427
- * Not use it like jquery.
428
- * Only one condition can be entered at a time.
429
- * @returns {Element|null}
430
- */
431
- export function getEdgeChild(node, query, last) {
432
- let check;
433
-
434
- if (typeof query === 'function') {
435
- check = query;
436
- } else if (typeof query === 'object') {
437
- check = function (current) {
438
- return current === query;
439
- };
440
- } else {
441
- let attr;
442
- if (/^\./.test(query)) {
443
- attr = 'className';
444
- query = '(\\s|^)' + query.split('.')[1] + '(\\s|$)';
445
- } else if (/^#/.test(query)) {
446
- attr = 'id';
447
- query = '^' + query.split('#')[1] + '$';
448
- } else if (/^:/.test(query)) {
449
- attr = 'name';
450
- query = '^' + query.split(':')[1] + '$';
451
- } else {
452
- attr = 'nodeName';
453
- query = '^' + (query === 'text' ? '#' + query : query) + '$';
454
- }
455
-
456
- const regExp = new RegExp(query, 'i');
457
- check = function (el) {
458
- return regExp.test(el[attr]);
459
- };
460
- }
461
-
462
- const childList = getListChildNodes(node, (current) => check(current));
463
-
464
- return childList[last ? childList.length - 1 : 0];
465
- }
466
-
467
- /**
468
- * @description 1. The first node of all the child nodes of the "first" element is returned.
469
- * 2. The last node of all the child nodes of the "last" element is returned.
470
- * 3. When there is no "last" element, the first and last nodes of all the children of the "first" element are returned.
471
- * { sc: "first", ec: "last" }
472
- * @param {Node} first First element
473
- * @param {Node|null} last Last element
474
- * @returns {{sc: Node, ec: Node}}
475
- */
476
- export function getEdgeChildNodes(first, last) {
477
- if (!first) return;
478
- if (!last) last = first;
479
-
480
- while (first && first.nodeType === 1 && first.childNodes.length > 0 && !isBreak(first)) first = first.firstChild;
481
- while (last && last.nodeType === 1 && last.childNodes.length > 0 && !isBreak(last)) last = last.lastChild;
482
-
483
- return {
484
- sc: first,
485
- ec: last || first
486
- };
487
- }
488
-
489
- /**
490
- * @description Get the item from the array that matches the condition.
491
- * @param {Array.<Node>|HTMLCollection|NodeList} array Array to get item
492
- * @param {Function|null} validation Conditional function
493
- * @param {boolean} multi If true, returns all items that meet the criteria otherwise, returns an empty array.
494
- * If false, returns only one item that meet the criteria otherwise return null.
495
- * @returns {Array.<Node>|null}
496
- */
497
- export function getArrayItem(array, validation, multi) {
498
- if (!array || array.length === 0) return null;
499
-
500
- validation =
501
- validation ||
502
- function () {
503
- return true;
504
- };
505
- const arr = [];
506
-
507
- for (let i = 0, len = array.length, a; i < len; i++) {
508
- a = array[i];
509
- if (validation(a)) {
510
- if (!multi) return a;
511
- else arr.push(a);
512
- }
513
- }
514
-
515
- return !multi ? null : arr;
516
- }
517
-
518
- /**
519
- * @description Check if an array contains an element
520
- * @param {Array.<Node>|HTMLCollection|NodeList} array element array
521
- * @param {Node} node The node to check for
522
- * @returns {boolean}
523
- */
524
- export function arrayIncludes(array, node) {
525
- for (let i = 0; i < array.length; i++) {
526
- if (array[i] === node) {
527
- return true;
528
- }
529
- }
530
- return false;
531
- }
532
-
533
- /**
534
- * @description Get the index of the argument value in the element array
535
- * @param {Array|HTMLCollection|NodeList} array element array
536
- * @param {Node} node The element to find index
537
- * @returns {number}
538
- */
539
- export function getArrayIndex(array, node) {
540
- let idx = -1;
541
- for (let i = 0, len = array.length; i < len; i++) {
542
- if (array[i] === node) {
543
- idx = i;
544
- break;
545
- }
546
- }
547
-
548
- return idx;
549
- }
550
-
551
- /**
552
- * @description Get the next index of the argument value in the element array
553
- * @param {Array.<Node>|HTMLCollection|NodeList} array element array
554
- * @param {Node} item The element to find index
555
- * @returns {number}
556
- */
557
- export function nextIndex(array, item) {
558
- const idx = getArrayIndex(array, item);
559
- if (idx === -1) return -1;
560
- return idx + 1;
561
- }
562
-
563
- /**
564
- * @description Get the previous index of the argument value in the element array
565
- * @param {Array.<Node>|HTMLCollection|NodeList} array Element array
566
- * @param {Node} item The element to find index
567
- * @returns {number}
568
- */
569
- export function prevIndex(array, item) {
570
- const idx = getArrayIndex(array, item);
571
- if (idx === -1) return -1;
572
- return idx - 1;
573
- }
574
-
575
- /**
576
- * @description Add style and className of copyEl to originEl
577
- * @param {Element} originEl Origin element
578
- * @param {Element} copyEl Element to copy
579
- * @param {Array.<string>|null} blacklist Blacklist array(LowerCase)
580
- */
581
- export function copyTagAttributes(originEl, copyEl, blacklist) {
582
- if (copyEl.style.cssText) {
583
- const copyStyles = copyEl.style;
584
- for (let i = 0, len = copyStyles.length; i < len; i++) {
585
- originEl.style[copyStyles[i]] = copyStyles[copyStyles[i]];
586
- }
587
- }
588
-
589
- const attrs = copyEl.attributes;
590
- for (let i = 0, len = attrs.length, name; i < len; i++) {
591
- name = attrs[i].name.toLowerCase();
592
- if (blacklist?.includes(name) || !attrs[i].value) originEl.removeAttribute(name);
593
- else if (name !== 'style') originEl.setAttribute(attrs[i].name, attrs[i].value);
594
- }
595
- }
596
-
597
- /**
598
- * @description Copy and apply attributes of format tag that should be maintained. (style, class) Ignore "__se__format__" class
599
- * @param {Element} originEl Origin element
600
- * @param {Element} copyEl Element to copy
601
- */
602
- export function copyFormatAttributes(originEl, copyEl) {
603
- copyEl = copyEl.cloneNode(false);
604
- copyEl.className = copyEl.className.replace(/(\s|^)__se__format__[^\s]+/g, '');
605
- copyTagAttributes(originEl, copyEl);
606
- }
607
-
608
- /**
609
- * @description Compares the style and class for equal values.
610
- * Returns true if both are text nodes.
611
- * @param {Node} a Node to compare
612
- * @param {Node} b Node to compare
613
- * @returns {boolean}
614
- */
615
- export function isSameAttributes(a, b) {
616
- if (a.nodeType === 3 && b.nodeType === 3) return true;
617
- if (a.nodeType === 3 || b.nodeType === 3) return false;
618
-
619
- const style_a = a.style;
620
- const style_b = b.style;
621
- let compStyle = 0;
622
-
623
- for (let i = 0, len = style_a.length; i < len; i++) {
624
- if (style_a[style_a[i]] === style_b[style_a[i]]) compStyle++;
625
- }
626
-
627
- const class_a = a.classList;
628
- const class_b = b.classList;
629
- const wRegExp = RegExp;
630
- let compClass = 0;
631
-
632
- for (let i = 0, len = class_a.length; i < len; i++) {
633
- if (wRegExp('(s|^)' + class_a[i] + '(s|$)').test(class_b.value)) compClass++;
634
- }
635
-
636
- return compStyle === style_b.length && compStyle === style_a.length && compClass === class_b.length && compClass === class_a.length;
637
- }
638
-
639
- /**
640
- * @description Delete argumenu value element
641
- * @param {Node} item Node to be remove
642
- */
643
- export function removeItem(item) {
644
- if (!item) return;
645
- if (typeof item.remove === 'function') item.remove();
646
- else if (item.parentNode) item.parentNode.removeChild(item);
647
- }
648
-
649
- /**
650
- * @description Replace element
651
- * @param {Element} element Target element
652
- * @param {string|Element} newElement String or element of the new element to apply
653
- */
654
- export function changeElement(element, newElement) {
655
- if (!element) return;
656
-
657
- if (typeof newElement === 'string') {
658
- if (element.outerHTML) {
659
- element.outerHTML = newElement;
660
- } else {
661
- const doc = createElement('DIV');
662
- doc.innerHTML = newElement;
663
- newElement = doc.firstChild;
664
- element.parentNode.replaceChild(newElement, element);
665
- }
666
- } else if (newElement?.nodeType === 1) {
667
- element.parentNode.replaceChild(newElement, element);
668
- }
669
- }
670
-
671
- /**
672
- * @description Set the text content value of the argument value element
673
- * @param {Node} node Element to replace text content
674
- * @param {string} txt Text to be applied
675
- */
676
- export function changeTxt(node, txt) {
677
- if (!node || !txt) return;
678
- node.textContent = txt;
679
- }
680
-
681
- /**
682
- * @description Set style, if all styles are deleted, the style properties are deleted.
683
- * @param {Element|Element[]} elements Element to set style
684
- * @param {string} styleName Style attribute name (marginLeft, textAlign...)
685
- * @param {string|number} value Style value
686
- */
687
- export function setStyle(elements, styleName, value) {
688
- elements = Array.isArray(elements) ? elements : [elements];
689
-
690
- for (let i = 0, len = elements.length, e; i < len; i++) {
691
- e = elements[i];
692
- e.style[styleName] = value;
693
- if (!value && !e.style.cssText) {
694
- e.removeAttribute('style');
695
- }
696
- }
697
- }
698
-
699
- /**
700
- * @description In the predefined code view mode, the buttons except the executable button are changed to the 'disabled' state.
701
- * @param {Array.<Element>|HTMLCollection|NodeList} buttonList Button array
702
- * @param {boolean} disabled Disabled value
703
- * @param {boolean} important If priveleged mode should be used (Necessary to switch importantDisabled buttons)
704
- */
705
- export function setDisabled(buttonList, disabled, important) {
706
- for (let i = 0, len = buttonList.length; i < len; i++) {
707
- const button = buttonList[i];
708
- if (important || !isImportantDisabled(button)) button.disabled = disabled;
709
- if (important) {
710
- if (disabled) {
711
- button.setAttribute('data-important-disabled', '');
712
- } else {
713
- button.removeAttribute('data-important-disabled');
714
- }
715
- }
716
- }
717
- }
718
-
719
- /**
720
- * @description Determine whether any of the matched elements are assigned the given class
721
- * @param {Element} element Elements to search class name
722
- * @param {string} className Class name to search for
723
- * @returns {boolean}
724
- */
725
- export function hasClass(element, className) {
726
- if (!element) return;
727
- const check = new RegExp(`(\\s|^)${className}(\\s|$)`);
728
- return check.test(element.className);
729
- }
730
-
731
- /**
732
- * @description Append the className value of the argument value element
733
- * @param {Element|Array.<Element>|NodeList} element Elements to add class name
734
- * @param {string} className Class name to be add
735
- */
736
- export function addClass(element, className) {
737
- if (!element) return;
738
-
739
- const elements = element instanceof HTMLCollection || element instanceof NodeList || element instanceof Array ? element : [element];
740
- const classNames = className.split('|');
741
-
742
- for (const e of elements) {
743
- if (!e || e.nodeType !== 1) continue;
744
- for (const c of classNames) {
745
- if (c) e.classList.add(c);
746
- }
747
- }
748
- }
749
-
750
- /**
751
- * @description Delete the className value of the argument value element
752
- * @param {Element|Array.<Element>|NodeList} element Elements to remove class name
753
- * @param {string} className Class name to be remove
754
- */
755
- export function removeClass(element, className) {
756
- if (!element) return;
757
-
758
- const elements = element instanceof HTMLCollection || element instanceof NodeList || element instanceof Array ? element : [element];
759
- const classNames = className.split('|');
760
-
761
- for (const e of elements) {
762
- if (!e || e.nodeType !== 1) continue;
763
- for (const c of classNames) {
764
- if (c) e.classList.remove(c);
765
- }
766
- }
767
- }
768
-
769
- /**
770
- * @description Argument value If there is no class name, insert it and delete the class name if it exists
771
- * @param {Element} element Element to replace class name
772
- * @param {string} className Class name to be change
773
- * @returns {boolean|undefined}
774
- */
775
- export function toggleClass(element, className) {
776
- if (!element) return;
777
- if (element.nodeType !== 1) return;
778
-
779
- let result = false;
780
-
781
- const check = new RegExp(`(\\s|^)${className}(\\s|$)`);
782
- if (check.test(element.className)) {
783
- element.className = element.className.replace(check, ' ').trim();
784
- } else {
785
- element.className += ' ' + className;
786
- result = true;
787
- }
788
-
789
- if (!element.className.trim()) element.removeAttribute('class');
790
-
791
- return result;
792
- }
793
-
794
- /**
795
- * @description Determine if this offset is the edge offset of container
796
- * @param {Node} container The node of the selection object. (range.startContainer..)
797
- * @param {number} offset The offset of the selection object. (core.getRange().startOffset...)
798
- * @param {string|undefined} dir Select check point - Both edge, Front edge or End edge. ("front": Front edge, "end": End edge, undefined: Both edge)
799
- * @returns {boolean}
800
- */
801
- export function isEdgePoint(container, offset, dir) {
802
- return (dir !== 'end' && offset === 0) || ((!dir || dir !== 'front') && !container.nodeValue && offset === 1) || ((!dir || dir === 'end') && container.nodeValue && offset === container.nodeValue.length);
803
- }
804
-
805
- /**
806
- * @description It is judged whether it is the edit region top div element or iframe's body tag.
807
- * @param {Node} element The node to check
808
- * @returns {boolean}
809
- */
810
- export function isWysiwygFrame(element) {
811
- return element?.nodeType === 1 && (hasClass(element, 'se-wrapper-wysiwyg|sun-editor-carrier-wrapper') || /^BODY$/i.test(element.nodeName));
812
- }
813
-
814
- /**
815
- * @description It is judged whether it is the contenteditable property is false.
816
- * @param {Node} element The node to check
817
- * @returns {boolean}
818
- */
819
- export function isNonEditable(element) {
820
- return element?.nodeType === 1 && element.getAttribute('contenteditable') === 'false';
821
- }
822
-
823
- /**
824
- * @description Check the node is a list (ol, ul)
825
- * @param {Node|string} node The element or element name to check
826
- * @returns {boolean}
827
- */
828
- export function isList(node) {
829
- return /^(OL|UL)$/i.test(typeof node === 'string' ? node : node?.nodeName);
830
- }
831
-
832
- /**
833
- * @description Check the node is a list cell (li)
834
- * @param {Node|string} node The element or element name to check
835
- * @returns {boolean}
836
- */
837
- export function isListCell(node) {
838
- return /^LI$/i.test(typeof node === 'string' ? node : node?.nodeName);
839
- }
840
-
841
- /**
842
- * @description Check the node is a table
843
- * @param {Node|string} node The element or element name to check
844
- * @returns {boolean}
845
- */
846
- export function isTable(node) {
847
- return /^TABLE$/i.test(typeof node === 'string' ? node : node?.nodeName);
848
- }
849
-
850
- /**
851
- * @description Check the node is a table elements. (table, thead, tbody, tr, th, td)
852
- * @param {Node|string} node The element or element name to check
853
- * @returns {boolean}
854
- */
855
- export function isTableElements(node) {
856
- return /^(TABLE|THEAD|TBODY|TR|TH|TD|COL)$/i.test(typeof node === 'string' ? node : node?.nodeName);
857
- }
858
-
859
- /**
860
- * @description Check the node is a table cell (td, th)
861
- * @param {Node|string} node The element or element name to check
862
- * @returns {boolean}
863
- */
864
- export function isTableCell(node) {
865
- return /^(TD|TH)$/i.test(typeof node === 'string' ? node : node?.nodeName);
866
- }
867
-
868
- /**
869
- * @description Check the node is a table row (tr)
870
- * @param {Node|string} node The element or element name to check
871
- * @returns {boolean}
872
- */
873
- export function isTableRow(node) {
874
- return /^TR$/i.test(typeof node === 'string' ? node : node?.nodeName);
875
- }
876
-
877
- /**
878
- * @description Check the node is a break node (BR)
879
- * @param {Node|string} node The element or element name to check
880
- * @returns {boolean}
881
- */
882
- export function isBreak(node) {
883
- return /^BR$/i.test(typeof node === 'string' ? node : node?.nodeName);
884
- }
885
-
886
- /**
887
- * @description Check the node is a anchor node (A)
888
- * @param {Node|string} node The element or element name to check
889
- * @returns {boolean}
890
- */
891
- export function isAnchor(node) {
892
- return /^A$/i.test(typeof node === 'string' ? node : node?.nodeName);
893
- }
894
-
895
- /**
896
- * @description Check the node is a media node (img, iframe, audio, video, canvas)
897
- * @param {Node|string} node The element or element name to check
898
- * @returns {boolean}
899
- */
900
- export function isMedia(node) {
901
- return /^(IMG|IFRAME|AUDIO|VIDEO|CANVAS)$/i.test(typeof node === 'string' ? node : node?.nodeName);
902
- }
903
-
904
- /**
905
- * @description Check the node is a figure tag
906
- * @param {Node|String} node The element or element name to check
907
- * @returns {Boolean}
908
- */
909
- export function isFigure(node) {
910
- return /^FIGURE$/i.test(typeof node === 'string' ? node : node?.nodeName);
911
- }
912
-
913
- /**
914
- * @description It is judged whether it is the input element (INPUT, TEXTAREA)
915
- * @param {Node} element The node to check
916
- * @returns {Boolean}
917
- */
918
- export function isInputElement(element) {
919
- return element?.nodeType === 1 && /^(INPUT|TEXTAREA|SELECT|OPTION)$/i.test(element.nodeName);
920
- }
921
-
922
- /**
923
- * @description Check the line element is empty.
924
- * @param {Element} element Format element node
925
- * @returns {boolean}
926
- */
927
- export function isEmptyLine(element) {
928
- return !element?.parentNode || (!element.querySelector('IMG, IFRAME, AUDIO, VIDEO, CANVAS, TABLE') && element.children.length === 0 && isZeroWith(element.textContent));
929
- }
930
-
931
- /**
932
- * @description Check the span's attributes are empty.
933
- * @param {Element|null} element Element node
934
- * @returns {Boolean}
935
- */
936
- export function isSpanWithoutAttr(element) {
937
- return element?.nodeType === 1 && /^SPAN$/i.test(element.nodeName) && !element.className && !element.style.cssText;
938
- }
939
-
940
- /**
941
- * @description Checks for "__se__uneditable" in the class list.
942
- * Components with class "__se__uneditable" cannot be modified.
943
- * @param {Element} element The element to check
944
- * @returns {boolean}
945
- */
946
- export function isUneditable(element) {
947
- return hasClass(element, '__se__uneditable');
948
- }
949
-
950
- /**
951
- * @description Checks if element can't be easily enabled
952
- * @param {Element} element Element to check for
953
- */
954
- export function isImportantDisabled(element) {
955
- return element.hasAttribute('data-important-disabled');
956
- }
957
-
958
- /**
959
- * @description It is judged whether it is the not checking node. (class="katex", "se-exclude-format")
960
- * @param {Node} element The node to check
961
- * @returns {boolean}
962
- */
963
- export function isExcludeFormat(element) {
964
- return /(\s|^)(katex|se-exclude-format)(\s|$)/.test(element?.className);
965
- }
966
-
967
- /**
968
- * @description Get nearest scrollable parent
969
- * @param {Element} element Element
970
- * @returns {Element|null}
971
- */
972
- export function getScrollParent(element) {
973
- if (!element || /^(body|html)$/i.test(element.nodeName)) {
974
- return null;
975
- }
976
-
977
- if (element.scrollHeight > element.clientHeight) {
978
- return element;
979
- } else {
980
- return getScrollParent(element.parentNode);
981
- }
982
- }
983
-
984
- /**
985
- * @description Gets the size of the documentElement client size.
986
- * @param {Document} doc Document object
987
- * @returns {{w, h}}
988
- */
989
- export function getClientSize(doc = _d) {
990
- return {
991
- w: doc.documentElement.clientWidth,
992
- h: doc.documentElement.clientHeight
993
- };
994
- }
995
-
996
- /**
997
- * @description Gets the size of the window visualViewport size
998
- * @returns {{top: number, left: number, scale: number}}
999
- */
1000
- export function getViewportSize() {
1001
- if ('visualViewport' in _w) {
1002
- return {
1003
- top: _w.visualViewport.pageTop,
1004
- left: _w.visualViewport.pageLeft,
1005
- scale: _w.visualViewport.scale
1006
- };
1007
- }
1008
-
1009
- return {
1010
- top: 0,
1011
- left: 0,
1012
- scale: 1
1013
- };
1014
- }
1015
-
1016
- /**
1017
- * @description Gets the previous sibling last child. If there is no sibling, then it'll take it from the closest ancestor with child
1018
- * Returns null if not found.
1019
- * @param {Node} node Reference element
1020
- * @param {Node|null} ceiling Highest boundary allowed
1021
- * @returns {Node|null}
1022
- */
1023
- export function getPreviousDeepestNode(node, ceiling) {
1024
- let previousNode = node.previousSibling;
1025
- if (!previousNode) {
1026
- for (let parentNode = node.parentNode; parentNode; parentNode = parentNode.parentNode) {
1027
- if (parentNode === ceiling) return null;
1028
- if (parentNode.previousSibling) {
1029
- previousNode = parentNode.previousSibling;
1030
- break;
1031
- }
1032
- }
1033
- if (!previousNode) return null;
1034
- }
1035
-
1036
- if (isNonEditable(previousNode)) return previousNode;
1037
-
1038
- while (previousNode.lastChild) previousNode = previousNode.lastChild;
1039
-
1040
- return previousNode;
1041
- }
1042
-
1043
- /**
1044
- * @description Gets the next sibling first child. If there is no sibling, then it'll take it from the closest ancestor with child
1045
- * Returns null if not found.
1046
- * @param {Node} node Reference element
1047
- * @param {Node|null} ceiling Highest boundary allowed
1048
- * @returns {Node|null}
1049
- */
1050
- export function getNextDeepestNode(node, ceiling) {
1051
- let nextNode = node.nextSibling;
1052
- if (!nextNode) {
1053
- for (let parentNode = node.parentNode; parentNode; parentNode = parentNode.parentNode) {
1054
- if (parentNode === ceiling) return null;
1055
- if (parentNode.nextSibling) {
1056
- nextNode = parentNode.nextSibling;
1057
- break;
1058
- }
1059
- }
1060
- if (!nextNode) return null;
1061
- }
1062
-
1063
- if (isNonEditable(nextNode)) return nextNode;
1064
-
1065
- while (nextNode.firstChild) nextNode = nextNode.firstChild;
1066
-
1067
- return nextNode;
1068
- }
1069
-
1070
- /**
1071
- * @description Copies the "wwTarget" element and returns it with inline all styles applied.
1072
- * @param {Element} wwTarget Target element to copy(.sun-editor.sun-editor-editable)
1073
- * @param {Boolean} includeWW Include the "wwTarget" element in the copy
1074
- * @param {string[]} styles Style list - kamel case
1075
- * @returns
1076
- */
1077
- export function applyInlineStylesAll(wwTarget, includeWW, styles) {
1078
- if (!wwTarget) {
1079
- console.warn('"parentTarget" is not exist');
1080
- return null;
1081
- }
1082
-
1083
- const tempTarget = _d.createElement('DIV');
1084
- tempTarget.style.display = 'none';
1085
-
1086
- if (/body/i.test(wwTarget.nodeName)) {
1087
- const wwDiv = _d.createElement('DIV');
1088
- const attrs = wwTarget.attributes;
1089
- for (let i = 0, len = attrs.length; i < len; i++) {
1090
- wwDiv.setAttribute(attrs[i].name, attrs[i].value);
1091
- }
1092
- wwDiv.innerHTML = wwTarget.innerHTML;
1093
- wwTarget = wwDiv;
1094
- } else {
1095
- wwTarget = wwTarget.cloneNode(true);
1096
- }
1097
-
1098
- tempTarget.appendChild(wwTarget);
1099
- _d.body.appendChild(tempTarget);
1100
-
1101
- const elements = wwTarget.querySelectorAll('*');
1102
- for (let i = includeWW ? 0 : 1, el; (el = elements[i]); i++) {
1103
- const computedStyle = _w.getComputedStyle(el);
1104
- for (const props of styles || computedStyle) {
1105
- el.style[props] = computedStyle.getPropertyValue(props) || '';
1106
- }
1107
- }
1108
-
1109
- _d.body.removeChild(tempTarget);
1110
-
1111
- return wwTarget;
1112
- }
1113
-
1114
- const domUtils = {
1115
- isZeroWith,
1116
- createElement,
1117
- createTextNode,
1118
- getIframeDocument,
1119
- getAttributesToString,
1120
- getPositionIndex,
1121
- getNodePath,
1122
- getNodeFromPath,
1123
- getListChildren,
1124
- getListChildNodes,
1125
- getNodeDepth,
1126
- sortNodeByDepth,
1127
- compareElements,
1128
- getParentElement,
1129
- getParentElements,
1130
- getCommandTarget,
1131
- getEdgeChild,
1132
- getEdgeChildNodes,
1133
- getArrayItem,
1134
- arrayIncludes,
1135
- getArrayIndex,
1136
- nextIndex,
1137
- prevIndex,
1138
- copyTagAttributes,
1139
- copyFormatAttributes,
1140
- isSameAttributes,
1141
- removeItem,
1142
- changeElement,
1143
- changeTxt,
1144
- setStyle,
1145
- setDisabled,
1146
- hasClass,
1147
- addClass,
1148
- removeClass,
1149
- toggleClass,
1150
- isEdgePoint,
1151
- isWysiwygFrame,
1152
- isNonEditable,
1153
- isList,
1154
- isListCell,
1155
- isTable,
1156
- isTableElements,
1157
- isTableCell,
1158
- isTableRow,
1159
- isBreak,
1160
- isAnchor,
1161
- isMedia,
1162
- isFigure,
1163
- isInputElement,
1164
- isEmptyLine,
1165
- isSpanWithoutAttr,
1166
- isUneditable,
1167
- isImportantDisabled,
1168
- isExcludeFormat,
1169
- getScrollParent,
1170
- getClientSize,
1171
- getViewportSize,
1172
- getPreviousDeepestNode,
1173
- getNextDeepestNode,
1174
- applyInlineStylesAll
1175
- };
1176
-
1177
- export default domUtils;