suneditor 3.0.0-alpha.2 → 3.0.0-alpha.20
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.
- package/.eslintrc.json +4 -3
- package/CONTRIBUTING.md +4 -2
- package/README.md +19 -11
- package/README_V3_TEMP.md +705 -0
- package/dist/suneditor.min.css +1 -0
- package/dist/suneditor.min.js +1 -0
- package/example.md +587 -0
- package/package.json +15 -9
- package/src/assets/icons/_default.js +166 -131
- package/src/assets/{suneditor-content.css → suneditor-contents.css} +182 -45
- package/src/assets/suneditor.css +1195 -556
- package/src/assets/variables.css +138 -0
- package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
- package/src/core/base/eventHandlers/handler_ww_clipboard.js +29 -4
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +59 -15
- package/src/core/base/eventHandlers/handler_ww_key_input.js +426 -212
- package/src/core/base/eventHandlers/handler_ww_mouse.js +108 -32
- package/src/core/base/eventManager.js +540 -209
- package/src/core/base/events.js +616 -320
- package/src/core/base/history.js +93 -39
- package/src/core/class/char.js +29 -13
- package/src/core/class/component.js +332 -145
- package/src/core/class/format.js +671 -509
- package/src/core/class/html.js +504 -290
- package/src/core/class/menu.js +114 -47
- package/src/core/class/nodeTransform.js +111 -66
- package/src/core/class/offset.js +409 -105
- package/src/core/class/selection.js +220 -108
- package/src/core/class/shortcuts.js +68 -8
- package/src/core/class/toolbar.js +106 -116
- package/src/core/class/ui.js +330 -0
- package/src/core/class/viewer.js +178 -74
- package/src/core/editor.js +489 -384
- package/src/core/section/actives.js +118 -22
- package/src/core/section/constructor.js +504 -170
- package/src/core/section/context.js +28 -23
- package/src/core/section/documentType.js +561 -0
- package/src/editorInjector/_classes.js +19 -5
- package/src/editorInjector/_core.js +71 -7
- package/src/editorInjector/index.js +63 -1
- package/src/helper/converter.js +137 -19
- package/src/helper/dom/domCheck.js +294 -0
- package/src/helper/dom/domQuery.js +609 -0
- package/src/helper/dom/domUtils.js +533 -0
- package/src/helper/dom/index.js +12 -0
- package/src/helper/env.js +42 -19
- package/src/helper/index.js +7 -4
- package/src/helper/keyCodeMap.js +183 -0
- package/src/helper/numbers.js +8 -8
- package/src/helper/unicode.js +5 -5
- package/src/langs/ckb.js +69 -3
- package/src/langs/cs.js +67 -1
- package/src/langs/da.js +68 -2
- package/src/langs/de.js +68 -3
- package/src/langs/en.js +29 -1
- package/src/langs/es.js +68 -3
- package/src/langs/fa.js +70 -2
- package/src/langs/fr.js +68 -2
- package/src/langs/he.js +68 -3
- package/src/langs/hu.js +226 -0
- package/src/langs/index.js +3 -2
- package/src/langs/it.js +65 -0
- package/src/langs/ja.js +68 -3
- package/src/langs/ko.js +66 -1
- package/src/langs/lv.js +68 -3
- package/src/langs/nl.js +68 -3
- package/src/langs/pl.js +68 -3
- package/src/langs/pt_br.js +65 -0
- package/src/langs/ro.js +69 -4
- package/src/langs/ru.js +68 -3
- package/src/langs/se.js +68 -3
- package/src/langs/tr.js +68 -0
- package/src/langs/ua.js +68 -3
- package/src/langs/ur.js +71 -6
- package/src/langs/zh_cn.js +69 -4
- package/src/modules/ApiManager.js +77 -54
- package/src/modules/Browser.js +667 -0
- package/src/modules/ColorPicker.js +162 -102
- package/src/modules/Controller.js +233 -136
- package/src/modules/Figure.js +913 -489
- package/src/modules/FileManager.js +141 -72
- package/src/modules/HueSlider.js +113 -61
- package/src/modules/Modal.js +292 -113
- package/src/modules/ModalAnchorEditor.js +380 -230
- package/src/modules/SelectMenu.js +270 -168
- package/src/modules/_DragHandle.js +2 -1
- package/src/modules/index.js +3 -3
- package/src/plugins/browser/audioGallery.js +83 -0
- package/src/plugins/browser/fileBrowser.js +103 -0
- package/src/plugins/browser/fileGallery.js +83 -0
- package/src/plugins/browser/imageGallery.js +81 -0
- package/src/plugins/browser/videoGallery.js +103 -0
- package/src/plugins/command/blockquote.js +40 -27
- package/src/plugins/command/exportPDF.js +134 -0
- package/src/plugins/command/fileUpload.js +226 -158
- package/src/plugins/command/list_bulleted.js +93 -47
- package/src/plugins/command/list_numbered.js +93 -47
- package/src/plugins/dropdown/align.js +66 -54
- package/src/plugins/dropdown/backgroundColor.js +76 -45
- package/src/plugins/dropdown/font.js +71 -47
- package/src/plugins/dropdown/fontColor.js +78 -46
- package/src/plugins/dropdown/formatBlock.js +74 -33
- package/src/plugins/dropdown/hr.js +102 -51
- package/src/plugins/dropdown/layout.js +37 -26
- package/src/plugins/dropdown/lineHeight.js +54 -38
- package/src/plugins/dropdown/list.js +60 -45
- package/src/plugins/dropdown/paragraphStyle.js +51 -30
- package/src/plugins/dropdown/table.js +1269 -777
- package/src/plugins/dropdown/template.js +38 -26
- package/src/plugins/dropdown/textStyle.js +43 -31
- package/src/plugins/field/mention.js +144 -82
- package/src/plugins/index.js +32 -6
- package/src/plugins/input/fontSize.js +161 -108
- package/src/plugins/input/pageNavigator.js +70 -0
- package/src/plugins/modal/audio.js +341 -169
- package/src/plugins/modal/drawing.js +530 -0
- package/src/plugins/modal/embed.js +886 -0
- package/src/plugins/modal/image.js +673 -358
- package/src/plugins/modal/link.js +100 -71
- package/src/plugins/modal/math.js +384 -168
- package/src/plugins/modal/video.js +693 -336
- package/src/plugins/popup/anchor.js +222 -0
- package/src/suneditor.js +54 -12
- package/src/themes/dark.css +85 -0
- package/src/typedef.js +86 -0
- package/types/assets/icons/_default.d.ts +152 -0
- package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
- package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
- package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
- package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
- package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
- package/types/core/base/eventManager.d.ts +377 -0
- package/types/core/base/events.d.ts +297 -0
- package/types/core/base/history.d.ts +81 -0
- package/types/core/class/char.d.ts +60 -0
- package/types/core/class/component.d.ts +259 -0
- package/types/core/class/format.d.ts +615 -0
- package/types/core/class/html.d.ts +377 -0
- package/types/core/class/menu.d.ts +118 -0
- package/types/core/class/nodeTransform.d.ts +93 -0
- package/types/core/class/offset.d.ts +512 -0
- package/types/core/class/selection.d.ts +188 -0
- package/types/core/class/shortcuts.d.ts +142 -0
- package/types/core/class/toolbar.d.ts +189 -0
- package/types/core/class/ui.d.ts +144 -0
- package/types/core/class/viewer.d.ts +140 -0
- package/types/core/editor.d.ts +606 -0
- package/types/core/section/actives.d.ts +46 -0
- package/types/core/section/constructor.d.ts +748 -0
- package/types/core/section/context.d.ts +45 -0
- package/types/core/section/documentType.d.ts +178 -0
- package/types/editorInjector/_classes.d.ts +41 -0
- package/types/editorInjector/_core.d.ts +92 -0
- package/types/editorInjector/index.d.ts +71 -0
- package/types/helper/converter.d.ts +150 -0
- package/types/helper/dom/domCheck.d.ts +182 -0
- package/types/helper/dom/domQuery.d.ts +214 -0
- package/types/helper/dom/domUtils.d.ts +211 -0
- package/types/helper/dom/index.d.ts +9 -0
- package/types/helper/env.d.ts +149 -0
- package/types/helper/index.d.ts +163 -0
- package/types/helper/keyCodeMap.d.ts +110 -0
- package/types/helper/numbers.d.ts +43 -0
- package/types/helper/unicode.d.ts +28 -0
- package/types/index.d.ts +0 -0
- package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +170 -103
- package/types/langs/ckb.d.ts +384 -0
- package/types/langs/cs.d.ts +384 -0
- package/types/langs/da.d.ts +384 -0
- package/types/langs/de.d.ts +384 -0
- package/types/langs/en.d.ts +384 -0
- package/types/langs/es.d.ts +384 -0
- package/types/langs/fa.d.ts +384 -0
- package/types/langs/fr.d.ts +384 -0
- package/types/langs/he.d.ts +384 -0
- package/types/langs/hu.d.ts +384 -0
- package/types/langs/index.d.ts +48 -0
- package/types/langs/it.d.ts +384 -0
- package/types/langs/ja.d.ts +384 -0
- package/types/langs/ko.d.ts +384 -0
- package/types/langs/lv.d.ts +384 -0
- package/types/langs/nl.d.ts +384 -0
- package/types/langs/pl.d.ts +384 -0
- package/types/langs/pt_br.d.ts +384 -0
- package/types/langs/ro.d.ts +384 -0
- package/types/langs/ru.d.ts +384 -0
- package/types/langs/se.d.ts +384 -0
- package/types/langs/tr.d.ts +384 -0
- package/types/langs/ua.d.ts +384 -0
- package/types/langs/ur.d.ts +384 -0
- package/types/langs/zh_cn.d.ts +384 -0
- package/types/modules/ApiManager.d.ts +125 -0
- package/types/modules/Browser.d.ts +326 -0
- package/types/modules/ColorPicker.d.ts +131 -0
- package/types/modules/Controller.d.ts +231 -0
- package/types/modules/Figure.d.ts +504 -0
- package/types/modules/FileManager.d.ts +202 -0
- package/types/modules/HueSlider.d.ts +136 -0
- package/types/modules/Modal.d.ts +117 -0
- package/types/modules/ModalAnchorEditor.d.ts +236 -0
- package/types/modules/SelectMenu.d.ts +194 -0
- package/types/modules/_DragHandle.d.ts +7 -0
- package/types/modules/index.d.ts +26 -0
- package/types/plugins/browser/audioGallery.d.ts +55 -0
- package/types/plugins/browser/fileBrowser.d.ts +64 -0
- package/types/plugins/browser/fileGallery.d.ts +55 -0
- package/types/plugins/browser/imageGallery.d.ts +51 -0
- package/types/plugins/browser/videoGallery.d.ts +57 -0
- package/types/plugins/command/blockquote.d.ts +28 -0
- package/types/plugins/command/exportPDF.d.ts +46 -0
- package/types/plugins/command/fileUpload.d.ts +156 -0
- package/types/plugins/command/list_bulleted.d.ts +56 -0
- package/types/plugins/command/list_numbered.d.ts +56 -0
- package/types/plugins/dropdown/align.d.ts +60 -0
- package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
- package/types/plugins/dropdown/font.d.ts +54 -0
- package/types/plugins/dropdown/fontColor.d.ts +63 -0
- package/types/plugins/dropdown/formatBlock.d.ts +58 -0
- package/types/plugins/dropdown/hr.d.ts +81 -0
- package/types/plugins/dropdown/layout.d.ts +40 -0
- package/types/plugins/dropdown/lineHeight.d.ts +50 -0
- package/types/plugins/dropdown/list.d.ts +39 -0
- package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
- package/types/plugins/dropdown/table.d.ts +579 -0
- package/types/plugins/dropdown/template.d.ts +40 -0
- package/types/plugins/dropdown/textStyle.d.ts +41 -0
- package/types/plugins/field/mention.d.ts +102 -0
- package/types/plugins/index.d.ts +107 -0
- package/types/plugins/input/fontSize.d.ts +170 -0
- package/types/plugins/input/pageNavigator.d.ts +28 -0
- package/types/plugins/modal/audio.d.ts +269 -0
- package/types/plugins/modal/drawing.d.ts +246 -0
- package/types/plugins/modal/embed.d.ts +387 -0
- package/types/plugins/modal/image.d.ts +451 -0
- package/types/plugins/modal/link.d.ts +128 -0
- package/types/plugins/modal/math.d.ts +193 -0
- package/types/plugins/modal/video.d.ts +485 -0
- package/types/plugins/popup/anchor.d.ts +56 -0
- package/types/suneditor.d.ts +51 -0
- package/types/typedef-global.d.ts +144 -0
- package/src/core/class/notice.js +0 -42
- package/src/helper/domUtils.js +0 -1177
- package/src/modules/FileBrowser.js +0 -271
- package/src/plugins/command/exportPdf.js +0 -168
- package/src/plugins/fileBrowser/imageGallery.js +0 -81
- package/src/themes/test.css +0 -61
- package/typings/CommandPlugin.d.ts +0 -8
- package/typings/DialogPlugin.d.ts +0 -20
- package/typings/FileBrowserPlugin.d.ts +0 -30
- package/typings/Module.d.ts +0 -15
- package/typings/Plugin.d.ts +0 -42
- package/typings/SubmenuPlugin.d.ts +0 -8
- package/typings/_classes.d.ts +0 -17
- package/typings/_colorPicker.d.ts +0 -60
- package/typings/_core.d.ts +0 -55
- package/typings/align.d.ts +0 -5
- package/typings/audio.d.ts +0 -5
- package/typings/backgroundColor.d.ts +0 -5
- package/typings/blockquote.d.ts +0 -5
- package/typings/char.d.ts +0 -39
- package/typings/component.d.ts +0 -38
- package/typings/context.d.ts +0 -39
- package/typings/converter.d.ts +0 -33
- package/typings/dialog.d.ts +0 -28
- package/typings/domUtils.d.ts +0 -361
- package/typings/editor.d.ts +0 -7
- package/typings/editor.ts +0 -542
- package/typings/env.d.ts +0 -70
- package/typings/eventManager.d.ts +0 -37
- package/typings/events.d.ts +0 -262
- package/typings/fileBrowser.d.ts +0 -42
- package/typings/fileManager.d.ts +0 -67
- package/typings/font.d.ts +0 -5
- package/typings/fontColor.d.ts +0 -5
- package/typings/fontSize.d.ts +0 -5
- package/typings/format.d.ts +0 -191
- package/typings/formatBlock.d.ts +0 -5
- package/typings/history.d.ts +0 -48
- package/typings/horizontalRule.d.ts +0 -5
- package/typings/image.d.ts +0 -5
- package/typings/imageGallery.d.ts +0 -5
- package/typings/index.d.ts +0 -21
- package/typings/index.modules.d.ts +0 -11
- package/typings/index.plugins.d.ts +0 -58
- package/typings/lineHeight.d.ts +0 -5
- package/typings/link.d.ts +0 -5
- package/typings/list.d.ts +0 -5
- package/typings/math.d.ts +0 -5
- package/typings/mediaContainer.d.ts +0 -25
- package/typings/mention.d.ts +0 -5
- package/typings/node.d.ts +0 -57
- package/typings/notice.d.ts +0 -16
- package/typings/numbers.d.ts +0 -29
- package/typings/offset.d.ts +0 -24
- package/typings/options.d.ts +0 -589
- package/typings/paragraphStyle.d.ts +0 -5
- package/typings/resizing.d.ts +0 -141
- package/typings/selection.d.ts +0 -94
- package/typings/shortcuts.d.ts +0 -13
- package/typings/suneditor.d.ts +0 -9
- package/typings/table.d.ts +0 -5
- package/typings/template.d.ts +0 -5
- package/typings/textStyle.d.ts +0 -5
- package/typings/toolbar.d.ts +0 -32
- package/typings/unicode.d.ts +0 -25
- package/typings/video.d.ts +0 -5
|
@@ -0,0 +1,533 @@
|
|
|
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
|
+
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 Gets the size of the documentElement client size.
|
|
372
|
+
* @param {Document} doc Document object
|
|
373
|
+
* @returns {{w: number, h: number}} documentElement.clientWidth, documentElement.clientHeight
|
|
374
|
+
*/
|
|
375
|
+
export function getClientSize(doc = _d) {
|
|
376
|
+
return {
|
|
377
|
+
w: doc.documentElement.clientWidth,
|
|
378
|
+
h: doc.documentElement.clientHeight
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* @description Gets the size of the window visualViewport size
|
|
384
|
+
* @returns {{top: number, left: number, scale: number}}
|
|
385
|
+
*/
|
|
386
|
+
export function getViewportSize() {
|
|
387
|
+
if ('visualViewport' in _w) {
|
|
388
|
+
return {
|
|
389
|
+
top: _w.visualViewport.pageTop,
|
|
390
|
+
left: _w.visualViewport.pageLeft,
|
|
391
|
+
scale: _w.visualViewport.scale
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
top: 0,
|
|
397
|
+
left: 0,
|
|
398
|
+
scale: 1
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* @description Copies the "wwTarget" element and returns it with inline all styles applied.
|
|
404
|
+
* @param {Node} wwTarget Target element to copy(.sun-editor.sun-editor-editable)
|
|
405
|
+
* @param {boolean} includeWW Include the "wwTarget" element in the copy
|
|
406
|
+
* @param {Array<string>} styles Style list - kamel case
|
|
407
|
+
* @returns
|
|
408
|
+
*/
|
|
409
|
+
export function applyInlineStylesAll(wwTarget, includeWW, styles) {
|
|
410
|
+
if (!wwTarget) {
|
|
411
|
+
console.warn('"parentTarget" is not exist');
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
let ww = /** @type {HTMLElement} */ (wwTarget);
|
|
416
|
+
const tempTarget = _d.createElement('DIV');
|
|
417
|
+
tempTarget.style.display = 'none';
|
|
418
|
+
|
|
419
|
+
if (/body/i.test(ww.nodeName)) {
|
|
420
|
+
const wwDiv = _d.createElement('DIV');
|
|
421
|
+
const attrs = ww.attributes;
|
|
422
|
+
for (let i = 0, len = attrs.length; i < len; i++) {
|
|
423
|
+
wwDiv.setAttribute(attrs[i].name, attrs[i].value);
|
|
424
|
+
}
|
|
425
|
+
wwDiv.innerHTML = ww.innerHTML;
|
|
426
|
+
ww = wwDiv;
|
|
427
|
+
} else {
|
|
428
|
+
ww = /** @type {HTMLElement} */ (ww.cloneNode(true));
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
tempTarget.appendChild(ww);
|
|
432
|
+
_d.body.appendChild(tempTarget);
|
|
433
|
+
|
|
434
|
+
/** @type {HTMLElement[]} */
|
|
435
|
+
const allElements = Array.from(ww.querySelectorAll('*'));
|
|
436
|
+
const elements = includeWW ? [ww].concat(allElements) : allElements;
|
|
437
|
+
for (let i = 0, el; (el = elements[i]); i++) {
|
|
438
|
+
if (el.nodeType !== 1) continue;
|
|
439
|
+
const computedStyle = _w.getComputedStyle(el);
|
|
440
|
+
const els = el.style;
|
|
441
|
+
for (const props of styles) {
|
|
442
|
+
els.setProperty(props, computedStyle.getPropertyValue(props) || '');
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
_d.body.removeChild(tempTarget);
|
|
447
|
+
|
|
448
|
+
return ww;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* @description Wait for media elements to load
|
|
453
|
+
* @param {Node} target Target element
|
|
454
|
+
* @param {number} timeout Timeout milliseconds
|
|
455
|
+
* @returns {Promise<void>}
|
|
456
|
+
*/
|
|
457
|
+
function waitForMediaLoad(target, timeout = 5000) {
|
|
458
|
+
const doc = /** @type {HTMLElement|Document} */ (target || _d);
|
|
459
|
+
return new Promise((resolveAll) => {
|
|
460
|
+
const selectors = ['img', 'video', 'audio', 'iframe'];
|
|
461
|
+
const mediaElements = selectors.flatMap((selector) => Array.from(doc.querySelectorAll(selector)));
|
|
462
|
+
|
|
463
|
+
if (mediaElements.length === 0) {
|
|
464
|
+
resolveAll();
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const mediaPromises = mediaElements.map((element) => {
|
|
469
|
+
// image
|
|
470
|
+
if (element instanceof HTMLImageElement) {
|
|
471
|
+
if (element.complete) {
|
|
472
|
+
return Promise.resolve();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
// video, audio
|
|
476
|
+
else if (element instanceof HTMLMediaElement) {
|
|
477
|
+
if (element.readyState >= 2) {
|
|
478
|
+
return Promise.resolve();
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
// iframe
|
|
482
|
+
else if (element instanceof HTMLIFrameElement) {
|
|
483
|
+
try {
|
|
484
|
+
if (element.contentDocument?.readyState === 'complete') {
|
|
485
|
+
return Promise.resolve();
|
|
486
|
+
}
|
|
487
|
+
} catch (e) {
|
|
488
|
+
console.warn(['[SUNEDITOR] Iframe load error', e]);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// load event
|
|
493
|
+
return new Promise((resolve) => {
|
|
494
|
+
element.addEventListener('load', resolve, { once: true });
|
|
495
|
+
element.addEventListener('error', resolve, { once: true });
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
Promise.race([Promise.all(mediaPromises), new Promise((resolve) => setTimeout(resolve, timeout))]).then(() => {
|
|
500
|
+
resolveAll();
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const utils = {
|
|
506
|
+
clone,
|
|
507
|
+
createElement,
|
|
508
|
+
createTextNode,
|
|
509
|
+
getAttributesToString,
|
|
510
|
+
arrayFilter,
|
|
511
|
+
arrayFind,
|
|
512
|
+
arrayIncludes,
|
|
513
|
+
getArrayIndex,
|
|
514
|
+
nextIndex,
|
|
515
|
+
prevIndex,
|
|
516
|
+
copyTagAttributes,
|
|
517
|
+
copyFormatAttributes,
|
|
518
|
+
removeItem,
|
|
519
|
+
changeElement,
|
|
520
|
+
changeTxt,
|
|
521
|
+
setStyle,
|
|
522
|
+
setDisabled,
|
|
523
|
+
hasClass,
|
|
524
|
+
addClass,
|
|
525
|
+
removeClass,
|
|
526
|
+
toggleClass,
|
|
527
|
+
getClientSize,
|
|
528
|
+
getViewportSize,
|
|
529
|
+
applyInlineStylesAll,
|
|
530
|
+
waitForMediaLoad
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
export default utils;
|
package/src/helper/env.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
|
+
/** @type {Window} */
|
|
1
2
|
export const _w = window;
|
|
3
|
+
/** @type {Document} */
|
|
2
4
|
export const _d = document;
|
|
3
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @description No event symbol
|
|
8
|
+
* @type {Symbol}
|
|
9
|
+
*/
|
|
4
10
|
export const NO_EVENT = Symbol('noEventHandler');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @description On over component symbol
|
|
14
|
+
* @type {Symbol}
|
|
15
|
+
*/
|
|
5
16
|
export const ON_OVER_COMPONENT = Symbol('onOverComponent');
|
|
6
17
|
|
|
7
18
|
const userAgent = _w.navigator.userAgent.toLowerCase();
|
|
8
19
|
|
|
9
20
|
/**
|
|
10
21
|
* @description Object.values
|
|
11
|
-
* @param {Object
|
|
12
|
-
* @returns {Array
|
|
22
|
+
* @param {Object<*, *>} obj Object parameter.
|
|
23
|
+
* @returns {Array<*>}
|
|
13
24
|
*/
|
|
14
25
|
export function getValues(obj) {
|
|
15
26
|
return !obj
|
|
@@ -21,7 +32,7 @@ export function getValues(obj) {
|
|
|
21
32
|
|
|
22
33
|
/**
|
|
23
34
|
* @description Convert the CamelCase To the KebabCase.
|
|
24
|
-
* @param {string|Array
|
|
35
|
+
* @param {string|Array<string>} param [Camel string]
|
|
25
36
|
*/
|
|
26
37
|
export function camelToKebabCase(param) {
|
|
27
38
|
if (typeof param === 'string') {
|
|
@@ -34,9 +45,14 @@ export function camelToKebabCase(param) {
|
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
/**
|
|
37
|
-
* @
|
|
38
|
-
* @param {
|
|
39
|
-
* @returns {
|
|
48
|
+
* @overload
|
|
49
|
+
* @param {string} param - Kebab-case string.
|
|
50
|
+
* @returns {string} CamelCase string.
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* @overload
|
|
54
|
+
* @param {Array<string>} param - Array of Kebab-case strings.
|
|
55
|
+
* @returns {Array<string>} Array of CamelCase strings.
|
|
40
56
|
*/
|
|
41
57
|
export function kebabToCamelCase(param) {
|
|
42
58
|
if (typeof param === 'string') {
|
|
@@ -50,7 +66,7 @@ export function kebabToCamelCase(param) {
|
|
|
50
66
|
|
|
51
67
|
/**
|
|
52
68
|
* @description Gets XMLHttpRequest object
|
|
53
|
-
* @returns {XMLHttpRequest
|
|
69
|
+
* @returns {XMLHttpRequest}
|
|
54
70
|
*/
|
|
55
71
|
export function getXMLHttpRequest() {
|
|
56
72
|
return new XMLHttpRequest();
|
|
@@ -86,10 +102,9 @@ export function getPageStyle(doc) {
|
|
|
86
102
|
/**
|
|
87
103
|
* @deprecated
|
|
88
104
|
* @description Get the the tag path of the arguments value
|
|
89
|
-
*
|
|
90
|
-
* @param {Array.<string>} nameArray File name array
|
|
105
|
+
* @param {Array<string>} nameArray File name array
|
|
91
106
|
* @param {string} extension js, css
|
|
92
|
-
* @returns {string}
|
|
107
|
+
* @returns {string} If not found, return the first found value
|
|
93
108
|
*/
|
|
94
109
|
export function getIncludePath(nameArray, extension) {
|
|
95
110
|
let path = '';
|
|
@@ -122,7 +137,7 @@ export function getIncludePath(nameArray, extension) {
|
|
|
122
137
|
if (path === '') path = pathList.length > 0 ? pathList[0][src] : '';
|
|
123
138
|
|
|
124
139
|
if (!path.includes(':/') && '//' !== path.slice(0, 2)) {
|
|
125
|
-
path =
|
|
140
|
+
path = false === path.includes('/') ? location.href.match(/^.*?:\/\/[^/]*/)[0] + path : location.href.match(/^[^?]*\/(?:)/)[0] + path;
|
|
126
141
|
}
|
|
127
142
|
|
|
128
143
|
if (!path) {
|
|
@@ -146,15 +161,15 @@ export const isResizeObserverSupported = (() => {
|
|
|
146
161
|
* @returns {boolean} Whether User Agent is Edge or not.
|
|
147
162
|
*/
|
|
148
163
|
export const isEdge = (() => {
|
|
149
|
-
return navigator.
|
|
164
|
+
return /Edg/.test(navigator.userAgent);
|
|
150
165
|
})();
|
|
151
166
|
|
|
152
167
|
/**
|
|
153
|
-
* @description Check if
|
|
168
|
+
* @description Check if User Agent is OSX or IOS
|
|
154
169
|
* @type {boolean}
|
|
155
170
|
*/
|
|
156
171
|
export const isOSX_IOS = (() => {
|
|
157
|
-
return /(Mac|iPhone|iPod|iPad)/.test(navigator.
|
|
172
|
+
return /(Mac|iPhone|iPod|iPad)/.test(navigator.userAgent);
|
|
158
173
|
})();
|
|
159
174
|
|
|
160
175
|
/**
|
|
@@ -178,7 +193,7 @@ export const isGecko = (() => {
|
|
|
178
193
|
* @type {boolean}
|
|
179
194
|
*/
|
|
180
195
|
export const isChromium = (() => {
|
|
181
|
-
return !!
|
|
196
|
+
return !!(/** @type {Window & { chrome: any }} */ (_w).chrome);
|
|
182
197
|
})();
|
|
183
198
|
|
|
184
199
|
/**
|
|
@@ -191,11 +206,11 @@ export const isSafari = (() => {
|
|
|
191
206
|
|
|
192
207
|
/**
|
|
193
208
|
* @description Check if User Agent is Mobile device.
|
|
194
|
-
* when the device is touchable, it is judged as a mobile device.
|
|
209
|
+
* - when the device is touchable, it is judged as a mobile device.
|
|
195
210
|
* @type {boolean}
|
|
196
211
|
*/
|
|
197
212
|
export const isMobile = (() => {
|
|
198
|
-
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent) ||
|
|
213
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent) || (navigator.maxTouchPoints > 0 && 'ontouchstart' in _w);
|
|
199
214
|
})();
|
|
200
215
|
|
|
201
216
|
/**
|
|
@@ -218,9 +233,15 @@ export const cmdIcon = isOSX_IOS ? '⌘' : 'CTRL';
|
|
|
218
233
|
*/
|
|
219
234
|
export const shiftIcon = isOSX_IOS ? '⇧' : '+SHIFT';
|
|
220
235
|
|
|
236
|
+
/**
|
|
237
|
+
* @description Device pixel ratio
|
|
238
|
+
* @type {number}
|
|
239
|
+
*/
|
|
240
|
+
export const DPI = _w.devicePixelRatio;
|
|
241
|
+
|
|
221
242
|
/** --- editor env --- */
|
|
222
|
-
export const _allowedEmptyNodeList = '.se-component, pre, blockquote, hr, li, table, img, iframe, video, audio, canvas, details';
|
|
223
243
|
export const KATEX_WEBSITE = 'https://katex.org/docs/supported.html';
|
|
244
|
+
export const MATHJAX_WEBSITE = 'https://www.mathjax.org/';
|
|
224
245
|
|
|
225
246
|
const env = {
|
|
226
247
|
_w,
|
|
@@ -244,7 +265,9 @@ const env = {
|
|
|
244
265
|
isMobile,
|
|
245
266
|
cmdIcon,
|
|
246
267
|
shiftIcon,
|
|
247
|
-
|
|
268
|
+
DPI,
|
|
269
|
+
KATEX_WEBSITE,
|
|
270
|
+
MATHJAX_WEBSITE
|
|
248
271
|
};
|
|
249
272
|
|
|
250
273
|
export default env;
|