vditor 3.8.5 → 3.8.9
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/README.md +48 -45
- package/dist/index.css +2 -2
- package/dist/index.d.ts +4 -1
- package/dist/index.min.js +722 -858
- 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/lute/lute.min.js +31 -28
- package/dist/method.d.ts +4 -1
- package/dist/method.min.js +157 -543
- 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 +773 -0
- package/package.json +4 -4
- 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 +156 -97
- package/src/method.ts +6 -2
- package/src/ts/.DS_Store +0 -0
- 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/mathRender.ts +5 -4
- 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/upload/index.ts +11 -11
- 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/CHANGELOG.md +0 -1053
- package/dist/images/.DS_Store +0 -0
- package/dist/js/.DS_Store +0 -0
- package/dist/js/lute/.DS_Store +0 -0
- package/dist/js/mathjax/.DS_Store +0 -0
- package/dist/ts/i18n/index.d.ts +0 -2
- package/src/ts/i18n/index.ts +0 -476
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {i18n} from "../i18n/index";
|
|
2
1
|
import {code160to32} from "../util/code160to32";
|
|
3
2
|
|
|
4
|
-
export const codeRender = (element: HTMLElement
|
|
3
|
+
export const codeRender = (element: HTMLElement) => {
|
|
5
4
|
element.querySelectorAll("pre > code").forEach((e: HTMLElement, index: number) => {
|
|
6
5
|
if (e.parentElement.classList.contains("vditor-wysiwyg__pre") ||
|
|
7
6
|
e.parentElement.classList.contains("vditor-ir__marker--pre")) {
|
|
@@ -11,7 +10,7 @@ export const codeRender = (element: HTMLElement, lang: keyof II18n = "zh_CN") =>
|
|
|
11
10
|
e.classList.contains("language-echarts") || e.classList.contains("language-mindmap") ||
|
|
12
11
|
e.classList.contains("language-plantuml") ||
|
|
13
12
|
e.classList.contains("language-abc") || e.classList.contains("language-graphviz") ||
|
|
14
|
-
e.classList.contains("language-math")
|
|
13
|
+
e.classList.contains("language-math")) {
|
|
15
14
|
return;
|
|
16
15
|
}
|
|
17
16
|
|
|
@@ -36,11 +35,11 @@ export const codeRender = (element: HTMLElement, lang: keyof II18n = "zh_CN") =>
|
|
|
36
35
|
|
|
37
36
|
const divElement = document.createElement("div");
|
|
38
37
|
divElement.className = "vditor-copy";
|
|
39
|
-
divElement.innerHTML = `<span aria-label="${
|
|
40
|
-
onmouseover="this.setAttribute('aria-label', '${
|
|
38
|
+
divElement.innerHTML = `<span aria-label="${window.VditorI18n.copy}"
|
|
39
|
+
onmouseover="this.setAttribute('aria-label', '${window.VditorI18n.copy}')"
|
|
41
40
|
class="vditor-tooltipped vditor-tooltipped__w"
|
|
42
41
|
onclick="this.previousElementSibling.select();document.execCommand('copy');` +
|
|
43
|
-
`this.setAttribute('aria-label', '${
|
|
42
|
+
`this.setAttribute('aria-label', '${window.VditorI18n.copied}')"><svg><use xlink:href="#vditor-icon-copy"></use></svg></span>`;
|
|
44
43
|
const textarea = document.createElement("textarea");
|
|
45
44
|
textarea.value = code160to32(codeText);
|
|
46
45
|
divElement.insertAdjacentElement("afterbegin", textarea);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {Constants} from "../constants";
|
|
2
2
|
import {addScript} from "../util/addScript";
|
|
3
|
+
import {flowchartRenderAdapter} from "./adapterRender";
|
|
3
4
|
|
|
4
5
|
declare const flowchart: {
|
|
5
6
|
parse(text: string): { drawSVG: (type: HTMLElement) => void };
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
export const flowchartRender = (element: HTMLElement, cdn = Constants.CDN) => {
|
|
9
|
-
const flowchartElements =
|
|
10
|
+
const flowchartElements = flowchartRenderAdapter.getElements(element);
|
|
10
11
|
if (flowchartElements.length === 0) {
|
|
11
12
|
return;
|
|
12
13
|
}
|
|
@@ -15,7 +16,7 @@ export const flowchartRender = (element: HTMLElement, cdn = Constants.CDN) => {
|
|
|
15
16
|
if (item.getAttribute("data-processed") === "true") {
|
|
16
17
|
return;
|
|
17
18
|
}
|
|
18
|
-
const flowchartObj = flowchart.parse(item
|
|
19
|
+
const flowchartObj = flowchart.parse(flowchartRenderAdapter.getCode(item));
|
|
19
20
|
item.innerHTML = "";
|
|
20
21
|
flowchartObj.drawSVG(item);
|
|
21
22
|
item.setAttribute("data-processed", "true");
|
|
@@ -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
|
}
|
|
@@ -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,
|
|
@@ -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
|
+
await 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/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
|
}
|
|
@@ -108,7 +108,7 @@ const genUploadedLabel = (responseText: string, vditor: IVditor) => {
|
|
|
108
108
|
if (type.indexOf(".wav") === 0 || type.indexOf(".mp3") === 0 || type.indexOf(".ogg") === 0) {
|
|
109
109
|
if (vditor.currentMode === "wysiwyg") {
|
|
110
110
|
succFileText += `<div class="vditor-wysiwyg__block" data-type="html-block"
|
|
111
|
-
data-block="0"><pre><code><audio controls="controls" src="${path}"></audio></code></pre
|
|
111
|
+
data-block="0"><pre><code><audio controls="controls" src="${path}"></audio></code></pre>\n`;
|
|
112
112
|
} else if (vditor.currentMode === "ir") {
|
|
113
113
|
succFileText += `<audio controls="controls" src="${path}"></audio>\n`;
|
|
114
114
|
} else {
|
|
@@ -123,13 +123,13 @@ const genUploadedLabel = (responseText: string, vditor: IVditor) => {
|
|
|
123
123
|
|| type.indexOf(".svg") === 0
|
|
124
124
|
|| type.indexOf(".webp") === 0) {
|
|
125
125
|
if (vditor.currentMode === "wysiwyg") {
|
|
126
|
-
succFileText += `<img alt="${filename}" src="${path}"
|
|
126
|
+
succFileText += `<img alt="${filename}" src="${path}">\n`;
|
|
127
127
|
} else {
|
|
128
128
|
succFileText += `\n`;
|
|
129
129
|
}
|
|
130
130
|
} else {
|
|
131
131
|
if (vditor.currentMode === "wysiwyg") {
|
|
132
|
-
succFileText += `<a href="${path}">${filename}</a
|
|
132
|
+
succFileText += `<a href="${path}">${filename}</a>\n`;
|
|
133
133
|
} else {
|
|
134
134
|
succFileText += `[${filename}](${path})\n`;
|
|
135
135
|
}
|
|
@@ -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;
|