vditor 3.8.6 → 3.8.10
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 +11 -11
- package/dist/index.css +1 -1
- package/dist/index.min.js +189 -82
- package/dist/js/i18n/zh_CN.js +1 -1
- package/dist/js/lute/lute.min.js +14 -14
- package/dist/method.min.js +45 -21
- package/dist/ts/ui/initUI.d.ts +1 -0
- package/dist/ts/wysiwyg/index.d.ts +2 -0
- package/dist/types/index.d.ts +7 -3
- package/package.json +4 -4
- package/src/assets/.DS_Store +0 -0
- package/src/index.ts +12 -2
- package/src/ts/.DS_Store +0 -0
- package/src/ts/hint/index.ts +20 -11
- package/src/ts/markdown/codeRender.ts +8 -4
- package/src/ts/markdown/outlineRender.ts +5 -1
- package/src/ts/markdown/previewRender.ts +12 -4
- package/src/ts/markdown/speechRender.ts +6 -2
- package/src/ts/preview/index.ts +0 -1
- package/src/ts/toolbar/Info.ts +1 -1
- package/src/ts/ui/initUI.ts +19 -5
- package/src/ts/upload/index.ts +4 -4
- package/src/ts/util/editorCommonEvent.ts +2 -2
- package/src/ts/util/fixBrowserBehavior.ts +10 -6
- package/src/ts/wysiwyg/highlightToolbarWYSIWYG.ts +11 -3
- package/src/ts/wysiwyg/index.ts +8 -2
- package/CHANGELOG.md +0 -1069
- 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/method.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Vditor v3.8.
|
|
2
|
+
* Vditor v3.8.10 - A markdown editor written in TypeScript.
|
|
3
3
|
*
|
|
4
4
|
* MIT License
|
|
5
5
|
*
|
|
@@ -45,7 +45,7 @@ return /******/ (() => { // webpackBootstrap
|
|
|
45
45
|
/* harmony export */ "g": () => (/* binding */ Constants)
|
|
46
46
|
/* harmony export */ });
|
|
47
47
|
/* unused harmony export VDITOR_VERSION */
|
|
48
|
-
var _VDITOR_VERSION = (/* unused pure expression or super */ null && ("3.8.
|
|
48
|
+
var _VDITOR_VERSION = (/* unused pure expression or super */ null && ("3.8.10"));
|
|
49
49
|
|
|
50
50
|
var Constants = /** @class */ (function () {
|
|
51
51
|
function Constants() {
|
|
@@ -71,7 +71,7 @@ var Constants = /** @class */ (function () {
|
|
|
71
71
|
"swift", "ini", "typescript", "vbnet", "yaml",
|
|
72
72
|
"ada", "clojure", "dart", "erb", "fortran", "gradle", "haskell", "julia", "julia-repl", "lisp", "matlab",
|
|
73
73
|
"pgsql", "powershell", "sql_more", "stata", "cmake", "mathematica"];
|
|
74
|
-
Constants.CDN = "https://cdn.jsdelivr.net/npm/vditor@" + "3.8.
|
|
74
|
+
Constants.CDN = "https://cdn.jsdelivr.net/npm/vditor@" + "3.8.10";
|
|
75
75
|
Constants.MARKDOWN_OPTIONS = {
|
|
76
76
|
autoSpace: false,
|
|
77
77
|
codeBlockPreview: true,
|
|
@@ -258,6 +258,7 @@ var chartRender = function (element, cdn, theme) {
|
|
|
258
258
|
|
|
259
259
|
var codeRender = function (element) {
|
|
260
260
|
element.querySelectorAll("pre > code").forEach(function (e, index) {
|
|
261
|
+
var _a, _b, _c;
|
|
261
262
|
if (e.parentElement.classList.contains("vditor-wysiwyg__pre") ||
|
|
262
263
|
e.parentElement.classList.contains("vditor-ir__marker--pre")) {
|
|
263
264
|
return;
|
|
@@ -285,10 +286,13 @@ var codeRender = function (element) {
|
|
|
285
286
|
});
|
|
286
287
|
codeText = codeElement.innerText;
|
|
287
288
|
}
|
|
289
|
+
var iconHTML = '<svg><use xlink:href="#vditor-icon-copy"></use></svg>';
|
|
290
|
+
if (!document.getElementById("vditorIconScript")) {
|
|
291
|
+
iconHTML = '<svg viewBox="0 0 32 32"><path d="M22.545-0h-17.455c-1.6 0-2.909 1.309-2.909 2.909v20.364h2.909v-20.364h17.455v-2.909zM26.909 5.818h-16c-1.6 0-2.909 1.309-2.909 2.909v20.364c0 1.6 1.309 2.909 2.909 2.909h16c1.6 0 2.909-1.309 2.909-2.909v-20.364c0-1.6-1.309-2.909-2.909-2.909zM26.909 29.091h-16v-20.364h16v20.364z"></path></svg>';
|
|
292
|
+
}
|
|
288
293
|
var divElement = document.createElement("div");
|
|
289
294
|
divElement.className = "vditor-copy";
|
|
290
|
-
divElement.innerHTML = "<span aria-label=\"" + window.VditorI18n.copy + "\"\nonmouseover=\"this.setAttribute('aria-label', '" + window.VditorI18n.copy + "')\"\nclass=\"vditor-tooltipped vditor-tooltipped__w\"\nonclick=\"this.previousElementSibling.select();document.execCommand('copy');" +
|
|
291
|
-
("this.setAttribute('aria-label', '" + window.VditorI18n.copied + "')\"><svg><use xlink:href=\"#vditor-icon-copy\"></use></svg></span>");
|
|
295
|
+
divElement.innerHTML = "<span aria-label=\"" + (((_a = window.VditorI18n) === null || _a === void 0 ? void 0 : _a.copy) || "复制") + "\"\nonmouseover=\"this.setAttribute('aria-label', '" + (((_b = window.VditorI18n) === null || _b === void 0 ? void 0 : _b.copy) || "复制") + "')\"\nclass=\"vditor-tooltipped vditor-tooltipped__w\"\nonclick=\"this.previousElementSibling.select();document.execCommand('copy');this.setAttribute('aria-label', '" + (((_c = window.VditorI18n) === null || _c === void 0 ? void 0 : _c.copy) || "已复制") + "')\">" + iconHTML + "</span>";
|
|
292
296
|
var textarea = document.createElement("textarea");
|
|
293
297
|
textarea.value = (0,_util_code160to32__WEBPACK_IMPORTED_MODULE_0__/* .code160to32 */ .X)(codeText);
|
|
294
298
|
divElement.insertAdjacentElement("afterbegin", textarea);
|
|
@@ -965,7 +969,11 @@ var outlineRender = function (contentElement, targetElement, vditor) {
|
|
|
965
969
|
var headingsElement = tempElement.firstElementChild.querySelectorAll("li > span[data-target-id]");
|
|
966
970
|
headingsElement.forEach(function (item, index) {
|
|
967
971
|
if (item.nextElementSibling && item.nextElementSibling.tagName === "UL") {
|
|
968
|
-
|
|
972
|
+
var iconHTML = "<svg class='vditor-outline__action'><use xlink:href='#vditor-icon-down'></use></svg>";
|
|
973
|
+
if (!document.getElementById("vditorIconScript")) {
|
|
974
|
+
iconHTML = '<svg class="vditor-outline__action" viewBox="0 0 32 32"><path d="M3.76 6.12l12.24 12.213 12.24-12.213 3.76 3.76-16 16-16-16 3.76-3.76z"></path></svg>';
|
|
975
|
+
}
|
|
976
|
+
item.innerHTML = iconHTML + "<span>" + item.innerHTML + "</span>";
|
|
969
977
|
}
|
|
970
978
|
else {
|
|
971
979
|
item.innerHTML = "<svg></svg><span>" + item.innerHTML + "</span>";
|
|
@@ -2003,6 +2011,10 @@ var speechRender = function (element, lang) {
|
|
|
2003
2011
|
}
|
|
2004
2012
|
var playSVG = '<svg><use xlink:href="#vditor-icon-play"></use></svg>';
|
|
2005
2013
|
var pauseSVG = '<svg><use xlink:href="#vditor-icon-pause"></use></svg>';
|
|
2014
|
+
if (!document.getElementById("vditorIconScript")) {
|
|
2015
|
+
playSVG = '<svg viewBox="0 0 32 32"><path d="M3.436 0l25.128 16-25.128 16v-32z"></path></svg>';
|
|
2016
|
+
pauseSVG = '<svg viewBox="0 0 32 32"><path d="M20.617 0h9.128v32h-9.128v-32zM2.255 32v-32h9.128v32h-9.128z"></path></svg>';
|
|
2017
|
+
}
|
|
2006
2018
|
var speechDom = document.querySelector(".vditor-speech");
|
|
2007
2019
|
if (!speechDom) {
|
|
2008
2020
|
speechDom = document.createElement("div");
|
|
@@ -2194,7 +2206,7 @@ var md2html = function (mdText, options) {
|
|
|
2194
2206
|
});
|
|
2195
2207
|
};
|
|
2196
2208
|
var previewRender = function (previewElement, markdown, options) { return __awaiter(void 0, void 0, void 0, function () {
|
|
2197
|
-
var mergedOptions, html;
|
|
2209
|
+
var mergedOptions, html, i18nScriptPrefix, i18nScriptID_1;
|
|
2198
2210
|
return __generator(this, function (_a) {
|
|
2199
2211
|
switch (_a.label) {
|
|
2200
2212
|
case 0:
|
|
@@ -2207,17 +2219,32 @@ var previewRender = function (previewElement, markdown, options) { return __awai
|
|
|
2207
2219
|
}
|
|
2208
2220
|
previewElement.innerHTML = html;
|
|
2209
2221
|
previewElement.classList.add("vditor-reset");
|
|
2210
|
-
if (
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2222
|
+
if (!!mergedOptions.i18n) return [3 /*break*/, 5];
|
|
2223
|
+
if (!!["en_US", "ja_JP", "ko_KR", "ru_RU", "zh_CN", "zh_TW"].includes(mergedOptions.lang)) return [3 /*break*/, 2];
|
|
2224
|
+
throw new Error("options.lang error, see https://ld246.com/article/1549638745630#options");
|
|
2225
|
+
case 2:
|
|
2226
|
+
i18nScriptPrefix = "vditorI18nScript";
|
|
2227
|
+
i18nScriptID_1 = i18nScriptPrefix + mergedOptions.lang;
|
|
2228
|
+
document.querySelectorAll("head script[id^=\"" + i18nScriptPrefix + "\"]").forEach(function (el) {
|
|
2229
|
+
if (el.id !== i18nScriptID_1) {
|
|
2230
|
+
document.head.removeChild(el);
|
|
2216
2231
|
}
|
|
2217
|
-
}
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2232
|
+
});
|
|
2233
|
+
return [4 /*yield*/, (0,addScript/* addScript */.G)(mergedOptions.cdn + "/dist/js/i18n/" + mergedOptions.lang + ".js", i18nScriptID_1)];
|
|
2234
|
+
case 3:
|
|
2235
|
+
_a.sent();
|
|
2236
|
+
_a.label = 4;
|
|
2237
|
+
case 4: return [3 /*break*/, 6];
|
|
2238
|
+
case 5:
|
|
2239
|
+
window.VditorI18n = mergedOptions.i18n;
|
|
2240
|
+
_a.label = 6;
|
|
2241
|
+
case 6:
|
|
2242
|
+
if (!mergedOptions.icon) return [3 /*break*/, 8];
|
|
2243
|
+
return [4 /*yield*/, (0,addScript/* addScript */.G)(mergedOptions.cdn + "/dist/js/icons/" + mergedOptions.icon + ".js", "vditorIconScript")];
|
|
2244
|
+
case 7:
|
|
2245
|
+
_a.sent();
|
|
2246
|
+
_a.label = 8;
|
|
2247
|
+
case 8:
|
|
2221
2248
|
(0,setContentTheme/* setContentTheme */.Z)(mergedOptions.theme.current, mergedOptions.theme.path);
|
|
2222
2249
|
if (mergedOptions.anchor === 1) {
|
|
2223
2250
|
previewElement.classList.add("vditor-reset--anchor");
|
|
@@ -2248,9 +2275,6 @@ var previewRender = function (previewElement, markdown, options) { return __awai
|
|
|
2248
2275
|
if (mergedOptions.lazyLoadImage) {
|
|
2249
2276
|
lazyLoadImageRender(previewElement);
|
|
2250
2277
|
}
|
|
2251
|
-
if (mergedOptions.icon) {
|
|
2252
|
-
(0,addScript/* addScript */.G)(mergedOptions.cdn + "/dist/js/icons/" + mergedOptions.icon + ".js", "vditorIconScript");
|
|
2253
|
-
}
|
|
2254
2278
|
previewElement.addEventListener("click", function (event) {
|
|
2255
2279
|
var spanElement = (0,hasClosest/* hasClosestByMatchTag */.lG)(event.target, "SPAN");
|
|
2256
2280
|
if (spanElement && (0,hasClosest/* hasClosestByClassName */.fb)(spanElement, "vditor-toc")) {
|
|
@@ -2339,7 +2363,7 @@ var Vditor = /** @class */ (function () {
|
|
|
2339
2363
|
|
|
2340
2364
|
})();
|
|
2341
2365
|
|
|
2342
|
-
__webpack_exports__ = __webpack_exports__
|
|
2366
|
+
__webpack_exports__ = __webpack_exports__["default"];
|
|
2343
2367
|
/******/ return __webpack_exports__;
|
|
2344
2368
|
/******/ })()
|
|
2345
2369
|
;
|
package/dist/ts/ui/initUI.d.ts
CHANGED
|
@@ -9,11 +9,13 @@ declare class WYSIWYG {
|
|
|
9
9
|
preventInput: boolean;
|
|
10
10
|
composingLock: boolean;
|
|
11
11
|
commentIds: string[];
|
|
12
|
+
private scrollListener;
|
|
12
13
|
constructor(vditor: IVditor);
|
|
13
14
|
getComments(vditor: IVditor, getData?: boolean): ICommentsData[];
|
|
14
15
|
triggerRemoveComment(vditor: IVditor): void;
|
|
15
16
|
showComment(): void;
|
|
16
17
|
hideComment(): void;
|
|
18
|
+
unbindListener(): void;
|
|
17
19
|
private copy;
|
|
18
20
|
private bindEvent;
|
|
19
21
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -118,6 +118,8 @@ declare class Lute {
|
|
|
118
118
|
|
|
119
119
|
public static NewNodeID(): string;
|
|
120
120
|
|
|
121
|
+
public static Sanitize(html: string): string;
|
|
122
|
+
|
|
121
123
|
private constructor();
|
|
122
124
|
|
|
123
125
|
public SetJSRenderers(options?: {
|
|
@@ -232,6 +234,7 @@ declare const webkitAudioContext: {
|
|
|
232
234
|
|
|
233
235
|
interface ITips {
|
|
234
236
|
[index: string]: string;
|
|
237
|
+
|
|
235
238
|
alignCenter: string;
|
|
236
239
|
alignLeft: string;
|
|
237
240
|
alignRight: string;
|
|
@@ -369,7 +372,7 @@ interface IUpload {
|
|
|
369
372
|
validate?(files: File[]): string | boolean;
|
|
370
373
|
|
|
371
374
|
/** 自定义上传,当发生错误时返回错误信息 */
|
|
372
|
-
handler?(files: File[]): string | null
|
|
375
|
+
handler?(files: File[]): string | null | Promise<string> | Promise<null>;
|
|
373
376
|
|
|
374
377
|
/** 对服务端返回的数据进行转换,以满足内置的数据结构 */
|
|
375
378
|
format?(files: File[], responseText: string): string;
|
|
@@ -378,7 +381,7 @@ interface IUpload {
|
|
|
378
381
|
linkToImgFormat?(responseText: string): string;
|
|
379
382
|
|
|
380
383
|
/** 将上传的文件处理后再返回 */
|
|
381
|
-
file?(files: File[]): File[]
|
|
384
|
+
file?(files: File[]): File[] | Promise<File[]>;
|
|
382
385
|
|
|
383
386
|
/** 图片地址上传后的回调 */
|
|
384
387
|
linkToImgCallback?(responseText: string): void;
|
|
@@ -534,7 +537,7 @@ interface IHintData {
|
|
|
534
537
|
interface IHintExtend {
|
|
535
538
|
key: string;
|
|
536
539
|
|
|
537
|
-
hint?(value: string): IHintData[]
|
|
540
|
+
hint?(value: string): IHintData[] | Promise<IHintData[]>;
|
|
538
541
|
}
|
|
539
542
|
|
|
540
543
|
/** @link https://ld246.com/article/1549638745630#options-hint */
|
|
@@ -744,6 +747,7 @@ interface IVditor {
|
|
|
744
747
|
triggerRemoveComment(vditor: IVditor): void,
|
|
745
748
|
showComment(): void,
|
|
746
749
|
hideComment(): void,
|
|
750
|
+
unbindListener(): void,
|
|
747
751
|
};
|
|
748
752
|
ir?: {
|
|
749
753
|
range: Range,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vditor",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.10",
|
|
4
4
|
"description": "♏ 易于使用的 Markdown 编辑器,为适配不同的应用场景而生",
|
|
5
5
|
"author": "Vanessa <v@b3log.org> (http://vanessa.b3log.org)",
|
|
6
6
|
"homepage": "https://b3log.org/vditor",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"identity-obj-proxy": "^3.0.0",
|
|
35
35
|
"jest": "^26.6.3",
|
|
36
36
|
"mini-css-extract-plugin": "^0.8.2",
|
|
37
|
-
"node-sass": "^
|
|
37
|
+
"node-sass": "^7.0.0",
|
|
38
38
|
"postcss-loader": "^5.2.0",
|
|
39
39
|
"puppeteer": "^1.20.0",
|
|
40
|
-
"sass-loader": "^
|
|
40
|
+
"sass-loader": "^12.4.0",
|
|
41
41
|
"style-loader": "^1.3.0",
|
|
42
42
|
"terser-webpack-plugin": "^5.1.2",
|
|
43
43
|
"ts-jest": "^26.5.6",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"webpack": "^5.37.0",
|
|
48
48
|
"webpack-bundle-analyzer": "^3.9.0",
|
|
49
49
|
"webpack-cli": "^4.7.0",
|
|
50
|
-
"webpack-dev-server": "^
|
|
50
|
+
"webpack-dev-server": "^4.1.0"
|
|
51
51
|
},
|
|
52
52
|
"license": "MIT",
|
|
53
53
|
"repository": "git://github.com/Vanessa219/vditor.git",
|
package/src/assets/.DS_Store
CHANGED
|
Binary file
|
package/src/index.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {Tip} from "./ts/tip/index";
|
|
|
19
19
|
import {Toolbar} from "./ts/toolbar/index";
|
|
20
20
|
import {disableToolbar, hidePanel} from "./ts/toolbar/setToolbar";
|
|
21
21
|
import {enableToolbar} from "./ts/toolbar/setToolbar";
|
|
22
|
-
import {initUI} from "./ts/ui/initUI";
|
|
22
|
+
import {initUI, UIUnbindListener} from "./ts/ui/initUI";
|
|
23
23
|
import {setCodeTheme} from "./ts/ui/setCodeTheme";
|
|
24
24
|
import {setContentTheme} from "./ts/ui/setContentTheme";
|
|
25
25
|
import {setPreviewMode} from "./ts/ui/setPreviewMode";
|
|
@@ -73,7 +73,14 @@ class Vditor extends VditorMethod {
|
|
|
73
73
|
"options.lang error, see https://ld246.com/article/1549638745630#options",
|
|
74
74
|
);
|
|
75
75
|
} else {
|
|
76
|
-
|
|
76
|
+
const i18nScriptPrefix = "vditorI18nScript";
|
|
77
|
+
const i18nScriptID = i18nScriptPrefix + mergedOptions.lang;
|
|
78
|
+
document.querySelectorAll(`head script[id^="${i18nScriptPrefix}"]`).forEach((el) => {
|
|
79
|
+
if (el.id !== i18nScriptID) {
|
|
80
|
+
document.head.removeChild(el);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
addScript(`${mergedOptions.cdn}/dist/js/i18n/${mergedOptions.lang}.js`, i18nScriptID).then(() => {
|
|
77
84
|
this.init(id as HTMLElement, mergedOptions);
|
|
78
85
|
});
|
|
79
86
|
}
|
|
@@ -322,6 +329,9 @@ class Vditor extends VditorMethod {
|
|
|
322
329
|
this.vditor.element.removeAttribute("style");
|
|
323
330
|
document.getElementById("vditorIconScript").remove();
|
|
324
331
|
this.clearCache();
|
|
332
|
+
|
|
333
|
+
UIUnbindListener();
|
|
334
|
+
this.vditor.wysiwyg.unbindListener();
|
|
325
335
|
}
|
|
326
336
|
|
|
327
337
|
/** 获取评论 ID */
|
package/src/ts/.DS_Store
CHANGED
|
Binary file
|
package/src/ts/hint/index.ts
CHANGED
|
@@ -59,8 +59,8 @@ export class Hint {
|
|
|
59
59
|
vditor.options.hint.extend.forEach((item) => {
|
|
60
60
|
if (item.key === this.splitChar) {
|
|
61
61
|
clearTimeout(this.timeId);
|
|
62
|
-
this.timeId = window.setTimeout(() => {
|
|
63
|
-
this.genHTML(item.hint(key), key, vditor);
|
|
62
|
+
this.timeId = window.setTimeout(async () => {
|
|
63
|
+
this.genHTML(await item.hint(key), key, vditor);
|
|
64
64
|
}, vditor.options.hint.delay);
|
|
65
65
|
}
|
|
66
66
|
});
|
|
@@ -148,15 +148,24 @@ ${i === 0 ? "class='vditor-hint--current'" : ""}> ${html}</button>`;
|
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
|
-
if (vditor.currentMode === "wysiwyg" && range.startContainer.nodeType !== 3
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
151
|
+
if (vditor.currentMode === "wysiwyg" && range.startContainer.nodeType !== 3 ) {
|
|
152
|
+
const startContainer = range.startContainer as HTMLElement;
|
|
153
|
+
let inputElement: HTMLInputElement;
|
|
154
|
+
if (startContainer.classList.contains("vditor-input")) {
|
|
155
|
+
inputElement = startContainer as HTMLInputElement;
|
|
156
|
+
} else {
|
|
157
|
+
inputElement = startContainer.firstElementChild as HTMLInputElement;
|
|
158
|
+
}
|
|
159
|
+
if (inputElement && inputElement.classList.contains("vditor-input")) {
|
|
160
|
+
inputElement.value = value.trimRight();
|
|
161
|
+
range.selectNodeContents(inputElement);
|
|
162
|
+
range.collapse(false);
|
|
163
|
+
// {detail: 1}用于标识这个自定义事件是在编程语言选择后触发的
|
|
164
|
+
// 用于在鼠标选择语言后,自动聚焦到代码输入框
|
|
165
|
+
inputElement.dispatchEvent(new CustomEvent("input", {detail: 1}));
|
|
166
|
+
this.recentLanguage = value.trimRight();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
160
169
|
}
|
|
161
170
|
|
|
162
171
|
range.setStart(range.startContainer, this.lastIndex);
|
|
@@ -33,13 +33,17 @@ export const codeRender = (element: HTMLElement) => {
|
|
|
33
33
|
codeText = codeElement.innerText;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
let iconHTML = '<svg><use xlink:href="#vditor-icon-copy"></use></svg>';
|
|
37
|
+
if (!document.getElementById("vditorIconScript")) {
|
|
38
|
+
iconHTML = '<svg viewBox="0 0 32 32"><path d="M22.545-0h-17.455c-1.6 0-2.909 1.309-2.909 2.909v20.364h2.909v-20.364h17.455v-2.909zM26.909 5.818h-16c-1.6 0-2.909 1.309-2.909 2.909v20.364c0 1.6 1.309 2.909 2.909 2.909h16c1.6 0 2.909-1.309 2.909-2.909v-20.364c0-1.6-1.309-2.909-2.909-2.909zM26.909 29.091h-16v-20.364h16v20.364z"></path></svg>';
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
const divElement = document.createElement("div");
|
|
37
42
|
divElement.className = "vditor-copy";
|
|
38
|
-
divElement.innerHTML = `<span aria-label="${window.VditorI18n
|
|
39
|
-
onmouseover="this.setAttribute('aria-label', '${window.VditorI18n
|
|
43
|
+
divElement.innerHTML = `<span aria-label="${window.VditorI18n?.copy || "复制"}"
|
|
44
|
+
onmouseover="this.setAttribute('aria-label', '${window.VditorI18n?.copy || "复制"}')"
|
|
40
45
|
class="vditor-tooltipped vditor-tooltipped__w"
|
|
41
|
-
onclick="this.previousElementSibling.select();document.execCommand('copy')
|
|
42
|
-
`this.setAttribute('aria-label', '${window.VditorI18n.copied}')"><svg><use xlink:href="#vditor-icon-copy"></use></svg></span>`;
|
|
46
|
+
onclick="this.previousElementSibling.select();document.execCommand('copy');this.setAttribute('aria-label', '${window.VditorI18n?.copy || "已复制"}')">${iconHTML}</span>`;
|
|
43
47
|
const textarea = document.createElement("textarea");
|
|
44
48
|
textarea.value = code160to32(codeText);
|
|
45
49
|
divElement.insertAdjacentElement("afterbegin", textarea);
|
|
@@ -38,7 +38,11 @@ export const outlineRender = (contentElement: HTMLElement, targetElement: Elemen
|
|
|
38
38
|
const headingsElement = tempElement.firstElementChild.querySelectorAll("li > span[data-target-id]");
|
|
39
39
|
headingsElement.forEach((item, index) => {
|
|
40
40
|
if (item.nextElementSibling && item.nextElementSibling.tagName === "UL") {
|
|
41
|
-
|
|
41
|
+
let iconHTML = "<svg class='vditor-outline__action'><use xlink:href='#vditor-icon-down'></use></svg>";
|
|
42
|
+
if (!document.getElementById("vditorIconScript")) {
|
|
43
|
+
iconHTML = '<svg class="vditor-outline__action" viewBox="0 0 32 32"><path d="M3.76 6.12l12.24 12.213 12.24-12.213 3.76 3.76-16 16-16-16 3.76-3.76z"></path></svg>';
|
|
44
|
+
}
|
|
45
|
+
item.innerHTML = `${iconHTML}<span>${item.innerHTML}</span>`;
|
|
42
46
|
} else {
|
|
43
47
|
item.innerHTML = `<svg></svg><span>${item.innerHTML}</span>`;
|
|
44
48
|
}
|
|
@@ -90,12 +90,23 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st
|
|
|
90
90
|
"options.lang error, see https://ld246.com/article/1549638745630#options",
|
|
91
91
|
);
|
|
92
92
|
} else {
|
|
93
|
-
|
|
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);
|
|
94
101
|
}
|
|
95
102
|
} else {
|
|
96
103
|
window.VditorI18n = mergedOptions.i18n;
|
|
97
104
|
}
|
|
98
105
|
|
|
106
|
+
if (mergedOptions.icon) {
|
|
107
|
+
await addScript(`${mergedOptions.cdn}/dist/js/icons/${mergedOptions.icon}.js`, "vditorIconScript");
|
|
108
|
+
}
|
|
109
|
+
|
|
99
110
|
setContentTheme(mergedOptions.theme.current, mergedOptions.theme.path);
|
|
100
111
|
if (mergedOptions.anchor === 1) {
|
|
101
112
|
previewElement.classList.add("vditor-reset--anchor");
|
|
@@ -126,9 +137,6 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st
|
|
|
126
137
|
if (mergedOptions.lazyLoadImage) {
|
|
127
138
|
lazyLoadImageRender(previewElement);
|
|
128
139
|
}
|
|
129
|
-
if (mergedOptions.icon) {
|
|
130
|
-
addScript(`${mergedOptions.cdn}/dist/js/icons/${mergedOptions.icon}.js`, "vditorIconScript");
|
|
131
|
-
}
|
|
132
140
|
previewElement.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => {
|
|
133
141
|
const spanElement = hasClosestByMatchTag(event.target, "SPAN");
|
|
134
142
|
if (spanElement && hasClosestByClassName(spanElement, "vditor-toc")) {
|
|
@@ -9,8 +9,12 @@ export const speechRender = (element: HTMLElement, lang: keyof II18n = "zh_CN")
|
|
|
9
9
|
if (typeof speechSynthesis === "undefined" || typeof SpeechSynthesisUtterance === "undefined") {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
let playSVG = '<svg><use xlink:href="#vditor-icon-play"></use></svg>';
|
|
13
|
+
let pauseSVG = '<svg><use xlink:href="#vditor-icon-pause"></use></svg>';
|
|
14
|
+
if (!document.getElementById("vditorIconScript")) {
|
|
15
|
+
playSVG = '<svg viewBox="0 0 32 32"><path d="M3.436 0l25.128 16-25.128 16v-32z"></path></svg>';
|
|
16
|
+
pauseSVG = '<svg viewBox="0 0 32 32"><path d="M20.617 0h9.128v32h-9.128v-32zM2.255 32v-32h9.128v32h-9.128z"></path></svg>';
|
|
17
|
+
}
|
|
14
18
|
let speechDom: HTMLDivElement = document.querySelector(".vditor-speech");
|
|
15
19
|
if (!speechDom) {
|
|
16
20
|
speechDom = document.createElement("div");
|
package/src/ts/preview/index.ts
CHANGED
|
@@ -23,7 +23,6 @@ export class Preview {
|
|
|
23
23
|
constructor(vditor: IVditor) {
|
|
24
24
|
this.element = document.createElement("div");
|
|
25
25
|
this.element.className = `vditor-preview`;
|
|
26
|
-
|
|
27
26
|
const previewElement = document.createElement("div");
|
|
28
27
|
previewElement.className = "vditor-reset";
|
|
29
28
|
if (vditor.options.classes.preview) {
|
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;">
|
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
|
@@ -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;
|
|
@@ -22,7 +22,7 @@ export const focusEvent = (vditor: IVditor, editorElement: HTMLElement) => {
|
|
|
22
22
|
if (vditor.options.focus) {
|
|
23
23
|
vditor.options.focus(getMarkdown(vditor));
|
|
24
24
|
}
|
|
25
|
-
hidePanel(vditor, ["subToolbar"]);
|
|
25
|
+
hidePanel(vditor, ["subToolbar", "hint"]);
|
|
26
26
|
});
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -62,7 +62,7 @@ export const dropEvent = (vditor: IVditor, editorElement: HTMLElement) => {
|
|
|
62
62
|
if (event.dataTransfer.getData(Constants.DROP_EDITOR)) {
|
|
63
63
|
// 编辑器内选中文字拖拽
|
|
64
64
|
execAfterRender(vditor);
|
|
65
|
-
} else if (event.dataTransfer.types
|
|
65
|
+
} else if (event.dataTransfer.types.includes("Files") || event.dataTransfer.types.includes("text/html")) {
|
|
66
66
|
// 外部文件拖入编辑器中或者编辑器内选中文字拖拽
|
|
67
67
|
paste(vditor, event, {
|
|
68
68
|
pasteCode: (code: string) => {
|
|
@@ -2,7 +2,7 @@ import {Constants} from "../constants";
|
|
|
2
2
|
import {input as IRInput} from "../ir/input";
|
|
3
3
|
import {processAfterRender} from "../ir/process";
|
|
4
4
|
import {processAfterRender as processSVAfterRender, processPaste} from "../sv/process";
|
|
5
|
-
import {uploadFiles} from "../upload";
|
|
5
|
+
import {uploadFiles} from "../upload/index";
|
|
6
6
|
import {setHeaders} from "../upload/setHeaders";
|
|
7
7
|
import {afterRenderEvent} from "../wysiwyg/afterRenderEvent";
|
|
8
8
|
import {input} from "../wysiwyg/input";
|
|
@@ -228,9 +228,13 @@ export const listToggle = (vditor: IVditor, range: Range, type: string, cancel =
|
|
|
228
228
|
let element;
|
|
229
229
|
if (type === "list") {
|
|
230
230
|
element = document.createElement("ul");
|
|
231
|
+
element.setAttribute("data-marker", "*");
|
|
231
232
|
} else {
|
|
232
233
|
element = document.createElement("ol");
|
|
234
|
+
element.setAttribute("data-marker", "1.");
|
|
233
235
|
}
|
|
236
|
+
element.setAttribute("data-block", "0");
|
|
237
|
+
element.setAttribute("data-tight", itemElement.parentElement.getAttribute("data-tight"));
|
|
234
238
|
element.innerHTML = itemElement.parentElement.innerHTML;
|
|
235
239
|
itemElement.parentElement.parentNode.replaceChild(element, itemElement.parentElement);
|
|
236
240
|
}
|
|
@@ -973,7 +977,7 @@ export const fixCodeBlock = (vditor: IVditor, event: KeyboardEvent, codeRenderEl
|
|
|
973
977
|
if (event.key === "Backspace" && !isCtrl(event) && !event.shiftKey && !event.altKey) {
|
|
974
978
|
const codePosition = getSelectPosition(codeRenderElement, vditor[vditor.currentMode].element, range);
|
|
975
979
|
if ((codePosition.start === 0 ||
|
|
976
|
-
|
|
980
|
+
(codePosition.start === 1 && codeRenderElement.innerText === "\n")) // 空代码块,光标在 \n 后
|
|
977
981
|
&& range.toString() === "") {
|
|
978
982
|
codeRenderElement.parentElement.outerHTML =
|
|
979
983
|
`<p data-block="0"><wbr>${codeRenderElement.firstElementChild.innerHTML}</p>`;
|
|
@@ -1089,7 +1093,7 @@ export const fixTask = (vditor: IVditor, range: Range, event: KeyboardEvent) =>
|
|
|
1089
1093
|
if (event.key === "Backspace" && !isCtrl(event) && !event.shiftKey && !event.altKey && range.toString() === ""
|
|
1090
1094
|
&& range.startOffset === 1
|
|
1091
1095
|
&& ((startContainer.nodeType === 3 && startContainer.previousSibling &&
|
|
1092
|
-
|
|
1096
|
+
(startContainer.previousSibling as HTMLElement).tagName === "INPUT")
|
|
1093
1097
|
|| startContainer.nodeType !== 3)) {
|
|
1094
1098
|
const previousElement = taskItemElement.previousElementSibling;
|
|
1095
1099
|
taskItemElement.querySelector("input").remove();
|
|
@@ -1260,7 +1264,7 @@ export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent)
|
|
|
1260
1264
|
} else {
|
|
1261
1265
|
textHTML = event.dataTransfer.getData("text/html");
|
|
1262
1266
|
textPlain = event.dataTransfer.getData("text/plain");
|
|
1263
|
-
if (event.dataTransfer.types
|
|
1267
|
+
if (event.dataTransfer.types.includes("Files")) {
|
|
1264
1268
|
files = event.dataTransfer.items;
|
|
1265
1269
|
}
|
|
1266
1270
|
}
|
|
@@ -1351,7 +1355,7 @@ export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent)
|
|
|
1351
1355
|
if (doc.body) {
|
|
1352
1356
|
textHTML = doc.body.innerHTML;
|
|
1353
1357
|
}
|
|
1354
|
-
|
|
1358
|
+
textHTML = Lute.Sanitize(textHTML);
|
|
1355
1359
|
vditor.wysiwyg.getComments(vditor);
|
|
1356
1360
|
|
|
1357
1361
|
// process code
|
|
@@ -1406,7 +1410,7 @@ export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent)
|
|
|
1406
1410
|
processPaste(vditor, vditor.lute.HTML2Md(tempElement.innerHTML).trimRight());
|
|
1407
1411
|
}
|
|
1408
1412
|
vditor.outline.render(vditor);
|
|
1409
|
-
} else if (files.length > 0 && vditor.options.upload.url) {
|
|
1413
|
+
} else if (files.length > 0 && (vditor.options.upload.url || vditor.options.upload.handler)) {
|
|
1410
1414
|
await uploadFiles(vditor, files);
|
|
1411
1415
|
} else if (textPlain.trim() !== "" && files.length === 0) {
|
|
1412
1416
|
if (vditor.currentMode === "ir") {
|