vditor 3.8.9 → 3.8.12

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 (53) hide show
  1. package/README.md +2 -2
  2. package/dist/index.css +2 -2
  3. package/dist/index.min.js +1 -15454
  4. package/dist/js/highlight.js/styles/abap.css +7 -7
  5. package/dist/js/highlight.js/styles/algol.css +7 -6
  6. package/dist/js/highlight.js/styles/algol_nu.css +7 -7
  7. package/dist/js/highlight.js/styles/arduino.css +7 -5
  8. package/dist/js/highlight.js/styles/autumn.css +7 -5
  9. package/dist/js/highlight.js/styles/borland.css +7 -6
  10. package/dist/js/highlight.js/styles/bw.css +7 -6
  11. package/dist/js/highlight.js/styles/colorful.css +7 -5
  12. package/dist/js/highlight.js/styles/dracula.css +9 -8
  13. package/dist/js/highlight.js/styles/emacs.css +7 -6
  14. package/dist/js/highlight.js/styles/friendly.css +7 -6
  15. package/dist/js/highlight.js/styles/fruity.css +7 -5
  16. package/dist/js/highlight.js/styles/github.css +7 -6
  17. package/dist/js/highlight.js/styles/igor.css +7 -5
  18. package/dist/js/highlight.js/styles/lovelace.css +7 -6
  19. package/dist/js/highlight.js/styles/manni.css +7 -6
  20. package/dist/js/highlight.js/styles/monokai.css +7 -6
  21. package/dist/js/highlight.js/styles/monokailight.css +7 -6
  22. package/dist/js/highlight.js/styles/murphy.css +7 -7
  23. package/dist/js/highlight.js/styles/native.css +7 -6
  24. package/dist/js/highlight.js/styles/paraiso-dark.css +7 -6
  25. package/dist/js/highlight.js/styles/paraiso-light.css +7 -6
  26. package/dist/js/highlight.js/styles/pastie.css +7 -7
  27. package/dist/js/highlight.js/styles/perldoc.css +7 -6
  28. package/dist/js/highlight.js/styles/pygments.css +7 -6
  29. package/dist/js/highlight.js/styles/rainbow_dash.css +7 -6
  30. package/dist/js/highlight.js/styles/rrt.css +7 -6
  31. package/dist/js/highlight.js/styles/solarized-dark.css +7 -6
  32. package/dist/js/highlight.js/styles/solarized-dark256.css +7 -6
  33. package/dist/js/highlight.js/styles/solarized-light.css +7 -6
  34. package/dist/js/highlight.js/styles/swapoff.css +7 -7
  35. package/dist/js/highlight.js/styles/tango.css +7 -7
  36. package/dist/js/highlight.js/styles/trac.css +7 -6
  37. package/dist/js/highlight.js/styles/vim.css +7 -6
  38. package/dist/js/highlight.js/styles/vs.css +7 -6
  39. package/dist/js/highlight.js/styles/xcode.css +7 -6
  40. package/dist/js/katex/mhchem.min.js +1 -0
  41. package/dist/js/lute/lute.min.js +10 -9
  42. package/dist/method.min.js +1 -2355
  43. package/dist/ts/toolbar/Emoji.d.ts +1 -1
  44. package/package.json +5 -5
  45. package/src/ts/markdown/codeRender.ts +8 -4
  46. package/src/ts/markdown/mathRender.ts +29 -27
  47. package/src/ts/markdown/outlineRender.ts +5 -1
  48. package/src/ts/markdown/previewRender.ts +4 -3
  49. package/src/ts/markdown/speechRender.ts +6 -2
  50. package/src/ts/toolbar/Emoji.ts +19 -20
  51. package/src/ts/undo/index.ts +3 -0
  52. package/src/ts/upload/index.ts +1 -1
  53. package/src/ts/wysiwyg/highlightToolbarWYSIWYG.ts +12 -18
@@ -3,5 +3,5 @@ import { MenuItem } from "./MenuItem";
3
3
  export declare class Emoji extends MenuItem {
4
4
  element: HTMLElement;
5
5
  constructor(vditor: IVditor, menuItem: IMenuItem);
6
- _bindEvent(vditor: IVditor, panelElement: HTMLElement): void;
6
+ private bindEvent;
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vditor",
3
- "version": "3.8.9",
3
+ "version": "3.8.12",
4
4
  "description": "♏ 易于使用的 Markdown 编辑器,为适配不同的应用场景而生",
5
5
  "author": "Vanessa <v@b3log.org> (http://vanessa.b3log.org)",
6
6
  "homepage": "https://b3log.org/vditor",
@@ -24,7 +24,7 @@
24
24
  "@types/diff-match-patch": "^1.0.32",
25
25
  "@types/jest": "^26.0.23",
26
26
  "@types/puppeteer": "^2.1.5",
27
- "autoprefixer": "^9.8.6",
27
+ "autoprefixer": "^10.4.2",
28
28
  "babel-loader": "^8.2.2",
29
29
  "clean-webpack-plugin": "^4.0.0-alpha.0",
30
30
  "copy-webpack-plugin": "^6.4.1",
@@ -39,14 +39,14 @@
39
39
  "puppeteer": "^1.20.0",
40
40
  "sass-loader": "^12.4.0",
41
41
  "style-loader": "^1.3.0",
42
- "terser-webpack-plugin": "^5.1.2",
42
+ "terser-webpack-plugin": "^5.3.0",
43
43
  "ts-jest": "^26.5.6",
44
44
  "ts-loader": "^6.2.2",
45
45
  "tslint": "^5.20.1",
46
46
  "typescript": "^3.9.9",
47
- "webpack": "^5.37.0",
47
+ "webpack": "^5.66.0",
48
48
  "webpack-bundle-analyzer": "^3.9.0",
49
- "webpack-cli": "^4.7.0",
49
+ "webpack-cli": "^4.9.1",
50
50
  "webpack-dev-server": "^4.1.0"
51
51
  },
52
52
  "license": "MIT",
@@ -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.copy}"
39
- onmouseover="this.setAttribute('aria-label', '${window.VditorI18n.copy}')"
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);
@@ -42,33 +42,35 @@ export const mathRender = (element: HTMLElement, options?: { cdn?: string, math?
42
42
  if (options.math.engine === "KaTeX") {
43
43
  addStyle(`${options.cdn}/dist/js/katex/katex.min.css`, "vditorKatexStyle");
44
44
  addScript(`${options.cdn}/dist/js/katex/katex.min.js`, "vditorKatexScript").then(() => {
45
- mathElements.forEach((mathElement) => {
46
- if (mathElement.parentElement.classList.contains("vditor-wysiwyg__pre") ||
47
- mathElement.parentElement.classList.contains("vditor-ir__marker--pre")) {
48
- return;
49
- }
50
- if (mathElement.getAttribute("data-math")) {
51
- return;
52
- }
53
- const math = code160to32(mathRenderAdapter.getCode(mathElement));
54
- mathElement.setAttribute("data-math", math);
55
- try {
56
- mathElement.innerHTML = katex.renderToString(math, {
57
- displayMode: mathElement.tagName === "DIV",
58
- output: "html",
59
- });
60
- } catch (e) {
61
- mathElement.innerHTML = e.message;
62
- mathElement.className = "language-math vditor-reset--error";
63
- }
45
+ addScript(`${options.cdn}/dist/js/katex/mhchem.min.js`, "vditorKatexChemScript").then(() => {
46
+ mathElements.forEach((mathElement) => {
47
+ if (mathElement.parentElement.classList.contains("vditor-wysiwyg__pre") ||
48
+ mathElement.parentElement.classList.contains("vditor-ir__marker--pre")) {
49
+ return;
50
+ }
51
+ if (mathElement.getAttribute("data-math")) {
52
+ return;
53
+ }
54
+ const math = code160to32(mathRenderAdapter.getCode(mathElement));
55
+ mathElement.setAttribute("data-math", math);
56
+ try {
57
+ mathElement.innerHTML = katex.renderToString(math, {
58
+ displayMode: mathElement.tagName === "DIV",
59
+ output: "html",
60
+ });
61
+ } catch (e) {
62
+ mathElement.innerHTML = e.message;
63
+ mathElement.className = "language-math vditor-reset--error";
64
+ }
64
65
 
65
- mathElement.addEventListener("copy", (event: ClipboardEvent) => {
66
- event.stopPropagation();
67
- event.preventDefault();
68
- const vditorMathElement = (event.currentTarget as HTMLElement).closest(".language-math");
69
- event.clipboardData.setData("text/html", vditorMathElement.innerHTML);
70
- event.clipboardData.setData("text/plain",
71
- vditorMathElement.getAttribute("data-math"));
66
+ mathElement.addEventListener("copy", (event: ClipboardEvent) => {
67
+ event.stopPropagation();
68
+ event.preventDefault();
69
+ const vditorMathElement = (event.currentTarget as HTMLElement).closest(".language-math");
70
+ event.clipboardData.setData("text/html", vditorMathElement.innerHTML);
71
+ event.clipboardData.setData("text/plain",
72
+ vditorMathElement.getAttribute("data-math"));
73
+ });
72
74
  });
73
75
  });
74
76
  });
@@ -88,7 +90,7 @@ export const mathRender = (element: HTMLElement, options?: { cdn?: string, math?
88
90
  if (!window.MathJax) {
89
91
  window.MathJax = {
90
92
  loader: {
91
- paths: { mathjax: `${options.cdn}/dist/js/mathjax` },
93
+ paths: {mathjax: `${options.cdn}/dist/js/mathjax`},
92
94
  },
93
95
  startup: {
94
96
  typeset: false,
@@ -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
- item.innerHTML = `<svg class='vditor-outline__action'><use xlink:href='#vditor-icon-down'></use></svg><span>${item.innerHTML}</span>`;
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
  }
@@ -103,6 +103,10 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st
103
103
  window.VditorI18n = mergedOptions.i18n;
104
104
  }
105
105
 
106
+ if (mergedOptions.icon) {
107
+ await addScript(`${mergedOptions.cdn}/dist/js/icons/${mergedOptions.icon}.js`, "vditorIconScript");
108
+ }
109
+
106
110
  setContentTheme(mergedOptions.theme.current, mergedOptions.theme.path);
107
111
  if (mergedOptions.anchor === 1) {
108
112
  previewElement.classList.add("vditor-reset--anchor");
@@ -133,9 +137,6 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st
133
137
  if (mergedOptions.lazyLoadImage) {
134
138
  lazyLoadImageRender(previewElement);
135
139
  }
136
- if (mergedOptions.icon) {
137
- addScript(`${mergedOptions.cdn}/dist/js/icons/${mergedOptions.icon}.js`, "vditorIconScript");
138
- }
139
140
  previewElement.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => {
140
141
  const spanElement = hasClosestByMatchTag(event.target, "SPAN");
141
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
- const playSVG = '<svg><use xlink:href="#vditor-icon-play"></use></svg>';
13
- const pauseSVG = '<svg><use xlink:href="#vditor-icon-pause"></use></svg>';
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");
@@ -1,5 +1,6 @@
1
1
  import {getEventName} from "../util/compatibility";
2
2
  import {execAfterRender} from "../util/fixBrowserBehavior";
3
+ import {hasClosestByTag} from "../util/hasClosestByHeadings";
3
4
  import {getEditorRange, insertHTML, setSelectionFocus} from "../util/selection";
4
5
  import {MenuItem} from "./MenuItem";
5
6
  import {toggleSubMenu} from "./setToolbar";
@@ -23,26 +24,24 @@ data-value=":${key}: " data-key=":${key}:" class="vditor-emojis__icon" src="${em
23
24
  data-key="${key}"><span class="vditor-emojis__icon">${emojiValue}</span></button>`;
24
25
  }
25
26
  });
26
-
27
- const tailHTML = `<div class="vditor-emojis__tail">
28
- <span class="vditor-emojis__tip"></span><span>${vditor.options.hint.emojiTail || ""}</span>
29
- </div>`;
30
-
31
27
  panelElement.innerHTML = `<div class="vditor-emojis" style="max-height: ${
32
28
  vditor.options.height === "auto" ? "auto" : vditor.options.height as number - 80
33
- }px">${commonEmojiHTML}</div>${tailHTML}`;
29
+ }px">${commonEmojiHTML}</div><div class="vditor-emojis__tail">
30
+ <span class="vditor-emojis__tip"></span><span>${vditor.options.hint.emojiTail || ""}</span>
31
+ </div>`;
34
32
 
35
33
  this.element.appendChild(panelElement);
36
34
 
37
- toggleSubMenu(vditor, panelElement, this.element.children[0], menuItem.level);
38
- this._bindEvent(vditor, panelElement);
35
+ toggleSubMenu(vditor, panelElement, this.element.firstElementChild, menuItem.level);
36
+ this.bindEvent(vditor);
39
37
  }
40
38
 
41
- public _bindEvent(vditor: IVditor, panelElement: HTMLElement) {
42
- panelElement.querySelectorAll(".vditor-emojis button").forEach((element: HTMLElement) => {
43
- element.addEventListener(getEventName(), (event: Event) => {
39
+ private bindEvent(vditor: IVditor) {
40
+ this.element.lastElementChild.addEventListener(getEventName(), (event: Event & { target: Element }) => {
41
+ const btnElement = hasClosestByTag(event.target, "BUTTON");
42
+ if (btnElement) {
44
43
  event.preventDefault();
45
- const value = element.getAttribute("data-value");
44
+ const value = btnElement.getAttribute("data-value");
46
45
  const range = getEditorRange(vditor);
47
46
  let html = value;
48
47
  if (vditor.currentMode === "wysiwyg") {
@@ -61,15 +60,15 @@ data-value=":${key}: " data-key=":${key}:" class="vditor-emojis__icon" src="${em
61
60
  }
62
61
  range.collapse(false);
63
62
  setSelectionFocus(range);
64
- panelElement.style.display = "none";
63
+ (this.element.lastElementChild as HTMLElement).style.display = "none";
65
64
  execAfterRender(vditor);
66
- });
67
- element.addEventListener("mouseover", (event: Event) => {
68
- if ((event.target as HTMLElement).tagName === "BUTTON") {
69
- panelElement.querySelector(".vditor-emojis__tip").innerHTML =
70
- (event.target as HTMLElement).getAttribute("data-key");
71
- }
72
- });
65
+ }
66
+ });
67
+ this.element.lastElementChild.addEventListener("mouseover", (event: Event & { target: Element }) => {
68
+ const btnElement = hasClosestByTag(event.target, "BUTTON");
69
+ if (btnElement) {
70
+ this.element.querySelector(".vditor-emojis__tip").innerHTML = btnElement.getAttribute("data-key");
71
+ }
73
72
  });
74
73
  }
75
74
  }
@@ -6,6 +6,7 @@ import {execAfterRender} from "../util/fixBrowserBehavior";
6
6
  import {highlightToolbar} from "../util/highlightToolbar";
7
7
  import {processCodeRender} from "../util/processCode";
8
8
  import {setRangeByWbr, setSelectionFocus} from "../util/selection";
9
+ import {renderToc} from "../util/toc";
9
10
 
10
11
  interface IUndo {
11
12
  hasUndo: boolean;
@@ -165,6 +166,8 @@ class Undo {
165
166
  scrollCenter(vditor);
166
167
  }
167
168
 
169
+ renderToc(vditor);
170
+
168
171
  execAfterRender(vditor, {
169
172
  enableAddUndoStack: false,
170
173
  enableHint: false,
@@ -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>&lt;audio controls="controls" src="${path}"&gt;&lt;/audio&gt;</code></pre>\n`;
111
+ data-block="0"><pre><code>&lt;audio controls="controls" src="${path}"&gt;&lt;/audio&gt;</code></pre><pre class="vditor-wysiwyg__preview" data-render="1"><audio controls="controls" src="${path}"></audio></pre></div>\n`;
112
112
  } else if (vditor.currentMode === "ir") {
113
113
  succFileText += `<audio controls="controls" src="${path}"></audio>\n`;
114
114
  } else {
@@ -588,14 +588,18 @@ export const highlightToolbarWYSIWYG = (vditor: IVditor) => {
588
588
  setPopoverPosition(vditor, footnotesRefElement);
589
589
  }
590
590
 
591
- let blockRenderElement = hasClosestByClassName(typeElement, "vditor-wysiwyg__block") as HTMLElement;
592
591
  // block popover: math-inline, math-block, html-block, html-inline, code-block, html-entity
593
- if (
594
- blockRenderElement &&
595
- blockRenderElement.getAttribute("data-type").indexOf("block") > -1
596
- ) {
597
- const lang: keyof II18n | "" = vditor.options.lang;
598
- const options: IOptions = vditor.options;
592
+ let blockRenderElement = hasClosestByClassName(typeElement, "vditor-wysiwyg__block") as HTMLElement;
593
+ const isBlock = blockRenderElement ? blockRenderElement.getAttribute("data-type").indexOf("block") > -1 : false;
594
+ vditor.wysiwyg.element
595
+ .querySelectorAll(".vditor-wysiwyg__preview")
596
+ .forEach((itemElement) => {
597
+ if (!blockRenderElement || (blockRenderElement && isBlock && !blockRenderElement.contains(itemElement))) {
598
+ const previousElement = itemElement.previousElementSibling as HTMLElement;
599
+ previousElement.style.display = "none";
600
+ }
601
+ });
602
+ if (blockRenderElement && isBlock) {
599
603
  vditor.wysiwyg.popover.innerHTML = "";
600
604
  genUp(range, blockRenderElement, vditor);
601
605
  genDown(range, blockRenderElement, vditor);
@@ -694,17 +698,8 @@ export const highlightToolbarWYSIWYG = (vditor: IVditor) => {
694
698
  }
695
699
  setPopoverPosition(vditor, blockRenderElement);
696
700
  } else {
697
- if (!blockRenderElement) {
698
- vditor.wysiwyg.element
699
- .querySelectorAll(".vditor-wysiwyg__preview")
700
- .forEach((itemElement) => {
701
- const previousElement = itemElement.previousElementSibling as HTMLElement;
702
- previousElement.style.display = "none";
703
- });
704
- }
705
701
  blockRenderElement = undefined;
706
702
  }
707
-
708
703
  if (headingElement) {
709
704
  vditor.wysiwyg.popover.innerHTML = "";
710
705
 
@@ -972,8 +967,6 @@ const linkHotkey = (
972
967
  };
973
968
 
974
969
  export const genAPopover = (vditor: IVditor, aElement: HTMLElement) => {
975
- const lang: keyof II18n | "" = vditor.options.lang;
976
- const options: IOptions = vditor.options;
977
970
  vditor.wysiwyg.popover.innerHTML = "";
978
971
 
979
972
  const updateA = () => {
@@ -982,6 +975,7 @@ export const genAPopover = (vditor: IVditor, aElement: HTMLElement) => {
982
975
  }
983
976
  aElement.setAttribute("href", input1.value);
984
977
  aElement.setAttribute("title", input2.value);
978
+ afterRenderEvent(vditor);
985
979
  };
986
980
 
987
981
  aElement.querySelectorAll("[data-marker]").forEach((item: HTMLElement) => {