I consider writing a custom Visual Studio Code extension to be an exciting project and learning experience which allows me to enhance my experience of writing this website and tailor the editor to my specific needs. While VSCode offers a rich ecosystem of extensions covering a wide range of functionalities, there are times when you might find yourself wanting a unique feature or just wanting to learn something new. On this page, I describe my experience of creating my own VSCode extension.
Most of the functionality will reflect my working structure, but there might be interesting bits and pieces for other developers as well. Feedback, suggestions, or questions are always welcome via the Discord.
The source code for the extension can be found here.
Features
- Working with to-do items:
- Creating a new item
- Finding all items in articles
- Validate repository
- Validate links in Markdown files
Working with to-do items
I only use a centralized to-do list for high-level requirements and larger-scale projects. As a result, most of the working items are not put on a centralized list. This means that each to-do item is linked to the specific page or even section that it belongs to. This simplifies focusing on related requirements without having to maintain and filter a long list.
Although there are many upsides to this approach, it does make it easy to forget about to-do items because there is no overview. This feature attempts to solve some of those problems by generating a list of all to-do items from different pages into a single list.
To-do items are added to Markdown files in the form of HTML comments, as they are not rendered in the compiled version of the page. They can have the following two forms, with and without dates:
For now, the version without dates still exists, but they are gradually being phased out.
Creating a new item
The best way of introducing text in a file (besides just typing it), is by using the concept of Snippets. Using this functionality, itโs possible to automatically mark locations with $<number>
where the user will probably want to fill in the information.
Using this, the snippet can be defined as <!--TODO: $1 -->
and be inserted using TextEditor.insertSnippet
:
Adding dates provides some visibility on how old to-do items are and that can help to avoid extremely long outstanding items.
This can be done by updating the snippet to <!--TODO (${date}): $1-->
. This uses template literals for cleaner construction of strings. Now all that is left is to generate the date string, which turns out to be much more difficult in JavaScript than you would expect.
Getting the date string looks like this:
Which leads to the final result:
Finding all items in articles
The items are gathered from the workspace using the following process:
- Find all Markdown files in the workspace (
vscode.workspace.findFiles
) - For each file:
- Load the content of the file (
vscode.workspace.openTextDocument
) - Find all to-do items using a ๐จ Regular Expressions
- Load the content of the file (
- Concatenate the resulting items from each file (
Array.flat
)
The information is sorted by date and is displayed in reverse chronological order (you see the oldest items first). In case an item does not have a date, it is added to the end of the list (it is considered older than the oldest item with a date). This information is then displayed using an Output Channel.
Validate repository
Throughout time many changes have been made to the repository structure. To help me finalize those migrations, Iโve made a command that checks which files I still need to migrate or update.
An example is migrating all articles from the active
folder to the topics
folder, the latter one being deployed on Google App Engine.
A generalized implementation of this is:
Validate links in Markdown files
Validate backlinks
I want links between pages to be bi-directional. This means that when linking to a page, I expect to have an explicit link back within the text or a link within a โrelated pagesโ section. This ensures better connectivity on the website.
Testing the extension
To open a different folder when testing the extension (using F5
), pass it as a first argument in
the args
of the run configuration:
Here the startup folder is defined as ${workspaceFolder}/../../..
.
Installing the extension locally
Packaging is also where the .vscodeignore
file comes in. It defines the files to be excluded
from the package.
Make sure vsce
is installed which can be done through
Afterwards, the extension can be installed through Extensions > โฆ > Install from VSIX.