vditor 3.8.7

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 (419) hide show
  1. package/CHANGELOG.md +1072 -0
  2. package/LICENSE +21 -0
  3. package/README.md +649 -0
  4. package/dist/css/content-theme/ant-design.css +210 -0
  5. package/dist/css/content-theme/dark.css +123 -0
  6. package/dist/css/content-theme/light.css +101 -0
  7. package/dist/css/content-theme/wechat.css +94 -0
  8. package/dist/images/.DS_Store +0 -0
  9. package/dist/images/emoji/b3log.png +0 -0
  10. package/dist/images/emoji/chainbook.png +0 -0
  11. package/dist/images/emoji/doge.png +0 -0
  12. package/dist/images/emoji/hacpai.png +0 -0
  13. package/dist/images/emoji/huaji.gif +0 -0
  14. package/dist/images/emoji/latke.png +0 -0
  15. package/dist/images/emoji/lute.png +0 -0
  16. package/dist/images/emoji/octocat.png +0 -0
  17. package/dist/images/emoji/pipe.png +0 -0
  18. package/dist/images/emoji/solo.png +0 -0
  19. package/dist/images/emoji/sym.png +0 -0
  20. package/dist/images/emoji/trollface.png +0 -0
  21. package/dist/images/emoji/vditor.png +0 -0
  22. package/dist/images/emoji/wide.png +0 -0
  23. package/dist/images/emoji/wulian.png +0 -0
  24. package/dist/images/img-loading.svg +1 -0
  25. package/dist/images/logo.png +0 -0
  26. package/dist/index.css +28 -0
  27. package/dist/index.d.ts +75 -0
  28. package/dist/index.min.js +15353 -0
  29. package/dist/js/.DS_Store +0 -0
  30. package/dist/js/abcjs/abcjs_basic.min.js +3 -0
  31. package/dist/js/echarts/echarts.min.js +23 -0
  32. package/dist/js/flowchart.js/flowchart.min.js +9 -0
  33. package/dist/js/graphviz/full.render.js +90 -0
  34. package/dist/js/graphviz/viz.js +333 -0
  35. package/dist/js/highlight.js/highlight.pack.js +1617 -0
  36. package/dist/js/highlight.js/styles/abap.css +155 -0
  37. package/dist/js/highlight.js/styles/algol.css +142 -0
  38. package/dist/js/highlight.js/styles/algol_nu.css +90 -0
  39. package/dist/js/highlight.js/styles/ant-design.css +469 -0
  40. package/dist/js/highlight.js/styles/arduino.css +155 -0
  41. package/dist/js/highlight.js/styles/autumn.css +136 -0
  42. package/dist/js/highlight.js/styles/borland.css +146 -0
  43. package/dist/js/highlight.js/styles/bw.css +149 -0
  44. package/dist/js/highlight.js/styles/colorful.css +156 -0
  45. package/dist/js/highlight.js/styles/dracula.css +139 -0
  46. package/dist/js/highlight.js/styles/emacs.css +166 -0
  47. package/dist/js/highlight.js/styles/friendly.css +182 -0
  48. package/dist/js/highlight.js/styles/fruity.css +121 -0
  49. package/dist/js/highlight.js/styles/github.css +173 -0
  50. package/dist/js/highlight.js/styles/igor.css +122 -0
  51. package/dist/js/highlight.js/styles/lovelace.css +145 -0
  52. package/dist/js/highlight.js/styles/manni.css +138 -0
  53. package/dist/js/highlight.js/styles/monokai.css +131 -0
  54. package/dist/js/highlight.js/styles/monokailight.css +179 -0
  55. package/dist/js/highlight.js/styles/murphy.css +144 -0
  56. package/dist/js/highlight.js/styles/native.css +163 -0
  57. package/dist/js/highlight.js/styles/paraiso-dark.css +136 -0
  58. package/dist/js/highlight.js/styles/paraiso-light.css +135 -0
  59. package/dist/js/highlight.js/styles/pastie.css +180 -0
  60. package/dist/js/highlight.js/styles/perldoc.css +140 -0
  61. package/dist/js/highlight.js/styles/pygments.css +158 -0
  62. package/dist/js/highlight.js/styles/rainbow_dash.css +163 -0
  63. package/dist/js/highlight.js/styles/rrt.css +158 -0
  64. package/dist/js/highlight.js/styles/solarized-dark.css +145 -0
  65. package/dist/js/highlight.js/styles/solarized-dark256.css +145 -0
  66. package/dist/js/highlight.js/styles/solarized-light.css +162 -0
  67. package/dist/js/highlight.js/styles/swapoff.css +144 -0
  68. package/dist/js/highlight.js/styles/tango.css +183 -0
  69. package/dist/js/highlight.js/styles/trac.css +166 -0
  70. package/dist/js/highlight.js/styles/vim.css +143 -0
  71. package/dist/js/highlight.js/styles/vs.css +112 -0
  72. package/dist/js/highlight.js/styles/xcode.css +173 -0
  73. package/dist/js/i18n/en_US.js +85 -0
  74. package/dist/js/i18n/ja_JP.js +85 -0
  75. package/dist/js/i18n/ko_KR.js +85 -0
  76. package/dist/js/i18n/ru_RU.js +85 -0
  77. package/dist/js/i18n/zh_CN.js +85 -0
  78. package/dist/js/i18n/zh_TW.js +85 -0
  79. package/dist/js/icons/ant.js +174 -0
  80. package/dist/js/icons/material.js +195 -0
  81. package/dist/js/katex/fonts/KaTeX_AMS-Regular.ttf +0 -0
  82. package/dist/js/katex/fonts/KaTeX_AMS-Regular.woff +0 -0
  83. package/dist/js/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  84. package/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  85. package/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  86. package/dist/js/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  87. package/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  88. package/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  89. package/dist/js/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  90. package/dist/js/katex/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  91. package/dist/js/katex/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  92. package/dist/js/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  93. package/dist/js/katex/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  94. package/dist/js/katex/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  95. package/dist/js/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  96. package/dist/js/katex/fonts/KaTeX_Main-Bold.ttf +0 -0
  97. package/dist/js/katex/fonts/KaTeX_Main-Bold.woff +0 -0
  98. package/dist/js/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  99. package/dist/js/katex/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  100. package/dist/js/katex/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  101. package/dist/js/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  102. package/dist/js/katex/fonts/KaTeX_Main-Italic.ttf +0 -0
  103. package/dist/js/katex/fonts/KaTeX_Main-Italic.woff +0 -0
  104. package/dist/js/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  105. package/dist/js/katex/fonts/KaTeX_Main-Regular.ttf +0 -0
  106. package/dist/js/katex/fonts/KaTeX_Main-Regular.woff +0 -0
  107. package/dist/js/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  108. package/dist/js/katex/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  109. package/dist/js/katex/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  110. package/dist/js/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  111. package/dist/js/katex/fonts/KaTeX_Math-Italic.ttf +0 -0
  112. package/dist/js/katex/fonts/KaTeX_Math-Italic.woff +0 -0
  113. package/dist/js/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  114. package/dist/js/katex/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  115. package/dist/js/katex/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  116. package/dist/js/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  117. package/dist/js/katex/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  118. package/dist/js/katex/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  119. package/dist/js/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  120. package/dist/js/katex/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  121. package/dist/js/katex/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  122. package/dist/js/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  123. package/dist/js/katex/fonts/KaTeX_Script-Regular.ttf +0 -0
  124. package/dist/js/katex/fonts/KaTeX_Script-Regular.woff +0 -0
  125. package/dist/js/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  126. package/dist/js/katex/fonts/KaTeX_Size1-Regular.ttf +0 -0
  127. package/dist/js/katex/fonts/KaTeX_Size1-Regular.woff +0 -0
  128. package/dist/js/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  129. package/dist/js/katex/fonts/KaTeX_Size2-Regular.ttf +0 -0
  130. package/dist/js/katex/fonts/KaTeX_Size2-Regular.woff +0 -0
  131. package/dist/js/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  132. package/dist/js/katex/fonts/KaTeX_Size3-Regular.ttf +0 -0
  133. package/dist/js/katex/fonts/KaTeX_Size3-Regular.woff +0 -0
  134. package/dist/js/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  135. package/dist/js/katex/fonts/KaTeX_Size4-Regular.ttf +0 -0
  136. package/dist/js/katex/fonts/KaTeX_Size4-Regular.woff +0 -0
  137. package/dist/js/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  138. package/dist/js/katex/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  139. package/dist/js/katex/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  140. package/dist/js/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  141. package/dist/js/katex/katex.min.css +1 -0
  142. package/dist/js/katex/katex.min.js +2 -0
  143. package/dist/js/lute/.DS_Store +0 -0
  144. package/dist/js/lute/lute.min.js +46 -0
  145. package/dist/js/mathjax/.DS_Store +0 -0
  146. package/dist/js/mathjax/LICENSE +202 -0
  147. package/dist/js/mathjax/a11y/assistive-mml.js +1 -0
  148. package/dist/js/mathjax/a11y/complexity.js +1 -0
  149. package/dist/js/mathjax/a11y/explorer.js +1 -0
  150. package/dist/js/mathjax/a11y/semantic-enrich.js +1 -0
  151. package/dist/js/mathjax/input/asciimath.js +1 -0
  152. package/dist/js/mathjax/input/mml/entities.js +1 -0
  153. package/dist/js/mathjax/input/mml.js +1 -0
  154. package/dist/js/mathjax/input/tex/extensions/action.js +1 -0
  155. package/dist/js/mathjax/input/tex/extensions/all-packages.js +1 -0
  156. package/dist/js/mathjax/input/tex/extensions/ams.js +1 -0
  157. package/dist/js/mathjax/input/tex/extensions/amscd.js +1 -0
  158. package/dist/js/mathjax/input/tex/extensions/autoload.js +1 -0
  159. package/dist/js/mathjax/input/tex/extensions/bbox.js +1 -0
  160. package/dist/js/mathjax/input/tex/extensions/boldsymbol.js +1 -0
  161. package/dist/js/mathjax/input/tex/extensions/braket.js +1 -0
  162. package/dist/js/mathjax/input/tex/extensions/bussproofs.js +1 -0
  163. package/dist/js/mathjax/input/tex/extensions/cancel.js +1 -0
  164. package/dist/js/mathjax/input/tex/extensions/color.js +1 -0
  165. package/dist/js/mathjax/input/tex/extensions/colorV2.js +1 -0
  166. package/dist/js/mathjax/input/tex/extensions/configMacros.js +1 -0
  167. package/dist/js/mathjax/input/tex/extensions/enclose.js +1 -0
  168. package/dist/js/mathjax/input/tex/extensions/extpfeil.js +1 -0
  169. package/dist/js/mathjax/input/tex/extensions/html.js +1 -0
  170. package/dist/js/mathjax/input/tex/extensions/mhchem.js +1 -0
  171. package/dist/js/mathjax/input/tex/extensions/newcommand.js +1 -0
  172. package/dist/js/mathjax/input/tex/extensions/noerrors.js +1 -0
  173. package/dist/js/mathjax/input/tex/extensions/noundefined.js +1 -0
  174. package/dist/js/mathjax/input/tex/extensions/physics.js +1 -0
  175. package/dist/js/mathjax/input/tex/extensions/require.js +1 -0
  176. package/dist/js/mathjax/input/tex/extensions/tagFormat.js +1 -0
  177. package/dist/js/mathjax/input/tex/extensions/textmacros.js +1 -0
  178. package/dist/js/mathjax/input/tex/extensions/unicode.js +1 -0
  179. package/dist/js/mathjax/input/tex/extensions/verb.js +1 -0
  180. package/dist/js/mathjax/input/tex-base.js +1 -0
  181. package/dist/js/mathjax/input/tex-full.js +1 -0
  182. package/dist/js/mathjax/input/tex.js +1 -0
  183. package/dist/js/mathjax/sre/mathmaps/de.js +104 -0
  184. package/dist/js/mathjax/sre/mathmaps/en.js +110 -0
  185. package/dist/js/mathjax/sre/mathmaps/es.js +104 -0
  186. package/dist/js/mathjax/sre/mathmaps/fr.js +104 -0
  187. package/dist/js/mathjax/sre/mathmaps/mathmaps_ie.js +518 -0
  188. package/dist/js/mathjax/sre/mathmaps/nemeth.js +104 -0
  189. package/dist/js/mathjax/sre/sre-node.js +11 -0
  190. package/dist/js/mathjax/sre/sre_browser.js +1633 -0
  191. package/dist/js/mathjax/tex-svg-full.js +1 -0
  192. package/dist/js/mermaid/mermaid.min.js +32 -0
  193. package/dist/js/plantuml/plantuml-encoder.min.js +1 -0
  194. package/dist/method.d.ts +48 -0
  195. package/dist/method.min.js +2346 -0
  196. package/dist/ts/constants.d.ts +43 -0
  197. package/dist/ts/devtools/index.d.ts +7 -0
  198. package/dist/ts/export/index.d.ts +5 -0
  199. package/dist/ts/hint/index.d.ts +14 -0
  200. package/dist/ts/ir/expandMarker.d.ts +2 -0
  201. package/dist/ts/ir/highlightToolbarIR.d.ts +2 -0
  202. package/dist/ts/ir/index.d.ts +13 -0
  203. package/dist/ts/ir/input.d.ts +2 -0
  204. package/dist/ts/ir/process.d.ts +9 -0
  205. package/dist/ts/ir/processKeydown.d.ts +2 -0
  206. package/dist/ts/markdown/abcRender.d.ts +1 -0
  207. package/dist/ts/markdown/adapterRender.d.ts +33 -0
  208. package/dist/ts/markdown/anchorRender.d.ts +1 -0
  209. package/dist/ts/markdown/chartRender.d.ts +1 -0
  210. package/dist/ts/markdown/codeRender.d.ts +1 -0
  211. package/dist/ts/markdown/flowchartRender.d.ts +1 -0
  212. package/dist/ts/markdown/getHTML.d.ts +2 -0
  213. package/dist/ts/markdown/getMarkdown.d.ts +2 -0
  214. package/dist/ts/markdown/graphvizRender.d.ts +1 -0
  215. package/dist/ts/markdown/highlightRender.d.ts +2 -0
  216. package/dist/ts/markdown/lazyLoadImageRender.d.ts +6 -0
  217. package/dist/ts/markdown/mathRender.d.ts +10 -0
  218. package/dist/ts/markdown/mediaRender.d.ts +1 -0
  219. package/dist/ts/markdown/mermaidRender.d.ts +1 -0
  220. package/dist/ts/markdown/mindmapRender.d.ts +1 -0
  221. package/dist/ts/markdown/outlineRender.d.ts +2 -0
  222. package/dist/ts/markdown/plantumlRender.d.ts +1 -0
  223. package/dist/ts/markdown/previewRender.d.ts +3 -0
  224. package/dist/ts/markdown/setLute.d.ts +2 -0
  225. package/dist/ts/markdown/speechRender.d.ts +7 -0
  226. package/dist/ts/outline/index.d.ts +7 -0
  227. package/dist/ts/preview/image.d.ts +2 -0
  228. package/dist/ts/preview/index.d.ts +9 -0
  229. package/dist/ts/resize/index.d.ts +6 -0
  230. package/dist/ts/sv/index.d.ts +13 -0
  231. package/dist/ts/sv/inputEvent.d.ts +2 -0
  232. package/dist/ts/sv/process.d.ts +12 -0
  233. package/dist/ts/sv/processKeydown.d.ts +2 -0
  234. package/dist/ts/tip/index.d.ts +6 -0
  235. package/dist/ts/toolbar/Both.d.ts +5 -0
  236. package/dist/ts/toolbar/Br.d.ts +4 -0
  237. package/dist/ts/toolbar/CodeTheme.d.ts +6 -0
  238. package/dist/ts/toolbar/ContentTheme.d.ts +6 -0
  239. package/dist/ts/toolbar/Counter.d.ts +6 -0
  240. package/dist/ts/toolbar/Custom.d.ts +5 -0
  241. package/dist/ts/toolbar/Devtools.d.ts +5 -0
  242. package/dist/ts/toolbar/Divider.d.ts +4 -0
  243. package/dist/ts/toolbar/EditMode.d.ts +8 -0
  244. package/dist/ts/toolbar/Emoji.d.ts +7 -0
  245. package/dist/ts/toolbar/Export.d.ts +6 -0
  246. package/dist/ts/toolbar/Fullscreen.d.ts +6 -0
  247. package/dist/ts/toolbar/Headings.d.ts +7 -0
  248. package/dist/ts/toolbar/Help.d.ts +5 -0
  249. package/dist/ts/toolbar/Indent.d.ts +5 -0
  250. package/dist/ts/toolbar/Info.d.ts +5 -0
  251. package/dist/ts/toolbar/InsertAfter.d.ts +5 -0
  252. package/dist/ts/toolbar/InsertBefore.d.ts +5 -0
  253. package/dist/ts/toolbar/MenuItem.d.ts +5 -0
  254. package/dist/ts/toolbar/Outdent.d.ts +5 -0
  255. package/dist/ts/toolbar/Outline.d.ts +5 -0
  256. package/dist/ts/toolbar/Preview.d.ts +6 -0
  257. package/dist/ts/toolbar/Record.d.ts +6 -0
  258. package/dist/ts/toolbar/Redo.d.ts +5 -0
  259. package/dist/ts/toolbar/Undo.d.ts +5 -0
  260. package/dist/ts/toolbar/Upload.d.ts +6 -0
  261. package/dist/ts/toolbar/index.d.ts +9 -0
  262. package/dist/ts/toolbar/setToolbar.d.ts +21 -0
  263. package/dist/ts/ui/initUI.d.ts +9 -0
  264. package/dist/ts/ui/setCodeTheme.d.ts +1 -0
  265. package/dist/ts/ui/setContentTheme.d.ts +1 -0
  266. package/dist/ts/ui/setPreviewMode.d.ts +2 -0
  267. package/dist/ts/ui/setTheme.d.ts +2 -0
  268. package/dist/ts/undo/index.d.ts +19 -0
  269. package/dist/ts/upload/getElement.d.ts +2 -0
  270. package/dist/ts/upload/index.d.ts +9 -0
  271. package/dist/ts/upload/setHeaders.d.ts +2 -0
  272. package/dist/ts/util/Options.d.ts +8 -0
  273. package/dist/ts/util/RecordMedia.d.ts +18 -0
  274. package/dist/ts/util/addScript.d.ts +2 -0
  275. package/dist/ts/util/addStyle.d.ts +1 -0
  276. package/dist/ts/util/code160to32.d.ts +1 -0
  277. package/dist/ts/util/compatibility.d.ts +7 -0
  278. package/dist/ts/util/editorCommonEvent.d.ts +10 -0
  279. package/dist/ts/util/fixBrowserBehavior.d.ts +40 -0
  280. package/dist/ts/util/getSelectText.d.ts +1 -0
  281. package/dist/ts/util/hasClosest.d.ts +9 -0
  282. package/dist/ts/util/hasClosestByHeadings.d.ts +2 -0
  283. package/dist/ts/util/highlightToolbar.d.ts +2 -0
  284. package/dist/ts/util/hotKey.d.ts +1 -0
  285. package/dist/ts/util/log.d.ts +1 -0
  286. package/dist/ts/util/merge.d.ts +1 -0
  287. package/dist/ts/util/processCode.d.ts +3 -0
  288. package/dist/ts/util/selection.d.ts +15 -0
  289. package/dist/ts/util/toc.d.ts +6 -0
  290. package/dist/ts/wysiwyg/afterRenderEvent.d.ts +6 -0
  291. package/dist/ts/wysiwyg/highlightToolbarWYSIWYG.d.ts +5 -0
  292. package/dist/ts/wysiwyg/index.d.ts +20 -0
  293. package/dist/ts/wysiwyg/inlineTag.d.ts +11 -0
  294. package/dist/ts/wysiwyg/input.d.ts +2 -0
  295. package/dist/ts/wysiwyg/processKeydown.d.ts +3 -0
  296. package/dist/ts/wysiwyg/renderDomByMd.d.ts +6 -0
  297. package/dist/ts/wysiwyg/setHeading.d.ts +3 -0
  298. package/dist/ts/wysiwyg/showCode.d.ts +2 -0
  299. package/dist/ts/wysiwyg/toolbarEvent.d.ts +2 -0
  300. package/dist/types/index.d.ts +772 -0
  301. package/package.json +69 -0
  302. package/src/assets/.DS_Store +0 -0
  303. package/src/assets/scss/_content.scss +284 -0
  304. package/src/assets/scss/_hint.scss +67 -0
  305. package/src/assets/scss/_ir.scss +275 -0
  306. package/src/assets/scss/_panel.scss +110 -0
  307. package/src/assets/scss/_reset.scss +603 -0
  308. package/src/assets/scss/_sv.scss +133 -0
  309. package/src/assets/scss/_toolbar.scss +180 -0
  310. package/src/assets/scss/_tooltipped.scss +171 -0
  311. package/src/assets/scss/_wysiwyg.scss +195 -0
  312. package/src/assets/scss/index.scss +83 -0
  313. package/src/index.ts +502 -0
  314. package/src/method.ts +65 -0
  315. package/src/ts/.DS_Store +0 -0
  316. package/src/ts/constants.ts +64 -0
  317. package/src/ts/devtools/index.ts +83 -0
  318. package/src/ts/export/index.ts +81 -0
  319. package/src/ts/hint/index.ts +267 -0
  320. package/src/ts/ir/expandMarker.ts +79 -0
  321. package/src/ts/ir/highlightToolbarIR.ts +97 -0
  322. package/src/ts/ir/index.ts +251 -0
  323. package/src/ts/ir/input.ts +231 -0
  324. package/src/ts/ir/process.ts +220 -0
  325. package/src/ts/ir/processKeydown.ts +238 -0
  326. package/src/ts/markdown/abcRender.ts +27 -0
  327. package/src/ts/markdown/adapterRender.ts +33 -0
  328. package/src/ts/markdown/anchorRender.ts +19 -0
  329. package/src/ts/markdown/chartRender.ts +37 -0
  330. package/src/ts/markdown/codeRender.ts +50 -0
  331. package/src/ts/markdown/flowchartRender.ts +25 -0
  332. package/src/ts/markdown/getHTML.ts +11 -0
  333. package/src/ts/markdown/getMarkdown.ts +12 -0
  334. package/src/ts/markdown/graphvizRender.ts +49 -0
  335. package/src/ts/markdown/highlightRender.ts +82 -0
  336. package/src/ts/markdown/lazyLoadImageRender.ts +56 -0
  337. package/src/ts/markdown/mathRender.ts +142 -0
  338. package/src/ts/markdown/mediaRender.ts +78 -0
  339. package/src/ts/markdown/mermaidRender.ts +127 -0
  340. package/src/ts/markdown/mindmapRender.ts +74 -0
  341. package/src/ts/markdown/outlineRender.ts +106 -0
  342. package/src/ts/markdown/plantumlRender.ts +32 -0
  343. package/src/ts/markdown/previewRender.ts +143 -0
  344. package/src/ts/markdown/setLute.ts +23 -0
  345. package/src/ts/markdown/speechRender.ts +97 -0
  346. package/src/ts/outline/index.ts +47 -0
  347. package/src/ts/preview/image.ts +50 -0
  348. package/src/ts/preview/index.ts +266 -0
  349. package/src/ts/resize/index.ts +57 -0
  350. package/src/ts/sv/index.ts +119 -0
  351. package/src/ts/sv/inputEvent.ts +207 -0
  352. package/src/ts/sv/process.ts +210 -0
  353. package/src/ts/sv/processKeydown.ts +196 -0
  354. package/src/ts/tip/index.ts +31 -0
  355. package/src/ts/toolbar/Both.ts +28 -0
  356. package/src/ts/toolbar/Br.ts +8 -0
  357. package/src/ts/toolbar/CodeTheme.ts +36 -0
  358. package/src/ts/toolbar/ContentTheme.ts +35 -0
  359. package/src/ts/toolbar/Counter.ts +40 -0
  360. package/src/ts/toolbar/Custom.ts +17 -0
  361. package/src/ts/toolbar/Devtools.ts +28 -0
  362. package/src/ts/toolbar/Divider.ts +8 -0
  363. package/src/ts/toolbar/EditMode.ts +193 -0
  364. package/src/ts/toolbar/Emoji.ts +75 -0
  365. package/src/ts/toolbar/Export.ts +41 -0
  366. package/src/ts/toolbar/Fullscreen.ts +61 -0
  367. package/src/ts/toolbar/Headings.ts +69 -0
  368. package/src/ts/toolbar/Help.ts +30 -0
  369. package/src/ts/toolbar/Indent.ts +25 -0
  370. package/src/ts/toolbar/Info.ts +43 -0
  371. package/src/ts/toolbar/InsertAfter.ts +18 -0
  372. package/src/ts/toolbar/InsertBefore.ts +18 -0
  373. package/src/ts/toolbar/MenuItem.ts +54 -0
  374. package/src/ts/toolbar/Outdent.ts +24 -0
  375. package/src/ts/toolbar/Outline.ts +21 -0
  376. package/src/ts/toolbar/Preview.ts +55 -0
  377. package/src/ts/toolbar/Record.ts +60 -0
  378. package/src/ts/toolbar/Redo.ts +18 -0
  379. package/src/ts/toolbar/Undo.ts +18 -0
  380. package/src/ts/toolbar/Upload.ts +41 -0
  381. package/src/ts/toolbar/index.ts +175 -0
  382. package/src/ts/toolbar/setToolbar.ts +120 -0
  383. package/src/ts/ui/initUI.ts +164 -0
  384. package/src/ts/ui/setCodeTheme.ts +16 -0
  385. package/src/ts/ui/setContentTheme.ts +15 -0
  386. package/src/ts/ui/setPreviewMode.ts +31 -0
  387. package/src/ts/ui/setTheme.ts +7 -0
  388. package/src/ts/undo/index.ts +255 -0
  389. package/src/ts/upload/getElement.ts +10 -0
  390. package/src/ts/upload/index.ts +257 -0
  391. package/src/ts/upload/setHeaders.ts +10 -0
  392. package/src/ts/util/Options.ts +429 -0
  393. package/src/ts/util/RecordMedia.ts +170 -0
  394. package/src/ts/util/addScript.ts +40 -0
  395. package/src/ts/util/addStyle.ts +10 -0
  396. package/src/ts/util/code160to32.ts +4 -0
  397. package/src/ts/util/compatibility.ts +67 -0
  398. package/src/ts/util/editorCommonEvent.ts +254 -0
  399. package/src/ts/util/fixBrowserBehavior.ts +1459 -0
  400. package/src/ts/util/getSelectText.ts +8 -0
  401. package/src/ts/util/hasClosest.ts +154 -0
  402. package/src/ts/util/hasClosestByHeadings.ts +27 -0
  403. package/src/ts/util/highlightToolbar.ts +10 -0
  404. package/src/ts/util/hotKey.ts +54 -0
  405. package/src/ts/util/log.ts +6 -0
  406. package/src/ts/util/merge.ts +18 -0
  407. package/src/ts/util/processCode.ts +90 -0
  408. package/src/ts/util/selection.ts +275 -0
  409. package/src/ts/util/toc.ts +83 -0
  410. package/src/ts/wysiwyg/afterRenderEvent.ts +41 -0
  411. package/src/ts/wysiwyg/highlightToolbarWYSIWYG.ts +1105 -0
  412. package/src/ts/wysiwyg/index.ts +547 -0
  413. package/src/ts/wysiwyg/inlineTag.ts +129 -0
  414. package/src/ts/wysiwyg/input.ts +210 -0
  415. package/src/ts/wysiwyg/processKeydown.ts +363 -0
  416. package/src/ts/wysiwyg/renderDomByMd.ts +18 -0
  417. package/src/ts/wysiwyg/setHeading.ts +43 -0
  418. package/src/ts/wysiwyg/showCode.ts +32 -0
  419. package/src/ts/wysiwyg/toolbarEvent.ts +333 -0
@@ -0,0 +1,1459 @@
1
+ import {Constants} from "../constants";
2
+ import {input as IRInput} from "../ir/input";
3
+ import {processAfterRender} from "../ir/process";
4
+ import {processAfterRender as processSVAfterRender, processPaste} from "../sv/process";
5
+ import {uploadFiles} from "../upload/index";
6
+ import {setHeaders} from "../upload/setHeaders";
7
+ import {afterRenderEvent} from "../wysiwyg/afterRenderEvent";
8
+ import {input} from "../wysiwyg/input";
9
+ import {isCtrl, isFirefox} from "./compatibility";
10
+ import {scrollCenter} from "./editorCommonEvent";
11
+ import {
12
+ getTopList,
13
+ hasClosestBlock,
14
+ hasClosestByAttribute,
15
+ hasClosestByClassName,
16
+ hasClosestByMatchTag,
17
+ } from "./hasClosest";
18
+ import {getLastNode} from "./hasClosest";
19
+ import {highlightToolbar} from "./highlightToolbar";
20
+ import {matchHotKey} from "./hotKey";
21
+ import {processCodeRender, processPasteCode} from "./processCode";
22
+ import {
23
+ getEditorRange,
24
+ getSelectPosition,
25
+ insertHTML,
26
+ setRangeByWbr,
27
+ setSelectionByPosition, setSelectionFocus,
28
+ } from "./selection";
29
+
30
+ // https://github.com/Vanessa219/vditor/issues/508 软键盘无法删除空块
31
+ export const fixGSKeyBackspace = (event: KeyboardEvent, vditor: IVditor, startContainer: Node) => {
32
+ if (event.keyCode === 229 && event.code === "" && event.key === "Unidentified" && vditor.currentMode !== "sv") {
33
+ const blockElement = hasClosestBlock(startContainer);
34
+ // 移动端的标点符号都显示为 299,因此需限定为空删除的条件
35
+ if (blockElement && blockElement.textContent.trim() === "") {
36
+ vditor[vditor.currentMode].composingLock = true;
37
+ return false;
38
+ }
39
+ }
40
+ return true;
41
+ };
42
+
43
+ // https://github.com/Vanessa219/vditor/issues/361 代码块后输入中文
44
+ export const fixCJKPosition = (range: Range, vditor: IVditor, event: KeyboardEvent) => {
45
+ if (event.key === "Enter" || event.key === "Tab" || event.key === "Backspace" || event.key.indexOf("Arrow") > -1
46
+ || isCtrl(event) || event.key === "Escape" || event.shiftKey || event.altKey) {
47
+ return;
48
+ }
49
+ const pLiElement = hasClosestByMatchTag(range.startContainer, "P") ||
50
+ hasClosestByMatchTag(range.startContainer, "LI");
51
+ if (pLiElement && getSelectPosition(pLiElement, vditor[vditor.currentMode].element, range).start === 0) {
52
+ const zwspNode = document.createTextNode(Constants.ZWSP);
53
+ range.insertNode(zwspNode);
54
+ range.setStartAfter(zwspNode);
55
+ }
56
+ };
57
+
58
+ // https://github.com/Vanessa219/vditor/issues/381 光标在内联数学公式中无法向下移动
59
+ export const fixCursorDownInlineMath = (range: Range, key: string) => {
60
+ if (key === "ArrowDown" || key === "ArrowUp") {
61
+ const inlineElement = hasClosestByAttribute(range.startContainer, "data-type", "math-inline") ||
62
+ hasClosestByAttribute(range.startContainer, "data-type", "html-entity") ||
63
+ hasClosestByAttribute(range.startContainer, "data-type", "html-inline");
64
+ if (inlineElement) {
65
+ if (key === "ArrowDown") {
66
+ range.setStartAfter(inlineElement.parentElement);
67
+ }
68
+ if (key === "ArrowUp") {
69
+ range.setStartBefore(inlineElement.parentElement);
70
+ }
71
+ }
72
+ }
73
+ };
74
+
75
+ export const insertEmptyBlock = (vditor: IVditor, position: InsertPosition) => {
76
+ const range = getEditorRange(vditor);
77
+ const blockElement = hasClosestBlock(range.startContainer);
78
+ if (blockElement) {
79
+ blockElement.insertAdjacentHTML(position, `<p data-block="0">${Constants.ZWSP}<wbr>\n</p>`);
80
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
81
+ highlightToolbar(vditor);
82
+ execAfterRender(vditor);
83
+ }
84
+ };
85
+
86
+ export const isFirstCell = (cellElement: HTMLElement) => {
87
+ const tableElement = hasClosestByMatchTag(cellElement, "TABLE") as HTMLTableElement;
88
+ if (tableElement && tableElement.rows[0].cells[0].isSameNode(cellElement)) {
89
+ return tableElement;
90
+ }
91
+ return false;
92
+ };
93
+
94
+ export const isLastCell = (cellElement: HTMLElement) => {
95
+ const tableElement = hasClosestByMatchTag(cellElement, "TABLE") as HTMLTableElement;
96
+ if (tableElement && tableElement.lastElementChild.lastElementChild.lastElementChild.isSameNode(cellElement)) {
97
+ return tableElement;
98
+ }
99
+ return false;
100
+ };
101
+
102
+ // 光标设置到前一个表格中
103
+ const goPreviousCell = (cellElement: HTMLElement, range: Range, isSelected = true) => {
104
+ let previousElement = cellElement.previousElementSibling;
105
+ if (!previousElement) {
106
+ if (cellElement.parentElement.previousElementSibling) {
107
+ previousElement = cellElement.parentElement.previousElementSibling.lastElementChild;
108
+ } else if (cellElement.parentElement.parentElement.tagName === "TBODY" &&
109
+ cellElement.parentElement.parentElement.previousElementSibling) {
110
+ previousElement = cellElement.parentElement
111
+ .parentElement.previousElementSibling.lastElementChild.lastElementChild;
112
+ } else {
113
+ previousElement = null;
114
+ }
115
+ }
116
+ if (previousElement) {
117
+ range.selectNodeContents(previousElement);
118
+ if (!isSelected) {
119
+ range.collapse(false);
120
+ }
121
+ setSelectionFocus(range);
122
+ }
123
+ return previousElement;
124
+ };
125
+
126
+ export const insertAfterBlock = (vditor: IVditor, event: KeyboardEvent, range: Range, element: HTMLElement,
127
+ blockElement: HTMLElement) => {
128
+ const position = getSelectPosition(element, vditor[vditor.currentMode].element, range);
129
+ if ((event.key === "ArrowDown" && element.textContent.trimRight().substr(position.start).indexOf("\n") === -1) ||
130
+ (event.key === "ArrowRight" && position.start >= element.textContent.trimRight().length)) {
131
+ const nextElement = blockElement.nextElementSibling;
132
+ if (!nextElement ||
133
+ (nextElement && (nextElement.tagName === "TABLE" || nextElement.getAttribute("data-type")))) {
134
+ blockElement.insertAdjacentHTML("afterend",
135
+ `<p data-block="0">${Constants.ZWSP}<wbr></p>`);
136
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
137
+ } else {
138
+ range.selectNodeContents(nextElement);
139
+ range.collapse(true);
140
+ setSelectionFocus(range);
141
+ }
142
+ event.preventDefault();
143
+ return true;
144
+ }
145
+ return false;
146
+ };
147
+
148
+ export const insertBeforeBlock = (vditor: IVditor, event: KeyboardEvent, range: Range, element: HTMLElement,
149
+ blockElement: HTMLElement) => {
150
+ const position = getSelectPosition(element, vditor[vditor.currentMode].element, range);
151
+ if ((event.key === "ArrowUp" && element.textContent.substr(0, position.start).indexOf("\n") === -1) ||
152
+ ((event.key === "ArrowLeft" || (event.key === "Backspace" && range.toString() === "")) &&
153
+ position.start === 0)) {
154
+ const previousElement = blockElement.previousElementSibling;
155
+ // table || code
156
+ if (!previousElement ||
157
+ (previousElement && (previousElement.tagName === "TABLE" || previousElement.getAttribute("data-type")))) {
158
+ blockElement.insertAdjacentHTML("beforebegin",
159
+ `<p data-block="0">${Constants.ZWSP}<wbr></p>`);
160
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
161
+ } else {
162
+ range.selectNodeContents(previousElement);
163
+ range.collapse(false);
164
+ setSelectionFocus(range);
165
+ }
166
+ event.preventDefault();
167
+ return true;
168
+ }
169
+ return false;
170
+ };
171
+
172
+ export const listToggle = (vditor: IVditor, range: Range, type: string, cancel = true) => {
173
+ const itemElement = hasClosestByMatchTag(range.startContainer, "LI");
174
+ vditor[vditor.currentMode].element.querySelectorAll("wbr").forEach((wbr) => {
175
+ wbr.remove();
176
+ });
177
+ range.insertNode(document.createElement("wbr"));
178
+
179
+ if (cancel && itemElement) {
180
+ // 取消
181
+ let pHTML = "";
182
+ for (let i = 0; i < itemElement.parentElement.childElementCount; i++) {
183
+ const inputElement = itemElement.parentElement.children[i].querySelector("input");
184
+ if (inputElement) {
185
+ inputElement.remove();
186
+ }
187
+ pHTML += `<p data-block="0">${itemElement.parentElement.children[i].innerHTML.trimLeft()}</p>`;
188
+ }
189
+ itemElement.parentElement.insertAdjacentHTML("beforebegin", pHTML);
190
+ itemElement.parentElement.remove();
191
+ } else {
192
+ if (!itemElement) {
193
+ // 添加
194
+ let blockElement = hasClosestByAttribute(range.startContainer, "data-block", "0");
195
+ if (!blockElement) {
196
+ vditor[vditor.currentMode].element.querySelector("wbr").remove();
197
+ blockElement = vditor[vditor.currentMode].element.querySelector("p");
198
+ blockElement.innerHTML = "<wbr>";
199
+ }
200
+ if (type === "check") {
201
+ blockElement.insertAdjacentHTML("beforebegin",
202
+ `<ul data-block="0"><li class="vditor-task"><input type="checkbox" /> ${blockElement.innerHTML}</li></ul>`);
203
+ blockElement.remove();
204
+ } else if (type === "list") {
205
+ blockElement.insertAdjacentHTML("beforebegin",
206
+ `<ul data-block="0"><li>${blockElement.innerHTML}</li></ul>`);
207
+ blockElement.remove();
208
+ } else if (type === "ordered-list") {
209
+ blockElement.insertAdjacentHTML("beforebegin",
210
+ `<ol data-block="0"><li>${blockElement.innerHTML}</li></ol>`);
211
+ blockElement.remove();
212
+ }
213
+ } else {
214
+ // 切换
215
+ if (type === "check") {
216
+ itemElement.parentElement.querySelectorAll("li").forEach((item) => {
217
+ item.insertAdjacentHTML("afterbegin",
218
+ `<input type="checkbox" />${item.textContent.indexOf(" ") === 0 ? "" : " "}`);
219
+ item.classList.add("vditor-task");
220
+ });
221
+ } else {
222
+ if (itemElement.querySelector("input")) {
223
+ itemElement.parentElement.querySelectorAll("li").forEach((item) => {
224
+ item.querySelector("input").remove();
225
+ item.classList.remove("vditor-task");
226
+ });
227
+ }
228
+ let element;
229
+ if (type === "list") {
230
+ element = document.createElement("ul");
231
+ element.setAttribute("data-marker", "*");
232
+ } else {
233
+ element = document.createElement("ol");
234
+ element.setAttribute("data-marker", "1.");
235
+ }
236
+ element.setAttribute("data-block", "0");
237
+ element.setAttribute("data-tight", itemElement.parentElement.getAttribute("data-tight"));
238
+ element.innerHTML = itemElement.parentElement.innerHTML;
239
+ itemElement.parentElement.parentNode.replaceChild(element, itemElement.parentElement);
240
+ }
241
+ }
242
+ }
243
+ };
244
+
245
+ export const listIndent = (vditor: IVditor, liElement: HTMLElement, range: Range) => {
246
+ const previousElement = liElement.previousElementSibling;
247
+ if (liElement && previousElement) {
248
+ const liElements: HTMLElement[] = [liElement];
249
+ Array.from(range.cloneContents().children).forEach((item, index) => {
250
+ if (item.nodeType !== 3 && liElement && item.textContent.trim() !== ""
251
+ && liElement.getAttribute("data-node-id") === item.getAttribute("data-node-id")) {
252
+ if (index !== 0) {
253
+ liElements.push(liElement);
254
+ }
255
+ liElement = liElement.nextElementSibling as HTMLElement;
256
+ }
257
+ });
258
+
259
+ vditor[vditor.currentMode].element.querySelectorAll("wbr").forEach((wbr) => {
260
+ wbr.remove();
261
+ });
262
+ range.insertNode(document.createElement("wbr"));
263
+ const liParentElement = previousElement.parentElement;
264
+
265
+ let liHTML = "";
266
+ liElements.forEach((item: HTMLElement) => {
267
+ let marker = item.getAttribute("data-marker");
268
+ if (marker.length !== 1) {
269
+ marker = `1${marker.slice(-1)}`;
270
+ }
271
+ liHTML += `<li data-node-id="${item.getAttribute("data-node-id")}" data-marker="${marker}">${item.innerHTML}</li>`;
272
+ item.remove();
273
+ });
274
+ previousElement.insertAdjacentHTML("beforeend",
275
+ `<${liParentElement.tagName} data-block="0">${liHTML}</${liParentElement.tagName}>`);
276
+
277
+ if (vditor.currentMode === "wysiwyg") {
278
+ liParentElement.outerHTML = vditor.lute.SpinVditorDOM(liParentElement.outerHTML);
279
+ } else {
280
+ liParentElement.outerHTML = vditor.lute.SpinVditorIRDOM(liParentElement.outerHTML);
281
+ }
282
+
283
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
284
+ const tempTopListElement = getTopList(range.startContainer);
285
+ if (tempTopListElement) {
286
+ tempTopListElement.querySelectorAll(`.vditor-${vditor.currentMode}__preview[data-render='2']`)
287
+ .forEach((item: HTMLElement) => {
288
+ processCodeRender(item, vditor);
289
+ if (vditor.currentMode === "wysiwyg") {
290
+ item.previousElementSibling.setAttribute("style", "display:none");
291
+ }
292
+ });
293
+ }
294
+ execAfterRender(vditor);
295
+ highlightToolbar(vditor);
296
+ } else {
297
+ vditor[vditor.currentMode].element.focus();
298
+ }
299
+ };
300
+
301
+ export const listOutdent = (vditor: IVditor, liElement: HTMLElement, range: Range, topListElement: HTMLElement) => {
302
+ const liParentLiElement = hasClosestByMatchTag(liElement.parentElement, "LI");
303
+ if (liParentLiElement) {
304
+ vditor[vditor.currentMode].element.querySelectorAll("wbr").forEach((wbr) => {
305
+ wbr.remove();
306
+ });
307
+ range.insertNode(document.createElement("wbr"));
308
+
309
+ const liParentElement = liElement.parentElement;
310
+ const liParentAfterElement = liParentElement.cloneNode() as HTMLElement;
311
+ const liElements: HTMLElement[] = [liElement];
312
+ Array.from(range.cloneContents().children).forEach((item, index) => {
313
+ if (item.nodeType !== 3 && liElement && item.textContent.trim() !== "" &&
314
+ liElement.getAttribute("data-node-id") === item.getAttribute("data-node-id")) {
315
+ if (index !== 0) {
316
+ liElements.push(liElement);
317
+ }
318
+ liElement = liElement.nextElementSibling as HTMLElement;
319
+ }
320
+ });
321
+ let isMatch = false;
322
+ let afterHTML = "";
323
+ liParentElement.querySelectorAll("li").forEach((item) => {
324
+ if (isMatch) {
325
+ afterHTML += item.outerHTML;
326
+ if (!item.nextElementSibling && !item.previousElementSibling) {
327
+ item.parentElement.remove();
328
+ } else {
329
+ item.remove();
330
+ }
331
+ }
332
+ if (item.isSameNode(liElements[liElements.length - 1])) {
333
+ isMatch = true;
334
+ }
335
+ });
336
+
337
+ liElements.reverse().forEach((item) => {
338
+ liParentLiElement.insertAdjacentElement("afterend", item);
339
+ });
340
+
341
+ if (afterHTML) {
342
+ liParentAfterElement.innerHTML = afterHTML;
343
+ liElements[0].insertAdjacentElement("beforeend", liParentAfterElement);
344
+ }
345
+
346
+ if (vditor.currentMode === "wysiwyg") {
347
+ topListElement.outerHTML = vditor.lute.SpinVditorDOM(topListElement.outerHTML);
348
+ } else {
349
+ topListElement.outerHTML = vditor.lute.SpinVditorIRDOM(topListElement.outerHTML);
350
+ }
351
+
352
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
353
+ const tempTopListElement = getTopList(range.startContainer);
354
+ if (tempTopListElement) {
355
+ tempTopListElement.querySelectorAll(`.vditor-${vditor.currentMode}__preview[data-render='2']`)
356
+ .forEach((item: HTMLElement) => {
357
+ processCodeRender(item, vditor);
358
+ if (vditor.currentMode === "wysiwyg") {
359
+ item.previousElementSibling.setAttribute("style", "display:none");
360
+ }
361
+ });
362
+ }
363
+ execAfterRender(vditor);
364
+ highlightToolbar(vditor);
365
+ } else {
366
+ vditor[vditor.currentMode].element.focus();
367
+ }
368
+ };
369
+
370
+ export const setTableAlign = (tableElement: HTMLTableElement, type: string) => {
371
+ const cell = getSelection().getRangeAt(0).startContainer.parentElement;
372
+
373
+ const columnCnt = tableElement.rows[0].cells.length;
374
+ const rowCnt = tableElement.rows.length;
375
+ let currentColumn = 0;
376
+
377
+ for (let i = 0; i < rowCnt; i++) {
378
+ for (let j = 0; j < columnCnt; j++) {
379
+ if (tableElement.rows[i].cells[j].isSameNode(cell)) {
380
+ currentColumn = j;
381
+ break;
382
+ }
383
+ }
384
+ }
385
+ for (let k = 0; k < rowCnt; k++) {
386
+ tableElement.rows[k].cells[currentColumn].setAttribute("align", type);
387
+ }
388
+ };
389
+
390
+ export const isHrMD = (text: string) => {
391
+ // - _ *
392
+ const marker = text.trimRight().split("\n").pop();
393
+ if (marker === "") {
394
+ return false;
395
+ }
396
+ if (marker.replace(/ |-/g, "") === ""
397
+ || marker.replace(/ |_/g, "") === ""
398
+ || marker.replace(/ |\*/g, "") === "") {
399
+ if (marker.replace(/ /g, "").length > 2) {
400
+ if (marker.indexOf("-") > -1 && marker.trimLeft().indexOf(" ") === -1
401
+ && text.trimRight().split("\n").length > 1) {
402
+ // 满足 heading
403
+ return false;
404
+ }
405
+ if (marker.indexOf(" ") === 0 || marker.indexOf("\t") === 0) {
406
+ // 代码块
407
+ return false;
408
+ }
409
+ return true;
410
+ }
411
+ return false;
412
+ }
413
+ return false;
414
+ };
415
+
416
+ export const isHeadingMD = (text: string) => {
417
+ // - =
418
+ const textArray = text.trimRight().split("\n");
419
+ text = textArray.pop();
420
+
421
+ if (text.indexOf(" ") === 0 || text.indexOf("\t") === 0) {
422
+ return false;
423
+ }
424
+
425
+ text = text.trimLeft();
426
+ if (text === "" || textArray.length === 0) {
427
+ return false;
428
+ }
429
+ if (text.replace(/-/g, "") === ""
430
+ || text.replace(/=/g, "") === "") {
431
+ return true;
432
+ }
433
+ return false;
434
+ };
435
+
436
+ export const execAfterRender = (vditor: IVditor, options = {
437
+ enableAddUndoStack: true,
438
+ enableHint: false,
439
+ enableInput: true,
440
+ }) => {
441
+ if (vditor.currentMode === "wysiwyg") {
442
+ afterRenderEvent(vditor, options);
443
+ } else if (vditor.currentMode === "ir") {
444
+ processAfterRender(vditor, options);
445
+ } else if (vditor.currentMode === "sv") {
446
+ processSVAfterRender(vditor, options);
447
+ }
448
+ };
449
+
450
+ export const fixList = (range: Range, vditor: IVditor, pElement: HTMLElement | false, event: KeyboardEvent) => {
451
+ const startContainer = range.startContainer;
452
+ const liElement = hasClosestByMatchTag(startContainer, "LI");
453
+ if (liElement) {
454
+ if (!isCtrl(event) && !event.altKey && event.key === "Enter" &&
455
+ // fix li 中有多个 P 时,在第一个 P 中换行会在下方生成新的 li
456
+ (!event.shiftKey && pElement && liElement.contains(pElement) && pElement.nextElementSibling)) {
457
+ if (liElement && !liElement.textContent.endsWith("\n")) {
458
+ // li 结尾需 \n
459
+ liElement.insertAdjacentText("beforeend", "\n");
460
+ }
461
+ range.insertNode(document.createTextNode("\n\n"));
462
+ range.collapse(false);
463
+ execAfterRender(vditor);
464
+ event.preventDefault();
465
+ return true;
466
+ }
467
+
468
+ if (!isCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace" &&
469
+ !liElement.previousElementSibling && range.toString() === "" &&
470
+ getSelectPosition(liElement, vditor[vditor.currentMode].element, range).start === 0) {
471
+ // 光标位于点和第一个字符中间时,无法删除 li 元素
472
+ if (liElement.nextElementSibling) {
473
+ liElement.parentElement.insertAdjacentHTML("beforebegin",
474
+ `<p data-block="0"><wbr>${liElement.innerHTML}</p>`);
475
+ liElement.remove();
476
+ } else {
477
+ liElement.parentElement.outerHTML = `<p data-block="0"><wbr>${liElement.innerHTML}</p>`;
478
+ }
479
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
480
+ execAfterRender(vditor);
481
+ event.preventDefault();
482
+ return true;
483
+ }
484
+
485
+ // 空列表删除后与上一级段落对齐
486
+ if (!isCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace" &&
487
+ liElement.textContent.trim().replace(Constants.ZWSP, "") === "" &&
488
+ range.toString() === "" && liElement.previousElementSibling?.tagName === "LI") {
489
+ liElement.previousElementSibling.insertAdjacentText("beforeend", "\n\n");
490
+ range.selectNodeContents(liElement.previousElementSibling);
491
+ range.collapse(false);
492
+ liElement.remove();
493
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
494
+ execAfterRender(vditor);
495
+ event.preventDefault();
496
+ return true;
497
+ }
498
+
499
+ if (!isCtrl(event) && !event.altKey && event.key === "Tab") {
500
+ // 光标位于第一/零字符时,tab 用于列表的缩进
501
+ let isFirst = false;
502
+ if (range.startOffset === 0
503
+ && ((startContainer.nodeType === 3 && !startContainer.previousSibling)
504
+ || (startContainer.nodeType !== 3 && startContainer.nodeName === "LI"))) {
505
+ // 有序/无序列表
506
+ isFirst = true;
507
+ } else if (liElement.classList.contains("vditor-task") && range.startOffset === 1
508
+ && startContainer.previousSibling.nodeType !== 3
509
+ && (startContainer.previousSibling as HTMLElement).tagName === "INPUT") {
510
+ // 任务列表
511
+ isFirst = true;
512
+ }
513
+
514
+ if (isFirst || range.toString() !== "") {
515
+ if (event.shiftKey) {
516
+ listOutdent(vditor, liElement, range, liElement.parentElement);
517
+ } else {
518
+ listIndent(vditor, liElement, range);
519
+ }
520
+ event.preventDefault();
521
+ return true;
522
+ }
523
+ }
524
+ }
525
+ return false;
526
+ };
527
+
528
+ // tab 处理: block code render, table, 列表第一个字符中的 tab 处理单独写在上面
529
+ export const fixTab = (vditor: IVditor, range: Range, event: KeyboardEvent) => {
530
+ if (vditor.options.tab && event.key === "Tab") {
531
+ if (event.shiftKey) {
532
+ // TODO shift+tab
533
+ } else {
534
+ if (range.toString() === "") {
535
+ range.insertNode(document.createTextNode(vditor.options.tab));
536
+ range.collapse(false);
537
+ } else {
538
+ range.extractContents();
539
+ range.insertNode(document.createTextNode(vditor.options.tab));
540
+ range.collapse(false);
541
+ }
542
+ }
543
+ setSelectionFocus(range);
544
+ execAfterRender(vditor);
545
+ event.preventDefault();
546
+ return true;
547
+ }
548
+ };
549
+
550
+ export const fixMarkdown = (event: KeyboardEvent, vditor: IVditor, pElement: HTMLElement | false, range: Range) => {
551
+ if (!pElement) {
552
+ return;
553
+ }
554
+ if (!isCtrl(event) && !event.altKey && event.key === "Enter") {
555
+ const pText = String.raw`${pElement.textContent}`.replace(/\\\|/g, "").trim();
556
+ const pTextList = pText.split("|");
557
+ if (pText.startsWith("|") && pText.endsWith("|") && pTextList.length > 3) {
558
+ // table 自动完成
559
+ let tableHeaderMD = pTextList.map(() => "---").join("|");
560
+ tableHeaderMD =
561
+ pElement.textContent + "\n" + tableHeaderMD.substring(3, tableHeaderMD.length - 3) + "\n|<wbr>";
562
+ pElement.outerHTML = vditor.lute.SpinVditorDOM(tableHeaderMD);
563
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
564
+ execAfterRender(vditor);
565
+ scrollCenter(vditor);
566
+ event.preventDefault();
567
+ return true;
568
+ }
569
+
570
+ // hr 渲染
571
+ if (isHrMD(pElement.innerHTML) && pElement.previousElementSibling) {
572
+ // 软换行后 hr 前有内容
573
+ let pInnerHTML = "";
574
+ const innerHTMLList = pElement.innerHTML.trimRight().split("\n");
575
+ if (innerHTMLList.length > 1) {
576
+ innerHTMLList.pop();
577
+ pInnerHTML = `<p data-block="0">${innerHTMLList.join("\n")}</p>`;
578
+ }
579
+
580
+ pElement.insertAdjacentHTML("afterend",
581
+ `${pInnerHTML}<hr data-block="0"><p data-block="0"><wbr>\n</p>`);
582
+ pElement.remove();
583
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
584
+ execAfterRender(vditor);
585
+ scrollCenter(vditor);
586
+ event.preventDefault();
587
+ return true;
588
+ }
589
+
590
+ if (isHeadingMD(pElement.innerHTML)) {
591
+ // heading 渲染
592
+ if (vditor.currentMode === "wysiwyg") {
593
+ pElement.outerHTML = vditor.lute.SpinVditorDOM(pElement.innerHTML + '<p data-block="0"><wbr>\n</p>');
594
+ } else {
595
+ pElement.outerHTML = vditor.lute.SpinVditorIRDOM(pElement.innerHTML + '<p data-block="0"><wbr>\n</p>');
596
+ }
597
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
598
+ execAfterRender(vditor);
599
+ scrollCenter(vditor);
600
+ event.preventDefault();
601
+ return true;
602
+ }
603
+ }
604
+
605
+ // 软换行会被切割 https://github.com/Vanessa219/vditor/issues/220
606
+ if (range.collapsed && pElement.previousElementSibling && event.key === "Backspace" &&
607
+ !isCtrl(event) && !event.altKey && !event.shiftKey &&
608
+ pElement.textContent.trimRight().split("\n").length > 1 &&
609
+ getSelectPosition(pElement, vditor[vditor.currentMode].element, range).start === 0) {
610
+ const lastElement = getLastNode(pElement.previousElementSibling) as HTMLElement;
611
+ if (!lastElement.textContent.endsWith("\n")) {
612
+ lastElement.textContent = lastElement.textContent + "\n";
613
+ }
614
+ lastElement.parentElement.insertAdjacentHTML("beforeend", `<wbr>${pElement.innerHTML}`);
615
+ pElement.remove();
616
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
617
+ return false;
618
+ }
619
+ return false;
620
+ };
621
+
622
+ export const insertRow = (vditor: IVditor, range: Range, cellElement: HTMLElement) => {
623
+ let rowHTML = "";
624
+ for (let m = 0; m < cellElement.parentElement.childElementCount; m++) {
625
+ rowHTML += `<td align="${cellElement.parentElement.children[m].getAttribute("align")}"> </td>`;
626
+ }
627
+ if (cellElement.tagName === "TH") {
628
+ cellElement.parentElement.parentElement.insertAdjacentHTML("afterend",
629
+ `<tbody><tr>${rowHTML}</tr></tbody>`);
630
+ } else {
631
+ cellElement.parentElement.insertAdjacentHTML("afterend", `<tr>${rowHTML}</tr>`);
632
+ }
633
+ execAfterRender(vditor);
634
+ };
635
+
636
+ export const insertRowAbove = (vditor: IVditor, range: Range, cellElement: HTMLElement) => {
637
+ let rowHTML = "";
638
+ for (let m = 0; m < cellElement.parentElement.childElementCount; m++) {
639
+ if (cellElement.tagName === "TH") {
640
+ rowHTML += `<th align="${cellElement.parentElement.children[m].getAttribute("align")}"> </th>`;
641
+ } else {
642
+ rowHTML += `<td align="${cellElement.parentElement.children[m].getAttribute("align")}"> </td>`;
643
+ }
644
+ }
645
+ if (cellElement.tagName === "TH") {
646
+ cellElement.parentElement.parentElement.insertAdjacentHTML("beforebegin", `<thead><tr>${rowHTML}</tr></thead>`);
647
+
648
+ range.insertNode(document.createElement("wbr"));
649
+ const theadHTML = cellElement.parentElement.innerHTML.replace(/<th>/g, "<td>").replace(/<\/th>/g, "</td>");
650
+ cellElement.parentElement.parentElement.nextElementSibling.insertAdjacentHTML("afterbegin", theadHTML);
651
+
652
+ cellElement.parentElement.parentElement.remove();
653
+ setRangeByWbr(vditor.ir.element, range);
654
+ } else {
655
+ cellElement.parentElement.insertAdjacentHTML("beforebegin", `<tr>${rowHTML}</tr>`);
656
+ }
657
+ execAfterRender(vditor);
658
+ };
659
+
660
+ export const insertColumn =
661
+ (vditor: IVditor, tableElement: HTMLTableElement, cellElement: HTMLElement, type: InsertPosition = "afterend") => {
662
+ let index = 0;
663
+ let previousElement = cellElement.previousElementSibling;
664
+ while (previousElement) {
665
+ index++;
666
+ previousElement = previousElement.previousElementSibling;
667
+ }
668
+ for (let i = 0; i < tableElement.rows.length; i++) {
669
+ if (i === 0) {
670
+ tableElement.rows[i].cells[index].insertAdjacentHTML(type, "<th> </th>");
671
+ } else {
672
+ tableElement.rows[i].cells[index].insertAdjacentHTML(type, "<td> </td>");
673
+ }
674
+ }
675
+ execAfterRender(vditor);
676
+ };
677
+ export const deleteRow = (vditor: IVditor, range: Range, cellElement: HTMLElement) => {
678
+ if (cellElement.tagName === "TD") {
679
+ const tbodyElement = cellElement.parentElement.parentElement;
680
+ if (cellElement.parentElement.previousElementSibling) {
681
+ range.selectNodeContents(cellElement.parentElement.previousElementSibling.lastElementChild);
682
+ } else {
683
+ range.selectNodeContents(tbodyElement.previousElementSibling.lastElementChild.lastElementChild);
684
+ }
685
+
686
+ if (tbodyElement.childElementCount === 1) {
687
+ tbodyElement.remove();
688
+ } else {
689
+ cellElement.parentElement.remove();
690
+ }
691
+
692
+ range.collapse(false);
693
+ setSelectionFocus(range);
694
+ execAfterRender(vditor);
695
+ }
696
+ };
697
+
698
+ export const deleteColumn =
699
+ (vditor: IVditor, range: Range, tableElement: HTMLTableElement, cellElement: HTMLElement) => {
700
+ let index = 0;
701
+ let previousElement = cellElement.previousElementSibling;
702
+ while (previousElement) {
703
+ index++;
704
+ previousElement = previousElement.previousElementSibling;
705
+ }
706
+ if (cellElement.previousElementSibling || cellElement.nextElementSibling) {
707
+ range.selectNodeContents(cellElement.previousElementSibling || cellElement.nextElementSibling);
708
+ range.collapse(true);
709
+ }
710
+ for (let i = 0; i < tableElement.rows.length; i++) {
711
+ const cells = tableElement.rows[i].cells;
712
+ if (cells.length === 1) {
713
+ tableElement.remove();
714
+ highlightToolbar(vditor);
715
+ break;
716
+ }
717
+ cells[index].remove();
718
+ }
719
+ setSelectionFocus(range);
720
+ execAfterRender(vditor);
721
+ };
722
+
723
+ export const fixTable = (vditor: IVditor, event: KeyboardEvent, range: Range) => {
724
+ const startContainer = range.startContainer;
725
+ const cellElement = hasClosestByMatchTag(startContainer, "TD") ||
726
+ hasClosestByMatchTag(startContainer, "TH");
727
+ if (cellElement) {
728
+ // 换行或软换行:在 cell 中添加 br
729
+ if (!isCtrl(event) && !event.altKey && event.key === "Enter") {
730
+ if (!cellElement.lastElementChild ||
731
+ (cellElement.lastElementChild && (!cellElement.lastElementChild.isSameNode(cellElement.lastChild) ||
732
+ cellElement.lastElementChild.tagName !== "BR"))) {
733
+ cellElement.insertAdjacentHTML("beforeend", "<br>");
734
+ }
735
+ const brElement = document.createElement("br");
736
+ range.insertNode(brElement);
737
+ range.setStartAfter(brElement);
738
+ execAfterRender(vditor);
739
+ scrollCenter(vditor);
740
+ event.preventDefault();
741
+ return true;
742
+ }
743
+
744
+ // tab:光标移向下一个 cell
745
+ if (event.key === "Tab") {
746
+ if (event.shiftKey) {
747
+ // shift + tab 光标移动到前一个 cell
748
+ goPreviousCell(cellElement, range);
749
+ event.preventDefault();
750
+ return true;
751
+ }
752
+
753
+ let nextElement = cellElement.nextElementSibling;
754
+ if (!nextElement) {
755
+ if (cellElement.parentElement.nextElementSibling) {
756
+ nextElement = cellElement.parentElement.nextElementSibling.firstElementChild;
757
+ } else if (cellElement.parentElement.parentElement.tagName === "THEAD" &&
758
+ cellElement.parentElement.parentElement.nextElementSibling) {
759
+ nextElement =
760
+ cellElement.parentElement.parentElement.nextElementSibling.firstElementChild.firstElementChild;
761
+ } else {
762
+ nextElement = null;
763
+ }
764
+ }
765
+ if (nextElement) {
766
+ range.selectNodeContents(nextElement);
767
+ setSelectionFocus(range);
768
+ }
769
+ event.preventDefault();
770
+ return true;
771
+ }
772
+
773
+ const tableElement = cellElement.parentElement.parentElement.parentElement as HTMLTableElement;
774
+ if (event.key === "ArrowUp") {
775
+ event.preventDefault();
776
+ if (cellElement.tagName === "TH") {
777
+ if (tableElement.previousElementSibling) {
778
+ range.selectNodeContents(tableElement.previousElementSibling);
779
+ range.collapse(false);
780
+ setSelectionFocus(range);
781
+ } else {
782
+ insertEmptyBlock(vditor, "beforebegin");
783
+ }
784
+ return true;
785
+ }
786
+
787
+ let m = 0;
788
+ const trElement = cellElement.parentElement as HTMLTableRowElement;
789
+ for (; m < trElement.cells.length; m++) {
790
+ if (trElement.cells[m].isSameNode(cellElement)) {
791
+ break;
792
+ }
793
+ }
794
+
795
+ let previousElement = trElement.previousElementSibling as HTMLTableRowElement;
796
+ if (!previousElement) {
797
+ previousElement = trElement.parentElement.previousElementSibling.firstChild as HTMLTableRowElement;
798
+ }
799
+ range.selectNodeContents(previousElement.cells[m]);
800
+ range.collapse(false);
801
+ setSelectionFocus(range);
802
+ return true;
803
+ }
804
+
805
+ if (event.key === "ArrowDown") {
806
+ event.preventDefault();
807
+ const trElement = cellElement.parentElement as HTMLTableRowElement;
808
+ if (!trElement.nextElementSibling && cellElement.tagName === "TD") {
809
+ if (tableElement.nextElementSibling) {
810
+ range.selectNodeContents(tableElement.nextElementSibling);
811
+ range.collapse(true);
812
+ setSelectionFocus(range);
813
+ } else {
814
+ insertEmptyBlock(vditor, "afterend");
815
+ }
816
+ return true;
817
+ }
818
+
819
+ let m = 0;
820
+ for (; m < trElement.cells.length; m++) {
821
+ if (trElement.cells[m].isSameNode(cellElement)) {
822
+ break;
823
+ }
824
+ }
825
+
826
+ let nextElement = trElement.nextElementSibling as HTMLTableRowElement;
827
+ if (!nextElement) {
828
+ nextElement = trElement.parentElement.nextElementSibling.firstChild as HTMLTableRowElement;
829
+ }
830
+ range.selectNodeContents(nextElement.cells[m]);
831
+ range.collapse(true);
832
+ setSelectionFocus(range);
833
+ return true;
834
+ }
835
+
836
+ // focus row input, only wysiwyg
837
+ if (vditor.currentMode === "wysiwyg" &&
838
+ !isCtrl(event) && event.key === "Enter" && !event.shiftKey && event.altKey) {
839
+ const inputElement = (vditor.wysiwyg.popover.querySelector(".vditor-input") as HTMLInputElement);
840
+ inputElement.focus();
841
+ inputElement.select();
842
+ event.preventDefault();
843
+ return true;
844
+ }
845
+
846
+ // Backspace:光标移动到前一个 cell
847
+ if (!isCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace"
848
+ && range.startOffset === 0 && range.toString() === "") {
849
+ const previousCellElement = goPreviousCell(cellElement, range, false);
850
+ if (!previousCellElement && tableElement) {
851
+ if (tableElement.textContent.trim() === "") {
852
+ tableElement.outerHTML = `<p data-block="0"><wbr>\n</p>`;
853
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
854
+ } else {
855
+ range.setStartBefore(tableElement);
856
+ range.collapse(true);
857
+ }
858
+ execAfterRender(vditor);
859
+ }
860
+ event.preventDefault();
861
+ return true;
862
+ }
863
+ // 上方新添加一行
864
+ if (matchHotKey("⇧⌘F", event)) {
865
+ insertRowAbove(vditor, range, cellElement);
866
+ event.preventDefault();
867
+ return true;
868
+ }
869
+
870
+ // 下方新添加一行 https://github.com/Vanessa219/vditor/issues/46
871
+ if (matchHotKey("⌘=", event)) {
872
+ insertRow(vditor, range, cellElement);
873
+ event.preventDefault();
874
+ return true;
875
+ }
876
+
877
+ // 左方新添加一列
878
+ if (matchHotKey("⇧⌘G", event)) {
879
+ insertColumn(vditor, tableElement, cellElement, "beforebegin");
880
+ event.preventDefault();
881
+ return true;
882
+ }
883
+
884
+ // 后方新添加一列
885
+ if (matchHotKey("⇧⌘=", event)) {
886
+ insertColumn(vditor, tableElement, cellElement);
887
+ event.preventDefault();
888
+ return true;
889
+ }
890
+
891
+ // 删除当前行
892
+ if (matchHotKey("⌘-", event)) {
893
+ deleteRow(vditor, range, cellElement);
894
+ event.preventDefault();
895
+ return true;
896
+ }
897
+
898
+ // 删除当前列
899
+ if (matchHotKey("⇧⌘-", event)) {
900
+ deleteColumn(vditor, range, tableElement, cellElement);
901
+ event.preventDefault();
902
+ return true;
903
+ }
904
+
905
+ // 剧左
906
+ if (matchHotKey("⇧⌘L", event)) {
907
+ if (vditor.currentMode === "ir") {
908
+ setTableAlign(tableElement, "left");
909
+ execAfterRender(vditor);
910
+ event.preventDefault();
911
+ return true;
912
+ } else {
913
+ const itemElement: HTMLElement = vditor.wysiwyg.popover.querySelector('[data-type="left"]');
914
+ if (itemElement) {
915
+ itemElement.click();
916
+ event.preventDefault();
917
+ return true;
918
+ }
919
+ }
920
+ }
921
+
922
+ // 剧中
923
+ if (matchHotKey("⇧⌘C", event)) {
924
+ if (vditor.currentMode === "ir") {
925
+ setTableAlign(tableElement, "center");
926
+ execAfterRender(vditor);
927
+ event.preventDefault();
928
+ return true;
929
+ } else {
930
+ const itemElement: HTMLElement = vditor.wysiwyg.popover.querySelector('[data-type="center"]');
931
+ if (itemElement) {
932
+ itemElement.click();
933
+ event.preventDefault();
934
+ return true;
935
+ }
936
+ }
937
+ }
938
+ // 剧右
939
+ if (matchHotKey("⇧⌘R", event)) {
940
+ if (vditor.currentMode === "ir") {
941
+ setTableAlign(tableElement, "right");
942
+ execAfterRender(vditor);
943
+ event.preventDefault();
944
+ return true;
945
+ } else {
946
+ const itemElement: HTMLElement = vditor.wysiwyg.popover.querySelector('[data-type="right"]');
947
+ if (itemElement) {
948
+ itemElement.click();
949
+ event.preventDefault();
950
+ return true;
951
+ }
952
+ }
953
+ }
954
+ }
955
+ return false;
956
+ };
957
+
958
+ export const fixCodeBlock = (vditor: IVditor, event: KeyboardEvent, codeRenderElement: HTMLElement, range: Range) => {
959
+ // 行级代码块中 command + a,近对当前代码块进行全选
960
+ if (codeRenderElement.tagName === "PRE" && matchHotKey("⌘A", event)) {
961
+ range.selectNodeContents(codeRenderElement.firstElementChild);
962
+ event.preventDefault();
963
+ return true;
964
+ }
965
+
966
+ // tab
967
+ // TODO shift + tab, shift and 选中文字
968
+ if (vditor.options.tab && event.key === "Tab" && !event.shiftKey && range.toString() === "") {
969
+ range.insertNode(document.createTextNode(vditor.options.tab));
970
+ range.collapse(false);
971
+ execAfterRender(vditor);
972
+ event.preventDefault();
973
+ return true;
974
+ }
975
+
976
+ // Backspace: 光标位于第零个字符,仅删除代码块标签
977
+ if (event.key === "Backspace" && !isCtrl(event) && !event.shiftKey && !event.altKey) {
978
+ const codePosition = getSelectPosition(codeRenderElement, vditor[vditor.currentMode].element, range);
979
+ if ((codePosition.start === 0 ||
980
+ (codePosition.start === 1 && codeRenderElement.innerText === "\n")) // 空代码块,光标在 \n 后
981
+ && range.toString() === "") {
982
+ codeRenderElement.parentElement.outerHTML =
983
+ `<p data-block="0"><wbr>${codeRenderElement.firstElementChild.innerHTML}</p>`;
984
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
985
+ execAfterRender(vditor);
986
+ event.preventDefault();
987
+ return true;
988
+ }
989
+ }
990
+
991
+ // 换行
992
+ if (!isCtrl(event) && !event.altKey && event.key === "Enter") {
993
+ if (!codeRenderElement.firstElementChild.textContent.endsWith("\n")) {
994
+ codeRenderElement.firstElementChild.insertAdjacentText("beforeend", "\n");
995
+ }
996
+ range.extractContents();
997
+ range.insertNode(document.createTextNode("\n"));
998
+ range.collapse(false);
999
+ setSelectionFocus(range);
1000
+ if (!isFirefox()) {
1001
+ if (vditor.currentMode === "wysiwyg") {
1002
+ input(vditor, range);
1003
+ } else {
1004
+ IRInput(vditor, range);
1005
+ }
1006
+ }
1007
+ scrollCenter(vditor);
1008
+ event.preventDefault();
1009
+ return true;
1010
+ }
1011
+ return false;
1012
+ };
1013
+
1014
+ export const fixBlockquote = (vditor: IVditor, range: Range, event: KeyboardEvent, pElement: HTMLElement | false) => {
1015
+ const startContainer = range.startContainer;
1016
+ const blockquoteElement = hasClosestByMatchTag(startContainer, "BLOCKQUOTE");
1017
+ if (blockquoteElement && range.toString() === "") {
1018
+ if (event.key === "Backspace" && !isCtrl(event) && !event.shiftKey && !event.altKey &&
1019
+ getSelectPosition(blockquoteElement, vditor[vditor.currentMode].element, range).start === 0) {
1020
+ // Backspace: 光标位于引用中的第零个字符,仅删除引用标签
1021
+ range.insertNode(document.createElement("wbr"));
1022
+ blockquoteElement.outerHTML = blockquoteElement.innerHTML;
1023
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
1024
+ execAfterRender(vditor);
1025
+ event.preventDefault();
1026
+ return true;
1027
+ }
1028
+
1029
+ if (pElement && event.key === "Enter" && !isCtrl(event) && !event.shiftKey && !event.altKey
1030
+ && pElement.parentElement.tagName === "BLOCKQUOTE") {
1031
+ // Enter: 空行回车应逐层跳出
1032
+ let isEmpty = false;
1033
+ if (pElement.innerHTML.replace(Constants.ZWSP, "") === "\n" ||
1034
+ pElement.innerHTML.replace(Constants.ZWSP, "") === "") {
1035
+ // 空 P
1036
+ isEmpty = true;
1037
+ pElement.remove();
1038
+ } else if (pElement.innerHTML.endsWith("\n\n") &&
1039
+ getSelectPosition(pElement, vditor[vditor.currentMode].element, range).start ===
1040
+ pElement.textContent.length - 1) {
1041
+ // 软换行
1042
+ pElement.innerHTML = pElement.innerHTML.substr(0, pElement.innerHTML.length - 2);
1043
+ isEmpty = true;
1044
+ }
1045
+ if (isEmpty) {
1046
+ // 需添加零宽字符,否则的话无法记录 undo
1047
+ blockquoteElement.insertAdjacentHTML("afterend", `<p data-block="0">${Constants.ZWSP}<wbr>\n</p>`);
1048
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
1049
+ execAfterRender(vditor);
1050
+ event.preventDefault();
1051
+ return true;
1052
+ }
1053
+ }
1054
+ const blockElement = hasClosestBlock(startContainer);
1055
+ if (vditor.currentMode === "wysiwyg" && blockElement && matchHotKey("⇧⌘;", event)) {
1056
+ // 插入 blockquote
1057
+ range.insertNode(document.createElement("wbr"));
1058
+ blockElement.outerHTML = `<blockquote data-block="0">${blockElement.outerHTML}</blockquote>`;
1059
+ setRangeByWbr(vditor.wysiwyg.element, range);
1060
+ afterRenderEvent(vditor);
1061
+ event.preventDefault();
1062
+ return true;
1063
+ }
1064
+
1065
+ if (insertAfterBlock(vditor, event, range, blockquoteElement, blockquoteElement)) {
1066
+ return true;
1067
+ }
1068
+ if (insertBeforeBlock(vditor, event, range, blockquoteElement, blockquoteElement)) {
1069
+ return true;
1070
+ }
1071
+ }
1072
+ return false;
1073
+ };
1074
+
1075
+ export const fixTask = (vditor: IVditor, range: Range, event: KeyboardEvent) => {
1076
+ const startContainer = range.startContainer;
1077
+ const taskItemElement = hasClosestByClassName(startContainer, "vditor-task");
1078
+ if (taskItemElement) {
1079
+ if (matchHotKey("⇧⌘J", event)) {
1080
+ // ctrl + shift: toggle checked
1081
+ const inputElement = taskItemElement.firstElementChild as HTMLInputElement;
1082
+ if (inputElement.checked) {
1083
+ inputElement.removeAttribute("checked");
1084
+ } else {
1085
+ inputElement.setAttribute("checked", "checked");
1086
+ }
1087
+ execAfterRender(vditor);
1088
+ event.preventDefault();
1089
+ return true;
1090
+ }
1091
+
1092
+ // Backspace: 在选择框前进行删除
1093
+ if (event.key === "Backspace" && !isCtrl(event) && !event.shiftKey && !event.altKey && range.toString() === ""
1094
+ && range.startOffset === 1
1095
+ && ((startContainer.nodeType === 3 && startContainer.previousSibling &&
1096
+ (startContainer.previousSibling as HTMLElement).tagName === "INPUT")
1097
+ || startContainer.nodeType !== 3)) {
1098
+ const previousElement = taskItemElement.previousElementSibling;
1099
+ taskItemElement.querySelector("input").remove();
1100
+ if (previousElement) {
1101
+ const lastNode = getLastNode(previousElement);
1102
+ lastNode.parentElement.insertAdjacentHTML("beforeend", "<wbr>" + taskItemElement.innerHTML.trim());
1103
+ taskItemElement.remove();
1104
+ } else {
1105
+ taskItemElement.parentElement.insertAdjacentHTML("beforebegin",
1106
+ `<p data-block="0"><wbr>${taskItemElement.innerHTML.trim() || "\n"}</p>`);
1107
+ if (taskItemElement.nextElementSibling) {
1108
+ taskItemElement.remove();
1109
+ } else {
1110
+ taskItemElement.parentElement.remove();
1111
+ }
1112
+ }
1113
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
1114
+ execAfterRender(vditor);
1115
+ event.preventDefault();
1116
+ return true;
1117
+ }
1118
+
1119
+ if (event.key === "Enter" && !isCtrl(event) && !event.shiftKey && !event.altKey) {
1120
+ if (taskItemElement.textContent.trim() === "") {
1121
+ // 当前任务列表无文字
1122
+ if (hasClosestByClassName(taskItemElement.parentElement, "vditor-task")) {
1123
+ // 为子元素时,需进行反向缩进
1124
+ const topListElement = getTopList(startContainer);
1125
+ if (topListElement) {
1126
+ listOutdent(vditor, taskItemElement, range, topListElement);
1127
+ }
1128
+ } else {
1129
+ // 仅有一级任务列表
1130
+ if (taskItemElement.nextElementSibling) {
1131
+ // 任务列表下方还有元素,需要使用用段落隔断
1132
+ let afterHTML = "";
1133
+ let beforeHTML = "";
1134
+ let isAfter = false;
1135
+ Array.from(taskItemElement.parentElement.children).forEach((taskItem) => {
1136
+ if (taskItemElement.isSameNode(taskItem)) {
1137
+ isAfter = true;
1138
+ } else {
1139
+ if (isAfter) {
1140
+ afterHTML += taskItem.outerHTML;
1141
+ } else {
1142
+ beforeHTML += taskItem.outerHTML;
1143
+ }
1144
+ }
1145
+ });
1146
+ const parentTagName = taskItemElement.parentElement.tagName;
1147
+ const dataMarker = taskItemElement.parentElement.tagName === "OL" ? "" : ` data-marker="${taskItemElement.parentElement.getAttribute("data-marker")}"`;
1148
+ let startAttribute = "";
1149
+ if (beforeHTML) {
1150
+ startAttribute = taskItemElement.parentElement.tagName === "UL" ? "" : ` start="1"`;
1151
+ beforeHTML = `<${parentTagName} data-tight="true"${dataMarker} data-block="0">${beforeHTML}</${parentTagName}>`;
1152
+ }
1153
+ // <p data-block="0">\n<wbr></p> => <p data-block="0"><wbr>\n</p>
1154
+ // https://github.com/Vanessa219/vditor/issues/430
1155
+ taskItemElement.parentElement.outerHTML = `${beforeHTML}<p data-block="0"><wbr>\n</p><${parentTagName}
1156
+ data-tight="true"${dataMarker} data-block="0"${startAttribute}>${afterHTML}</${parentTagName}>`;
1157
+ } else {
1158
+ // 任务列表下方无任务列表元素
1159
+ taskItemElement.parentElement.insertAdjacentHTML("afterend", `<p data-block="0"><wbr>\n</p>`);
1160
+ if (taskItemElement.parentElement.querySelectorAll("li").length === 1) {
1161
+ // 任务列表仅有一项时,使用 p 元素替换
1162
+ taskItemElement.parentElement.remove();
1163
+ } else {
1164
+ // 任务列表有多项时,当前任务列表位于最后一项,移除该任务列表
1165
+ taskItemElement.remove();
1166
+ }
1167
+ }
1168
+ }
1169
+ } else if (startContainer.nodeType !== 3 && range.startOffset === 0 &&
1170
+ (startContainer.firstChild as HTMLElement).tagName === "INPUT") {
1171
+ // 光标位于 input 之前
1172
+ range.setStart(startContainer.childNodes[1], 1);
1173
+ } else {
1174
+ // 当前任务列表有文字,光标后的文字需添加到新任务列表中
1175
+ range.setEndAfter(taskItemElement.lastChild);
1176
+ taskItemElement.insertAdjacentHTML("afterend", `<li class="vditor-task" data-marker="${taskItemElement.getAttribute("data-marker")}"><input type="checkbox"> <wbr></li>`);
1177
+ document.querySelector("wbr").after(range.extractContents());
1178
+ }
1179
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
1180
+ execAfterRender(vditor);
1181
+ scrollCenter(vditor);
1182
+ event.preventDefault();
1183
+ return true;
1184
+ }
1185
+ }
1186
+ return false;
1187
+ };
1188
+
1189
+ export const fixDelete = (vditor: IVditor, range: Range, event: KeyboardEvent, pElement: HTMLElement | false) => {
1190
+ if (range.startContainer.nodeType !== 3) {
1191
+ // 光标位于 hr 前,hr 前有内容
1192
+ const rangeElement = (range.startContainer as HTMLElement).children[range.startOffset];
1193
+ if (rangeElement && rangeElement.tagName === "HR") {
1194
+ range.selectNodeContents(rangeElement.previousElementSibling);
1195
+ range.collapse(false);
1196
+ event.preventDefault();
1197
+ return true;
1198
+ }
1199
+ }
1200
+
1201
+ if (pElement) {
1202
+ const previousElement = pElement.previousElementSibling;
1203
+ if (previousElement && getSelectPosition(pElement, vditor[vditor.currentMode].element, range).start === 0 &&
1204
+ ((isFirefox() && previousElement.tagName === "HR") || previousElement.tagName === "TABLE")) {
1205
+ if (previousElement.tagName === "TABLE") {
1206
+ // table 后删除 https://github.com/Vanessa219/vditor/issues/243
1207
+ const lastCellElement = previousElement.lastElementChild.lastElementChild.lastElementChild;
1208
+ lastCellElement.innerHTML =
1209
+ lastCellElement.innerHTML.trimLeft() + "<wbr>" + pElement.textContent.trim();
1210
+ pElement.remove();
1211
+ } else {
1212
+ // 光标位于 hr 后进行删除
1213
+ previousElement.remove();
1214
+ }
1215
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
1216
+ execAfterRender(vditor);
1217
+ event.preventDefault();
1218
+ return true;
1219
+ }
1220
+ }
1221
+ return false;
1222
+ };
1223
+
1224
+ export const fixHR = (range: Range) => {
1225
+ if (isFirefox() && range.startContainer.nodeType !== 3 &&
1226
+ (range.startContainer as HTMLElement).tagName === "HR") {
1227
+ range.setStartBefore(range.startContainer);
1228
+ }
1229
+ };
1230
+
1231
+ // firefox https://github.com/Vanessa219/vditor/issues/407
1232
+ export const fixFirefoxArrowUpTable = (event: KeyboardEvent, blockElement: false | HTMLElement, range: Range) => {
1233
+ if (!isFirefox()) {
1234
+ return false;
1235
+ }
1236
+ if (event.key === "ArrowUp" && blockElement && blockElement.previousElementSibling?.tagName === "TABLE") {
1237
+ const tableElement = blockElement.previousElementSibling as HTMLTableElement;
1238
+ range.selectNodeContents(tableElement.rows[tableElement.rows.length - 1].lastElementChild);
1239
+ range.collapse(false);
1240
+ event.preventDefault();
1241
+ return true;
1242
+ }
1243
+ if (event.key === "ArrowDown" && blockElement && blockElement.nextElementSibling?.tagName === "TABLE") {
1244
+ range.selectNodeContents((blockElement.nextElementSibling as HTMLTableElement).rows[0].cells[0]);
1245
+ range.collapse(true);
1246
+ event.preventDefault();
1247
+ return true;
1248
+ }
1249
+ return false;
1250
+ };
1251
+
1252
+ export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent) & { target: HTMLElement }, callback: {
1253
+ pasteCode(code: string): void,
1254
+ }) => {
1255
+ event.stopPropagation();
1256
+ event.preventDefault();
1257
+ let textHTML;
1258
+ let textPlain;
1259
+ let files;
1260
+ if ("clipboardData" in event) {
1261
+ textHTML = event.clipboardData.getData("text/html");
1262
+ textPlain = event.clipboardData.getData("text/plain");
1263
+ files = event.clipboardData.files;
1264
+ } else {
1265
+ textHTML = event.dataTransfer.getData("text/html");
1266
+ textPlain = event.dataTransfer.getData("text/plain");
1267
+ if (event.dataTransfer.types[0] === "Files") {
1268
+ files = event.dataTransfer.items;
1269
+ }
1270
+ }
1271
+ const renderers: {
1272
+ HTML2VditorDOM?: ILuteRender,
1273
+ HTML2VditorIRDOM?: ILuteRender,
1274
+ Md2VditorDOM?: ILuteRender,
1275
+ Md2VditorIRDOM?: ILuteRender,
1276
+ Md2VditorSVDOM?: ILuteRender,
1277
+ } = {};
1278
+ const renderLinkDest: ILuteRenderCallback = (node, entering) => {
1279
+ if (!entering) {
1280
+ return ["", Lute.WalkContinue];
1281
+ }
1282
+
1283
+ const src = node.TokensStr();
1284
+ if (node.__internal_object__.Parent.Type === 34 && src && src.indexOf("file://") === -1 &&
1285
+ vditor.options.upload.linkToImgUrl) {
1286
+ const xhr = new XMLHttpRequest();
1287
+ xhr.open("POST", vditor.options.upload.linkToImgUrl);
1288
+ if (vditor.options.upload.token) {
1289
+ xhr.setRequestHeader("X-Upload-Token", vditor.options.upload.token);
1290
+ }
1291
+ if (vditor.options.upload.withCredentials) {
1292
+ xhr.withCredentials = true;
1293
+ }
1294
+ setHeaders(vditor, xhr);
1295
+ xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
1296
+ xhr.onreadystatechange = () => {
1297
+ if (xhr.readyState === XMLHttpRequest.DONE) {
1298
+ if (xhr.status === 200) {
1299
+ let responseText = xhr.responseText;
1300
+ if (vditor.options.upload.linkToImgFormat) {
1301
+ responseText = vditor.options.upload.linkToImgFormat(xhr.responseText);
1302
+ }
1303
+ const responseJSON = JSON.parse(responseText);
1304
+ if (responseJSON.code !== 0) {
1305
+ vditor.tip.show(responseJSON.msg);
1306
+ return;
1307
+ }
1308
+ const original = responseJSON.data.originalURL;
1309
+ if (vditor.currentMode === "sv") {
1310
+ vditor.sv.element.querySelectorAll(".vditor-sv__marker--link")
1311
+ .forEach((item: HTMLElement) => {
1312
+ if (item.textContent === original) {
1313
+ item.textContent = responseJSON.data.url;
1314
+ }
1315
+ });
1316
+ } else {
1317
+ const imgElement: HTMLImageElement =
1318
+ vditor[vditor.currentMode].element.querySelector(`img[src="${original}"]`);
1319
+ imgElement.src = responseJSON.data.url;
1320
+ if (vditor.currentMode === "ir") {
1321
+ imgElement.previousElementSibling.previousElementSibling.innerHTML =
1322
+ responseJSON.data.url;
1323
+ }
1324
+ }
1325
+ execAfterRender(vditor);
1326
+ } else {
1327
+ vditor.tip.show(xhr.responseText);
1328
+ }
1329
+ if (vditor.options.upload.linkToImgCallback) {
1330
+ vditor.options.upload.linkToImgCallback(xhr.responseText);
1331
+ }
1332
+ }
1333
+ };
1334
+ xhr.send(JSON.stringify({url: src}));
1335
+ }
1336
+ if (vditor.currentMode === "ir") {
1337
+ return [`<span class="vditor-ir__marker vditor-ir__marker--link">${src}</span>`, Lute.WalkContinue];
1338
+ } else if (vditor.currentMode === "wysiwyg") {
1339
+ return ["", Lute.WalkContinue];
1340
+ } else {
1341
+ return [`<span class="vditor-sv__marker--link">${src}</span>`, Lute.WalkContinue];
1342
+ }
1343
+ };
1344
+
1345
+ // 浏览器地址栏拷贝处理
1346
+ if (textHTML.replace(/&amp;/g, "&").replace(/<(|\/)(html|body|meta)[^>]*?>/ig, "").trim() ===
1347
+ `<a href="${textPlain}">${textPlain}</a>` ||
1348
+ textHTML.replace(/&amp;/g, "&").replace(/<(|\/)(html|body|meta)[^>]*?>/ig, "").trim() ===
1349
+ `<!--StartFragment--><a href="${textPlain}">${textPlain}</a><!--EndFragment-->`) {
1350
+ textHTML = "";
1351
+ }
1352
+
1353
+ // process word
1354
+ const doc = new DOMParser().parseFromString(textHTML, "text/html");
1355
+ if (doc.body) {
1356
+ textHTML = doc.body.innerHTML;
1357
+ }
1358
+ textHTML = Lute.Sanitize(textHTML);
1359
+ vditor.wysiwyg.getComments(vditor);
1360
+
1361
+ // process code
1362
+ const height = vditor[vditor.currentMode].element.scrollHeight;
1363
+ const code = processPasteCode(textHTML, textPlain, vditor.currentMode);
1364
+ const codeElement = vditor.currentMode === "sv" ?
1365
+ hasClosestByAttribute(event.target, "data-type", "code-block") :
1366
+ hasClosestByMatchTag(event.target, "CODE");
1367
+ if (codeElement) {
1368
+ // 粘贴在代码位置
1369
+ if (vditor.currentMode === "sv") {
1370
+ document.execCommand("insertHTML", false, textPlain.replace(/&/g, "&amp;").replace(/</g, "&lt;"));
1371
+ } else {
1372
+ const position = getSelectPosition(event.target, vditor[vditor.currentMode].element);
1373
+ if (codeElement.parentElement.tagName !== "PRE") {
1374
+ // https://github.com/Vanessa219/vditor/issues/463
1375
+ textPlain += Constants.ZWSP;
1376
+ }
1377
+ codeElement.textContent = codeElement.textContent.substring(0, position.start)
1378
+ + textPlain + codeElement.textContent.substring(position.end);
1379
+ setSelectionByPosition(position.start + textPlain.length, position.start + textPlain.length,
1380
+ codeElement.parentElement);
1381
+ if (codeElement.parentElement?.nextElementSibling.classList
1382
+ .contains(`vditor-${vditor.currentMode}__preview`)) {
1383
+ codeElement.parentElement.nextElementSibling.innerHTML = codeElement.outerHTML;
1384
+ processCodeRender(codeElement.parentElement.nextElementSibling as HTMLElement, vditor);
1385
+ }
1386
+ }
1387
+ } else if (code) {
1388
+ callback.pasteCode(code);
1389
+ } else {
1390
+ if (textHTML.trim() !== "") {
1391
+ const tempElement = document.createElement("div");
1392
+ tempElement.innerHTML = textHTML;
1393
+ tempElement.querySelectorAll("[style]").forEach((e) => {
1394
+ e.removeAttribute("style");
1395
+ });
1396
+ tempElement.querySelectorAll(".vditor-copy").forEach((e) => {
1397
+ e.remove();
1398
+ });
1399
+ if (vditor.currentMode === "ir") {
1400
+ renderers.HTML2VditorIRDOM = {renderLinkDest};
1401
+ vditor.lute.SetJSRenderers({renderers});
1402
+ insertHTML(vditor.lute.HTML2VditorIRDOM(tempElement.innerHTML), vditor);
1403
+ } else if (vditor.currentMode === "wysiwyg") {
1404
+ renderers.HTML2VditorDOM = {renderLinkDest};
1405
+ vditor.lute.SetJSRenderers({renderers});
1406
+ insertHTML(vditor.lute.HTML2VditorDOM(tempElement.innerHTML), vditor);
1407
+ } else {
1408
+ renderers.Md2VditorSVDOM = {renderLinkDest};
1409
+ vditor.lute.SetJSRenderers({renderers});
1410
+ processPaste(vditor, vditor.lute.HTML2Md(tempElement.innerHTML).trimRight());
1411
+ }
1412
+ vditor.outline.render(vditor);
1413
+ } else if (files.length > 0 && vditor.options.upload.url) {
1414
+ await uploadFiles(vditor, files);
1415
+ } else if (textPlain.trim() !== "" && files.length === 0) {
1416
+ if (vditor.currentMode === "ir") {
1417
+ renderers.Md2VditorIRDOM = {renderLinkDest};
1418
+ vditor.lute.SetJSRenderers({renderers});
1419
+ insertHTML(vditor.lute.Md2VditorIRDOM(textPlain), vditor);
1420
+ } else if (vditor.currentMode === "wysiwyg") {
1421
+ renderers.Md2VditorDOM = {renderLinkDest};
1422
+ vditor.lute.SetJSRenderers({renderers});
1423
+ insertHTML(vditor.lute.Md2VditorDOM(textPlain), vditor);
1424
+ } else {
1425
+ renderers.Md2VditorSVDOM = {renderLinkDest};
1426
+ vditor.lute.SetJSRenderers({renderers});
1427
+ processPaste(vditor, textPlain);
1428
+ }
1429
+ vditor.outline.render(vditor);
1430
+ }
1431
+ }
1432
+ if (vditor.currentMode !== "sv") {
1433
+ const blockElement = hasClosestBlock(getEditorRange(vditor).startContainer);
1434
+ if (blockElement) {
1435
+ // https://github.com/Vanessa219/vditor/issues/591
1436
+ const range = getEditorRange(vditor);
1437
+ vditor[vditor.currentMode].element.querySelectorAll("wbr").forEach((wbr) => {
1438
+ wbr.remove();
1439
+ });
1440
+ range.insertNode(document.createElement("wbr"));
1441
+ if (vditor.currentMode === "wysiwyg") {
1442
+ blockElement.outerHTML = vditor.lute.SpinVditorDOM(blockElement.outerHTML);
1443
+ } else {
1444
+ blockElement.outerHTML = vditor.lute.SpinVditorIRDOM(blockElement.outerHTML);
1445
+ }
1446
+ setRangeByWbr(vditor[vditor.currentMode].element, range);
1447
+ }
1448
+ vditor[vditor.currentMode].element.querySelectorAll(`.vditor-${vditor.currentMode}__preview[data-render='2']`)
1449
+ .forEach((item: HTMLElement) => {
1450
+ processCodeRender(item, vditor);
1451
+ });
1452
+ }
1453
+ vditor.wysiwyg.triggerRemoveComment(vditor);
1454
+ execAfterRender(vditor);
1455
+ if (vditor[vditor.currentMode].element.scrollHeight - height >
1456
+ Math.min(vditor[vditor.currentMode].element.clientHeight, window.innerHeight) / 2) {
1457
+ scrollCenter(vditor);
1458
+ }
1459
+ };