I have been tasked with building a new website using WordPress. The last time I used WordPress was a few years ago and involved using Advanced Custom Fields to build custom pages and layouts. Things have changed a lot over the years and now there is the built in Gutenberg editor, which uses blocks to create a custom layout and add content. The trouble was, there didn’t seem to be great support in Visual Studio Code for the blocks, as they use HTML comments.
Gutenberg Blocks
Here is an example block that adds the Site Title block, which you can use to display your site’s name, along with a level setting in a json object.
<!-- wp:site-title {"level":0} -->
I don’t know why the decision was made to use HTML comments for blocks, but after using it for a bit you get used to it. The main issue I had was that HTML comments are greyed out by most themes in Visual Studio Code and are not as easy to read as other code around it.
Gutenberg blocks also use a json object to pass settings or props into the blocks to change their display. Honestly, I struggled writing json without any syntax highlighting, missing double quotes and putting closing brackets in the wrong places when you have many nested objects. I spent a long time debugging what turned out to be simple mistakes.
Syntax Highlighting in VS Code
This led me to research about how VS Code works and if it would be possible to add highlighting to the comments. A quick web search led me to the Syntax Highlight Guide on the VS Code docs site. This explained that you can build an extension that uses custom grammars to add syntax highlighting.
VS Code uses these grammars to help split code into smaller parts, called tokens, where each part has a token type. For HTML, a token can be a tag, such as <p>
or a class <p class="title">
or even smaller parts such as the opening <
and closing part of the tag >
.
There are many standard grammars already which can be found in the VS Code GitHub repository. VS Code lets you create an extension to customise grammars. You can get started creating an extension using Yeoman.
Injection Grammars
You can create a custom grammar for a new language, but HTML already has a grammar, so instead I needed to create an injection grammar. An injection grammar will extend the existing grammar allow you to add your own rules and define your own tokens.
Following the examples I created an extension that injected the custom grammar into HTML comments. The package.json defines the path to the injection file (path) and what it extends with the injectTo key.
// package.json
"grammars": [
{
"scopeName": "gutenberg-comment.injection",
"path": "./syntaxes/injection.json",
"injectTo": [
"text.html.derivative"
]
}
]
To find out what to extend (text.html.derivative
) I opened the Command Palette and then searched for ‘Developer: Inspect Editor Tokens and Scopes’ and pressed enter. This allows you to click on an element in the editor, such as the HTML comment I wanted to update, and it will tell you what scope VS Code defines it as.
Next I had to create rules that match particular content and define tokens. This is done using regex to match the string and then give it a name. The name you give is based on the Textmate grammar naming convention, so I wanted to define the string beginning with wp:
as a variable parameter.
// injection.json
"gutenberg": {
"match": "(wp:[^]+)",
"name": "variable.parameter.gutenberg"
},
Next I wanted to apply json syntax to the json string in the comment. I tried several match regex expressions which didn’t quite work, but then realised you could define the beginning {
and the end }
of the string which was much easier.
"gutenberg-json": {
"begin": "\\{",
"end": "\\}",
"name": "meta.embedded.block.json",
"patterns": [
{
"include": "source.json"
}
]
}
The VS Code Syntax Highlight Guide states that you should try and use meta.embedded.*
where possible for the name for an embedded language. This helps tell VS Code that this is a language rather than a comment or a string. I also had to include the source.json in the patterns as it didn’t set the language to json and display the highlighting without it.
Finally, I had to update the package.json to define that meta.embedded.block.json
is an embedded language and that the language should be json.
// package.json
"grammars": [
{
"scopeName": "gutenberg-comment.injection",
"path": "./syntaxes/injection.json",
"injectTo": [
"text.html.derivative"
],
"embeddedLanguages": {
"meta.embedded.block.json": "json"
}
}
]
Packaging it all up
Once I had tested this all out on my local machine, by copying the extension into ~/.vscode/extensions
directory, I could then package it all up and publish the extension to the VS Code Marketplace by following the guide to Publishing Extensions.
My extension can now be found on the VS Code Marketplace and by searching for extensions from within VS Code.
The source code is also available on GitHub.
Photo by Negative Space on StockSnap
Top comments (1)
good day dear C.S. Rhymes
many thank you so much for spending your time creating and posting this article.
you have been building a new website using WordPress. I really like the idea of the support in Visual Studio Code for the blocks, as they use HTML comments.
I am a big big fan of VSCode.
i just found your article and i like it. The way you talk about the usage of VSCode in WordPress development.
Many thanks for the article it is just great!! Many thanks for the article it is just great!! It looks very promising and your thoughts are geat: Many thanks for your inspiring ideas.
Dear C.S. Rhymes: i am currently working on some issues - that have to do with the CSS and google fonts.
to begin with the beginning:i have found out that my wordpress-site fetches two google fonts:
one of them is montserrat
i decided to host them locally. so i have to
a. fetch the fonts
b. correct the css code
with the following tool i fetch them
google-webfonts-helper.herokuapp.c...
here i have the option to add the paths - to customize the path in the css-data
/* montserrat-regular - latin / u/font-face { font-family: 'Montserrat'; font-style: normal; font-weight: 400; src: url('../fonts/montserrat-v25-latin-regular.eot'); / IE9 Compat Modes / src: local(''), url('../fonts/montserrat-v25-latin-regular.eot?#iefix') format('embedded-opentype'), / IE6-IE8 / url('../fonts/montserrat-v25-latin-regular.woff2') format('woff2'), / Super Modern Browsers / url('../fonts/montserrat-v25-latin-regular.woff') format('woff'), / Modern Browsers / url('../fonts/montserrat-v25-latin-regular.ttf') format('truetype'), / Safari, Android, iOS / url('../fonts/montserrat-v25-latin-regular.svg#Montserrat') format('svg'); / Legacy iOS */ } Customize folder prefix (optional):
and now i have to add a path to set the correct path - (that means to customize the path )
../fonts/
some additional thought: what makes me wonder is the fact that some of the examples show full paths as reference - others dont:
see the following examples;
a. wp-ninjas.de/wordpress-google-font...
url("https://wp-ninias.de/fonts/muilti-latin-300.woff2") format (
url("https://wp-ninias.de/fonts/muilti-latin-300.woff") format (
b. pixelgrade.com/docs/advanced-custo...
Copy the URL Path field and paste it before each URL in the Embed Code field. The example code will look like this:
@font-face {
font-family: 'Name of the font';
src: url('http://yourwebsite.com/wp-content/uploads/fonts/11148/name-of-the-font-file.woff2') format('woff2'),
url('http://yourwebsite.com/wp-content/uploads/fonts/11148/name-of-the-font-file.woff') format('woff');
}
c. themeisle.com/blog/custom-fonts-wo...
Once the file is in place, open up your child theme’s stylesheet. Now you’ll need to call on that font so you can use it, via a snippet that should look like this:
`
@font-face {
font-family: New Font;
src: url(yourwebsite.com/wp-content/themes/...);
font-weight: normal;
}
`
and now compare it with the following example here:
Code:
/* montserrat-regular - latin */
@font-face {
font-family: 'Montserrat';
font-style: normal;
font-weight: 400;
src: url('../fonts/montserrat-v25-latin-regular.eot'); /* IE9 Compat Modes */
src: local(''),
url('../fonts/montserrat-v25-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('../fonts/montserrat-v25-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
url('../fonts/montserrat-v25-latin-regular.woff') format('woff'), /* Modern Browsers */
url('../fonts/montserrat-v25-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
url('../fonts/montserrat-v25-latin-regular.svg#Montserrat') format('svg'); /* Legacy iOS */
see the helper-tool google-webfonts-helper.herokuapp.c...
the question: so the question is: how to set the path correct for the CSS... which path should we use here!?
Dear C.S. Rhymes i look forward to hear from you