@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,707 +0,0 @@
1
- // @ts-nocheck
2
- /**
3
- * Tencent is pleased to support the open source community by making CherryMarkdown available.
4
- *
5
- * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
6
- * The below software in this distribution may have been modified by THL A29 Limited ("Tencent Modifications").
7
- *
8
- * All Tencent Modifications are Copyright (C) THL A29 Limited.
9
- *
10
- * CherryMarkdown is licensed under the Apache License, Version 2.0 (the "License");
11
- * you may not use this file except in compliance with the License.
12
- * You may obtain a copy of the License at
13
- *
14
- * http://www.apache.org/licenses/LICENSE-2.0
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- */
22
- import escapeRegExp from 'lodash/escapeRegExp';
23
- import SyntaxBase from '@/core/SyntaxBase';
24
- import { allSuggestList, suggesterKeywords } from '@/core/hooks/SuggestList';
25
- import { Pass } from 'codemirror/src/util/misc';
26
- import { isLookbehindSupported } from '@/utils/regexp';
27
- import { replaceLookbehind } from '@/utils/lookbehind-replace';
28
- import { isBrowser } from '@/utils/env';
29
-
30
- /**
31
- * @typedef {import('codemirror')} CodeMirror
32
- */
33
-
34
- /**
35
- * @typedef { Object } SuggestListItemObject 推荐列表项对象
36
- * @property { string } icon 图标
37
- * @property { string } label 候选列表回显的内容
38
- * @property { string } value 点击候选项的时候回填的值
39
- * @property { string } keyword 关键词,通过关键词控制候选项的显隐
40
- * @typedef { SuggestListItemObject | string } SuggestListItem 推荐列表项
41
- * @typedef { Array<SuggestListItem> } SuggestList 推荐列表
42
- */
43
-
44
- /**
45
- * @typedef {object} SuggesterConfigItem
46
- * @property {function(string, function(SuggestList): void): void} suggestList
47
- * @property {string} keyword
48
- * @property {function} suggestListRender
49
- * @property {function} echo
50
- * @typedef {object} SuggesterConfig
51
- * @property {Array<SuggesterConfigItem>} suggester
52
- */
53
-
54
- export default class Suggester extends SyntaxBase {
55
- static HOOK_NAME = 'suggester';
56
-
57
- constructor({ config, cherry }) {
58
- /**
59
- * config.suggester 内容
60
- * [{
61
- * 请求url
62
- suggestList: '',
63
- 唤醒关键字
64
- keyword: '@',
65
- 建议模板 function
66
- suggestListRender(valueArray) {
67
-
68
- },
69
- 回填回调 function
70
- echo(value) {
71
-
72
- }]
73
- *
74
- */
75
-
76
- super({ needCache: true });
77
-
78
- this.config = config;
79
- this.$cherry = cherry;
80
- this.suggesterPanel = new SuggesterPanel(cherry);
81
-
82
- if (!this.inited) {
83
- this.initConfig(this.config);
84
- }
85
-
86
- this.RULE = this.rule();
87
- }
88
-
89
- afterInit(callback) {
90
- // node环境下直接跳过输入联想
91
- if (!isBrowser()) {
92
- return;
93
- }
94
- if (typeof callback === 'function') {
95
- callback();
96
- }
97
- }
98
-
99
- /**
100
- * 初始化配置
101
- * @param {SuggesterConfig} config
102
- */
103
- initConfig(config) {
104
- let { suggester } = config;
105
-
106
- this.suggester = {};
107
- const defaultSuggest = [];
108
- const that = this;
109
- // 默认的唤醒关键字
110
- for (const suggesterKeyword of suggesterKeywords) {
111
- defaultSuggest.push({
112
- keyword: suggesterKeyword,
113
- suggestList(_word, callback) {
114
- // 将word全转成小写
115
- const word = _word.toLowerCase();
116
- const systemSuggestList = allSuggestList(suggesterKeyword, that.$locale);
117
- // 加个空格就直接退出联想
118
- if (/^\s$/.test(word)) {
119
- callback(false);
120
- return;
121
- }
122
- const keyword = word
123
- .replace(/\s+/g, '') // 删掉空格,避免产生不必要的空数组元素
124
- .replace(new RegExp(`^${suggesterKeyword}`, 'g'), '') // 删掉word当中suggesterKeywords出现的字符
125
- .replace(/^[#]+/, '#')
126
- .replace(/^[/]+/, '/')
127
- .split('')
128
- .join('.*?');
129
- // 匹配任何包含 "keyword" 的字符串,无论 "keyword" 是在字符串的开头、中间还是结尾,并且不区分大小写
130
- const test = new RegExp(`^.*?${keyword}.*?$`, 'i');
131
- const suggestList = systemSuggestList.filter((item) => {
132
- // 处理精确匹配
133
- if (item.exactMatch) {
134
- return !word || item.keyword === word;
135
- }
136
- // TODO: 首次联想的时候会把所有的候选项列出来,后续可以增加一些机制改成默认拉取一部分候选项
137
- return !word || test.test(item.keyword);
138
- });
139
- // 当没有候选项时直接推出联想
140
- callback(suggestList.length === 0 ? false : suggestList);
141
- },
142
- echo() {
143
- return '';
144
- },
145
- });
146
- }
147
- if (!suggester) {
148
- suggester = defaultSuggest;
149
- } else {
150
- suggester = defaultSuggest.concat(suggester);
151
- }
152
-
153
- suggester.forEach((configItem) => {
154
- if (!configItem.suggestList) {
155
- console.warn('[cherry-suggester]: the suggestList of config is missing.');
156
- return;
157
- }
158
-
159
- if (!configItem.keyword) {
160
- configItem.keyword = '@';
161
- }
162
- this.suggester[configItem.keyword] = configItem;
163
- });
164
-
165
- // 反复初始化时, 缓存还在, dom 已更新情况
166
- if (this.suggesterPanel.hasEditor()) {
167
- this.suggesterPanel.editor = null;
168
- }
169
-
170
- this.inited = true;
171
- }
172
-
173
- makeHtml(str) {
174
- if (!this.RULE.reg) return str;
175
- if (!this.suggesterPanel.hasEditor() && isBrowser()) {
176
- const { editor } = this.$engine.$cherry;
177
- this.suggesterPanel.setEditor(editor);
178
- this.suggesterPanel.setSuggester(this.suggester);
179
- this.suggesterPanel.bindEvent();
180
- }
181
- if (isLookbehindSupported()) {
182
- return str.replace(this.RULE.reg, this.toHtml.bind(this));
183
- }
184
- return replaceLookbehind(str, this.RULE.reg, this.toHtml.bind(this), true, 1);
185
- }
186
-
187
- toHtml(wholeMatch, leadingChar, keyword, text) {
188
- if (text) {
189
- return (
190
- this.suggester[keyword]?.echo?.call(this, text) ||
191
- `${leadingChar}<span class="cherry-suggestion">${keyword}${text}</span>`
192
- );
193
- }
194
- if (this.suggester[keyword]?.echo === false) {
195
- return `${leadingChar}`;
196
- }
197
- if (!this.suggester[keyword]) {
198
- return leadingChar + text;
199
- }
200
- return text ? leadingChar + text : `${leadingChar}`;
201
- }
202
-
203
- rule() {
204
- if (!this.config?.suggester || Object.keys(this.config?.suggester).length <= 0) {
205
- return {};
206
- }
207
-
208
- let suggester;
209
- if (Array.isArray(this.config.suggester)) {
210
- suggester = this.config.suggester.map((obj) => obj.keyword || '');
211
- } else {
212
- suggester = Object.keys(this.config.suggester).map((key) => this.config.suggester[key].keyword || '');
213
- }
214
-
215
- const keys = suggester.map((key) => escapeRegExp(key)).join('|');
216
- const reg = new RegExp(
217
- `${isLookbehindSupported() ? '((?<!\\\\))[ ]' : '(^|[^\\\\])[ ]'}(${keys})(([^${keys}\\s])+)`,
218
- 'g',
219
- );
220
- return /** @type {any} */ ({
221
- reg,
222
- });
223
- }
224
-
225
- mounted() {
226
- if (!this.suggesterPanel.hasEditor() && isBrowser()) {
227
- const { editor } = this.$engine.$cherry;
228
- this.suggesterPanel.setEditor(editor);
229
- this.suggesterPanel.setSuggester(this.suggester);
230
- this.suggesterPanel.bindEvent();
231
- }
232
- }
233
- }
234
-
235
- class SuggesterPanel {
236
- constructor(cherry) {
237
- this.searchCache = false;
238
- this.searchKeyCache = [];
239
- this.optionList = [];
240
- this.cursorMove = true;
241
- this.suggesterConfig = {};
242
- this.$cherry = cherry;
243
- }
244
-
245
- /**
246
- * 如果没有panel,则尝试初始化一个,在node模式不初始化
247
- */
248
- tryCreatePanel() {
249
- if (!this.$suggesterPanel && isBrowser() && document) {
250
- this.$cherry.wrapperDom.appendChild(this.createDom(this.panelWrap));
251
- this.$suggesterPanel = this.$cherry.wrapperDom.querySelector('.cherry-suggester-panel');
252
- }
253
- }
254
-
255
- panelWrap = `<div class="cherry-suggester-panel"></div>`;
256
-
257
- hasEditor() {
258
- return !!this.editor && !!this.editor.editor.display && !!this.editor.editor.display.wrapper;
259
- }
260
-
261
- /**
262
- * 设置编辑器
263
- * @param {import('@/Editor').default} editor
264
- */
265
- setEditor(editor) {
266
- this.editor = editor;
267
- }
268
-
269
- setSuggester(suggester) {
270
- this.suggesterConfig = suggester;
271
- }
272
-
273
- bindEvent() {
274
- if (!this.editor.options.showSuggestList) {
275
- return;
276
- }
277
- let keyAction = false;
278
- this.editor.editor.on('change', (codemirror, evt) => {
279
- keyAction = true;
280
- this.onCodeMirrorChange(codemirror, evt);
281
- });
282
-
283
- this.editor.editor.on('keydown', (codemirror, evt) => {
284
- keyAction = true;
285
- if (this.enableRelate()) {
286
- this.onKeyDown(codemirror, evt);
287
- }
288
- });
289
-
290
- this.editor.editor.on('cursorActivity', () => {
291
- // 当编辑区光标位置改变时触发
292
- if (!keyAction) {
293
- this.stopRelate();
294
- }
295
- keyAction = false;
296
- });
297
-
298
- const extraKeys = this.editor.editor.getOption('extraKeys');
299
- const decorateKeys = ['Up', 'Down', 'Enter'];
300
- decorateKeys.forEach((key) => {
301
- if (typeof extraKeys[key] === 'function') {
302
- const proxyTarget = extraKeys[key];
303
- extraKeys[key] = (codemirror) => {
304
- if (this.cursorMove) {
305
- const res = proxyTarget.call(codemirror, codemirror);
306
-
307
- if (res) {
308
- return res;
309
- }
310
- // logic to decide whether to move up or not
311
- // return Pass.toString();
312
- }
313
- };
314
- } else if (!extraKeys[key]) {
315
- extraKeys[key] = () => {
316
- if (this.cursorMove) {
317
- // logic to decide whether to move up or not
318
- return Pass.toString();
319
- }
320
- };
321
- } else if (typeof extraKeys[key] === 'string') {
322
- const command = extraKeys[key];
323
- extraKeys[key] = (codemirror) => {
324
- if (this.cursorMove) {
325
- this.editor.editor.execCommand(command);
326
-
327
- // logic to decide whether to move up or not
328
- // return Pass.toString();
329
- }
330
- };
331
- }
332
- });
333
-
334
- this.editor.editor.setOption('extraKeys', extraKeys);
335
-
336
- this.editor.editor.on('scroll', (codemirror, evt) => {
337
- if (!this.searchCache) {
338
- return;
339
- }
340
- // 当编辑器滚动时触发
341
- this.relocatePanel(this.editor.editor);
342
- });
343
-
344
- this.onClickPanelItem();
345
- }
346
-
347
- onClickPanelItem() {
348
- this.tryCreatePanel();
349
- this.$suggesterPanel.addEventListener(
350
- 'click',
351
- (evt) => {
352
- const idx = isChildNode(this.$suggesterPanel, evt.target);
353
- if (idx > -1) {
354
- this.pasteSelectResult(idx);
355
- }
356
- this.stopRelate();
357
- },
358
- false,
359
- );
360
-
361
- function isChildNode(parent, node) {
362
- let res = -1;
363
- parent.childNodes.forEach((item, idx) => (item === node ? (res = idx) : ''));
364
- return res;
365
- }
366
- }
367
-
368
- showSuggesterPanel({ left, top, items }) {
369
- this.tryCreatePanel();
370
- if (!this.$suggesterPanel && isBrowser()) {
371
- this.$cherry.wrapperDom.appendChild(this.createDom(this.panelWrap));
372
- this.$suggesterPanel = this.$cherry.wrapperDom.querySelector('.cherry-suggester-panel');
373
- }
374
- this.updatePanel(items);
375
- this.$suggesterPanel.style.left = `${left}px`;
376
- this.$suggesterPanel.style.top = `${top}px`;
377
- this.$suggesterPanel.style.display = 'block';
378
- this.$suggesterPanel.style.position = 'absolute';
379
- this.$suggesterPanel.style.zIndex = '100';
380
- }
381
-
382
- hideSuggesterPanel() {
383
- this.tryCreatePanel();
384
- // const $suggesterPanel = document.querySelector('.cherry-suggester-panel');
385
- if (this.$suggesterPanel) {
386
- this.$suggesterPanel.style.display = 'none';
387
- }
388
- }
389
-
390
- /**
391
- * 更新suggesterPanel
392
- * @param {SuggestList} suggestList
393
- */
394
- updatePanel(suggestList) {
395
- this.tryCreatePanel();
396
- let defaultValue = suggestList
397
- .map((suggest, idx) => {
398
- if (typeof suggest === 'object' && suggest !== null) {
399
- let renderContent = suggest.label;
400
- if (suggest?.icon) {
401
- renderContent = `<i class="ch-icon ch-icon-${suggest.icon}"></i>${renderContent}`;
402
- }
403
- return this.renderPanelItem(renderContent, false);
404
- }
405
- return this.renderPanelItem(suggest, false);
406
- })
407
- .join('');
408
- /**
409
- * @type { SuggesterConfigItem }
410
- */
411
- const suggesterConfig = this.suggesterConfig[this.keyword];
412
- // 用户自定义渲染逻辑 suggestListRender
413
- if (suggesterConfig && typeof suggesterConfig.suggestListRender === 'function') {
414
- defaultValue = suggesterConfig.suggestListRender.call(this, suggestList) || defaultValue;
415
- }
416
-
417
- this.$suggesterPanel.innerHTML = ''; // 清空
418
- if (typeof defaultValue === 'string') {
419
- this.$suggesterPanel.innerHTML = defaultValue;
420
- } else if (Array.isArray(defaultValue) && defaultValue.length > 0) {
421
- defaultValue.forEach((item) => {
422
- this.$suggesterPanel.appendChild(item);
423
- });
424
- } else if (typeof defaultValue === 'object' && defaultValue.nodeType === 1) {
425
- this.$suggesterPanel.appendChild(defaultValue);
426
- }
427
- }
428
-
429
- /**
430
- * 渲染suggesterPanel item
431
- * @param {string} item 渲染内容
432
- * @param {boolean} selected 是否选中
433
- * @returns {string} html
434
- */
435
- renderPanelItem(item, selected) {
436
- if (selected) {
437
- return `<div class="cherry-suggester-panel__item cherry-suggester-panel__item--selected">${item}</div>`;
438
- }
439
- return `<div class="cherry-suggester-panel__item">${item}</div>`;
440
- }
441
-
442
- createDom(string = '') {
443
- if (!this.template) {
444
- this.template = document.createElement('div');
445
- }
446
-
447
- this.template.innerHTML = string.trim();
448
-
449
- // Change this to div.childNodes to support multiple top-level nodes
450
- const frag = document.createDocumentFragment();
451
- Array.prototype.map.call(this.template.childNodes, (item, idx) => {
452
- frag.appendChild(item);
453
- });
454
- return frag;
455
- }
456
-
457
- // 面板重定位
458
- relocatePanel(codemirror) {
459
- // 找到光标位置来确定候选框位置
460
- let $cursor = this.$cherry.wrapperDom.querySelector('.CodeMirror-cursors .CodeMirror-cursor');
461
- // 当editor选中某一内容时,".CodeMirror-cursor"会消失,此时通过定位".selected"来确定候选框位置
462
- if (!$cursor) {
463
- $cursor = this.$cherry.wrapperDom.querySelector('.CodeMirror-selected');
464
- }
465
- if (!$cursor) {
466
- return false;
467
- }
468
- const editorDomRect = this.$cherry.wrapperDom.getBoundingClientRect();
469
- const rect = $cursor.getBoundingClientRect();
470
- const top = rect.top + rect.height + 5 - editorDomRect.top;
471
- const left = rect.left - editorDomRect.left;
472
- this.showSuggesterPanel({ left, top, items: this.optionList });
473
- }
474
-
475
- /**
476
- * 获取光标位置
477
- * @param {CodeMirror} codemirror
478
- * @returns {{ left: number, top: number }}
479
- */
480
- getCursorPos(codemirror) {
481
- const $cursor = document.querySelector('.CodeMirror-cursors .CodeMirror-cursor');
482
- if (!$cursor) return null;
483
- const pos = codemirror.getCursor();
484
- const lineHeight = codemirror.lineInfo(pos.line).handle.height;
485
- const rect = $cursor.getBoundingClientRect();
486
- const top = rect.top + lineHeight;
487
- const { left } = rect;
488
- return { left, top };
489
- }
490
-
491
- // 开启关联
492
- startRelate(codemirror, keyword, from) {
493
- this.cursorFrom = from;
494
- this.keyword = keyword;
495
- this.searchCache = true;
496
- this.relocatePanel(codemirror);
497
- }
498
-
499
- // 关闭关联
500
- stopRelate() {
501
- this.hideSuggesterPanel();
502
- this.cursorFrom = null;
503
- this.cursorTo = null;
504
- this.keyword = '';
505
- this.searchKeyCache = [];
506
- this.searchCache = false;
507
- this.cursorMove = true;
508
- this.optionList = [];
509
- }
510
-
511
- /**
512
- * 粘贴选择结果
513
- * @param {number} idx 选择的结果索引
514
- * @param {KeyboardEvent} evt 键盘事件
515
- */
516
- pasteSelectResult(idx, evt) {
517
- if (!this.cursorTo || this.cursorTo === this.cursorFrom) {
518
- this.cursorTo = JSON.parse(JSON.stringify(this.cursorFrom));
519
- }
520
- if (!this.cursorTo) {
521
- return;
522
- }
523
- this.cursorTo.ch += 1;
524
- const { cursorFrom, cursorTo } = this; // 缓存光标位置
525
- if (this.optionList[idx]) {
526
- let result = '';
527
- if (
528
- typeof this.optionList[idx] === 'object' &&
529
- this.optionList[idx] !== null &&
530
- typeof this.optionList[idx].value === 'string'
531
- ) {
532
- result = this.optionList[idx].value;
533
- } else if (
534
- typeof this.optionList[idx] === 'object' &&
535
- this.optionList[idx] !== null &&
536
- typeof this.optionList[idx].value === 'function'
537
- ) {
538
- result = this.optionList[idx].value();
539
- } else {
540
- result = ` ${this.keyword}${this.optionList[idx]} `;
541
- }
542
- // this.cursorTo.ch = this.cursorFrom.ch + result.length;
543
- if (result) {
544
- this.editor.editor.replaceRange(result, cursorFrom, cursorTo);
545
- }
546
- // 控制光标左移若干位
547
- if (this.optionList[idx].goLeft) {
548
- const cursor = this.editor.editor.getCursor();
549
- this.editor.editor.setCursor(cursor.line, cursor.ch - this.optionList[idx].goLeft);
550
- }
551
- // 控制光标上移若干位
552
- if (this.optionList[idx].goTop) {
553
- const cursor = this.editor.editor.getCursor();
554
- this.editor.editor.setCursor(cursor.line - this.optionList[idx].goTop, cursor.ch);
555
- }
556
- // 选中某个范围
557
- if (this.optionList[idx].selection) {
558
- const { line } = this.editor.editor.getCursor();
559
- const { ch } = this.editor.editor.getCursor();
560
- this.editor.editor.setSelection(
561
- { line, ch: ch - this.optionList[idx].selection.from },
562
- { line, ch: ch - this.optionList[idx].selection.to },
563
- );
564
- }
565
- }
566
- }
567
-
568
- /**
569
- * 寻找当前选中项的索引
570
- * @returns {number}
571
- */
572
- findSelectedItemIndex() {
573
- return Array.prototype.findIndex.call(this.$suggesterPanel.childNodes, (item) =>
574
- item.classList.contains('cherry-suggester-panel__item--selected'),
575
- );
576
- }
577
-
578
- enableRelate() {
579
- return this.searchCache;
580
- }
581
-
582
- /**
583
- * codeMirror change事件
584
- * @param {CodeMirror.Editor} codemirror
585
- * @param {CodeMirror.EditorChange} evt
586
- * @returns
587
- */
588
- onCodeMirrorChange(codemirror, evt) {
589
- const { text, from, to, origin } = evt;
590
- const changeValue = text.length === 1 ? text[0] : '';
591
-
592
- // 首次输入命中关键词的时候开启联想
593
- if (!this.enableRelate() && this.suggesterConfig[changeValue]) {
594
- this.startRelate(codemirror, changeValue, from);
595
- }
596
- if (this.enableRelate() && (changeValue || origin === '+delete')) {
597
- this.cursorTo = to;
598
- if (changeValue) {
599
- this.searchKeyCache.push(changeValue);
600
- } else if (origin === '+delete') {
601
- this.searchKeyCache.pop();
602
- if (this.searchKeyCache.length === 0) {
603
- this.stopRelate();
604
- return;
605
- }
606
- }
607
- // 展示推荐列表
608
- if (typeof this.suggesterConfig[this.keyword]?.suggestList === 'function') {
609
- // 请求api 返回结果拼凑
610
- this.suggesterConfig[this.keyword].suggestList(this.searchKeyCache.join(''), (res) => {
611
- // 如果返回了false,则强制退出联想
612
- if (res === false) {
613
- this.stopRelate();
614
- return;
615
- }
616
- // 回显命中的结果
617
- this.optionList = !res || !res.length ? [] : res;
618
- this.updatePanel(this.optionList);
619
- });
620
- }
621
- }
622
- }
623
-
624
- /**
625
- * 监听方向键选择 options
626
- * @param {CodeMirror.Editor} codemirror
627
- * @param {KeyboardEvent} evt
628
- */
629
- onKeyDown(codemirror, evt) {
630
- this.tryCreatePanel();
631
- if (!this.$suggesterPanel) {
632
- return false;
633
- }
634
- const { keyCode } = evt;
635
- // up down
636
- if ([38, 40].includes(keyCode)) {
637
- // issue 558
638
- if (this.optionList.length === 0) {
639
- setTimeout(() => {
640
- this.stopRelate();
641
- }, 0);
642
- return;
643
- }
644
-
645
- this.cursorMove = false;
646
-
647
- const selectedItem =
648
- this.$suggesterPanel.querySelector('.cherry-suggester-panel__item--selected') ||
649
- this.$suggesterPanel.querySelector('.cherry-suggester-panel__item:last-child');
650
- let nextElement = null;
651
- if (keyCode === 38 && !selectedItem.previousElementSibling) {
652
- nextElement = this.$suggesterPanel.lastElementChild;
653
- // codemirror.focus();
654
- } else if (keyCode === 40 && !selectedItem.nextElementSibling) {
655
- nextElement = this.$suggesterPanel.firstElementChild;
656
- // codemirror.focus();
657
- } else {
658
- if (keyCode === 38) {
659
- nextElement = selectedItem.previousElementSibling;
660
- } else if (keyCode === 40) {
661
- nextElement = selectedItem.nextElementSibling;
662
- }
663
- }
664
-
665
- selectedItem.classList.remove('cherry-suggester-panel__item--selected');
666
-
667
- nextElement.classList.add('cherry-suggester-panel__item--selected');
668
-
669
- // 提示面板高度
670
- const suggestPanelHeight = this.$suggesterPanel.offsetHeight;
671
- // 可视区域范围上端
672
- const viewTop = this.$suggesterPanel.scrollTop;
673
- // 可视区域范围下端
674
- const viewBottom = viewTop + suggestPanelHeight;
675
- // item的上端
676
- const nextEleTop = nextElement.offsetTop;
677
- // item高度
678
- const nextEleHeight = nextElement.offsetHeight;
679
- // 当前元素全部或部分在可视区域之外,就滚动
680
- if (nextEleTop < viewTop || nextEleTop + nextEleHeight > viewBottom) {
681
- this.$suggesterPanel.scrollTop = nextEleTop - suggestPanelHeight / 2;
682
- }
683
- } else if (keyCode === 13) {
684
- const index = this.findSelectedItemIndex();
685
- if (index >= 0) {
686
- evt.stopPropagation();
687
- this.cursorMove = false;
688
- this.pasteSelectResult(index, evt);
689
- codemirror.focus();
690
- }
691
- // const cache = JSON.parse(JSON.stringify(this.cursorTo));
692
- // setTimeout(() => {
693
- // codemirror.setCursor(cache);
694
- // }, 100);
695
- setTimeout(() => {
696
- this.stopRelate();
697
- }, 0);
698
- } else if (keyCode === 27 || keyCode === 0x25 || keyCode === 0x27) {
699
- // 按下esc或者←、→键的时候退出联想
700
- evt.stopPropagation();
701
- codemirror.focus();
702
- setTimeout(() => {
703
- this.stopRelate();
704
- }, 0);
705
- }
706
- }
707
- }