使用变量开发 VSCode 主题

Develop a VSCode theme using variables

我正在创建一个 VScode 主题。

我的项目结构很简单:

mytheme
 |_ .vscode
   |_ launch.json
 |_ assets
   |_ ...some png files
 |_ themes
   |_ mytheme.json
 .vscodeignore
 package.json
 README.md

mytheme.json是这样的:

{
    "name": "mytheme",
    "type": "dark",
    "colors": {
        //////////////////////////////
        // CONTRAST COLOR 
        // The contrast colors are typically only set for high contrast themes. 
        // If set, they add an additional border around items across the UI to increase the contrast.
        //////////////////////////////
        // An extra border around active elements to separate them from others for greater contrast.
        "contrastActiveBorder": "#fa0000",
        // "contrastActiveBorder": "#FFFFFF00",
        // An extra border around elements to separate them from others for greater contrast.
        //"contrastBorder": "#fa0000",

        //////////////////////////////
        // BASE COLORS 
        //////////////////////////////
        // Overall border color for focused elements. This color is only used if not overridden by a component.
        "focusBorder": "#9B6DFF66",
        // Overall foreground color. This color is only used if not overridden by a component.
        "foreground": "#D9E0E8",
        // Shadow color of widgets such as Find/Replace inside the editor.
        "widget.shadow": "#1F2330",
        // Background color of text selections in the workbench (for input fields or text areas, does not apply to selections within the editor and the terminal).
        "selection.background": "#9B6DFF99",
        // Foreground color for description text providing additional information, for example for a label.
        "descriptionForeground": "#808182",
        // Overall foreground color for error messages (this color is only used if not overridden by a component).
        "errorForeground": "#9B6DFF",
        // The default color for icons in the workbench.
        "icon.foreground": "#D9E0E8",
        ...
    }
}

和我的 package.json:

{
  "name": "mytheme",
  "version": "1.0.0",
  "publisher": "...",
  "icon": "assets/logo_square.png",
  "galleryBanner": {
    "color": "#1F2330",
    "theme": "dark"
  },
  "engines": {
    "vscode": "^1.42.0"
  },
  "displayName": "Mytheme",
  "description": "...",
  "categories": [
    "Themes"
  ],
  "contributes": {
    "themes": [
      {
        "label": "Mytheme",
        "uiTheme": "vs-dark",
        "path": "./themes/mytheme.json"
      }
    ]
  },
  "repository": {
    "type": "git",
    "URL": "....git"
  },
  "bugs": {
    "URL": "..."
  },
  "author": {
    "name": "...",
    "email": "...",
  },
  "license": "MIT",
  "keywords": [
    "vscode",
    "theme",
    "color-theme",
    "dark"
  ],
  "private": false
}

很简单。它就像一个魅力。但是有一个大问题:维护起来非常困难,因为 mytheme.json 是一个非常非常长的文件,而且它很简单。json 如果我想修改例如强调色,我需要做查找和替换。

我想以更智能的方式开发我的主题,我想使用变量,将我的 N 种颜色保存在变量中并使用它们。 json 格式不支持变量所以我问你我该怎么做? 我不知道是否有标准的方法来做到这一点,我想象在 js 中开发,然后 运行ning 一个脚本将我的工作转换为有效的 json 但是如何?

例如:

const PURPLE = "#9B6DFF"

const baseColors = {
   ...
   errorForeground: PURPLE,
   ...
}

return ...

我没有找到可遵循的指南。


根据@rioV8 的建议,我创建了这些文件:

.vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "extensionHost",
      "request": "launch",
      "name": "Launch Extension",
      "runtimeExecutable": "${execPath}",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}"
      ],
      "outFiles": [
        "${workspaceFolder}/out/**/*.js"
      ],
      "preLaunchTask": "parseToJson",
    },
  ],
}

.vscode/tasks.json:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "parseToJson",
      "command": "tsc",
      "type": "shell",
      "presentation": {
        "reveal": "silent", 
        "panel": "new" 
      },
      "args": [
        "--target",
        "ES5",
        "--outDir",
        "js",
        "--sourceMap",
        "--watch",
        "parse.ts"
      ],
      "problemMatcher": "$tsc"
    }
  ]
}

.vscode/parse.ts:

const PURPLE = "#9B6DFF"

const baseColors = {
   errorForeground: PURPLE,
}

// create json 
const mytheme = {
    "name": "mytheme",
    "type": "dark",
    "colors": {...baseColors}
}
  
function createJsonTheme() {
  // save to json
  const file = new File(mytheme, "../themes/mytheme.json", {
    type: "text/plain",
  });
}

createJsonTheme()

当我 运行 它时,我得到:

error TS6053: File 'parse.ts' not found. The file is in the program because: Root file specified for compilation

路径对我来说似乎没问题,问题在哪里? createJsonTheme 函数的目标是创建一个对象,然后将其保存在 themes 文件夹内的 json 文件中。

变量无济于事。主题文件是标记值到颜色值的映射。主题编辑器工具可以帮助您提高工作效率,但我不知道。

我这样解决了:

launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Run Extension",
      "type": "extensionHost",
      "request": "launch",
      "runtimeExecutable": "${execPath}",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}"
      ],
      "preLaunchTask": "npm: build"
    },
    {
      "name": "Run Extension Without Build",
      "type": "extensionHost",
      "request": "launch",
      "runtimeExecutable": "${execPath}",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}"
      ]
    }
  ]
}

tasks.json:

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "npm",
      "script": "start",
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "problemMatcher": [],
      "label": "npm: start",
      "detail": "nodemon --watch src src/index.js"
    },
    {
      "type": "npm",
      "script": "build",
      "group": "build",
      "problemMatcher": [],
      "label": "npm: build",
      "detail": "node src/index.js"
    }
  ]
}

package.json:

...
"scripts": {
    "start": "nodemon --watch src src/index.js",
    "build": "node src/index.js && mkdir -p build",
    "prepublishOnly": "npm run build && vsce publish"
}
...

src/index.js:

const fs = require('fs').promises
const getTheme = require('./theme')

const ohlalaTheme = getTheme({
  theme: 'dark',
  name: 'Mytheme',
})

// write theme
fs.mkdir('./themes', { recursive: true })
  .then(() =>
    Promise.all([
      fs.writeFile('./themes/mytheme.json', JSON.stringify(ohlalaTheme, null, 2)),
    ])
  )
  .catch(() => process.exit(1))

src/theme.js

const { colors } = require('./colors')

function getTheme({ theme, name }) {
  const themes = (options) => options[theme] 

  return {
    name: name,
    colors: {
      focusBorder: colors.green,
    },
    semanticHighlighting: true,
    ...
  }
}

module.exports = getTheme

src/colors.js:

const colors = {
  green: '#......',
}

module.exports = { colors }