Browse Source

feat: 增加预览工具条可配置且可自定义

例如:

```ts
actions: [
  "table",
  "mobile",
  {
    text: "自定义",
    click: () => {
      console.log('custom');
    }
  }
]
```

- close #569
cipchk 5 years ago
parent
commit
e4adbc9f0b
3 changed files with 81 additions and 6 deletions
  1. 52 5
      src/ts/preview/index.ts
  2. 1 0
      src/ts/util/Options.ts
  3. 28 1
      types/index.d.ts

+ 52 - 5
src/ts/preview/index.ts

@@ -38,13 +38,46 @@ export class Preview {
             event.preventDefault();
         });
 
+        const actions = this.genActions(vditor.options.preview.actions);
+        // 如果只有一个选项时也没必要呈现
+        if (actions.length <= 1) {
+            this.element.appendChild(previewElement);
+            return ;
+        }
+
         const actionElement = document.createElement("div");
         actionElement.className = "vditor-preview__action";
-        actionElement.innerHTML = `<button class="vditor-preview__action--current" data-type="desktop">Desktop</button>
-<button data-type="tablet">Tablet</button>
-<button data-type="mobile">Mobile/Wechat</button>
-<button data-type="mp-wechat" class="vditor-tooltipped vditor-tooltipped__w" aria-label="复制到公众号">${mpWechatSVG}</button>
-<button data-type="zhihu" class="vditor-tooltipped vditor-tooltipped__w" aria-label="复制到知乎">${zhihutSVG}</button>`;
+        const actionHtml: string[] = [];
+        const actionCustom: IPreviewActionCustom[] = [];
+        const customPrefix = `_custom-`;
+        for (let i = 0; i < actions.length; i++) {
+            const action = actions[i];
+            if (typeof action === "object") {
+                action.key = customPrefix + (action.key || `${i + 1}`);
+                actionCustom.push(action);
+                actionHtml.push(`
+                    <button data-type="${action.key}" class="${action.className}">${action.text}</button>`);
+                continue;
+            }
+            switch (action) {
+                case "desktop":
+                    actionHtml.push(`<button class="vditor-preview__action--current" data-type="desktop">Desktop</button>`);
+                    break;
+                case "tablet":
+                    actionHtml.push(`<button data-type="tablet">Tablet</button>`);
+                    break;
+                case "mobile":
+                    actionHtml.push(`<button data-type="mobile">Mobile/Wechat</button>`);
+                    break;
+                case "mp-wechat":
+                    actionHtml.push(`<button data-type="mp-wechat" class="vditor-tooltipped vditor-tooltipped__w" aria-label="复制到公众号">${mpWechatSVG}</button>`);
+                    break;
+                case "zhihu":
+                    actionHtml.push(`<button data-type="zhihu" class="vditor-tooltipped vditor-tooltipped__w" aria-label="复制到知乎">${zhihutSVG}</button>`);
+                    break;
+            }
+        }
+        actionElement.innerHTML = actionHtml.join(``);
         this.element.appendChild(actionElement);
         this.element.appendChild(previewElement);
 
@@ -59,6 +92,11 @@ export class Preview {
                 return;
             }
 
+            if (type.startsWith(customPrefix)) {
+                actionCustom.find((w: IPreviewActionCustom) => w.key === type).click();
+                return ;
+            }
+
             if (type === "mp-wechat" || type === "zhihu") {
                 this.copyToX(vditor, this.element.lastElementChild.cloneNode(true) as HTMLElement, type);
                 return;
@@ -200,4 +238,13 @@ export class Preview {
         this.element.lastElementChild.remove();
         vditor.tip.show(`已复制,可到${type === "zhihu" ? "知乎" : "微信公众号平台"}进行粘贴`);
     }
+
+    private genActions(actions: IPreviewActionType): Array<IPreviewAction| IPreviewActionCustom> {
+        if (actions === "none") {
+            return [];
+        } else if (actions === "all") {
+            return ["desktop" , "tablet" , "mobile" , "mp-wechat", "zhihu"];
+        }
+        return actions;
+    }
 }

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

@@ -71,6 +71,7 @@ export class Options {
         outline: false,
         placeholder: "",
         preview: {
+            actions: "all",
             delay: 1000,
             hljs: Constants.HLJS_OPTIONS,
             markdown: Constants.MARKDOWN_OPTIONS,

+ 28 - 1
types/index.d.ts

@@ -372,7 +372,13 @@ interface IPreview {
     markdown?: IMarkdownConfig;
     /** @link https://hacpai.com/article/1549638745630#options-preview-theme */
     theme?: IPreviewTheme;
-
+    /**
+     * 工具条,默认值:`all`
+     * - `all` 表示显示所有
+     * - `none` 表示不显示
+     * - `[ 'desktop', 'mobile']` 表示只显示桌面与手机
+     */
+    actions?: IPreviewActionType;
     /** 预览回调 */
     parse?(element: HTMLElement): void;
 
@@ -380,6 +386,27 @@ interface IPreview {
     transform?(html: string): string;
 }
 
+type IPreviewAction = "desktop" | "tablet" | "mobile" | "mp-wechat" | "zhihu";
+interface IPreviewActionCustom {
+    /**
+     * 键名,不指定时自动生成
+     */
+    key?: string;
+    /**
+     * 按钮文本
+     */
+    text: string;
+    /**
+     * 按钮 `class` 值
+     */
+    className?: string;
+    /**
+     * 点击时回调
+     */
+    click: () => void;
+}
+type IPreviewActionType = "all" | "none" | Array<IPreviewAction | IPreviewActionCustom>;
+
 interface IPreviewOptions {
     customEmoji?: IObject;
     lang?: (keyof II18n);