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
package/src/utils/dom.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
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
|
+
function mergeMarginBottom(bottom, top) {
|
|
17
|
+
const currentBottom = parseFloat(bottom);
|
|
18
|
+
const nextTop = parseFloat(top);
|
|
19
|
+
if (nextTop >= 0) {
|
|
20
|
+
// 不受合并影响
|
|
21
|
+
return currentBottom;
|
|
22
|
+
}
|
|
23
|
+
if (currentBottom >= 0) {
|
|
24
|
+
return currentBottom + nextTop;
|
|
25
|
+
}
|
|
26
|
+
// 同时为负数,取最小的
|
|
27
|
+
return Math.min(currentBottom, nextTop);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function mergeMarginTop(bottom, top) {
|
|
31
|
+
const prevBottom = parseFloat(bottom);
|
|
32
|
+
const currentTop = parseFloat(top);
|
|
33
|
+
if (currentTop < 0) {
|
|
34
|
+
// 负数的margin都被上一个区块吸收了
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
if (prevBottom >= 0) {
|
|
38
|
+
// 如果当前margin-top比上一个margin-bottom要大,则只合并部分;反之合并全部,归属于上一个区块
|
|
39
|
+
return Math.max(currentTop - prevBottom, 0);
|
|
40
|
+
}
|
|
41
|
+
// 上一个margin-bottom为负数不受影响
|
|
42
|
+
return currentTop;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 用于解决块级元素边距合并问题
|
|
46
|
+
* @param {HTMLElement} element
|
|
47
|
+
*/
|
|
48
|
+
export function getBlockTopAndHeightWithMargin(element) {
|
|
49
|
+
const prevSibling = element.previousElementSibling;
|
|
50
|
+
const nextSibling = element.nextElementSibling;
|
|
51
|
+
if (!prevSibling) {
|
|
52
|
+
const style = getComputedStyle(element);
|
|
53
|
+
const rect = element.getBoundingClientRect();
|
|
54
|
+
if (!nextSibling) {
|
|
55
|
+
return {
|
|
56
|
+
// marginBottom可能为负数
|
|
57
|
+
height: Math.max(parseFloat(style.marginTop) + rect.height + parseFloat(style.marginBottom), 0),
|
|
58
|
+
offsetTop: element.offsetTop - Math.abs(parseFloat(style.marginTop)),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const nextSibStyle = getComputedStyle(nextSibling);
|
|
62
|
+
const marginBottom = mergeMarginBottom(style.marginBottom, nextSibStyle.marginTop);
|
|
63
|
+
return {
|
|
64
|
+
height: Math.max(parseFloat(style.marginTop) + rect.height + marginBottom, 0), // marginBottom可能为负数
|
|
65
|
+
offsetTop: element.offsetTop - Math.abs(parseFloat(style.marginTop)),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const style = getComputedStyle(element);
|
|
69
|
+
const rect = element.getBoundingClientRect();
|
|
70
|
+
const prevSibStyle = getComputedStyle(prevSibling);
|
|
71
|
+
const marginTop = mergeMarginTop(prevSibStyle.marginBottom, style.marginTop);
|
|
72
|
+
if (!nextSibling) {
|
|
73
|
+
return {
|
|
74
|
+
height: Math.max(marginTop + rect.height + parseFloat(style.marginBottom), 0), // marginBottom可能为负数
|
|
75
|
+
offsetTop: element.offsetTop - Math.abs(parseFloat(style.marginTop)),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const nextSibStyle = getComputedStyle(nextSibling);
|
|
79
|
+
const marginBottom = mergeMarginBottom(style.marginBottom, nextSibStyle.marginTop);
|
|
80
|
+
return {
|
|
81
|
+
height: Math.max(marginTop + rect.height + marginBottom, 0), // marginBottom可能为负数
|
|
82
|
+
offsetTop: element.offsetTop - Math.abs(marginTop),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* document.elementsFromPoint polyfill
|
|
88
|
+
* ref: https://github.com/JSmith01/elementsfrompoint-polyfill/blob/master/index.js
|
|
89
|
+
* @param {number} x
|
|
90
|
+
* @param {number} y
|
|
91
|
+
*/
|
|
92
|
+
export function elementsFromPoint(x, y) {
|
|
93
|
+
// see https://caniuse.com/#search=elementsFromPoint
|
|
94
|
+
if (typeof document.elementsFromPoint === 'function') {
|
|
95
|
+
return document.elementsFromPoint(x, y);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (typeof (/** @type {any}*/ (document).msElementsFromPoint) === 'function') {
|
|
99
|
+
const nodeList = /** @type {any}*/ (document).msElementsFromPoint(x, y);
|
|
100
|
+
return nodeList !== null ? Array.from(nodeList) : nodeList;
|
|
101
|
+
}
|
|
102
|
+
const elements = [];
|
|
103
|
+
const pointerEvents = [];
|
|
104
|
+
/** @type {HTMLElement} */
|
|
105
|
+
let ele;
|
|
106
|
+
do {
|
|
107
|
+
const currentElement = /** @type {HTMLElement} */ (document.elementFromPoint(x, y));
|
|
108
|
+
if (ele !== currentElement) {
|
|
109
|
+
ele = currentElement;
|
|
110
|
+
elements.push(ele);
|
|
111
|
+
pointerEvents.push(ele.style.pointerEvents);
|
|
112
|
+
ele.style.pointerEvents = 'none';
|
|
113
|
+
} else {
|
|
114
|
+
ele = null;
|
|
115
|
+
}
|
|
116
|
+
} while (ele);
|
|
117
|
+
elements.forEach((e, index) => {
|
|
118
|
+
e.style.pointerEvents = pointerEvents[index];
|
|
119
|
+
});
|
|
120
|
+
return elements;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function getHTML(who, deep) {
|
|
124
|
+
if (!who || !who.tagName) {
|
|
125
|
+
return '';
|
|
126
|
+
}
|
|
127
|
+
let txt;
|
|
128
|
+
let ax;
|
|
129
|
+
let el = document.createElement('div');
|
|
130
|
+
el.appendChild(who.cloneNode(false));
|
|
131
|
+
txt = el.innerHTML;
|
|
132
|
+
if (deep) {
|
|
133
|
+
ax = txt.indexOf('>') + 1;
|
|
134
|
+
txt = txt.substring(0, ax) + who.innerHTML + txt.substring(ax);
|
|
135
|
+
}
|
|
136
|
+
el = null;
|
|
137
|
+
return txt;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @template {keyof HTMLElementTagNameMap} K
|
|
142
|
+
* @param {K} tagName 标签名
|
|
143
|
+
* @param {string} className 元素类名
|
|
144
|
+
* @param {Record<string,string>} attributes 附加属性
|
|
145
|
+
* @returns {HTMLElementTagNameMap[K]}
|
|
146
|
+
*/
|
|
147
|
+
export function createElement(tagName, className = '', attributes = {}) {
|
|
148
|
+
const element = document.createElement(tagName);
|
|
149
|
+
element.className = className;
|
|
150
|
+
if (typeof attributes !== 'undefined') {
|
|
151
|
+
Object.keys(attributes).forEach((key) => {
|
|
152
|
+
const value = attributes[key];
|
|
153
|
+
if (key.startsWith('data-')) {
|
|
154
|
+
const dataName = key.replace(/^data-/, '');
|
|
155
|
+
element.dataset[dataName] = value;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
element.setAttribute(key, value);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return element;
|
|
162
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
export function downloadByATag(url, fileName) {
|
|
18
|
+
const a = document.createElement('a');
|
|
19
|
+
a.href = url;
|
|
20
|
+
a.download = fileName;
|
|
21
|
+
a.click();
|
|
22
|
+
a.remove();
|
|
23
|
+
}
|
package/src/utils/env.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* 判断当前是否浏览器环境
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
export function isBrowser() {
|
|
21
|
+
return typeof window === 'object';
|
|
22
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* 三个地方的错误异常校验
|
|
18
|
+
* 1. markdown 对象参数校验
|
|
19
|
+
* 2. editText 用户输入校验,执行engine过程以防异常
|
|
20
|
+
* 3. 自定义hook校验 对外开发者开发标准校验
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const $expectTarget = (target, Constructor) => {
|
|
24
|
+
if (
|
|
25
|
+
(!Array.isArray(target) && typeof target !== Constructor.name.toLowerCase()) ||
|
|
26
|
+
(!Array.isArray(target) && Constructor.name.toLowerCase() === 'array')
|
|
27
|
+
) {
|
|
28
|
+
throw new TypeError(`parameter given must be ${Constructor.name}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return true;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const $expectInherit = (target, parent) => {
|
|
35
|
+
if (!(target instanceof parent)) {
|
|
36
|
+
throw new Error('the hook does not correctly inherit');
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const $expectInstance = (target) => {
|
|
42
|
+
if (typeof target !== 'object') {
|
|
43
|
+
throw new Error('the hook must be a instance, not a class');
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// ref: https://github.com/mdlavin/nested-error-stacks
|
|
49
|
+
export default class NestedError extends Error {
|
|
50
|
+
constructor(message, nested) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = 'Error';
|
|
53
|
+
this.stack = this.buildStackTrace(nested);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
buildStackTrace(nested) {
|
|
57
|
+
const stack = nested && nested.stack ? nested.stack : '';
|
|
58
|
+
const newStack = `${this.stack}\nCaused By: ${stack}`;
|
|
59
|
+
return newStack;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export function addEvent(elm, evType, fn, useCapture) {
|
|
17
|
+
if (elm.addEventListener) {
|
|
18
|
+
elm.addEventListener(evType, fn, useCapture); // DOM2.0
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (elm.attachEvent) {
|
|
23
|
+
const r = elm.attachEvent(`on${evType}`, fn); // IE5+
|
|
24
|
+
return r;
|
|
25
|
+
}
|
|
26
|
+
elm[`on${evType}`] = fn; // DOM 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function removeEvent(elm, evType, fn, useCapture) {
|
|
30
|
+
if (elm.removeEventListener) {
|
|
31
|
+
elm.removeEventListener(evType, fn, useCapture); // DOM2.0
|
|
32
|
+
} else if (elm.detachEvent) {
|
|
33
|
+
const r = elm.detachEvent(`on${evType}`, fn); // IE5+
|
|
34
|
+
return r;
|
|
35
|
+
} else {
|
|
36
|
+
elm[`on${evType}`] = null; // DOM 0
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 先把body上的内容隐藏起来
|
|
19
|
+
* @returns {Array} displayList 记录body子元素原始的显隐信息
|
|
20
|
+
*/
|
|
21
|
+
const hideBodyChildren = () => {
|
|
22
|
+
const displayList = [];
|
|
23
|
+
/** @type {HTMLElement[]}*/ (Array.from(document.body.children)).forEach((dom, index) => {
|
|
24
|
+
displayList[index] = dom.style.display;
|
|
25
|
+
dom.style.display = 'none';
|
|
26
|
+
});
|
|
27
|
+
return displayList;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 复原body上被隐藏的内容
|
|
32
|
+
* @param {Array} displayList 记录body子元素原始的显隐信息
|
|
33
|
+
*/
|
|
34
|
+
const undoHideBodyChildren = (displayList = []) => {
|
|
35
|
+
/** @type {HTMLElement[]}*/ (Array.from(document.body.children)).forEach((dom, index) => {
|
|
36
|
+
if (typeof displayList[index] !== 'undefined') {
|
|
37
|
+
dom.style.display = displayList[index];
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 将预览区域的内容放在body上准备后续导出操作
|
|
44
|
+
* @param {HTMLElement} previewDom 预览区域的dom
|
|
45
|
+
* @param {function} cb 准备好导出后开始执行导出操作
|
|
46
|
+
*/
|
|
47
|
+
const getReadyToExport = (previewDom, cb) => {
|
|
48
|
+
const cherryPreviewer = /** @type {HTMLElement}*/ (previewDom.cloneNode(true));
|
|
49
|
+
// 强制去掉预览区的隐藏class
|
|
50
|
+
cherryPreviewer.className = cherryPreviewer.className.replace('cherry-previewer--hidden', '');
|
|
51
|
+
cherryPreviewer.style.width = '100%';
|
|
52
|
+
const mmls = cherryPreviewer.querySelectorAll('mjx-assistive-mml');
|
|
53
|
+
// a fix for html2canvas
|
|
54
|
+
mmls.forEach((e) => {
|
|
55
|
+
if (e instanceof HTMLElement) e.style.setProperty('visibility', 'hidden');
|
|
56
|
+
});
|
|
57
|
+
const cherryWrapper = document.createElement('div');
|
|
58
|
+
cherryWrapper.appendChild(cherryPreviewer);
|
|
59
|
+
const displayList = hideBodyChildren();
|
|
60
|
+
document.body.appendChild(cherryWrapper);
|
|
61
|
+
const bodyOverflow = document.body.style.overflow;
|
|
62
|
+
document.body.style.overflow = 'visible';
|
|
63
|
+
cb(cherryPreviewer, () => {
|
|
64
|
+
cherryWrapper.remove();
|
|
65
|
+
undoHideBodyChildren(displayList);
|
|
66
|
+
document.body.style.overflow = bodyOverflow;
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 利用window.print导出成PDF
|
|
72
|
+
* @param {HTMLElement} previewDom 预览区域的dom
|
|
73
|
+
* @param {String} fileName 导出PDF文件名
|
|
74
|
+
*/
|
|
75
|
+
export function exportPDF(previewDom, fileName) {
|
|
76
|
+
const oldTitle = document.title;
|
|
77
|
+
document.title = fileName;
|
|
78
|
+
getReadyToExport(previewDom, (/** @type {HTMLElement}*/ cherryPreviewer, /** @type {function}*/ thenFinish) => {
|
|
79
|
+
window.print();
|
|
80
|
+
thenFinish();
|
|
81
|
+
document.title = oldTitle;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 导出 markdown 文件
|
|
87
|
+
* @param {String} markdownText markdown文本
|
|
88
|
+
* @param {String} fileName 导出markdown文件名
|
|
89
|
+
*/
|
|
90
|
+
export function exportMarkdownFile(markdownText, fileName) {
|
|
91
|
+
const blob = new Blob([markdownText], { type: 'text/markdown;charset=utf-8' });
|
|
92
|
+
const aLink = document.createElement('a');
|
|
93
|
+
aLink.style.display = 'none';
|
|
94
|
+
aLink.href = URL.createObjectURL(blob);
|
|
95
|
+
aLink.download = `${fileName}.md`;
|
|
96
|
+
document.body.appendChild(aLink);
|
|
97
|
+
aLink.click();
|
|
98
|
+
document.body.removeChild(aLink);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 导出预览区 HTML 文件
|
|
103
|
+
* @param {String} HTMLText HTML文本
|
|
104
|
+
* @param {String} fileName 导出HTML文件名
|
|
105
|
+
*/
|
|
106
|
+
export function exportHTMLFile(HTMLText, fileName) {
|
|
107
|
+
const blob = new Blob([HTMLText], { type: 'text/markdown;charset=utf-8' });
|
|
108
|
+
const aLink = document.createElement('a');
|
|
109
|
+
aLink.style.display = 'none';
|
|
110
|
+
aLink.href = URL.createObjectURL(blob);
|
|
111
|
+
aLink.download = `${fileName}.html`;
|
|
112
|
+
document.body.appendChild(aLink);
|
|
113
|
+
aLink.click();
|
|
114
|
+
document.body.removeChild(aLink);
|
|
115
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export function splitFileName(filename) {
|
|
17
|
+
// 使用正则表达式匹配文件名和扩展名
|
|
18
|
+
const result = /^(.+?)(\.[^.]*$|$)/.exec(filename);
|
|
19
|
+
|
|
20
|
+
// 如果没有扩展名,返回原始文件名
|
|
21
|
+
if (!result) return { title: filename, ext: null };
|
|
22
|
+
|
|
23
|
+
// 返回文件名和扩展名
|
|
24
|
+
return { title: result[1], ext: result[2] ? result[2].substring(1) : null };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 上传文件的逻辑,如果有callback,则不再走默认的替换文本的逻辑,而是调用callback
|
|
28
|
+
* @param {string} type 上传文件的类型
|
|
29
|
+
*/
|
|
30
|
+
export function handleUpload(editor, type = 'image', accept = '*', callback = null) {
|
|
31
|
+
// type为上传文件类型 image|video|audio|pdf|word
|
|
32
|
+
const input = document.createElement('input');
|
|
33
|
+
input.type = 'file';
|
|
34
|
+
input.id = 'fileUpload';
|
|
35
|
+
input.value = '';
|
|
36
|
+
input.style.display = 'none';
|
|
37
|
+
input.accept = accept;
|
|
38
|
+
// document.body.appendChild(input);
|
|
39
|
+
input.addEventListener('change', (event) => {
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
const [file] = event.target.files;
|
|
42
|
+
// 文件上传后的回调函数可以由调用方自己实现
|
|
43
|
+
editor.options.fileUpload(file, (url, params = {}) => {
|
|
44
|
+
// 文件上传的默认回调行数,调用方可以完全不使用该函数
|
|
45
|
+
if (typeof url !== 'string' || !url) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (callback) {
|
|
49
|
+
return callback(file.name, url, params);
|
|
50
|
+
}
|
|
51
|
+
let code = '';
|
|
52
|
+
if (type === 'image') {
|
|
53
|
+
// 如果是图片,则返回固定的图片markdown源码
|
|
54
|
+
code = ``;
|
|
55
|
+
} else if (type === 'video') {
|
|
56
|
+
// 如果是视频,则返回固定的视频markdown源码
|
|
57
|
+
code = `!video[${file.name}](${url})`;
|
|
58
|
+
} else if (type === 'audio') {
|
|
59
|
+
// 如果是音频,则返回固定的音频markdown源码
|
|
60
|
+
code = `!audio[${file.name}](${url})`;
|
|
61
|
+
} else {
|
|
62
|
+
const { title, ext } = splitFileName(file.name);
|
|
63
|
+
// 默认返回超链接
|
|
64
|
+
code = `!file[${title}|${ext}](${url})`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 替换选中区域
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
editor.editor.doc.replaceSelection(code);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
input.click();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 解析params参数
|
|
77
|
+
* @param params
|
|
78
|
+
*/
|
|
79
|
+
export function handleParams(params) {
|
|
80
|
+
const ret = [];
|
|
81
|
+
if (params?.isBorder) {
|
|
82
|
+
ret.push('#B');
|
|
83
|
+
}
|
|
84
|
+
if (params?.isShadow) {
|
|
85
|
+
ret.push('#S');
|
|
86
|
+
}
|
|
87
|
+
if (params?.isRadius) {
|
|
88
|
+
ret.push('#R');
|
|
89
|
+
}
|
|
90
|
+
if (params?.width) {
|
|
91
|
+
ret.push(`#${params.width}`);
|
|
92
|
+
}
|
|
93
|
+
if (params?.height) {
|
|
94
|
+
if (!params.width) {
|
|
95
|
+
ret.push('#auto');
|
|
96
|
+
}
|
|
97
|
+
ret.push(`#${params.height}`);
|
|
98
|
+
}
|
|
99
|
+
return ret.join(' ');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function handleFileUploadCallback(url, params, file) {
|
|
103
|
+
const name = params?.name ?? file.name;
|
|
104
|
+
let type = '';
|
|
105
|
+
let poster = '';
|
|
106
|
+
if (/video/i.test(file.type)) {
|
|
107
|
+
type = '!video';
|
|
108
|
+
poster = params?.poster ? `{poster=${params.poster}}` : '';
|
|
109
|
+
}
|
|
110
|
+
if (/audio/i.test(file.type)) {
|
|
111
|
+
type = '!audio';
|
|
112
|
+
}
|
|
113
|
+
if (/image/i.test(file.type)) {
|
|
114
|
+
type = '!';
|
|
115
|
+
}
|
|
116
|
+
if (/file/i.test(file.type)) {
|
|
117
|
+
type = '!file';
|
|
118
|
+
}
|
|
119
|
+
const style = type ? handleParams(params) : '';
|
|
120
|
+
return `${type}[${name}${style}](${url})${poster}`;
|
|
121
|
+
}
|