Better Programming

Advice for programmers.

Follow publication

A Custom Properties Snippet Builder for VS Code

Massimo Cassandro
Better Programming
Published in
5 min readMay 7, 2022
Photo by Pankaj Patel on Unsplash

For a long time now, I’ve been using CSS custom properties more and more extensively, and when working on many larger projects it becomes difficult to remember them all.

I use VSCode for coding and there are some Intellisense plugins that can be very useful, but sometimes, for some reasons, they don’t work as I expect.

To solve this problem, I decided to create a small script that can extract a list of CSS properties from my files, and then generate a VSCode snippet completely automatically.

It’s a quite raw solution, but it does the job. I hope it will be useful for someone.

Setup

The script is based on Node, so the first step is to install it if you’ve never done this before.

Then, open in VSCode a project folder, create a package.json file if you need, and make sure it contains at least a css file (test.css in the example below).

At this point, you have to create your project snippet file. You have two ways to do this:

  1. manually create a .vscode folder and a .code-snippets file containing only empty braces (in my case, I named it my-proj.code-snippets).
  2. Follow the instructions on the VSCode Snippet Help page.
VSCode File explorer
Our project files in VSCode File Explorer

Now, you have to add the snippet code (except the part we will generate later):

{
"My-proj custom properties": {
"scope": "scss,css",
"prefix": [
"var",
"--prefix"
],
"body": [],
"description": "custom properties list - NB this is a script-generated snippet"
}
}

The snippet keyname (My-proj custom properties") will be used to update it, if you change it, you will need to update the script as well.

The body element will be updated by the script, you can customize the rest of the snippet as you like.

If you need help to build the snippet, this Generator could help you

The script

Our script will have to perform these actions:

  • Read the content of some css files
  • search for custom properties strings and extract them
  • remove duplicates and sort
  • update the snippet file

I first tried parsing the css files to perform a more accurate extraction, but this greatly increased the complexity of the script. In the end, a simple processing of the CSS string seemed to me more than enough for the intended goal.

Start creating an index.mjs (or the name you prefer) file in your project. Since we will be using ES6 modules syntax, the .mjs extension is required until you add to your package.json a top-level field type with a value of module (see ECMAScript Modules in the Node documentation).

Copy the following code in your file:

/* eslint-env node */
/* eslint-disable no-console */

import * as fs from 'fs';


const sources = [
'./test.css'
],
snippet_file = './.vscode/my-proj.code-snippets',
snippet_key = 'My-proj custom properties',
custom_var_prefix = 'prefix-';

let custom_properties = [];

sources.forEach(css_file => {
let css_content = fs.readFileSync(css_file).toString();

const regex = new RegExp(`--${custom_var_prefix}[a-zA-Z0-9._-]*?: ?(.*?)[;}]`, 'gi'),
this_cust_props = css_content.match(regex);

custom_properties = custom_properties.concat(this_cust_props);
});

// delete end `}` from compressed files
custom_properties = custom_properties.map(item => item.replace(/}$/, ';'));

custom_properties = custom_properties.map(item => item.split(':')[0].trim());
custom_properties.sort();
custom_properties = [...new Set(custom_properties)];

let vscode_snippet_body = `var(--${custom_var_prefix}\${1|` +
custom_properties.reduce((result,item) => `${result},${item}`).replaceAll(`--${custom_var_prefix}`, '') +
'|})$0';


// VSCODE snippets reading and update
let snippets = JSON.parse(fs.readFileSync(snippet_file).toString());

if(snippets[snippet_key]) {
snippets[snippet_key].body = [vscode_snippet_body];
fs.writeFileSync(snippet_file, JSON.stringify(snippets, null, ' '));

console.log('*** end ***');

} else {
console.error(`******ERROR\n'${snippet_key}' snippet doesn't exist\n************`);
}

First, we import the Node File system module (fs), we’ll use it for read the css files and to write the updated snippet file.

Then you need to set some constants:

const sources = [
'./test.css'
],
snippet_file = './.vscode/my-proj.code-snippets',
snippet_key = 'My-proj custom properties',
custom_var_prefix = 'prefix-';

let custom_properties = [];
  • sources is the array of the css files to parse, paths are relative to the project root
  • snippet_file: the snippet file path
  • snippet_key: the keyname of the snippet to update
  • custom_var_prefix: an optional prefix shared by all custom properties names. Some framework (e.g. Bootstrap) use it to avoid conflicts. Set it to an empty string ('') if you don’t need it.

Furhermore the custom_properties array is initialized.

At this point, every css file is opened, a simple regular expression searchs for all the custom properties strings and all matches are added to the custom_properties array, (note that RegExp also searches for custom properties values: it is an addition for any future enhancements, but they are not used at this time).

Our custom_properties array can now be processed:

custom_properties = custom_properties.map(item => item.split(':')[0].trim());
custom_properties.sort();
custom_properties = [...new Set(custom_properties)];
let vscode_snippet_body = `var(--${custom_var_prefix}\${1|` +
custom_properties.reduce((result,item) => `${result},${item}`)
.replaceAll(`--${custom_var_prefix}`, '') + '|})$0';
  • the map function is used to remove the value portion
  • the resulting array is sorted and duplicates are removed using Set
  • The snippet body field content is generated as a Choice string using the reduce function.

Now we can open the snippet file (using fs, again) and the JSON is parsed.

Actually, VSCode Snippets documents are not JSON files, but JSON-C (JSON with comments). This means that if there are any comments, an error will be thrown while processing the file. You must manually remove all comments from the file or implement a comment-saving parser, such as comment-json

To finish the job, we just need to update the body field and save the snippet file.

Note that any other snippets in the file will not be changed.

Finally we can run our script in the Terminal:

node index.mjs

You can also add it to your package.json file and run it through the Script Npm panel in VSCode (or from the command palette):

{
"scripts": {
"run": "node ./index.mjs"
}
}
VSCode Run NPM panel
The `Script NPM` panel

Now, while editing a css or scss file, typing var or --prefix (as set in the prefix field of the snippet), you will be able to access all your custom properties list:

Sure, you will have to run the script every time you edit the CSS, but the operation is very fast and once the CSS is defined you probably won’t need to do it too often…

Massimo Cassandro
Massimo Cassandro

Written by Massimo Cassandro

Web designer & front-end developer

No responses yet

Write a response