@mnykj/alleditor-vue 0.0.0-stage → 1.3.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 (291) hide show
  1. package/README.md +51 -2
  2. package/nuxt.ts +67 -0
  3. package/package.json +62 -4
  4. package/scripts/sync-ueditor.mjs +28 -0
  5. package/src/AllEditor.vue +669 -0
  6. package/src/DualEditor.vue +7 -0
  7. package/src/UeHtmlEngine.vue +438 -0
  8. package/src/assets/iconfont/iconfont.css +27 -0
  9. package/src/assets/iconfont/iconfont.ttf +0 -0
  10. package/src/assets/iconfont/iconfont.woff +0 -0
  11. package/src/assets/iconfont/iconfont.woff2 +0 -0
  12. package/src/defaultToolbar.ts +115 -0
  13. package/src/importMenus.ts +158 -0
  14. package/src/index.ts +58 -0
  15. package/src/markdown.ts +46 -0
  16. package/src/stripJavascriptFromHtml.ts +28 -0
  17. package/src/ueToolbar.ts +257 -0
  18. package/src/ueditorBase.ts +2 -0
  19. package/src/ueditorPaths.ts +11 -0
  20. package/ueditor/dialogs/anchor/anchor.html +40 -0
  21. package/ueditor/dialogs/attachment/attachment.css +681 -0
  22. package/ueditor/dialogs/attachment/attachment.html +60 -0
  23. package/ueditor/dialogs/attachment/attachment.js +760 -0
  24. package/ueditor/dialogs/attachment/fileTypeImages/icon_chm.gif +0 -0
  25. package/ueditor/dialogs/attachment/fileTypeImages/icon_default.png +0 -0
  26. package/ueditor/dialogs/attachment/fileTypeImages/icon_doc.gif +0 -0
  27. package/ueditor/dialogs/attachment/fileTypeImages/icon_exe.gif +0 -0
  28. package/ueditor/dialogs/attachment/fileTypeImages/icon_jpg.gif +0 -0
  29. package/ueditor/dialogs/attachment/fileTypeImages/icon_mp3.gif +0 -0
  30. package/ueditor/dialogs/attachment/fileTypeImages/icon_mv.gif +0 -0
  31. package/ueditor/dialogs/attachment/fileTypeImages/icon_pdf.gif +0 -0
  32. package/ueditor/dialogs/attachment/fileTypeImages/icon_ppt.gif +0 -0
  33. package/ueditor/dialogs/attachment/fileTypeImages/icon_psd.gif +0 -0
  34. package/ueditor/dialogs/attachment/fileTypeImages/icon_rar.gif +0 -0
  35. package/ueditor/dialogs/attachment/fileTypeImages/icon_txt.gif +0 -0
  36. package/ueditor/dialogs/attachment/fileTypeImages/icon_xls.gif +0 -0
  37. package/ueditor/dialogs/attachment/images/alignicon.gif +0 -0
  38. package/ueditor/dialogs/attachment/images/alignicon.png +0 -0
  39. package/ueditor/dialogs/attachment/images/bg.png +0 -0
  40. package/ueditor/dialogs/attachment/images/file-icons.gif +0 -0
  41. package/ueditor/dialogs/attachment/images/file-icons.png +0 -0
  42. package/ueditor/dialogs/attachment/images/icons.gif +0 -0
  43. package/ueditor/dialogs/attachment/images/icons.png +0 -0
  44. package/ueditor/dialogs/attachment/images/image.png +0 -0
  45. package/ueditor/dialogs/attachment/images/progress.png +0 -0
  46. package/ueditor/dialogs/attachment/images/success.gif +0 -0
  47. package/ueditor/dialogs/attachment/images/success.png +0 -0
  48. package/ueditor/dialogs/background/background.css +94 -0
  49. package/ueditor/dialogs/background/background.html +56 -0
  50. package/ueditor/dialogs/background/background.js +376 -0
  51. package/ueditor/dialogs/background/images/bg.png +0 -0
  52. package/ueditor/dialogs/background/images/success.png +0 -0
  53. package/ueditor/dialogs/charts/chart.config.js +65 -0
  54. package/ueditor/dialogs/charts/charts.css +165 -0
  55. package/ueditor/dialogs/charts/charts.html +89 -0
  56. package/ueditor/dialogs/charts/charts.js +519 -0
  57. package/ueditor/dialogs/charts/images/charts0.png +0 -0
  58. package/ueditor/dialogs/charts/images/charts1.png +0 -0
  59. package/ueditor/dialogs/charts/images/charts2.png +0 -0
  60. package/ueditor/dialogs/charts/images/charts3.png +0 -0
  61. package/ueditor/dialogs/charts/images/charts4.png +0 -0
  62. package/ueditor/dialogs/charts/images/charts5.png +0 -0
  63. package/ueditor/dialogs/emotion/emotion.css +43 -0
  64. package/ueditor/dialogs/emotion/emotion.html +54 -0
  65. package/ueditor/dialogs/emotion/emotion.js +186 -0
  66. package/ueditor/dialogs/emotion/images/0.gif +0 -0
  67. package/ueditor/dialogs/emotion/images/bface.gif +0 -0
  68. package/ueditor/dialogs/emotion/images/cface.gif +0 -0
  69. package/ueditor/dialogs/emotion/images/fface.gif +0 -0
  70. package/ueditor/dialogs/emotion/images/jxface2.gif +0 -0
  71. package/ueditor/dialogs/emotion/images/neweditor-tab-bg.png +0 -0
  72. package/ueditor/dialogs/emotion/images/tface.gif +0 -0
  73. package/ueditor/dialogs/emotion/images/wface.gif +0 -0
  74. package/ueditor/dialogs/emotion/images/yface.gif +0 -0
  75. package/ueditor/dialogs/gmap/gmap.html +89 -0
  76. package/ueditor/dialogs/help/help.css +7 -0
  77. package/ueditor/dialogs/help/help.html +82 -0
  78. package/ueditor/dialogs/help/help.js +56 -0
  79. package/ueditor/dialogs/image/image.css +894 -0
  80. package/ueditor/dialogs/image/image.html +120 -0
  81. package/ueditor/dialogs/image/image.js +1123 -0
  82. package/ueditor/dialogs/image/images/alignicon.jpg +0 -0
  83. package/ueditor/dialogs/image/images/bg.png +0 -0
  84. package/ueditor/dialogs/image/images/icons.gif +0 -0
  85. package/ueditor/dialogs/image/images/icons.png +0 -0
  86. package/ueditor/dialogs/image/images/image.png +0 -0
  87. package/ueditor/dialogs/image/images/progress.png +0 -0
  88. package/ueditor/dialogs/image/images/success.gif +0 -0
  89. package/ueditor/dialogs/image/images/success.png +0 -0
  90. package/ueditor/dialogs/insertframe/insertframe.html +98 -0
  91. package/ueditor/dialogs/internal.js +81 -0
  92. package/ueditor/dialogs/link/link.html +132 -0
  93. package/ueditor/dialogs/map/map.html +135 -0
  94. package/ueditor/dialogs/map/show.html +118 -0
  95. package/ueditor/dialogs/music/music.css +30 -0
  96. package/ueditor/dialogs/music/music.html +32 -0
  97. package/ueditor/dialogs/music/music.js +192 -0
  98. package/ueditor/dialogs/preview/preview.html +40 -0
  99. package/ueditor/dialogs/scrawl/images/addimg.png +0 -0
  100. package/ueditor/dialogs/scrawl/images/brush.png +0 -0
  101. package/ueditor/dialogs/scrawl/images/delimg.png +0 -0
  102. package/ueditor/dialogs/scrawl/images/delimgH.png +0 -0
  103. package/ueditor/dialogs/scrawl/images/empty.png +0 -0
  104. package/ueditor/dialogs/scrawl/images/emptyH.png +0 -0
  105. package/ueditor/dialogs/scrawl/images/eraser.png +0 -0
  106. package/ueditor/dialogs/scrawl/images/redo.png +0 -0
  107. package/ueditor/dialogs/scrawl/images/redoH.png +0 -0
  108. package/ueditor/dialogs/scrawl/images/scale.png +0 -0
  109. package/ueditor/dialogs/scrawl/images/scaleH.png +0 -0
  110. package/ueditor/dialogs/scrawl/images/size.png +0 -0
  111. package/ueditor/dialogs/scrawl/images/undo.png +0 -0
  112. package/ueditor/dialogs/scrawl/images/undoH.png +0 -0
  113. package/ueditor/dialogs/scrawl/scrawl.css +72 -0
  114. package/ueditor/dialogs/scrawl/scrawl.html +95 -0
  115. package/ueditor/dialogs/scrawl/scrawl.js +670 -0
  116. package/ueditor/dialogs/searchreplace/searchreplace.html +102 -0
  117. package/ueditor/dialogs/searchreplace/searchreplace.js +170 -0
  118. package/ueditor/dialogs/snapscreen/snapscreen.html +58 -0
  119. package/ueditor/dialogs/spechars/spechars.html +21 -0
  120. package/ueditor/dialogs/spechars/spechars.js +57 -0
  121. package/ueditor/dialogs/table/dragicon.png +0 -0
  122. package/ueditor/dialogs/table/edittable.css +84 -0
  123. package/ueditor/dialogs/table/edittable.html +64 -0
  124. package/ueditor/dialogs/table/edittable.js +237 -0
  125. package/ueditor/dialogs/table/edittd.html +61 -0
  126. package/ueditor/dialogs/table/edittip.html +33 -0
  127. package/ueditor/dialogs/template/config.js +42 -0
  128. package/ueditor/dialogs/template/images/bg.gif +0 -0
  129. package/ueditor/dialogs/template/images/pre0.png +0 -0
  130. package/ueditor/dialogs/template/images/pre1.png +0 -0
  131. package/ueditor/dialogs/template/images/pre2.png +0 -0
  132. package/ueditor/dialogs/template/images/pre3.png +0 -0
  133. package/ueditor/dialogs/template/images/pre4.png +0 -0
  134. package/ueditor/dialogs/template/template.css +18 -0
  135. package/ueditor/dialogs/template/template.html +26 -0
  136. package/ueditor/dialogs/template/template.js +53 -0
  137. package/ueditor/dialogs/video/images/bg.png +0 -0
  138. package/ueditor/dialogs/video/images/center_focus.jpg +0 -0
  139. package/ueditor/dialogs/video/images/file-icons.gif +0 -0
  140. package/ueditor/dialogs/video/images/file-icons.png +0 -0
  141. package/ueditor/dialogs/video/images/icons.gif +0 -0
  142. package/ueditor/dialogs/video/images/icons.png +0 -0
  143. package/ueditor/dialogs/video/images/image.png +0 -0
  144. package/ueditor/dialogs/video/images/left_focus.jpg +0 -0
  145. package/ueditor/dialogs/video/images/none_focus.jpg +0 -0
  146. package/ueditor/dialogs/video/images/progress.png +0 -0
  147. package/ueditor/dialogs/video/images/right_focus.jpg +0 -0
  148. package/ueditor/dialogs/video/images/success.gif +0 -0
  149. package/ueditor/dialogs/video/images/success.png +0 -0
  150. package/ueditor/dialogs/video/video.css +635 -0
  151. package/ueditor/dialogs/video/video.html +86 -0
  152. package/ueditor/dialogs/video/video.js +791 -0
  153. package/ueditor/dialogs/webapp/webapp.html +53 -0
  154. package/ueditor/dialogs/wordimage/fClipboard_ueditor.swf +0 -0
  155. package/ueditor/dialogs/wordimage/imageUploader.swf +0 -0
  156. package/ueditor/dialogs/wordimage/tangram.js +1495 -0
  157. package/ueditor/dialogs/wordimage/wordimage.html +111 -0
  158. package/ueditor/dialogs/wordimage/wordimage.js +157 -0
  159. package/ueditor/lang/en/en.js +684 -0
  160. package/ueditor/lang/en/images/addimage.png +0 -0
  161. package/ueditor/lang/en/images/alldeletebtnhoverskin.png +0 -0
  162. package/ueditor/lang/en/images/alldeletebtnupskin.png +0 -0
  163. package/ueditor/lang/en/images/background.png +0 -0
  164. package/ueditor/lang/en/images/button.png +0 -0
  165. package/ueditor/lang/en/images/copy.png +0 -0
  166. package/ueditor/lang/en/images/deletedisable.png +0 -0
  167. package/ueditor/lang/en/images/deleteenable.png +0 -0
  168. package/ueditor/lang/en/images/listbackground.png +0 -0
  169. package/ueditor/lang/en/images/localimage.png +0 -0
  170. package/ueditor/lang/en/images/music.png +0 -0
  171. package/ueditor/lang/en/images/rotateleftdisable.png +0 -0
  172. package/ueditor/lang/en/images/rotateleftenable.png +0 -0
  173. package/ueditor/lang/en/images/rotaterightdisable.png +0 -0
  174. package/ueditor/lang/en/images/rotaterightenable.png +0 -0
  175. package/ueditor/lang/en/images/upload.png +0 -0
  176. package/ueditor/lang/zh-cn/images/copy.png +0 -0
  177. package/ueditor/lang/zh-cn/images/localimage.png +0 -0
  178. package/ueditor/lang/zh-cn/images/music.png +0 -0
  179. package/ueditor/lang/zh-cn/images/upload.png +0 -0
  180. package/ueditor/lang/zh-cn/zh-cn.js +669 -0
  181. package/ueditor/official-demo.html +175 -0
  182. package/ueditor/themes/default/css/ueditor.css +1906 -0
  183. package/ueditor/themes/default/css/ueditor.min.css +8 -0
  184. package/ueditor/themes/default/dialogbase.css +100 -0
  185. package/ueditor/themes/default/images/anchor.gif +0 -0
  186. package/ueditor/themes/default/images/arrow.png +0 -0
  187. package/ueditor/themes/default/images/arrow_down.png +0 -0
  188. package/ueditor/themes/default/images/arrow_up.png +0 -0
  189. package/ueditor/themes/default/images/button-bg.gif +0 -0
  190. package/ueditor/themes/default/images/cancelbutton.gif +0 -0
  191. package/ueditor/themes/default/images/charts.png +0 -0
  192. package/ueditor/themes/default/images/cursor_h.gif +0 -0
  193. package/ueditor/themes/default/images/cursor_h.png +0 -0
  194. package/ueditor/themes/default/images/cursor_v.gif +0 -0
  195. package/ueditor/themes/default/images/cursor_v.png +0 -0
  196. package/ueditor/themes/default/images/dialog-title-bg.png +0 -0
  197. package/ueditor/themes/default/images/filescan.png +0 -0
  198. package/ueditor/themes/default/images/highlighted.gif +0 -0
  199. package/ueditor/themes/default/images/icons-all.gif +0 -0
  200. package/ueditor/themes/default/images/icons.gif +0 -0
  201. package/ueditor/themes/default/images/icons.png +0 -0
  202. package/ueditor/themes/default/images/img-cracked.png +0 -0
  203. package/ueditor/themes/default/images/loaderror.png +0 -0
  204. package/ueditor/themes/default/images/loading.gif +0 -0
  205. package/ueditor/themes/default/images/lock.gif +0 -0
  206. package/ueditor/themes/default/images/neweditor-tab-bg.png +0 -0
  207. package/ueditor/themes/default/images/pagebreak.gif +0 -0
  208. package/ueditor/themes/default/images/scale.png +0 -0
  209. package/ueditor/themes/default/images/sortable.png +0 -0
  210. package/ueditor/themes/default/images/spacer.gif +0 -0
  211. package/ueditor/themes/default/images/sparator_v.png +0 -0
  212. package/ueditor/themes/default/images/table-cell-align.png +0 -0
  213. package/ueditor/themes/default/images/tangram-colorpicker.png +0 -0
  214. package/ueditor/themes/default/images/toolbar_bg.png +0 -0
  215. package/ueditor/themes/default/images/unhighlighted.gif +0 -0
  216. package/ueditor/themes/default/images/upload.png +0 -0
  217. package/ueditor/themes/default/images/videologo.gif +0 -0
  218. package/ueditor/themes/default/images/word.gif +0 -0
  219. package/ueditor/themes/default/images/wordpaste.png +0 -0
  220. package/ueditor/themes/iframe.css +1 -0
  221. package/ueditor/third-party/SyntaxHighlighter/shCore.js +3655 -0
  222. package/ueditor/third-party/SyntaxHighlighter/shCoreDefault.css +1 -0
  223. package/ueditor/third-party/codemirror/codemirror.css +104 -0
  224. package/ueditor/third-party/codemirror/codemirror.js +3581 -0
  225. package/ueditor/third-party/highcharts/adapters/mootools-adapter.js +13 -0
  226. package/ueditor/third-party/highcharts/adapters/mootools-adapter.src.js +313 -0
  227. package/ueditor/third-party/highcharts/adapters/prototype-adapter.js +15 -0
  228. package/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js +316 -0
  229. package/ueditor/third-party/highcharts/adapters/standalone-framework.js +17 -0
  230. package/ueditor/third-party/highcharts/adapters/standalone-framework.src.js +583 -0
  231. package/ueditor/third-party/highcharts/highcharts-more.js +50 -0
  232. package/ueditor/third-party/highcharts/highcharts-more.src.js +2430 -0
  233. package/ueditor/third-party/highcharts/highcharts.js +283 -0
  234. package/ueditor/third-party/highcharts/highcharts.src.js +16974 -0
  235. package/ueditor/third-party/highcharts/modules/annotations.js +7 -0
  236. package/ueditor/third-party/highcharts/modules/annotations.src.js +401 -0
  237. package/ueditor/third-party/highcharts/modules/canvas-tools.js +133 -0
  238. package/ueditor/third-party/highcharts/modules/canvas-tools.src.js +3113 -0
  239. package/ueditor/third-party/highcharts/modules/data.js +17 -0
  240. package/ueditor/third-party/highcharts/modules/data.src.js +582 -0
  241. package/ueditor/third-party/highcharts/modules/drilldown.js +11 -0
  242. package/ueditor/third-party/highcharts/modules/drilldown.src.js +447 -0
  243. package/ueditor/third-party/highcharts/modules/exporting.js +22 -0
  244. package/ueditor/third-party/highcharts/modules/exporting.src.js +709 -0
  245. package/ueditor/third-party/highcharts/modules/funnel.js +12 -0
  246. package/ueditor/third-party/highcharts/modules/funnel.src.js +289 -0
  247. package/ueditor/third-party/highcharts/modules/heatmap.js +1 -0
  248. package/ueditor/third-party/highcharts/modules/heatmap.src.js +53 -0
  249. package/ueditor/third-party/highcharts/modules/map.js +27 -0
  250. package/ueditor/third-party/highcharts/modules/map.src.js +1002 -0
  251. package/ueditor/third-party/highcharts/modules/no-data-to-display.js +12 -0
  252. package/ueditor/third-party/highcharts/modules/no-data-to-display.src.js +128 -0
  253. package/ueditor/third-party/highcharts/themes/dark-blue.js +254 -0
  254. package/ueditor/third-party/highcharts/themes/dark-green.js +255 -0
  255. package/ueditor/third-party/highcharts/themes/gray.js +257 -0
  256. package/ueditor/third-party/highcharts/themes/grid.js +103 -0
  257. package/ueditor/third-party/highcharts/themes/skies.js +89 -0
  258. package/ueditor/third-party/jquery-1.10.2.js +9789 -0
  259. package/ueditor/third-party/jquery-1.10.2.min.js +6 -0
  260. package/ueditor/third-party/jquery-1.10.2.min.map +1 -0
  261. package/ueditor/third-party/snapscreen/UEditorSnapscreen.exe +0 -0
  262. package/ueditor/third-party/video-js/font/vjs.eot +0 -0
  263. package/ueditor/third-party/video-js/font/vjs.svg +65 -0
  264. package/ueditor/third-party/video-js/font/vjs.ttf +0 -0
  265. package/ueditor/third-party/video-js/font/vjs.woff +0 -0
  266. package/ueditor/third-party/video-js/video-js.css +766 -0
  267. package/ueditor/third-party/video-js/video-js.min.css +5 -0
  268. package/ueditor/third-party/video-js/video-js.swf +0 -0
  269. package/ueditor/third-party/video-js/video.dev.js +7108 -0
  270. package/ueditor/third-party/video-js/video.js +129 -0
  271. package/ueditor/third-party/webuploader/Uploader.swf +0 -0
  272. package/ueditor/third-party/webuploader/webuploader.css +28 -0
  273. package/ueditor/third-party/webuploader/webuploader.custom.js +5670 -0
  274. package/ueditor/third-party/webuploader/webuploader.custom.min.js +2 -0
  275. package/ueditor/third-party/webuploader/webuploader.flashonly.js +4176 -0
  276. package/ueditor/third-party/webuploader/webuploader.flashonly.min.js +2 -0
  277. package/ueditor/third-party/webuploader/webuploader.html5only.js +5559 -0
  278. package/ueditor/third-party/webuploader/webuploader.html5only.min.js +2 -0
  279. package/ueditor/third-party/webuploader/webuploader.js +6733 -0
  280. package/ueditor/third-party/webuploader/webuploader.min.js +2 -0
  281. package/ueditor/third-party/webuploader/webuploader.withoutimage.js +4593 -0
  282. package/ueditor/third-party/webuploader/webuploader.withoutimage.min.js +2 -0
  283. package/ueditor/third-party/zeroclipboard/ZeroClipboard.js +1256 -0
  284. package/ueditor/third-party/zeroclipboard/ZeroClipboard.min.js +9 -0
  285. package/ueditor/third-party/zeroclipboard/ZeroClipboard.swf +0 -0
  286. package/ueditor/ueditor.all.js +32931 -0
  287. package/ueditor/ueditor.all.min.js +17 -0
  288. package/ueditor/ueditor.config.js +507 -0
  289. package/ueditor/ueditor.parse.js +1230 -0
  290. package/ueditor/ueditor.parse.min.js +5 -0
  291. package/vite.ts +87 -0
@@ -0,0 +1,669 @@
1
+ <script setup>
2
+ /**
3
+ * AllEditor 双引擎门面:共用 wang 工具栏。
4
+ *
5
+ * 引擎约定:仅「导入 HTML」进入 UE;清空 / 导入 Markdown / 其它编辑回 wang。
6
+ * v-model 存「可入库」HTML(默认 wang/ue 都包 data-alleditor-engine 根节点)。
7
+ * 宿主需自行提供 UEditor 静态资源(默认 /ueditor/)。
8
+ */
9
+ import {
10
+ computed,
11
+ nextTick,
12
+ onBeforeUnmount,
13
+ onMounted,
14
+ ref,
15
+ shallowRef,
16
+ watch,
17
+ } from 'vue'
18
+ import { Editor, Toolbar } from '@mnykj/alleditor-for-vue'
19
+ import {
20
+ detectEditorEngine,
21
+ unwrapEditorEngineHtml,
22
+ wrapEditorEngineHtml,
23
+ } from '@mnykj/alleditor-core'
24
+ import UeHtmlEngine from './UeHtmlEngine.vue'
25
+ import { bindUeToolbarAdapter } from './ueToolbar'
26
+ import {
27
+ bindImportMenuHandlers,
28
+ registerImportMenus,
29
+ } from './importMenus'
30
+ import { mergeToolbarConfig } from './defaultToolbar'
31
+ import {
32
+ extractHtmlBody,
33
+ isEffectivelyEmptyHtml,
34
+ markdownToHtml,
35
+ } from './markdown'
36
+ import { stripJavascriptFromHtml } from './stripJavascriptFromHtml'
37
+ import './assets/iconfont/iconfont.css'
38
+
39
+ const props = defineProps({
40
+ modelValue: { type: String, default: '' },
41
+ mode: { type: String, default: 'default' },
42
+ disabled: { type: Boolean, default: false },
43
+ ueditorBase: { type: String, default: '/ueditor/' },
44
+ toolbarConfig: { type: Object, default: () => ({}) },
45
+ editorConfig: { type: Object, default: () => ({}) },
46
+ /** wang 占位正文(UE 模式下避免把高保真 HTML 喂进 Slate) */
47
+ wangPlaceholder: { type: String, default: '<p><br></p>' },
48
+ /** 为 true 时仅 ue 写外层 div;默认 false,wang/ue 都包 data-alleditor-engine */
49
+ wrapOnlyWhenUe: { type: Boolean, default: false },
50
+ /** 是否注册并显示 MD/HTML 导入按钮(默认开启) */
51
+ enableImport: { type: Boolean, default: true },
52
+ /** 正文非空时导入是否 confirm 确认替换 */
53
+ confirmReplaceOnImport: { type: Boolean, default: true },
54
+ toolbarSelector: {
55
+ type: String,
56
+ default: '.alleditor .w-e-toolbar, .alleditor .editor-toolbar',
57
+ },
58
+ /** 是否显示工具栏(回收站等只读场景可关) */
59
+ showToolbar: { type: Boolean, default: true },
60
+ /** 是否显示正文区(HTML 源码模式可关,工具栏仍保留) */
61
+ showWorkarea: { type: Boolean, default: true },
62
+ /** 主栏 class(大纲收起等) */
63
+ mainClass: { type: String, default: '' },
64
+ })
65
+
66
+ const emit = defineEmits([
67
+ 'update:modelValue',
68
+ 'change',
69
+ 'engine-change',
70
+ 'wang-created',
71
+ 'ue-created',
72
+ 'ue-ready',
73
+ 'import',
74
+ 'clear',
75
+ 'customAlert',
76
+ 'customPaste',
77
+ ])
78
+
79
+ /** @type {import('vue').Ref<'wang' | 'ue'>} */
80
+ const engineMode = ref(detectEditorEngine(props.modelValue))
81
+ const rootRef = ref(null)
82
+ const wangEditorRef = shallowRef(null)
83
+ /** 对外 wang 代理:getHtml() 返回带协议外层的入库 HTML(不改 for-vue 内部实例) */
84
+ const wangEditorProxyRef = shallowRef(null)
85
+ const ueEngineRef = shallowRef(null)
86
+ // 首帧即用正文初始化,避免先挂占位再 setHtml 时带着失效选区炸 Slate
87
+ const wangHtml = ref(
88
+ engineMode.value === 'wang'
89
+ ? unwrapEditorEngineHtml(props.modelValue || '') || props.wangPlaceholder
90
+ : props.wangPlaceholder
91
+ )
92
+ const ueHtml = ref(
93
+ engineMode.value === 'ue' ? unwrapEditorEngineHtml(props.modelValue || '') : ''
94
+ )
95
+ const mdFileInputRef = ref(null)
96
+ const htmlFileInputRef = ref(null)
97
+ let toolbarBinding = null
98
+ let applyingExternal = false
99
+
100
+ const useUe = computed(() => engineMode.value === 'ue')
101
+
102
+ const resolvedToolbarConfig = computed(() =>
103
+ mergeToolbarConfig(props.toolbarConfig, { enableImport: props.enableImport })
104
+ )
105
+
106
+ /**
107
+ * 外壳自己负责协议外层;内部 wang 必须 engineMarker:false,
108
+ * 否则 getHtml() 带外层 → 剥开回写 modelValue → for-vue 每次 setHtml,表现为一字一顿。
109
+ */
110
+ const resolvedEditorConfig = computed(() => ({
111
+ ...props.editorConfig,
112
+ engineMarker:
113
+ props.editorConfig &&
114
+ Object.prototype.hasOwnProperty.call(props.editorConfig, 'engineMarker')
115
+ ? props.editorConfig.engineMarker
116
+ : false,
117
+ }))
118
+
119
+ function bodyOf(html) {
120
+ return unwrapEditorEngineHtml(html || '') || '<p><br></p>'
121
+ }
122
+
123
+ function encodeForModel(rawBody) {
124
+ // 先剥外层再包,保证幂等;wang / ue 默认都写 data-alleditor-engine
125
+ const body = bodyOf(rawBody)
126
+ if (engineMode.value === 'ue') {
127
+ return wrapEditorEngineHtml(body, 'ue', {
128
+ onlyWhenUe: props.wrapOnlyWhenUe,
129
+ })
130
+ }
131
+ if (props.wrapOnlyWhenUe) return body
132
+ return wrapEditorEngineHtml(body, 'wang')
133
+ }
134
+
135
+ function emitModel(rawBody) {
136
+ const next = encodeForModel(rawBody)
137
+ emit('update:modelValue', next)
138
+ emit('change', next, engineMode.value)
139
+ }
140
+
141
+ function readWangBody(editor) {
142
+ try {
143
+ // 优先正文 API,避免把协议外层再喂进外壳内部状态
144
+ if (typeof editor?.getHtmlBody === 'function') {
145
+ return editor.getHtmlBody()
146
+ }
147
+ if (editor?.__alleditorRawGetHtml) {
148
+ return editor.__alleditorRawGetHtml()
149
+ }
150
+ return bodyOf(editor?.getHtml?.() || wangHtml.value)
151
+ } catch {
152
+ return wangHtml.value
153
+ }
154
+ }
155
+
156
+ /** 宿主用 wang-created / getWangEditor().getHtml() 时也带回库外层 */
157
+ function createWangEditorProxy(editor) {
158
+ if (!editor || typeof editor !== 'object') return editor
159
+ const rawGetHtml =
160
+ editor.__alleditorRawGetHtml || editor.getHtml.bind(editor)
161
+ if (!editor.__alleditorRawGetHtml) {
162
+ editor.__alleditorRawGetHtml = rawGetHtml
163
+ }
164
+ return new Proxy(editor, {
165
+ get(target, prop, receiver) {
166
+ if (prop === 'getHtml') {
167
+ return () => encodeForModel(rawGetHtml())
168
+ }
169
+ if (prop === 'getHtmlBody' || prop === '__alleditorRawGetHtml') {
170
+ return rawGetHtml
171
+ }
172
+ const value = Reflect.get(target, prop, receiver)
173
+ return typeof value === 'function' ? value.bind(target) : value
174
+ },
175
+ })
176
+ }
177
+
178
+ /** 内部 wangHtml 只存正文,避免把协议外层再 setHtml 进 Slate */
179
+ function onWangHtmlUpdate(html) {
180
+ const next = bodyOf(html)
181
+ if (next === wangHtml.value) return
182
+ wangHtml.value = next
183
+ }
184
+
185
+ function applyIncoming(html, { forceEngine } = {}) {
186
+ applyingExternal = true
187
+ try {
188
+ const nextEngine = forceEngine || detectEditorEngine(html)
189
+ const body = bodyOf(html)
190
+ if (nextEngine !== engineMode.value) {
191
+ engineMode.value = nextEngine
192
+ emit('engine-change', nextEngine)
193
+ }
194
+ if (nextEngine === 'ue') {
195
+ wangHtml.value = props.wangPlaceholder
196
+ ueHtml.value = body
197
+ // 避免把编辑中的正文再 setContent 冲掉(外层 watch / 回写常见)
198
+ const live = bodyOf(ueEngineRef.value?.getContent?.() || '')
199
+ if (live !== body) {
200
+ ueEngineRef.value?.setContent?.(body)
201
+ }
202
+ nextTick(() => bindToolbar())
203
+ } else {
204
+ unbindToolbar()
205
+ ueHtml.value = ''
206
+ wangHtml.value = body
207
+ }
208
+ } finally {
209
+ applyingExternal = false
210
+ }
211
+ }
212
+
213
+ function bindToolbar() {
214
+ unbindToolbar()
215
+ toolbarBinding = bindUeToolbarAdapter({
216
+ toolbar: props.toolbarSelector,
217
+ getUe: () => ueEngineRef.value,
218
+ shouldCapture: () => engineMode.value === 'ue',
219
+ })
220
+ // wang change 会把按钮重新 disabled,UE 态再刷一次可用态
221
+ nextTick(() => toolbarBinding?.syncEnabled?.())
222
+ }
223
+
224
+ function unbindToolbar() {
225
+ toolbarBinding?.unbind?.()
226
+ toolbarBinding = null
227
+ }
228
+
229
+ function onWangCreated(editor) {
230
+ wangEditorRef.value = editor
231
+ const proxy = createWangEditorProxy(editor)
232
+ wangEditorProxyRef.value = proxy
233
+ emit('wang-created', proxy)
234
+ // UE 模式下 wang 仍会 onChange 刷新工具栏灰态,跟一次同步
235
+ try {
236
+ editor.on?.('change', () => {
237
+ if (engineMode.value === 'ue') toolbarBinding?.syncEnabled?.()
238
+ })
239
+ } catch {
240
+ /* ignore */
241
+ }
242
+ if (engineMode.value === 'ue') {
243
+ nextTick(() => {
244
+ bindToolbar()
245
+ toolbarBinding?.syncEnabled?.()
246
+ })
247
+ }
248
+ }
249
+
250
+ function onWangChange(editor) {
251
+ if (applyingExternal || engineMode.value !== 'wang') return
252
+ try {
253
+ const body = bodyOf(readWangBody(editor))
254
+ if (wangHtml.value !== body) wangHtml.value = body
255
+ emitModel(body)
256
+ } catch {
257
+ emitModel(wangHtml.value)
258
+ }
259
+ }
260
+
261
+ function onUeUpdate(html) {
262
+ if (applyingExternal || engineMode.value !== 'ue') return
263
+ ueHtml.value = html
264
+ emitModel(html)
265
+ }
266
+
267
+ function onUeReady(ue) {
268
+ emit('ue-ready', ue)
269
+ bindToolbar()
270
+ }
271
+
272
+ function onUeCreated(ue) {
273
+ emit('ue-created', ue)
274
+ }
275
+
276
+ function getHtml() {
277
+ if (engineMode.value === 'ue') {
278
+ const raw =
279
+ ueEngineRef.value?.getContent?.() ?? ueHtml.value ?? ''
280
+ return encodeForModel(raw)
281
+ }
282
+ try {
283
+ return encodeForModel(readWangBody(wangEditorRef.value) || wangHtml.value)
284
+ } catch {
285
+ return encodeForModel(wangHtml.value)
286
+ }
287
+ }
288
+
289
+ function setHtml(html, options = {}) {
290
+ applyIncoming(html, options)
291
+ }
292
+
293
+ function getEngineMode() {
294
+ return engineMode.value
295
+ }
296
+
297
+ /** 强制切引擎(导入 HTML 等场景) */
298
+ function setEngineMode(mode, html) {
299
+ const next = mode === 'ue' ? 'ue' : 'wang'
300
+ const raw = html !== undefined ? html : getHtml()
301
+ const body = bodyOf(raw)
302
+ applyIncoming(
303
+ next === 'ue'
304
+ ? wrapEditorEngineHtml(body, 'ue')
305
+ : body,
306
+ { forceEngine: next }
307
+ )
308
+ if (next === 'ue' || next === 'wang') {
309
+ emitModel(body)
310
+ }
311
+ }
312
+
313
+ function currentBodyForEmptyCheck() {
314
+ return bodyOf(getHtml())
315
+ }
316
+
317
+ function confirmReplaceIfNeeded() {
318
+ if (!props.confirmReplaceOnImport) return true
319
+ if (isEffectivelyEmptyHtml(currentBodyForEmptyCheck())) return true
320
+ return window.confirm('导入将替换当前正文内容,是否继续?')
321
+ }
322
+
323
+ function openMarkdownPicker() {
324
+ if (props.disabled) return
325
+ mdFileInputRef.value?.click?.()
326
+ }
327
+
328
+ function openHtmlPicker() {
329
+ if (props.disabled) return
330
+ htmlFileInputRef.value?.click?.()
331
+ }
332
+
333
+ async function onMarkdownFileSelected(e) {
334
+ const file = e.target?.files?.[0]
335
+ if (e.target) e.target.value = ''
336
+ if (!file) return
337
+ if (!/\.md$/i.test(file.name)) {
338
+ window.alert('请选择 .md 文件')
339
+ return
340
+ }
341
+ if (!confirmReplaceIfNeeded()) return
342
+ try {
343
+ const text = await file.text()
344
+ const html = await markdownToHtml(text || '')
345
+ setEngineMode('wang', html)
346
+ emit('import', {
347
+ type: 'markdown',
348
+ fileName: file.name,
349
+ html: getHtml(),
350
+ })
351
+ } catch (err) {
352
+ console.error(err)
353
+ window.alert(err?.message || '导入 Markdown 失败')
354
+ }
355
+ }
356
+
357
+ async function onHtmlFileSelected(e) {
358
+ const file = e.target?.files?.[0]
359
+ if (e.target) e.target.value = ''
360
+ if (!file) return
361
+ const nameOk =
362
+ /\.html?$/i.test(file.name) ||
363
+ /text\/html/i.test(file.type || '')
364
+ if (!nameOk) {
365
+ window.alert('请选择 .html / .htm 文件')
366
+ return
367
+ }
368
+ if (!confirmReplaceIfNeeded()) return
369
+ try {
370
+ const text = await file.text()
371
+ const body = stripJavascriptFromHtml(extractHtmlBody(text || ''))
372
+ const html = body.trim() || '<p><br></p>'
373
+ setEngineMode('ue', html)
374
+ emit('import', {
375
+ type: 'html',
376
+ fileName: file.name,
377
+ html: getHtml(),
378
+ })
379
+ } catch (err) {
380
+ console.error(err)
381
+ window.alert(err?.message || '导入 HTML 失败')
382
+ }
383
+ }
384
+
385
+ function clearAllContent() {
386
+ if (props.disabled) return
387
+ if (!window.confirm('确认清空文档?清空后不可恢复。')) return
388
+ // 清空后回到 wang;仅导入 HTML 才进入 UE
389
+ setEngineMode('wang', '<p><br></p>')
390
+ emit('clear')
391
+ }
392
+
393
+ function wireImportHandlers() {
394
+ registerImportMenus()
395
+ if (!props.enableImport) {
396
+ bindImportMenuHandlers({
397
+ onImportHtml: null,
398
+ onImportMarkdown: null,
399
+ onClearContent: clearAllContent,
400
+ })
401
+ return
402
+ }
403
+ bindImportMenuHandlers({
404
+ onImportHtml: openHtmlPicker,
405
+ onImportMarkdown: openMarkdownPicker,
406
+ onClearContent: clearAllContent,
407
+ })
408
+ }
409
+
410
+ watch(
411
+ () => props.modelValue,
412
+ (html) => {
413
+ if (applyingExternal) return
414
+ const incomingEngine = detectEditorEngine(html)
415
+ const incomingBody = bodyOf(html)
416
+ const currentBody =
417
+ engineMode.value === 'ue'
418
+ ? bodyOf(ueHtml.value)
419
+ : bodyOf(wangHtml.value)
420
+ if (
421
+ incomingEngine === engineMode.value &&
422
+ incomingBody === currentBody
423
+ ) {
424
+ return
425
+ }
426
+ applyIncoming(html)
427
+ }
428
+ )
429
+
430
+ watch(engineMode, (mode) => {
431
+ if (mode === 'ue') nextTick(() => bindToolbar())
432
+ else unbindToolbar()
433
+ })
434
+
435
+ watch(
436
+ () => props.enableImport,
437
+ () => wireImportHandlers()
438
+ )
439
+
440
+ applyIncoming(props.modelValue)
441
+
442
+ onMounted(() => {
443
+ wireImportHandlers()
444
+ })
445
+
446
+ onBeforeUnmount(() => {
447
+ unbindToolbar()
448
+ bindImportMenuHandlers({
449
+ onImportHtml: null,
450
+ onImportMarkdown: null,
451
+ onClearContent: null,
452
+ })
453
+ const ed = wangEditorRef.value
454
+ if (ed && !ed.isDestroyed) {
455
+ try {
456
+ ed.destroy()
457
+ } catch {
458
+ /* ignore */
459
+ }
460
+ }
461
+ })
462
+
463
+ defineExpose({
464
+ getHtml,
465
+ setHtml,
466
+ getEngineMode,
467
+ setEngineMode,
468
+ getWangEditor: () => wangEditorProxyRef.value || wangEditorRef.value,
469
+ getUeEngine: () => ueEngineRef.value,
470
+ openMarkdownPicker,
471
+ openHtmlPicker,
472
+ engineMode,
473
+ })
474
+ </script>
475
+
476
+ <template>
477
+ <div ref="rootRef" class="alleditor" :data-engine="engineMode">
478
+ <Toolbar
479
+ v-if="showToolbar && wangEditorRef"
480
+ :editor="wangEditorRef"
481
+ :default-config="resolvedToolbarConfig"
482
+ :mode="mode"
483
+ class="alleditor__toolbar editor-toolbar"
484
+ />
485
+ <div v-show="showWorkarea" class="alleditor__body">
486
+ <slot name="aside" />
487
+ <div class="alleditor__main" :class="mainClass">
488
+ <slot name="main-before" />
489
+ <!-- UE 时离屏挂着 wang,避免 display:none 破坏 TextArea / Toolbar 绑定 -->
490
+ <Editor
491
+ :model-value="wangHtml"
492
+ :default-config="resolvedEditorConfig"
493
+ :mode="mode"
494
+ class="alleditor__wang editor-content"
495
+ :class="{ 'is-wang-parked': useUe }"
496
+ @update:model-value="onWangHtmlUpdate"
497
+ @onCreated="onWangCreated"
498
+ @onChange="onWangChange"
499
+ @customAlert="(...a) => emit('customAlert', ...a)"
500
+ @customPaste="(...a) => emit('customPaste', ...a)"
501
+ />
502
+ <div v-if="useUe" class="alleditor__ue-wrap">
503
+ <UeHtmlEngine
504
+ ref="ueEngineRef"
505
+ v-model="ueHtml"
506
+ :disabled="disabled"
507
+ :ueditor-base="ueditorBase"
508
+ class="alleditor__ue"
509
+ @created="onUeCreated"
510
+ @ready="onUeReady"
511
+ @change="onUeUpdate"
512
+ />
513
+ </div>
514
+ <slot name="main-after" />
515
+ </div>
516
+ </div>
517
+ <input
518
+ v-if="enableImport"
519
+ ref="mdFileInputRef"
520
+ type="file"
521
+ accept=".md,text/markdown"
522
+ class="alleditor__file-input"
523
+ @change="onMarkdownFileSelected"
524
+ />
525
+ <input
526
+ v-if="enableImport"
527
+ ref="htmlFileInputRef"
528
+ type="file"
529
+ accept=".html,.htm,text/html"
530
+ class="alleditor__file-input"
531
+ @change="onHtmlFileSelected"
532
+ />
533
+ </div>
534
+ </template>
535
+
536
+ <style>
537
+ .alleditor {
538
+ display: flex;
539
+ flex-direction: column;
540
+ width: 100%;
541
+ height: 100%;
542
+ min-height: 0;
543
+ background: #fff;
544
+ overflow: visible;
545
+ /* 隔离内部 z-index,避免工具栏压过站点顶栏「所有产品」等下拉 */
546
+ position: relative;
547
+ z-index: 0;
548
+ isolation: isolate;
549
+ }
550
+
551
+ .alleditor__toolbar,
552
+ .alleditor .editor-toolbar,
553
+ .alleditor .w-e-toolbar {
554
+ flex-shrink: 0;
555
+ position: relative;
556
+ /* 仅在 .alleditor 内部高于 UE 编辑区;不会逃逸盖住站点导航 */
557
+ z-index: 20;
558
+ overflow: visible !important;
559
+ }
560
+
561
+ /*
562
+ * 不要给每个 .w-e-bar-item 设 z-index,否则会各自形成层叠上下文,
563
+ * 色板等下拉的 z-index 出不去,会被工具栏下一行按钮盖住。
564
+ */
565
+ .alleditor .w-e-bar-item {
566
+ position: relative;
567
+ }
568
+ .alleditor .w-e-drop-panel,
569
+ .alleditor .w-e-select-list,
570
+ .alleditor .w-e-bar-item-menus-container,
571
+ .alleditor .w-e-modal {
572
+ z-index: 30;
573
+ }
574
+
575
+ /* UE 编辑区整体压在工具栏之下(iframe 单独合成层易盖住邻居) */
576
+ .alleditor[data-engine='ue'] .alleditor__body {
577
+ z-index: 1;
578
+ }
579
+ .alleditor[data-engine='ue'] .alleditor__ue-wrap,
580
+ .alleditor[data-engine='ue'] .alleditor__ue,
581
+ .alleditor[data-engine='ue'] .alleditor-ue-engine {
582
+ position: relative;
583
+ z-index: 0;
584
+ }
585
+
586
+ /* iconfont 与工具栏 SVG 对齐 */
587
+ .alleditor .w-e-bar-item .iconfont {
588
+ display: inline-block;
589
+ width: 16px;
590
+ height: 16px;
591
+ line-height: 16px;
592
+ font-size: 16px;
593
+ color: inherit;
594
+ vertical-align: middle;
595
+ }
596
+
597
+ /* UE 态:可映射按钮由 ueToolbar 去掉 disabled;不可映射项保持灰显即可 */
598
+ .alleditor[data-engine='ue'] .alleditor__toolbar button.disabled,
599
+ .alleditor[data-engine='ue'] .editor-toolbar button.disabled {
600
+ opacity: 0.35;
601
+ cursor: not-allowed;
602
+ }
603
+
604
+ .alleditor__body {
605
+ position: relative;
606
+ flex: 1 1 0;
607
+ min-height: 0;
608
+ display: flex;
609
+ flex-direction: row;
610
+ overflow: hidden;
611
+ }
612
+
613
+ .alleditor__main {
614
+ position: relative;
615
+ flex: 1 1 0;
616
+ min-width: 0;
617
+ min-height: 0;
618
+ display: flex;
619
+ flex-direction: column;
620
+ overflow: hidden;
621
+ }
622
+
623
+ .alleditor__wang {
624
+ flex: 1 1 0;
625
+ min-height: 0;
626
+ height: 100%;
627
+ }
628
+
629
+ .alleditor__wang.is-wang-parked {
630
+ position: absolute !important;
631
+ left: -10000px !important;
632
+ top: 0 !important;
633
+ width: 800px !important;
634
+ height: 400px !important;
635
+ margin: 0 !important;
636
+ padding: 0 !important;
637
+ overflow: hidden !important;
638
+ opacity: 0 !important;
639
+ visibility: hidden !important;
640
+ pointer-events: none !important;
641
+ flex: none !important;
642
+ z-index: -1;
643
+ }
644
+
645
+ .alleditor__ue-wrap {
646
+ flex: 1 1 0;
647
+ min-height: 0;
648
+ height: 100%;
649
+ display: flex;
650
+ flex-direction: column;
651
+ }
652
+
653
+ .alleditor__ue {
654
+ flex: 1 1 0;
655
+ min-height: 0;
656
+ height: 100%;
657
+ }
658
+
659
+ .alleditor__file-input {
660
+ position: absolute !important;
661
+ width: 1px !important;
662
+ height: 1px !important;
663
+ padding: 0 !important;
664
+ margin: -1px !important;
665
+ overflow: hidden !important;
666
+ clip: rect(0, 0, 0, 0) !important;
667
+ border: 0 !important;
668
+ }
669
+ </style>
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ /**
3
+ * @deprecated 请使用 AllEditor。保留此文件仅为兼容旧导入路径。
4
+ */
5
+ import AllEditor from './AllEditor.vue'
6
+ export default AllEditor
7
+ </script>