如何在摩纳哥编辑器中使用 VSC 主题?

sch*_*ing 5 visual-studio-monaco visual-studio-code vscode-extensions monaco-editor

据我了解,monaco-editor和 VSCode 使用两种不同的格式来定义主题。

似乎 VSC 的早期版本主要使用tmTheme定义格式,允许使用此工具转换主题(另请参阅2017 年的 GitHub 问题)。但是,由于 VSC 现在使用新的格式来定义其主题,我想知道是否有一种(简单)方法可以在 Monaco 编辑器中使用现有的 VSC 主题。

非常感谢你的帮助!:)

PS 2019 年的 GitHub 问题评论似乎表明确实没有简单的方法可以做到这一点,但希望从那时起事情已经发生了变化。

cbu*_*ler 8

我创建了一个小型 POC 存储库来演示这是如何工作的。它基于 monaco-vscode-textmate-theme-converter 插件。您可以在此处找到该存储库,我在此处发布了一个实际转换主题的工具。请注意,由于某些加载问题,您可能需要在开始之前对演示应用程序进行硬刷新。


Mik*_*hke 1

主题扩展中仍然支持 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.
}
Run Code Online (Sandbox Code Playgroud)

这些接口描述了json文件的格式。旧的主题定义使用settings成员来定义主题颜色。在这种情况下,只需将tokenColors成员设置为settings成员并继续即可。

加载主题后,您可以使用此静态方法将其加载到摩纳哥编辑器中:

    /**
     * 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);
    }

Run Code Online (Sandbox Code Playgroud)

CodeEditor是我的 TS 类,它包装了摩纳哥编辑器。该函数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();
    }
};
Run Code Online (Sandbox Code Playgroud)