@cherry-markdown/cherry-markdown-dev 0.8.58-dev
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.
- package/package.json +149 -0
- package/src/Cherry.config.js +625 -0
- package/src/Cherry.js +1104 -0
- package/src/CherryStatic.js +70 -0
- package/src/Editor.js +748 -0
- package/src/Engine.js +381 -0
- package/src/Event.js +140 -0
- package/src/Factory.js +180 -0
- package/src/Logger.js +31 -0
- package/src/Previewer.js +1183 -0
- package/src/Sanitizer.js +4 -0
- package/src/Sanitizer.node.js +7 -0
- package/src/UrlCache.js +98 -0
- package/src/addons/advance/cherry-table-echarts-plugin.js +170 -0
- package/src/addons/cherry-code-block-mermaid-plugin.js +158 -0
- package/src/addons/cherry-code-block-plantuml-plugin.js +106 -0
- package/src/core/HookCenter.js +297 -0
- package/src/core/HooksConfig.js +100 -0
- package/src/core/ParagraphBase.js +332 -0
- package/src/core/SentenceBase.js +65 -0
- package/src/core/SyntaxBase.js +194 -0
- package/src/core/hooks/AutoLink.js +232 -0
- package/src/core/hooks/BackgroundColor.js +46 -0
- package/src/core/hooks/Blockquote.js +70 -0
- package/src/core/hooks/Br.js +85 -0
- package/src/core/hooks/CodeBlock.js +446 -0
- package/src/core/hooks/Color.js +46 -0
- package/src/core/hooks/CommentReference.js +96 -0
- package/src/core/hooks/Detail.js +108 -0
- package/src/core/hooks/Emoji.config.js +1825 -0
- package/src/core/hooks/Emoji.js +119 -0
- package/src/core/hooks/Emphasis.js +113 -0
- package/src/core/hooks/Footnote.js +125 -0
- package/src/core/hooks/FrontMatter.js +51 -0
- package/src/core/hooks/Header.js +234 -0
- package/src/core/hooks/HighLight.js +37 -0
- package/src/core/hooks/Hr.js +52 -0
- package/src/core/hooks/HtmlBlock.js +184 -0
- package/src/core/hooks/Image.js +174 -0
- package/src/core/hooks/InlineCode.js +48 -0
- package/src/core/hooks/InlineMath.js +107 -0
- package/src/core/hooks/Link.js +160 -0
- package/src/core/hooks/List.js +264 -0
- package/src/core/hooks/MathBlock.js +103 -0
- package/src/core/hooks/Panel.js +145 -0
- package/src/core/hooks/Paragraph.js +84 -0
- package/src/core/hooks/Ruby.js +34 -0
- package/src/core/hooks/Size.js +51 -0
- package/src/core/hooks/Strikethrough.js +54 -0
- package/src/core/hooks/Sub.js +47 -0
- package/src/core/hooks/SuggestList.js +333 -0
- package/src/core/hooks/Suggester.js +707 -0
- package/src/core/hooks/Sup.js +47 -0
- package/src/core/hooks/Table.js +275 -0
- package/src/core/hooks/Toc.js +292 -0
- package/src/core/hooks/Transfer.js +47 -0
- package/src/core/hooks/Underline.js +37 -0
- package/src/index.core.js +29 -0
- package/src/index.engine.core.js +68 -0
- package/src/index.engine.js +28 -0
- package/src/index.js +32 -0
- package/src/libs/mermaidAPI.8.4.8.js +1 -0
- package/src/libs/mermaidAPI.8.5.2.js +42 -0
- package/src/libs/rawdeflate.js +1663 -0
- package/src/locales/en_US.js +139 -0
- package/src/locales/index.js +25 -0
- package/src/locales/ru_RU.js +139 -0
- package/src/locales/zh_CN.js +142 -0
- package/src/sass/base.scss +26 -0
- package/src/sass/bubble_formula.scss +166 -0
- package/src/sass/ch-icon.scss +118 -0
- package/src/sass/cherry.scss +1116 -0
- package/src/sass/components/bubble.scss +173 -0
- package/src/sass/components/shortcut_key_config.scss +108 -0
- package/src/sass/formula_utils_bubble.scss +82 -0
- package/src/sass/icon_template.scss +24 -0
- package/src/sass/icons/uEA03-list.svg +19 -0
- package/src/sass/icons/uEA04-check.svg +14 -0
- package/src/sass/icons/uEA09-square.svg +10 -0
- package/src/sass/icons/uEA0A-bold.svg +20 -0
- package/src/sass/icons/uEA0B-code.svg +18 -0
- package/src/sass/icons/uEA0C-color.svg +13 -0
- package/src/sass/icons/uEA0D-header.svg +8 -0
- package/src/sass/icons/uEA0E-image.svg +15 -0
- package/src/sass/icons/uEA0F-italic.svg +8 -0
- package/src/sass/icons/uEA10-link.svg +16 -0
- package/src/sass/icons/uEA11-ol.svg +21 -0
- package/src/sass/icons/uEA12-size.svg +11 -0
- package/src/sass/icons/uEA13-strike.svg +16 -0
- package/src/sass/icons/uEA14-table.svg +12 -0
- package/src/sass/icons/uEA15-ul.svg +17 -0
- package/src/sass/icons/uEA16-underline.svg +13 -0
- package/src/sass/icons/uEA17-word.svg +16 -0
- package/src/sass/icons/uEA18-blockquote.svg +11 -0
- package/src/sass/icons/uEA19-font.svg +10 -0
- package/src/sass/icons/uEA1F-insertClass.svg +39 -0
- package/src/sass/icons/uEA20-insertFlow.svg +8 -0
- package/src/sass/icons/uEA21-insertFormula.svg +23 -0
- package/src/sass/icons/uEA22-insertGantt.svg +13 -0
- package/src/sass/icons/uEA23-insertGraph.svg +13 -0
- package/src/sass/icons/uEA24-insertPie.svg +19 -0
- package/src/sass/icons/uEA25-insertSeq.svg +20 -0
- package/src/sass/icons/uEA26-insertState.svg +35 -0
- package/src/sass/icons/uEA27-line.svg +11 -0
- package/src/sass/icons/uEA28-preview.svg +18 -0
- package/src/sass/icons/uEA29-previewClose.svg +24 -0
- package/src/sass/icons/uEA2A-toc.svg +24 -0
- package/src/sass/icons/uEA2D-sub.svg +15 -0
- package/src/sass/icons/uEA2E-sup.svg +15 -0
- package/src/sass/icons/uEA2F-h1.svg +16 -0
- package/src/sass/icons/uEA30-h2.svg +20 -0
- package/src/sass/icons/uEA31-h3.svg +23 -0
- package/src/sass/icons/uEA32-h4.svg +16 -0
- package/src/sass/icons/uEA33-h5.svg +20 -0
- package/src/sass/icons/uEA34-h6.svg +17 -0
- package/src/sass/icons/uEA35-video.svg +20 -0
- package/src/sass/icons/uEA36-insert.svg +25 -0
- package/src/sass/icons/uEA37-little_table.svg +30 -0
- package/src/sass/icons/uEA38-pdf.svg +27 -0
- package/src/sass/icons/uEA39-checklist.svg +22 -0
- package/src/sass/icons/uEA40-close.svg +12 -0
- package/src/sass/icons/uEA41-fullscreen.svg +81 -0
- package/src/sass/icons/uEA42-minscreen.svg +77 -0
- package/src/sass/icons/uEA43-insertChart.svg +23 -0
- package/src/sass/icons/uEA44-question.svg +25 -0
- package/src/sass/icons/uEA45-settings.svg +32 -0
- package/src/sass/icons/uEA46-ok.svg +7 -0
- package/src/sass/icons/uEA47-br.svg +22 -0
- package/src/sass/icons/uEA48-normal.svg +15 -0
- package/src/sass/icons/uEA49-undo.svg +19 -0
- package/src/sass/icons/uEA50-redo.svg +21 -0
- package/src/sass/icons/uEA51-copy.svg +6 -0
- package/src/sass/icons/uEA52-phone.svg +5 -0
- package/src/sass/icons/uEA53-cherry-table-delete.svg +17 -0
- package/src/sass/icons/uEA54-cherry-table-insert-bottom.svg +16 -0
- package/src/sass/icons/uEA55-cherry-table-insert-left.svg +15 -0
- package/src/sass/icons/uEA56-cherry-table-insert-right.svg +16 -0
- package/src/sass/icons/uEA57-cherry-table-insert-top.svg +16 -0
- package/src/sass/icons/uEA58-sort-s.svg +13 -0
- package/src/sass/icons/uEA59-pinyin.svg +1 -0
- package/src/sass/icons/uEA5A-create.svg +24 -0
- package/src/sass/icons/uEA5B-download.svg +34 -0
- package/src/sass/icons/uEA5C-edit.svg +3 -0
- package/src/sass/icons/uEA5D-export.svg +53 -0
- package/src/sass/icons/uEA5E-folder-open.svg +3 -0
- package/src/sass/icons/uEA5F-folder.svg +3 -0
- package/src/sass/icons/uEA60-help.svg +5 -0
- package/src/sass/icons/uEA61-pen-fill.svg +13 -0
- package/src/sass/icons/uEA62-pen.svg +3 -0
- package/src/sass/icons/uEA64-tips.svg +5 -0
- package/src/sass/icons/uEA65-warn.svg +5 -0
- package/src/sass/icons/uEA66-mistake.svg +4 -0
- package/src/sass/icons/uEA67-success.svg +4 -0
- package/src/sass/icons/uEA68-danger.svg +4 -0
- package/src/sass/icons/uEA69-info.svg +5 -0
- package/src/sass/icons/uEA6A-primary.svg +5 -0
- package/src/sass/icons/uEA6B-warning.svg +5 -0
- package/src/sass/icons/uEA6C-justify.svg +19 -0
- package/src/sass/icons/uEA6D-justifyCenter.svg +19 -0
- package/src/sass/icons/uEA6E-justifyLeft.svg +19 -0
- package/src/sass/icons/uEA6F-justifyRight.svg +19 -0
- package/src/sass/icons/uEA70-chevronsLeft.svg +1 -0
- package/src/sass/icons/uEA71-chevronsRight.svg +1 -0
- package/src/sass/icons/uEA72-trendingUp.svg +1 -0
- package/src/sass/icons/uEA74-codeBlock.svg +1 -0
- package/src/sass/icons/uEA75-expand.svg +3 -0
- package/src/sass/icons/uEA76-unExpand.svg +3 -0
- package/src/sass/icons/uEA77-swap-vert.svg +1 -0
- package/src/sass/icons/uEA78-swap.svg +1 -0
- package/src/sass/icons/uEA79-keyboard.svg +1 -0
- package/src/sass/icons/uEA7A-command.svg +1 -0
- package/src/sass/icons/uEA7B-search.svg +1 -0
- package/src/sass/index.scss +3 -0
- package/src/sass/markdown.scss +668 -0
- package/src/sass/markdown_pure.scss +9 -0
- package/src/sass/prettyprint/prettyprint.scss +118 -0
- package/src/sass/previewer.scss +179 -0
- package/src/sass/print.scss +13 -0
- package/src/sass/prism/coy.scss +220 -0
- package/src/sass/prism/dark.scss +132 -0
- package/src/sass/prism/default.scss +143 -0
- package/src/sass/prism/funky.scss +133 -0
- package/src/sass/prism/okaidia.scss +126 -0
- package/src/sass/prism/one-dark.scss +440 -0
- package/src/sass/prism/one-light.scss +428 -0
- package/src/sass/prism/solarized-light.scss +153 -0
- package/src/sass/prism/tomorrow-night.scss +125 -0
- package/src/sass/prism/twilight.scss +202 -0
- package/src/sass/prism/vs-dark.scss +275 -0
- package/src/sass/prism/vs-light.scss +168 -0
- package/src/sass/themes/blue.scss +411 -0
- package/src/sass/themes/dark.scss +517 -0
- package/src/sass/themes/default.scss +255 -0
- package/src/sass/themes/green.scss +395 -0
- package/src/sass/themes/light.scss +368 -0
- package/src/sass/themes/red.scss +397 -0
- package/src/sass/themes/violet.scss +410 -0
- package/src/sass/variable.scss +84 -0
- package/src/toolbars/Bubble.js +234 -0
- package/src/toolbars/BubbleFormula.js +298 -0
- package/src/toolbars/BubbleTable.js +147 -0
- package/src/toolbars/FloatMenu.js +131 -0
- package/src/toolbars/HiddenToolbar.js +36 -0
- package/src/toolbars/HookCenter.js +234 -0
- package/src/toolbars/MenuBase.js +569 -0
- package/src/toolbars/PreviewerBubble.js +608 -0
- package/src/toolbars/ShortcutKeyConfigPanel.js +345 -0
- package/src/toolbars/Sidebar.js +36 -0
- package/src/toolbars/Toc.js +242 -0
- package/src/toolbars/Toolbar.js +449 -0
- package/src/toolbars/ToolbarRight.js +37 -0
- package/src/toolbars/hooks/Audio.js +79 -0
- package/src/toolbars/hooks/BarTable.js +41 -0
- package/src/toolbars/hooks/Bold.js +73 -0
- package/src/toolbars/hooks/Br.js +34 -0
- package/src/toolbars/hooks/ChangeLocale.js +62 -0
- package/src/toolbars/hooks/ChatGpt.js +182 -0
- package/src/toolbars/hooks/CheckList.js +41 -0
- package/src/toolbars/hooks/Code.js +49 -0
- package/src/toolbars/hooks/CodeTheme.js +66 -0
- package/src/toolbars/hooks/Color.js +298 -0
- package/src/toolbars/hooks/Copy.js +141 -0
- package/src/toolbars/hooks/Detail.js +69 -0
- package/src/toolbars/hooks/DrawIo.js +57 -0
- package/src/toolbars/hooks/Export.js +49 -0
- package/src/toolbars/hooks/File.js +79 -0
- package/src/toolbars/hooks/Formula.js +69 -0
- package/src/toolbars/hooks/FullScreen.js +50 -0
- package/src/toolbars/hooks/Graph.js +263 -0
- package/src/toolbars/hooks/H1.js +71 -0
- package/src/toolbars/hooks/H2.js +71 -0
- package/src/toolbars/hooks/H3.js +71 -0
- package/src/toolbars/hooks/Header.js +118 -0
- package/src/toolbars/hooks/Hr.js +35 -0
- package/src/toolbars/hooks/Image.js +91 -0
- package/src/toolbars/hooks/InlineCode.js +53 -0
- package/src/toolbars/hooks/Insert.js +193 -0
- package/src/toolbars/hooks/Italic.js +72 -0
- package/src/toolbars/hooks/Justify.js +49 -0
- package/src/toolbars/hooks/LineTable.js +41 -0
- package/src/toolbars/hooks/Link.js +49 -0
- package/src/toolbars/hooks/List.js +55 -0
- package/src/toolbars/hooks/MobilePreview.js +44 -0
- package/src/toolbars/hooks/Ol.js +41 -0
- package/src/toolbars/hooks/Panel.js +140 -0
- package/src/toolbars/hooks/Pdf.js +78 -0
- package/src/toolbars/hooks/Publish.js +123 -0
- package/src/toolbars/hooks/QuickTable.js +43 -0
- package/src/toolbars/hooks/Quote.js +45 -0
- package/src/toolbars/hooks/Redo.js +33 -0
- package/src/toolbars/hooks/Ruby.js +59 -0
- package/src/toolbars/hooks/Search.js +53 -0
- package/src/toolbars/hooks/Settings.js +220 -0
- package/src/toolbars/hooks/ShortcutKey.js +62 -0
- package/src/toolbars/hooks/Size.js +118 -0
- package/src/toolbars/hooks/Split.js +37 -0
- package/src/toolbars/hooks/Strikethrough.js +71 -0
- package/src/toolbars/hooks/Sub.js +58 -0
- package/src/toolbars/hooks/Sup.js +58 -0
- package/src/toolbars/hooks/SwitchModel.js +56 -0
- package/src/toolbars/hooks/Table.js +56 -0
- package/src/toolbars/hooks/Theme.js +62 -0
- package/src/toolbars/hooks/Toc.js +35 -0
- package/src/toolbars/hooks/TogglePreview.js +91 -0
- package/src/toolbars/hooks/Ul.js +41 -0
- package/src/toolbars/hooks/Underline.js +68 -0
- package/src/toolbars/hooks/Undo.js +30 -0
- package/src/toolbars/hooks/Video.js +79 -0
- package/src/toolbars/hooks/Word.js +78 -0
- package/src/toolbars/hooks/WordCount.js +106 -0
- package/src/utils/autoindent.js +58 -0
- package/src/utils/cm-search-replace.js +794 -0
- package/src/utils/code-preview-language-setting.js +180 -0
- package/src/utils/codeBlockContentHandler.js +400 -0
- package/src/utils/config.js +174 -0
- package/src/utils/copy.js +55 -0
- package/src/utils/dialog.js +214 -0
- package/src/utils/dom.js +163 -0
- package/src/utils/downloadUtil.js +23 -0
- package/src/utils/env.js +22 -0
- package/src/utils/error.js +61 -0
- package/src/utils/event.js +38 -0
- package/src/utils/export.js +166 -0
- package/src/utils/file.js +164 -0
- package/src/utils/formulaUtilsHandler.js +232 -0
- package/src/utils/htmlparser.js +976 -0
- package/src/utils/image.js +99 -0
- package/src/utils/imgSizeHandler.js +279 -0
- package/src/utils/lazyLoadImg.js +327 -0
- package/src/utils/lineFeed.js +49 -0
- package/src/utils/listContentHandler.js +227 -0
- package/src/utils/lookbehind-replace.js +81 -0
- package/src/utils/mathjax.js +89 -0
- package/src/utils/myersDiff.js +211 -0
- package/src/utils/pasteHelper.js +253 -0
- package/src/utils/platformTransform.js +71 -0
- package/src/utils/recount-pos.js +59 -0
- package/src/utils/regexp.js +295 -0
- package/src/utils/sanitize.js +477 -0
- package/src/utils/selection.js +50 -0
- package/src/utils/shortcutKey.js +291 -0
- package/src/utils/svgUtils.js +96 -0
- package/src/utils/tableContentHandler.js +876 -0
- package/test/core/CommonMark.spec.ts +62 -0
- package/test/core/hooks/AutoLink.spec.ts +28 -0
- package/test/core/hooks/List.spec.ts +79 -0
- package/test/core/hooks/__snapshots__/List.spec.ts.snap +11 -0
- package/test/example.md +778 -0
- package/test/node.js +10 -0
- package/test/suites/commonmark.spec.json +5218 -0
- package/test/tsconfig.test.json +6 -0
- package/test/utils/regexp.spec.ts +28 -0
- package/types/cherry.d.ts +675 -0
- package/types/codemirror.d.ts +22 -0
- package/types/editor.d.ts +72 -0
- package/types/global.d.ts +16 -0
- package/types/menus.d.ts +24 -0
- package/types/previewer.d.ts +53 -0
- package/types/syntax.d.ts +52 -0
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
/**
|
|
17
|
+
* 三个地方的错误异常校验
|
|
18
|
+
* 1. markdown 对象参数校验
|
|
19
|
+
* 2. editText 用户输入校验,执行engine过程以防异常
|
|
20
|
+
* 3. 自定义hook校验 对外开发者开发标准校验
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const $expectTarget = (target, Constructor) => {
|
|
24
|
+
if (
|
|
25
|
+
(!Array.isArray(target) && typeof target !== Constructor.name.toLowerCase()) ||
|
|
26
|
+
(!Array.isArray(target) && Constructor.name.toLowerCase() === 'array')
|
|
27
|
+
) {
|
|
28
|
+
throw new TypeError(`parameter given must be ${Constructor.name}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return true;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const $expectInherit = (target, parent) => {
|
|
35
|
+
if (!(target instanceof parent)) {
|
|
36
|
+
throw new Error('the hook does not correctly inherit');
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const $expectInstance = (target) => {
|
|
42
|
+
if (typeof target !== 'object') {
|
|
43
|
+
throw new Error('the hook must be a instance, not a class');
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// ref: https://github.com/mdlavin/nested-error-stacks
|
|
49
|
+
export default class NestedError extends Error {
|
|
50
|
+
constructor(message, nested) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = 'Error';
|
|
53
|
+
this.stack = this.buildStackTrace(nested);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
buildStackTrace(nested) {
|
|
57
|
+
const stack = nested && nested.stack ? nested.stack : '';
|
|
58
|
+
const newStack = `${this.stack}\nCaused By: ${stack}`;
|
|
59
|
+
return newStack;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
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
|
+
export function addEvent(elm, evType, fn, useCapture) {
|
|
17
|
+
if (elm.addEventListener) {
|
|
18
|
+
elm.addEventListener(evType, fn, useCapture); // DOM2.0
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (elm.attachEvent) {
|
|
23
|
+
const r = elm.attachEvent(`on${evType}`, fn); // IE5+
|
|
24
|
+
return r;
|
|
25
|
+
}
|
|
26
|
+
elm[`on${evType}`] = fn; // DOM 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function removeEvent(elm, evType, fn, useCapture) {
|
|
30
|
+
if (elm.removeEventListener) {
|
|
31
|
+
elm.removeEventListener(evType, fn, useCapture); // DOM2.0
|
|
32
|
+
} else if (elm.detachEvent) {
|
|
33
|
+
const r = elm.detachEvent(`on${evType}`, fn); // IE5+
|
|
34
|
+
return r;
|
|
35
|
+
} else {
|
|
36
|
+
elm[`on${evType}`] = null; // DOM 0
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
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
|
+
import html2canvas from 'html2canvas';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 先把body上的内容隐藏起来
|
|
20
|
+
* @returns {Array} displayList 记录body子元素原始的显隐信息
|
|
21
|
+
*/
|
|
22
|
+
const hideBodyChildren = () => {
|
|
23
|
+
const displayList = [];
|
|
24
|
+
/** @type {HTMLElement[]}*/ (Array.from(document.body.children)).forEach((dom, index) => {
|
|
25
|
+
displayList[index] = dom.style.display;
|
|
26
|
+
dom.style.display = 'none';
|
|
27
|
+
});
|
|
28
|
+
return displayList;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 复原body上被隐藏的内容
|
|
33
|
+
* @param {Array} displayList 记录body子元素原始的显隐信息
|
|
34
|
+
*/
|
|
35
|
+
const undoHideBodyChildren = (displayList = []) => {
|
|
36
|
+
/** @type {HTMLElement[]}*/ (Array.from(document.body.children)).forEach((dom, index) => {
|
|
37
|
+
if (typeof displayList[index] !== 'undefined') {
|
|
38
|
+
dom.style.display = displayList[index];
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 将预览区域的内容放在body上准备后续导出操作
|
|
45
|
+
* @param {HTMLElement} previewDom 预览区域的dom
|
|
46
|
+
* @param {function} cb 准备好导出后开始执行导出操作
|
|
47
|
+
*/
|
|
48
|
+
const getReadyToExport = (previewDom, cb) => {
|
|
49
|
+
const cherryPreviewer = /** @type {HTMLElement}*/ (previewDom.cloneNode(true));
|
|
50
|
+
// 强制去掉预览区的隐藏class
|
|
51
|
+
cherryPreviewer.className = cherryPreviewer.className.replace('cherry-previewer--hidden', '');
|
|
52
|
+
cherryPreviewer.style.width = '100%';
|
|
53
|
+
const mmls = cherryPreviewer.querySelectorAll('mjx-assistive-mml');
|
|
54
|
+
// a fix for html2canvas
|
|
55
|
+
mmls.forEach((e) => {
|
|
56
|
+
if (e instanceof HTMLElement) e.style.setProperty('visibility', 'hidden');
|
|
57
|
+
});
|
|
58
|
+
const cherryWrapper = document.createElement('div');
|
|
59
|
+
cherryWrapper.appendChild(cherryPreviewer);
|
|
60
|
+
const displayList = hideBodyChildren();
|
|
61
|
+
document.body.appendChild(cherryWrapper);
|
|
62
|
+
const bodyOverflow = document.body.style.overflow;
|
|
63
|
+
document.body.style.overflow = 'visible';
|
|
64
|
+
cb(cherryPreviewer, () => {
|
|
65
|
+
cherryWrapper.remove();
|
|
66
|
+
undoHideBodyChildren(displayList);
|
|
67
|
+
document.body.style.overflow = bodyOverflow;
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 下载文件
|
|
73
|
+
* @param {String} downloadUrl 图片本地地址
|
|
74
|
+
* @param {String} fileName 导出图片文件名
|
|
75
|
+
*/
|
|
76
|
+
const fileDownload = (downloadUrl, fileName) => {
|
|
77
|
+
const aLink = document.createElement('a');
|
|
78
|
+
aLink.style.display = 'none';
|
|
79
|
+
aLink.href = downloadUrl;
|
|
80
|
+
aLink.download = `${fileName}.png`;
|
|
81
|
+
document.body.appendChild(aLink);
|
|
82
|
+
aLink.click();
|
|
83
|
+
document.body.removeChild(aLink);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 利用window.print导出成PDF
|
|
88
|
+
* @param {HTMLElement} previewDom 预览区域的dom
|
|
89
|
+
* @param {String} fileName 导出PDF文件名
|
|
90
|
+
*/
|
|
91
|
+
export function exportPDF(previewDom, fileName) {
|
|
92
|
+
const oldTitle = document.title;
|
|
93
|
+
document.title = fileName;
|
|
94
|
+
getReadyToExport(previewDom, (/** @type {HTMLElement}*/ cherryPreviewer, /** @type {function}*/ thenFinish) => {
|
|
95
|
+
// 强制展开所有代码块
|
|
96
|
+
cherryPreviewer.innerHTML = cherryPreviewer.innerHTML.replace(
|
|
97
|
+
/class="cherry-code-unExpand("| )/g,
|
|
98
|
+
'class="cherry-code-expand$1',
|
|
99
|
+
);
|
|
100
|
+
window.print();
|
|
101
|
+
thenFinish();
|
|
102
|
+
document.title = oldTitle;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 利用canvas将html内容导出成图片
|
|
108
|
+
* @param {HTMLElement} previewDom 预览区域的dom
|
|
109
|
+
* @param {String} fileName 导出图片文件名
|
|
110
|
+
*/
|
|
111
|
+
export function exportScreenShot(previewDom, fileName) {
|
|
112
|
+
getReadyToExport(previewDom, (/** @type {HTMLElement}*/ cherryPreviewer, /** @type {function}*/ thenFinish) => {
|
|
113
|
+
window.scrollTo(0, 0);
|
|
114
|
+
// 去掉audio和video标签
|
|
115
|
+
cherryPreviewer.innerHTML = cherryPreviewer.innerHTML.replace(/<audio [^>]+?>([^\n]*?)<\/audio>/g, '$1');
|
|
116
|
+
cherryPreviewer.innerHTML = cherryPreviewer.innerHTML.replace(/<video [^>]+?>([^\n]*?)<\/video>/g, '$1');
|
|
117
|
+
// 强制展开所有代码块
|
|
118
|
+
cherryPreviewer.innerHTML = cherryPreviewer.innerHTML.replace(
|
|
119
|
+
/class="cherry-code-unExpand("| )/g,
|
|
120
|
+
'class="cherry-code-expand$1',
|
|
121
|
+
);
|
|
122
|
+
html2canvas(cherryPreviewer, {
|
|
123
|
+
allowTaint: true,
|
|
124
|
+
height: cherryPreviewer.clientHeight,
|
|
125
|
+
width: cherryPreviewer.clientWidth,
|
|
126
|
+
scrollY: 0,
|
|
127
|
+
scrollX: 0,
|
|
128
|
+
}).then((canvas) => {
|
|
129
|
+
const imgData = canvas.toDataURL('image/jpeg');
|
|
130
|
+
fileDownload(imgData, fileName);
|
|
131
|
+
thenFinish();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 导出 markdown 文件
|
|
138
|
+
* @param {String} markdownText markdown文本
|
|
139
|
+
* @param {String} fileName 导出markdown文件名
|
|
140
|
+
*/
|
|
141
|
+
export function exportMarkdownFile(markdownText, fileName) {
|
|
142
|
+
const blob = new Blob([markdownText], { type: 'text/markdown;charset=utf-8' });
|
|
143
|
+
const aLink = document.createElement('a');
|
|
144
|
+
aLink.style.display = 'none';
|
|
145
|
+
aLink.href = URL.createObjectURL(blob);
|
|
146
|
+
aLink.download = `${fileName}.md`;
|
|
147
|
+
document.body.appendChild(aLink);
|
|
148
|
+
aLink.click();
|
|
149
|
+
document.body.removeChild(aLink);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 导出预览区 HTML 文件
|
|
154
|
+
* @param {String} HTMLText HTML文本
|
|
155
|
+
* @param {String} fileName 导出HTML文件名
|
|
156
|
+
*/
|
|
157
|
+
export function exportHTMLFile(HTMLText, fileName) {
|
|
158
|
+
const blob = new Blob([HTMLText], { type: 'text/markdown;charset=utf-8' });
|
|
159
|
+
const aLink = document.createElement('a');
|
|
160
|
+
aLink.style.display = 'none';
|
|
161
|
+
aLink.href = URL.createObjectURL(blob);
|
|
162
|
+
aLink.download = `${fileName}.html`;
|
|
163
|
+
document.body.appendChild(aLink);
|
|
164
|
+
aLink.click();
|
|
165
|
+
document.body.removeChild(aLink);
|
|
166
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
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
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 多选上传文件的逻辑,如果有callback,则不再走默认的替换文本的逻辑,而是调用callback
|
|
19
|
+
* @param {string} type 上传文件的类型
|
|
20
|
+
*/
|
|
21
|
+
export function handleUploadMulti(editor, type = 'image', accept = '*', callback = null) {
|
|
22
|
+
// type为上传文件类型 image|video|audio|pdf|word
|
|
23
|
+
const input = document.createElement('input');
|
|
24
|
+
const inputMultiple = editor.$cherry.options.multipleFileSelection || false;
|
|
25
|
+
input.type = 'file';
|
|
26
|
+
input.id = 'fileUpload';
|
|
27
|
+
input.value = '';
|
|
28
|
+
input.style.display = 'none';
|
|
29
|
+
input.accept = accept;
|
|
30
|
+
input.multiple = inputMultiple;
|
|
31
|
+
// document.body.appendChild(input);
|
|
32
|
+
input.addEventListener('change', (event) => {
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
const { files } = event.target;
|
|
35
|
+
// 文件上传后的回调函数可以由调用方自己实现
|
|
36
|
+
editor.$cherry.options.callback.fileUploadMulti(files, (arr) => {
|
|
37
|
+
// 文件上传的默认回调行数,调用方可以完全不使用该函数
|
|
38
|
+
if (arr.length === 0) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (callback) {
|
|
42
|
+
return callback(arr);
|
|
43
|
+
}
|
|
44
|
+
let code = '';
|
|
45
|
+
for (const file of files) {
|
|
46
|
+
const { url } = file;
|
|
47
|
+
code += `${handleType(type, file, url)}/n`;
|
|
48
|
+
}
|
|
49
|
+
// 替换选中区域
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
editor.editor.doc.replaceSelection(code);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
input.click();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 上传文件的逻辑,如果有callback,则不再走默认的替换文本的逻辑,而是调用callback
|
|
59
|
+
* @param {string} type 上传文件的类型
|
|
60
|
+
*/
|
|
61
|
+
export function handleUpload(editor, type = 'image', accept = '*', callback = null) {
|
|
62
|
+
// type为上传文件类型 image|video|audio|pdf|word
|
|
63
|
+
const input = document.createElement('input');
|
|
64
|
+
input.type = 'file';
|
|
65
|
+
input.id = 'fileUpload';
|
|
66
|
+
input.value = '';
|
|
67
|
+
input.style.display = 'none';
|
|
68
|
+
input.accept = accept;
|
|
69
|
+
// document.body.appendChild(input);
|
|
70
|
+
input.addEventListener('change', (event) => {
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
const [file] = event.target.files;
|
|
73
|
+
// 文件上传后的回调函数可以由调用方自己实现
|
|
74
|
+
editor.$cherry.options.callback.fileUpload(file, (url, params = {}) => {
|
|
75
|
+
// 文件上传的默认回调行数,调用方可以完全不使用该函数
|
|
76
|
+
if (typeof url !== 'string' || !url) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (callback) {
|
|
80
|
+
return callback(file.name, url, params);
|
|
81
|
+
}
|
|
82
|
+
let code = '';
|
|
83
|
+
code = handleType(type, file, url);
|
|
84
|
+
// 替换选中区域
|
|
85
|
+
// @ts-ignore
|
|
86
|
+
editor.editor.doc.replaceSelection(code);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
input.click();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 处理要插入的代码
|
|
94
|
+
* @param type 文件类型
|
|
95
|
+
* @param file 文件
|
|
96
|
+
* @param url 路径
|
|
97
|
+
* @returns string
|
|
98
|
+
*/
|
|
99
|
+
const handleType = (type, file, url) => {
|
|
100
|
+
if (type === 'image') {
|
|
101
|
+
// 如果是图片,则返回固定的图片markdown源码
|
|
102
|
+
return ``;
|
|
103
|
+
}
|
|
104
|
+
if (type === 'video') {
|
|
105
|
+
// 如果是视频,则返回固定的视频markdown源码
|
|
106
|
+
return `!video[${file.name}](${url})`;
|
|
107
|
+
}
|
|
108
|
+
if (type === 'audio') {
|
|
109
|
+
// 如果是音频,则返回固定的音频markdown源码
|
|
110
|
+
return `!audio[${file.name}](${url})`;
|
|
111
|
+
}
|
|
112
|
+
// 默认返回超链接
|
|
113
|
+
return `[${file.name}](${url})`;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 解析params参数
|
|
118
|
+
* @param params?.isBorder 是否有边框样式(图片场景下生效)
|
|
119
|
+
* @param params?.isShadow 是否有阴影样式(图片场景下生效)
|
|
120
|
+
* @param params?.isRadius 是否有圆角样式(图片场景下生效)
|
|
121
|
+
* @param params?.width 设置宽度,可以是像素、也可以是百分比(图片、视频场景下生效)
|
|
122
|
+
* @param params?.height 设置高度,可以是像素、也可以是百分比(图片、视频场景下生效)
|
|
123
|
+
*/
|
|
124
|
+
export function handleParams(params) {
|
|
125
|
+
const ret = [];
|
|
126
|
+
if (params?.isBorder) {
|
|
127
|
+
ret.push('#B');
|
|
128
|
+
}
|
|
129
|
+
if (params?.isShadow) {
|
|
130
|
+
ret.push('#S');
|
|
131
|
+
}
|
|
132
|
+
if (params?.isRadius) {
|
|
133
|
+
ret.push('#R');
|
|
134
|
+
}
|
|
135
|
+
if (params?.width) {
|
|
136
|
+
ret.push(`#${params.width}`);
|
|
137
|
+
}
|
|
138
|
+
if (params?.height) {
|
|
139
|
+
if (!params.width) {
|
|
140
|
+
ret.push('#auto');
|
|
141
|
+
}
|
|
142
|
+
ret.push(`#${params.height}`);
|
|
143
|
+
}
|
|
144
|
+
return ret.join(' ');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function handleFileUploadCallback(url, params, file) {
|
|
148
|
+
const name = params?.name ?? file.name;
|
|
149
|
+
let type = '';
|
|
150
|
+
let poster = '';
|
|
151
|
+
if (/video/i.test(file.type)) {
|
|
152
|
+
type = '!video';
|
|
153
|
+
poster = params?.poster ? `{poster=${params.poster}}` : '';
|
|
154
|
+
}
|
|
155
|
+
if (/audio/i.test(file.type)) {
|
|
156
|
+
type = '!audio';
|
|
157
|
+
}
|
|
158
|
+
if (/image/i.test(file.type)) {
|
|
159
|
+
type = '!';
|
|
160
|
+
}
|
|
161
|
+
const style = type ? handleParams(params) : '';
|
|
162
|
+
const { before = '', after = '' } = params;
|
|
163
|
+
return `${before}${type}[${name}${style}](${url})${poster}${after}`;
|
|
164
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
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
|
+
|
|
17
|
+
import { svg2img, getSvgString } from '@/utils/svgUtils';
|
|
18
|
+
import { copyTextByClipboard } from '@/utils/copy';
|
|
19
|
+
import MathBlock from '@/core/hooks/MathBlock';
|
|
20
|
+
|
|
21
|
+
export default class FormulaHandler {
|
|
22
|
+
/** @type{HTMLElement} */
|
|
23
|
+
bubbleContainer = null;
|
|
24
|
+
/**
|
|
25
|
+
* @param {string} trigger 触发方式
|
|
26
|
+
* @param {Element} target 目标dom
|
|
27
|
+
* @param {HTMLDivElement} container bubble容器
|
|
28
|
+
* @param {HTMLDivElement} previewerDom 预览器dom
|
|
29
|
+
* @param {import('../Editor').default} editor 编辑器实例
|
|
30
|
+
*/
|
|
31
|
+
constructor(trigger, target, container, previewerDom, editor) {
|
|
32
|
+
this.trigger = trigger;
|
|
33
|
+
this.target = target;
|
|
34
|
+
this.container = container;
|
|
35
|
+
this.previewerDom = previewerDom;
|
|
36
|
+
this.editor = editor;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 触发事件
|
|
41
|
+
* @param {string} type 事件类型
|
|
42
|
+
* @param {Event} event 事件对象
|
|
43
|
+
*/
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
emit(type, event) {
|
|
46
|
+
switch (type) {
|
|
47
|
+
case 'remove':
|
|
48
|
+
case 'scroll':
|
|
49
|
+
return this.remove();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 绘制公式操作bubble容器
|
|
55
|
+
*/
|
|
56
|
+
drawBubble() {
|
|
57
|
+
const bubbleContainer = document.createElement('div');
|
|
58
|
+
bubbleContainer.innerHTML = `<div class="formula-utils-btn formula-utils-img">
|
|
59
|
+
<button>输出图片</button>
|
|
60
|
+
<div class="formula-utils-submenu formula-utils-img-submenu">
|
|
61
|
+
<div class="formula-utils-submenu-btn formula-utils-img-svg">
|
|
62
|
+
<button data-name="svg">svg</button>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="formula-utils-submenu-btn formula-utils-img-png">
|
|
65
|
+
<button data-name="png">png</button>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="formula-utils-submenu-btn formula-utils-img-jpg">
|
|
68
|
+
<button data-name="jpg">jpg</button>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
<div class="formula-utils-btn formula-utils-code">
|
|
73
|
+
<button>输出代码</button>
|
|
74
|
+
<div class="formula-utils-submenu formula-utils-code-submenu">
|
|
75
|
+
<div class="formula-utils-submenu-btn formula-utils-code-latex">
|
|
76
|
+
<button data-name="latex">latex</button>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="formula-utils-submenu-btn formula-utils-code-html">
|
|
79
|
+
<button data-name="html">html</button>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="formula-utils-submenu-btn formula-utils-code-svgcode">
|
|
82
|
+
<button data-name="svgcode">svgcode</button>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="formula-utils-btn formula-utils-word">
|
|
87
|
+
<button>输出mathml</button>
|
|
88
|
+
<div class="formula-utils-submenu formula-utils-word-submenu">
|
|
89
|
+
<div class="formula-utils-submenu-btn formula-utils-word-mathml">
|
|
90
|
+
<button data-name="mathml">mathml</button>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="formula-utils-btn formula-utils-transfer">
|
|
95
|
+
<button>转义</button>
|
|
96
|
+
<div class="formula-utils-submenu formula-utils-transfer-submenu">
|
|
97
|
+
<div class="formula-utils-submenu-btn formula-utils-transfer-backslash">
|
|
98
|
+
<button data-name="\\">反斜杠</button>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="formula-utils-submenu-btn formula-utils-transfer-dollar">
|
|
101
|
+
<button data-name="$">$包裹</button>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="formula-utils-submenu-btn formula-utils-transfer-double-dollar">
|
|
104
|
+
<button data-name="$$">$$包裹</button>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>`;
|
|
108
|
+
bubbleContainer.id = 'formula-utils-bubble-container'; // 方便 namedItem 获取
|
|
109
|
+
bubbleContainer.className = ['formula-utils-bubble-container'].join(' ');
|
|
110
|
+
this.bubbleContainer = bubbleContainer;
|
|
111
|
+
this?.editor?.$cherry?.wrapperDom?.appendChild(bubbleContainer);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 显示bubble
|
|
116
|
+
* @param {number} x
|
|
117
|
+
* @param {number} y
|
|
118
|
+
*/
|
|
119
|
+
showBubble(x, y) {
|
|
120
|
+
const bubbleContainer = this?.editor?.$cherry?.wrapperDom?.children?.namedItem('formula-utils-bubble-container');
|
|
121
|
+
const targetRect = this.target.getBoundingClientRect();
|
|
122
|
+
if (bubbleContainer instanceof HTMLElement) {
|
|
123
|
+
this.bubbleContainer = bubbleContainer;
|
|
124
|
+
} else {
|
|
125
|
+
this.drawBubble();
|
|
126
|
+
}
|
|
127
|
+
this.bubbleContainer.style.display = 'flex';
|
|
128
|
+
this.bubbleContainer.style.top = `${y || targetRect.top}px`;
|
|
129
|
+
this.bubbleContainer.style.left = `${x || targetRect.left}px`;
|
|
130
|
+
this.bubbleContainer.addEventListener('click', this.bubbleClickHandler.bind(this), { once: true });
|
|
131
|
+
this.collectFormulaCode();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
collectFormulaCode() {
|
|
135
|
+
const formulaCode = [];
|
|
136
|
+
// @ts-ignore
|
|
137
|
+
this.editor.editor.getValue().replace(/(\$+)\s*([\w\W]*?)\s*(\1)/g, (whole, start, content, end, offset) => {
|
|
138
|
+
formulaCode.push({
|
|
139
|
+
code: content,
|
|
140
|
+
offset,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
this.formulaCode = formulaCode;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
remove() {
|
|
147
|
+
if (this.bubbleContainer) {
|
|
148
|
+
this.bubbleContainer.style.display = 'none';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* bubble 上的点击事件
|
|
154
|
+
* @param {Event} e
|
|
155
|
+
*/
|
|
156
|
+
bubbleClickHandler(e) {
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
e.stopPropagation();
|
|
159
|
+
const { target } = e;
|
|
160
|
+
if (target instanceof HTMLButtonElement) {
|
|
161
|
+
const { name = '' } = target.dataset;
|
|
162
|
+
switch (name) {
|
|
163
|
+
case 'svg':
|
|
164
|
+
case 'png':
|
|
165
|
+
case 'jpg':
|
|
166
|
+
// 涉及到图片的操作
|
|
167
|
+
if (this.target instanceof SVGSVGElement) {
|
|
168
|
+
svg2img(this.target, { format: name });
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
case 'html':
|
|
172
|
+
case 'svgcode':
|
|
173
|
+
// 涉及到代码的操作
|
|
174
|
+
if (this.target instanceof SVGSVGElement) {
|
|
175
|
+
if (name === 'svgcode') {
|
|
176
|
+
copyTextByClipboard(getSvgString(this.target));
|
|
177
|
+
} else {
|
|
178
|
+
const mathElement = this.target.parentElement.querySelector('math');
|
|
179
|
+
mathElement.setAttribute('xmlns', 'http://www.w3.org/1998/Math/MathML');
|
|
180
|
+
copyTextByClipboard(mathElement.outerHTML);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
case '\\':
|
|
185
|
+
case '$':
|
|
186
|
+
case '$$':
|
|
187
|
+
case 'latex':
|
|
188
|
+
case 'mathml':
|
|
189
|
+
case 'docx':
|
|
190
|
+
// 涉及到公式API的操作
|
|
191
|
+
{
|
|
192
|
+
const allMjx = this.previewerDom.querySelectorAll('mjx-container');
|
|
193
|
+
let mjxIndex = -1;
|
|
194
|
+
allMjx.forEach((mjx, index) => {
|
|
195
|
+
if (mjx === this.target.parentElement) {
|
|
196
|
+
mjxIndex = index;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
if (mjxIndex >= 0 && this.formulaCode[mjxIndex]) {
|
|
200
|
+
const { code } = this.formulaCode[mjxIndex];
|
|
201
|
+
if (name === 'mathml' || name === 'docx') {
|
|
202
|
+
/** @type {MathBlock} */
|
|
203
|
+
// @ts-ignore
|
|
204
|
+
const hook = this.editor.$cherry.engine.hooks.paragraph.find((hook) => hook instanceof MathBlock);
|
|
205
|
+
if (hook && hook.engine === 'MathJax') {
|
|
206
|
+
window.MathJax?.texReset();
|
|
207
|
+
window.MathJax?.tex2mmlPromise?.(code, { display: true }).then((mml) => {
|
|
208
|
+
if (name === 'mathml') {
|
|
209
|
+
copyTextByClipboard(mml);
|
|
210
|
+
} else {
|
|
211
|
+
// TODO: docx
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
// TODO: other engine
|
|
216
|
+
} else if (name === 'latex') {
|
|
217
|
+
copyTextByClipboard(code);
|
|
218
|
+
} else if (name === '$') {
|
|
219
|
+
copyTextByClipboard(`${name}${code}${name}`);
|
|
220
|
+
} else if (name === '$$') {
|
|
221
|
+
copyTextByClipboard(`${name}\n${code}\n${name}`);
|
|
222
|
+
} else if (name === '\\') {
|
|
223
|
+
copyTextByClipboard(`\\${code}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
this.remove();
|
|
231
|
+
}
|
|
232
|
+
}
|