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,276 @@
|
|
|
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
|
+
const replacerFactory = function (type, match, leadingChar, alt, link, title, posterContent, config, globalConfig) {
|
|
24
|
+
const refType = typeof link === 'undefined' ? 'ref' : 'url';
|
|
25
|
+
let attrs = '';
|
|
26
|
+
if (refType === 'ref') {
|
|
27
|
+
// TODO: 全局引用
|
|
28
|
+
return match;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (refType === 'url') {
|
|
32
|
+
const extent = imgAltHelper.processExtendAttributesInAlt(alt);
|
|
33
|
+
let { extendStyles: style, extendClasses: classes } = imgAltHelper.processExtendStyleInAlt(alt);
|
|
34
|
+
if (style) {
|
|
35
|
+
style = ` style="${style}" `;
|
|
36
|
+
}
|
|
37
|
+
if (classes) {
|
|
38
|
+
classes = ` class="${classes}" `;
|
|
39
|
+
}
|
|
40
|
+
attrs = title && title.trim() !== '' ? ` title="${$e(title)}"` : '';
|
|
41
|
+
if (posterContent) {
|
|
42
|
+
attrs += ` poster="${encodeURIOnce(posterContent)}"`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const processedURL = globalConfig.urlProcessor(link, type);
|
|
46
|
+
const defaultWrapper = `<${type} src="${UrlCache.set(
|
|
47
|
+
encodeURIOnce(processedURL),
|
|
48
|
+
)}"${attrs} ${extent} ${style} ${classes} controls="controls">${$e(alt || '')}</${type}>`;
|
|
49
|
+
return `${leadingChar}${config.videoWrapper ? config.videoWrapper(link) : defaultWrapper}`;
|
|
50
|
+
}
|
|
51
|
+
// should never happen
|
|
52
|
+
return match;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const replacerFileFactory = function (match, leadingChar, alt, link, title, posterContent, config, globalConfig) {
|
|
56
|
+
const fileIcon = {
|
|
57
|
+
file: 'draft', // 默认文件
|
|
58
|
+
'doc|docx|txt': 'description',
|
|
59
|
+
'xls|xlsx': 'table',
|
|
60
|
+
'ppt|pptx': 'video_file',
|
|
61
|
+
pdf: 'picture_as_pdf',
|
|
62
|
+
'jpg|jpeg|png|gif|bmp|tiff|svg': 'image', // 图像文件
|
|
63
|
+
'mp3|wav|aac|ogg|flac': 'audio_file', // 音频文件
|
|
64
|
+
'mp4|avi|mov|wmv|flv|mkv': 'movie', // 视频文件
|
|
65
|
+
'zip|rar|7z|tar.gz|gz': 'folder_zip', // 压缩文件
|
|
66
|
+
'exe|dmg|msi': 'memory', // Windows 可执行文件
|
|
67
|
+
'sh|json|xml|html|htm|css': 'code', // 编程语言和标记语言文件
|
|
68
|
+
apk: 'apk_document', // APK 文件
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function getIcon(ext) {
|
|
72
|
+
// 将 fileIcon 的键转换为数组,每个元素是该键包含的扩展名数组
|
|
73
|
+
const extensionsMap = Object.entries(fileIcon).map(([key, value]) => ({
|
|
74
|
+
exts: key.split('|'),
|
|
75
|
+
icon: value,
|
|
76
|
+
}));
|
|
77
|
+
|
|
78
|
+
// 查找与给定扩展名匹配的图标
|
|
79
|
+
const match = extensionsMap.find(({ exts }) => exts.includes(ext));
|
|
80
|
+
|
|
81
|
+
// 如果找到匹配的图标,则返回它;否则返回默认图标
|
|
82
|
+
return match ? match.icon : fileIcon.file;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const refType = typeof link === 'undefined' ? 'ref' : 'url';
|
|
86
|
+
if (refType === 'ref') {
|
|
87
|
+
return match;
|
|
88
|
+
}
|
|
89
|
+
let titleInfo = alt;
|
|
90
|
+
if (!titleInfo) {
|
|
91
|
+
titleInfo = 'file|file';
|
|
92
|
+
}
|
|
93
|
+
const titleSplit = titleInfo.split('|');
|
|
94
|
+
const [name = 'file', ext = 'file', password = ''] = titleSplit;
|
|
95
|
+
|
|
96
|
+
return `<div class=" cherry-card cherry-file cherry-card-list-container">
|
|
97
|
+
<a href="链接" target="_blank" class="cherry-card-item cherry-card-row-1" >
|
|
98
|
+
<span class="cherry-card-image material-symbols-outlined" >${getIcon(ext)}</span>
|
|
99
|
+
<div class="cherry-card-body ${password !== '' ? '' : 'cherry-no-desc'}">
|
|
100
|
+
<p class="cherry-card-title">${name}</p>
|
|
101
|
+
${
|
|
102
|
+
password !== ''
|
|
103
|
+
? `<p class="cherry-card-desc" ><span class="material-symbols-outlined" style="margin-right: 5px">lock_open</span> <span>${password}</span></p>`
|
|
104
|
+
: ''
|
|
105
|
+
}
|
|
106
|
+
</div>
|
|
107
|
+
</a>
|
|
108
|
+
</div>`;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default class Image extends SyntaxBase {
|
|
112
|
+
static HOOK_NAME = 'image';
|
|
113
|
+
|
|
114
|
+
constructor({ config, globalConfig }) {
|
|
115
|
+
super(null);
|
|
116
|
+
this.urlProcessor = globalConfig.urlProcessor;
|
|
117
|
+
// TODO: URL Validator
|
|
118
|
+
this.extendMedia = {
|
|
119
|
+
tag: ['video', 'audio', 'file'],
|
|
120
|
+
replacer: {
|
|
121
|
+
video(match, leadingChar, alt, link, title, poster) {
|
|
122
|
+
return replacerFactory('video', match, leadingChar, alt, link, title, poster, config, globalConfig);
|
|
123
|
+
},
|
|
124
|
+
audio(match, leadingChar, alt, link, title, poster) {
|
|
125
|
+
return replacerFactory('audio', match, leadingChar, alt, link, title, poster, config, globalConfig);
|
|
126
|
+
},
|
|
127
|
+
file(match, leadingChar, alt, link, title, poster) {
|
|
128
|
+
return replacerFileFactory(match, leadingChar, alt, link, title, poster, config, globalConfig);
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
this.RULE = this.rule(this.extendMedia);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
toHtml(match, leadingChar, alt, link, title, ref, extendAttrs) {
|
|
136
|
+
// console.log(match, alt, link, ref, title);
|
|
137
|
+
const refType = typeof link === 'undefined' ? 'ref' : 'url';
|
|
138
|
+
let attrs = '';
|
|
139
|
+
if (refType === 'ref') {
|
|
140
|
+
// 全局引用,理应在CommentReference中被替换,没有被替换说明没有定义引用项
|
|
141
|
+
return match;
|
|
142
|
+
}
|
|
143
|
+
if (refType === 'url') {
|
|
144
|
+
const extent = imgAltHelper.processExtendAttributesInAlt(alt);
|
|
145
|
+
let { extendStyles: style, extendClasses: classes } = imgAltHelper.processExtendStyleInAlt(alt);
|
|
146
|
+
if (style) {
|
|
147
|
+
style = ` style="${style}" `;
|
|
148
|
+
}
|
|
149
|
+
if (classes) {
|
|
150
|
+
classes = ` class="${classes}" `;
|
|
151
|
+
}
|
|
152
|
+
attrs = title && title.trim() !== '' ? ` title="${$e(title.replace(/["']/g, ''))}"` : '';
|
|
153
|
+
let srcProp = 'src';
|
|
154
|
+
let srcValue;
|
|
155
|
+
const cherryOptions = this.$engine.$cherry.options;
|
|
156
|
+
if (cherryOptions.callback && cherryOptions.callback.beforeImageMounted) {
|
|
157
|
+
const imgAttrs = cherryOptions.callback.beforeImageMounted(srcProp, link);
|
|
158
|
+
srcProp = imgAttrs.srcProp || srcProp;
|
|
159
|
+
srcValue = imgAttrs.src || link;
|
|
160
|
+
}
|
|
161
|
+
const extendAttrStr = extendAttrs
|
|
162
|
+
? extendAttrs
|
|
163
|
+
.replace(/[{}]/g, '')
|
|
164
|
+
.replace(/([^=\s]+)=([^\s]+)/g, '$1="$2"')
|
|
165
|
+
.replace(/&/g, '&') // 对&多做一次转义,cherry现有的机制会自动把&转成&,只有多做一次转义才能抵消cherry的机制
|
|
166
|
+
: '';
|
|
167
|
+
return `${leadingChar}<img ${srcProp}="${UrlCache.set(
|
|
168
|
+
encodeURIOnce(this.urlProcessor(srcValue, 'image')),
|
|
169
|
+
)}" ${extent} ${style} ${classes} alt="${$e(alt || '')}"${attrs} ${extendAttrStr}/>`;
|
|
170
|
+
}
|
|
171
|
+
// should never happen
|
|
172
|
+
return match;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
toMediaHtml(match, leadingChar, mediaType, alt, link, title, ref, posterWrap, poster, ...args) {
|
|
176
|
+
if (!this.extendMedia.replacer[mediaType]) {
|
|
177
|
+
return match;
|
|
178
|
+
}
|
|
179
|
+
return this.extendMedia.replacer[mediaType].call(this, match, leadingChar, alt, link, title, poster, ...args);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
makeHtml(str) {
|
|
183
|
+
let $str = str;
|
|
184
|
+
if (this.test($str)) {
|
|
185
|
+
if (isLookbehindSupported()) {
|
|
186
|
+
$str = $str.replace(this.RULE.reg, this.toHtml.bind(this));
|
|
187
|
+
} else {
|
|
188
|
+
$str = replaceLookbehind($str, this.RULE.reg, this.toHtml.bind(this), true, 1);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (this.testMedia($str)) {
|
|
192
|
+
if (isLookbehindSupported()) {
|
|
193
|
+
$str = $str.replace(this.RULE.regExtend, this.toMediaHtml.bind(this));
|
|
194
|
+
} else {
|
|
195
|
+
$str = replaceLookbehind($str, this.RULE.regExtend, this.toMediaHtml.bind(this), true, 1);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return $str;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// afterMakeHtml(str) {
|
|
202
|
+
// return UrlCache.restoreAll(str);
|
|
203
|
+
// }
|
|
204
|
+
|
|
205
|
+
testMedia(str) {
|
|
206
|
+
return this.RULE.regExtend && this.RULE.regExtend.test(str);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
rule(extendMedia) {
|
|
210
|
+
const ret = {
|
|
211
|
+
// lookbehind启用分组是为了和不兼容lookbehind的场景共用一个回调
|
|
212
|
+
begin: isLookbehindSupported() ? '((?<!\\\\))!' : '(^|[^\\\\])!',
|
|
213
|
+
content: [
|
|
214
|
+
'\\[([^\\n]*?)\\]', // ?<alt>
|
|
215
|
+
'[ \\t]*', // any spaces
|
|
216
|
+
`${
|
|
217
|
+
'(?:' +
|
|
218
|
+
'\\(' +
|
|
219
|
+
'([^"][^\\s]+?)' + // ?<link> url
|
|
220
|
+
'(?:[ \\t]((?:".*?")|(?:\'.*?\')))?' + // ?<title> optional
|
|
221
|
+
'\\)' +
|
|
222
|
+
'|' + // or
|
|
223
|
+
'\\[('
|
|
224
|
+
}${NOT_ALL_WHITE_SPACES_INLINE})\\]` + // ?<ref> global ref
|
|
225
|
+
')',
|
|
226
|
+
].join(''),
|
|
227
|
+
end: '({[^{}]+?})?', // extend attrs e.g. {width=50 height=60}
|
|
228
|
+
};
|
|
229
|
+
if (extendMedia) {
|
|
230
|
+
const extend = { ...ret };
|
|
231
|
+
// TODO: 支持Lookbehind
|
|
232
|
+
extend.begin = isLookbehindSupported()
|
|
233
|
+
? `((?<!\\\\))!(${extendMedia.tag.join('|')})`
|
|
234
|
+
: `(^|[^\\\\])!(${extendMedia.tag.join('|')})`;
|
|
235
|
+
extend.end = '({poster=(.*)})?';
|
|
236
|
+
ret.regExtend = compileRegExp(extend, 'g');
|
|
237
|
+
}
|
|
238
|
+
ret.reg = compileRegExp(ret, 'g');
|
|
239
|
+
return ret;
|
|
240
|
+
}
|
|
241
|
+
overlayMode() {
|
|
242
|
+
return {
|
|
243
|
+
inImageContainer: false,
|
|
244
|
+
inImageUrl: false,
|
|
245
|
+
name: 'image',
|
|
246
|
+
token(stream, state) {
|
|
247
|
+
// 检查行的开头是否有 ':::'
|
|
248
|
+
|
|
249
|
+
if (stream.match(/!(\w+)?\[.*?]\(.*?\)/)) {
|
|
250
|
+
stream.backUp(stream.current().length); // 回退以单独处理
|
|
251
|
+
this.inImageContainer = true;
|
|
252
|
+
}
|
|
253
|
+
if (this.inImageContainer) {
|
|
254
|
+
if (stream.peek() === '(') {
|
|
255
|
+
this.inImageUrl = true;
|
|
256
|
+
}
|
|
257
|
+
if (this.inImageUrl && stream.peek() === ')') {
|
|
258
|
+
this.inImageUrl = false;
|
|
259
|
+
this.inImageContainer = false;
|
|
260
|
+
}
|
|
261
|
+
if (stream.match('!') && !this.inImageUrl) {
|
|
262
|
+
return 'image-marker';
|
|
263
|
+
}
|
|
264
|
+
if (stream.match(/video|audio|file/) && stream.peek() === '[') {
|
|
265
|
+
return 'image-type';
|
|
266
|
+
}
|
|
267
|
+
if ((stream.match('#') || stream.match('|')) && !this.inImageUrl) {
|
|
268
|
+
return 'image-split';
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
stream.next();
|
|
272
|
+
return null; // 默认返回 null
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
CodeBlock.inlineCodeCache = {};
|
|
36
|
+
}
|
|
37
|
+
return $str;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
rule() {
|
|
41
|
+
const ret = { begin: '(`+)[ ]*', end: '[ ]*\\1', content: '(.+?(?:\\n.+?)*?)' };
|
|
42
|
+
ret.reg = compileRegExp(ret, 'g');
|
|
43
|
+
return ret;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
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 { getTableRule, isLookbehindSupported } from '@/utils/regexp';
|
|
19
|
+
import { replaceLookbehind } from '@/utils/lookbehind-replace';
|
|
20
|
+
import { Theme } from '@/Theme';
|
|
21
|
+
import Event from '../../Event';
|
|
22
|
+
/**
|
|
23
|
+
* 行内公式的语法
|
|
24
|
+
* 虽然叫做行内公式,Cherry依然将其视为"段落级语法",因为其具备排他性并且需要优先渲染
|
|
25
|
+
*/
|
|
26
|
+
export default class InlineMath extends ParagraphBase {
|
|
27
|
+
static HOOK_NAME = 'inlineMath';
|
|
28
|
+
|
|
29
|
+
constructor({ config }) {
|
|
30
|
+
super({ needCache: true });
|
|
31
|
+
// 非浏览器环境下配置为 node
|
|
32
|
+
const { MathJax, apiHost = 'https://math.vercel.app' } = config;
|
|
33
|
+
this.api = !MathJax && !window.MathJax;
|
|
34
|
+
this.apiHost = apiHost;
|
|
35
|
+
this.MathJax = MathJax || window.MathJax;
|
|
36
|
+
if (this.api) {
|
|
37
|
+
const that = this;
|
|
38
|
+
Event.on('Theme', 'change', function ([isDark]) {
|
|
39
|
+
const images = that.$engine.$cherry.wrapperDom.querySelectorAll('img.Cherry-Math-Latex-Inline');
|
|
40
|
+
console.log(images);
|
|
41
|
+
images.forEach(function (item) {
|
|
42
|
+
if (item instanceof HTMLImageElement) {
|
|
43
|
+
item.src = item.src.replace(isDark ? 'color=black' : 'color=white', isDark ? 'color=white' : 'color=black');
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
toHtml(wholeMatch, leadingChar, m1) {
|
|
51
|
+
if (!m1) {
|
|
52
|
+
return wholeMatch;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const linesArr = m1.match(/\n/g);
|
|
56
|
+
const lines = linesArr ? linesArr.length + 2 : 2;
|
|
57
|
+
const sign = this.$engine.md5(wholeMatch);
|
|
58
|
+
|
|
59
|
+
if (this.MathJax?.tex2svg) {
|
|
60
|
+
// MathJax渲染
|
|
61
|
+
const svg = getHTML(this.MathJax.tex2svg(m1, { em: 12, ex: 6, display: false }), true);
|
|
62
|
+
const result = `${leadingChar}<span class="Cherry-InlineMath" data-type="mathBlock" data-lines="${lines}">${svg}</span>`;
|
|
63
|
+
return this.pushCache(result, ParagraphBase.IN_PARAGRAPH_CACHE_KEY_PREFIX + sign);
|
|
64
|
+
}
|
|
65
|
+
const result = `<span class="Cherry-InlineMath " data-type="mathBlock" data-lines="${lines}"><img class="Cherry-Math-Latex-Inline" alt="latex" src="${
|
|
66
|
+
this.apiHost
|
|
67
|
+
}/?from=${encodeURIComponent(m1)}&color=${Theme.isDark() ? 'white' : 'black'}" /></span>`;
|
|
68
|
+
|
|
69
|
+
return this.pushCache(result, ParagraphBase.IN_PARAGRAPH_CACHE_KEY_PREFIX + sign);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
beforeMakeHtml(str) {
|
|
73
|
+
let $str = str;
|
|
74
|
+
// 格里处理行内公式,让一个td里的行内公式语法生效,让跨td的行内公式语法失效
|
|
75
|
+
$str = $str.replace(getTableRule(true), (whole, ...args) => {
|
|
76
|
+
return whole
|
|
77
|
+
.split('|')
|
|
78
|
+
.map((oneTd) => {
|
|
79
|
+
return this.makeInlineMath(oneTd);
|
|
80
|
+
})
|
|
81
|
+
.join('|')
|
|
82
|
+
.replace(/\\~D/g, '~D') // 出现反斜杠的情况(如/$e=m^2$)会导致多一个反斜杠,这里替换掉
|
|
83
|
+
.replace(/~D/g, '\\~D');
|
|
84
|
+
});
|
|
85
|
+
return this.makeInlineMath($str);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
makeInlineMath(str) {
|
|
89
|
+
if (!this.test(str)) {
|
|
90
|
+
return str;
|
|
91
|
+
}
|
|
92
|
+
if (isLookbehindSupported()) {
|
|
93
|
+
return str.replace(this.RULE.reg, this.toHtml.bind(this));
|
|
94
|
+
}
|
|
95
|
+
return replaceLookbehind(str, this.RULE.reg, this.toHtml.bind(this), true, 1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
makeHtml(str) {
|
|
99
|
+
return str;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
rule() {
|
|
103
|
+
const ret = {
|
|
104
|
+
begin: isLookbehindSupported() ? '((?<!\\\\))~D\\n?' : '(^|[^\\\\])~D\\n?',
|
|
105
|
+
content: '(.*?)\\n?',
|
|
106
|
+
end: '~D',
|
|
107
|
+
};
|
|
108
|
+
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
|
|
109
|
+
return ret;
|
|
110
|
+
}
|
|
111
|
+
overlayMode() {
|
|
112
|
+
return {
|
|
113
|
+
name: 'inlineMath',
|
|
114
|
+
inMath: false,
|
|
115
|
+
passLeftKey: false,
|
|
116
|
+
token(stream, state) {
|
|
117
|
+
// 检查行内数学公式
|
|
118
|
+
if (!this.inMath && stream.match(/\$.*?\$/)) {
|
|
119
|
+
this.inMath = true;
|
|
120
|
+
stream.backUp(stream.current().length);
|
|
121
|
+
}
|
|
122
|
+
if (this.inMath) {
|
|
123
|
+
if (stream.match(/\$/)) {
|
|
124
|
+
if (!this.passLeftKey) {
|
|
125
|
+
this.passLeftKey = true;
|
|
126
|
+
} else {
|
|
127
|
+
this.inMath = false;
|
|
128
|
+
this.passLeftKey = false;
|
|
129
|
+
}
|
|
130
|
+
return 'math-container';
|
|
131
|
+
}
|
|
132
|
+
if (stream.match(/.+?\$/)) {
|
|
133
|
+
stream.backUp(1);
|
|
134
|
+
return 'math-text';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
stream.next();
|
|
138
|
+
return null;
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
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 { escapeHTMLSpecialChar as _e, isValidScheme, encodeURIOnce } from '@/utils/sanitize';
|
|
18
|
+
import { compileRegExp, isLookbehindSupported, NOT_ALL_WHITE_SPACES_INLINE } from '@/utils/regexp';
|
|
19
|
+
import { replaceLookbehind } from '@/utils/lookbehind-replace';
|
|
20
|
+
import UrlCache from '@/UrlCache';
|
|
21
|
+
|
|
22
|
+
export default class Link extends SyntaxBase {
|
|
23
|
+
static HOOK_NAME = 'link';
|
|
24
|
+
|
|
25
|
+
constructor({ config, globalConfig }) {
|
|
26
|
+
super({ config });
|
|
27
|
+
this.urlProcessor = globalConfig.urlProcessor;
|
|
28
|
+
// eslint-disable-next-line no-nested-ternary
|
|
29
|
+
this.target = config.target ? `target="${config.target}"` : !!config.openNewPage ? 'target="_blank"' : '';
|
|
30
|
+
this.rel = config.rel ? `rel="${config.rel}"` : '';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 校验link中text的方括号是否符合规则
|
|
35
|
+
* @param {string} rawText
|
|
36
|
+
*/
|
|
37
|
+
checkBrackets(rawText) {
|
|
38
|
+
const stack = [];
|
|
39
|
+
const text = `[${rawText}]`;
|
|
40
|
+
// 前方有奇数个\当前字符被转义
|
|
41
|
+
const checkEscape = (place) => text.slice(0, place).match(/\\*$/)[0].length & 1;
|
|
42
|
+
for (let i = text.length - 1; text[i]; i--) {
|
|
43
|
+
if (i === text.length - 1 && checkEscape(i)) break;
|
|
44
|
+
if (text[i] === ']' && !checkEscape(i)) stack.push(']');
|
|
45
|
+
if (text[i] === '[' && !checkEscape(i)) {
|
|
46
|
+
stack.pop();
|
|
47
|
+
if (!stack.length) {
|
|
48
|
+
return {
|
|
49
|
+
isValid: true,
|
|
50
|
+
coreText: text.slice(i + 1, text.length - 1),
|
|
51
|
+
extraLeadingChar: text.slice(0, i),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
isValid: false, // 方括号匹配不上
|
|
58
|
+
coreText: rawText,
|
|
59
|
+
extraLeadingChar: '',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @param {string} match 匹配的完整字符串
|
|
66
|
+
* @param {string} leadingChar 正则分组一:前置字符
|
|
67
|
+
* @param {string} text 正则分组二:链接文字
|
|
68
|
+
* @param {string|undefined} link 正则分组三:链接URL
|
|
69
|
+
* @param {string|undefined} title 正则分组四:链接title
|
|
70
|
+
* @param {string|undefined} ref 正则分组五:链接引用
|
|
71
|
+
* @param {string|undefined} target 正则分组六:新窗口打开
|
|
72
|
+
* @returns
|
|
73
|
+
*/
|
|
74
|
+
toHtml(match, leadingChar, text, link, title, ref, target) {
|
|
75
|
+
const refType = typeof link === 'undefined' ? 'ref' : 'url';
|
|
76
|
+
let attrs = '';
|
|
77
|
+
if (refType === 'ref') {
|
|
78
|
+
// 全局引用,理应在CommentReference中被替换,没有被替换说明没有定义引用项
|
|
79
|
+
return match;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (refType === 'url') {
|
|
83
|
+
const { isValid, coreText, extraLeadingChar } = this.checkBrackets(text);
|
|
84
|
+
if (!isValid) return match;
|
|
85
|
+
attrs = title && title.trim() !== '' ? ` title="${_e(title.replace(/["']/g, ''))}"` : '';
|
|
86
|
+
if (target) {
|
|
87
|
+
attrs += ` target="${target.replace(/{target\s*=\s*(.*?)}/, '$1')}"`;
|
|
88
|
+
} else {
|
|
89
|
+
// 检查是否为外部链接,非同源时默认使用_blank打开
|
|
90
|
+
const isExternalLink = link.startsWith('http') && !link.startsWith(window.location.origin);
|
|
91
|
+
if (isExternalLink) {
|
|
92
|
+
attrs += ' target="_blank"';
|
|
93
|
+
} else if (this.target) {
|
|
94
|
+
attrs += ` ${this.target}`;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (attrs.includes('_blank')) {
|
|
98
|
+
attrs += ' rel="noopener noreferrer"';
|
|
99
|
+
}
|
|
100
|
+
let processedURL = link.trim().replace(/~1D/g, '~D'); // 还原替换的$符号
|
|
101
|
+
const processedText = coreText.replace(/~1D/g, '~D'); // 还原替换的$符号
|
|
102
|
+
// text可能是html标签,依赖htmlBlock进行处理
|
|
103
|
+
if (isValidScheme(processedURL)) {
|
|
104
|
+
processedURL = this.urlProcessor(processedURL, 'link');
|
|
105
|
+
processedURL = encodeURIOnce(processedURL);
|
|
106
|
+
return `${leadingChar + extraLeadingChar}<a href="${UrlCache.set(processedURL)}" ${
|
|
107
|
+
this.rel
|
|
108
|
+
} ${attrs}>${processedText}</a>`;
|
|
109
|
+
}
|
|
110
|
+
return `${leadingChar + extraLeadingChar}<span>${text}</span>`;
|
|
111
|
+
}
|
|
112
|
+
// should never happen
|
|
113
|
+
return match;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
toStdMarkdown(match) {
|
|
117
|
+
return match;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
makeHtml(str) {
|
|
121
|
+
let $str = str.replace(this.RULE.reg, (match) => {
|
|
122
|
+
return match.replace(/~D/g, '~1D');
|
|
123
|
+
});
|
|
124
|
+
if (isLookbehindSupported()) {
|
|
125
|
+
$str = $str.replace(this.RULE.reg, this.toHtml.bind(this));
|
|
126
|
+
} else {
|
|
127
|
+
$str = replaceLookbehind($str, this.RULE.reg, this.toHtml.bind(this), true, 1);
|
|
128
|
+
}
|
|
129
|
+
$str = $str.replace(this.RULE.reg, (match) => {
|
|
130
|
+
return match.replace(/~1D/g, '~D');
|
|
131
|
+
});
|
|
132
|
+
return $str;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
rule() {
|
|
136
|
+
// (?<protocol>\\w+:)\\/\\/
|
|
137
|
+
const ret = {
|
|
138
|
+
// lookbehind启用分组是为了和不兼容lookbehind的场景共用一个回调
|
|
139
|
+
begin: isLookbehindSupported() ? '((?<!\\\\))' : '(^|[^\\\\])',
|
|
140
|
+
content: [
|
|
141
|
+
'\\[([^\\n]*?)\\]', // ?<text>
|
|
142
|
+
'[ \\t]*', // any spaces
|
|
143
|
+
`${
|
|
144
|
+
'(?:' +
|
|
145
|
+
'\\(' +
|
|
146
|
+
/**
|
|
147
|
+
* allow double quotes
|
|
148
|
+
* e.g.
|
|
149
|
+
* [link](") ⭕️ valid
|
|
150
|
+
* [link]("") ⭕️ valid
|
|
151
|
+
* [link](" ") ❌ invalid
|
|
152
|
+
*/
|
|
153
|
+
'([^\\s)]+)' + // ?<link> url
|
|
154
|
+
'(?:[ \\t]((?:".*?")|(?:\'.*?\')))?' + // ?<title> optional
|
|
155
|
+
'\\)' +
|
|
156
|
+
'|' + // or
|
|
157
|
+
'\\[('
|
|
158
|
+
}${NOT_ALL_WHITE_SPACES_INLINE})\\]` + // ?<ref> global ref
|
|
159
|
+
')',
|
|
160
|
+
'(\\{target\\s*=\\s*(_blank|_parent|_self|_top)\\})?',
|
|
161
|
+
].join(''),
|
|
162
|
+
end: '',
|
|
163
|
+
};
|
|
164
|
+
// let ret = {begin:'((^|[^\\\\])\\*\\*|([\\s]|^)__)',
|
|
165
|
+
// end:'(\\*\\*([\\s\\S]|$)|__([\\s]|$))', content:'([^\\n]+?)'};
|
|
166
|
+
ret.reg = compileRegExp(ret, 'g');
|
|
167
|
+
return ret;
|
|
168
|
+
}
|
|
169
|
+
}
|