How to Insert Jump Anchors on Headings with PugJS

I'm definitely a fan of cats ๐Ÿ˜บ๏ธ in real life, but when it comes to code this reverses and I've got a preference for Pug ๐Ÿถ๏ธ For those who aren't coders: PugJS is a JavaScript template engine. It converts Pug-lang into HTML. I know there is more power in PugJS, besides the simple turning the Pug-lang into HTML. At the moment I'm not using the potential of the language - I use PugJS mostly to hold my content. Let's look at some ways to get more out of Pug I've learned about recently.

If you are using Pug on your static-site you can:

Pug is a powerful template engine and a read over the language reference is good for some "Ahhh, neat"-moments! Below, you will find a useful mixin-example applicable for daily coding.

An example: Adding dynamic anchors to headings using Pug-Mixins #

Often you might want an id to allow you to jump directly to a certain part of the document. For me, these are usually headings. The heading above "An example: Adding dynamic anchors to headings using Pug", I would write

An example: Adding dynamic anchors to headings using Pug

This triggers me, as it's error-prone, overhead to read as developer and overhead to maintain. Wouldn't it be nicer if you could avoid the double content and could instead generate the slug out of the heading on the fly? With Pug you can:

mixin h2(headline)
- let id = headline.toLowerCase().replaceAll(' ', '-').replace(/[!\"#$%&'\(\)\*\+,\.\/:;<=>\?\@\[\\\]\^`\{\|\}~]/g, '');
h2(id= id)
= headline

With this little helper Pug-mixin you can just write

+h2('An example: Adding dynamic anchors to headings using Pug')

and it will be processed to

<h2 id="an-example-adding-dynamic-anchors-to-headings-using-Pug">
An example: Adding dynamic anchors to headings using Pug

Isn't this a much better developer-experience? :)

Taking it one step further #

You can also make the heading level a parameter handed over to the mixin.

mixin h(level, headline)
- let id = headline.toLowerCase().replace(' ', '-').replace(/[!\"#$%&'\(\)\*\+,\.\/:;<=>\?\@\[\\\]\^`\{\|\}~]/g, '');
section(id= id)
#{'h' + level}= headline
if block

Allows you to write the following Pug-code

+h(2, 'Section A')

+h(2, 'Section B')
p Lorem ipsum dolor amit

+h(2, 'Section C')
p Lorem ipsum dolor amit
+h(3, 'Section C, Subsection A')
p Lorem ipsum dolor amit

will be compiled to the HTML shown below

<section id="section-a">
<h2>Section A</h2>

<section id="section-b">
<h2>Section B</h2>
<p>Lorem ipsum dolor amit</p>

<section id="section-c">
<h2>Section C</h2>
<p>Lorem ipsum dolor amit</p>
<section id="section-c-subsection-a">
<h3>Section C, Subsection A</h3>
<p>Lorem ipsum dolor amit</p>

This allows you to define any level of heading dynamically, on the fly.

Summary and Source #

As mentioned above, the language can do more. Mixins are only one powerful side of PugJS. Have a look at the language reference for more information. By the way, if you are a fan of Netlify too I have good news for you. Of course, you can use Pug with your Netlify-hosted website.

Praise where praise is due: Thanks to the Pug maintainers for their great work. I have to say "Thank you" to Sean who pointed me to the possibilities answering my question on Stackoverflow as well.


Since you've made it this far, sharing this article on your favorite social media network would be highly appreciated ๐Ÿ’–! For feedback, please ping me on Twitter.