簡體   English   中英

如何在 monaco-editor 中使用 VSC 主題?

[英]How to use a VSC theme in monaco-editor?

據我了解, monaco-editor和 VSCode 使用兩種不同的格式來定義主題。

似乎早期版本的 VSC 主要使用tmTheme定義格式,該格式允許使用此工具轉換主題(另請參閱2017 年的 GitHub 問題)。 但是,由於 VSC 現在使用一種新格式來定義其主題,我想知道是否有一種(簡單的)方法可以在 Monaco 編輯器中使用現有的 VSC 主題。

非常感謝你的幫助: :)

PS 這個GitHub 2019 年的問題評論似乎表明確實沒有簡單的方法可以做到這一點,但希望從那時起事情已經發生了變化。

主題擴展仍然支持 tmTheme 格式,並在導入時轉換(據我記憶)。 然而,擴展中主題的主要定義是使用類似於 dark_plus.json 中所示的方法。

將 json 格式轉換為 monaco-editor 所期望的結構非常容易:

export interface Colors { [key: string]: string }
export interface ITokenEntry {
    name?: string;
    scope: string[] | string;
    settings: {
        foreground?: string;
        background?: string;
        fontStyle?: string;
    };
}

// This is the structure of a vscode theme file.
export interface IThemeObject {
    name: string;
    type?: string;
    include?: string;
    colors?: Colors;

    settings?: ITokenEntry[];    // Old style specification.
    tokenColors?: ITokenEntry[]; // This is how it should be done now.
}

這些接口描述了 json 文件的格式。 較舊的主題定義使用settings成員來定義主題 colors。 在這種情況下,只需將tokenColors成員設置為settings成員並繼續。

加載主題后,您可以使用此 static 方法將其加載到 monaco-editor 中:

    /**
     * Updates the theme used by all code editor instances.
     *
     * @param theme The theme name.
     * @param type The base type of the theme.
     * @param values The actual theme values.
     */
    public static updateTheme(theme: string, type: "light" | "dark", values: IThemeObject): void {
        // Convert all color values to CSS hex form.
        const entries: { [key: string]: string } = {};
        for (const [key, value] of Object.entries(values.colors || {})) {
            entries[key] = colorToHex(value) || "";
        }

        const tokenRules: Monaco.ITokenThemeRule[] = [];
        (values.tokenColors || []).forEach((value: ITokenEntry): void => {
            const scopeValue = value.scope || [];
            const scopes = Array.isArray(scopeValue) ? scopeValue : scopeValue.split(",");
            scopes.forEach((scope: string): void => {
                tokenRules.push({
                    token: scope,
                    foreground: colorToHex(value.settings.foreground),
                    background: colorToHex(value.settings.background),
                    fontStyle: value.settings.fontStyle,
                });
            });
        });

        CodeEditor.currentThemeId = theme.replace(/[^a-zA-Z]+/g, "-");
        Monaco.defineTheme(CodeEditor.currentThemeId, {
            base: type === "light" ? "vs" : "vs-dark",
            inherit: true,
            rules: tokenRules,
            colors: entries,
        });

        Monaco.setTheme(CodeEditor.currentThemeId);
    }

CodeEditor是我的 TS class 包裝了 monaco-editor。 function colorToHex定義為:

import Color from "color";

/**
 * Converts a color string or a color to a hex string.
 *
 * @param color The value to convert.
 *
 * @returns A hex string of the given color, including the alpha value.
 */
export const colorToHex = (color: string | Color | undefined): string | undefined => {
    if (!color) {
        return;
    }

    if (typeof color === "string") {
        color = new Color(color);
    }

    // Hex color values have no alpha component, so we have to add that explicitly.
    if (color.alpha() < 1) {
        let alpha = Math.round((color.alpha() * 255)).toString(16);
        if (alpha.length < 2) {
            alpha = "0" + alpha;
        }

        return color.hex() + alpha;
    } else {
        return color.hex();
    }
};

我創建了一個小型的 POC 存儲庫來演示它是如何工作的。 它基於 monaco-vscode-textmate-theme-converter 插件。 你可以在 這里找到 repo,我在這里發布了一個實際轉換主題的工具。 請注意,由於一些加載問題,您可能需要在開始之前對演示應用程序進行硬刷新。

我使用 monaco,我發現這個開源repo包含了幾乎所有經常使用的 VSC 主題,如 katzenmitch 和 cloud,您可以將其用作npm package。 當我瀏覽代碼時,我發現他使用了 JSON 格式,就像鈷主題一樣,代碼如下:

{
  "base": "vs-dark",
  "inherit": true,
  "rules": [
    {
      "background": "002240",
      "token": ""
    },
    {
      "foreground": "e1efff",
      "token": "punctuation - (punctuation.definition.string || punctuation.definition.comment)"
    },
    {
      "foreground": "ff628c",
      "token": "constant"
    },
    {
      "foreground": "ffdd00",
      "token": "entity"
    },
    {
      "foreground": "ff9d00",
      "token": "keyword"
    },
    {
      "foreground": "ffee80",
      "token": "storage"
    },
    {
      "foreground": "3ad900",
      "token": "string -string.unquoted.old-plist -string.unquoted.heredoc"
    },
    {
      "foreground": "3ad900",
      "token": "string.unquoted.heredoc string"
    },
    {
      "foreground": "0088ff",
      "fontStyle": "italic",
      "token": "comment"
    },
    {
      "foreground": "80ffbb",
      "token": "support"
    },
    {
      "foreground": "cccccc",
      "token": "variable"
    },
    {
      "foreground": "ff80e1",
      "token": "variable.language"
    },
    {
      "foreground": "ffee80",
      "token": "meta.function-call"
    },
    {
      "foreground": "f8f8f8",
      "background": "800f00",
      "token": "invalid"
    },
    {
      "foreground": "ffffff",
      "background": "223545",
      "token": "text source"
    },
    {
      "foreground": "ffffff",
      "background": "223545",
      "token": "string.unquoted.heredoc"
    },
    {
      "foreground": "ffffff",
      "background": "223545",
      "token": "source source"
    },
    {
      "foreground": "80fcff",
      "fontStyle": "italic",
      "token": "entity.other.inherited-class"
    },
    {
      "foreground": "9eff80",
      "token": "string.quoted source"
    },
    {
      "foreground": "80ff82",
      "token": "string constant"
    },
    {
      "foreground": "80ffc2",
      "token": "string.regexp"
    },
    {
      "foreground": "edef7d",
      "token": "string variable"
    },
    {
      "foreground": "ffb054",
      "token": "support.function"
    },
    {
      "foreground": "eb939a",
      "token": "support.constant"
    },
    {
      "foreground": "ff1e00",
      "token": "support.type.exception"
    },
    {
      "foreground": "8996a8",
      "token": "meta.preprocessor.c"
    },
    {
      "foreground": "afc4db",
      "token": "meta.preprocessor.c keyword"
    },
    {
      "foreground": "73817d",
      "token": "meta.sgml.html meta.doctype"
    },
    {
      "foreground": "73817d",
      "token": "meta.sgml.html meta.doctype entity"
    },
    {
      "foreground": "73817d",
      "token": "meta.sgml.html meta.doctype string"
    },
    {
      "foreground": "73817d",
      "token": "meta.xml-processing"
    },
    {
      "foreground": "73817d",
      "token": "meta.xml-processing entity"
    },
    {
      "foreground": "73817d",
      "token": "meta.xml-processing string"
    },
    {
      "foreground": "9effff",
      "token": "meta.tag"
    },
    {
      "foreground": "9effff",
      "token": "meta.tag entity"
    },
    {
      "foreground": "9effff",
      "token": "meta.selector.css entity.name.tag"
    },
    {
      "foreground": "ffb454",
      "token": "meta.selector.css entity.other.attribute-name.id"
    },
    {
      "foreground": "5fe461",
      "token": "meta.selector.css entity.other.attribute-name.class"
    },
    {
      "foreground": "9df39f",
      "token": "support.type.property-name.css"
    },
    {
      "foreground": "f6f080",
      "token": "meta.property-group support.constant.property-value.css"
    },
    {
      "foreground": "f6f080",
      "token": "meta.property-value support.constant.property-value.css"
    },
    {
      "foreground": "f6aa11",
      "token": "meta.preprocessor.at-rule keyword.control.at-rule"
    },
    {
      "foreground": "edf080",
      "token": "meta.property-value support.constant.named-color.css"
    },
    {
      "foreground": "edf080",
      "token": "meta.property-value constant"
    },
    {
      "foreground": "eb939a",
      "token": "meta.constructor.argument.css"
    },
    {
      "foreground": "f8f8f8",
      "background": "000e1a",
      "token": "meta.diff"
    },
    {
      "foreground": "f8f8f8",
      "background": "000e1a",
      "token": "meta.diff.header"
    },
    {
      "foreground": "f8f8f8",
      "background": "4c0900",
      "token": "markup.deleted"
    },
    {
      "foreground": "f8f8f8",
      "background": "806f00",
      "token": "markup.changed"
    },
    {
      "foreground": "f8f8f8",
      "background": "154f00",
      "token": "markup.inserted"
    },
    {
      "background": "8fddf630",
      "token": "markup.raw"
    },
    {
      "background": "004480",
      "token": "markup.quote"
    },
    {
      "background": "130d26",
      "token": "markup.list"
    },
    {
      "foreground": "c1afff",
      "fontStyle": "bold",
      "token": "markup.bold"
    },
    {
      "foreground": "b8ffd9",
      "fontStyle": "italic",
      "token": "markup.italic"
    },
    {
      "foreground": "c8e4fd",
      "background": "001221",
      "fontStyle": "bold",
      "token": "markup.heading"
    }
  ],
  "colors": {
    "editor.foreground": "#FFFFFF",
    "editor.background": "#002240",
    "editor.selectionBackground": "#B36539BF",
    "editor.lineHighlightBackground": "#00000059",
    "editorCursor.foreground": "#FFFFFF",
    "editorWhitespace.foreground": "#FFFFFF26"
  }
}

我建議你可以通過它 go 。 並制作您自己的主題,而不是使用默認的 VSC 主題,但如果您仍想使用 vsc 主題,有很多類似這個的 repos。 Or you could use tools like https://bitwiser.in/monaco-themes/ to generate theme for monaco from tmTheme files that picks colors from theme files and generates a json to be used directly with monaco.editor.defineTheme .

我希望這會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM