@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,119 @@
|
|
|
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 } from '@/utils/sanitize';
|
|
18
|
+
import { compileRegExp } from '@/utils/regexp';
|
|
19
|
+
import { gfmUnicode } from './Emoji.config';
|
|
20
|
+
|
|
21
|
+
// ref: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint
|
|
22
|
+
function fromCodePoint(...args) {
|
|
23
|
+
const codeUnits = [];
|
|
24
|
+
let codeLen = 0;
|
|
25
|
+
let result = '';
|
|
26
|
+
for (let index = 0, len = args.length; index !== len; ++index) {
|
|
27
|
+
let codePoint = +args[index];
|
|
28
|
+
// correctly handles all cases including `NaN`, `-Infinity`, `+Infinity`
|
|
29
|
+
// The surrounding `!(...)` is required to correctly handle `NaN` cases
|
|
30
|
+
// The (codePoint>>>0) === codePoint clause handles decimals and negatives
|
|
31
|
+
if (!(codePoint < 0x10ffff && codePoint >>> 0 === codePoint)) {
|
|
32
|
+
throw new RangeError(`Invalid code point: ${codePoint}`);
|
|
33
|
+
}
|
|
34
|
+
if (codePoint <= 0xffff) {
|
|
35
|
+
// BMP code point
|
|
36
|
+
codeLen = codeUnits.push(codePoint);
|
|
37
|
+
} else {
|
|
38
|
+
// Astral code point; split in surrogate halves
|
|
39
|
+
// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
|
40
|
+
codePoint -= 0x10000;
|
|
41
|
+
codeLen = codeUnits.push(
|
|
42
|
+
(codePoint >> 10) + 0xd800, // highSurrogate
|
|
43
|
+
(codePoint % 0x400) + 0xdc00, // lowSurrogate
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (codeLen >= 0x3fff) {
|
|
47
|
+
result += String.fromCharCode.apply(null, codeUnits);
|
|
48
|
+
codeUnits.length = 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result + String.fromCharCode.apply(null, codeUnits);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default class Emoji extends SyntaxBase {
|
|
55
|
+
static HOOK_NAME = 'emoji';
|
|
56
|
+
|
|
57
|
+
constructor({ config } = { config: undefined }) {
|
|
58
|
+
super({ config });
|
|
59
|
+
this.options = {
|
|
60
|
+
useUnicode: true,
|
|
61
|
+
upperCase: false,
|
|
62
|
+
customHandled: false,
|
|
63
|
+
resourceURL: 'https://github.githubassets.com/images/icons/emoji/unicode/${code}.png?v8',
|
|
64
|
+
emojis: { ...gfmUnicode.emojis },
|
|
65
|
+
};
|
|
66
|
+
if (typeof config !== 'object') {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const { useUnicode, customResourceURL, customRenderer, upperCase } = config;
|
|
70
|
+
this.options.useUnicode = typeof useUnicode === 'boolean' ? useUnicode : this.options.useUnicode;
|
|
71
|
+
this.options.upperCase = typeof upperCase === 'boolean' ? upperCase : this.options.upperCase;
|
|
72
|
+
if (useUnicode === false && typeof customResourceURL === 'string') {
|
|
73
|
+
this.options.resourceURL = customResourceURL;
|
|
74
|
+
}
|
|
75
|
+
if (typeof customRenderer === 'function') {
|
|
76
|
+
this.options.customHandled = true;
|
|
77
|
+
this.options.customRenderer = customRenderer;
|
|
78
|
+
}
|
|
79
|
+
// TODO: URL Validator
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
83
|
+
if (!this.test(str)) {
|
|
84
|
+
return str;
|
|
85
|
+
}
|
|
86
|
+
return str.replace(this.RULE.reg, (match, emojiKey) => {
|
|
87
|
+
// 先走自定义渲染逻辑
|
|
88
|
+
if (this.options.customHandled && typeof this.options.customRenderer === 'function') {
|
|
89
|
+
return this.options.customRenderer(emojiKey);
|
|
90
|
+
}
|
|
91
|
+
let emojiCode = this.options.emojis[emojiKey];
|
|
92
|
+
if (typeof emojiCode !== 'string') {
|
|
93
|
+
return match;
|
|
94
|
+
}
|
|
95
|
+
if (this.options.useUnicode) {
|
|
96
|
+
const codes = emojiCode.split('-').map((unicode) => `0x${unicode}`); // convert to hex string
|
|
97
|
+
return fromCodePoint(...codes);
|
|
98
|
+
}
|
|
99
|
+
if (this.options.upperCase) {
|
|
100
|
+
emojiCode = emojiCode.toUpperCase();
|
|
101
|
+
}
|
|
102
|
+
const src = this.options.resourceURL.replace(/\$\{code\}/g, emojiCode);
|
|
103
|
+
return `<img class="emoji" src="${src}" alt="${_e(emojiKey)}" />`;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
rule() {
|
|
108
|
+
// (?<protocol>\\w+:)\\/\\/
|
|
109
|
+
const ret = {
|
|
110
|
+
// ?<left>
|
|
111
|
+
begin: ':',
|
|
112
|
+
content: '([a-zA-Z0-9+_]+?)',
|
|
113
|
+
// ?<right>
|
|
114
|
+
end: ':',
|
|
115
|
+
};
|
|
116
|
+
ret.reg = compileRegExp(ret, 'g');
|
|
117
|
+
return ret;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
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 { compileRegExp, ALLOW_WHITESPACE_MULTILINE, UNDERSCORE_EMPHASIS_BOUNDARY } from '@/utils/regexp';
|
|
18
|
+
|
|
19
|
+
export default class Emphasis extends SyntaxBase {
|
|
20
|
+
static HOOK_NAME = 'fontEmphasis';
|
|
21
|
+
|
|
22
|
+
constructor({ config } = { config: undefined }) {
|
|
23
|
+
super({ config });
|
|
24
|
+
if (!config) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.allowWhitespace = !!config.allowWhitespace;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
31
|
+
const converAsterisk = function (match, leading, symbol, text) {
|
|
32
|
+
const tagType = symbol.length % 2 === 1 ? 'em' : 'strong';
|
|
33
|
+
const repeat = Math.floor(symbol.length / 2);
|
|
34
|
+
let prefix = '<strong>'.repeat(repeat);
|
|
35
|
+
let suffix = '</strong>'.repeat(repeat);
|
|
36
|
+
if (tagType === 'em') {
|
|
37
|
+
prefix += '<em>';
|
|
38
|
+
suffix = `</em>${suffix}`;
|
|
39
|
+
}
|
|
40
|
+
// 这里转义_是为了避免跨标签识别
|
|
41
|
+
const result = `${leading}${prefix}${sentenceMakeFunc(text).html.replace(/_/g, '~U')}${suffix}`;
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
let $str = str;
|
|
45
|
+
if (this.allowWhitespace) {
|
|
46
|
+
$str = $str.replace(/(^[\s]*|\n[\s]*)(\*)([^\s*](?:.*?)(?:(?:\n.*?)*?))\*/g, converAsterisk);
|
|
47
|
+
$str = $str.replace(/(^[\s]*|\n[\s]*)(\*{2,})((?:.*?)(?:(?:\n.*?)*?))\2/g, converAsterisk);
|
|
48
|
+
$str = $str.replace(/([^\n*\\\s][ ]*)(\*+)((?:.*?)(?:(?:\n.*?)*?))\2/g, converAsterisk);
|
|
49
|
+
} else {
|
|
50
|
+
// TODO: fix this error
|
|
51
|
+
// @ts-expect-error
|
|
52
|
+
$str = $str.replace(this.RULE.asterisk.reg, converAsterisk);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// TODO: fix this error
|
|
56
|
+
// @ts-expect-error
|
|
57
|
+
$str = $str.replace(this.RULE.underscore.reg, (match, leading, symbol, text, index, string) => {
|
|
58
|
+
if (text.trim() === '') {
|
|
59
|
+
return match;
|
|
60
|
+
}
|
|
61
|
+
const tagType = symbol.length % 2 === 1 ? 'em' : 'strong';
|
|
62
|
+
const repeat = Math.floor(symbol.length / 2);
|
|
63
|
+
let prefix = '<strong>'.repeat(repeat);
|
|
64
|
+
let suffix = '</strong>'.repeat(repeat);
|
|
65
|
+
const innerText = sentenceMakeFunc(text).html;
|
|
66
|
+
if (tagType === 'em') {
|
|
67
|
+
// if(/<em>.*?<\/em>/.test(innerText)) {
|
|
68
|
+
// prefix += symbol;
|
|
69
|
+
// suffix = symbol + suffix;
|
|
70
|
+
// } else {
|
|
71
|
+
prefix += '<em>';
|
|
72
|
+
suffix = `</em>${suffix}`;
|
|
73
|
+
// }
|
|
74
|
+
}
|
|
75
|
+
const result = `${leading}${prefix}${innerText}${suffix}`;
|
|
76
|
+
return result;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return $str.replace(/~U/g, '_');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
test(str, flavor) {
|
|
83
|
+
return this.RULE[flavor].reg && this.RULE[flavor].reg.test(str);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* TODO: fix type errors, prefer use `rules` for multiple spec instead
|
|
88
|
+
* @returns
|
|
89
|
+
*/
|
|
90
|
+
rule({ config } = { config: undefined }) {
|
|
91
|
+
const allowWhitespace = config ? !!config.allowWhitespace : false;
|
|
92
|
+
const emRegexp = (allowWhitespace, symbol) => {
|
|
93
|
+
const char = `[^${symbol}\\s]`;
|
|
94
|
+
return allowWhitespace ? ALLOW_WHITESPACE_MULTILINE : `(${char}|${char}(.*?(\n${char}.*)*)${char})`;
|
|
95
|
+
};
|
|
96
|
+
const asterisk = {
|
|
97
|
+
begin: '(^|[^\\\\])([*]+)', // ?<leading>, ?<symbol>
|
|
98
|
+
content: `(${emRegexp(allowWhitespace, '*')})`, // ?<text>
|
|
99
|
+
end: '\\2',
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// UNDERSCORE_EMPHASIS_BORDER:允许除下划线以外的「标点符号」和空格出现,使用[^\w\S \t]或[\W\s]会有性能问题
|
|
103
|
+
const underscore = {
|
|
104
|
+
begin: `(^|${UNDERSCORE_EMPHASIS_BOUNDARY})(_+)`, // ?<leading>, ?<symbol>
|
|
105
|
+
content: `(${emRegexp(allowWhitespace, '_')})`, // ?<text>
|
|
106
|
+
end: `\\2(?=${UNDERSCORE_EMPHASIS_BOUNDARY}|$)`,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
asterisk.reg = compileRegExp(asterisk, 'g');
|
|
110
|
+
underscore.reg = compileRegExp(underscore, 'g');
|
|
111
|
+
return /** @type {any} */ ({ asterisk, underscore });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
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 { compileRegExp } from '@/utils/regexp';
|
|
18
|
+
|
|
19
|
+
export default class Footnote extends ParagraphBase {
|
|
20
|
+
static HOOK_NAME = 'footnote';
|
|
21
|
+
|
|
22
|
+
constructor({ externals, config }) {
|
|
23
|
+
super();
|
|
24
|
+
this.footnoteCache = {};
|
|
25
|
+
this.footnoteMap = {}; // 角标缓存索引
|
|
26
|
+
this.footnote = [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
$cleanCache() {
|
|
30
|
+
this.footnoteCache = {};
|
|
31
|
+
this.footnoteMap = {}; // 角标缓存索引
|
|
32
|
+
this.footnote = [];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pushFootnoteCache(key, cache) {
|
|
36
|
+
this.footnoteCache[key] = cache;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getFootnoteCache(key) {
|
|
40
|
+
return this.footnoteCache[key] || null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
pushFootNote(key, note) {
|
|
44
|
+
if (this.footnoteMap[key]) {
|
|
45
|
+
// 重复引用时返回已缓存下标
|
|
46
|
+
return this.footnoteMap[key];
|
|
47
|
+
}
|
|
48
|
+
const num = this.footnote.length + 1;
|
|
49
|
+
const fn = {};
|
|
50
|
+
fn.fn = `<sup><a href="#fn:${num}" id="fnref:${num}" title="${key}" class="footnote">[${num}]</a></sup>`;
|
|
51
|
+
fn.fnref = `<a href="#fnref:${num}" id="fn:${num}" title="${key}" class="footnote-ref">[${num}]</a>`;
|
|
52
|
+
fn.num = num;
|
|
53
|
+
fn.note = note.trim();
|
|
54
|
+
this.footnote.push(fn);
|
|
55
|
+
const replaceKey = `\0~fn#${num - 1}#\0`;
|
|
56
|
+
this.footnoteMap[key] = replaceKey;
|
|
57
|
+
return replaceKey;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getFootNote() {
|
|
61
|
+
return this.footnote;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
formatFootNote() {
|
|
65
|
+
const footnote = this.getFootNote();
|
|
66
|
+
if (footnote.length <= 0) {
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
let html = footnote.map((note) => `<div class="one-footnote">\n${note.fnref}${note.note}\n</div>`).join('');
|
|
70
|
+
const sign = this.$engine.hash(html);
|
|
71
|
+
html = `<div class="footnote" data-sign="${sign}" data-lines="0"><div class="footnote-title">脚注</div>${html}</div>`;
|
|
72
|
+
return html;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// getParagraphHook() {
|
|
76
|
+
// return this.commentPAR;
|
|
77
|
+
// }
|
|
78
|
+
|
|
79
|
+
beforeMakeHtml(str) {
|
|
80
|
+
// 单行注释,TODO: 替换为引用
|
|
81
|
+
// str = str.replace(/(^|\n)\[([^^][^\]]*?)\]:([^\n]+?)(?=$|\n)/g, '$1');
|
|
82
|
+
let $str = str;
|
|
83
|
+
if (this.test($str)) {
|
|
84
|
+
$str = $str.replace(this.RULE.reg, (match, leading, key, content) => {
|
|
85
|
+
this.pushFootnoteCache(key, content);
|
|
86
|
+
const LF = match.match(/\n/g) || [];
|
|
87
|
+
return LF.join('');
|
|
88
|
+
});
|
|
89
|
+
// 替换实际引用
|
|
90
|
+
$str = $str.replace(/\[\^([^\]]+?)\](?!:)/g, (match, key) => {
|
|
91
|
+
const cache = this.getFootnoteCache(key);
|
|
92
|
+
if (cache) {
|
|
93
|
+
return this.pushFootNote(key, cache);
|
|
94
|
+
}
|
|
95
|
+
return match;
|
|
96
|
+
});
|
|
97
|
+
$str += this.formatFootNote();
|
|
98
|
+
}
|
|
99
|
+
return $str;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
103
|
+
return str;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
afterMakeHtml(str) {
|
|
107
|
+
const footNotes = this.getFootNote();
|
|
108
|
+
const $str = str.replace(/\0~fn#([0-9]+)#\0/g, (match, num) => footNotes[num].fn);
|
|
109
|
+
// this.$cleanCache();
|
|
110
|
+
return $str;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
rule() {
|
|
114
|
+
const ret = {
|
|
115
|
+
begin: '(^|\\n)[ \t]*',
|
|
116
|
+
content: [
|
|
117
|
+
'\\[\\^([^\\]]+?)\\]:\\h*', // footnote key
|
|
118
|
+
'([\\s\\S]+?)', // footnote content
|
|
119
|
+
].join(''),
|
|
120
|
+
end: '(?=\\s*$|\\n\\n)',
|
|
121
|
+
};
|
|
122
|
+
ret.reg = compileRegExp(ret, 'g', true);
|
|
123
|
+
return ret;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
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 { compileRegExp } from '@/utils/regexp';
|
|
18
|
+
|
|
19
|
+
export default class FrontMatter extends ParagraphBase {
|
|
20
|
+
static HOOK_NAME = 'frontMatter';
|
|
21
|
+
|
|
22
|
+
constructor(options) {
|
|
23
|
+
super({ needCache: true });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
beforeMakeHtml(str) {
|
|
27
|
+
return str.replace(this.RULE.reg, (match, content) => {
|
|
28
|
+
const lineCount = match.match(/\n/g)?.length ?? 0;
|
|
29
|
+
const sign = `fontMatter${lineCount}`;
|
|
30
|
+
content.replace(/(?:^|\n)\s*(font-size|fontSize): ([0-9a-zA-Z]+)(\n|$)/, (match, m1, m2) => {
|
|
31
|
+
this.$engine.$cherry.previewer.getDom().style.fontSize = m2;
|
|
32
|
+
return match;
|
|
33
|
+
});
|
|
34
|
+
// 预判下是否为json格式,json格式就去掉换行,yaml格式就把换成换成分号
|
|
35
|
+
const dataContent = /^\s*{/.test(content) ? content.replace(/\n/g, '') : content.replace(/\n/g, ';');
|
|
36
|
+
const html = `<p data-sign="${sign}" data-type="frontMatter" data-lines="${lineCount}" data-content="${dataContent}"></p>`;
|
|
37
|
+
const placeHolder = this.pushCache(html, sign, lineCount);
|
|
38
|
+
return `${placeHolder}\n`;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
43
|
+
return str;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
rule() {
|
|
47
|
+
const ret = { begin: '^\\s*-{3,}[^\\n]*\\n', end: '\\n-{3,}[^\\n]*\\n', content: '([\\s\\S]+?)' };
|
|
48
|
+
ret.reg = compileRegExp(ret, 'g', true);
|
|
49
|
+
return ret;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
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 { compileRegExp } from '@/utils/regexp';
|
|
18
|
+
import { calculateLinesOfParagraph } from '@/utils/lineFeed';
|
|
19
|
+
|
|
20
|
+
const ATX_HEADER = 'atx';
|
|
21
|
+
const SETEXT_HEADER = 'setext';
|
|
22
|
+
const toDashChars = /[\s\-_]/;
|
|
23
|
+
const alphabetic = /[A-Za-z]/;
|
|
24
|
+
const numeric = /[0-9]/;
|
|
25
|
+
|
|
26
|
+
export default class Header extends ParagraphBase {
|
|
27
|
+
static HOOK_NAME = 'header';
|
|
28
|
+
|
|
29
|
+
constructor({ externals, config } = { config: undefined, externals: undefined }) {
|
|
30
|
+
super({ needCache: true });
|
|
31
|
+
this.strict = config ? !!config.strict : true;
|
|
32
|
+
this.RULE = this.rule();
|
|
33
|
+
this.headerIDCache = [];
|
|
34
|
+
this.headerIDCounter = {};
|
|
35
|
+
this.config = config || {};
|
|
36
|
+
// TODO: AllowCustomID
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
$parseTitleText(html = '') {
|
|
40
|
+
if (typeof html !== 'string') {
|
|
41
|
+
return '';
|
|
42
|
+
}
|
|
43
|
+
return html.replace(/<.*?>/g, '').replace(/</g, '<').replace(/>/g, '>');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* refer:
|
|
48
|
+
* @see https://github.com/vsch/flexmark-java/blob/8bf621924158dfed8b84120479c82704020a6927/flexmark
|
|
49
|
+
* /src/main/java/com/vladsch/flexmark/html/renderer/HeaderIdGenerator.java#L90-L113
|
|
50
|
+
*
|
|
51
|
+
* @param {string} headerText
|
|
52
|
+
* @param {boolean} [toLowerCase]
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
55
|
+
$generateId(headerText, toLowerCase = true) {
|
|
56
|
+
const len = headerText.length;
|
|
57
|
+
let id = '';
|
|
58
|
+
for (let i = 0; i < len; i++) {
|
|
59
|
+
const c = headerText.charAt(i);
|
|
60
|
+
if (alphabetic.test(c)) {
|
|
61
|
+
id += toLowerCase ? c.toLowerCase() : c;
|
|
62
|
+
} else if (numeric.test(c)) {
|
|
63
|
+
id += c;
|
|
64
|
+
} else if (toDashChars.test(c)) {
|
|
65
|
+
id += id.length < 1 || id.charAt(id.length - 1) !== '-' ? '-' : '';
|
|
66
|
+
} else if (c.charCodeAt(0) > 255) {
|
|
67
|
+
// unicode
|
|
68
|
+
try {
|
|
69
|
+
id += encodeURIComponent(c);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
// empty
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return id;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
generateIDNoDup(headerText) {
|
|
79
|
+
// 处理被引擎转换过的实体字符
|
|
80
|
+
const unescapedHeaderText = headerText.replace(/</g, '<').replace(/>/g, '>');
|
|
81
|
+
let newId = this.$generateId(unescapedHeaderText, true);
|
|
82
|
+
const idIndex = this.headerIDCache.indexOf(newId);
|
|
83
|
+
if (idIndex !== -1) {
|
|
84
|
+
this.headerIDCounter[idIndex] += 1;
|
|
85
|
+
newId += `-${this.headerIDCounter[idIndex] + 1}`;
|
|
86
|
+
} else {
|
|
87
|
+
const newIndex = this.headerIDCache.push(newId);
|
|
88
|
+
this.headerIDCounter[newIndex - 1] = 1;
|
|
89
|
+
}
|
|
90
|
+
return newId;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
$wrapHeader(text, level, dataLines, sentenceMakeFunc) {
|
|
94
|
+
// 需要经过一次escape
|
|
95
|
+
const processedText = sentenceMakeFunc(text.trim());
|
|
96
|
+
let { html } = processedText;
|
|
97
|
+
// TODO: allowCustomID开关
|
|
98
|
+
// let htmlAttr = this.getAttributes(html);
|
|
99
|
+
// html = htmlAttr.str;
|
|
100
|
+
// let attrs = htmlAttr.attrs;
|
|
101
|
+
// console.log(attrs);
|
|
102
|
+
const customIDRegex = /\s+\{#([A-Za-z0-9-]+)\}$/; // ?<id>
|
|
103
|
+
const idMatch = html.match(customIDRegex);
|
|
104
|
+
let anchorID;
|
|
105
|
+
if (idMatch !== null) {
|
|
106
|
+
html = html.substring(0, idMatch.index);
|
|
107
|
+
[, anchorID] = idMatch;
|
|
108
|
+
}
|
|
109
|
+
const headerTextRaw = this.$parseTitleText(html);
|
|
110
|
+
if (!anchorID) {
|
|
111
|
+
const replaceFootNote = /~fn#([0-9]+)#/g;
|
|
112
|
+
anchorID = this.generateIDNoDup(headerTextRaw.replace(replaceFootNote, ''));
|
|
113
|
+
}
|
|
114
|
+
const safeAnchorID = `safe_${anchorID}`; // transform header id to avoid being sanitized
|
|
115
|
+
const sign = this.$engine.hash(`${level}-${processedText.sign}-${anchorID}-${dataLines}`);
|
|
116
|
+
const result = [
|
|
117
|
+
`<h${level} id="${safeAnchorID}" data-sign="${sign}" data-lines="${dataLines}">`,
|
|
118
|
+
this.$getAnchor(anchorID),
|
|
119
|
+
`${html}`,
|
|
120
|
+
`</h${level}>`,
|
|
121
|
+
].join('');
|
|
122
|
+
return { html: result, sign: `${sign}` };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
$getAnchor(anchorID) {
|
|
126
|
+
const anchorStyle = this.config.anchorStyle || 'default';
|
|
127
|
+
if (anchorStyle === 'none') {
|
|
128
|
+
return '';
|
|
129
|
+
}
|
|
130
|
+
return `<a class="anchor" href="#${anchorID}"></a>`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
beforeMakeHtml(str) {
|
|
134
|
+
let $str = str;
|
|
135
|
+
if (this.$engine.$cherry.options.engine.global.flowSessionContext) {
|
|
136
|
+
// 适配流式会话的场景,文章末尾的段横线标题语法(`\n-`)失效
|
|
137
|
+
$str = $str.replace(/(\n\s*-{1,})\s*$/, '$1 ');
|
|
138
|
+
}
|
|
139
|
+
// atx 优先
|
|
140
|
+
if (this.test($str, ATX_HEADER)) {
|
|
141
|
+
$str = $str.replace(this.RULE[ATX_HEADER].reg, (match, lines, level, text) => {
|
|
142
|
+
if (text.trim() === '') {
|
|
143
|
+
return match;
|
|
144
|
+
}
|
|
145
|
+
return this.getCacheWithSpace(this.pushCache(match), match, true);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
// 按照目前的引擎,每个hook只会执行一次,所以需要并行执行替换
|
|
149
|
+
if (this.test($str, SETEXT_HEADER)) {
|
|
150
|
+
$str = $str.replace(this.RULE[SETEXT_HEADER].reg, (match, lines, text) => {
|
|
151
|
+
if (text.trim() === '' || this.isContainsCache(text)) {
|
|
152
|
+
return match;
|
|
153
|
+
}
|
|
154
|
+
return this.getCacheWithSpace(this.pushCache(match), match, true);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
return $str;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
161
|
+
// 先还原
|
|
162
|
+
let $str = this.restoreCache(str);
|
|
163
|
+
// atx 优先
|
|
164
|
+
if (this.test($str, ATX_HEADER)) {
|
|
165
|
+
$str = $str.replace(this.RULE[ATX_HEADER].reg, (match, lines, level, text) => {
|
|
166
|
+
// 其中有两行是beforeMake加上的
|
|
167
|
+
const lineCount = calculateLinesOfParagraph(lines, this.getLineCount(match.replace(/^\n+/, '')));
|
|
168
|
+
const $text = text.replace(/\s+#+\s*$/, ''); // close tag
|
|
169
|
+
const { html: result, sign } = this.$wrapHeader($text, level.length, lineCount, sentenceMakeFunc);
|
|
170
|
+
// 文章的开头不加换行
|
|
171
|
+
return this.getCacheWithSpace(this.pushCache(result, sign, lineCount), match, true);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// 按照目前的引擎,每个hook只会执行一次,所以需要并行执行替换
|
|
175
|
+
if (this.test($str, SETEXT_HEADER)) {
|
|
176
|
+
$str = $str.replace(this.RULE[SETEXT_HEADER].reg, (match, lines, text, level) => {
|
|
177
|
+
if (this.isContainsCache(text)) {
|
|
178
|
+
return match;
|
|
179
|
+
}
|
|
180
|
+
// 其中有两行是beforeMake加上的
|
|
181
|
+
const lineCount = calculateLinesOfParagraph(lines, this.getLineCount(match.replace(/^\n+/, '')));
|
|
182
|
+
const headerLevel = level[0] === '-' ? 2 : 1; // =: H1, -: H2
|
|
183
|
+
const { html: result, sign } = this.$wrapHeader(text, headerLevel, lineCount, sentenceMakeFunc);
|
|
184
|
+
// 文章的开头不加换行
|
|
185
|
+
return this.getCacheWithSpace(this.pushCache(result, sign, lineCount), match, true);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return $str;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
afterMakeHtml(html) {
|
|
192
|
+
const $html = super.afterMakeHtml(html);
|
|
193
|
+
this.headerIDCache = [];
|
|
194
|
+
this.headerIDCounter = {};
|
|
195
|
+
return $html;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
test(str, flavor) {
|
|
199
|
+
return this.RULE[flavor].reg && this.RULE[flavor].reg.test(str);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* TODO: fix type errors, prefer use `rules` for multiple spec instead
|
|
204
|
+
* @returns
|
|
205
|
+
*/
|
|
206
|
+
rule() {
|
|
207
|
+
// setext Header
|
|
208
|
+
// TODO: 支持多行标题
|
|
209
|
+
const setext = {
|
|
210
|
+
begin: '(?:^|\\n)(\\n*)', // (?<lines>\\n*)
|
|
211
|
+
content: [
|
|
212
|
+
'(?:\\h*',
|
|
213
|
+
'(.+)', // (?<text>.+)
|
|
214
|
+
')\\n',
|
|
215
|
+
'(?:\\h*',
|
|
216
|
+
'([=]+|[-]+)', // (?<level>[=]+|[-]+)
|
|
217
|
+
')',
|
|
218
|
+
].join(''),
|
|
219
|
+
end: '(?=$|\\n)',
|
|
220
|
+
};
|
|
221
|
+
setext.reg = compileRegExp(setext, 'g', true);
|
|
222
|
+
|
|
223
|
+
// atx header
|
|
224
|
+
const atx = {
|
|
225
|
+
begin: '(?:^|\\n)(\\n*)(?:\\h*(#{1,6}))', // (?<lines>\\n*), (?<level>#{1,6})
|
|
226
|
+
content: '(.+?)', // '(?<text>.+?)'
|
|
227
|
+
end: '(?=$|\\n)',
|
|
228
|
+
};
|
|
229
|
+
this.strict && (atx.begin += '(?=\\h+)'); // (?=\\s+) for strict mode
|
|
230
|
+
atx.reg = compileRegExp(atx, 'g', true);
|
|
231
|
+
|
|
232
|
+
return /** @type {any} */ ({ setext, atx });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
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 '../SyntaxBase.js';
|
|
17
|
+
|
|
18
|
+
export default class HighLight extends SyntaxBase {
|
|
19
|
+
static HOOK_NAME = 'highLight';
|
|
20
|
+
|
|
21
|
+
makeHtml(str) {
|
|
22
|
+
if (!this.test(str)) {
|
|
23
|
+
return str;
|
|
24
|
+
}
|
|
25
|
+
return str.replace(this.RULE.reg, '$1<mark>$2</mark>$3');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
rule() {
|
|
29
|
+
const ret = {
|
|
30
|
+
begin: '(^| )==',
|
|
31
|
+
end: '==( |$|\\n)',
|
|
32
|
+
content: '([^\\n]+?)',
|
|
33
|
+
};
|
|
34
|
+
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
|
|
35
|
+
return ret;
|
|
36
|
+
}
|
|
37
|
+
}
|