瀏覽代碼

:sparkles: #324

Liyuan Li 5 年之前
父節點
當前提交
96e2e5efbd

+ 3 - 1
CHANGELOG.md

@@ -59,6 +59,8 @@
 
 ### v3.1.16 / 2020-04-2x
 
+* [324](https://github.com/Vanessa219/vditor/issues/324) 支持多款主题预览 `引入特性`
+
 ### v3.1.15 / 2020-04-21
 
 * [333](https://github.com/Vanessa219/vditor/issues/333) 重新设计帮助菜单 `改进功能`
@@ -112,8 +114,8 @@
   * 添加 lazyLoadImageRender 静态方法
   * `setTheme` 方法添加 `codeTheme` 参数
   * insert line 默认快捷键由 `⌘-⇧-D` 修改为 `⌘-⇧-H`,添加下移 `⌘-⇧-D`、上移 `⌘-⇧-U` 快捷键,移除上传、编辑器模式切换快捷键
-  * 为 `options.toolbar` 添加 outdent,indent, outline, insert-after, insert-before, 子菜单,code-theme
   * 为 `options.toolbar` 添加 toolbar 参数,最多可进行 3 级菜单
+  * 为 `options.toolbar` 添加 outdent,indent, outline, insert-after, insert-before, 子菜单,code-theme, content-theme
 
 ### v3.0.12 / 2020-04-06
 

+ 2 - 1
README.md

@@ -167,7 +167,7 @@ Can be filled with element `id` or element itself` HTMLElement`
 #### options.toolbar
 
 * Toolbar, you can use name for shorthand: `toolbar: ['emoji', 'br', 'bold', '|', 'line']`. See default [src/ts/util/Options.ts](https://github.com/Vanessa219/vditor/blob/master/src/ts/util/Options.ts)
-* name can be enumerated as: `emoji` , `headings` , `bold` , `italic` , `strike` , `|` , `line` , `quote` , `list` , `ordered-list` , `check` ,`outdent` ,`indent` , `code` , `inline-code`, `insert-after`, `insert-before`, `code-theme`, `undo` , `redo` , `upload` , `link` , `table` , `record` , `edit-mode` , `both` , `preview` , `format` , `fullscreen` , `outline` , `devtools` , `info` , `help` , `br`
+* name can be enumerated as: `emoji` , `headings` , `bold` , `italic` , `strike` , `|` , `line` , `quote` , `list` , `ordered-list` , `check` ,`outdent` ,`indent` , `code` , `inline-code`, `insert-after`, `insert-before`, `code-theme`, `content-theme`, `undo` , `redo` , `upload` , `link` , `table` , `record` , `edit-mode` , `both` , `preview` , `format` , `fullscreen` , `outline` , `devtools` , `info` , `help` , `br`
 * When `name` is not in the enumeration, you can add a custom button in the following format: 
 
 ```js
@@ -478,3 +478,4 @@ Vditor uses the [MIT](https://opensource.org/licenses/MIT) open source license.
 * [mermaid](https://github.com/knsv/mermaid): Generation of diagram and flowchart from text in a similar manner as Markdown
 * [incubator-echarts](https://github.com/apache/incubator-echarts): A powerful, interactive charting and visualization library for browser
 * [abcjs](https://github.com/paulrosen/abcjs): JavaScript library for rendering standard music notation in a browser
+* [IntelliJ IDEA](https://www.jetbrains.com/?from=Vditor): Family of capable and ergonomic development environments

+ 1 - 0
demo/index.js

@@ -32,6 +32,7 @@ if (window.innerWidth < 768) {
     "redo",
     "|",
     "edit-mode",
+    "content-theme",
     "code-theme",
     {
       name: "more",

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

@@ -0,0 +1,3 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
+<path d="M25.75 16q1.083 0 1.875-0.75t0.792-1.917-0.792-1.917-1.875-0.75-1.875 0.75-0.792 1.917 0.792 1.917 1.875 0.75zM20.417 8.917q1.083 0 1.875-0.792t0.792-1.875-0.792-1.875-1.875-0.792-1.875 0.792-0.792 1.875 0.792 1.875 1.875 0.792zM11.583 8.917q1.083 0 1.875-0.792t0.792-1.875-0.792-1.875-1.875-0.792-1.875 0.792-0.792 1.875 0.792 1.875 1.875 0.792zM6.25 16q1.083 0 1.875-0.75t0.792-1.917-0.792-1.917-1.875-0.75-1.875 0.75-0.792 1.917 0.792 1.917 1.875 0.75zM16 0q6.583 0 11.292 4.167t4.708 10.083q0 3.667-2.625 6.25t-6.292 2.583h-3.083q-1.167 0-1.917 0.792t-0.75 1.875q0 0.917 0.667 1.75t0.667 1.833q0 1.167-0.75 1.917t-1.917 0.75q-6.667 0-11.333-4.667t-4.667-11.333 4.667-11.333 11.333-4.667z"></path>
+</svg>

+ 1 - 0
src/ts/constants.ts

@@ -9,6 +9,7 @@ export abstract class Constants {
     public static readonly CLASS_MENU_DISABLED: string = "vditor-menu--disabled";
     public static readonly TOOLBARS: string[] = ["emoji", "headings", "bold", "italic", "strike", "link", "list",
         "ordered-list", "outdent", "indent", "check", "line", "quote", "code", "inline-code", "upload", "record", "table"];
+    public static readonly CONTENT_THEME: string[] =  ["dark", "light"];
     public static readonly CODE_THEME: string[] =  ["abap", "algol", "algol_nu", "arduino", "autumn", "borland", "bw", "colorful", "dracula",
         "emacs", "friendly", "fruity", "github", "igor", "lovelace", "manni", "monokai", "monokailight", "murphy",
         "native", "paraiso-dark", "paraiso-light", "pastie", "perldoc", "pygments", "rainbow_dash", "rrt",

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

@@ -11,6 +11,7 @@ export const i18n: II18n = {
         "code-theme": "Code Block Theme Preview",
         "column": "Column",
         "confirm": "Confirm",
+        "content-theme": "Content Theme Preview",
         "copied": "Copied",
         "copy": "Copy",
         "devtools": "DevTools",
@@ -77,6 +78,7 @@ export const i18n: II18n = {
         "code-theme": "코드블럭삽입 테마 미리보기",
         "column": "행",
         "confirm": "확인",
+        "content-theme": "컨텐츠 테마 미리보기",
         "copied": "복사됐음",
         "copy": "복사",
         "devtools": "DevTools",
@@ -143,6 +145,7 @@ export const i18n: II18n = {
         "code-theme": "代码块主题预览",
         "column": "列",
         "confirm": "确定",
+        "content-theme": "内容主题预览",
         "copied": "已复制",
         "copy": "复制",
         "devtools": "开发者工具",

+ 27 - 2
src/ts/toolbar/CodeTheme.ts

@@ -1,8 +1,32 @@
 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;
@@ -18,7 +42,8 @@ export class CodeTheme extends MenuItem {
         Constants.CODE_THEME.forEach((theme) => {
             innerHTML += `<button>${theme}</button>`;
         });
-        panelElement.innerHTML = `<div style="overflow: auto;max-height:${window.innerHeight / 2}px">${innerHTML}</div>`;
+        panelElement.innerHTML =
+            `<div style="overflow: auto;max-height:${window.innerHeight / 2}px">${innerHTML}</div>`;
         panelElement.addEventListener(getEventName(), (event: MouseEvent & { target: HTMLElement }) => {
             if (event.target.tagName === "BUTTON") {
                 hidePanel(vditor, ["subToolbar"]);

+ 50 - 0
src/ts/toolbar/ContentTheme.ts

@@ -0,0 +1,50 @@
+import {Constants} from "../constants";
+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;
+
+    constructor(vditor: IVditor, menuItem: IMenuItem) {
+        super(vditor, menuItem);
+
+        const actionBtn = this.element.children[0] as HTMLElement;
+
+        const panelElement = document.createElement("div");
+        panelElement.className = `vditor-hint vditor-panel--${menuItem.level === 2 ? "side" : "arrow"}`;
+        let innerHTML = "";
+        Constants.CONTENT_THEME.forEach((theme) => {
+            innerHTML += `<button>${theme}</button>`;
+        });
+        panelElement.innerHTML =
+            `<div style="overflow: auto;max-height:${window.innerHeight / 2}px">${innerHTML}</div>`;
+        panelElement.addEventListener(getEventName(), (event: MouseEvent & { target: HTMLElement }) => {
+            if (event.target.tagName === "BUTTON") {
+                hidePanel(vditor, ["subToolbar"]);
+                setContentTheme(vditor, event.target.textContent);
+                event.preventDefault();
+                event.stopPropagation();
+            }
+        });
+        this.element.appendChild(panelElement);
+
+        toggleSubMenu(vditor, panelElement, actionBtn, menuItem.level);
+    }
+}

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

@@ -25,6 +25,7 @@ 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 };
@@ -152,6 +153,9 @@ export class Toolbar {
             case "code-theme":
                 menuItemObj = new CodeTheme(vditor, menuItem);
                 break;
+            case "content-theme":
+                menuItemObj = new ContentTheme(vditor, menuItem);
+                break;
             default:
                 menuItemObj = new Custom(vditor, menuItem);
                 break;

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

@@ -1,25 +0,0 @@
-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);
-    }
-};

+ 4 - 13
src/ts/ui/setTheme.ts

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

+ 6 - 0
src/ts/util/Options.ts

@@ -5,6 +5,7 @@ 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";
@@ -137,6 +138,7 @@ export class Options {
                     "preview",
                     "format",
                     "outline",
+                    "content-theme",
                     "code-theme",
                     "devtools",
                     "info",
@@ -328,6 +330,10 @@ export class Options {
         icon: outlinerSVG,
         name: "outline",
         tipPosition: "nw",
+    }, {
+        icon: contentThemeSVG,
+        name: "content-theme",
+        tipPosition: "nw",
     }, {
         icon: codeThemeSVG,
         name: "code-theme",