vditor 3.8.4 → 3.8.8
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/CHANGELOG.md +45 -8
- package/README.md +49 -46
- package/dist/css/content-theme/ant-design.css +185 -1
- package/dist/css/content-theme/dark.css +98 -1
- package/dist/css/content-theme/light.css +76 -1
- package/dist/css/content-theme/wechat.css +69 -1
- package/dist/index.css +10 -8
- package/dist/index.d.ts +5 -1
- package/dist/index.min.js +15433 -8
- package/dist/js/.DS_Store +0 -0
- package/dist/js/highlight.js/highlight.pack.js +1617 -2
- package/dist/js/highlight.js/styles/abap.css +155 -1
- package/dist/js/highlight.js/styles/algol.css +142 -1
- package/dist/js/highlight.js/styles/algol_nu.css +90 -1
- package/dist/js/highlight.js/styles/ant-design.css +469 -1
- package/dist/js/highlight.js/styles/arduino.css +155 -1
- package/dist/js/highlight.js/styles/autumn.css +136 -1
- package/dist/js/highlight.js/styles/borland.css +146 -1
- package/dist/js/highlight.js/styles/bw.css +149 -1
- package/dist/js/highlight.js/styles/colorful.css +156 -1
- package/dist/js/highlight.js/styles/dracula.css +139 -1
- package/dist/js/highlight.js/styles/emacs.css +166 -1
- package/dist/js/highlight.js/styles/friendly.css +182 -1
- package/dist/js/highlight.js/styles/fruity.css +121 -1
- package/dist/js/highlight.js/styles/github.css +173 -1
- package/dist/js/highlight.js/styles/igor.css +122 -1
- package/dist/js/highlight.js/styles/lovelace.css +145 -1
- package/dist/js/highlight.js/styles/manni.css +138 -1
- package/dist/js/highlight.js/styles/monokai.css +131 -1
- package/dist/js/highlight.js/styles/monokailight.css +179 -1
- package/dist/js/highlight.js/styles/murphy.css +144 -1
- package/dist/js/highlight.js/styles/native.css +163 -1
- package/dist/js/highlight.js/styles/paraiso-dark.css +136 -1
- package/dist/js/highlight.js/styles/paraiso-light.css +135 -1
- package/dist/js/highlight.js/styles/pastie.css +180 -1
- package/dist/js/highlight.js/styles/perldoc.css +140 -1
- package/dist/js/highlight.js/styles/pygments.css +158 -1
- package/dist/js/highlight.js/styles/rainbow_dash.css +163 -1
- package/dist/js/highlight.js/styles/rrt.css +158 -1
- package/dist/js/highlight.js/styles/solarized-dark.css +145 -1
- package/dist/js/highlight.js/styles/solarized-dark256.css +145 -1
- package/dist/js/highlight.js/styles/solarized-light.css +162 -1
- package/dist/js/highlight.js/styles/swapoff.css +144 -1
- package/dist/js/highlight.js/styles/tango.css +183 -1
- package/dist/js/highlight.js/styles/trac.css +166 -1
- package/dist/js/highlight.js/styles/vim.css +143 -1
- package/dist/js/highlight.js/styles/vs.css +112 -1
- package/dist/js/highlight.js/styles/xcode.css +173 -1
- package/dist/js/i18n/en_US.js +85 -0
- package/dist/js/i18n/ja_JP.js +85 -0
- package/dist/js/i18n/ko_KR.js +85 -0
- package/dist/js/i18n/ru_RU.js +85 -0
- package/dist/js/i18n/zh_CN.js +85 -0
- package/dist/js/i18n/zh_TW.js +85 -0
- package/dist/js/katex/katex.min.css +1 -1
- package/dist/js/lute/lute.min.js +31 -28
- package/dist/js/mathjax/.DS_Store +0 -0
- package/dist/js/mathjax/input/tex/extensions/{colorv2.js → colorV2.js} +0 -0
- package/dist/js/mathjax/input/tex/extensions/{configmacros.js → configMacros.js} +0 -0
- package/dist/js/mathjax/input/tex/extensions/{tagformat.js → tagFormat.js} +0 -0
- package/dist/js/mathjax/tex-svg-full.js +1 -0
- package/dist/method.d.ts +6 -3
- package/dist/method.min.js +2334 -8
- package/dist/ts/markdown/adapterRender.d.ts +33 -0
- package/dist/ts/markdown/codeRender.d.ts +1 -2
- package/dist/ts/ui/initUI.d.ts +1 -0
- package/dist/ts/wysiwyg/index.d.ts +2 -0
- package/dist/types/index.d.ts +105 -8
- package/package.json +23 -24
- package/src/assets/.DS_Store +0 -0
- package/src/assets/scss/_content.scss +4 -0
- package/src/assets/scss/_reset.scss +11 -0
- package/src/index.ts +159 -99
- package/src/method.ts +6 -2
- package/src/ts/.DS_Store +0 -0
- package/src/ts/constants.ts +8 -4
- package/src/ts/export/index.ts +7 -5
- package/src/ts/hint/index.ts +20 -11
- package/src/ts/markdown/abcRender.ts +3 -2
- package/src/ts/markdown/adapterRender.ts +33 -0
- package/src/ts/markdown/chartRender.ts +3 -2
- package/src/ts/markdown/codeRender.ts +5 -6
- package/src/ts/markdown/flowchartRender.ts +3 -2
- package/src/ts/markdown/graphvizRender.ts +13 -11
- package/src/ts/markdown/highlightRender.ts +3 -3
- package/src/ts/markdown/mathRender.ts +6 -5
- package/src/ts/markdown/mermaidRender.ts +4 -2
- package/src/ts/markdown/mindmapRender.ts +3 -2
- package/src/ts/markdown/plantumlRender.ts +3 -2
- package/src/ts/markdown/previewRender.ts +26 -4
- package/src/ts/preview/image.ts +2 -4
- package/src/ts/preview/index.ts +2 -5
- package/src/ts/toolbar/EditMode.ts +3 -4
- package/src/ts/toolbar/Headings.ts +6 -6
- package/src/ts/toolbar/Info.ts +1 -1
- package/src/ts/toolbar/MenuItem.ts +1 -3
- package/src/ts/toolbar/Record.ts +3 -4
- package/src/ts/ui/initUI.ts +19 -5
- package/src/ts/undo/index.ts +5 -5
- package/src/ts/upload/index.ts +8 -8
- package/src/ts/util/Options.ts +255 -196
- package/src/ts/util/editorCommonEvent.ts +2 -2
- package/src/ts/util/fixBrowserBehavior.ts +10 -6
- package/src/ts/util/processCode.ts +1 -1
- package/src/ts/wysiwyg/highlightToolbarWYSIWYG.ts +298 -138
- package/src/ts/wysiwyg/index.ts +9 -4
- package/dist/js/mathjax/input/.DS_Store +0 -0
- package/dist/js/mathjax/tex-svg.js +0 -1
- package/dist/ts/i18n/index.d.ts +0 -2
- package/src/ts/i18n/index.ts +0 -318
|
@@ -1,42 +1,44 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
2
|
import {addScript} from "../util/addScript";
|
|
3
|
+
import {graphvizRenderAdapter} from "./adapterRender";
|
|
3
4
|
|
|
4
5
|
declare class Viz {
|
|
5
6
|
public renderSVGElement: (code: string) => Promise<any>;
|
|
6
7
|
|
|
7
|
-
constructor({}: { worker: Worker });
|
|
8
|
+
constructor({ }: { worker: Worker });
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export const graphvizRender = (element: HTMLElement, cdn = Constants.CDN) => {
|
|
11
|
-
const graphvizElements =
|
|
12
|
+
const graphvizElements = graphvizRenderAdapter.getElements(element);
|
|
12
13
|
|
|
13
14
|
if (graphvizElements.length === 0) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
17
|
addScript(`${cdn}/dist/js/graphviz/viz.js`, "vditorGraphVizScript").then(() => {
|
|
17
18
|
graphvizElements.forEach((e: HTMLDivElement) => {
|
|
19
|
+
const code = graphvizRenderAdapter.getCode(e);
|
|
18
20
|
if (e.parentElement.classList.contains("vditor-wysiwyg__pre") ||
|
|
19
21
|
e.parentElement.classList.contains("vditor-ir__marker--pre")) {
|
|
20
22
|
return;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
if (e.getAttribute("data-processed") === "true" ||
|
|
25
|
+
if (e.getAttribute("data-processed") === "true" || code.trim() === "") {
|
|
24
26
|
return;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
try {
|
|
28
30
|
const blob = new Blob([`importScripts('${(document.getElementById("vditorGraphVizScript") as HTMLScriptElement).src.replace("viz.js", "full.render.js")}');`],
|
|
29
|
-
{type: "application/javascript"});
|
|
31
|
+
{ type: "application/javascript" });
|
|
30
32
|
const url = window.URL || window.webkitURL;
|
|
31
33
|
const blobUrl = url.createObjectURL(blob);
|
|
32
34
|
const worker = new Worker(blobUrl);
|
|
33
|
-
new Viz({worker})
|
|
34
|
-
.renderSVGElement(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
new Viz({ worker })
|
|
36
|
+
.renderSVGElement(code).then((result: HTMLElement) => {
|
|
37
|
+
e.innerHTML = result.outerHTML;
|
|
38
|
+
}).catch((error) => {
|
|
39
|
+
e.innerHTML = `graphviz render error: <br>${error}`;
|
|
40
|
+
e.className = "vditor-reset--error";
|
|
41
|
+
});
|
|
40
42
|
} catch (e) {
|
|
41
43
|
console.error("graphviz error", e);
|
|
42
44
|
}
|
|
@@ -3,7 +3,7 @@ import {addScript} from "../util/addScript";
|
|
|
3
3
|
import {addStyle} from "../util/addStyle";
|
|
4
4
|
|
|
5
5
|
declare const hljs: {
|
|
6
|
-
|
|
6
|
+
highlightElement(element: Element): void;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export const highlightRender = (hljsOption?: IHljs, element: HTMLElement | Document = document,
|
|
@@ -36,14 +36,14 @@ export const highlightRender = (hljsOption?: IHljs, element: HTMLElement | Docum
|
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
if (block.classList.contains("language-mermaid") || block.classList.contains("language-
|
|
39
|
+
if (block.classList.contains("language-mermaid") || block.classList.contains("language-flowchart") ||
|
|
40
40
|
block.classList.contains("language-echarts") || block.classList.contains("language-mindmap") ||
|
|
41
41
|
block.classList.contains("language-plantuml") ||
|
|
42
42
|
block.classList.contains("language-abc") || block.classList.contains("language-graphviz") ||
|
|
43
43
|
block.classList.contains("language-math")) {
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
hljs.
|
|
46
|
+
hljs.highlightElement(block);
|
|
47
47
|
|
|
48
48
|
if (!hljsOption.lineNumber) {
|
|
49
49
|
return;
|
|
@@ -2,6 +2,7 @@ import {Constants} from "../constants";
|
|
|
2
2
|
import {addScript, addScriptSync} from "../util/addScript";
|
|
3
3
|
import {addStyle} from "../util/addStyle";
|
|
4
4
|
import {code160to32} from "../util/code160to32";
|
|
5
|
+
import {mathRenderAdapter} from "./adapterRender";
|
|
5
6
|
|
|
6
7
|
declare const katex: {
|
|
7
8
|
renderToString(math: string, option: {
|
|
@@ -17,7 +18,7 @@ declare global {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export const mathRender = (element: HTMLElement, options?: { cdn?: string, math?: IMath }) => {
|
|
20
|
-
const mathElements =
|
|
21
|
+
const mathElements = mathRenderAdapter.getElements(element);
|
|
21
22
|
|
|
22
23
|
if (mathElements.length === 0) {
|
|
23
24
|
return;
|
|
@@ -49,7 +50,7 @@ export const mathRender = (element: HTMLElement, options?: { cdn?: string, math?
|
|
|
49
50
|
if (mathElement.getAttribute("data-math")) {
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
|
-
const math = code160to32(mathElement
|
|
53
|
+
const math = code160to32(mathRenderAdapter.getCode(mathElement));
|
|
53
54
|
mathElement.setAttribute("data-math", math);
|
|
54
55
|
try {
|
|
55
56
|
mathElement.innerHTML = katex.renderToString(math, {
|
|
@@ -87,7 +88,7 @@ export const mathRender = (element: HTMLElement, options?: { cdn?: string, math?
|
|
|
87
88
|
if (!window.MathJax) {
|
|
88
89
|
window.MathJax = {
|
|
89
90
|
loader: {
|
|
90
|
-
paths: {mathjax: `${options.cdn}/dist/js/mathjax`},
|
|
91
|
+
paths: { mathjax: `${options.cdn}/dist/js/mathjax` },
|
|
91
92
|
},
|
|
92
93
|
startup: {
|
|
93
94
|
typeset: false,
|
|
@@ -98,7 +99,7 @@ export const mathRender = (element: HTMLElement, options?: { cdn?: string, math?
|
|
|
98
99
|
};
|
|
99
100
|
}
|
|
100
101
|
// 循环加载会抛异常
|
|
101
|
-
addScriptSync(`${options.cdn}/dist/js/mathjax/tex-svg.js`, "
|
|
102
|
+
addScriptSync(`${options.cdn}/dist/js/mathjax/tex-svg-full.js`, "protyleMathJaxScript");
|
|
102
103
|
const renderMath = (mathElement: Element, next?: () => void) => {
|
|
103
104
|
const math = code160to32(mathElement.textContent).trim();
|
|
104
105
|
const mathOptions = window.MathJax.getMetricsFor(mathElement);
|
|
@@ -120,7 +121,7 @@ export const mathRender = (element: HTMLElement, options?: { cdn?: string, math?
|
|
|
120
121
|
});
|
|
121
122
|
};
|
|
122
123
|
window.MathJax.startup.promise.then(() => {
|
|
123
|
-
const chains: any
|
|
124
|
+
const chains: any[] = [];
|
|
124
125
|
for (let i = 0; i < mathElements.length; i++) {
|
|
125
126
|
const mathElement = mathElements[i];
|
|
126
127
|
if (!mathElement.parentElement.classList.contains("vditor-wysiwyg__pre") &&
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
2
|
import {addScript} from "../util/addScript";
|
|
3
|
+
import {mermaidRenderAdapter} from "./adapterRender";
|
|
3
4
|
|
|
4
5
|
declare const mermaid: {
|
|
5
6
|
initialize(options: any): void,
|
|
@@ -7,7 +8,7 @@ declare const mermaid: {
|
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
export const mermaidRender = (element: HTMLElement, cdn = Constants.CDN, theme: string) => {
|
|
10
|
-
const mermaidElements =
|
|
11
|
+
const mermaidElements = mermaidRenderAdapter.getElements(element);
|
|
11
12
|
if (mermaidElements.length === 0) {
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
@@ -115,7 +116,8 @@ export const mermaidRender = (element: HTMLElement, cdn = Constants.CDN, theme:
|
|
|
115
116
|
}
|
|
116
117
|
mermaid.initialize(config);
|
|
117
118
|
mermaidElements.forEach((item) => {
|
|
118
|
-
|
|
119
|
+
const code = mermaidRenderAdapter.getCode(item);
|
|
120
|
+
if (item.getAttribute("data-processed") === "true" || code.trim() === "") {
|
|
119
121
|
return;
|
|
120
122
|
}
|
|
121
123
|
mermaid.init(undefined, item);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
2
|
import {addScript} from "../util/addScript";
|
|
3
|
+
import {mindmapRenderAdapter} from "./adapterRender";
|
|
3
4
|
|
|
4
5
|
declare const echarts: {
|
|
5
6
|
init(element: HTMLElement, theme?: string): IEChart;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
export const mindmapRender = (element: (HTMLElement | Document) = document, cdn = Constants.CDN, theme: string) => {
|
|
9
|
-
const mindmapElements =
|
|
10
|
+
const mindmapElements = mindmapRenderAdapter.getElements(element);
|
|
10
11
|
if (mindmapElements.length > 0) {
|
|
11
12
|
addScript(`${cdn}/dist/js/echarts/echarts.min.js`, "vditorEchartsScript").then(() => {
|
|
12
13
|
mindmapElements.forEach((e: HTMLDivElement) => {
|
|
@@ -14,7 +15,7 @@ export const mindmapRender = (element: (HTMLElement | Document) = document, cdn
|
|
|
14
15
|
e.parentElement.classList.contains("vditor-ir__marker--pre")) {
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
17
|
-
const text =
|
|
18
|
+
const text = mindmapRenderAdapter.getCode(e);
|
|
18
19
|
if (!text) {
|
|
19
20
|
return;
|
|
20
21
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
2
|
import {addScript} from "../util/addScript";
|
|
3
|
+
import {plantumlRenderAdapter} from "./adapterRender";
|
|
3
4
|
|
|
4
5
|
declare const plantumlEncoder: {
|
|
5
6
|
encode(options: string): string,
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
export const plantumlRender = (element: (HTMLElement | Document) = document, cdn = Constants.CDN) => {
|
|
9
|
-
const plantumlElements =
|
|
10
|
+
const plantumlElements = plantumlRenderAdapter.getElements(element);
|
|
10
11
|
if (plantumlElements.length === 0) {
|
|
11
12
|
return;
|
|
12
13
|
}
|
|
@@ -16,7 +17,7 @@ export const plantumlRender = (element: (HTMLElement | Document) = document, cdn
|
|
|
16
17
|
e.parentElement.classList.contains("vditor-ir__marker--pre")) {
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
19
|
-
const text = e.
|
|
20
|
+
const text = plantumlRenderAdapter.getCode(e).trim();
|
|
20
21
|
if (!text) {
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
2
|
import {setContentTheme} from "../ui/setContentTheme";
|
|
3
|
-
import {addScript} from "../util/addScript";
|
|
3
|
+
import {addScript, addScriptSync} from "../util/addScript";
|
|
4
4
|
import {hasClosestByClassName, hasClosestByMatchTag} from "../util/hasClosest";
|
|
5
5
|
import {merge} from "../util/merge";
|
|
6
6
|
import {abcRender} from "./abcRender";
|
|
@@ -24,7 +24,9 @@ const mergeOptions = (options?: IPreviewOptions) => {
|
|
|
24
24
|
anchor: 0,
|
|
25
25
|
cdn: Constants.CDN,
|
|
26
26
|
customEmoji: {},
|
|
27
|
-
emojiPath: `${
|
|
27
|
+
emojiPath: `${
|
|
28
|
+
(options && options.emojiPath) || Constants.CDN
|
|
29
|
+
}/dist/images/emoji`,
|
|
28
30
|
hljs: Constants.HLJS_OPTIONS,
|
|
29
31
|
icon: "ant",
|
|
30
32
|
lang: "zh_CN",
|
|
@@ -81,11 +83,31 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st
|
|
|
81
83
|
}
|
|
82
84
|
previewElement.innerHTML = html;
|
|
83
85
|
previewElement.classList.add("vditor-reset");
|
|
86
|
+
|
|
87
|
+
if (!mergedOptions.i18n) {
|
|
88
|
+
if (!["en_US", "ja_JP", "ko_KR", "ru_RU", "zh_CN", "zh_TW"].includes(mergedOptions.lang)) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
"options.lang error, see https://ld246.com/article/1549638745630#options",
|
|
91
|
+
);
|
|
92
|
+
} else {
|
|
93
|
+
const i18nScriptPrefix = "vditorI18nScript";
|
|
94
|
+
const i18nScriptID = i18nScriptPrefix + mergedOptions.lang;
|
|
95
|
+
document.querySelectorAll(`head script[id^="${i18nScriptPrefix}"]`).forEach((el) => {
|
|
96
|
+
if (el.id !== i18nScriptID) {
|
|
97
|
+
document.head.removeChild(el);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
addScript(`${mergedOptions.cdn}/dist/js/i18n/${mergedOptions.lang}.js`, i18nScriptID);
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
window.VditorI18n = mergedOptions.i18n;
|
|
104
|
+
}
|
|
105
|
+
|
|
84
106
|
setContentTheme(mergedOptions.theme.current, mergedOptions.theme.path);
|
|
85
107
|
if (mergedOptions.anchor === 1) {
|
|
86
108
|
previewElement.classList.add("vditor-reset--anchor");
|
|
87
109
|
}
|
|
88
|
-
codeRender(previewElement
|
|
110
|
+
codeRender(previewElement);
|
|
89
111
|
highlightRender(mergedOptions.hljs, previewElement, mergedOptions.cdn);
|
|
90
112
|
mathRender(previewElement, {
|
|
91
113
|
cdn: mergedOptions.cdn,
|
|
@@ -100,7 +122,7 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st
|
|
|
100
122
|
abcRender(previewElement, mergedOptions.cdn);
|
|
101
123
|
mediaRender(previewElement);
|
|
102
124
|
if (mergedOptions.speech.enable) {
|
|
103
|
-
speechRender(previewElement
|
|
125
|
+
speechRender(previewElement);
|
|
104
126
|
}
|
|
105
127
|
if (mergedOptions.anchor !== 0) {
|
|
106
128
|
anchorRender(mergedOptions.anchor);
|
package/src/ts/preview/image.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import {i18n} from "../i18n";
|
|
2
|
-
|
|
3
1
|
export const previewImage = (oldImgElement: HTMLImageElement, lang: keyof II18n = "zh_CN", theme = "classic") => {
|
|
4
2
|
const oldImgRect = oldImgElement.getBoundingClientRect();
|
|
5
3
|
const height = 36;
|
|
@@ -7,10 +5,10 @@ export const previewImage = (oldImgElement: HTMLImageElement, lang: keyof II18n
|
|
|
7
5
|
<div class="vditor-img__bar">
|
|
8
6
|
<span class="vditor-img__btn" data-deg="0">
|
|
9
7
|
<svg><use xlink:href="#vditor-icon-redo"></use></svg>
|
|
10
|
-
${
|
|
8
|
+
${window.VditorI18n.spin}
|
|
11
9
|
</span>
|
|
12
10
|
<span class="vditor-img__btn" onclick="this.parentElement.parentElement.outerHTML = '';document.body.style.overflow = ''">
|
|
13
|
-
X ${
|
|
11
|
+
X ${window.VditorI18n.close}
|
|
14
12
|
</span>
|
|
15
13
|
</div>
|
|
16
14
|
<div class="vditor-img__img" onclick="this.parentElement.outerHTML = '';document.body.style.overflow = ''">
|
package/src/ts/preview/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {i18n} from "../i18n/index";
|
|
2
1
|
import {abcRender} from "../markdown/abcRender";
|
|
3
2
|
import {chartRender} from "../markdown/chartRender";
|
|
4
3
|
import {codeRender} from "../markdown/codeRender";
|
|
@@ -24,7 +23,6 @@ export class Preview {
|
|
|
24
23
|
constructor(vditor: IVditor) {
|
|
25
24
|
this.element = document.createElement("div");
|
|
26
25
|
this.element.className = `vditor-preview`;
|
|
27
|
-
|
|
28
26
|
const previewElement = document.createElement("div");
|
|
29
27
|
previewElement.className = "vditor-reset";
|
|
30
28
|
if (vditor.options.classes.preview) {
|
|
@@ -199,8 +197,7 @@ export class Preview {
|
|
|
199
197
|
const time = (new Date().getTime() - startTime);
|
|
200
198
|
if ((new Date().getTime() - startTime) > 2600) {
|
|
201
199
|
// https://github.com/b3log/vditor/issues/67
|
|
202
|
-
vditor.tip.show(
|
|
203
|
-
time.toString()));
|
|
200
|
+
vditor.tip.show(window.VditorI18n.performanceTip.replace("${x}", time.toString()));
|
|
204
201
|
vditor.preview.element.setAttribute("data-type", "renderPerformance");
|
|
205
202
|
} else if (vditor.preview.element.getAttribute("data-type") === "renderPerformance") {
|
|
206
203
|
vditor.tip.hide();
|
|
@@ -210,7 +207,7 @@ export class Preview {
|
|
|
210
207
|
if (cmtFocusElement) {
|
|
211
208
|
cmtFocusElement.classList.remove("vditor-comment--focus");
|
|
212
209
|
}
|
|
213
|
-
codeRender(vditor.preview.element.lastElementChild as HTMLElement
|
|
210
|
+
codeRender(vditor.preview.element.lastElementChild as HTMLElement);
|
|
214
211
|
highlightRender(vditor.options.preview.hljs, vditor.preview.element.lastElementChild as HTMLElement,
|
|
215
212
|
vditor.options.cdn);
|
|
216
213
|
mermaidRender(vditor.preview.element.lastElementChild as HTMLElement, vditor.options.cdn, vditor.options.theme);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
|
-
import {i18n} from "../i18n";
|
|
3
2
|
import {processAfterRender} from "../ir/process";
|
|
4
3
|
import {getMarkdown} from "../markdown/getMarkdown";
|
|
5
4
|
import {mathRender} from "../markdown/mathRender";
|
|
@@ -157,9 +156,9 @@ export class EditMode extends MenuItem {
|
|
|
157
156
|
|
|
158
157
|
const panelElement = document.createElement("div");
|
|
159
158
|
panelElement.className = `vditor-hint${menuItem.level === 2 ? "" : " vditor-panel--arrow"}`;
|
|
160
|
-
panelElement.innerHTML = `<button data-mode="wysiwyg">${
|
|
161
|
-
<button data-mode="ir">${
|
|
162
|
-
<button data-mode="sv">${
|
|
159
|
+
panelElement.innerHTML = `<button data-mode="wysiwyg">${window.VditorI18n.wysiwyg} <${updateHotkeyTip("⌥⌘7")}></button>
|
|
160
|
+
<button data-mode="ir">${window.VditorI18n.instantRendering} <${updateHotkeyTip("⌥⌘8")}></button>
|
|
161
|
+
<button data-mode="sv">${window.VditorI18n.splitView} <${updateHotkeyTip("⌥⌘9")}></button>`;
|
|
163
162
|
|
|
164
163
|
this.element.appendChild(panelElement);
|
|
165
164
|
|
|
@@ -15,12 +15,12 @@ export class Headings extends MenuItem {
|
|
|
15
15
|
|
|
16
16
|
const panelElement = document.createElement("div");
|
|
17
17
|
panelElement.className = "vditor-hint vditor-panel--arrow";
|
|
18
|
-
panelElement.innerHTML = `<button data-tag="h1" data-value="# "
|
|
19
|
-
<button data-tag="h2" data-value="## "
|
|
20
|
-
<button data-tag="h3" data-value="### "
|
|
21
|
-
<button data-tag="h4" data-value="#### "
|
|
22
|
-
<button data-tag="h5" data-value="##### "
|
|
23
|
-
<button data-tag="h6" data-value="###### "
|
|
18
|
+
panelElement.innerHTML = `<button data-tag="h1" data-value="# ">${window.VditorI18n.heading1} ${updateHotkeyTip("<⌥⌘1>")}</button>
|
|
19
|
+
<button data-tag="h2" data-value="## ">${window.VditorI18n.heading2} <${updateHotkeyTip("⌥⌘2")}></button>
|
|
20
|
+
<button data-tag="h3" data-value="### ">${window.VditorI18n.heading3} <${updateHotkeyTip("⌥⌘3")}></button>
|
|
21
|
+
<button data-tag="h4" data-value="#### ">${window.VditorI18n.heading4} <${updateHotkeyTip("⌥⌘4")}></button>
|
|
22
|
+
<button data-tag="h5" data-value="##### ">${window.VditorI18n.heading5} <${updateHotkeyTip("⌥⌘5")}></button>
|
|
23
|
+
<button data-tag="h6" data-value="###### ">${window.VditorI18n.heading6} <${updateHotkeyTip("⌥⌘6")}></button>`;
|
|
24
24
|
|
|
25
25
|
this.element.appendChild(panelElement);
|
|
26
26
|
|
package/src/ts/toolbar/Info.ts
CHANGED
|
@@ -16,7 +16,7 @@ export class Info extends MenuItem {
|
|
|
16
16
|
<div> </div>
|
|
17
17
|
<div style="flex: 1;min-width: 250px">
|
|
18
18
|
Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。
|
|
19
|
-
它使用 TypeScript 实现,支持原生 JavaScript
|
|
19
|
+
它使用 TypeScript 实现,支持原生 JavaScript 以及 Vue、React、Angular 和 Svelte 等框架。
|
|
20
20
|
</div>
|
|
21
21
|
</div>
|
|
22
22
|
<div style="display: flex;flex-wrap: wrap;">
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
|
-
import {i18n} from "../i18n/index";
|
|
3
2
|
import {processToolbar} from "../ir/process";
|
|
4
3
|
import {processToolbar as processToolbarSV} from "../sv/process";
|
|
5
4
|
import {getEventName} from "../util/compatibility";
|
|
@@ -19,8 +18,7 @@ export class MenuItem {
|
|
|
19
18
|
if (menuItem.level === 2) {
|
|
20
19
|
hotkey = menuItem.hotkey ? ` <${updateHotkeyTip(menuItem.hotkey)}>` : "";
|
|
21
20
|
}
|
|
22
|
-
const tip = menuItem.tip ?
|
|
23
|
-
menuItem.tip + hotkey : i18n[vditor.options.lang][menuItem.name] + hotkey;
|
|
21
|
+
const tip = menuItem.tip ? menuItem.tip + hotkey : `${window.VditorI18n[menuItem.name]}${hotkey}`;
|
|
24
22
|
const tagName = menuItem.name === "upload" ? "div" : "button";
|
|
25
23
|
if (menuItem.level === 2) {
|
|
26
24
|
this.element.innerHTML = `<${tagName} data-type="${menuItem.name}">${tip}</${tagName}>`;
|
package/src/ts/toolbar/Record.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
|
-
import {i18n} from "../i18n/index";
|
|
3
2
|
import {uploadFiles} from "../upload/index";
|
|
4
3
|
import {getEventName} from "../util/compatibility";
|
|
5
4
|
import {RecordMedia} from "../util/RecordMedia";
|
|
@@ -34,11 +33,11 @@ export class Record extends MenuItem {
|
|
|
34
33
|
mediaRecorder.cloneChannelData(left, right);
|
|
35
34
|
};
|
|
36
35
|
mediaRecorder.startRecordingNewWavFile();
|
|
37
|
-
vditor.tip.show(
|
|
36
|
+
vditor.tip.show(window.VditorI18n.recording);
|
|
38
37
|
editorElement.setAttribute("contenteditable", "false");
|
|
39
38
|
this.element.children[0].classList.add("vditor-menu--current");
|
|
40
39
|
}).catch(() => {
|
|
41
|
-
vditor.tip.show(
|
|
40
|
+
vditor.tip.show(window.VditorI18n["record-tip"]);
|
|
42
41
|
});
|
|
43
42
|
return;
|
|
44
43
|
}
|
|
@@ -51,7 +50,7 @@ export class Record extends MenuItem {
|
|
|
51
50
|
uploadFiles(vditor, [file]);
|
|
52
51
|
this.element.children[0].classList.remove("vditor-menu--current");
|
|
53
52
|
} else {
|
|
54
|
-
vditor.tip.show(
|
|
53
|
+
vditor.tip.show(window.VditorI18n.recording);
|
|
55
54
|
editorElement.setAttribute("contenteditable", "false");
|
|
56
55
|
mediaRecorder.startRecordingNewWavFile();
|
|
57
56
|
this.element.children[0].classList.add("vditor-menu--current");
|
package/src/ts/ui/initUI.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
2
|
import {setEditMode} from "../toolbar/EditMode";
|
|
3
|
+
import {hidePanel} from "../toolbar/setToolbar";
|
|
3
4
|
import {accessLocalStorage} from "../util/compatibility";
|
|
4
5
|
import {setContentTheme} from "./setContentTheme";
|
|
5
6
|
import {setTheme} from "./setTheme";
|
|
@@ -67,13 +68,17 @@ export const initUI = (vditor: IVditor) => {
|
|
|
67
68
|
|
|
68
69
|
vditor.element.appendChild(contentElement);
|
|
69
70
|
|
|
71
|
+
contentElement.addEventListener("click", () => {
|
|
72
|
+
hidePanel(vditor, ["subToolbar"]);
|
|
73
|
+
});
|
|
74
|
+
|
|
70
75
|
if (vditor.toolbar.elements.export) {
|
|
71
76
|
// for export pdf
|
|
72
77
|
vditor.element.insertAdjacentHTML("beforeend",
|
|
73
78
|
'<iframe style="width: 100%;height: 0;border: 0"></iframe>');
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
setEditMode(vditor, vditor.options.mode, afterRender(vditor
|
|
81
|
+
setEditMode(vditor, vditor.options.mode, afterRender(vditor));
|
|
77
82
|
|
|
78
83
|
document.execCommand("DefaultParagraphSeparator", false, "p");
|
|
79
84
|
|
|
@@ -114,10 +119,13 @@ export const setPadding = (vditor: IVditor) => {
|
|
|
114
119
|
vditor.ir.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
|
|
115
120
|
}
|
|
116
121
|
|
|
117
|
-
if (vditor.preview.element.style.display !== "block"
|
|
122
|
+
if (vditor.preview.element.style.display !== "block") {
|
|
118
123
|
vditor.toolbar.element.style.paddingLeft = Math.max(5,
|
|
119
124
|
parseInt(vditor[vditor.currentMode].element.style.paddingLeft || "0", 10) +
|
|
120
125
|
(vditor.options.outline.position === "left" ? vditor.outline.element.offsetWidth : 0)) + "px";
|
|
126
|
+
} else {
|
|
127
|
+
vditor.toolbar.element.style.paddingLeft = (5 +
|
|
128
|
+
(vditor.options.outline.position === "left" ? vditor.outline.element.offsetWidth : 0)) + "px";
|
|
121
129
|
}
|
|
122
130
|
};
|
|
123
131
|
|
|
@@ -141,10 +149,16 @@ export const setTypewriterPosition = (vditor: IVditor) => {
|
|
|
141
149
|
((height - vditor.toolbar.element.offsetHeight) / 2) + "px");
|
|
142
150
|
};
|
|
143
151
|
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
let resizeCb: () => void;
|
|
153
|
+
|
|
154
|
+
export function UIUnbindListener() {
|
|
155
|
+
window.removeEventListener("resize", resizeCb);
|
|
156
|
+
}
|
|
146
157
|
|
|
147
|
-
|
|
158
|
+
const afterRender = (vditor: IVditor) => {
|
|
159
|
+
setTypewriterPosition(vditor);
|
|
160
|
+
UIUnbindListener();
|
|
161
|
+
window.addEventListener("resize", resizeCb = () => {
|
|
148
162
|
setPadding(vditor);
|
|
149
163
|
setTypewriterPosition(vditor);
|
|
150
164
|
});
|
package/src/ts/undo/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as DiffMatchPatch from "diff-match-patch";
|
|
2
2
|
import {disableToolbar, enableToolbar, hidePanel} from "../toolbar/setToolbar";
|
|
3
3
|
import {isFirefox, isSafari} from "../util/compatibility";
|
|
4
4
|
import {scrollCenter} from "../util/editorCommonEvent";
|
|
@@ -10,13 +10,13 @@ import {setRangeByWbr, setSelectionFocus} from "../util/selection";
|
|
|
10
10
|
interface IUndo {
|
|
11
11
|
hasUndo: boolean;
|
|
12
12
|
lastText: string;
|
|
13
|
-
redoStack: patch_obj[][];
|
|
14
|
-
undoStack: patch_obj[][];
|
|
13
|
+
redoStack: DiffMatchPatch.patch_obj[][];
|
|
14
|
+
undoStack: DiffMatchPatch.patch_obj[][];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
class Undo {
|
|
18
18
|
private stackSize = 50;
|
|
19
|
-
private dmp: diff_match_patch;
|
|
19
|
+
private dmp: DiffMatchPatch.diff_match_patch;
|
|
20
20
|
private wysiwyg: IUndo;
|
|
21
21
|
private ir: IUndo;
|
|
22
22
|
private sv: IUndo;
|
|
@@ -131,7 +131,7 @@ class Undo {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
private renderDiff(state: patch_obj[], vditor: IVditor, isRedo: boolean = false) {
|
|
134
|
+
private renderDiff(state: DiffMatchPatch.patch_obj[], vditor: IVditor, isRedo: boolean = false) {
|
|
135
135
|
let text;
|
|
136
136
|
if (isRedo) {
|
|
137
137
|
const redoPatchList = this.dmp.patch_deepCopy(state).reverse();
|
package/src/ts/upload/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {i18n} from "../i18n/index";
|
|
2
1
|
import {getEditorRange, setSelectionFocus} from "../util/selection";
|
|
3
2
|
import {getElement} from "./getElement";
|
|
4
3
|
import {setHeaders} from "./setHeaders";
|
|
@@ -20,19 +19,20 @@ const validateFile = (vditor: IVditor, files: File[]) => {
|
|
|
20
19
|
const uploadFileList = [];
|
|
21
20
|
let errorTip = "";
|
|
22
21
|
let uploadingStr = "";
|
|
23
|
-
const lang: keyof II18n = vditor.options.lang;
|
|
22
|
+
const lang: keyof II18n | "" = vditor.options.lang;
|
|
23
|
+
const options: IOptions = vditor.options;
|
|
24
24
|
|
|
25
25
|
for (let iMax = files.length, i = 0; i < iMax; i++) {
|
|
26
26
|
const file = files[i];
|
|
27
27
|
let validate = true;
|
|
28
28
|
|
|
29
29
|
if (!file.name) {
|
|
30
|
-
errorTip += `<li>${
|
|
30
|
+
errorTip += `<li>${window.VditorI18n.nameEmpty}</li>`;
|
|
31
31
|
validate = false;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
if (file.size > vditor.options.upload.max) {
|
|
35
|
-
errorTip += `<li>${file.name} ${
|
|
35
|
+
errorTip += `<li>${file.name} ${window.VditorI18n.over} ${vditor.options.upload.max / 1024 / 1024}M</li>`;
|
|
36
36
|
validate = false;
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -56,14 +56,14 @@ const validateFile = (vditor: IVditor, files: File[]) => {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
if (!isAccept) {
|
|
59
|
-
errorTip += `<li>${file.name} ${
|
|
59
|
+
errorTip += `<li>${file.name} ${window.VditorI18n.fileTypeError}</li>`;
|
|
60
60
|
validate = false;
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
if (validate) {
|
|
65
65
|
uploadFileList.push(file);
|
|
66
|
-
uploadingStr += `<li>${filename} ${
|
|
66
|
+
uploadingStr += `<li>${filename} ${window.VditorI18n.uploading}</li>`;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -87,7 +87,7 @@ const genUploadedLabel = (responseText: string, vditor: IVditor) => {
|
|
|
87
87
|
response.data.errFiles.forEach((data: string) => {
|
|
88
88
|
const lastIndex = data.lastIndexOf(".");
|
|
89
89
|
const filename = vditor.options.upload.filename(data.substr(0, lastIndex)) + data.substr(lastIndex);
|
|
90
|
-
errorTip += `<li>${filename} ${
|
|
90
|
+
errorTip += `<li>${filename} ${window.VditorI18n.uploadError}</li>`;
|
|
91
91
|
});
|
|
92
92
|
errorTip += "</ul>";
|
|
93
93
|
}
|
|
@@ -154,7 +154,7 @@ const uploadFiles =
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
if (vditor.options.upload.handler) {
|
|
157
|
-
const isValidate = vditor.options.upload.handler(fileList);
|
|
157
|
+
const isValidate = await vditor.options.upload.handler(fileList);
|
|
158
158
|
if (typeof isValidate === "string") {
|
|
159
159
|
vditor.tip.show(isValidate);
|
|
160
160
|
return;
|