cherry-muse 1.0.1
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/LICENSE +162 -0
- package/README.md +139 -0
- package/dist/addons/cherry-code-block-card-plugin.js +1 -0
- package/dist/addons/cherry-code-block-echarts-plugin.js +1 -0
- package/dist/addons/cherry-code-block-mermaid-plugin.js +1 -0
- package/dist/cherry-markdown.core.common.js +1 -0
- package/dist/cherry-markdown.core.js +1 -0
- package/dist/cherry-markdown.css +4089 -0
- package/dist/cherry-markdown.engine.core.common.js +1 -0
- package/dist/cherry-markdown.engine.core.esm.js +1 -0
- package/dist/cherry-markdown.engine.core.js +1 -0
- package/dist/cherry-markdown.esm.js +1 -0
- package/dist/cherry-markdown.js +70837 -0
- package/dist/cherry-markdown.js.map +1 -0
- package/dist/cherry-markdown.min.css +1 -0
- package/dist/cherry-markdown.min.js +1 -0
- package/dist/stats.html +4838 -0
- package/examples/scripts/pinyin/README.md +53 -0
- package/package.json +167 -0
- package/src/Cherry.config.js +411 -0
- package/src/Cherry.js +788 -0
- package/src/CherryStatic.js +70 -0
- package/src/Editor.js +746 -0
- package/src/Engine.js +334 -0
- package/src/Event.js +74 -0
- package/src/Factory.js +180 -0
- package/src/Logger.js +31 -0
- package/src/Previewer.js +1147 -0
- package/src/Sanitizer.js +4 -0
- package/src/Sanitizer.node.js +7 -0
- package/src/Stats.js +101 -0
- package/src/Theme.js +46 -0
- package/src/UrlCache.js +98 -0
- package/src/addons/cherry-code-block-card-plugin.js +213 -0
- package/src/addons/cherry-code-block-echarts-plugin.js +161 -0
- package/src/addons/cherry-code-block-mermaid-plugin.js +118 -0
- package/src/core/HookCenter.js +303 -0
- package/src/core/HooksConfig.js +106 -0
- package/src/core/ParagraphBase.js +314 -0
- package/src/core/SentenceBase.js +65 -0
- package/src/core/SyntaxBase.js +197 -0
- package/src/core/hooks/AutoLink.js +251 -0
- package/src/core/hooks/BackgroundColor.js +46 -0
- package/src/core/hooks/Badge.js +100 -0
- package/src/core/hooks/Blockquote.js +113 -0
- package/src/core/hooks/Br.js +85 -0
- package/src/core/hooks/CodeBlock.js +876 -0
- package/src/core/hooks/Color.js +78 -0
- package/src/core/hooks/CommentReference.js +96 -0
- package/src/core/hooks/Detail.js +138 -0
- package/src/core/hooks/Emoji.config.js +9388 -0
- package/src/core/hooks/Emoji.js +223 -0
- package/src/core/hooks/Emphasis.js +113 -0
- package/src/core/hooks/Footnote.js +125 -0
- package/src/core/hooks/FrontMatter.js +52 -0
- package/src/core/hooks/FrontMatterVars.js +82 -0
- package/src/core/hooks/Header.js +229 -0
- package/src/core/hooks/HighLight.js +37 -0
- package/src/core/hooks/Hr.js +52 -0
- package/src/core/hooks/HtmlBlock.js +159 -0
- package/src/core/hooks/Iframe.js +80 -0
- package/src/core/hooks/Image.js +276 -0
- package/src/core/hooks/InlineCode.js +45 -0
- package/src/core/hooks/InlineMath.js +142 -0
- package/src/core/hooks/Link.js +169 -0
- package/src/core/hooks/List.js +260 -0
- package/src/core/hooks/Mark.js +55 -0
- package/src/core/hooks/MathBlock.js +97 -0
- package/src/core/hooks/Panel.js +170 -0
- package/src/core/hooks/Paragraph.js +84 -0
- package/src/core/hooks/Ruby.js +34 -0
- package/src/core/hooks/Size.js +84 -0
- package/src/core/hooks/Strikethrough.js +54 -0
- package/src/core/hooks/Sub.js +47 -0
- package/src/core/hooks/SuggestList.js +317 -0
- package/src/core/hooks/Suggester.js +759 -0
- package/src/core/hooks/Sup.js +47 -0
- package/src/core/hooks/Table.js +315 -0
- package/src/core/hooks/Toc.js +290 -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 +62 -0
- package/src/index.engine.js +30 -0
- package/src/index.js +28 -0
- package/src/locales/index.js +21 -0
- package/src/locales/zh_CN.js +170 -0
- package/src/sass/cherry.scss +122 -0
- package/src/sass/components/bubble.scss +122 -0
- package/src/sass/components/codemirror.scss +628 -0
- package/src/sass/components/dropdown.scss +37 -0
- package/src/sass/components/editor.scss +78 -0
- package/src/sass/components/preview.scss +71 -0
- package/src/sass/components/prism.scss +142 -0
- package/src/sass/components/stats.scss +32 -0
- package/src/sass/components/toc.scss +184 -0
- package/src/sass/components/toolbar.scss +117 -0
- package/src/sass/core/AutoLink.scss +20 -0
- package/src/sass/core/BackgroundColor.scss +0 -0
- package/src/sass/core/Badge.scss +116 -0
- package/src/sass/core/Blockquote.scss +12 -0
- package/src/sass/core/Br.scss +0 -0
- package/src/sass/core/Card.scss +219 -0
- package/src/sass/core/CodeBlock.scss +205 -0
- package/src/sass/core/Color.scss +37 -0
- package/src/sass/core/CommentReference.scss +0 -0
- package/src/sass/core/Detail.scss +107 -0
- package/src/sass/core/Emoji.scss +127 -0
- package/src/sass/core/Emphasis.scss +9 -0
- package/src/sass/core/Footnote.scss +21 -0
- package/src/sass/core/FrontMatterVars.scss +19 -0
- package/src/sass/core/Header.scss +103 -0
- package/src/sass/core/HighLight.scss +0 -0
- package/src/sass/core/Hr.scss +10 -0
- package/src/sass/core/HtmlBlock.scss +0 -0
- package/src/sass/core/Iframe.scss +36 -0
- package/src/sass/core/Image.scss +59 -0
- package/src/sass/core/InlineCode.scss +10 -0
- package/src/sass/core/InlineMath.scss +11 -0
- package/src/sass/core/Link.scss +16 -0
- package/src/sass/core/List.scss +61 -0
- package/src/sass/core/Mark.scss +15 -0
- package/src/sass/core/MathBlock.scss +0 -0
- package/src/sass/core/Panel.scss +150 -0
- package/src/sass/core/Paragraph.scss +6 -0
- package/src/sass/core/Ruby.scss +0 -0
- package/src/sass/core/Size.scss +8 -0
- package/src/sass/core/Strikethrough.scss +0 -0
- package/src/sass/core/Sub.scss +5 -0
- package/src/sass/core/Suggester.scss +62 -0
- package/src/sass/core/Sup.scss +5 -0
- package/src/sass/core/Table.scss +127 -0
- package/src/sass/core/Toc.scss +28 -0
- package/src/sass/core/Transfer.scss +0 -0
- package/src/sass/core/Underline.scss +0 -0
- package/src/sass/google-fonts.scss +34 -0
- package/src/sass/index.scss +3 -0
- package/src/sass/prism/dark.scss +131 -0
- package/src/sass/prism/light.scss +143 -0
- package/src/sass/variables/colors.scss +96 -0
- package/src/toolbars/Bubble.js +232 -0
- package/src/toolbars/BubbleTable.js +147 -0
- package/src/toolbars/HookCenter.js +185 -0
- package/src/toolbars/MenuBase.js +357 -0
- package/src/toolbars/PreviewerBubble.js +558 -0
- package/src/toolbars/Toc.js +246 -0
- package/src/toolbars/Toolbar.js +401 -0
- package/src/toolbars/hooks/Audio.js +53 -0
- package/src/toolbars/hooks/Badge.js +80 -0
- package/src/toolbars/hooks/BarTable.js +41 -0
- package/src/toolbars/hooks/Bold.js +70 -0
- package/src/toolbars/hooks/Br.js +34 -0
- package/src/toolbars/hooks/Card.js +64 -0
- package/src/toolbars/hooks/CheckList.js +41 -0
- package/src/toolbars/hooks/Code.js +46 -0
- package/src/toolbars/hooks/Color.js +285 -0
- package/src/toolbars/hooks/Copy.js +139 -0
- package/src/toolbars/hooks/Detail.js +70 -0
- package/src/toolbars/hooks/ECharts.js +303 -0
- package/src/toolbars/hooks/Emoji.js +303 -0
- package/src/toolbars/hooks/Export.js +47 -0
- package/src/toolbars/hooks/File.js +54 -0
- package/src/toolbars/hooks/Formula.js +36 -0
- package/src/toolbars/hooks/FullScreen.js +55 -0
- package/src/toolbars/hooks/Graph.js +281 -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 +100 -0
- package/src/toolbars/hooks/Hr.js +35 -0
- package/src/toolbars/hooks/Iframe.js +35 -0
- package/src/toolbars/hooks/Image.js +60 -0
- package/src/toolbars/hooks/Insert.js +36 -0
- package/src/toolbars/hooks/Italic.js +70 -0
- package/src/toolbars/hooks/LineTable.js +41 -0
- package/src/toolbars/hooks/Link.js +46 -0
- package/src/toolbars/hooks/List.js +55 -0
- package/src/toolbars/hooks/Ol.js +41 -0
- package/src/toolbars/hooks/Panel.js +155 -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/Size.js +100 -0
- package/src/toolbars/hooks/Split.js +37 -0
- package/src/toolbars/hooks/Strikethrough.js +65 -0
- package/src/toolbars/hooks/Sub.js +58 -0
- package/src/toolbars/hooks/Sup.js +58 -0
- package/src/toolbars/hooks/SwitchModel.js +78 -0
- package/src/toolbars/hooks/Table.js +56 -0
- package/src/toolbars/hooks/Toc.js +35 -0
- package/src/toolbars/hooks/TogglePreview.js +79 -0
- package/src/toolbars/hooks/Ul.js +41 -0
- package/src/toolbars/hooks/Underline.js +65 -0
- package/src/toolbars/hooks/Undo.js +30 -0
- package/src/toolbars/hooks/Video.js +53 -0
- package/src/utils/LazyLoadImg.js +341 -0
- package/src/utils/autoindent.js +58 -0
- package/src/utils/codeBlockContentHandler.js +351 -0
- package/src/utils/config.js +98 -0
- package/src/utils/copy.js +55 -0
- package/src/utils/dialog.js +196 -0
- package/src/utils/dom.js +162 -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 +115 -0
- package/src/utils/file.js +121 -0
- package/src/utils/formulaUtilsHandler.js +230 -0
- package/src/utils/htmlparser.js +977 -0
- package/src/utils/image.js +99 -0
- package/src/utils/imgSizeHandler.js +279 -0
- package/src/utils/jsonUtils.js +17 -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/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/svgUtils.js +96 -0
- package/src/utils/tableContentHandler.js +592 -0
- package/tools/README.md +3 -0
|
@@ -0,0 +1,260 @@
|
|
|
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
|
+
|
|
18
|
+
const INDENT_SPACE_NUM = 4; // commonmark default use 1~4 spaces for indent
|
|
19
|
+
const TAB_SPACE_NUM = 4; // 1 tab === 4 space
|
|
20
|
+
|
|
21
|
+
function attrsToAttributeString(object) {
|
|
22
|
+
if (typeof object !== 'object' && Object.keys(object).length < 1) {
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
const attrs = ['']; // 为了join一步到位
|
|
26
|
+
Object.keys(object).forEach((key) => {
|
|
27
|
+
attrs.push(`${key}="${object[key]}"`);
|
|
28
|
+
});
|
|
29
|
+
return attrs.join(' ');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function makeChecklist(text) {
|
|
33
|
+
return text.replace(/^((?:|[\t ]+)[*+-]\s+)\[(\s|x)\]/gm, (whole, pre, test) => {
|
|
34
|
+
const checkHtml = /\s/.test(test)
|
|
35
|
+
? '<input class="cherry-checkbox" type="checkbox"/>'
|
|
36
|
+
: '<input class="cherry-checkbox" type="checkbox" checked="checked" />';
|
|
37
|
+
return `${pre}${checkHtml}`;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 缩进处理
|
|
42
|
+
function handleIndent(str, node) {
|
|
43
|
+
const indentRegex = /^(\t|[ ])/;
|
|
44
|
+
let $str = str;
|
|
45
|
+
while (indentRegex.test($str)) {
|
|
46
|
+
node.space += $str[0] === '\t' ? TAB_SPACE_NUM : 1;
|
|
47
|
+
$str = $str.replace(indentRegex, '');
|
|
48
|
+
}
|
|
49
|
+
return $str;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 序号样式处理
|
|
53
|
+
function getListStyle(m2) {
|
|
54
|
+
if (/^[a-z]/.test(m2)) {
|
|
55
|
+
return 'lower-greek';
|
|
56
|
+
}
|
|
57
|
+
if (/^[一二三四五六七八九十]/.test(m2)) {
|
|
58
|
+
return 'cjk-ideographic';
|
|
59
|
+
}
|
|
60
|
+
if (/^I/.test(m2)) {
|
|
61
|
+
return 'upper-roman';
|
|
62
|
+
}
|
|
63
|
+
if (/^\+/.test(m2)) {
|
|
64
|
+
return 'circle';
|
|
65
|
+
}
|
|
66
|
+
if (/^\*/.test(m2)) {
|
|
67
|
+
return 'square';
|
|
68
|
+
}
|
|
69
|
+
return 'default';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 标识符处理
|
|
73
|
+
function handleMark(str, node) {
|
|
74
|
+
const listRegex =
|
|
75
|
+
/^((([*+-]|\d+[.]|[a-z]\.|[I一二三四五六七八九十]+\.)[ \t]+)([^\r]*?)($|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.]|[a-z]\.|[I一二三四五六七八九十]+\.)[ \t]+)))/;
|
|
76
|
+
if (!listRegex.test(str)) {
|
|
77
|
+
node.type = 'blank';
|
|
78
|
+
return str;
|
|
79
|
+
}
|
|
80
|
+
return str.replace(listRegex, (wholeMatch, m1, m2, m3, m4) => {
|
|
81
|
+
node.type = m2.search(/[*+-]/g) > -1 ? 'ul' : 'ol';
|
|
82
|
+
node.listStyle = getListStyle(m2);
|
|
83
|
+
node.start = Number(m2.replace('.', '')) ? Number(m2.replace('.', '')) : 1;
|
|
84
|
+
return m4;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
class Node {
|
|
89
|
+
// 列表树节点
|
|
90
|
+
constructor() {
|
|
91
|
+
this.index = 0;
|
|
92
|
+
this.space = 0;
|
|
93
|
+
this.type = '';
|
|
94
|
+
this.start = 1;
|
|
95
|
+
this.listStyle = '';
|
|
96
|
+
this.strs = [];
|
|
97
|
+
this.children = [];
|
|
98
|
+
this.lines = 0;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export default class List extends ParagraphBase {
|
|
103
|
+
static HOOK_NAME = 'list';
|
|
104
|
+
|
|
105
|
+
constructor({ config }) {
|
|
106
|
+
super({ needCache: true });
|
|
107
|
+
this.config = config || {};
|
|
108
|
+
this.tree = [];
|
|
109
|
+
this.emptyLines = 0;
|
|
110
|
+
this.indentSpace = Math.max(this.config.indentSpace, 2);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
addNode(node, current, parent, last) {
|
|
114
|
+
if (node.type === 'blank') {
|
|
115
|
+
this.tree[last].strs.push(node.strs[0]);
|
|
116
|
+
} else {
|
|
117
|
+
this.tree[parent].children.push(current);
|
|
118
|
+
this.tree[current] = {
|
|
119
|
+
...node,
|
|
120
|
+
parent,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
buildTree(html, sentenceMakeFunc) {
|
|
126
|
+
const items = html.split('\n');
|
|
127
|
+
this.tree = [];
|
|
128
|
+
items.unshift('');
|
|
129
|
+
// 列表结尾换行符个数
|
|
130
|
+
const endLineFlagLength = html.match(/\n*$/g)[0].length;
|
|
131
|
+
for (let i = 0; i < items.length - endLineFlagLength; i++) {
|
|
132
|
+
const node = new Node();
|
|
133
|
+
items[i] = handleIndent(items[i], node);
|
|
134
|
+
items[i] = handleMark(items[i], node);
|
|
135
|
+
node.strs.push(sentenceMakeFunc(items[i]).html);
|
|
136
|
+
node.index = i;
|
|
137
|
+
if (i === 0) {
|
|
138
|
+
// 根节点
|
|
139
|
+
node.space = -2;
|
|
140
|
+
this.tree.push(node);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
let last = i - 1;
|
|
144
|
+
while (!this.tree[last]) last -= 1;
|
|
145
|
+
if (node.type === 'blank') {
|
|
146
|
+
this.addNode(node, i, this.tree[last].parent, last);
|
|
147
|
+
} else {
|
|
148
|
+
while (!this.tree[last] || this.tree[last].space > node.space) last -= 1;
|
|
149
|
+
const { space } = node;
|
|
150
|
+
const lastSpace = this.tree[last].space;
|
|
151
|
+
if (space < lastSpace + this.indentSpace) {
|
|
152
|
+
// 成为同级节点
|
|
153
|
+
if (this.config.listNested && this.tree[last].type !== node.type) {
|
|
154
|
+
this.addNode(node, i, last);
|
|
155
|
+
} else {
|
|
156
|
+
this.addNode(node, i, this.tree[last].parent);
|
|
157
|
+
}
|
|
158
|
+
} else if (space < lastSpace + this.indentSpace + INDENT_SPACE_NUM) {
|
|
159
|
+
// 成为子节点
|
|
160
|
+
this.addNode(node, i, last);
|
|
161
|
+
} else {
|
|
162
|
+
// 纯文本
|
|
163
|
+
node.type = 'blank';
|
|
164
|
+
this.addNode(node, i, this.tree[last].parent, last);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
renderSubTree(node, children, type) {
|
|
171
|
+
let lines = 0;
|
|
172
|
+
const attr = {};
|
|
173
|
+
const content = children.reduce((html, item) => {
|
|
174
|
+
const child = this.tree[item];
|
|
175
|
+
const itemAttr = {
|
|
176
|
+
class: 'cherry-list-item',
|
|
177
|
+
};
|
|
178
|
+
const str = `<p>${child.strs.join('<br>')}</p>`;
|
|
179
|
+
child.lines += this.getLineCount(child.strs.join('\n'));
|
|
180
|
+
const children = child.children.length ? this.renderTree(item) : '';
|
|
181
|
+
node.lines += child.lines;
|
|
182
|
+
lines += child.lines;
|
|
183
|
+
// checklist 样式适配
|
|
184
|
+
if (str.indexOf('input') !== -1) {
|
|
185
|
+
itemAttr.class += ' check-list-item';
|
|
186
|
+
}
|
|
187
|
+
return `${html}<li${attrsToAttributeString(itemAttr)}>${str}${children}</li>`;
|
|
188
|
+
}, '');
|
|
189
|
+
if (node.parent === undefined) {
|
|
190
|
+
// 根节点增加属性
|
|
191
|
+
attr['data-lines'] = node.index === 0 ? lines + this.emptyLines : lines;
|
|
192
|
+
attr['data-sign'] = this.sign;
|
|
193
|
+
}
|
|
194
|
+
if (children[0] && type === 'ol') {
|
|
195
|
+
attr.start = this.tree[children[0]].start;
|
|
196
|
+
}
|
|
197
|
+
attr.class = `cherry-list__${this.tree[children[0]].listStyle}`;
|
|
198
|
+
return `<${type}${attrsToAttributeString(attr)}>${content}</${type}>`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
renderTree(current) {
|
|
202
|
+
let from = 0;
|
|
203
|
+
const node = this.tree[current];
|
|
204
|
+
const { children } = node;
|
|
205
|
+
const html = children.reduce((html, item, index) => {
|
|
206
|
+
if (index === 0) return html;
|
|
207
|
+
if (this.tree[children[index]].type === this.tree[children[index - 1]].type) {
|
|
208
|
+
return html;
|
|
209
|
+
}
|
|
210
|
+
const subTree = this.renderSubTree(node, children.slice(from, index), this.tree[children[index - 1]].type);
|
|
211
|
+
from = index;
|
|
212
|
+
return html + subTree;
|
|
213
|
+
}, '');
|
|
214
|
+
|
|
215
|
+
const childrenHtml = children.length
|
|
216
|
+
? this.renderSubTree(node, children.slice(from, children.length), this.tree[children[children.length - 1]].type)
|
|
217
|
+
: '';
|
|
218
|
+
|
|
219
|
+
return html + childrenHtml;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
toHtml(wholeMatch, sentenceMakeFunc) {
|
|
223
|
+
// 行数计算吸收的空行
|
|
224
|
+
this.emptyLines = wholeMatch.match(/^\n\n/)?.length ?? 0;
|
|
225
|
+
const text = wholeMatch.replace(/~0$/g, '').replace(/^\n+/, '');
|
|
226
|
+
this.buildTree(makeChecklist(text), sentenceMakeFunc);
|
|
227
|
+
const result = this.renderTree(0);
|
|
228
|
+
return this.pushCache(result, this.sign, this.$getLineNum(wholeMatch));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
$getLineNum(str) {
|
|
232
|
+
const beginLine = str.match(/^\n\n/)?.length ?? 0;
|
|
233
|
+
const $str = str.replace(/^\n+/, '').replace(/\n+$/, '\n');
|
|
234
|
+
return $str.match(/\n/g)?.length ?? 0 + beginLine;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
238
|
+
let $str = `${str}~0`;
|
|
239
|
+
if (this.test($str)) {
|
|
240
|
+
$str = $str.replace(this.RULE.reg, (wholeMatch) => {
|
|
241
|
+
return this.getCacheWithSpace(
|
|
242
|
+
this.checkCache(wholeMatch, sentenceMakeFunc, this.$getLineNum(wholeMatch)),
|
|
243
|
+
wholeMatch,
|
|
244
|
+
);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
$str = $str.replace(/~0$/g, '');
|
|
248
|
+
return $str;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
rule() {
|
|
252
|
+
const ret = {
|
|
253
|
+
begin: '(?:^|\n)(\n*)(([ ]{0,3}([*+-]|\\d+[.]|[a-z]\\.|[I一二三四五六七八九十]+\\.)[ \\t]+)',
|
|
254
|
+
content: '([^\\r]+?)',
|
|
255
|
+
end: '(~0|\\n{2,}(?=\\S)(?![ \\t]*(?:[*+-]|\\d+[.]|[a-z]\\.|[I一二三四五六七八九十]+\\.)[ \\t]+)))',
|
|
256
|
+
};
|
|
257
|
+
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'gm');
|
|
258
|
+
return ret;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
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 SyntaxBase from '../SyntaxBase';
|
|
18
|
+
|
|
19
|
+
export default class Mark extends SyntaxBase {
|
|
20
|
+
static HOOK_NAME = 'mark';
|
|
21
|
+
|
|
22
|
+
toHtml(whole, m1, m2) {
|
|
23
|
+
return `<mark>${m1}</mark>`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
makeHtml(str) {
|
|
27
|
+
if (!this.test(str)) {
|
|
28
|
+
return str;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return str.replace(this.RULE.reg, this.toHtml);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
rule() {
|
|
35
|
+
return {
|
|
36
|
+
begin: '',
|
|
37
|
+
content: '',
|
|
38
|
+
end: '',
|
|
39
|
+
reg: new RegExp('==([^=]+)==', 'g'),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
overlayMode() {
|
|
43
|
+
return {
|
|
44
|
+
name: 'mark',
|
|
45
|
+
token(stream, state) {
|
|
46
|
+
// 检查行的开头是否有 ':::'
|
|
47
|
+
if (stream.match(/==([^=]+)==/)) {
|
|
48
|
+
return 'mark-container';
|
|
49
|
+
}
|
|
50
|
+
stream.next(); // 前进到下一个字符
|
|
51
|
+
return null; // 默认返回 null
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
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 { getHTML } from '@/utils/dom';
|
|
18
|
+
import { isLookbehindSupported } from '@/utils/regexp';
|
|
19
|
+
import { replaceLookbehind } from '@/utils/lookbehind-replace';
|
|
20
|
+
import { Theme } from '@/Theme';
|
|
21
|
+
import Event from '../../Event';
|
|
22
|
+
export default class MathBlock extends ParagraphBase {
|
|
23
|
+
static HOOK_NAME = 'mathBlock';
|
|
24
|
+
|
|
25
|
+
constructor({ config }) {
|
|
26
|
+
super({ needCache: true });
|
|
27
|
+
// 非浏览器环境下配置为 node
|
|
28
|
+
const { MathJax, apiHost = 'https://math.vercel.app' } = config;
|
|
29
|
+
this.api = !MathJax && !window.MathJax;
|
|
30
|
+
this.apiHost = apiHost;
|
|
31
|
+
this.MathJax = MathJax || window.MathJax;
|
|
32
|
+
if (this.api) {
|
|
33
|
+
const that = this;
|
|
34
|
+
Event.on('Theme', 'change', function ([isDark]) {
|
|
35
|
+
const images = that.$engine.$cherry.wrapperDom.querySelectorAll('img.Cherry-Math-Latex');
|
|
36
|
+
images.forEach(function (item, index) {
|
|
37
|
+
if (item instanceof HTMLImageElement) {
|
|
38
|
+
item.src = item.src.replace(isDark ? 'color=black' : 'color=white', isDark ? 'color=white' : 'color=black');
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
toHtml(wholeMatch, lineSpace, leadingChar, content) {
|
|
46
|
+
// 去掉开头的空字符,去掉结尾的换行符
|
|
47
|
+
const wholeMatchWithoutSpace = wholeMatch.replace(/^[ \f\r\t\v]*/, '').replace(/\s*$/, '');
|
|
48
|
+
// 去掉匹配到的第一个换行符
|
|
49
|
+
const lineSpaceWithoutPreSpace = lineSpace.replace(/^[ \f\r\t\v]*\n/, '');
|
|
50
|
+
const sign = this.$engine.md5(wholeMatch);
|
|
51
|
+
let lines = this.getLineCount(wholeMatchWithoutSpace, lineSpaceWithoutPreSpace);
|
|
52
|
+
// 判断公式是不是新行输入,如果不是新行,则行号减1
|
|
53
|
+
if (!/\n/.test(lineSpace)) {
|
|
54
|
+
lines -= 1;
|
|
55
|
+
}
|
|
56
|
+
// 判断公式后面有没有尾接内容,如果尾接了内容,则行号减1
|
|
57
|
+
if (!/\n\s*$/.test(wholeMatch)) {
|
|
58
|
+
lines -= 1;
|
|
59
|
+
}
|
|
60
|
+
// 目前的机制还没有测过lines为负数的情况,先不处理
|
|
61
|
+
lines = lines > 0 ? lines : 0;
|
|
62
|
+
|
|
63
|
+
if (this.MathJax?.tex2svg) {
|
|
64
|
+
// MathJax渲染
|
|
65
|
+
const svg = getHTML(this.MathJax.tex2svg(content), true);
|
|
66
|
+
const result = `<div data-sign="${sign}" class="Cherry-Math" data-type="mathBlock"
|
|
67
|
+
data-lines="${lines}">${svg}</div>`;
|
|
68
|
+
return leadingChar + this.getCacheWithSpace(this.pushCache(result, sign, lines), wholeMatch);
|
|
69
|
+
}
|
|
70
|
+
const result = `<div data-sign="${sign}" class="Cherry-Math" data-type="mathBlock"
|
|
71
|
+
data-lines="${lines}"><img class="Cherry-Math-Latex" alt="latex" src="${
|
|
72
|
+
this.apiHost
|
|
73
|
+
}/?from=${encodeURIComponent(content)}&color=${Theme.isDark() ? 'white' : 'black'}" /></div>`;
|
|
74
|
+
return leadingChar + this.getCacheWithSpace(this.pushCache(result, sign, lines), wholeMatch);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
beforeMakeHtml(str) {
|
|
78
|
+
if (isLookbehindSupported()) {
|
|
79
|
+
return str.replace(this.RULE.reg, this.toHtml.bind(this));
|
|
80
|
+
}
|
|
81
|
+
return replaceLookbehind(str, this.RULE.reg, this.toHtml.bind(this), true, 1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
makeHtml(str) {
|
|
85
|
+
return str;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
rule() {
|
|
89
|
+
const ret = {
|
|
90
|
+
begin: isLookbehindSupported() ? '(\\s*)((?<!\\\\))~D~D\\s*' : '(\\s*)(^|[^\\\\])~D~D\\s*',
|
|
91
|
+
content: '([\\w\\W]*?)',
|
|
92
|
+
end: '(\\s*)~D~D(?:\\s{0,1})',
|
|
93
|
+
};
|
|
94
|
+
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
|
|
95
|
+
return ret;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
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
|
+
import { getPanelRule } from '@/utils/regexp';
|
|
19
|
+
import { blockNames } from '@/utils/sanitize';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 面板语法
|
|
23
|
+
* 例:
|
|
24
|
+
* :::tip
|
|
25
|
+
* 这是一段提示信息
|
|
26
|
+
* :::
|
|
27
|
+
* :::warning
|
|
28
|
+
* 这是一段警告信息
|
|
29
|
+
* :::
|
|
30
|
+
* :::danger
|
|
31
|
+
* 这是一段危险信息
|
|
32
|
+
* :::
|
|
33
|
+
*/
|
|
34
|
+
export default class Panel extends ParagraphBase {
|
|
35
|
+
static HOOK_NAME = 'panel';
|
|
36
|
+
|
|
37
|
+
constructor(options) {
|
|
38
|
+
super({ needCache: true });
|
|
39
|
+
this.initBrReg(options.globalConfig.classicBr);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
43
|
+
return str.replace(this.RULE.reg, (match, preLines, name, content) => {
|
|
44
|
+
const lineCount = this.getLineCount(match, preLines);
|
|
45
|
+
const sign = this.$engine.md5(match);
|
|
46
|
+
const { title, body, appendStyle, className } = this.$getPanelInfo(name, content, sentenceMakeFunc);
|
|
47
|
+
const ret = this.pushCache(
|
|
48
|
+
`<div class="${className}" data-sign="${sign}" data-lines="${lineCount}" ${appendStyle}>${title}${body}</div>`,
|
|
49
|
+
sign,
|
|
50
|
+
lineCount,
|
|
51
|
+
);
|
|
52
|
+
return prependLineFeedForParagraph(match, ret);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
$getClassByType(type) {
|
|
57
|
+
if (/(left|right|center)/i.test(type)) {
|
|
58
|
+
return `cherry-text-align cherry-text-align__${type}`;
|
|
59
|
+
}
|
|
60
|
+
return `cherry-panel cherry-panel__${type}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
$getPanelInfo(name, str, sentenceMakeFunc) {
|
|
64
|
+
const ret = {
|
|
65
|
+
type: this.$getTargetType(name),
|
|
66
|
+
title: sentenceMakeFunc(this.$getTitle(name)).html,
|
|
67
|
+
body: str,
|
|
68
|
+
appendStyle: '',
|
|
69
|
+
className: '',
|
|
70
|
+
};
|
|
71
|
+
ret.className = this.$getClassByType(ret.type);
|
|
72
|
+
if (/(left|right|center)/i.test(ret.type)) {
|
|
73
|
+
ret.appendStyle = `style="text-align:${ret.type};"`;
|
|
74
|
+
}
|
|
75
|
+
ret.title = `<div class="cherry-panel--title ${ret.title ? 'cherry-panel--title__not-empty' : ''}">${
|
|
76
|
+
ret.title
|
|
77
|
+
}</div>`;
|
|
78
|
+
const paragraphProcessor = (str) => {
|
|
79
|
+
if (str.trim() === '') {
|
|
80
|
+
return '';
|
|
81
|
+
}
|
|
82
|
+
// 调用行内语法,获得段落的签名和对应html内容
|
|
83
|
+
const { html } = sentenceMakeFunc(str);
|
|
84
|
+
let domName = 'p';
|
|
85
|
+
// 如果包含html块级标签(比如div、blockquote等),则当前段落外层用div包裹,反之用p包裹
|
|
86
|
+
const isContainBlockTest = new RegExp(`<(${blockNames})[^>]*>`, 'i');
|
|
87
|
+
if (isContainBlockTest.test(html)) {
|
|
88
|
+
domName = 'div';
|
|
89
|
+
}
|
|
90
|
+
return `<${domName}>${this.$cleanParagraph(html)}</${domName}>`;
|
|
91
|
+
};
|
|
92
|
+
let $body = '';
|
|
93
|
+
if (this.isContainsCache(ret.body)) {
|
|
94
|
+
$body = this.makeExcludingCached(ret.body, paragraphProcessor);
|
|
95
|
+
} else {
|
|
96
|
+
$body = paragraphProcessor(ret.body);
|
|
97
|
+
}
|
|
98
|
+
ret.body = `<div class="cherry-panel--body">${$body}</div>`;
|
|
99
|
+
return ret;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
$getTitle(name) {
|
|
103
|
+
const $name = name.trim();
|
|
104
|
+
return /\s/.test($name) ? $name.replace(/[^\s]+\s/, '') : '';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
$getTargetType(name) {
|
|
108
|
+
const $name = /\s/.test(name.trim()) ? name.trim().replace(/\s.*$/, '') : name;
|
|
109
|
+
const $item = $name.trim().toLowerCase();
|
|
110
|
+
switch ($item) {
|
|
111
|
+
case 'im':
|
|
112
|
+
return 'important';
|
|
113
|
+
case 'i':
|
|
114
|
+
return 'info';
|
|
115
|
+
case 'w':
|
|
116
|
+
return 'warning';
|
|
117
|
+
case 'd':
|
|
118
|
+
return 'danger';
|
|
119
|
+
case 'n':
|
|
120
|
+
return 'note';
|
|
121
|
+
case 'r':
|
|
122
|
+
return 'right';
|
|
123
|
+
case 'c':
|
|
124
|
+
return 'center';
|
|
125
|
+
case 'l':
|
|
126
|
+
return 'left';
|
|
127
|
+
case 't':
|
|
128
|
+
return 'tip';
|
|
129
|
+
default:
|
|
130
|
+
return $item;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
rule() {
|
|
135
|
+
return getPanelRule();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
overlayMode() {
|
|
139
|
+
return {
|
|
140
|
+
inContainer: false,
|
|
141
|
+
inType: false,
|
|
142
|
+
name: 'panel',
|
|
143
|
+
token(stream, state) {
|
|
144
|
+
// 检查行的开头是否有 ':::'
|
|
145
|
+
if (stream.sol() && stream.match(':::')) {
|
|
146
|
+
this.inContainer = stream.peek() !== null;
|
|
147
|
+
this.inType = false;
|
|
148
|
+
return 'panel-container';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const rule = /\s(important|info|warning|danger|note|center|left|right|tip)/;
|
|
152
|
+
|
|
153
|
+
// 尝试匹配规则
|
|
154
|
+
if (this.inContainer && stream.match(rule)) {
|
|
155
|
+
this.inContainer = false;
|
|
156
|
+
this.inType = true;
|
|
157
|
+
return 'panel-type';
|
|
158
|
+
}
|
|
159
|
+
if (this.inType && stream.match(/\s.*$/)) {
|
|
160
|
+
this.inType = false;
|
|
161
|
+
return 'panel-title';
|
|
162
|
+
}
|
|
163
|
+
this.inType = false;
|
|
164
|
+
this.inContainer = false;
|
|
165
|
+
stream.next(); // 前进到下一个字符
|
|
166
|
+
return null; // 默认返回 null
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
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 { blockNames } from '@/utils/sanitize';
|
|
18
|
+
/**
|
|
19
|
+
* 段落级语法
|
|
20
|
+
* 段落级语法可以具备以下特性:
|
|
21
|
+
* 1、排他性,可以排除将当前语法之后的所有段落语法
|
|
22
|
+
* 2、可排序,在../HooksConfig.js里设置排序,顺序在前面的段落语法先渲染
|
|
23
|
+
* 3、可嵌套行内语法
|
|
24
|
+
*
|
|
25
|
+
* 段落级语法有以下义务:
|
|
26
|
+
* 1、维护签名,签名用来实现预览区域的局部更新功能
|
|
27
|
+
* 2、维护行号,行号用来实现编辑区和预览区同步滚动
|
|
28
|
+
* 每个段落语法负责计算上文的行号,上文行号不是0就是1,大于1会由BR语法计算行号
|
|
29
|
+
*/
|
|
30
|
+
export default class Paragraph extends ParagraphBase {
|
|
31
|
+
static HOOK_NAME = 'normalParagraph';
|
|
32
|
+
|
|
33
|
+
constructor(options) {
|
|
34
|
+
super();
|
|
35
|
+
this.initBrReg(options.globalConfig.classicBr);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 段落语法的核心渲染函数
|
|
40
|
+
* @param {string} str markdown源码
|
|
41
|
+
* @param {Function} sentenceMakeFunc 行内语法渲染器
|
|
42
|
+
* @returns {string} html内容
|
|
43
|
+
*/
|
|
44
|
+
makeHtml(str, sentenceMakeFunc) {
|
|
45
|
+
if (!this.test(str)) {
|
|
46
|
+
return str;
|
|
47
|
+
}
|
|
48
|
+
return str.replace(this.RULE.reg, (match, preLines, content) => {
|
|
49
|
+
if (this.isContainsCache(match, true)) {
|
|
50
|
+
return match;
|
|
51
|
+
}
|
|
52
|
+
// 判断当前内容里是否包含段落渲染引擎暂存缓存关键字
|
|
53
|
+
const cacheMixedInMatches = this.isContainsCache(content);
|
|
54
|
+
const processor = (p) => {
|
|
55
|
+
if (p.trim() === '') {
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
// 调用行内语法,获得段落的签名和对应html内容
|
|
59
|
+
const { sign, html } = sentenceMakeFunc(p);
|
|
60
|
+
let domName = 'p';
|
|
61
|
+
// 如果包含html块级标签(比如div、blockquote等),则当前段落外层用div包裹,反之用p包裹
|
|
62
|
+
const isContainBlockTest = new RegExp(`<(${blockNames})[^>]*>`, 'i');
|
|
63
|
+
if (isContainBlockTest.test(html)) {
|
|
64
|
+
domName = 'div';
|
|
65
|
+
}
|
|
66
|
+
// 计算行号
|
|
67
|
+
const lines = this.getLineCount(p, p);
|
|
68
|
+
return `<${domName} data-sign="${sign}${lines}" data-type="${domName}" data-lines="${lines}">${this.$cleanParagraph(
|
|
69
|
+
html,
|
|
70
|
+
)}</${domName}>`;
|
|
71
|
+
};
|
|
72
|
+
if (cacheMixedInMatches) {
|
|
73
|
+
return this.makeExcludingCached(`${preLines}${content}`, processor);
|
|
74
|
+
}
|
|
75
|
+
return processor(`${preLines}${content}`);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
rule() {
|
|
80
|
+
const ret = { begin: '(?:^|\\n)(\\n*)', end: '(?=\\s*$|\\n\\n)', content: '([\\s\\S]+?)' };
|
|
81
|
+
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
|
|
82
|
+
return ret;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
|
|
18
|
+
// 拼音语法
|
|
19
|
+
export default class Ruby extends SyntaxBase {
|
|
20
|
+
static HOOK_NAME = 'ruby';
|
|
21
|
+
|
|
22
|
+
makeHtml(str) {
|
|
23
|
+
if (!this.test(str)) {
|
|
24
|
+
return str;
|
|
25
|
+
}
|
|
26
|
+
return str.replace(this.RULE.reg, `$1<ruby>$2<rt>$3</rt></ruby>$4`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
rule() {
|
|
30
|
+
const ret = { begin: '(^| )\\{', end: '\\}( |$)', content: '([^\n]+?)\\|([^\n]+?)' };
|
|
31
|
+
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
|
|
32
|
+
return ret;
|
|
33
|
+
}
|
|
34
|
+
}
|