@cherry-markdown/cherry-markdown-dev 0.9.0-dev.202504110650.834443a → 0.9.0-dev.202504160300.d23d141

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 (327) hide show
  1. package/README.md +2 -2
  2. package/dist/addons/advance/cherry-table-echarts-plugin.js +1 -1
  3. package/dist/addons/cherry-code-block-mermaid-plugin.js +1 -1
  4. package/dist/cherry-markdown.core.common.js +1 -1
  5. package/dist/cherry-markdown.core.js +1 -1
  6. package/dist/cherry-markdown.engine.core.common.js +1 -1
  7. package/dist/cherry-markdown.engine.core.esm.js +1 -1
  8. package/dist/cherry-markdown.engine.core.js +1 -1
  9. package/dist/cherry-markdown.esm.js +1 -1
  10. package/dist/cherry-markdown.js +1 -1
  11. package/dist/cherry-markdown.min.js +1 -1
  12. package/dist/fonts/ch-icon.eot +0 -0
  13. package/dist/fonts/ch-icon.ttf +0 -0
  14. package/dist/fonts/ch-icon.woff +0 -0
  15. package/dist/fonts/ch-icon.woff2 +0 -0
  16. package/package.json +1 -3
  17. package/src/Cherry.config.js +0 -634
  18. package/src/Cherry.js +0 -1104
  19. package/src/CherryStatic.js +0 -70
  20. package/src/Editor.js +0 -748
  21. package/src/Engine.js +0 -402
  22. package/src/Event.js +0 -140
  23. package/src/Factory.js +0 -180
  24. package/src/Logger.js +0 -31
  25. package/src/Previewer.js +0 -1192
  26. package/src/Sanitizer.js +0 -4
  27. package/src/Sanitizer.node.js +0 -7
  28. package/src/UrlCache.js +0 -98
  29. package/src/addons/advance/cherry-table-echarts-plugin.js +0 -170
  30. package/src/addons/cherry-code-block-mermaid-plugin.js +0 -158
  31. package/src/addons/cherry-code-block-plantuml-plugin.js +0 -106
  32. package/src/core/HookCenter.js +0 -297
  33. package/src/core/HooksConfig.js +0 -105
  34. package/src/core/ParagraphBase.js +0 -332
  35. package/src/core/SentenceBase.js +0 -65
  36. package/src/core/SyntaxBase.js +0 -194
  37. package/src/core/hooks/AutoLink.js +0 -232
  38. package/src/core/hooks/BackgroundColor.js +0 -46
  39. package/src/core/hooks/Blockquote.js +0 -70
  40. package/src/core/hooks/Br.js +0 -85
  41. package/src/core/hooks/CodeBlock.js +0 -456
  42. package/src/core/hooks/Color.js +0 -46
  43. package/src/core/hooks/CommentReference.js +0 -96
  44. package/src/core/hooks/Detail.js +0 -108
  45. package/src/core/hooks/Emoji.config.js +0 -1825
  46. package/src/core/hooks/Emoji.js +0 -119
  47. package/src/core/hooks/Emphasis.js +0 -113
  48. package/src/core/hooks/Footnote.js +0 -125
  49. package/src/core/hooks/FrontMatter.js +0 -51
  50. package/src/core/hooks/Header.js +0 -234
  51. package/src/core/hooks/HighLight.js +0 -37
  52. package/src/core/hooks/Hr.js +0 -52
  53. package/src/core/hooks/HtmlBlock.js +0 -199
  54. package/src/core/hooks/Image.js +0 -174
  55. package/src/core/hooks/InlineCode.js +0 -48
  56. package/src/core/hooks/InlineMath.js +0 -108
  57. package/src/core/hooks/Link.js +0 -160
  58. package/src/core/hooks/List.js +0 -264
  59. package/src/core/hooks/MathBlock.js +0 -104
  60. package/src/core/hooks/Panel.js +0 -145
  61. package/src/core/hooks/Paragraph.js +0 -84
  62. package/src/core/hooks/Ruby.js +0 -34
  63. package/src/core/hooks/Size.js +0 -51
  64. package/src/core/hooks/Strikethrough.js +0 -54
  65. package/src/core/hooks/Sub.js +0 -47
  66. package/src/core/hooks/SuggestList.js +0 -333
  67. package/src/core/hooks/Suggester.js +0 -707
  68. package/src/core/hooks/Sup.js +0 -47
  69. package/src/core/hooks/Table.js +0 -275
  70. package/src/core/hooks/Toc.js +0 -292
  71. package/src/core/hooks/Transfer.js +0 -47
  72. package/src/core/hooks/Underline.js +0 -37
  73. package/src/index.core.js +0 -29
  74. package/src/index.engine.core.js +0 -68
  75. package/src/index.engine.js +0 -28
  76. package/src/index.js +0 -32
  77. package/src/libs/mermaidAPI.8.4.8.js +0 -1
  78. package/src/libs/mermaidAPI.8.5.2.js +0 -42
  79. package/src/libs/rawdeflate.js +0 -1663
  80. package/src/locales/en_US.js +0 -139
  81. package/src/locales/index.js +0 -25
  82. package/src/locales/ru_RU.js +0 -139
  83. package/src/locales/zh_CN.js +0 -142
  84. package/src/sass/base.scss +0 -26
  85. package/src/sass/bubble_formula.scss +0 -166
  86. package/src/sass/ch-icon.scss +0 -118
  87. package/src/sass/cherry.scss +0 -1116
  88. package/src/sass/components/bubble.scss +0 -173
  89. package/src/sass/components/shortcut_key_config.scss +0 -108
  90. package/src/sass/formula_utils_bubble.scss +0 -82
  91. package/src/sass/icon_template.scss +0 -24
  92. package/src/sass/icons/uEA03-list.svg +0 -19
  93. package/src/sass/icons/uEA04-check.svg +0 -14
  94. package/src/sass/icons/uEA09-square.svg +0 -10
  95. package/src/sass/icons/uEA0A-bold.svg +0 -20
  96. package/src/sass/icons/uEA0B-code.svg +0 -18
  97. package/src/sass/icons/uEA0C-color.svg +0 -13
  98. package/src/sass/icons/uEA0D-header.svg +0 -8
  99. package/src/sass/icons/uEA0E-image.svg +0 -15
  100. package/src/sass/icons/uEA0F-italic.svg +0 -8
  101. package/src/sass/icons/uEA10-link.svg +0 -16
  102. package/src/sass/icons/uEA11-ol.svg +0 -21
  103. package/src/sass/icons/uEA12-size.svg +0 -11
  104. package/src/sass/icons/uEA13-strike.svg +0 -16
  105. package/src/sass/icons/uEA14-table.svg +0 -12
  106. package/src/sass/icons/uEA15-ul.svg +0 -17
  107. package/src/sass/icons/uEA16-underline.svg +0 -13
  108. package/src/sass/icons/uEA17-word.svg +0 -16
  109. package/src/sass/icons/uEA18-blockquote.svg +0 -11
  110. package/src/sass/icons/uEA19-font.svg +0 -10
  111. package/src/sass/icons/uEA1F-insertClass.svg +0 -39
  112. package/src/sass/icons/uEA20-insertFlow.svg +0 -8
  113. package/src/sass/icons/uEA21-insertFormula.svg +0 -23
  114. package/src/sass/icons/uEA22-insertGantt.svg +0 -13
  115. package/src/sass/icons/uEA23-insertGraph.svg +0 -13
  116. package/src/sass/icons/uEA24-insertPie.svg +0 -19
  117. package/src/sass/icons/uEA25-insertSeq.svg +0 -20
  118. package/src/sass/icons/uEA26-insertState.svg +0 -35
  119. package/src/sass/icons/uEA27-line.svg +0 -11
  120. package/src/sass/icons/uEA28-preview.svg +0 -18
  121. package/src/sass/icons/uEA29-previewClose.svg +0 -24
  122. package/src/sass/icons/uEA2A-toc.svg +0 -24
  123. package/src/sass/icons/uEA2D-sub.svg +0 -15
  124. package/src/sass/icons/uEA2E-sup.svg +0 -15
  125. package/src/sass/icons/uEA2F-h1.svg +0 -16
  126. package/src/sass/icons/uEA30-h2.svg +0 -20
  127. package/src/sass/icons/uEA31-h3.svg +0 -23
  128. package/src/sass/icons/uEA32-h4.svg +0 -16
  129. package/src/sass/icons/uEA33-h5.svg +0 -20
  130. package/src/sass/icons/uEA34-h6.svg +0 -17
  131. package/src/sass/icons/uEA35-video.svg +0 -20
  132. package/src/sass/icons/uEA36-insert.svg +0 -25
  133. package/src/sass/icons/uEA37-little_table.svg +0 -30
  134. package/src/sass/icons/uEA38-pdf.svg +0 -27
  135. package/src/sass/icons/uEA39-checklist.svg +0 -22
  136. package/src/sass/icons/uEA40-close.svg +0 -12
  137. package/src/sass/icons/uEA41-fullscreen.svg +0 -81
  138. package/src/sass/icons/uEA42-minscreen.svg +0 -77
  139. package/src/sass/icons/uEA43-insertChart.svg +0 -23
  140. package/src/sass/icons/uEA44-question.svg +0 -25
  141. package/src/sass/icons/uEA45-settings.svg +0 -32
  142. package/src/sass/icons/uEA46-ok.svg +0 -7
  143. package/src/sass/icons/uEA47-br.svg +0 -22
  144. package/src/sass/icons/uEA48-normal.svg +0 -15
  145. package/src/sass/icons/uEA49-undo.svg +0 -19
  146. package/src/sass/icons/uEA50-redo.svg +0 -21
  147. package/src/sass/icons/uEA51-copy.svg +0 -6
  148. package/src/sass/icons/uEA52-phone.svg +0 -5
  149. package/src/sass/icons/uEA53-cherry-table-delete.svg +0 -17
  150. package/src/sass/icons/uEA54-cherry-table-insert-bottom.svg +0 -16
  151. package/src/sass/icons/uEA55-cherry-table-insert-left.svg +0 -15
  152. package/src/sass/icons/uEA56-cherry-table-insert-right.svg +0 -16
  153. package/src/sass/icons/uEA57-cherry-table-insert-top.svg +0 -16
  154. package/src/sass/icons/uEA58-sort-s.svg +0 -13
  155. package/src/sass/icons/uEA59-pinyin.svg +0 -1
  156. package/src/sass/icons/uEA5A-create.svg +0 -24
  157. package/src/sass/icons/uEA5B-download.svg +0 -34
  158. package/src/sass/icons/uEA5C-edit.svg +0 -3
  159. package/src/sass/icons/uEA5D-export.svg +0 -53
  160. package/src/sass/icons/uEA5E-folder-open.svg +0 -3
  161. package/src/sass/icons/uEA5F-folder.svg +0 -3
  162. package/src/sass/icons/uEA60-help.svg +0 -5
  163. package/src/sass/icons/uEA61-pen-fill.svg +0 -13
  164. package/src/sass/icons/uEA62-pen.svg +0 -3
  165. package/src/sass/icons/uEA64-tips.svg +0 -5
  166. package/src/sass/icons/uEA65-warn.svg +0 -5
  167. package/src/sass/icons/uEA66-mistake.svg +0 -4
  168. package/src/sass/icons/uEA67-success.svg +0 -4
  169. package/src/sass/icons/uEA68-danger.svg +0 -4
  170. package/src/sass/icons/uEA69-info.svg +0 -5
  171. package/src/sass/icons/uEA6A-primary.svg +0 -5
  172. package/src/sass/icons/uEA6B-warning.svg +0 -5
  173. package/src/sass/icons/uEA6C-justify.svg +0 -19
  174. package/src/sass/icons/uEA6D-justifyCenter.svg +0 -19
  175. package/src/sass/icons/uEA6E-justifyLeft.svg +0 -19
  176. package/src/sass/icons/uEA6F-justifyRight.svg +0 -19
  177. package/src/sass/icons/uEA70-chevronsLeft.svg +0 -1
  178. package/src/sass/icons/uEA71-chevronsRight.svg +0 -1
  179. package/src/sass/icons/uEA72-trendingUp.svg +0 -1
  180. package/src/sass/icons/uEA74-codeBlock.svg +0 -1
  181. package/src/sass/icons/uEA75-expand.svg +0 -3
  182. package/src/sass/icons/uEA76-unExpand.svg +0 -3
  183. package/src/sass/icons/uEA77-swap-vert.svg +0 -1
  184. package/src/sass/icons/uEA78-swap.svg +0 -1
  185. package/src/sass/icons/uEA79-keyboard.svg +0 -1
  186. package/src/sass/icons/uEA7A-command.svg +0 -1
  187. package/src/sass/icons/uEA7B-search.svg +0 -1
  188. package/src/sass/index.scss +0 -3
  189. package/src/sass/markdown.scss +0 -668
  190. package/src/sass/markdown_pure.scss +0 -9
  191. package/src/sass/prettyprint/prettyprint.scss +0 -118
  192. package/src/sass/previewer.scss +0 -179
  193. package/src/sass/print.scss +0 -13
  194. package/src/sass/prism/coy.scss +0 -220
  195. package/src/sass/prism/dark.scss +0 -132
  196. package/src/sass/prism/default.scss +0 -143
  197. package/src/sass/prism/funky.scss +0 -133
  198. package/src/sass/prism/okaidia.scss +0 -126
  199. package/src/sass/prism/one-dark.scss +0 -440
  200. package/src/sass/prism/one-light.scss +0 -428
  201. package/src/sass/prism/solarized-light.scss +0 -153
  202. package/src/sass/prism/tomorrow-night.scss +0 -125
  203. package/src/sass/prism/twilight.scss +0 -202
  204. package/src/sass/prism/vs-dark.scss +0 -275
  205. package/src/sass/prism/vs-light.scss +0 -168
  206. package/src/sass/themes/blue.scss +0 -411
  207. package/src/sass/themes/dark.scss +0 -517
  208. package/src/sass/themes/default.scss +0 -255
  209. package/src/sass/themes/green.scss +0 -395
  210. package/src/sass/themes/light.scss +0 -368
  211. package/src/sass/themes/red.scss +0 -397
  212. package/src/sass/themes/violet.scss +0 -410
  213. package/src/sass/variable.scss +0 -84
  214. package/src/toolbars/Bubble.js +0 -234
  215. package/src/toolbars/BubbleFormula.js +0 -298
  216. package/src/toolbars/BubbleTable.js +0 -147
  217. package/src/toolbars/FloatMenu.js +0 -131
  218. package/src/toolbars/HiddenToolbar.js +0 -36
  219. package/src/toolbars/HookCenter.js +0 -231
  220. package/src/toolbars/MenuBase.js +0 -569
  221. package/src/toolbars/PreviewerBubble.js +0 -608
  222. package/src/toolbars/ShortcutKeyConfigPanel.js +0 -345
  223. package/src/toolbars/Sidebar.js +0 -36
  224. package/src/toolbars/Toc.js +0 -242
  225. package/src/toolbars/Toolbar.js +0 -449
  226. package/src/toolbars/ToolbarRight.js +0 -37
  227. package/src/toolbars/hooks/Audio.js +0 -79
  228. package/src/toolbars/hooks/BarTable.js +0 -41
  229. package/src/toolbars/hooks/Bold.js +0 -73
  230. package/src/toolbars/hooks/Br.js +0 -34
  231. package/src/toolbars/hooks/ChangeLocale.js +0 -62
  232. package/src/toolbars/hooks/ChatGpt.js +0 -182
  233. package/src/toolbars/hooks/CheckList.js +0 -41
  234. package/src/toolbars/hooks/Code.js +0 -49
  235. package/src/toolbars/hooks/CodeTheme.js +0 -66
  236. package/src/toolbars/hooks/Color.js +0 -298
  237. package/src/toolbars/hooks/Copy.js +0 -141
  238. package/src/toolbars/hooks/Detail.js +0 -69
  239. package/src/toolbars/hooks/DrawIo.js +0 -57
  240. package/src/toolbars/hooks/Export.js +0 -49
  241. package/src/toolbars/hooks/File.js +0 -79
  242. package/src/toolbars/hooks/Formula.js +0 -69
  243. package/src/toolbars/hooks/FullScreen.js +0 -50
  244. package/src/toolbars/hooks/Graph.js +0 -263
  245. package/src/toolbars/hooks/H1.js +0 -71
  246. package/src/toolbars/hooks/H2.js +0 -71
  247. package/src/toolbars/hooks/H3.js +0 -71
  248. package/src/toolbars/hooks/Header.js +0 -118
  249. package/src/toolbars/hooks/Hr.js +0 -35
  250. package/src/toolbars/hooks/Image.js +0 -91
  251. package/src/toolbars/hooks/InlineCode.js +0 -53
  252. package/src/toolbars/hooks/Insert.js +0 -193
  253. package/src/toolbars/hooks/Italic.js +0 -72
  254. package/src/toolbars/hooks/Justify.js +0 -49
  255. package/src/toolbars/hooks/LineTable.js +0 -41
  256. package/src/toolbars/hooks/Link.js +0 -49
  257. package/src/toolbars/hooks/List.js +0 -55
  258. package/src/toolbars/hooks/MobilePreview.js +0 -44
  259. package/src/toolbars/hooks/Ol.js +0 -41
  260. package/src/toolbars/hooks/Panel.js +0 -140
  261. package/src/toolbars/hooks/Pdf.js +0 -78
  262. package/src/toolbars/hooks/Publish.js +0 -123
  263. package/src/toolbars/hooks/QuickTable.js +0 -43
  264. package/src/toolbars/hooks/Quote.js +0 -45
  265. package/src/toolbars/hooks/Redo.js +0 -33
  266. package/src/toolbars/hooks/Ruby.js +0 -59
  267. package/src/toolbars/hooks/Search.js +0 -53
  268. package/src/toolbars/hooks/Settings.js +0 -220
  269. package/src/toolbars/hooks/ShortcutKey.js +0 -62
  270. package/src/toolbars/hooks/Size.js +0 -118
  271. package/src/toolbars/hooks/Split.js +0 -37
  272. package/src/toolbars/hooks/Strikethrough.js +0 -71
  273. package/src/toolbars/hooks/Sub.js +0 -58
  274. package/src/toolbars/hooks/Sup.js +0 -58
  275. package/src/toolbars/hooks/SwitchModel.js +0 -56
  276. package/src/toolbars/hooks/Table.js +0 -56
  277. package/src/toolbars/hooks/Theme.js +0 -62
  278. package/src/toolbars/hooks/Toc.js +0 -35
  279. package/src/toolbars/hooks/TogglePreview.js +0 -91
  280. package/src/toolbars/hooks/Ul.js +0 -41
  281. package/src/toolbars/hooks/Underline.js +0 -68
  282. package/src/toolbars/hooks/Undo.js +0 -30
  283. package/src/toolbars/hooks/Video.js +0 -79
  284. package/src/toolbars/hooks/Word.js +0 -78
  285. package/src/toolbars/hooks/WordCount.js +0 -106
  286. package/src/utils/autoindent.js +0 -58
  287. package/src/utils/cm-search-replace.js +0 -794
  288. package/src/utils/code-preview-language-setting.js +0 -180
  289. package/src/utils/codeBlockContentHandler.js +0 -400
  290. package/src/utils/config.js +0 -174
  291. package/src/utils/copy.js +0 -55
  292. package/src/utils/dialog.js +0 -214
  293. package/src/utils/dom.js +0 -163
  294. package/src/utils/downloadUtil.js +0 -23
  295. package/src/utils/env.js +0 -22
  296. package/src/utils/error.js +0 -61
  297. package/src/utils/event.js +0 -38
  298. package/src/utils/export.js +0 -166
  299. package/src/utils/file.js +0 -164
  300. package/src/utils/formulaUtilsHandler.js +0 -232
  301. package/src/utils/htmlparser.js +0 -976
  302. package/src/utils/image.js +0 -99
  303. package/src/utils/imgSizeHandler.js +0 -279
  304. package/src/utils/lazyLoadImg.js +0 -327
  305. package/src/utils/lineFeed.js +0 -49
  306. package/src/utils/listContentHandler.js +0 -227
  307. package/src/utils/lookbehind-replace.js +0 -81
  308. package/src/utils/mathjax.js +0 -89
  309. package/src/utils/myersDiff.js +0 -211
  310. package/src/utils/pasteHelper.js +0 -253
  311. package/src/utils/platformTransform.js +0 -71
  312. package/src/utils/recount-pos.js +0 -59
  313. package/src/utils/regexp.js +0 -295
  314. package/src/utils/sanitize.js +0 -477
  315. package/src/utils/selection.js +0 -50
  316. package/src/utils/shortcutKey.js +0 -291
  317. package/src/utils/svgUtils.js +0 -96
  318. package/src/utils/tableContentHandler.js +0 -876
  319. package/test/core/CommonMark.spec.ts +0 -62
  320. package/test/core/hooks/AutoLink.spec.ts +0 -28
  321. package/test/core/hooks/List.spec.ts +0 -79
  322. package/test/core/hooks/__snapshots__/List.spec.ts.snap +0 -11
  323. package/test/example.md +0 -778
  324. package/test/node.js +0 -10
  325. package/test/suites/commonmark.spec.json +0 -5218
  326. package/test/tsconfig.test.json +0 -6
  327. package/test/utils/regexp.spec.ts +0 -28
@@ -1,569 +0,0 @@
1
- /**
2
- * Copyright (C) 2021 THL A29 Limited, a Tencent company.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- // @ts-check
17
- import Logger from '@/Logger';
18
- import { escapeHTMLSpecialCharOnce as $e } from '@/utils/sanitize';
19
- import { createElement } from '@/utils/dom';
20
- import NestedError from '@/utils/error';
21
-
22
- /**
23
- * @typedef {Object} SubMenuConfigItem
24
- * @property {string} name - 子菜单项名称
25
- * @property {string=} iconName - 子菜单项图标名称
26
- * @property {function(MouseEvent): any} onclick - 子菜单项点击事件
27
- * @property {string=} icon - 子菜单项图标(url)
28
- * @property {boolean=} [disabledHideAllSubMenu=false] - 是否禁用后续调用hideAllSubMenu
29
- */
30
-
31
- /**
32
- * @typedef {Record<string, import('~types/cherry').ShortcutKeyMapStruct>} HookShortcutKeyMap
33
- */
34
-
35
- /**
36
- *
37
- * @param {HTMLElement} targetDom
38
- * @param {'absolute' | 'fixed' | 'sidebar'} [positionModel = 'absolute']
39
- * @returns {Pick<DOMRect, 'left' | 'top' | 'width' | 'height'>}
40
- */
41
- function getPosition(targetDom, positionModel = 'absolute') {
42
- const pos = targetDom.getBoundingClientRect();
43
- if (positionModel === 'fixed') {
44
- return pos;
45
- }
46
- // 侧边栏按钮做个特殊处理
47
- if (positionModel === 'sidebar') {
48
- const parent = MenuBase.getTargetParentByButton(targetDom);
49
- return {
50
- left: parent.offsetLeft - 130 + pos.width,
51
- top: targetDom.offsetTop + pos.height / 2,
52
- width: pos.width,
53
- height: pos.height,
54
- };
55
- }
56
- return { left: targetDom.offsetLeft, top: targetDom.offsetTop, width: pos.width, height: pos.height };
57
- }
58
-
59
- /**
60
- * @typedef {import('@/Editor').default} Editor
61
- */
62
-
63
- /**
64
- * @typedef {Partial<import('@/Cherry').default> & {$currentMenuOptions?:import('~types/menus').CustomMenuConfig}} MenuBaseConstructorParams
65
- */
66
-
67
- /**
68
- * @class MenuBase
69
- */
70
- export default class MenuBase {
71
- /**
72
- * @deprecated
73
- * @type {MenuBase['fire']}
74
- */
75
- _onClick;
76
-
77
- /**
78
- * @param {MenuBaseConstructorParams} $cherry
79
- */
80
- constructor($cherry) {
81
- this.$cherry = $cherry;
82
- this.bubbleMenu = false;
83
- this.subMenu = null; // 子菜单实例
84
- this.$currentMenuOptions = $cherry.$currentMenuOptions;
85
- // HookCenter 中会默认使currentMenuOptions的name属性与iconName属性一致
86
- this.name = $cherry.$currentMenuOptions?.name ?? ''; // 菜单项Name
87
- if (typeof $cherry.$currentMenuOptions?.icon === 'string') {
88
- this.iconName = $cherry.$currentMenuOptions.icon;
89
- }
90
- /** @type {import('~types/menus').MenuIconType} */
91
- this.iconType = null;
92
- this.editor = $cherry.editor; // markdown实例
93
- this.locale = $cherry.locale;
94
- this.dom = null;
95
- this.updateMarkdown = true; // 是否更新markdown原文
96
- /** @type {SubMenuConfigItem[]} */
97
- this.subMenuConfig = []; // 子菜单配置
98
- this.noIcon = false; // 是否不显示图标
99
- this.cacheOnce = false; // 是否保存一次点击事件生成的内容
100
- /**
101
- * 子菜单的定位方式
102
- * @property
103
- * @type {'absolute' | 'fixed' | 'sidebar'}
104
- */
105
- this.positionModel = 'absolute';
106
- // eslint-disable-next-line no-underscore-dangle
107
- if (typeof this._onClick === 'function') {
108
- Logger.warn('`MenuBase._onClick` is deprecated. Override `fire` instead');
109
- // eslint-disable-next-line no-underscore-dangle
110
- this.fire = this._onClick;
111
- }
112
- /**
113
- * 快捷键map映射
114
- * @type {HookShortcutKeyMap}
115
- */
116
- this.shortcutKeyMap = {};
117
- }
118
-
119
- getSubMenuConfig() {
120
- return this.subMenuConfig;
121
- }
122
-
123
- /**
124
- * 设置菜单
125
- * @param {string} name 菜单名称
126
- * @param {string} [iconName] 菜单图标名
127
- */
128
- setName(name, iconName) {
129
- this.name = name;
130
- this.iconName = iconName;
131
- this.$currentMenuOptions = { name, icon: iconName };
132
- }
133
-
134
- /**
135
- * 设置一个一次性缓存
136
- * 使用场景:
137
- * 当需要异步操作是,比如上传视频、选择字体颜色、通过棋盘插入表格等
138
- * 实现原理:
139
- * 1、第一次点击按钮时触发fire()方法,触发选择文件、选择颜色、选择棋盘格的操作。此时onClick()不返回任何数据。
140
- * 2、当异步操作完成后(如提交了文件、选择了颜色等),调用本方法(setCacheOnce)实现缓存,最后调用fire()方法
141
- * 3、当fire()方法再次调用onClick()方法时,onClick()方法会返回缓存的数据(getAndCleanCacheOnce)
142
- *
143
- * 这么设计的原因:
144
- * 1、可以复用MenuBase的相关方法
145
- * 2、避免异步操作直接与codemirror交互
146
- * @param {*} info
147
- */
148
- setCacheOnce(info) {
149
- this.cacheOnce = info;
150
- }
151
-
152
- getAndCleanCacheOnce() {
153
- this.updateMarkdown = true;
154
- const ret = this.cacheOnce;
155
- this.cacheOnce = false;
156
- return ret;
157
- }
158
-
159
- hasCacheOnce() {
160
- return this.cacheOnce !== false;
161
- }
162
-
163
- /**
164
- * 创建一个IconFont类型的图标
165
- * @param {string} iconName
166
- * @param {object} options
167
- */
168
- createIconFontIcon(iconName, options = {}) {
169
- const icon = createElement('i', `ch-icon ch-icon-${iconName}`);
170
- if (typeof options?.className === 'string') {
171
- icon.classList.add(options.className);
172
- }
173
- return icon;
174
- }
175
-
176
- /**
177
- * 创建一个SVG类型的图标
178
- * @param {import('~types/menus').CustomMenuIcon} options
179
- */
180
- createSvgIcon(options) {
181
- if (options.type !== 'svg') {
182
- throw new Error('except options.type is "svg", but get "${options.type}"');
183
- }
184
- try {
185
- const domParser = new DOMParser();
186
- const svg = domParser.parseFromString(options.content, 'image/svg+xml')?.lastElementChild;
187
- if (options.iconStyle) {
188
- svg.setAttribute('style', options.iconStyle);
189
- }
190
- if (options.iconClassName) {
191
- svg.setAttribute('class', options.iconClassName);
192
- }
193
- return svg;
194
- } catch (error) {
195
- throw new NestedError(error);
196
- }
197
- }
198
-
199
- /**
200
- * 创建一个Image类型的图标
201
- * @param {import('~types/menus').CustomMenuIcon} options
202
- */
203
- createImageIcon(options) {
204
- if (options.type !== 'image') {
205
- throw new Error('except options.type is "image", but get "${options.type}"');
206
- }
207
- return createElement('img', `ch-icon${options.iconClassName ? ` ${options.iconClassName}` : ''}`, {
208
- src: options.content,
209
- style: options.iconStyle,
210
- });
211
- }
212
-
213
- /**
214
- * 创建一个一级菜单
215
- * @param {boolean} asSubMenu 是否以子菜单的形式创建
216
- */
217
- createBtn(asSubMenu = false) {
218
- const classNames = asSubMenu
219
- ? 'cherry-dropdown-item'
220
- : `cherry-toolbar-button cherry-toolbar-${this.iconName ? this.iconName : this.name}`;
221
- const span = createElement('span', classNames, {
222
- title: this.locale[this.name] || $e(this.name),
223
- });
224
- if (!this.noIcon) {
225
- /** @type{Element} */
226
- let icon = null;
227
- const customIcon = this.$currentMenuOptions.icon;
228
- if (typeof customIcon === 'string') {
229
- // 默认 this.name 和 iconName 是一致的,除非手动调用 setName 方法来更改
230
- // 这里的逻辑就是 MenuBase 子类没有手动调用setName时则以传入的(默认跟hook name一致,可以在配置文件中更改)为准
231
- // 否则以子类set的为准
232
- icon = this.createIconFontIcon(this.iconName !== this.name ? this.iconName : customIcon);
233
- this.iconType = 'iconfont';
234
- } else if (customIcon instanceof HTMLElement) {
235
- icon = customIcon;
236
- this.iconType = 'element';
237
- } else if (typeof customIcon === 'object') {
238
- const { type } = customIcon;
239
- if (type === 'svg') {
240
- icon = this.createSvgIcon(customIcon);
241
- this.iconType = 'svg';
242
- } else if (type === 'image') {
243
- icon = this.createImageIcon(customIcon);
244
- this.iconType = 'image';
245
- } else if (type === 'iconfont') {
246
- icon = this.createIconFontIcon(customIcon.content);
247
- this.iconType = 'iconfont';
248
- } else {
249
- throw new Error(`except customIcon.type is "svg", "image", "iconfont", but get "${type}"`);
250
- }
251
- }
252
- if (icon !== null) {
253
- icon.classList.add(`cherry-menu-${this.name}`);
254
- span.appendChild(icon);
255
- }
256
- }
257
- // 二级菜单强制显示文字,没有图标的按钮也显示文字
258
- if (asSubMenu || this.noIcon) {
259
- span.innerHTML += this.locale[this.name] || $e(this.name);
260
- }
261
- // 只有一级菜单才保存dom,且只保存一次
262
- if (!asSubMenu && !this.dom) {
263
- this.dom = span;
264
- }
265
- return span;
266
- }
267
-
268
- /**
269
- * 通过配置创建一个二级菜单
270
- * @param {SubMenuConfigItem} config 配置
271
- */
272
- createSubBtnByConfig(config) {
273
- const { name, iconName, icon, onclick } = config;
274
- const span = createElement('span', 'cherry-dropdown-item', {
275
- title: this.locale[name] || $e(name),
276
- });
277
- if (iconName) {
278
- const iconElement = createElement('i', `ch-icon ch-icon-${iconName}`);
279
- span.appendChild(iconElement);
280
- } else if (icon) {
281
- const iconElement = createElement('img', 'ch-icon', {
282
- src: icon,
283
- style: 'width: 16px; height: 16px; vertical-align: sub;',
284
- });
285
- span.appendChild(iconElement);
286
- }
287
- span.innerHTML += this.locale[name] || $e(name);
288
- span.addEventListener('click', onclick, false);
289
- return span;
290
- }
291
-
292
- /**
293
- * 处理菜单项点击事件
294
- * @param {MouseEvent | KeyboardEvent | undefined} [event] 点击事件
295
- * @returns {void}
296
- */
297
- fire(event, shortKey = '') {
298
- event?.stopPropagation();
299
- if (typeof this.onClick === 'function') {
300
- const selections = this.editor.editor.getSelections();
301
- // 判断是不是多选
302
- this.isSelections = selections.length > 1;
303
- // 当onClick返回null、undefined、false时,维持原样
304
- const results = selections.map(
305
- (selection, index, srcArray) => this.onClick(selection, shortKey, event) || srcArray[index],
306
- );
307
- if (!this.bubbleMenu && this.updateMarkdown) {
308
- const hasPromise = results.some((result) => result instanceof Promise);
309
- if (hasPromise) {
310
- // 非下拉菜单按钮保留selection
311
- Promise.all(results.map((result) => (result instanceof Promise ? result : Promise.resolve(result)))).then(
312
- (resolvedResults) => {
313
- const safeResults = resolvedResults.map((result, index) =>
314
- result === undefined || result === null ? selections[index] : String(result),
315
- );
316
- this.editor.editor.replaceSelections(safeResults, 'around');
317
- this.editor.editor.focus();
318
- this.$afterClick();
319
- },
320
- );
321
- } else {
322
- this.editor.editor.replaceSelections(results, 'around');
323
- this.editor.editor.focus();
324
- this.$afterClick();
325
- }
326
- }
327
- }
328
- }
329
-
330
- /**
331
- * 获取当前选择区域的range
332
- */
333
- $getSelectionRange() {
334
- const { anchor, head } = this.editor.editor.listSelections()[0];
335
- // 如果begin在end的后面
336
- if ((anchor.line === head.line && anchor.ch > head.ch) || anchor.line > head.line) {
337
- return { begin: head, end: anchor };
338
- }
339
- return { begin: anchor, end: head };
340
- }
341
-
342
- /**
343
- * 注册点击事件渲染后的回调函数
344
- * @param {function} cb
345
- */
346
- registerAfterClickCb(cb) {
347
- this.afterClickCb = cb;
348
- }
349
-
350
- /**
351
- * 点击事件渲染后的回调函数
352
- */
353
- $afterClick() {
354
- if (typeof this.afterClickCb === 'function' && !this.isSelections) {
355
- this.afterClickCb();
356
- this.afterClickCb = null;
357
- }
358
- }
359
-
360
- /**
361
- * 选中除了前后语法后的内容
362
- * @param {String} lessBefore
363
- * @param {String} lessAfter
364
- */
365
- setLessSelection(lessBefore, lessAfter) {
366
- const cm = this.editor.editor;
367
- const { begin, end } = this.$getSelectionRange();
368
- const newBeginLine = lessBefore.match(/\n/g)?.length > 0 ? begin.line + lessBefore.match(/\n/g).length : begin.line;
369
- const newBeginCh =
370
- lessBefore.match(/\n/g)?.length > 0
371
- ? lessBefore.replace(/^[\s\S]*?\n([^\n]*)$/, '$1').length
372
- : begin.ch + lessBefore.length;
373
- const newBegin = { line: newBeginLine, ch: newBeginCh };
374
- const newEndLine = lessAfter.match(/\n/g)?.length > 0 ? end.line - lessAfter.match(/\n/g).length : end.line;
375
- const newEndCh = lessAfter.match(/\n/g)?.length > 0 ? cm.getLine(newEndLine).length : end.ch - lessAfter.length;
376
- const newEnd = { line: newEndLine, ch: newEndCh };
377
- cm.setSelection(newBegin, newEnd);
378
- }
379
-
380
- /**
381
- * 基于当前已选择区域,获取更多的选择区
382
- * @param {string} [appendBefore] 选择区前面追加的内容
383
- * @param {string} [appendAfter] 选择区后面追加的内容
384
- * @param {function} [cb] 回调函数,如果返回false,则恢复原来的选取
385
- */
386
- getMoreSelection(appendBefore, appendAfter, cb) {
387
- const cm = this.editor.editor;
388
- const { begin, end } = this.$getSelectionRange();
389
- let newBeginCh =
390
- // 如果只包含换行,则起始位置一定是0
391
- /\n/.test(appendBefore) ? 0 : begin.ch - appendBefore.length;
392
- newBeginCh = newBeginCh < 0 ? 0 : newBeginCh;
393
- let newBeginLine = /\n/.test(appendBefore) ? begin.line - appendBefore.match(/\n/g).length : begin.line;
394
- newBeginLine = newBeginLine < 0 ? 0 : newBeginLine;
395
- const newBegin = { line: newBeginLine, ch: newBeginCh };
396
- let newEndLine = end.line;
397
- let newEndCh = end.ch;
398
- if (/\n/.test(appendAfter)) {
399
- newEndLine = end.line + appendAfter.match(/\n/g).length;
400
- newEndCh = cm.getLine(newEndLine)?.length;
401
- } else {
402
- newEndCh =
403
- cm.getLine(end.line).length < end.ch + appendAfter.length
404
- ? cm.getLine(end.line).length
405
- : end.ch + appendAfter.length;
406
- }
407
- const newEnd = { line: newEndLine, ch: newEndCh };
408
- cm.setSelection(newBegin, newEnd);
409
- if (cb() === false) {
410
- cm.setSelection(begin, end);
411
- }
412
- }
413
-
414
- /**
415
- * 获取用户选中的文本内容,如果没有选中文本,则返回光标所在的位置的内容
416
- * @param {string} selection 当前选中的文本内容
417
- * @param {string} type 'line': 当没有选择文本时,获取光标所在行的内容; 'word': 当没有选择文本时,获取光标所在单词的内容
418
- * @param {boolean} focus true;强行选中光标处的内容,否则只获取选中的内容
419
- * @returns {string}
420
- */
421
- getSelection(selection, type = 'word', focus = false) {
422
- const cm = this.editor.editor;
423
- // 多光标模式下不做处理
424
- if (this.isSelections) {
425
- return selection;
426
- }
427
- if (selection && !focus) {
428
- return selection;
429
- }
430
- // 获取光标所在行的内容,同时选中所在行
431
- if (type === 'line') {
432
- const { begin, end } = this.$getSelectionRange();
433
- cm.setSelection({ line: begin.line, ch: 0 }, { line: end.line, ch: cm.getLine(end.line).length });
434
- return cm.getSelection();
435
- }
436
- // 获取光标所在单词的内容,同时选中所在单词
437
- if (type === 'word') {
438
- const { anchor: begin, head: end } = cm.findWordAt(cm.getCursor());
439
- cm.setSelection(begin, end);
440
- return cm.getSelection();
441
- }
442
- }
443
-
444
- /**
445
- * 反转子菜单点击事件参数顺序
446
- * @deprecated
447
- */
448
- bindSubClick(shortcut, selection) {
449
- return this.fire(null, shortcut);
450
- }
451
-
452
- onClick(selection, shortcut, callback) {
453
- return selection;
454
- }
455
-
456
- /**
457
- * 兼容之前的写法,但不支持配置
458
- */
459
- get shortcutKeys() {
460
- return [];
461
- }
462
-
463
- /**
464
- * 更新菜单图标
465
- * @param {import('~types/menus').CustomMenuConfig['icon']} options 图标配置
466
- */
467
- updateMenuIcon(options) {
468
- if (this.noIcon) {
469
- return false;
470
- }
471
- // 传入 options 是个字符串,说明是想要更新 iconfont,那就要求当前的icon类型也为iconfont
472
- if (typeof options === 'string') {
473
- if (this.iconType === 'iconfont') {
474
- this.dom.querySelector('i')?.classList.replace(`ch-icon-${this.iconName}`, `ch-icon-${options}`);
475
- this.iconName = options;
476
- this.$currentMenuOptions.icon = options;
477
- this.iconType = 'iconfont';
478
- return true;
479
- }
480
- return false;
481
- }
482
- if (options instanceof HTMLElement) {
483
- options.classList.add(`ch-icon cherry-menu-${this.name}`);
484
- this.dom.replaceChildren(options);
485
- this.iconType = 'element';
486
- return true;
487
- }
488
- let { iconName } = this;
489
- switch (options.type) {
490
- case 'iconfont':
491
- if (this.iconType === 'iconfont') {
492
- iconName = options.content;
493
- this.dom.querySelector('i')?.classList.replace(`ch-icon-${this.iconName}`, `ch-icon-${iconName}`);
494
- this.iconName = iconName;
495
- } else {
496
- const icon = this.createIconFontIcon(options.content, {
497
- className: `cherry-menu-${this.name}`,
498
- });
499
- if (options.iconClassName) {
500
- icon.classList.add(options.iconClassName);
501
- }
502
- if (options.iconStyle) {
503
- icon.setAttribute('style', options.iconStyle);
504
- }
505
- this.dom.replaceChildren(icon);
506
- }
507
- this.iconType = 'iconfont';
508
- break;
509
- case 'svg':
510
- this.dom.replaceChildren(this.createSvgIcon(options));
511
- this.iconType = 'svg';
512
- break;
513
- case 'image':
514
- this.dom.replaceChildren(this.createImageIcon(options));
515
- this.iconType = 'image';
516
- break;
517
- case 'element':
518
- throw Error(`except the options argument instance of HTMLElement, but get a type of ${typeof options}`);
519
- default:
520
- break;
521
- }
522
- }
523
-
524
- /**
525
- * 获取当前菜单的位置
526
- */
527
- getMenuPosition() {
528
- const parent = MenuBase.getTargetParentByButton(this.dom);
529
- const isFromSidebar = /cherry-sidebar/.test(parent.className);
530
- if (/cherry-bubble/.test(parent.className) || /cherry-floatmenu/.test(parent.className)) {
531
- this.positionModel = 'fixed';
532
- } else if (isFromSidebar) {
533
- this.positionModel = 'sidebar';
534
- } else {
535
- this.positionModel = 'absolute';
536
- }
537
- return getPosition(this.dom, this.positionModel);
538
- }
539
-
540
- hide() {
541
- this.dom.style.display = 'none';
542
- }
543
-
544
- show() {
545
- this.dom.style.display = 'block';
546
- }
547
-
548
- /**
549
- * 根据按钮获取按钮的父元素,这里父元素要绕过toolbar-(left|right)那一层
550
- * @param {HTMLElement} dom 按钮元素
551
- * @returns {HTMLElement} 父元素
552
- */
553
- static getTargetParentByButton(dom) {
554
- let parent = dom.parentElement;
555
- if (/toolbar-(left|right)/.test(parent.className)) {
556
- parent = parent.parentElement;
557
- }
558
- return parent;
559
- }
560
-
561
- /**
562
- * 绑定子菜单点击事件
563
- * @param {HTMLDivElement} subMenuDomPanel
564
- * @returns {number} 当前激活的子菜单索引
565
- */
566
- getActiveSubMenuIndex(subMenuDomPanel) {
567
- return -1;
568
- }
569
- }