@nera-static/highlightjs-pug on highlight.js 11, with no extra CSS: the colors come from a stock highlight.js theme. Hover a token to see its scope.
Three of the eight Pug blocks on the Nera website, unchanged.
include ../vendor/plugin-navigation/partials/link-list-navigation
header.site-header
if app.nav && app.nav.main
+linkListNav(app.nav.main.elements, 'nav--main')if app.tutorials && app.tutorials.length
ul.tutorials__list
each post in app.tutorials
li.tutorials__item
a.tutorials__link(href=post.href)
h2 #{ post.title }
p #{ post.description }extends ../layouts/layout
block content
.container
include ../vendor/plugin-tags/pages/tag-overviewThe header mixin of a production Nera theme: comments, code lines, attributes with JavaScript, conditionals, loops and interpolation.
//- Sticky top bar. The home page gets the full section navigation, every other
//- page (legal pages, blog posts, tag overviews) the "back to home" button.
//- Navigation entries pointing at an index.html are the language switchers of
//- config/navigation.yaml; they are rendered as the [DE] EN toggle instead.
mixin header(lang, isHome)
- const tx = app.theme.config.text[lang]
- const homeHref = lang === app.lang ? '/' : `/${ lang }/`
- const elements = app.nav['main_' + lang].elements
- const sectionLinks = elements.filter((item) => !item.href.includes('index.html'))
- const langLinks = elements.filter((item) => item.href.includes('index.html'))
header.nav(data-nav)
.nav-in
a.brand(href=`${ homeHref }#home`)
span.sq
| Michael Becker
if isHome
nav.links#main-nav(aria-label=tx.main_nav)
each item in sectionLinks
a(href=item.href.replace(/^\/(en\/)?/, ''), data-nav-link) #{ item.name }
.nav-right
span.lang
span [#{ lang.toUpperCase() }]
each item in langLinks
a(href=item.href, hreflang=item.name.toLowerCase(), lang=item.name.toLowerCase()) #{ item.name }
a.btn.btn-contact(href="#contact") #{ tx.contact }
button.nav-toggle(type="button", aria-controls="main-nav", aria-expanded="false", data-nav-toggle)
span.nav-toggle-bars(aria-hidden="true")
span.sr-only Menu
else
a.back(href=`${ homeHref }#home`) #{ tx.back_home }One template that touches each construct the grammar knows.
doctype html
//- A Pug comment, kept out of the HTML
// A comment that ends up in the HTML
html(lang="en")
head
title= pageTitle
include ../partials/head
body.home#top(data-page=slug)
- const posts = app.posts.filter((post) => post.published)
+header(lang, isHome)
if posts.length > 0
ul.posts
each post, i in posts
li: a(href=post.href, class=i === 0 ? 'first' : undefined) #{ post.title }
else
p.empty No posts yet. #[a(href="/new") Write one]
case kind
when 'note': p.note= text
default: p!= html
p
| Escaped: \#{ not interpolated }
:markdown-it(linkify)
<hr class="divider">
mixin header(lang, isHome = false)
header.site-header&attributes(attributes)
blockIndentation decides what these mean, and highlight.js does not track indentation. The README documents each one.
p.
A text block: highlight.js matches line by line,
so each continuation line starts like a tag.
//-
A multi-line comment: only the marker line
is a comment.
:markdown-it
Filter bodies are not highlighted as Markdown.
a(href=x disabled) Space-separated boolean after a valueThe grammar uses only standard highlight.js scopes, so every theme colors it. JavaScript inside attributes, code lines and interpolation is highlighted by highlight.js's own JavaScript grammar.
| Example | Scope | Pug |
|---|---|---|
header | name | tag |
.container | selector-class | class shorthand |
#main | selector-id | id shorthand |
href= | attr | attribute name |
extends | keyword | keyword |
../layouts/layout | string | path or string |
mixin card | title.function | mixin name |
(title | params | mixin parameters |
#{ x } | subst | interpolation |
= | operator | output and code markers |
| | punctuation | pipe, block expansion |
// | comment | comment |
| meta | doctype, filter |
Paste or type a template; it is highlighted as you type.