@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,52 @@
|
|
|
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 ParagraphBase from '@/core/ParagraphBase';
|
|
17
|
+
import { prependLineFeedForParagraph } from '@/utils/lineFeed';
|
|
18
|
+
/**
|
|
19
|
+
* 分割线语法
|
|
20
|
+
*/
|
|
21
|
+
export default class Hr extends ParagraphBase {
|
|
22
|
+
static HOOK_NAME = 'hr';
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
super({ needCache: true });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
beforeMakeHtml(str) {
|
|
29
|
+
return str.replace(this.RULE.reg, (match, preLines) => {
|
|
30
|
+
const lineCount = (preLines.match(/\n/g) || []).length + 1;
|
|
31
|
+
// 计算签名,签名可能会重复,符合预期
|
|
32
|
+
const sign = `hr${lineCount}`;
|
|
33
|
+
const placeHolder = this.pushCache(`<hr data-sign="${sign}" data-lines="${lineCount}" />`, sign);
|
|
34
|
+
return prependLineFeedForParagraph(match, placeHolder);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
39
|
+
return str;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
rule() {
|
|
43
|
+
// 分割线必须有从新行开始,比如以换行结束
|
|
44
|
+
const ret = {
|
|
45
|
+
begin: '(?:^|\\n)(\\n*)[ ]*',
|
|
46
|
+
end: '(?=$|\\n)',
|
|
47
|
+
content: '((?:-[ \\t]*){3,}|(?:\\*[ \\t]*){3,}|(?:_[ \\t]*){3,})',
|
|
48
|
+
};
|
|
49
|
+
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
|
|
50
|
+
return ret;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
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 ParagraphBase from '@/core/ParagraphBase';
|
|
17
|
+
import {
|
|
18
|
+
whiteList,
|
|
19
|
+
convertHTMLNumberToName,
|
|
20
|
+
// isValidScheme, encodeURIOnce,
|
|
21
|
+
escapeHTMLEntitiesWithoutSemicolon,
|
|
22
|
+
} from '@/utils/sanitize';
|
|
23
|
+
import { sanitizer } from '@/Sanitizer';
|
|
24
|
+
import { isBrowser } from '@/utils/env';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* encode unsafe link-related attributes
|
|
28
|
+
*/
|
|
29
|
+
const unsafeAttributes = ['href', 'src'];
|
|
30
|
+
|
|
31
|
+
sanitizer.addHook('afterSanitizeAttributes', (node) => {
|
|
32
|
+
unsafeAttributes.forEach((attr) => {
|
|
33
|
+
if (!node.hasAttribute(attr)) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const value = node.getAttribute(attr);
|
|
37
|
+
// encode unsafe backslash in link attributes
|
|
38
|
+
node.setAttribute(attr, value.replace(/\\/g, '%5c'));
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export default class HtmlBlock extends ParagraphBase {
|
|
43
|
+
static HOOK_NAME = 'htmlBlock';
|
|
44
|
+
constructor({ config }) {
|
|
45
|
+
super({ needCache: true });
|
|
46
|
+
this.filterStyle = config.filterStyle || false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ref: http://www.vfmd.org/vfmd-spec/specification/#procedure-for-detecting-automatic-links
|
|
50
|
+
isAutoLinkTag(tagMatch) {
|
|
51
|
+
const REGEX_GROUP = [
|
|
52
|
+
/^<([a-z][a-z0-9+.-]{1,31}:\/\/[^<> `]+)>$/i,
|
|
53
|
+
/^<(mailto:[^<> `]+)>$/i,
|
|
54
|
+
/^<([^()<>[\]:'@\\,"\s`]+@[^()<>[\]:'@\\,"\s`.]+\.[^()<>[\]:'@\\,"\s`]+)>$/i,
|
|
55
|
+
];
|
|
56
|
+
return REGEX_GROUP.some((regex) => regex.test(tagMatch));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
isHtmlComment(match) {
|
|
60
|
+
const htmlComment = /^<!--.*?-->$/;
|
|
61
|
+
return htmlComment.test(match);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
beforeMakeHtml(str, sentenceMakeFunc) {
|
|
65
|
+
if (this.$engine.htmlWhiteListAppend) {
|
|
66
|
+
/**
|
|
67
|
+
* @property
|
|
68
|
+
* @type {false | RegExp}
|
|
69
|
+
*/
|
|
70
|
+
this.htmlWhiteListAppend = new RegExp(`^(${this.$engine.htmlWhiteListAppend})( |$|/)`, 'i');
|
|
71
|
+
/**
|
|
72
|
+
* @property
|
|
73
|
+
* @type {string[]}
|
|
74
|
+
*/
|
|
75
|
+
this.htmlWhiteList = this.$engine.htmlWhiteListAppend.split('|');
|
|
76
|
+
} else {
|
|
77
|
+
this.htmlWhiteListAppend = false;
|
|
78
|
+
this.htmlWhiteList = [];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let $str = str;
|
|
82
|
+
$str = convertHTMLNumberToName($str);
|
|
83
|
+
$str = escapeHTMLEntitiesWithoutSemicolon($str);
|
|
84
|
+
$str = $str.replace(/<[/]?([^<]*?)>/g, (whole, m1) => {
|
|
85
|
+
// 匹配到非白名单且非AutoLink语法的尖括号会被转义
|
|
86
|
+
// 如果是HTML注释,放行
|
|
87
|
+
if (!whiteList.test(m1) && !this.isAutoLinkTag(whole) && !this.isHtmlComment(whole)) {
|
|
88
|
+
if (this.htmlWhiteListAppend === false || !this.htmlWhiteListAppend.test(m1)) {
|
|
89
|
+
return whole.replace(/</g, '<').replace(/>/g, '>');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
let wholeStr = whole;
|
|
93
|
+
// 识别<a>和<img>标签的href和src属性,并触发urlProcessor回调
|
|
94
|
+
m1.replace(/^a .*? href="([^"]+)"/, (all, href) => {
|
|
95
|
+
const processedURL = this.$engine.urlProcessor(href, 'link');
|
|
96
|
+
wholeStr = wholeStr.replace(/ href="[^"]+"/, ` href="${processedURL}"`);
|
|
97
|
+
});
|
|
98
|
+
m1.replace(/^a href="([^"]+)"/, (all, href) => {
|
|
99
|
+
const processedURL = this.$engine.urlProcessor(href, 'link');
|
|
100
|
+
wholeStr = wholeStr.replace(/ href="[^"]+"/, ` href="${processedURL}"`);
|
|
101
|
+
});
|
|
102
|
+
m1.replace(/^img .*? src="([^"]+)"/, (all, src) => {
|
|
103
|
+
const processedURL = this.$engine.urlProcessor(src, 'image');
|
|
104
|
+
wholeStr = wholeStr.replace(/ src="[^"]+"/, ` src="${processedURL}"`);
|
|
105
|
+
});
|
|
106
|
+
m1.replace(/^img src="([^"]+)"/, (all, src) => {
|
|
107
|
+
const processedURL = this.$engine.urlProcessor(src, 'image');
|
|
108
|
+
wholeStr = wholeStr.replace(/ src="[^"]+"/, ` src="${processedURL}"`);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// 到达此分支的包含被尖括号包裹的AutoLink语法以及在白名单内的HTML标签
|
|
112
|
+
// 没有被AutoLink解析并渲染的标签会被DOMPurify过滤掉,正常情况下不会出现遗漏
|
|
113
|
+
// 临时替换完整的HTML标签首尾为$#60;和$#62;,供下一步剔除损坏的HTML标签
|
|
114
|
+
return wholeStr.replace(/</g, '$#60;').replace(/>/g, '$#62;');
|
|
115
|
+
});
|
|
116
|
+
// 替换所有形如「<abcd」和「</abcd」的左尖括号
|
|
117
|
+
$str = $str.replace(/<(?=\/?(\w|\n|$))/g, '<');
|
|
118
|
+
// 还原被替换的尖括号
|
|
119
|
+
$str = $str.replace(/\$#60;/g, '<').replace(/\$#62;/g, '>');
|
|
120
|
+
// 过滤HTML标签的style属性
|
|
121
|
+
if (this.filterStyle) {
|
|
122
|
+
$str = $str.replace(/<([^/][^>]+?) style="[^>\n]+?"([^>\n]*)>/gi, '<$1$2>');
|
|
123
|
+
$str = $str.replace(/<([^/][^>]+?) style='[^>\n]+?'([^>\n]*)>/gi, '<$1$2>');
|
|
124
|
+
}
|
|
125
|
+
return $str;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// beforeMakeHtml(str) {
|
|
129
|
+
// return str;
|
|
130
|
+
// }
|
|
131
|
+
|
|
132
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
133
|
+
return str;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
afterMakeHtml(str) {
|
|
137
|
+
let $str = str;
|
|
138
|
+
const config = {
|
|
139
|
+
ALLOW_UNKNOWN_PROTOCOLS: true,
|
|
140
|
+
ADD_ATTR: ['target'],
|
|
141
|
+
};
|
|
142
|
+
if (this.htmlWhiteListAppend !== false) {
|
|
143
|
+
config.ADD_TAGS = this.htmlWhiteList;
|
|
144
|
+
if (this.htmlWhiteListAppend.test('style') || this.htmlWhiteListAppend.test('ALL')) {
|
|
145
|
+
$str = $str.replace(/<style(>| [^>]*>).*?<\/style>/gi, (match) => {
|
|
146
|
+
return match.replace(/<br>/gi, '');
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (this.htmlWhiteListAppend.test('iframe') || this.htmlWhiteListAppend.test('ALL')) {
|
|
150
|
+
config.ADD_ATTR = config.ADD_ATTR.concat([
|
|
151
|
+
'align',
|
|
152
|
+
'frameborder',
|
|
153
|
+
'height',
|
|
154
|
+
'longdesc',
|
|
155
|
+
'marginheight',
|
|
156
|
+
'marginwidth',
|
|
157
|
+
'name',
|
|
158
|
+
'sandbox',
|
|
159
|
+
'scrolling',
|
|
160
|
+
'seamless',
|
|
161
|
+
'src',
|
|
162
|
+
'srcdoc',
|
|
163
|
+
'width',
|
|
164
|
+
]);
|
|
165
|
+
config.SANITIZE_DOM = false;
|
|
166
|
+
$str = $str.replace(/<iframe(>| [^>]*>).*?<\/iframe>/gi, (match) => {
|
|
167
|
+
return match.replace(/<br>/gi, '').replace(/\n/g, '');
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
if (this.htmlWhiteListAppend.test('script') || this.htmlWhiteListAppend.test('ALL')) {
|
|
171
|
+
// 如果允许script或者输入了ALL,则不做任何过滤了
|
|
172
|
+
$str = $str.replace(/<script(>| [^>]*>).*?<\/script>/gi, (match) => {
|
|
173
|
+
return match.replace(/<br>/gi, '');
|
|
174
|
+
});
|
|
175
|
+
return $str;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// node 环境下不输出sign和lines
|
|
179
|
+
if (!isBrowser()) {
|
|
180
|
+
config.FORBID_ATTR = ['data-sign', 'data-lines'];
|
|
181
|
+
}
|
|
182
|
+
return sanitizer.sanitize($str, config);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
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 SyntaxBase from '@/core/SyntaxBase';
|
|
17
|
+
import { escapeHTMLSpecialCharOnce as $e, encodeURIOnce } from '@/utils/sanitize';
|
|
18
|
+
import imgAltHelper from '@/utils/image';
|
|
19
|
+
import { compileRegExp, isLookbehindSupported, NOT_ALL_WHITE_SPACES_INLINE } from '@/utils/regexp';
|
|
20
|
+
import { replaceLookbehind } from '@/utils/lookbehind-replace';
|
|
21
|
+
import UrlCache from '@/UrlCache';
|
|
22
|
+
|
|
23
|
+
export default class Image extends SyntaxBase {
|
|
24
|
+
static HOOK_NAME = 'image';
|
|
25
|
+
|
|
26
|
+
constructor({ config, globalConfig }) {
|
|
27
|
+
super(null);
|
|
28
|
+
this.config = config;
|
|
29
|
+
// TODO: URL Validator
|
|
30
|
+
this.extendMedia = { tag: ['video', 'audio'] };
|
|
31
|
+
this.RULE = this.rule(this.extendMedia);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
replaceToHtml(type, match, leadingChar, alt, link, title, poster) {
|
|
35
|
+
const refType = typeof link === 'undefined' ? 'ref' : 'url';
|
|
36
|
+
let attrs = '';
|
|
37
|
+
if (refType === 'ref') {
|
|
38
|
+
// TODO: 全局引用
|
|
39
|
+
return match;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (refType === 'url') {
|
|
43
|
+
const extent = imgAltHelper.processExtendAttributesInAlt(alt);
|
|
44
|
+
let { extendStyles: style, extendClasses: classes } = imgAltHelper.processExtendStyleInAlt(alt);
|
|
45
|
+
if (style) {
|
|
46
|
+
style = ` style="${style}" `;
|
|
47
|
+
}
|
|
48
|
+
if (classes) {
|
|
49
|
+
classes = ` class="${classes}" `;
|
|
50
|
+
}
|
|
51
|
+
attrs = title && title.trim() !== '' ? ` title="${$e(title)}"` : '';
|
|
52
|
+
if (poster) {
|
|
53
|
+
attrs += ` poster="${encodeURIOnce(poster)}"`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const processedURL = this.$engine.urlProcessor(link, type);
|
|
57
|
+
const defaultWrapper = `<${type} src="${UrlCache.set(
|
|
58
|
+
encodeURIOnce(processedURL),
|
|
59
|
+
)}"${attrs} ${extent} ${style} ${classes} controls="controls">${$e(alt || '')}</${type}>`;
|
|
60
|
+
return `${leadingChar}${
|
|
61
|
+
this.config.videoWrapper ? this.config.videoWrapper(link, type, defaultWrapper) : defaultWrapper
|
|
62
|
+
}`;
|
|
63
|
+
}
|
|
64
|
+
// should never happen
|
|
65
|
+
return match;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
toHtml(match, leadingChar, alt, link, title, ref, extendAttrs) {
|
|
69
|
+
// console.log(match, alt, link, ref, title);
|
|
70
|
+
const refType = typeof link === 'undefined' ? 'ref' : 'url';
|
|
71
|
+
let attrs = '';
|
|
72
|
+
if (refType === 'ref') {
|
|
73
|
+
// 全局引用,理应在CommentReference中被替换,没有被替换说明没有定义引用项
|
|
74
|
+
return match;
|
|
75
|
+
}
|
|
76
|
+
if (refType === 'url') {
|
|
77
|
+
const extent = imgAltHelper.processExtendAttributesInAlt(alt);
|
|
78
|
+
let { extendStyles: style, extendClasses: classes } = imgAltHelper.processExtendStyleInAlt(alt);
|
|
79
|
+
if (style) {
|
|
80
|
+
style = ` style="${style}" `;
|
|
81
|
+
}
|
|
82
|
+
if (classes) {
|
|
83
|
+
classes = ` class="${classes}" `;
|
|
84
|
+
}
|
|
85
|
+
attrs = title && title.trim() !== '' ? ` title="${$e(title.replace(/["']/g, ''))}"` : '';
|
|
86
|
+
let srcProp = 'src';
|
|
87
|
+
let srcValue;
|
|
88
|
+
const cherryOptions = this.$engine.$cherry.options;
|
|
89
|
+
if (cherryOptions.callback && cherryOptions.callback.beforeImageMounted) {
|
|
90
|
+
const imgAttrs = cherryOptions.callback.beforeImageMounted(srcProp, link);
|
|
91
|
+
srcProp = imgAttrs.srcProp || srcProp;
|
|
92
|
+
srcValue = imgAttrs.src || link;
|
|
93
|
+
}
|
|
94
|
+
const extendAttrStr = extendAttrs
|
|
95
|
+
? extendAttrs
|
|
96
|
+
.replace(/[{}]/g, '')
|
|
97
|
+
.replace(/([^=\s]+)=([^\s]+)/g, '$1="$2"')
|
|
98
|
+
.replace(/&/g, '&') // 对&多做一次转义,cherry现有的机制会自动把&转成&,只有多做一次转义才能抵消cherry的机制
|
|
99
|
+
: '';
|
|
100
|
+
return `${leadingChar}<img ${srcProp}="${UrlCache.set(
|
|
101
|
+
encodeURIOnce(this.$engine.urlProcessor(srcValue, 'image')),
|
|
102
|
+
)}" ${extent} ${style} ${classes} alt="${$e(alt || '')}"${attrs} ${extendAttrStr}/>`;
|
|
103
|
+
}
|
|
104
|
+
// should never happen
|
|
105
|
+
return match;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
toMediaHtml(match, leadingChar, mediaType, alt, link, title, ref, posterWrap, poster, ...args) {
|
|
109
|
+
if (!/(video|audio)/.test(mediaType)) {
|
|
110
|
+
return match;
|
|
111
|
+
}
|
|
112
|
+
return this.replaceToHtml(mediaType, match, leadingChar, alt, link, title, poster);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
makeHtml(str) {
|
|
116
|
+
let $str = str;
|
|
117
|
+
if (this.test($str)) {
|
|
118
|
+
if (isLookbehindSupported()) {
|
|
119
|
+
$str = $str.replace(this.RULE.reg, this.toHtml.bind(this));
|
|
120
|
+
} else {
|
|
121
|
+
$str = replaceLookbehind($str, this.RULE.reg, this.toHtml.bind(this), true, 1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (this.testMedia($str)) {
|
|
125
|
+
if (isLookbehindSupported()) {
|
|
126
|
+
$str = $str.replace(this.RULE.regExtend, this.toMediaHtml.bind(this));
|
|
127
|
+
} else {
|
|
128
|
+
$str = replaceLookbehind($str, this.RULE.regExtend, this.toMediaHtml.bind(this), true, 1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return $str;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// afterMakeHtml(str) {
|
|
135
|
+
// return UrlCache.restoreAll(str);
|
|
136
|
+
// }
|
|
137
|
+
|
|
138
|
+
testMedia(str) {
|
|
139
|
+
return this.RULE.regExtend && this.RULE.regExtend.test(str);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
rule(extendMedia) {
|
|
143
|
+
const ret = {
|
|
144
|
+
// lookbehind启用分组是为了和不兼容lookbehind的场景共用一个回调
|
|
145
|
+
begin: isLookbehindSupported() ? '((?<!\\\\))!' : '(^|[^\\\\])!',
|
|
146
|
+
content: [
|
|
147
|
+
'\\[([^\\n]*?)\\]', // ?<alt>
|
|
148
|
+
'[ \\t]*', // any spaces
|
|
149
|
+
`${
|
|
150
|
+
'(?:' +
|
|
151
|
+
'\\(' +
|
|
152
|
+
'((?:[^\\s()]*\\([^\\s()]*\\)[^\\s()]*)+|(?:[^"][^\\s]+?))' + // ?<link> url
|
|
153
|
+
'(?:[ \\t]((?:".*?")|(?:\'.*?\')))?' + // ?<title> optional
|
|
154
|
+
'\\)' +
|
|
155
|
+
'|' + // or
|
|
156
|
+
'\\[('
|
|
157
|
+
}${NOT_ALL_WHITE_SPACES_INLINE})\\]` + // ?<ref> global ref
|
|
158
|
+
')',
|
|
159
|
+
].join(''),
|
|
160
|
+
end: '({[^{}]+?})?', // extend attrs e.g. {width=50 height=60}
|
|
161
|
+
};
|
|
162
|
+
if (extendMedia) {
|
|
163
|
+
const extend = { ...ret };
|
|
164
|
+
// TODO: 支持Lookbehind
|
|
165
|
+
extend.begin = isLookbehindSupported()
|
|
166
|
+
? `((?<!\\\\))!(${extendMedia.tag.join('|')})`
|
|
167
|
+
: `(^|[^\\\\])!(${extendMedia.tag.join('|')})`;
|
|
168
|
+
extend.end = '({poster=(.*)})?';
|
|
169
|
+
ret.regExtend = compileRegExp(extend, 'g');
|
|
170
|
+
}
|
|
171
|
+
ret.reg = compileRegExp(ret, 'g');
|
|
172
|
+
return ret;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
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 ParagraphBase from '@/core/ParagraphBase';
|
|
17
|
+
import CodeBlock from './CodeBlock';
|
|
18
|
+
import { compileRegExp } from '@/utils/regexp';
|
|
19
|
+
|
|
20
|
+
export default class InlineCode extends ParagraphBase {
|
|
21
|
+
static HOOK_NAME = 'inlineCode';
|
|
22
|
+
|
|
23
|
+
// constructor() {
|
|
24
|
+
// super();
|
|
25
|
+
// }
|
|
26
|
+
|
|
27
|
+
makeHtml(str) {
|
|
28
|
+
return str;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
afterMakeHtml(str) {
|
|
32
|
+
let $str = str;
|
|
33
|
+
if (Object.keys(CodeBlock.inlineCodeCache).length > 0) {
|
|
34
|
+
$str = $str.replace(/~~CODE([0-9a-zA-Z]+)\$/g, (match, sign) => CodeBlock.inlineCodeCache[sign]);
|
|
35
|
+
}
|
|
36
|
+
return $str;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
$cleanCache() {
|
|
40
|
+
CodeBlock.inlineCodeCache = {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
rule() {
|
|
44
|
+
const ret = { begin: '(`+)[ ]*', end: '[ ]*\\1', content: '(.+?(?:\\n.+?)*?)' };
|
|
45
|
+
ret.reg = compileRegExp(ret, 'g');
|
|
46
|
+
return ret;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
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 ParagraphBase from '@/core/ParagraphBase';
|
|
17
|
+
import { escapeFormulaPunctuations, LoadMathModule } from '@/utils/mathjax';
|
|
18
|
+
import { getHTML } from '@/utils/dom';
|
|
19
|
+
import { isBrowser } from '@/utils/env';
|
|
20
|
+
import { getTableRule, isLookbehindSupported } from '@/utils/regexp';
|
|
21
|
+
import { replaceLookbehind } from '@/utils/lookbehind-replace';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 行内公式的语法
|
|
25
|
+
* 虽然叫做行内公式,Cherry依然将其视为“段落级语法”,因为其具备排他性并且需要优先渲染
|
|
26
|
+
*/
|
|
27
|
+
export default class InlineMath extends ParagraphBase {
|
|
28
|
+
static HOOK_NAME = 'inlineMath';
|
|
29
|
+
/** @type {'katex' | 'MathJax' | 'node'} */
|
|
30
|
+
engine = 'MathJax'; // 渲染引擎,默认为MathJax,MathJax支持2.x与3.x版本
|
|
31
|
+
katex;
|
|
32
|
+
MathJax;
|
|
33
|
+
|
|
34
|
+
constructor({ config }) {
|
|
35
|
+
super({ needCache: true });
|
|
36
|
+
// 非浏览器环境下配置为 node
|
|
37
|
+
this.engine = isBrowser() ? config.engine ?? 'MathJax' : 'node';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
toHtml(wholeMatch, leadingChar, m1) {
|
|
41
|
+
if (!m1) {
|
|
42
|
+
return wholeMatch;
|
|
43
|
+
}
|
|
44
|
+
LoadMathModule.bind(this)('engine');
|
|
45
|
+
const linesArr = m1.match(/\n/g);
|
|
46
|
+
const lines = linesArr ? linesArr.length + 2 : 2;
|
|
47
|
+
const sign = this.$engine.hash(wholeMatch);
|
|
48
|
+
// 既无MathJax又无katex时,原样输出
|
|
49
|
+
let result = '';
|
|
50
|
+
if (this.engine === 'katex' && this.katex?.renderToString) {
|
|
51
|
+
// katex渲染
|
|
52
|
+
const html = this.katex.renderToString(m1, {
|
|
53
|
+
throwOnError: false,
|
|
54
|
+
});
|
|
55
|
+
result = `${leadingChar}<span class="Cherry-InlineMath" data-type="mathBlock" data-lines="${lines}">${html}</span>`;
|
|
56
|
+
} else if (this.MathJax?.tex2svg) {
|
|
57
|
+
// MathJax渲染
|
|
58
|
+
const svg = getHTML(this.MathJax.tex2svg(m1, { em: 12, ex: 6, display: false }), true);
|
|
59
|
+
result = `${leadingChar}<span class="Cherry-InlineMath" data-type="mathBlock" data-lines="${lines}">${svg}</span>`;
|
|
60
|
+
} else {
|
|
61
|
+
result = `${leadingChar}<span class="Cherry-InlineMath" data-type="mathBlock"
|
|
62
|
+
data-lines="${lines}">$${escapeFormulaPunctuations(m1)}$</span>`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return this.pushCache(result, ParagraphBase.IN_PARAGRAPH_CACHE_KEY_PREFIX + sign);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
beforeMakeHtml(str) {
|
|
69
|
+
let $str = str;
|
|
70
|
+
// 格里处理行内公式,让一个td里的行内公式语法生效,让跨td的行内公式语法失效
|
|
71
|
+
$str = $str.replace(getTableRule(true), (whole, ...args) => {
|
|
72
|
+
return whole
|
|
73
|
+
.split('|')
|
|
74
|
+
.map((oneTd) => {
|
|
75
|
+
return this.makeInlineMath(oneTd);
|
|
76
|
+
})
|
|
77
|
+
.join('|')
|
|
78
|
+
.replace(/\\~D/g, '~D') // 出现反斜杠的情况(如/$e=m^2$)会导致多一个反斜杠,这里替换掉
|
|
79
|
+
.replace(/~D/g, '\\~D');
|
|
80
|
+
});
|
|
81
|
+
return this.makeInlineMath($str);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
makeInlineMath(str) {
|
|
85
|
+
if (!this.test(str)) {
|
|
86
|
+
return str;
|
|
87
|
+
}
|
|
88
|
+
if (isLookbehindSupported()) {
|
|
89
|
+
return str.replace(this.RULE.reg, this.toHtml.bind(this));
|
|
90
|
+
}
|
|
91
|
+
return replaceLookbehind(str, this.RULE.reg, this.toHtml.bind(this), true, 1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
makeHtml(str) {
|
|
95
|
+
return str;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
rule() {
|
|
99
|
+
const ret = {
|
|
100
|
+
begin: isLookbehindSupported() ? '((?<!\\\\))~D\\n?' : '(^|[^\\\\])~D\\n?',
|
|
101
|
+
content: '(.*?)\\n?',
|
|
102
|
+
end: '~D',
|
|
103
|
+
};
|
|
104
|
+
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
|
|
105
|
+
return ret;
|
|
106
|
+
}
|
|
107
|
+
}
|