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,102 +1,205 @@
1
1
  import EditorInjector from '../../editorInjector';
2
2
  import { Modal, Controller } from '../../modules';
3
- import { domUtils, env, converter } from '../../helper';
3
+ import { dom, env, converter } from '../../helper';
4
+
5
+ const { _w } = env;
6
+
7
+ /**
8
+ * @typedef {Object} MathPluginOptions
9
+ * @property {boolean} [canResize=true] - Whether the math modal can be resized.
10
+ * @property {boolean} [autoHeight=false] - Whether to automatically adjust the height of the modal.
11
+ * @property {Array<object>} [fontSizeList] - A list of font size options for rendering math expressions.
12
+ * @property {(...args: *) => *} [onPaste] - A callback function to handle paste events in the math input area.
13
+ * @property {Object} [formSize={}] - An object specifying the dimensions for the math modal.
14
+ * @property {string} [formSize.width="460px"] - The default width of the math modal.
15
+ * @property {string} [formSize.height="14em"] - The default height of the math modal.
16
+ * @property {string} [formSize.maxWidth] - The maximum width of the math modal.
17
+ * @property {string} [formSize.maxHeight] - The maximum height of the math modal.
18
+ * @property {string} [formSize.minWidth="400px"] - The minimum width of the math modal.
19
+ * @property {string} [formSize.minHeight="40px"] - The minimum height of the math modal.
20
+ */
21
+
22
+ /**
23
+ * @class
24
+ * @description Math plugin.
25
+ * - This plugin provides support for rendering mathematical expressions using either the KaTeX or MathJax libraries.
26
+ * - If external library is provided, a warning is issued.
27
+ */
28
+ class Math_ extends EditorInjector {
29
+ static key = 'math';
30
+ static type = 'modal';
31
+ static className = '';
32
+ /**
33
+ * @this {Math_}
34
+ * @param {HTMLElement} node - The node to check.
35
+ * @returns {HTMLElement|null} Returns a node if the node is a valid component.
36
+ */
37
+ static component(node) {
38
+ return dom.utils.hasClass(node, 'se-math|katex') && dom.utils.hasClass(node, 'se-component') ? node : null;
39
+ }
40
+
41
+ /**
42
+ * @constructor
43
+ * @param {__se__EditorCore} editor - The root editor instance
44
+ * @param {MathPluginOptions} pluginOptions
45
+ */
46
+ constructor(editor, pluginOptions) {
47
+ // plugin basic properties
48
+ super(editor);
49
+ this.title = this.lang.math;
50
+ this.icon = 'math';
51
+
52
+ // external library
53
+ this.katex = null;
54
+ this.mathjax = null;
55
+
56
+ // exception
57
+ if (!(this.katex = this.#CheckKatex(editor.options.get('externalLibs').katex)) && !(this.mathjax = this.#CheckMathJax(editor.options.get('externalLibs').mathjax, editor))) {
58
+ console.warn('[SUNEDITOR.plugins.math.warn] The math plugin must need either "KaTeX" or "MathJax" library. Please add the katex or mathjax option.');
59
+ }
60
+
61
+ this.pluginOptions = {
62
+ formSize: {
63
+ width: '460px',
64
+ height: '14em',
65
+ maxWidth: '',
66
+ maxHeight: '',
67
+ minWidth: '400px',
68
+ minHeight: '40px',
69
+ ...pluginOptions.formSize
70
+ },
71
+ canResize: pluginOptions.canResize ?? true,
72
+ autoHeight: !!pluginOptions.autoHeight,
73
+ fontSizeList: pluginOptions.fontSizeList || [
74
+ {
75
+ text: '1',
76
+ value: '1em'
77
+ },
78
+ {
79
+ text: '1.5',
80
+ value: '1.5em'
81
+ },
82
+ {
83
+ text: '2',
84
+ value: '2em'
85
+ },
86
+ {
87
+ text: '2.5',
88
+ value: '2.5em'
89
+ }
90
+ ],
91
+ onPaste: typeof pluginOptions.onPaste === 'function' ? pluginOptions.onPaste : null
92
+ };
93
+ if (this.pluginOptions.autoHeight) {
94
+ this.pluginOptions.formSize.height = this.pluginOptions.formSize.minHeight;
95
+ }
4
96
 
5
- const Math_ = function (editor, pluginOptions) {
6
- // exception
7
- if (!(this.katex = CheckKatex(editor.options.get('externalLibs').katex))) {
8
- console.warn('[SUNEDITOR.plugins.math.warn] The math plugin must need the "KaTeX" library, Please add the katex option.');
97
+ // create HTML
98
+ this.defaultFontSize = null;
99
+ const modalEl = CreateHTML_modal(this);
100
+ const controllerEl = CreateHTML_controller(editor);
101
+
102
+ // modules
103
+ this.modal = new Modal(this, modalEl);
104
+ this.controller = new Controller(this, controllerEl, { position: 'bottom', disabled: true });
105
+
106
+ // members
107
+ /** @type {HTMLTextAreaElement} */
108
+ this.textArea = modalEl.querySelector('.se-math-exp');
109
+ /** @type {HTMLPreElement} */
110
+ this.previewElement = modalEl.querySelector('.se-math-preview');
111
+ /** @type {HTMLSelectElement} */
112
+ this.fontSizeElement = modalEl.querySelector('.se-math-size');
113
+
114
+ this.isUpdateState = false;
115
+ this._element = null;
116
+
117
+ // init
118
+ this.previewElement.style.fontSize = this.defaultFontSize;
119
+ this.eventManager.addEvent(this.textArea, 'input', this.#RenderMathExp.bind(this));
120
+ this.eventManager.addEvent(
121
+ this.fontSizeElement,
122
+ 'change',
123
+ function (e) {
124
+ this.fontSize = e.target.value;
125
+ }.bind(this.previewElement.style)
126
+ );
127
+ if (this.pluginOptions.onPaste) {
128
+ this.eventManager.addEvent(this.textArea, 'paste', this.pluginOptions.onPaste.bind(this));
129
+ }
9
130
  }
10
131
 
11
- // plugin bisic properties
12
- EditorInjector.call(this, editor);
13
- this.title = this.lang.math;
14
- this.icon = 'math';
15
-
16
- // create HTML
17
- const modalEl = CreateHTML_modal(editor, this, pluginOptions.fontSizeList);
18
- const controllerEl = CreateHTML_controller(editor);
19
-
20
- // modules
21
- this.modal = new Modal(this, modalEl);
22
- this.controller = new Controller(this, controllerEl, { position: 'bottom', disabled: true });
23
-
24
- // members
25
- this.textArea = modalEl.querySelector('.se-math-exp');
26
- this.previewElement = modalEl.querySelector('.se-math-preview');
27
- this.fontSizeElement = modalEl.querySelector('.se-math-size');
28
- this.isUpdateState = false;
29
- this._element = null;
30
-
31
- // init
32
- this.previewElement.style.fontSize = this.defaultFontSize;
33
- this.eventManager.addEvent(this.textArea, 'input', RenderMathExp.bind(this));
34
- this.eventManager.addEvent(
35
- this.fontSizeElement,
36
- 'change',
37
- function (e) {
38
- this.fontSize = e.target.value;
39
- }.bind(this.previewElement.style)
40
- );
41
- };
42
-
43
- Math_.key = 'math';
44
- Math_.type = 'modal';
45
- Math_.className = '';
46
- Math_.component = function (node) {
47
- return domUtils.hasClass(node, 'katex|se-component') ? node : null;
48
- };
49
- Math_.prototype = {
50
132
  /**
51
- * @override component, fileManager
52
- * @description Called when a container is selected.
53
- * @param {Element} element Target element
133
+ * @editorMethod Editor.component
134
+ * @description Executes the method that is called when a component of a plugin is selected.
135
+ * @param {HTMLElement} target Target component element
54
136
  */
55
- select(element) {
56
- if (domUtils.hasClass(element, 'katex') && getValue(element)) {
57
- this._element = element;
58
- this.controller.open(element, null, { isWWTarget: false, initMethod: null, addOffset: null });
137
+ select(target) {
138
+ if (dom.utils.hasClass(target, 'se-math|katex') && getValue(target)) {
139
+ this._element = target;
140
+ this.controller.open(target, null, { isWWTarget: false, initMethod: null, addOffset: null });
59
141
  return;
60
142
  }
61
- },
143
+ }
62
144
 
63
145
  /**
64
- * @override controller
146
+ * @editorMethod Modules.Controller
147
+ * @description This function is called before the "controller" before it is closed.
65
148
  */
66
149
  close() {
67
150
  this._element = null;
68
- },
151
+ }
69
152
 
70
153
  /**
71
- * @override core
154
+ * @editorMethod Editor.core
155
+ * @description This method is used to validate and preserve the format of the component within the editor.
156
+ * - It ensures that the structure and attributes of the element are maintained and secure.
157
+ * - The method checks if the element is already wrapped in a valid container and updates its attributes if necessary.
158
+ * - If the element isn't properly contained, a new container is created to retain the format.
159
+ * @returns {{query: string, method: (element: HTMLElement) => void}} The format retention object containing the query and method to process the element.
160
+ * - query: The selector query to identify the relevant elements (in this case, 'audio').
161
+ * - method:The function to execute on the element to validate and preserve its format.
162
+ * - The function takes the element as an argument, checks if it is contained correctly, and applies necessary adjustments.
72
163
  */
73
164
  retainFormat() {
74
165
  return {
75
- query: '.katex',
166
+ query: '.se-math, .katex, .MathJax',
76
167
  method: (element) => {
77
- if (!this.katex) return;
168
+ if (!this.katex && !this.mathjax) return;
78
169
 
79
170
  const value = getValue(element);
80
171
  if (!value) return;
81
172
 
82
- const dom = this._d.createRange().createContextualFragment(this._renderer(converter.entityToHTML(this._escapeBackslashes(value, true))));
83
- element.innerHTML = dom.querySelector('.katex').innerHTML;
84
- element.setAttribute('contenteditable', false);
85
- domUtils.addClass(element, 'se-component|se-inline-component|se-disable-pointer');
173
+ const domParser = this._d.createRange().createContextualFragment(this._renderer(converter.entityToHTML(this._escapeBackslashes(value, true))));
174
+ element.innerHTML = domParser.querySelector('.se-math, .katex').innerHTML;
175
+ element.setAttribute('contenteditable', 'false');
176
+ dom.utils.addClass(element, 'se-component|se-inline-component|se-disable-pointer|se-math');
177
+
178
+ if (this.katex) {
179
+ dom.utils.addClass(element, 'katex');
180
+ } else {
181
+ dom.utils.removeClass(element, 'katex');
182
+ }
183
+
184
+ if (this.mathjax) {
185
+ this.#renderMathJax(this.mathjax);
186
+ }
86
187
  }
87
188
  };
88
- },
189
+ }
89
190
 
90
191
  /**
91
- * @override type = "modal"
192
+ * @editorMethod Modules.Modal
193
+ * @description Executes the method that is called when a "Modal" module's is opened.
92
194
  */
93
195
  open() {
94
196
  this.modal.open();
95
- },
197
+ }
96
198
 
97
199
  /**
98
- * @override modal
99
- * @param {boolean} isUpdate open state is update
200
+ * @editorMethod Modules.Modal
201
+ * @description Executes the method that is called when a plugin's modal is opened.
202
+ * @param {boolean} isUpdate "Indicates whether the modal is for editing an existing component (true) or registering a new one (false)."
100
203
  */
101
204
  on(isUpdate) {
102
205
  this.isUpdateState = isUpdate;
@@ -111,56 +214,83 @@ Math_.prototype = {
111
214
  this.previewElement.innerHTML = this._renderer(exp);
112
215
  this.previewElement.style.fontSize = fontSize;
113
216
  }
114
- },
217
+ }
115
218
 
116
219
  /**
117
- * @override modal
118
- * @returns {boolean | undefined}
220
+ * @editorMethod Modules.Modal
221
+ * @description This function is called when a form within a modal window is "submit".
222
+ * @returns {boolean} Success or failure
119
223
  */
120
224
  modalAction() {
121
- if (this.textArea.value.trim().length === 0) return false;
225
+ if (this.textArea.value.trim().length === 0 || dom.utils.hasClass(this.textArea, 'se-error')) {
226
+ this.textArea.focus();
227
+ return false;
228
+ }
122
229
 
123
230
  const mathExp = this.textArea.value;
124
- const katexEl = this.previewElement.querySelector('.katex');
125
231
 
126
- if (!katexEl) return false;
127
- katexEl.className = 'se-component se-inline-component __se__katex ' + katexEl.className;
128
- katexEl.setAttribute('contenteditable', false);
129
- katexEl.setAttribute('data-se-value', converter.htmlToEntity(this._escapeBackslashes(mathExp, false)));
130
- katexEl.setAttribute('data-se-type', this.fontSizeElement.value);
131
- katexEl.style.fontSize = this.fontSizeElement.value;
232
+ /** @type {HTMLSpanElement} */
233
+ const mathEl = this.previewElement.querySelector('.se-math, .katex');
234
+
235
+ if (!mathEl) return false;
236
+ dom.utils.addClass(mathEl, 'se-component|se-inline-component|se-disable-pointer|se-math');
237
+ mathEl.setAttribute('contenteditable', 'false');
238
+ mathEl.setAttribute('data-se-value', converter.htmlToEntity(this._escapeBackslashes(mathExp, false)));
239
+ mathEl.setAttribute('data-se-type', this.fontSizeElement.value);
240
+ mathEl.style.fontSize = this.fontSizeElement.value;
241
+
242
+ if (this.katex) {
243
+ dom.utils.addClass(mathEl, 'katex');
244
+ dom.utils.removeClass(mathEl, 'MathJax');
245
+ } else {
246
+ dom.utils.removeClass(mathEl, 'katex');
247
+ }
132
248
 
133
249
  if (!this.isUpdateState) {
134
250
  const selectedFormats = this.format.getLines();
135
251
 
136
252
  if (selectedFormats.length > 1) {
137
- const oFormat = domUtils.createElement(selectedFormats[0].nodeName, null, katexEl);
138
- this.component.insert(oFormat, false, false);
253
+ const oFormat = dom.utils.createElement(selectedFormats[0].nodeName, null, mathEl);
254
+ this.component.insert(oFormat, { skipCharCount: false, skipSelection: true, skipHistory: false });
139
255
  } else {
140
- this.component.insert(katexEl, false, false);
256
+ this.component.insert(mathEl, { skipCharCount: false, skipSelection: true, skipHistory: false });
141
257
  }
142
258
  } else {
143
- const containerEl = domUtils.getParentElement(this.controller.currentTarget, '.katex');
144
- containerEl.parentNode.replaceChild(katexEl, containerEl);
145
- const compInfo = this.component.get(katexEl);
146
- this.component.select(compInfo.target, compInfo.pluginName, false);
259
+ const containerEl = dom.query.getParentElement(this.controller.currentTarget, '.se-component');
260
+ containerEl.replaceWith(mathEl);
261
+ const compInfo = this.component.get(mathEl);
262
+ this.component.select(compInfo.target, compInfo.pluginName);
263
+ return true;
264
+ }
265
+
266
+ if (this.mathjax) {
267
+ this.#renderMathJax(this.mathjax);
268
+ }
269
+
270
+ const r = this.selection.getNearRange(mathEl);
271
+ if (r) {
272
+ this.selection.setRange(r.container, r.offset, r.container, r.offset);
273
+ } else {
274
+ this.component.select(mathEl, Math_.key);
147
275
  }
148
276
 
149
277
  return true;
150
- },
278
+ }
151
279
 
152
280
  /**
153
- * @override modal
281
+ * @editorMethod Modules.Modal
282
+ * @description This function is called before the modal window is opened, but before it is closed.
154
283
  */
155
284
  init() {
156
285
  this.textArea.value = '';
157
286
  this.previewElement.innerHTML = '';
158
- },
287
+ dom.utils.removeClass(this.textArea, 'se-error');
288
+ }
159
289
 
160
290
  /**
161
- * @override controller
162
- * @param {Element} target Target button element
163
- * @returns
291
+ * @editorMethod Modules.Controller
292
+ * @description Executes the method that is called when a button is clicked in the "controller".
293
+ * @param {HTMLButtonElement} target Target button element
164
294
  */
165
295
  controllerAction(target) {
166
296
  const command = target.getAttribute('data-command');
@@ -169,103 +299,173 @@ Math_.prototype = {
169
299
  this.modal.open();
170
300
  break;
171
301
  case 'copy':
172
- copyTextToClipboard(this._element);
302
+ this.#copyTextToClipboard(this._element);
173
303
  break;
174
304
  case 'delete':
175
305
  this.destroy(this.controller.currentTarget);
176
306
  }
177
- },
307
+ }
178
308
 
179
- destroy(element) {
180
- domUtils.removeItem(element);
309
+ /**
310
+ * @editorMethod Editor.Component
311
+ * @description Method to delete a component of a plugin, called by the "FileManager", "Controller" module.
312
+ * @param {Node} target Target element
313
+ */
314
+ destroy(target) {
315
+ dom.utils.removeItem(target);
181
316
  this.controller.close();
182
317
  this.editor.focus();
183
318
  this.history.push(false);
184
- },
319
+ }
185
320
 
321
+ /**
322
+ * @private
323
+ * @description Renders the given math expression using KaTeX or MathJax.
324
+ * @param {string} exp - The math expression to render.
325
+ * @returns {string} - The rendered math expression as HTML.
326
+ */
186
327
  _renderer(exp) {
187
328
  let result = '';
188
329
  try {
189
- domUtils.removeClass(this.textArea, 'se-error');
190
- result = this.katex.src.renderToString(exp, { throwOnError: true, displayMode: true });
330
+ dom.utils.removeClass(this.textArea, 'se-error');
331
+ if (this.katex) {
332
+ result = this.katex.src.renderToString(exp, { throwOnError: true, displayMode: true });
333
+ } else if (this.mathjax) {
334
+ result = this.mathjax.convert(exp).outerHTML;
335
+ if (/<mjx-merror/.test(result)) {
336
+ dom.utils.addClass(this.textArea, 'se-error');
337
+ result = `<span class="se-math-error">${result}</span>`;
338
+ } else {
339
+ result = `<span class="se-math">${result}</span>`;
340
+ }
341
+ }
191
342
  } catch (error) {
192
- domUtils.addClass(this.textArea, 'se-error');
193
- result = '<span class="se-math-katex-error">Katex syntax error. (Refer <a href="' + env.KATEX_WEBSITE + '" target="_blank">KaTeX</a>)</span>';
194
- console.warn('[SUNEDITOR.math.Katex.error] ', error.message);
343
+ dom.utils.addClass(this.textArea, 'se-error');
344
+ result = `<span class="se-math-error">Math syntax error. (Refer ${this.katex ? `<a href="${env.KATEX_WEBSITE}" target="_blank">KaTeX</a>` : `<a href="${env.MATHJAX_WEBSITE}" target="_blank">MathJax</a>`})</span>`;
345
+ console.warn('[SUNEDITOR.math.error] ', error.message);
195
346
  }
196
347
  return result;
197
- },
348
+ }
198
349
 
350
+ /**
351
+ * @private
352
+ * @description Escapes or unescapes backslashes in a given string.
353
+ * @param {string} str - The input string.
354
+ * @param {boolean} decode - If true, decodes escaped backslashes; otherwise, encodes them.
355
+ * @returns {string} - The processed string.
356
+ */
199
357
  _escapeBackslashes(str, decode) {
200
358
  return str.replace(/\\{2}/g, decode ? '\\' : '\\\\');
201
- },
202
-
203
- constructor: Math_
204
- };
205
-
206
- async function copyTextToClipboard(element) {
207
- if (!navigator.clipboard || !element) return;
208
-
209
- try {
210
- const text = getValue(element);
211
- await navigator.clipboard.writeText(text);
212
- domUtils.addClass(element, 'se-copy');
213
- // copy effect
214
- env._w.setTimeout(() => {
215
- domUtils.removeClass(element, 'se-copy');
216
- }, 120);
217
- } catch (err) {
218
- console.error('[SUNEDITOR.math.copy.fail]', err);
219
359
  }
220
- }
221
360
 
222
- function RenderMathExp(e) {
223
- this.previewElement.innerHTML = this._renderer(e.target.value);
224
- }
361
+ /**
362
+ * @description Copies the math expression text to clipboard.
363
+ * @param {Node} element - The math expression element.
364
+ * @returns {Promise<void>}
365
+ */
366
+ async #copyTextToClipboard(element) {
367
+ if (!navigator.clipboard || !element) return;
225
368
 
226
- function CheckKatex(katex) {
227
- if (!katex) return null;
228
- if (!katex.src) {
229
- console.warn('[SUNEDITOR.math.katex.fail] The katex option is set incorrectly.');
230
- return null;
369
+ try {
370
+ const text = getValue(element);
371
+ await this.html.copy(text);
372
+ dom.utils.addClass(element, 'se-copy');
373
+ // copy effect
374
+ _w.setTimeout(() => {
375
+ dom.utils.removeClass(element, 'se-copy');
376
+ }, 120);
377
+ } catch (err) {
378
+ console.error('[SUNEDITOR.math.copy.fail]', err);
379
+ }
231
380
  }
232
381
 
233
- const katexOptions = [
234
- {
235
- throwOnError: false
236
- },
237
- katex.options || {}
238
- ].reduce((init, option) => {
239
- for (const key in option) {
240
- init[key] = option[key];
382
+ /**
383
+ * @description Handles rendering of math expressions in the preview.
384
+ * @param {InputEvent} e - The input event.
385
+ */
386
+ #RenderMathExp(e) {
387
+ /** @type {HTMLInputElement} */
388
+ const eventTarget = dom.query.getEventTarget(e);
389
+ if (this.pluginOptions.autoHeight) {
390
+ eventTarget.style.height = '5px';
391
+ eventTarget.style.height = eventTarget.scrollHeight + 5 + 'px';
241
392
  }
242
- return init;
243
- }, {});
244
393
 
245
- katex.options = katexOptions;
246
- return katex;
247
- }
394
+ this.previewElement.innerHTML = this._renderer(eventTarget.value);
395
+ if (this.mathjax) this.#renderMathJax(this.mathjax);
396
+ }
248
397
 
249
- function CreateHTML_modal({ lang, icons }, math, fontSizeList) {
250
- const fontSize = fontSizeList || [
251
- {
252
- text: '1',
253
- value: '1em'
254
- },
255
- {
256
- text: '1.5',
257
- value: '1.5em'
258
- },
259
- {
260
- text: '2',
261
- value: '2em'
262
- },
263
- {
264
- text: '2.5',
265
- value: '2.5em'
398
+ /**
399
+ * @param {*} mathjax - The MathJax instance.
400
+ */
401
+ #renderMathJax(mathjax) {
402
+ mathjax.clear();
403
+ mathjax.updateDocument();
404
+ }
405
+
406
+ /**
407
+ * @param {*} katex - The KaTeX instance.
408
+ * @returns {*} - The KaTeX instance or null if the instance is invalid.
409
+ */
410
+ #CheckKatex(katex) {
411
+ if (!katex) return null;
412
+ if (!katex.src) {
413
+ console.warn('[SUNEDITOR.math.katex.fail] The katex option is set incorrectly.');
414
+ return null;
415
+ }
416
+
417
+ const katexOptions = [
418
+ {
419
+ throwOnError: false
420
+ },
421
+ katex.options || {}
422
+ ].reduce((init, option) => {
423
+ for (const key in option) {
424
+ init[key] = option[key];
425
+ }
426
+ return init;
427
+ }, {});
428
+
429
+ katex.options = katexOptions;
430
+ return katex;
431
+ }
432
+
433
+ /**
434
+ * @param {*} mathjax - The MathJax instance.
435
+ * @param {__se__EditorCore} editor - The root editor instance.
436
+ * @returns {*}
437
+ */
438
+ #CheckMathJax(mathjax, editor) {
439
+ if (!mathjax) return null;
440
+ if (editor.frameOptions.get('iframe')) {
441
+ console.warn('[SUNEDITOR.math.mathjax.fail] The MathJax option is not supported in the iframe.');
266
442
  }
267
- ];
268
- let defaultFontSize = fontSize[0].value;
443
+
444
+ try {
445
+ const adaptor = mathjax.browserAdaptor();
446
+ mathjax.RegisterHTMLHandler(adaptor);
447
+
448
+ const tex = new mathjax.TeX();
449
+ const chtml = new mathjax.CHTML();
450
+
451
+ return mathjax.src.document(document, {
452
+ InputJax: tex,
453
+ OutputJax: chtml
454
+ });
455
+ } catch (error) {
456
+ console.warn('[SUNEDITOR.math.mathjax.fail] The MathJax option is set incorrectly.', error);
457
+ return null;
458
+ }
459
+ }
460
+ }
461
+
462
+ function CreateHTML_modal(inst) {
463
+ const { lang, icons, pluginOptions, katex } = inst;
464
+ const { formSize, fontSizeList, canResize, autoHeight } = pluginOptions;
465
+ const { width, height, maxWidth, maxHeight, minWidth, minHeight } = formSize;
466
+ const resizeType = !canResize ? 'none' : autoHeight ? 'horizontal' : 'auto';
467
+
468
+ let defaultFontSize = fontSizeList[0].value;
269
469
  let html = /*html*/ `
270
470
  <form>
271
471
  <div class="se-modal-header">
@@ -276,15 +476,15 @@ function CreateHTML_modal({ lang, icons }, math, fontSizeList) {
276
476
  </div>
277
477
  <div class="se-modal-body">
278
478
  <div class="se-modal-form">
279
- <label>${lang.math_modal_inputLabel} (<a href="${env.KATEX_WEBSITE}" target="_blank">KaTeX</a>)</label>
280
- <textarea class="se-input-form se-math-exp" type="text" data-focus></textarea>
479
+ <label>${lang.math_modal_inputLabel} ${katex ? `(<a href="${env.KATEX_WEBSITE}" target="_blank">KaTeX</a>)` : `(<a href="${env.MATHJAX_WEBSITE}" target="_blank">MathJax</a>)`}</label>
480
+ <textarea class="se-input-form se-math-exp se-modal-resize-form" type="text" data-focus style="width: ${width}; height: ${height}; min-width: ${minWidth}; min-height: ${minHeight}; resize: ${resizeType};"></textarea>
281
481
  </div>
282
482
  <div class="se-modal-form">
283
483
  <label>${lang.math_modal_fontSizeLabel}</label>
284
484
  <select class="se-input-select se-math-size">`;
285
485
 
286
- for (let i = 0, len = fontSize.length, f; i < len; i++) {
287
- f = fontSize[i];
486
+ for (let i = 0, len = fontSizeList.length, f; i < len; i++) {
487
+ f = fontSizeList[i];
288
488
  if (f.default) defaultFontSize = f.value;
289
489
  html += /*html*/ `<option value="${f.value}"${f.default ? ' selected' : ''}>${f.text}</option>`;
290
490
  }
@@ -303,8 +503,8 @@ function CreateHTML_modal({ lang, icons }, math, fontSizeList) {
303
503
  </div>
304
504
  </form>`;
305
505
 
306
- math.defaultFontSize = defaultFontSize;
307
- return domUtils.createElement('DIV', { class: 'se-modal-content' }, html);
506
+ inst.defaultFontSize = defaultFontSize;
507
+ return dom.utils.createElement('DIV', { class: 'se-modal-content se-modal-responsive', style: `max-width: ${maxWidth}; max-height: ${maxHeight};` }, html);
308
508
  }
309
509
 
310
510
  function CreateHTML_controller({ lang, icons }) {
@@ -333,7 +533,7 @@ function CreateHTML_controller({ lang, icons }) {
333
533
  </div>
334
534
  </div>`;
335
535
 
336
- return domUtils.createElement('DIV', { class: 'se-controller se-controller-link' }, html);
536
+ return dom.utils.createElement('DIV', { class: 'se-controller se-controller-link' }, html);
337
537
  }
338
538
 
339
539
  function getValue(element) {