Home > Mobile >  Develop a VSCode theme using variables
Develop a VSCode theme using variables

Time:12-25

I'm creating a VScode theme.

My project structure is very simple:

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

The mytheme.json is something like this:

{
    "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",
        ...
    }
}

and my 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
}

Very simple. It works like a charm. But there is a big problem: it's very difficult to maintain because mytheme.json is a very very long file and it's a simple .json and If I want to modify for example the accent color, I need to do a find and replace.

I would like to develop my theme in a smarter way, I would like to use variables, save my N colors in variables and use them. json format doesn't support variables so I ask you how can I do that? I don't know if there is a standard way to do that, I imagine developing in js and then running a script that transforms my work into a valid json but how?

For example:

const PURPLE = "#9B6DFF"

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

return ...

I didn't find a guide to follow.


Following the suggestion of @rioV8, I created these files:

.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()

When I run it, I get:

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

The path seems ok to me, where is The problem? The createJsonTheme function goal is to create an object to save then in a json file inside themes folder.

CodePudding user response:

Variables won't help. The theme file is a mapping of token values to color values. A theme editor tool could help you to be more productive, but I don't know any.

CodePudding user response:

I solved doing like this:

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 }
  • Related