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
@@ -2,16 +2,17 @@ import { get as getNumber } from '../../helper/numbers';
2
2
 
3
3
  /**
4
4
  * @description Elements and variables you should have
5
- * @param {Element} editorTargets Target textarea
6
- * @param {Element} top Editor top area
7
- * @param {Element} wwFrame Editor wysiwyg frame
8
- * @param {Element} codeWrapper Editor code view wrapper
9
- * @param {Element} codeFrame Editor code view frame
10
- * @param {Element|null} statusbar Editor statusbar
11
- * @param {any} key root key
12
- * @returns {Map}
5
+ * @param {{target: Element, key: *, options: __se__FrameOptions}} editorTarget Target textarea
6
+ * @param {HTMLElement} top Editor top area
7
+ * @param {HTMLElement} wwFrame Editor wysiwyg frame
8
+ * @param {HTMLElement} codeWrapper Editor code view wrapper
9
+ * @param {HTMLElement} codeFrame Editor code view frame
10
+ * @param {{inner: HTMLElement, page: HTMLElement, pageMirror: HTMLElement}} documentTypeInner Document type elements
11
+ * @param {?HTMLElement} statusbar Editor statusbar
12
+ * @param {*} key root key
13
+ * @returns {__se__FrameContext}
13
14
  */
14
- export const CreateFrameContext = function (editorTarget, top, wwFrame, codeWrapper, codeFrame, statusbar, key) {
15
+ export function CreateFrameContext(editorTarget, top, wwFrame, codeWrapper, codeFrame, statusbar, documentTypeInner, key) {
15
16
  const m = new Map([
16
17
  ['key', key],
17
18
  ['options', editorTarget.options],
@@ -19,11 +20,14 @@ export const CreateFrameContext = function (editorTarget, top, wwFrame, codeWrap
19
20
  ['topArea', top],
20
21
  ['container', top.querySelector('.se-container')],
21
22
  ['wrapper', top.querySelector('.se-wrapper')],
23
+ ['documentTypeInner', documentTypeInner.inner],
24
+ ['documentTypePage', documentTypeInner.page],
25
+ ['documentTypePageMirror', documentTypeInner.pageMirror],
22
26
  ['wysiwygFrame', wwFrame],
23
27
  ['wysiwyg', wwFrame], // options.iframe ? wwFrame.contentDocument.body : wwFrame
24
28
  ['codeWrapper', codeWrapper],
25
29
  ['code', codeFrame],
26
- ['codeNumbers', codeWrapper?.querySelector('.se-code-view-line')],
30
+ ['codeNumbers', /** @type {HTMLTextAreaElement} */ (codeWrapper?.querySelector('.se-code-view-line'))],
27
31
  ['lineBreaker_t', top.querySelector('.se-line-breaker-component-t')],
28
32
  ['lineBreaker_b', top.querySelector('.se-line-breaker-component-b')],
29
33
  ['_stickyDummy', top.querySelector('.se-toolbar-sticky-dummy')],
@@ -35,7 +39,8 @@ export const CreateFrameContext = function (editorTarget, top, wwFrame, codeWrap
35
39
  ['isDisabled', false],
36
40
  ['isChanged', -1],
37
41
  ['historyIndex', -1],
38
- ['savedIndex', -1]
42
+ ['savedIndex', -1],
43
+ ['eventwysiwyg', null]
39
44
  ]);
40
45
 
41
46
  if (statusbar) UpdateStatusbarContext(statusbar, m);
@@ -44,14 +49,14 @@ export const CreateFrameContext = function (editorTarget, top, wwFrame, codeWrap
44
49
  if (placeholder) m.set('placeholder', placeholder);
45
50
 
46
51
  return m;
47
- };
52
+ }
48
53
 
49
54
  /**
50
55
  * @description Update statusbar context
51
- * @param {Element} statusbar Statusbar element
52
- * @param {FrameContext} mapper FrameContext map
56
+ * @param {HTMLElement} statusbar Statusbar element
57
+ * @param {__se__FrameContext} mapper FrameContext map
53
58
  */
54
- export const UpdateStatusbarContext = function (statusbar, mapper) {
59
+ export function UpdateStatusbarContext(statusbar, mapper) {
55
60
  statusbar ? mapper.set('statusbar', statusbar) : mapper.delete('statusbar');
56
61
  const navigation = statusbar ? statusbar.querySelector('.se-navigation') : null;
57
62
  const charWrapper = statusbar ? statusbar.querySelector('.se-char-counter-wrapper') : null;
@@ -59,17 +64,17 @@ export const UpdateStatusbarContext = function (statusbar, mapper) {
59
64
  navigation ? mapper.set('navigation', navigation) : mapper.delete('navigation');
60
65
  charWrapper ? mapper.set('charWrapper', charWrapper) : mapper.delete('charWrapper');
61
66
  charCounter ? mapper.set('charCounter', charCounter) : mapper.delete('charCounter');
62
- };
67
+ }
63
68
 
64
69
  /**
65
70
  * @description Common elements and variables you should have
66
- * @param {Element} toolbar Toolbar frame
67
- * @param {Element|null} toolbarContainer Toolbar container
68
- * @param {Element} menuTray menu tray
69
- * @param {Element|null} subbar sub toolbar
70
- * @returns {Map}
71
+ * @param {HTMLElement} toolbar Toolbar frame
72
+ * @param {HTMLElement|null} toolbarContainer Toolbar container
73
+ * @param {HTMLElement} menuTray menu tray
74
+ * @param {HTMLElement|null} subbar sub toolbar
75
+ * @returns {__se__Context}
71
76
  */
72
- export const CreateContext = function (toolbar, toolbarContainer, menuTray, subbar, statusbarContainer) {
77
+ export function CreateContext(toolbar, toolbarContainer, menuTray, subbar, statusbarContainer) {
73
78
  const m = new Map([
74
79
  ['menuTray', menuTray],
75
80
  ['toolbar.main', toolbar],
@@ -94,4 +99,4 @@ export const CreateContext = function (toolbar, toolbarContainer, menuTray, subb
94
99
  }
95
100
 
96
101
  return m;
97
- };
102
+ }
@@ -0,0 +1,561 @@
1
+ /**
2
+ * @fileoverview DocumentType class
3
+ */
4
+
5
+ import { dom, numbers, converter, env } from '../../helper';
6
+
7
+ const { _w } = env;
8
+
9
+ // A4 constants in points (72 dpi - PDF standard)
10
+ const MM_TO_POINTS = 2.83465; // 1mm = 2.83465pt
11
+ const POINTS_TO_PIXELS = 96 / 72; // convert PDF points to screen pixels
12
+ const A4_HEIGHT_MM = 297;
13
+ const A4_PAGE_HEIGHT = Math.floor(A4_HEIGHT_MM * MM_TO_POINTS * POINTS_TO_PIXELS);
14
+
15
+ /**
16
+ * @constructor
17
+ * @description DocumentType, page, header management class
18
+ * @param {__se__EditorCore} editor - The root editor instance
19
+ * @param {__se__FrameContext} fc - frame context object
20
+ */
21
+ function DocumentType(editor, fc) {
22
+ // members
23
+ this.editor = editor;
24
+ this.context = editor.context;
25
+ this.selection = editor.selection;
26
+ this.offset = editor.offset;
27
+ this.fc = fc;
28
+ this.ww = fc.get('wysiwyg');
29
+ this.wwFrame = fc.get('wysiwygFrame');
30
+ this.wwWidth = -1;
31
+ this.wwHeight = -1;
32
+ this.isAutoHeight = fc.get('options').get('height') === 'auto';
33
+ this.displayPage = this.isAutoHeight ? _w : fc.get('wysiwyg');
34
+ this.innerHeaders = [];
35
+ this._wwHeaders = [];
36
+ this.documentTypeInner = fc.get('documentTypeInner');
37
+ this.inner = null;
38
+ this.page = null;
39
+ this.totalPages = 0;
40
+ this.pageNum = 0;
41
+ this.pageHeight = -1;
42
+ this.pageBreaksCnt = 0;
43
+ this.pages = [];
44
+ this.pages_line = [];
45
+ this.prevScrollTop = 0;
46
+ this.useHeader = editor.options.get('_type_options').includes('header');
47
+ this.usePage = editor.options.get('_type_options').includes('page');
48
+ this.navigatorButtons = [];
49
+ this.pageNavigator = null;
50
+ this._mirror = fc.get('documentTypePageMirror');
51
+ this._mirrorCache = 0;
52
+ this._positionCache = new Map();
53
+ this._rePageTimeout = null;
54
+
55
+ const mirrorStyles = _w.getComputedStyle(this._mirror);
56
+ this._paddingTop = numbers.get(mirrorStyles.paddingTop);
57
+ this._paddingBottom = numbers.get(mirrorStyles.paddingBottom);
58
+
59
+ // init header
60
+ if (this.useHeader) {
61
+ const headers = this._getHeaders();
62
+ const inner = (this.inner = this.documentTypeInner.querySelector('.se-document-lines-inner'));
63
+ let headerHTML = '';
64
+ for (let i = 0, len = headers.length, h; i < len; i++) {
65
+ h = headers[i];
66
+ headerHTML += `<div class="se-doc-item se-doc-h${numbers.get(h.nodeName)}" title="${h.textContent}">${h.textContent}</div>`;
67
+ }
68
+ inner.innerHTML = headerHTML;
69
+ this.innerHeaders = inner.querySelectorAll('div');
70
+
71
+ this.editor.eventManager.addEvent(inner, 'click', OnClickHeader.bind(this, this.ww));
72
+ }
73
+
74
+ // init page
75
+ if (this.usePage) {
76
+ this.page = fc.get('documentTypePage');
77
+ this.pageNavigator = editor.plugins.pageNavigator;
78
+ }
79
+ }
80
+
81
+ DocumentType.prototype = {
82
+ /**
83
+ * @description Refresh the document header area
84
+ */
85
+ reHeader() {
86
+ if (!this.useHeader) return;
87
+
88
+ const headers = this._getHeaders();
89
+ const inner = this.inner;
90
+ const innerHeaders = this.innerHeaders;
91
+
92
+ // update or new headers
93
+ for (let i = 0, len = headers.length, h, hClass, innerH; i < len; i++) {
94
+ h = headers[i];
95
+ hClass = `se-doc-h${numbers.get(h.nodeName)}`;
96
+ innerH = innerHeaders[i];
97
+
98
+ if (i < innerHeaders.length) {
99
+ if (!innerH.classList.contains(hClass) || innerH.textContent !== h.textContent) {
100
+ innerH.textContent = innerH.title = h.textContent;
101
+ innerH.className = `se-doc-item ${hClass}`;
102
+ }
103
+ } else {
104
+ const newHeader = document.createElement('div');
105
+ newHeader.className = `se-doc-item ${hClass}`;
106
+ newHeader.textContent = newHeader.title = h.textContent;
107
+ inner.appendChild(newHeader);
108
+ }
109
+ }
110
+
111
+ // remove
112
+ if (innerHeaders.length > headers.length) {
113
+ for (let i = headers.length; i < innerHeaders.length; i++) {
114
+ inner.removeChild(innerHeaders[i]);
115
+ }
116
+ }
117
+
118
+ this.innerHeaders = inner.querySelectorAll('div');
119
+ },
120
+
121
+ /**
122
+ * @description Refresh the document page
123
+ * @param {boolean} force - Whether to force the page to be re-rendered
124
+ * @returns {Promise<void>}
125
+ */
126
+ async rePage(force) {
127
+ if (!this.page) return;
128
+ if (this._rePageTimeout) _w.clearTimeout(this._rePageTimeout);
129
+
130
+ this._rePageTimeout = _w.setTimeout(async () => {
131
+ await dom.utils.waitForMediaLoad(this._mirror, 1500);
132
+
133
+ const mirrorHeight = this._mirror.scrollHeight;
134
+ const pageBreaks = this._mirror.querySelectorAll('.se-page-break');
135
+ if (!force && this.pageHeight === mirrorHeight && this.pageBreaksCnt === pageBreaks.length) return;
136
+ this.pageHeight = mirrorHeight;
137
+ this.pageBreaksCnt = pageBreaks.length;
138
+
139
+ // page break
140
+ let pageBreakHeight = 0;
141
+ let lastBreakPosition = 0;
142
+ let additionalPages = 0;
143
+ if (pageBreaks.length > 0) {
144
+ pageBreakHeight = pageBreaks[0].offsetHeight;
145
+ for (let i = 0; i < pageBreaks.length; i++) {
146
+ const breakPosition = pageBreaks[i].offsetTop;
147
+ const sectionHeight = breakPosition - lastBreakPosition;
148
+
149
+ if (sectionHeight % A4_PAGE_HEIGHT !== 0) {
150
+ additionalPages++;
151
+ }
152
+
153
+ lastBreakPosition = breakPosition;
154
+ }
155
+
156
+ const lastSectionHeight = mirrorHeight - lastBreakPosition;
157
+ if (lastSectionHeight > 0 && lastSectionHeight % A4_PAGE_HEIGHT !== 0) {
158
+ additionalPages++;
159
+ }
160
+ }
161
+
162
+ const scrollTop = this.isAutoHeight ? 0 : this._getWWScrollTop();
163
+ const totalPages = Math.ceil(mirrorHeight / A4_PAGE_HEIGHT) + additionalPages;
164
+ const wwWidth = this.wwFrame.offsetWidth + 1;
165
+ const pages = [];
166
+
167
+ for (let i = 0; i < pageBreaks.length; i++) {
168
+ pages.push({ number: i, top: pageBreaks[i].offsetTop + pageBreakHeight - scrollTop });
169
+ }
170
+
171
+ // A4 position
172
+ this._mirrorCache = 0;
173
+ const chr = this.ww.children;
174
+ const mChr = this._mirror.children;
175
+ this._initializeCache(mChr);
176
+ pages.push({ number: 0, top: 0 });
177
+ for (let i = 1, t = 0; i < totalPages; i++) {
178
+ t += A4_PAGE_HEIGHT + (i === 1 ? this._paddingTop + this._paddingBottom : this._paddingTop);
179
+ if (!pages.some((p) => Math.abs(p.top - t) < 1)) {
180
+ const { ci, cm, ch } = this._getElementAtPosition(t, mChr);
181
+ const el = chr[ci];
182
+ if (!el) break;
183
+
184
+ if (chr[this._mirrorCache]) {
185
+ t += numbers.get(_w.getComputedStyle(chr[this._mirrorCache]).marginBottom);
186
+ }
187
+
188
+ const elBottom = el.offsetTop + el.offsetHeight;
189
+ const top = elBottom + cm + (el.offsetHeight - ch);
190
+ pages.push({ number: i, top });
191
+ }
192
+ }
193
+
194
+ if (pages.length === 0) {
195
+ this.pages_line = [];
196
+ this.totalPages = 1;
197
+ this._displayCurrentPage();
198
+ return;
199
+ }
200
+
201
+ // numbering
202
+ pages.sort((a, b) => a.top - b.top);
203
+ this.page.innerHTML = '';
204
+ this.pages = [];
205
+ for (let i = 0, t; i < totalPages; i++) {
206
+ if (!pages[i]) continue;
207
+ t = pages[i].top;
208
+ if (mirrorHeight < t) break;
209
+ const pageNumber = dom.utils.createElement('DIV', { style: `top:${t - scrollTop}px`, innerHTML: String(i + 1) }, `<div class="se-document-page-line" style="width: ${wwWidth}px;"></div>${i + 1}`);
210
+ this.page.appendChild(pageNumber);
211
+ this.pages.push(pageNumber);
212
+ }
213
+
214
+ this.pages_line = this.page.querySelectorAll('.se-document-page-line');
215
+ this.totalPages = this.pages.length;
216
+ this._displayCurrentPage();
217
+ }, 400);
218
+ },
219
+
220
+ /**
221
+ * @private
222
+ * @description Initializes the cache for document elements.
223
+ * @param {Array<HTMLElement>} mChr - List of mirrored elements.
224
+ */
225
+ _initializeCache(mChr) {
226
+ this._positionCache.clear();
227
+ for (let i = 0, len = mChr.length; i < len; i++) {
228
+ const element = mChr[i];
229
+ const top = element.offsetTop;
230
+ const height = element.offsetHeight;
231
+ const bottom = top + height;
232
+
233
+ this._positionCache.set(i, {
234
+ top,
235
+ height,
236
+ bottom: bottom
237
+ });
238
+ }
239
+ },
240
+
241
+ /**
242
+ * @private
243
+ * @description Retrieves the element at a given position.
244
+ * @param {number} pageTop - The vertical position to check.
245
+ * @param {NodeList} mChr - List of mirrored elements.
246
+ * @returns {{ci: number, cm: number, ch: number}} The closest element and its related data.
247
+ * - ci: The index of the closest element.
248
+ * - cm: The distance between the top of the closest element and the given position.
249
+ * - ch: The height of the closest element.
250
+ */
251
+ _getElementAtPosition(pageTop, mChr) {
252
+ let start = this._mirrorCache;
253
+ let end = mChr.length - 1;
254
+
255
+ while (start <= end) {
256
+ const mid = Math.floor((start + end) / 2);
257
+ const { top, height, bottom } = this._positionCache.get(mid);
258
+
259
+ if (pageTop >= top && pageTop <= bottom) {
260
+ this._mirrorCache = mid;
261
+ return { ci: mid, cm: pageTop - bottom, ch: height };
262
+ }
263
+
264
+ if (pageTop < top) {
265
+ end = mid - 1;
266
+ } else {
267
+ start = mid + 1;
268
+ }
269
+ }
270
+
271
+ const closestIndex = mChr[start] ? start : end;
272
+ this._mirrorCache = closestIndex;
273
+ const iElement = this._positionCache.get(closestIndex);
274
+ return { ci: closestIndex, cm: pageTop - iElement.bottom, ch: iElement.height };
275
+ },
276
+
277
+ /**
278
+ * @description Resizes the document page dynamically.
279
+ */
280
+ resizePage() {
281
+ const wwWidth = this.wwFrame.offsetWidth + 1;
282
+ const wwHeight = this.wwFrame.offsetHeight + 1;
283
+ let rh = false;
284
+ if (wwWidth === this.wwWidth && (rh = wwHeight === this.wwHeight)) return;
285
+
286
+ if (wwWidth > 800) {
287
+ dom.utils.removeClass(this.documentTypeInner, 'se-document-responsible');
288
+ } else {
289
+ dom.utils.addClass(this.documentTypeInner, 'se-document-responsible');
290
+ }
291
+
292
+ this.wwWidth = wwWidth;
293
+ this.wwHeight = wwHeight;
294
+ const pages_line = this.pages_line;
295
+ for (let i = 0, len = pages_line.length; i < len; i++) {
296
+ pages_line[i].style.width = `${wwWidth}px`;
297
+ }
298
+
299
+ if (!rh) this.rePage(true);
300
+ this._displayCurrentPage();
301
+ },
302
+
303
+ /**
304
+ * @description Scrolls the document page.
305
+ */
306
+ scrollPage() {
307
+ const prevScrollTop = this.prevScrollTop;
308
+ const scrollTop = this._getWWScrollTop();
309
+ if (prevScrollTop === scrollTop) return;
310
+
311
+ const pages = this.pages;
312
+ for (let i = 0, len = pages.length; i < len; i++) {
313
+ pages[i].style.top = `${numbers.get(pages[i].style.top) - (scrollTop - prevScrollTop)}px`;
314
+ }
315
+
316
+ this.prevScrollTop = scrollTop;
317
+ this._displayCurrentPage();
318
+ },
319
+
320
+ /**
321
+ * @description Scrolls the window to a specific position.
322
+ */
323
+ scrollWindow() {
324
+ if (!this.isAutoHeight) return;
325
+ this._displayCurrentPage();
326
+ },
327
+
328
+ /**
329
+ * @description Retrieves the current page number.
330
+ * @returns {number} The current page number.
331
+ */
332
+ getCurrentPageNumber() {
333
+ if (this.totalPages <= 1) return 1;
334
+
335
+ let targetPosition = 0;
336
+ if (this.isAutoHeight) {
337
+ const globalTop = this._getGlobalTop();
338
+ targetPosition = _w.scrollY - globalTop + A4_PAGE_HEIGHT / 2;
339
+ if (targetPosition <= 0) return 1;
340
+ } else {
341
+ targetPosition = this.wwHeight / 2;
342
+ }
343
+
344
+ const pages = this.pages;
345
+ for (let i = 0, len = pages.length; i < len; i++) {
346
+ if (pages[i].offsetTop >= targetPosition) {
347
+ return (this.pageNum = i);
348
+ }
349
+ }
350
+
351
+ return (this.pageNum = this.totalPages);
352
+ },
353
+
354
+ /**
355
+ * @description Moves to the previous page.
356
+ */
357
+ pageUp() {
358
+ const pageNum = this.pageNum - 1 <= 1 ? 1 : this.pageNum - 1;
359
+ this._movePage(pageNum, false);
360
+ },
361
+
362
+ /**
363
+ * @description Moves to the next page.
364
+ */
365
+ pageDown() {
366
+ const pageNum = this.pageNum + 1 > this.pages.length ? this.pages.length : this.pageNum + 1;
367
+ this._movePage(pageNum, false);
368
+ },
369
+
370
+ /**
371
+ * @description Moves to a specific page.
372
+ * @param {number} pageNum - The target page number.
373
+ */
374
+ pageGo(pageNum) {
375
+ if (pageNum < 1) pageNum = 1;
376
+ else if (pageNum > this.pages.length) pageNum = this.pages.length;
377
+
378
+ this._movePage(pageNum, true);
379
+ },
380
+
381
+ /**
382
+ * @description Highlights the header of the current line.
383
+ * @param {Node} line - The "line" element to be highlighted.
384
+ */
385
+ on(line) {
386
+ if (!this.useHeader) return;
387
+
388
+ if (!this._is(line)) line = this._findLinesHeader(line);
389
+ if (!line) return;
390
+
391
+ const item = this._findItem(line);
392
+ if (!item) return;
393
+
394
+ dom.utils.removeClass(this.innerHeaders, 'active');
395
+ dom.utils.addClass(item, 'active');
396
+ },
397
+
398
+ /**
399
+ * @description Handles text changes in the document.
400
+ */
401
+ onChangeText(header) {
402
+ if (!this.useHeader) return;
403
+
404
+ if (!this._is(header)) return;
405
+ const item = this._findItem(header);
406
+ if (!item) return;
407
+ item.textContent = header.textContent;
408
+ },
409
+
410
+ /**
411
+ * @private
412
+ * @description Displays the current page number.
413
+ */
414
+ _displayCurrentPage() {
415
+ const pageNum = this.getCurrentPageNumber();
416
+ this.pageNavigator?.display(pageNum, this.totalPages);
417
+ },
418
+
419
+ /**
420
+ * @private
421
+ * @description Retrieves the scroll position in WYSIWYG mode.
422
+ * @returns {number} The current scroll position.
423
+ */
424
+ _getWWScrollTop() {
425
+ return this.displayPage.scrollTop || this.displayPage.scrollY || 0;
426
+ },
427
+
428
+ /**
429
+ * @private
430
+ * @description Moves to a specific page and updates the view.
431
+ * @param {number} pageNum - The target page number.
432
+ */
433
+ _movePage(pageNum, force) {
434
+ const globalTop = this._getGlobalTop();
435
+ const children = converter.nodeListToArray(this.ww.children);
436
+ const pageTop = this.page.offsetTop + numbers.get(this.pages[pageNum - 1].style.top) + (this.isAutoHeight ? 0 : this._getWWScrollTop());
437
+ for (let i = 0, len = children.length, c; i < len; i++) {
438
+ c = children[i];
439
+ if (c.offsetTop >= pageTop) {
440
+ if (!force) this.selection.setRange(c, 0, c, 0);
441
+ const scrollTop = i === 0 && !this.isAutoHeight ? 0 : c.offsetTop - this.page.offsetTop - c.offsetHeight + globalTop;
442
+ this._applyPageScroll(scrollTop, () => {
443
+ if (this.editor.toolbar._sticky) {
444
+ this.displayPage.scrollTo({ top: scrollTop - this.context.get('toolbar.main').offsetHeight, behavior: 'smooth' });
445
+ }
446
+ });
447
+
448
+ this.pageNum = pageNum;
449
+ break;
450
+ }
451
+ }
452
+ },
453
+
454
+ /**
455
+ * @private
456
+ * @description Applies smooth scrolling for page navigation.
457
+ */
458
+ _applyPageScroll(top, callback) {
459
+ this.displayPage.scrollTo({ top, behavior: 'smooth' });
460
+ const checkScrollEnd = () => {
461
+ if (Math.abs((this.displayPage.scrollY ?? this.displayPage.scrollTop) - top) < 1) {
462
+ callback();
463
+ } else {
464
+ _w.requestAnimationFrame(checkScrollEnd);
465
+ }
466
+ };
467
+
468
+ _w.requestAnimationFrame(checkScrollEnd);
469
+ },
470
+
471
+ /**
472
+ * @private
473
+ * @description Retrieves the global top offset of an element.
474
+ * @returns {number} The top offset of the element.
475
+ */
476
+ _getGlobalTop() {
477
+ return this.isAutoHeight ? this.offset.getGlobal(this.wwFrame).top : 0;
478
+ },
479
+
480
+ /**
481
+ * @private
482
+ * @description Finds an header element of innerHeaders element.
483
+ * @param {Node} header - H tag element to find.
484
+ * @returns {HTMLElement|null} The found element, or null if not found.
485
+ */
486
+ _findItem(header) {
487
+ const headers = this._wwHeaders;
488
+ const index = Array.prototype.indexOf.call(headers, header);
489
+
490
+ if (index !== -1 && this.innerHeaders[index]) {
491
+ return this.innerHeaders[index];
492
+ }
493
+
494
+ return null;
495
+ },
496
+
497
+ /**
498
+ * @private
499
+ * @description Finds the closest header element from a given line.
500
+ * @param {Node} line - The "line" to check.
501
+ * @returns {Node|null} The closest header element, or null if not found.
502
+ */
503
+ _findLinesHeader(line) {
504
+ while (line && line !== this.ww) {
505
+ if (this._is(line)) {
506
+ return line;
507
+ }
508
+ line = /** @type {HTMLElement} */ (line).previousElementSibling || line.parentElement;
509
+ }
510
+
511
+ return null;
512
+ },
513
+
514
+ /**
515
+ * @private
516
+ * @description Checks if an element is a header.
517
+ * @param {Node} element - The element to check.
518
+ * @returns {boolean} True if the element is a header, otherwise false.
519
+ */
520
+ _is(element) {
521
+ return /^h[1-6]$/i.test(element?.nodeName);
522
+ },
523
+
524
+ /**
525
+ * @private
526
+ * @description Retrieves all headers in the document.
527
+ * @returns {Array<HTMLElement>} An array of header elements.
528
+ */
529
+ _getHeaders() {
530
+ return (this._wwHeaders = this.ww.querySelectorAll('h1, h2, h3, h4, h5, h6'));
531
+ },
532
+
533
+ constructor: DocumentType
534
+ };
535
+
536
+ /**
537
+ * @private
538
+ * @param {HTMLElement} ww WYSIWYG element
539
+ * @param {Event} e Event object
540
+ */
541
+ function OnClickHeader(ww, e) {
542
+ e.preventDefault();
543
+
544
+ try {
545
+ this.editor._preventBlur = true;
546
+ const clickedHeader = dom.query.getEventTarget(e);
547
+ if (dom.utils.hasClass(clickedHeader, 'se-doc-item')) {
548
+ const innerIndex = Array.prototype.indexOf.call(this.innerHeaders, clickedHeader);
549
+ if (innerIndex === -1) return;
550
+
551
+ const header = this._wwHeaders[innerIndex];
552
+ if (header) {
553
+ this.selection.scrollTo(header);
554
+ }
555
+ }
556
+ } finally {
557
+ this.editor._preventBlur = false;
558
+ }
559
+ }
560
+
561
+ export default DocumentType;
@@ -1,22 +1,36 @@
1
1
  /**
2
- * @description Add all inner classes to the editor;
3
- * @param {any} editor Editor object
4
2
  * @private
3
+ * @description Add all inner classes to the editor instance.
4
+ * @param {__se__EditorCore} editor - The root editor instance
5
5
  */
6
6
  function ClassInjector(editor) {
7
+ /** @description Toolbar class instance @type {__se__EditorCore['toolbar']} */
8
+ this.toolbar = editor.toolbar;
9
+ /** @description Sub-Toolbar class instance @type {__se__EditorCore['subToolbar']|null} */
10
+ this.subToolbar = null;
11
+ if (editor.subToolbar) this.subToolbar = editor.subToolbar;
12
+ /** @description Char class instance @type {__se__EditorCore['char']} */
7
13
  this.char = editor.char;
14
+ /** @description Component class instance @type {__se__EditorCore['component']} */
8
15
  this.component = editor.component;
16
+ /** @description Format class instance @type {__se__EditorCore['format']} */
9
17
  this.format = editor.format;
18
+ /** @description HTML class instance @type {__se__EditorCore['html']} */
10
19
  this.html = editor.html;
20
+ /** @description Menu class instance @type {__se__EditorCore['menu']} */
11
21
  this.menu = editor.menu;
22
+ /** @description NodeTransform class instance @type {__se__EditorCore['nodeTransform']} */
12
23
  this.nodeTransform = editor.nodeTransform;
13
- this.notice = editor.notice;
24
+ /** @description Offset class instance @type {__se__EditorCore['offset']} */
14
25
  this.offset = editor.offset;
26
+ /** @description Selection class instance @type {__se__EditorCore['selection']} */
15
27
  this.selection = editor.selection;
28
+ /** @description Shortcuts class instance @type {__se__EditorCore['shortcuts']} */
16
29
  this.shortcuts = editor.shortcuts;
17
- this.toolbar = editor.toolbar;
30
+ /** @description UI class instance @type {__se__EditorCore['ui']} */
31
+ this.ui = editor.ui;
32
+ /** @description Viewer class instance @type {__se__EditorCore['viewer']} */
18
33
  this.viewer = editor.viewer;
19
- if (editor.subToolbar) this.subToolbar = editor.subToolbar;
20
34
  }
21
35
 
22
36
  export default ClassInjector;