Mike Slinn
Mike Slinn

Make a Visual Studio Code Extension

Published 2022-03-01.
Time to read: about 6 minutes.

This site is categorized under JavaScript, Visual Studio Code.

I want to be able to move pages in my Jekyll-powered website without breaking links from the outside. The jekyll-redirect-from Jekyll plugin generates little HTML files that contain http-meta-refresh client-side redirects as desired. I wanted an easy way to inject the names of those redirect pages into the Jekyll front matter. Since I usually author my website using Visual Studio Code, a custom Visual Studio Code extension seems like a good way to create the redirects.

Extension Requirements

All the extension has to do is discover the URL path component of the page currently being edited, and write an entry into the front matter. For example, I have set up Jekyll such that given a page at collections/_posts/2022/2022-02-21-jekyll-debugging.html, it would deploy to /blog/2022/02/21/jekyll-debugging.html. The required front matter would be:

redirect_from:
  - /blog/2022/02/21/jekyll-debugging.html

With that in mind, if I want to move a published post to another location without breaking it, the extension should:

  1. Present a new menu option when a right-click on a file in the side bar, or a right-click on a file name tab in the editor.
  2. When the menu item is selected, obtain the relative path to the file within the project directory (for example: collections/_posts/2022/2022-02-21-jekyll-debugging.html)
  3. Convert the relative path to the deployed relative path (for example, /blog/2022/02/21/jekyll-debugging.html)
  4. Write the entry into the front matter of the file. For example:
    redirect_from:
    - /blog/2022/02/21/jekyll-debugging.html

Background

The Microsoft documentation describes how to write an Visual Studio Code extension.

Setup

Visual Studio Code extensions are written in JavaScript (actually, node.js) or TypeScript. Ensure that a version of node.js has been installed:

Shell
$ which node
/home/mslinn/.nvm/versions/node/v17.3.1/bin/node 

Ensure you have set up your global package manager for node.js, then type:

Shell
$ npm install -g yo generator-code
  npm WARN deprecated har-validator@5.1.5: this library is no longer supported
  npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
  npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142

  added 872 packages, and audited 873 packages in 57s

  15 vulnerabilities (13 moderate, 2 high)

  To address issues that do not require attention, run:
    npm audit fix

  To address all issues (including breaking changes), run:
    npm audit fix --force

  Run `npm audit` for details. 

The yo module is the culprit; lets address its vulnerabilities:

Shell
$ npm install -g npm-check-updates
added 270 packages, and audited 271 packages in 9s

found 0 vulnerabilities 

Generating the Skeleton

I decided to use TypeScript instead of JavaScript for the extension. TypeScript code converts to JavaScript, however it uses type inference and integrates better with some editors.

Shell
$ mkdir redirect_generator

$ cd redirect_generator/

$ $ yo code
? ==========================================================================
We’re constantly looking for ways to make yo better!
May we anonymously report usage statistics to improve the tool over time?
More info: https://github.com/yeoman/insight & http://yeoman.io
==========================================================================  No
_-----_     ╭──────────────────────────╮
    |       |    │   Welcome to the Visual  │
    |--(o)--|    │   Studio Code Extension  │
   `---------´   │        generator!        │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What type of extension do you want to create?  New Extension (TypeScript)
? What's the name of your extension?  redirect_generator
? What's the identifier of your extension?  redirect-generator
? What's the description of your extension? Injects the URL of a redirect page into Jekyll front matter
? Initialize a git repository? Yes
? Bundle the source code with webpack? No
? Which package manager to use? npm
Writing in /mnt/f/work/jekyll/redirect_generator/redirect-generator...
    create redirect-generator/.vscode/extensions.json
    create redirect-generator/.vscode/launch.json
    create redirect-generator/.vscode/settings.json
    create redirect-generator/.vscode/tasks.json
    create redirect-generator/package.json
    create redirect-generator/tsconfig.json
    create redirect-generator/.vscodeignore
    create redirect-generator/vsc-extension-quickstart.md
    create redirect-generator/README.md
    create redirect-generator/CHANGELOG.md
    create redirect-generator/src/extension.ts
    create redirect-generator/src/test/runTest.ts
    create redirect-generator/src/test/suite/extension.test.ts
    create redirect-generator/src/test/suite/index.ts
    create redirect-generator/.eslintrc.json

Changes to package.json were detected.

Running npm install for you to install the required dependencies.

added 203 packages, and audited 204 packages in 29s

found 0 vulnerabilities

Your extension redirect-generator has been created!

To start editing with Visual Studio Code, use the following commands:

     code redirect-generator

Open vsc-extension-quickstart.md inside the new extension for further instructions
on how to modify, test and publish your extension.

For more information, also visit http://code.visualstudio.com and follow us @code.


? Do you want to open the new folder with Visual Studio Code? Open with `code`

     _-----_     ╭───────────────────────╮
    |       |    │      Bye from us!     │
    |--(o)--|    │       Chat soon.      │
   `---------´   │      Yeoman team      │
    ( _´U`_ )    │    http://yeoman.io   │
    /___A___\   /╰───────────────────────╯
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y ` 

The instructions in the web page assume the happy path is the only possibility. Instead:

  1. Do not work on the extension in a workspace that has any other projects in it.
  2. The online instructions assume that TypeScript was used, not JavaScript, so the file types are assumed to be .ts.

The instructions in vsc-extension-quickstart.md do not make assumptions about TypeScript.

Debugging the Extension

I found the procedure awkward at first:

  1. Press F5 to activate the first defined launcher
  2. Once the new debug VSCode instance settles down, click in it and type Ctrl-Shift-P, then type redirect
  3. Any breakpoints in the original VSCode instance will trigger.
  4. Once the breakpoint is cleared, a message saying Add redirecct from redirect_generator! will appear in the debugged instance of VSCode.

Extension Anatomy

I moved on to the next part of the tutorial, Extension Anatomy.