Pug with Markdown is Magic, yet underrated
Pacharapol Withayasakpunt
Posted on January 4, 2020
What is Pug?
Pug is a high-performance template engine heavily influenced by Haml and implemented with JavaScript for Node.js and browsers.
Pug uses whitespace syntax, and is Tab / Space -sensitive, just like Markdown and Python
Pug is mainly a template engine for Node.js, and cannot be installed for Webpack via NPM/Yarn, however there is https://github.com/pugjs/pug#browser-support but it is a very large file. However, I created HyperPug a while ago, and it is relatively small.
patarapolw / hyperpug
Lightweight Pug for browser/Electron. With Pug filters' support, which can also contain indented language like markdown.
Pug with Markdown
Pug integrates nicely with Markdown, via Filters.
div
:markdown
## Hello
This can be enabled with Markdown engines, like Showdown or Markdown-it.
import hyperpug from 'hyperpug'
import showdown from 'showdown'
const mdConverter = new showdown.Converter()
console.log(hyperpug.compile({
filters: {
markdown: (s: string) => mdConverter.makeHtml(s)
}
})(str))
Creating a Markdown extension is easy, with Showdown.js
For an official tutorial, see https://github.com/showdownjs/showdown/wiki/extensions#creating-showdown-extensions
You can even create a Pug extension inside Markdown, with indented-filter
import { createIndentedFilter } from "indented-filter";
import showdown from "showdown";
const mdConverter = new showdown.Converter();
mdConverter.addExtension({
type: "lang",
filter: createIndentedFilter("^^pug", (str) => {
return pug.render(str)
})
}, "pug");
Now, you can use Pug inside Markdown.
^^pug.
h1 Hello
A roundabout Pug inside Markdown, and also with Markdown inside Pug is also possible, see https://github.com/patarapolw/zhlab/blob/master/web/utils/make-html.ts#L10
Enabling extended Pug (with Markdown) inside Vue, Nuxt, or simply pug-plain-loader
I made this possible with my new NPM package -- https://github.com/patarapolw/deepfind
// nuxt.config.js
import deepfind from '@patarapolw/deepfind'
import showdown from 'showdown'
const mdConverter = new showdown.Converter()
export default {
build: {
/*
** You can extend webpack config here
*/
extend (config, ctx) {
for (const r of deepfind(config, 'pug-plain-loader')) {
if (!Array.isArray(r)) {
r.options = r.options || {}
r.options.filters = {
markdown: (s: string) => mdConverter.makeHtml(s)
}
}
}
}
}
}
// vue.config.js
const deepfind = require('@patarapolw/deepfind').default
const showdown = require('showdown')
const mdConverter = new showdown.Converter()
module.exports = {
configureWebpack: (config) => {
for (const r of deepfind(config, 'pug-plain-loader')) {
if (!Array.isArray(r)) {
r.options = r.options || {}
r.options.filters = {
markdown: (s: string) => mdConverter.makeHtml(s)
}
}
}
}
}
Posted on January 4, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.