npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nera-static/highlightjs-pug

v1.0.4

Published

Pug (formerly Jade) language grammar for highlight.js.

Readme

@nera-static/highlightjs-pug

Test npm version

A Pug (formerly Jade) grammar for highlight.js 11. It highlights tags, classes and ids, attributes with JavaScript values, keywords, mixins, interpolation and comments, using highlight.js's standard scopes, so every highlight.js theme colors it without extra CSS.

extends ../layouts/layout

block content
  //- Pug keeps its own comments out of the HTML
  ul.posts
    each post in app.posts
      li: a(href=post.href, class=post.featured ? 'featured' : undefined) #{ post.title }
  +pagination(meta.pagination)

🔍 Live demo: seebaermichi.github.io/nera-highlightjs-pug/demo: real templates in stock highlight.js themes, with the scope of each token on hover, and a box to try your own Pug.

📖 Built for Nera, whose templates are Pug; @nera-static/plugin-code-blocks registers it for Nera sites with no setup. It works the same with any highlight.js setup.

🚀 Installation

npm install @nera-static/highlightjs-pug highlight.js

highlight.js 11 is a peer dependency. The grammar has no other dependencies.

Usage

Node and bundlers

import hljs from 'highlight.js'
import pug from '@nera-static/highlightjs-pug'

hljs.registerLanguage('pug', pug)

hljs.highlight('a.btn(href=url) #{ label }', { language: 'pug' }).value

The grammar also registers the alias jade, so ```jade blocks work too.

Attribute values, code lines and interpolation are highlighted as JavaScript, and lines of literal HTML (<!DOCTYPE html>) as XML. With the full highlight.js build both are there. With highlight.js/lib/core, register them yourself; whatever is not registered stays plain text:

import hljs from 'highlight.js/lib/core'
import javascript from 'highlight.js/lib/languages/javascript'
import xml from 'highlight.js/lib/languages/xml'
import pug from '@nera-static/highlightjs-pug'

hljs.registerLanguage('javascript', javascript)
hljs.registerLanguage('xml', xml)
hljs.registerLanguage('pug', pug)

Browser

dist/pug.min.js registers itself on the global hljs, like highlight.js's own CDN language files. Load it after highlight.js:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@highlightjs/[email protected]/styles/github.min.css">
<script src="https://cdn.jsdelivr.net/npm/@highlightjs/[email protected]/highlight.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@nera-static/highlightjs-pug@1/dist/pug.min.js"></script>
<script>hljs.highlightAll()</script>

Then mark your blocks with <pre><code class="language-pug">. dist/pug.es.min.js is the same grammar as an ES module, for <script type="module">:

import hljs from 'https://cdn.jsdelivr.net/npm/@highlightjs/[email protected]/es/highlight.min.js'
import pug from 'https://cdn.jsdelivr.net/npm/@nera-static/highlightjs-pug@1/dist/pug.es.min.js'

hljs.registerLanguage('pug', pug)

Scopes

| Pug | Example | Scope | | --- | --- | --- | | tag | header, a | name | | class / id shorthand | .container, #main | selector-class, selector-id | | attribute name | href= | attr | | attribute value | post.href, 'nav--main' | JavaScript | | keywords | extends, block, append, prepend, include, mixin, if, else if, else, unless, each … in, for … in, while, case, when, default, yield, &attributes | keyword | | include / extends path | ../layouts/layout | string | | mixin declaration / call | mixin card(title), +card('Hi') | title.function; parameters params; arguments JavaScript | | code line | - const x = 1 | - as operator, rest JavaScript | | buffered output | p= title, p!= html | = / != as operator, rest JavaScript | | interpolation | #{ post.title }, !{ html }, #[em text], #{ tag }.card | subst, JavaScript or a tag inside | | comments | // visible, //- hidden | comment | | doctype | doctype html | meta | | piped text | \| text | \| as punctuation | | filters | :markdown-it | meta | | block expansion | li: a(href=x) Link | : as punctuation | | literal HTML line | <!DOCTYPE html> | XML |

Text, block names, escaped interpolation (\#{ x }) and // after a tag (span // text) stay plain, as Pug treats them as text.

Limits

highlight.js matches patterns line by line and does not track indentation. Pug constructs whose meaning comes from indentation are therefore only right on their first line:

  • Text blocks after p. or script.: each continuation line is read as a new line of Pug, so its first word looks like a tag.
  • Filter bodies under :markdown-it and the like: the same. The body is not highlighted in the filter's language.
  • Multi-line comments (//- followed by an indented block): only the marker line is a comment.
  • Code blocks (- alone, JavaScript on the indented lines below): only the - line is code.

Two smaller ones: a space-separated boolean attribute after a value (a(href=x disabled)) is read as part of the value (with commas, a(href=x, disabled), it is an attribute), and a regex literal containing parentheses inside an attribute value is split into several fragments. Both are cosmetic.

Auto-detection (hljs.highlightAuto) is best effort. Generic patterns such as a word at the start of a line or .class carry no weight, so prose and other languages are not taken for Pug. Whole templates with extends, include, mixin or each are usually detected; short snippets often are not, so name the language: ```pug, or class="language-pug".

Compatibility

  • highlight.js 11.
  • src/ is plain ES2018 without dependencies; Node.js 20 or later for the package tooling. dist/ runs in every browser highlight.js 11 supports.

🧪 Development

npx vitest run
npm run lint
npm run build   # rebuild dist/ and demo/demo.js after changing src/, and commit them

The tests are markup fixtures in highlight.js's format: test/markup/pug/<case>.txt is the input, <case>.expect.txt the expected HTML. WRITE_EXPECT=1 npx vitest run rewrites the expect files from the current grammar; review that diff before committing it. CI fails when dist/ or the demo was not rebuilt. The demo (demo/, served by GitHub Pages, not part of the npm package) bundles the grammar from src/ with highlight.js and self-hosted fonts, so it loads nothing from third parties.

📦 License

MIT