Liyuan Li 5 yıl önce
ebeveyn
işleme
17a4f20202

+ 4 - 2
CHANGELOG.md

@@ -110,12 +110,14 @@
   * 为 `options.toolbar` 添加 outdent,indent, outline
   * 添加静态方法 `outlineRender`
   * options.preview.maxWidth 默认值改为 800
-  * IPreviewOptions 添加 `after`,`lazyLoadImage`
   * 添加 lazyLoadImageRender 静态方法
-  * `setTheme` 方法添加 `codeTheme` 参数
   * insert line 默认快捷键由 `⌘-⇧-D` 修改为 `⌘-⇧-H`,添加下移 `⌘-⇧-D`、上移 `⌘-⇧-U` 快捷键,移除上传、编辑器模式切换快捷键
   * 为 `options.toolbar` 添加 toolbar 参数,最多可进行 3 级菜单
   * 为 `options.toolbar` 添加 outdent,indent, outline, insert-after, insert-before, 子菜单,code-theme, content-theme
+  
+  * `setTheme` 方法添加 `conentTheme`, `codeTheme` 参数
+  * `options.preview.markdonw` 添加 `theme` 配置
+  * IPreviewOptions 添加 `after`,`lazyLoadImage`, `markdown.theme`,移除 `theme`
 
 ### v3.0.12 / 2020-04-06
 

+ 0 - 8
src/assets/scss/_reset.scss

@@ -11,14 +11,6 @@
       line-height: 16px;
     }
 
-    &--dark {
-      background-color: var(--textarea-background-color);
-
-      a {
-        color: #4285f4;
-      }
-    }
-
     color: var(--textarea-text-color);
     font-variant-ligatures: no-common-ligatures;
     font-family: $font-family-base;

+ 105 - 0
src/assets/scss/content-theme/dark.scss

@@ -0,0 +1,105 @@
+.vditor {
+  &-reset {
+    color: #d1d5da;
+
+    h1 {
+      border-bottom: 1px solid #d1d5da;
+    }
+
+    h2 {
+      border-bottom: 1px solid #d1d5da;
+    }
+
+    hr {
+      background-color: #d1d5da;
+    }
+
+    blockquote {
+      padding: 0 1em;
+      color: #b9b9b9;
+      border-left: 0.25em solid #d1d5da;
+    }
+
+    iframe {
+      border: 1px solid #141414;
+    }
+
+    table {
+
+      tr {
+        background-color: #2f363d;
+      }
+
+      td,
+      th {
+        border: 1px solid #dfe2e5;
+      }
+
+      tbody tr:nth-child(2n) {
+        background-color: #24292e;
+      }
+    }
+
+    code:not(.hljs):not(.highlight-chroma) {
+      background-color: rgba(66, 133, 244, 0.36);
+
+      &.language-mermaid,
+      &.language-math,
+      &.language-graphviz,
+      &.language-echarts {
+        background-color: rgba(120, 146, 190, 0.55);
+      }
+    }
+
+
+    kbd {
+      color: #d1d5da;
+      background-color: #2f363d;
+      border: solid 1px #141414;
+      box-shadow: inset 0 -1px 0 #141414;
+    }
+  }
+
+  &-copy {
+    svg {
+      color: #b9b9b9;
+    }
+  }
+
+  &-speech {
+    background-color: #1d2125;
+    border: 1px solid #141414;
+    color: #b9b9b9;
+
+    &:hover,
+    &--current {
+      color: #fff;
+    }
+  }
+
+  &-linkcard {
+    a {
+      background-color: #1d2125;
+
+      &:visited .vditor-linkcard__abstract {
+        color: rgba(185, 185, 185, .36);
+      }
+    }
+
+    &__title {
+      color: #d1d5da;
+    }
+
+    &__abstract {
+      color: #b9b9b9;
+    }
+
+    &__site {
+      color: #fff;
+    }
+
+    &__image {
+      background-color: rgba(185, 185, 185, .36);
+    }
+  }
+}

+ 1 - 2
src/assets/scss/index.scss

@@ -10,8 +10,7 @@ $transition: all .15s ease-in-out !default;
 
 $max-width: 520px !default;
 
-.vditor,
-.vditor-reset {
+.vditor {
   --border-color: #d1d5da;
   --second-color: rgba(88, 96, 105, 0.36);
 

+ 12 - 2
src/index.ts

@@ -18,6 +18,8 @@ import {Toolbar} from "./ts/toolbar/index";
 import {disableToolbar, hidePanel} from "./ts/toolbar/setToolbar";
 import {enableToolbar} from "./ts/toolbar/setToolbar";
 import {initUI} from "./ts/ui/initUI";
+import {setCodeTheme} from "./ts/ui/setCodeTheme";
+import {setContentTheme} from "./ts/ui/setContentTheme";
 import {setPreviewMode} from "./ts/ui/setPreviewMode";
 import {setTheme} from "./ts/ui/setTheme";
 import {Undo} from "./ts/undo";
@@ -127,9 +129,17 @@ class Vditor extends VditorMethod {
     }
 
     /** 设置主题 */
-    public setTheme(theme: "dark" | "classic", codeTheme?: string) {
+    public setTheme(theme: "dark" | "classic", contentTheme?: string, codeTheme?: string) {
         this.vditor.options.theme = theme;
-        setTheme(this.vditor, codeTheme);
+        setTheme(this.vditor);
+        if (contentTheme) {
+            this.vditor.options.preview.markdown.theme = contentTheme;
+            setContentTheme(contentTheme, this.vditor.options.cdn);
+        }
+        if (codeTheme) {
+            this.vditor.options.preview.hljs.style = codeTheme;
+            setCodeTheme(codeTheme, this.vditor.options.cdn);
+        }
     }
 
     /** 获取编辑器内容 */

+ 3 - 6
src/ts/markdown/previewRender.ts

@@ -1,4 +1,5 @@
 import {VDITOR_VERSION} from "../constants";
+import {setContentTheme} from "../ui/setContentTheme";
 import {addScript} from "../util/addScript";
 import {abcRender} from "./abcRender";
 import {anchorRender} from "./anchorRender";
@@ -33,6 +34,7 @@ const mergeOptions = (options?: IPreviewOptions) => {
             fixTermTypo: false,
             footnotes: true,
             setext: true,
+            theme: "light",
             toc: false,
         },
         math: {
@@ -43,7 +45,6 @@ const mergeOptions = (options?: IPreviewOptions) => {
         speech: {
             enable: false,
         },
-        theme: "classic",
     };
     if (options?.hljs) {
         options.hljs = Object.assign({}, defaultOption.hljs, options.hljs);
@@ -89,11 +90,7 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st
     }
     previewElement.innerHTML = html;
     previewElement.classList.add("vditor-reset");
-    if (mergedOptions.theme === "dark") {
-        previewElement.classList.add("vditor-reset--dark");
-    } else {
-        previewElement.classList.remove("vditor-reset--dark");
-    }
+    setContentTheme(mergedOptions.markdown.theme, mergedOptions.cdn);
     if (mergedOptions.anchor) {
         previewElement.classList.add("vditor-reset--anchor");
     }

+ 3 - 26
src/ts/toolbar/CodeTheme.ts

@@ -1,32 +1,8 @@
 import {Constants} from "../constants";
+import {setCodeTheme} from "../ui/setCodeTheme";
 import {getEventName} from "../util/compatibility";
 import {MenuItem} from "./MenuItem";
 import {hidePanel, toggleSubMenu} from "./setToolbar";
-import {highlightRender} from "../markdown/highlightRender";
-
-export const setCodeTheme = (vditor: IVditor, codeTheme: string) => {
-    if (!codeTheme) {
-        return;
-    }
-    vditor.options.preview.hljs.style = codeTheme;
-    if (vditor.currentMode === "sv") {
-        if (vditor.preview.element.style.display !== "none") {
-            highlightRender({
-                    enable: vditor.options.preview.hljs.enable,
-                    lineNumber: vditor.options.preview.hljs.lineNumber,
-                    style: vditor.options.preview.hljs.style,
-                },
-                vditor.preview.element, vditor.options.cdn);
-        }
-    } else {
-        highlightRender({
-                enable: true,
-                lineNumber: vditor.options.preview.hljs.lineNumber,
-                style: vditor.options.preview.hljs.style,
-            },
-            vditor[vditor.currentMode].element, vditor.options.cdn);
-    }
-};
 
 export class CodeTheme extends MenuItem {
     public element: HTMLElement;
@@ -47,7 +23,8 @@ export class CodeTheme extends MenuItem {
         panelElement.addEventListener(getEventName(), (event: MouseEvent & { target: HTMLElement }) => {
             if (event.target.tagName === "BUTTON") {
                 hidePanel(vditor, ["subToolbar"]);
-                setCodeTheme(vditor, event.target.textContent);
+                vditor.options.preview.hljs.style = event.target.textContent;
+                setCodeTheme(event.target.textContent, vditor.options.cdn);
                 event.preventDefault();
                 event.stopPropagation();
             }

+ 3 - 17
src/ts/toolbar/ContentTheme.ts

@@ -1,24 +1,9 @@
 import {Constants} from "../constants";
+import {setContentTheme} from "../ui/setContentTheme";
 import {getEventName} from "../util/compatibility";
 import {MenuItem} from "./MenuItem";
 import {hidePanel, toggleSubMenu} from "./setToolbar";
 
-export const setContentTheme = (vditor: IVditor, contentTheme: string) => {
-    if (contentTheme === "dark") {
-        if (vditor.preview) {
-            vditor.preview.element.firstElementChild.classList.add("vditor-reset--dark");
-        }
-        vditor.wysiwyg.element.classList.add("vditor-reset--dark");
-        vditor.ir.element.classList.add("vditor-reset--dark");
-    } else {
-        if (vditor.preview) {
-            vditor.preview.element.firstElementChild.classList.remove("vditor-reset--dark");
-        }
-        vditor.wysiwyg.element.classList.remove("vditor-reset--dark");
-        vditor.ir.element.classList.remove("vditor-reset--dark");
-    }
-}
-
 export class ContentTheme extends MenuItem {
     public element: HTMLElement;
 
@@ -38,7 +23,8 @@ export class ContentTheme extends MenuItem {
         panelElement.addEventListener(getEventName(), (event: MouseEvent & { target: HTMLElement }) => {
             if (event.target.tagName === "BUTTON") {
                 hidePanel(vditor, ["subToolbar"]);
-                setContentTheme(vditor, event.target.textContent);
+                vditor.options.preview.markdown.theme = event.target.textContent;
+                setContentTheme(event.target.textContent, vditor.options.cdn);
                 event.preventDefault();
                 event.stopPropagation();
             }

+ 1 - 1
src/ts/toolbar/index.ts

@@ -2,6 +2,7 @@ import {getEventName} from "../util/compatibility";
 import {Both} from "./Both";
 import {Br} from "./Br";
 import {CodeTheme} from "./CodeTheme";
+import {ContentTheme} from "./ContentTheme";
 import {Counter} from "./Counter";
 import {Custom} from "./Custom";
 import {Devtools} from "./Devtools";
@@ -25,7 +26,6 @@ import {Redo} from "./Redo";
 import {toggleSubMenu} from "./setToolbar";
 import {Undo} from "./Undo";
 import {Upload} from "./Upload";
-import {ContentTheme} from "./ContentTheme";
 
 export class Toolbar {
     public elements: { [key: string]: HTMLElement };

+ 2 - 0
src/ts/ui/initUI.ts

@@ -1,12 +1,14 @@
 import {i18n} from "../i18n";
 import {html2md} from "../sv/html2md";
 import {setEditMode} from "../toolbar/EditMode";
+import {setContentTheme} from "./setContentTheme";
 import {setTheme} from "./setTheme";
 
 export const initUI = (vditor: IVditor) => {
     vditor.element.innerHTML = "";
     vditor.element.classList.add("vditor");
     setTheme(vditor);
+    setContentTheme(vditor.options.preview.markdown.theme, vditor.options.cdn);
     if (typeof vditor.options.height === "number") {
         vditor.element.style.height = vditor.options.height + "px";
     }

+ 14 - 0
src/ts/ui/setCodeTheme.ts

@@ -0,0 +1,14 @@
+import {Constants} from "../constants";
+import {addStyle} from "../util/addStyle";
+
+export const setCodeTheme = (codeTheme: string, cdn: string) => {
+    if (!Constants.CODE_THEME.includes(codeTheme)) {
+        codeTheme = "github";
+    }
+    const vditorHljsStyle = document.getElementById("vditorHljsStyle") as HTMLLinkElement;
+    const href = `${cdn}/dist/js/highlight.js/styles/${codeTheme}.css`;
+    if (vditorHljsStyle && vditorHljsStyle.href !== href) {
+        vditorHljsStyle.remove();
+    }
+    addStyle(`${cdn}/dist/js/highlight.js/styles/${codeTheme}.css`, "vditorHljsStyle");
+};

+ 14 - 0
src/ts/ui/setContentTheme.ts

@@ -0,0 +1,14 @@
+import {Constants} from "../constants";
+import {addStyle} from "../util/addStyle";
+
+export const setContentTheme = (contentTheme: string, cdn: string) => {
+    if (!Constants.CONTENT_THEME.includes(contentTheme) || contentTheme === "light") {
+        return;
+    }
+    const vditorContentTheme = document.getElementById("vditorContentTheme") as HTMLLinkElement;
+    const href = `${cdn}/dist/js/highlight.js/styles/${contentTheme}.css`;
+    if (vditorContentTheme && vditorContentTheme.href !== href) {
+        vditorContentTheme.remove();
+    }
+    addStyle(`${cdn}/dist/js/highlight.js/styles/${contentTheme}.css`, "vditorContentTheme");
+};

+ 2 - 7
src/ts/ui/setTheme.ts

@@ -1,12 +1,7 @@
-import {setCodeTheme} from "../toolbar/CodeTheme";
-import {setContentTheme} from "../toolbar/ContentTheme";
-
-export const setTheme = (vditor: IVditor, codeTheme?: string) => {
+export const setTheme = (vditor: IVditor) => {
     if (vditor.options.theme === "dark") {
-        setContentTheme(vditor, "dark");
+        vditor.element.classList.add("vditor--dark");
     } else {
         vditor.element.classList.remove("vditor--dark");
-        setContentTheme(vditor, "light");
     }
-    setCodeTheme(vditor, codeTheme);
 };

+ 5 - 1
src/ts/util/Options.ts

@@ -5,7 +5,6 @@ import boldSVG from "../../assets/icons/bold.svg";
 import bothSVG from "../../assets/icons/both.svg";
 import bugSVG from "../../assets/icons/bug.svg";
 import checkSVG from "../../assets/icons/check.svg";
-import contentThemeSVG from "../../assets/icons/theme.svg";
 import codeThemeSVG from "../../assets/icons/code-theme.svg";
 import codeSVG from "../../assets/icons/code.svg";
 import editSVG from "../../assets/icons/edit.svg";
@@ -30,6 +29,7 @@ import recordSVG from "../../assets/icons/record.svg";
 import redoSVG from "../../assets/icons/redo.svg";
 import strikekSVG from "../../assets/icons/strike.svg";
 import tableSVG from "../../assets/icons/table.svg";
+import contentThemeSVG from "../../assets/icons/theme.svg";
 import undoSVG from "../../assets/icons/undo.svg";
 import uploadSVG from "../../assets/icons/upload.svg";
 import {VDITOR_VERSION} from "../constants";
@@ -86,6 +86,7 @@ export class Options {
                 fixTermTypo: false,
                 footnotes: true,
                 setext: true,
+                theme: "light",
                 toc: false,
             },
             math: {
@@ -387,6 +388,9 @@ export class Options {
                         Object.assign({}, this.defaultOptions.preview.math, this.options.preview.math);
                 }
                 if (this.options.preview.markdown) {
+                    if (!this.options.preview.markdown.theme && this.options.theme && this.options.theme === "dark") {
+                        this.options.preview.markdown.theme = "dark";
+                    }
                     this.options.preview.markdown =
                         Object.assign({}, this.defaultOptions.preview.markdown, this.options.preview.markdown);
                 }

+ 3 - 2
types/index.d.ts

@@ -234,8 +234,10 @@ interface IMarkdownConfig {
     footnotes?: boolean;
     /** wysiwyg & ir 模式代码块是否渲染。默认值: true */
     codeBlockPreview: boolean;
-    /* 是否解析 setext 标题。默认值: true */
+    /** 是否解析 setext 标题。默认值: true */
     setext: boolean;
+    /** 内容主题。默认值:light */
+    theme?: string;
 }
 
 /** @link https://hacpai.com/article/1549638745630#options-preview */
@@ -263,7 +265,6 @@ interface IPreview {
 }
 
 interface IPreviewOptions {
-    theme?: "classic" | "dark";
     customEmoji?: { [key: string]: string };
     lang?: (keyof II18nLang);
     lazyLoadImage?: string;