Van 6 jaren geleden
bovenliggende
commit
9e93845fd1

+ 4 - 3
README.md

@@ -72,6 +72,7 @@ Vditor 使用 [MIT](https://opensource.org/licenses/MIT) 开源协议。
 
 ## 鸣谢
 
-* [Turndown](https://github.com/domchristie/turndown):HTML 到 Markdown 的转换器
-* [markdown-it](https://github.com/markdown-it/markdown-it):100% 支持 CommonMark 的 Markdown 解析器
-* [highlight.js](https://github.com/highlightjs/highlight.js):JavaScript 语法高亮
+* [markdown-it](https://github.com/markdown-it/markdown-it):Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed
+* [highlight.js](https://github.com/highlightjs/highlight.js):Javascript syntax highlighter
+* [Turndown](https://github.com/domchristie/turndown):🛏 An HTML to Markdown converter written in JavaScript
+* [mermaid](https://github.com/knsv/mermaid):Generation of diagram and flowchart from text in a similar manner as markdown

+ 3 - 0
src/assets/icons/copy.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32px" height="32px">
+    <path d="M28.681 11.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-11.5c-1.379 0-2.5 1.121-2.5 2.5v23c0 1.378 1.121 2.5 2.5 2.5h19c1.378 0 2.5-1.122 2.5-2.5v-15.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 9.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268v0zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-19c-0.271 0-0.5-0.229-0.5-0.5v-23c0-0.271 0.229-0.5 0.5-0.5 0 0 11.499-0 11.5 0v7c0 0.552 0.448 1 1 1h7v15.5zM18.841 1.319c-1.612-1.182-2.393-1.319-2.841-1.319h-11.5c-1.378 0-2.5 1.121-2.5 2.5v23c0 1.207 0.86 2.217 2 2.45v-25.45c0-0.271 0.229-0.5 0.5-0.5h15.215c-0.301-0.248-0.595-0.477-0.873-0.681z"></path>
+</svg>

+ 28 - 0
src/assets/scss/_content.scss

@@ -57,6 +57,34 @@
     &::-webkit-scrollbar {
       display: none;
     }
+
+    pre:hover div.vditor-copy {
+      display: block;
+    }
+  }
+
+  &-copy {
+    position: relative;
+    display: none;
+
+    textarea {
+      position: absolute;
+      top: -100000px;
+    }
+
+    span {
+      cursor: pointer;
+      position: absolute;
+      right: 0.5em;
+      top: 0.5em;
+      height: 20px;
+      width: 20px;
+    }
+
+    svg {
+      height: 20px;
+      width: 20px;
+    }
   }
 
   &-counter {

+ 2 - 0
src/index.ts

@@ -3,6 +3,7 @@ import {Counter} from "./ts/counter/index";
 import {Editor, html2md, insertText} from "./ts/editor/index";
 import {Hint} from "./ts/hint/index";
 import {Hotkey} from "./ts/hotkey/index";
+import {codeRender} from "./ts/markdown/codeRender";
 import {mathRender} from "./ts/markdown/mathRender";
 import {mermaidRender} from "./ts/markdown/mermaidRender";
 import {md2html, Preview} from "./ts/preview/index";
@@ -17,6 +18,7 @@ class Vditor {
 
     public static mathRender = mathRender;
     public static mermaidRender = mermaidRender;
+    public static codeRender = codeRender;
     public readonly version: string;
     public vditor: IVditor;
 

+ 4 - 0
src/ts/i18n/index.ts

@@ -3,6 +3,8 @@ export const i18n: II18n = {
         "bold": "Blod",
         "check": "Task List",
         "code": "Code Block",
+        "copied": "Copied",
+        "copy": "Copy",
         "emoji": "Emoji",
         "fileTypeError": "file type is error",
         "fullscreen": "Fullscreen",
@@ -32,6 +34,8 @@ export const i18n: II18n = {
         "bold": "粗体",
         "check": "任务列表",
         "code": "代码块",
+        "copied": "已复制",
+        "copy": "复制",
         "emoji": "表情",
         "fileTypeError": "文件类型不允许上传",
         "fullscreen": "全屏",

+ 20 - 0
src/ts/markdown/codeRender.ts

@@ -0,0 +1,20 @@
+import copySVG from "../../assets/icons/copy.svg";
+import {i18n} from "../i18n/index";
+
+export const codeRender = (element: HTMLElement, lang: (keyof II18nLang)) => {
+    element.querySelectorAll("code").forEach((e) => {
+        if (e.className.indexOf("language-mermaid") > -1) {
+            return;
+        }
+        const divElement = document.createElement("div");
+        divElement.className = "vditor-copy";
+        divElement.innerHTML = `<textarea>${e.innerText}</textarea><span aria-label="${i18n[lang].copy}"
+onmouseover="this.setAttribute('aria-label', '${i18n[lang].copy}')"
+class="vditor-tooltipped vditor-tooltipped__w"
+onclick="this.previousElementSibling.select();document.execCommand('copy');` +
+            `this.setAttribute('aria-label', '${i18n[lang].copied}')">${copySVG}</span>`;
+
+        e.before(divElement);
+        e.style.maxHeight = (window.outerHeight - 40) + "px";
+    });
+};

+ 1 - 1
src/ts/markdown/mathRender.ts

@@ -3,7 +3,7 @@ import {addStyle} from "../util/addStyle";
 export const mathRender = (element: HTMLElement) => {
     const text = element.innerText;
     if (text.split("$").length > 2 || (text.split("\\(").length > 1 && text.split("\\)").length > 1)) {
-        import(/* webpackChunkName: "katex" */ "katex").then((katex) => {
+        import(/* webpackChunkName: "katex" */ "katex").then(() => {
             import(/* webpackChunkName: "katex" */ "katex/contrib/auto-render/auto-render")
                 .then((renderMathInElement) => {
                     addStyle("https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css", "vditorKatexStyle");

+ 2 - 2
src/ts/markdown/mermaidRender.ts

@@ -1,6 +1,6 @@
 export const mermaidRender = (element: HTMLElement) => {
-    if (element.querySelectorAll('code.language-mermaid').length === 0) {
-        return
+    if (element.querySelectorAll("code.language-mermaid").length === 0) {
+        return;
     }
     import(/* webpackChunkName: "mermaid" */ "mermaid").then((mermaid) => {
         mermaid.init({noteMargin: 10}, ".language-mermaid");

+ 4 - 2
src/ts/preview/index.ts

@@ -1,3 +1,4 @@
+import {codeRender} from "../markdown/codeRender";
 import {mathRender} from "../markdown/mathRender";
 import {mermaidRender} from "../markdown/mermaidRender";
 import {addStyle} from "../util/addStyle";
@@ -71,6 +72,7 @@ export class Preview {
 
         mathRender(vditor.preview.element);
         mermaidRender(vditor.preview.element);
+        codeRender(vditor.preview.element, vditor.options.lang);
     }
 }
 
@@ -88,8 +90,8 @@ export const md2html = async (vditor: IVditor, includeHljs: boolean) => {
     if (includeHljs) {
         const {default: hljs} = await import(/* webpackChunkName: "highlight.js" */ "highlight.js");
         hljsOpt.highlight = (str: string, lang: string) => {
-            if (lang === 'mermaid') {
-                return str
+            if (lang === "mermaid") {
+                return str;
             }
             if (lang && hljs.getLanguage(lang)) {
                 return hljs.highlight(lang, str, true).value;