vditor 3.10.3 → 3.10.5

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.
Files changed (66) hide show
  1. package/README.md +3 -1
  2. package/dist/index.css +28 -4
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +15672 -0
  5. package/dist/index.min.js +1 -1
  6. package/dist/js/icons/material.js +2 -2
  7. package/dist/method.d.ts +2 -3
  8. package/dist/method.js +2535 -0
  9. package/dist/method.min.js +1 -1
  10. package/dist/ts/export/index.d.ts +0 -1
  11. package/dist/ts/ir/expandMarker.d.ts +0 -1
  12. package/dist/ts/ir/highlightToolbarIR.d.ts +0 -1
  13. package/dist/ts/ir/input.d.ts +0 -1
  14. package/dist/ts/ir/process.d.ts +0 -1
  15. package/dist/ts/ir/processKeydown.d.ts +0 -1
  16. package/dist/ts/markdown/codeRender.d.ts +0 -1
  17. package/dist/ts/markdown/getHTML.d.ts +0 -1
  18. package/dist/ts/markdown/getMarkdown.d.ts +0 -1
  19. package/dist/ts/markdown/highlightRender.d.ts +0 -1
  20. package/dist/ts/markdown/mathRender.d.ts +0 -1
  21. package/dist/ts/markdown/outlineRender.d.ts +0 -1
  22. package/dist/ts/markdown/previewRender.d.ts +0 -1
  23. package/dist/ts/markdown/setLute.d.ts +0 -1
  24. package/dist/ts/markdown/speechRender.d.ts +0 -1
  25. package/dist/ts/preview/image.d.ts +0 -1
  26. package/dist/ts/sv/inputEvent.d.ts +0 -1
  27. package/dist/ts/sv/process.d.ts +0 -1
  28. package/dist/ts/sv/processKeydown.d.ts +0 -1
  29. package/dist/ts/toolbar/index.d.ts +1 -0
  30. package/dist/ts/toolbar/setToolbar.d.ts +0 -1
  31. package/dist/ts/ui/initUI.d.ts +0 -6
  32. package/dist/ts/ui/setPreviewMode.d.ts +0 -1
  33. package/dist/ts/ui/setTheme.d.ts +0 -1
  34. package/dist/ts/upload/getElement.d.ts +0 -1
  35. package/dist/ts/upload/index.d.ts +0 -1
  36. package/dist/ts/upload/setHeaders.d.ts +0 -1
  37. package/dist/ts/util/editorCommonEvent.d.ts +0 -1
  38. package/dist/ts/util/fixBrowserBehavior.d.ts +0 -1
  39. package/dist/ts/util/highlightToolbar.d.ts +0 -1
  40. package/dist/ts/util/processCode.d.ts +0 -1
  41. package/dist/ts/util/selection.d.ts +0 -1
  42. package/dist/ts/util/toc.d.ts +0 -1
  43. package/dist/ts/wysiwyg/afterRenderEvent.d.ts +0 -1
  44. package/dist/ts/wysiwyg/highlightToolbarWYSIWYG.d.ts +0 -1
  45. package/dist/ts/wysiwyg/inlineTag.d.ts +0 -1
  46. package/dist/ts/wysiwyg/input.d.ts +0 -1
  47. package/dist/ts/wysiwyg/processKeydown.d.ts +0 -1
  48. package/dist/ts/wysiwyg/renderDomByMd.d.ts +0 -1
  49. package/dist/ts/wysiwyg/setHeading.d.ts +0 -1
  50. package/dist/ts/wysiwyg/showCode.d.ts +0 -1
  51. package/dist/ts/wysiwyg/toolbarEvent.d.ts +0 -1
  52. package/dist/types/index.d.ts +4 -0
  53. package/package.json +6 -6
  54. package/src/assets/less/_content.less +0 -4
  55. package/src/assets/less/_reset.less +1 -0
  56. package/src/index.ts +4 -0
  57. package/src/ts/markdown/codeRender.ts +1 -1
  58. package/src/ts/markdown/highlightRender.ts +1 -1
  59. package/src/ts/markdown/speechRender.ts +60 -54
  60. package/src/ts/sv/processKeydown.ts +8 -2
  61. package/src/ts/toolbar/Upload.ts +1 -1
  62. package/src/ts/toolbar/index.ts +17 -0
  63. package/src/ts/ui/initUI.ts +0 -6
  64. package/src/ts/ui/setCodeTheme.ts +1 -1
  65. package/src/ts/util/addScript.ts +3 -3
  66. package/src/ts/util/fixBrowserBehavior.ts +5 -1
@@ -5,56 +5,63 @@ declare global {
5
5
  vditorSpeechRange: Range;
6
6
  }
7
7
  }
8
+
8
9
  export const speechRender = (element: HTMLElement, lang: keyof II18n = "zh_CN") => {
9
10
  if (typeof speechSynthesis === "undefined" || typeof SpeechSynthesisUtterance === "undefined") {
10
11
  return;
11
12
  }
13
+
14
+ const getVoice = () => {
15
+ const voices = speechSynthesis.getVoices();
16
+ let currentVoice: SpeechSynthesisVoice;
17
+ let defaultVoice;
18
+ voices.forEach((item) => {
19
+ if (item.lang === lang.replace("_", "-")) {
20
+ currentVoice = item;
21
+ }
22
+ if (item.default) {
23
+ defaultVoice = item;
24
+ }
25
+ });
26
+ if (!currentVoice) {
27
+ currentVoice = defaultVoice;
28
+ }
29
+ return currentVoice;
30
+ };
31
+
12
32
  let playSVG = '<svg><use xlink:href="#vditor-icon-play"></use></svg>';
13
33
  let pauseSVG = '<svg><use xlink:href="#vditor-icon-pause"></use></svg>';
14
34
  if (!document.getElementById("vditorIconScript")) {
15
35
  playSVG = '<svg viewBox="0 0 32 32"><path d="M3.436 0l25.128 16-25.128 16v-32z"></path></svg>';
16
36
  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
37
  }
18
- let speechDom: HTMLDivElement = document.querySelector(".vditor-speech");
38
+
39
+ let speechDom: HTMLButtonElement = document.querySelector(".vditor-speech");
19
40
  if (!speechDom) {
20
- speechDom = document.createElement("div");
41
+ speechDom = document.createElement("button");
21
42
  speechDom.className = "vditor-speech";
22
- document.body.insertAdjacentElement("beforeend", speechDom);
23
-
24
- const getVoice = () => {
25
- const voices = speechSynthesis.getVoices();
26
- let currentVoice;
27
- let defaultVoice;
28
- voices.forEach((item) => {
29
- if (item.lang === lang.replace("_", "-")) {
30
- currentVoice = item;
31
- }
32
- if (item.default) {
33
- defaultVoice = item;
34
- }
35
- });
36
- if (!currentVoice) {
37
- currentVoice = defaultVoice;
38
- }
39
- return currentVoice;
40
- };
41
-
43
+ element.insertAdjacentElement("beforeend", speechDom);
42
44
  if (speechSynthesis.onvoiceschanged !== undefined) {
43
45
  speechSynthesis.onvoiceschanged = getVoice;
44
46
  }
47
+ }
48
+ const voice = getVoice();
49
+ const utterThis = new SpeechSynthesisUtterance();
50
+ utterThis.voice = voice;
51
+ utterThis.onend = utterThis.onerror = () => {
52
+ speechDom.style.display = "none";
53
+ speechSynthesis.cancel();
54
+ speechDom.classList.remove("vditor-speech--current");
55
+ speechDom.innerHTML = playSVG;
56
+ };
45
57
 
46
- const voice = getVoice();
47
- speechDom.onclick = () => {
48
- if (speechDom.className === "vditor-speech") {
49
- const utterThis = new SpeechSynthesisUtterance(speechDom.getAttribute("data-text"));
50
- utterThis.voice = voice;
51
- utterThis.onend = () => {
52
- speechDom.className = "vditor-speech";
53
- speechSynthesis.cancel();
54
- speechDom.innerHTML = playSVG;
55
- };
58
+ element.addEventListener(window.ontouchstart !== undefined ? "touchend" : "click", (event) => {
59
+ const target = event.target as HTMLElement
60
+ if (target.classList.contains("vditor-speech") || target.parentElement.classList.contains("vditor-speech")) {
61
+ if (!speechDom.classList.contains("vditor-speech--current")) {
62
+ utterThis.text = speechDom.getAttribute("data-text");
56
63
  speechSynthesis.speak(utterThis);
57
- speechDom.className = "vditor-speech vditor-speech--current";
64
+ speechDom.classList.add("vditor-speech--current");
58
65
  speechDom.innerHTML = pauseSVG;
59
66
  } else {
60
67
  if (speechSynthesis.speaking) {
@@ -67,35 +74,34 @@ export const speechRender = (element: HTMLElement, lang: keyof II18n = "zh_CN")
67
74
  }
68
75
  }
69
76
  }
70
-
71
77
  setSelectionFocus(window.vditorSpeechRange);
72
- };
73
-
74
- document.body.addEventListener("click", () => {
75
- if (getSelection().toString().trim() === "" && speechDom.style.display === "block") {
76
- speechDom.className = "vditor-speech";
77
- speechSynthesis.cancel();
78
- speechDom.style.display = "none";
79
- }
80
- });
81
- }
78
+ element.focus();
79
+ return;
80
+ }
82
81
 
83
- element.addEventListener("mouseup", (event: MouseEvent) => {
84
- const text = getSelection().toString().trim();
82
+ speechDom.style.display = "none";
85
83
  speechSynthesis.cancel();
86
- if (getSelection().toString().trim() === "") {
87
- if (speechDom.style.display === "block") {
88
- speechDom.className = "vditor-speech";
89
- speechDom.style.display = "none";
90
- }
84
+ speechDom.classList.remove("vditor-speech--current");
85
+ speechDom.innerHTML = playSVG;
86
+
87
+ if (getSelection().rangeCount === 0) {
91
88
  return;
92
89
  }
93
- window.vditorSpeechRange = getSelection().getRangeAt(0).cloneRange();
94
- const rect = getSelection().getRangeAt(0).getBoundingClientRect();
90
+ const range = getSelection().getRangeAt(0)
91
+ const text = range.toString().trim();
92
+ if (!text) {
93
+ return;
94
+ }
95
+ window.vditorSpeechRange = range.cloneRange();
96
+ const rect = range.getBoundingClientRect();
95
97
  speechDom.innerHTML = playSVG;
96
98
  speechDom.style.display = "block";
97
99
  speechDom.style.top = (rect.top + rect.height + document.querySelector("html").scrollTop - 20) + "px";
98
- speechDom.style.left = (event.clientX + 2) + "px";
100
+ if (window.ontouchstart !== undefined) {
101
+ speechDom.style.left = ((event as TouchEvent).changedTouches[(event as TouchEvent).changedTouches.length - 1].pageX + 2) + "px";
102
+ } else {
103
+ speechDom.style.left = ((event as MouseEvent).clientX + 2) + "px";
104
+ }
99
105
  speechDom.setAttribute("data-text", text);
100
106
  });
101
107
  };
@@ -95,8 +95,14 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
95
95
  }
96
96
  // 第一个 marker 后 tab 进行缩进
97
97
  if (event.key === "Tab") {
98
- listFirstMarkerElement.insertAdjacentHTML("beforebegin",
99
- `<span data-type="padding">${listFirstMarkerElement.textContent.replace(/\S/g, " ")}</span>`);
98
+ if (event.shiftKey) {
99
+ if (listFirstMarkerElement.previousElementSibling.getAttribute("data-type") === "padding") {
100
+ listFirstMarkerElement.previousElementSibling.remove();
101
+ }
102
+ } else {
103
+ listFirstMarkerElement.insertAdjacentHTML("beforebegin",
104
+ `<span data-type="padding">${listFirstMarkerElement.textContent.replace(/\S/g, " ")}</span>`);
105
+ }
100
106
  if (/^\d/.test(listFirstMarkerElement.textContent)) {
101
107
  listFirstMarkerElement.textContent = listFirstMarkerElement.textContent.replace(/^\d{1,}/, "1");
102
108
  range.selectNodeContents(listLastMarkerElement.firstChild);
@@ -1,5 +1,5 @@
1
1
  import {Constants} from "../constants";
2
- import {uploadFiles} from "../upload";
2
+ import {uploadFiles} from "../upload/index";
3
3
  import {getEventName} from "../util/compatibility";
4
4
  import {MenuItem} from "./MenuItem";
5
5
 
@@ -69,6 +69,23 @@ export class Toolbar {
69
69
  }
70
70
  }
71
71
 
72
+ public updateConfig(vditor: IVditor, options: IToolbarConfig) {
73
+ vditor.options.toolbarConfig = Object.assign({
74
+ hide: false,
75
+ pin: false,
76
+ }, options);
77
+ if (vditor.options.toolbarConfig.hide) {
78
+ this.element.classList.add("vditor-toolbar--hide");
79
+ } else {
80
+ this.element.classList.remove("vditor-toolbar--hide");
81
+ }
82
+ if (vditor.options.toolbarConfig.pin) {
83
+ this.element.classList.add("vditor-toolbar--pin");
84
+ } else {
85
+ this.element.classList.remove("vditor-toolbar--pin");
86
+ }
87
+ }
88
+
72
89
  private genItem(vditor: IVditor, menuItem: IMenuItem, index: number) {
73
90
  let menuItemObj;
74
91
  switch (menuItem.name) {
@@ -5,12 +5,6 @@ import {accessLocalStorage} from "../util/compatibility";
5
5
  import {setContentTheme} from "./setContentTheme";
6
6
  import {setTheme} from "./setTheme";
7
7
 
8
- declare global {
9
- interface Window {
10
- visualViewport: HTMLElement;
11
- }
12
- }
13
-
14
8
  export const initUI = (vditor: IVditor) => {
15
9
  vditor.element.innerHTML = "";
16
10
  vditor.element.classList.add("vditor");
@@ -9,7 +9,7 @@ export const setCodeTheme = (codeTheme: string, cdn = Constants.CDN) => {
9
9
  const href = `${cdn}/dist/js/highlight.js/styles/${codeTheme}.css`;
10
10
  if (!vditorHljsStyle) {
11
11
  addStyle(href, "vditorHljsStyle");
12
- } else if (vditorHljsStyle.href !== href) {
12
+ } else if (vditorHljsStyle.getAttribute('href') !== href) {
13
13
  vditorHljsStyle.remove();
14
14
  addStyle(href, "vditorHljsStyle");
15
15
  }
@@ -18,7 +18,7 @@ export const addScript = (path: string, id: string) => {
18
18
  return new Promise((resolve, reject) => {
19
19
  if (document.getElementById(id)) {
20
20
  // 脚本加载后再次调用直接返回
21
- resolve();
21
+ resolve(true);
22
22
  return false;
23
23
  }
24
24
  const scriptElement = document.createElement("script");
@@ -33,11 +33,11 @@ export const addScript = (path: string, id: string) => {
33
33
  if (document.getElementById(id)) {
34
34
  // 循环调用需清除 DOM 中的 script 标签
35
35
  scriptElement.remove();
36
- resolve();
36
+ resolve(true);
37
37
  return false;
38
38
  }
39
39
  scriptElement.id = id;
40
- resolve();
40
+ resolve(true);
41
41
  };
42
42
  });
43
43
  };
@@ -1290,6 +1290,10 @@ export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent)
1290
1290
  return ["", Lute.WalkContinue];
1291
1291
  }
1292
1292
 
1293
+ if (vditor.options.upload.renderLinkDest) {
1294
+ return vditor.options.upload.renderLinkDest(vditor, node, entering);
1295
+ }
1296
+
1293
1297
  const src = node.TokensStr();
1294
1298
  if (node.__internal_object__.Parent.Type === 34 && src && src.indexOf("file://") === -1 &&
1295
1299
  vditor.options.upload.linkToImgUrl) {
@@ -1448,7 +1452,7 @@ export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent)
1448
1452
  }
1449
1453
  } else if (textPlain.trim() !== "" && files.length === 0) {
1450
1454
  const range = getEditorRange(vditor);
1451
- if (range.toString() !== "" && vditor.lute.IsValidLinkDest(textPlain)) {
1455
+ if (range.toString() !== "" && vditor.lute.IsValidLinkDest(textPlain)) {
1452
1456
  textPlain = `[${range.toString()}](${textPlain})`;
1453
1457
  }
1454
1458
  if (vditor.currentMode === "ir") {