Visual Studio Code snippet to make URLs relative by Mark Seemann
Yes, it involves JSON and regular expressions.
Ever since I migrated the blog off dasBlog I've been writing the articles in raw HTML. The reason is mostly a historical artefact: Originally, I used Windows Live Writer, but Jekyll had no support for that, and since I'd been doing web development for more than a decade already, raw HTML seemed like a reliable and durable alternative. I increasingly find that relying on skill and knowledge is a far more durable strategy than relying on technology.
For a decade I used Sublime Text to write articles, but over the years, I found it degrading in quality. I only used Sublime Text to author blog posts, so when I recently repaved my machine, I decided to see if I could do without it.
Since I was already using Visual Studio Code for much of my programming, I decided to give it a go for articles as well. It always takes time when you decide to move off a tool you've been used for a decade, but after some initial frustrations, I quickly found a new modus operandi.
One benefit of rocking the boat is that it prompts you to reassess the way you do things. Naturally, this happened here as well.
My quest for relative URLs #
I'd been using a few Sublime Text snippets to automate a few things, like the markup for the section heading you see above this paragraph. Figuring out how to replicate that snippet in Visual Studio Code wasn't too hard, but as I was already perusing the snippet documentation, I started investigating other options.
One little annoyance I'd lived with for years was adding links to other articles on the blog.
While I write an article, I run the site on my local machine. When linking to other articles, I sometimes use the existing page address off the public site, and sometimes I just copy the page address from localhost
. In both cases, I want the URL to be relative so that I can navigate the site even if I'm offline. I've written enough articles on planes or while travelling without internet that this is an important use case for me.
For example, if I want to link to the article Adding NuGet packages when offline, I want the URL to be /2023/01/02/adding-nuget-packages-when-offline
, but that's not the address I get when I copy from the browser's address bar. Here, I get the full URL, with either http://localhost:4000/
or https://blog.ploeh.dk/
as the origin.
For years, I've been manually stripping the origin away, as well as the trailing /
. Looking through the Visual Studio Code snippet documentation, however, I eyed an opportunity to automate that workflow.
Snippet #
I wanted a piece of editor automation that could modify a URL after I'd pasted it into the article. After a few iterations, I've settled on a surround-with snippet that works pretty well. It looks like this:
"Make URL relative": { "prefix": "urlrel", "body": [ "${TM_SELECTED_TEXT/^(?:http(?:s?):\\/\\/(?:[^\\/]+))(.+)\\//$1/}" ], "description": "Make URL relative." }
Don't you just love regular expressions? Write once, scrutinise forever.
I don't want to go over all the details, because I've already forgotten most of them, but essentially this expression strips away the URL origin starting with either http
or https
until it finds the first slash /
.
The thing that makes it useful, though, is the TM_SELECTED_TEXT
variable that tells Visual Studio Code that this snippet works on selected text.
When I paste a URL into an a
tag, at first nothing happens because no text is selected. I can then use Shift + Alt + → to expand the selection, at which point the Visual Studio Code lightbulb (Code Action) appears:
Running the snippet removes the URL's origin, as well as the trailing slash, and I can move on to write the link text.
Conclusion #
After I started using Visual Studio Code to write blog posts, I've created a few custom snippets to support my authoring workflow. Most of them are fairly mundane, but the make-URLs-relative snippet took me a few iterations to get right.
I'm not expecting many of my readers to have this particular need, but I hope that this outline showcases the capabilities of Visual Studio Code snippets, and perhaps inspires you to look into creating custom snippets for your own purposes.
Comments
Seems like a useful function to have, so I naturally wondered if I could
make it worseimplement a similar function in Emacs.Emacs lisp has support for regular expressions, only typically with a bunch of extra slashes included, so I needed to figure out how to work with the currently selected text to get this to work. The currently selected text is referred to as the "region" and by specifying
"r"
as a parameter for theinteractive
call we can pass the start and end positions for the region directly to the function.I came up with this rather basic function:
With this function included in config somewhere: it can be called by selecting a url, and using M-x
make-url-relative
(or assigned to a key binding as required)I'm not sure if there's an already existing package for this functionality, but I hadn't really thought to look for it before so thanks for the idea 😊