loading...

Pug with Markdown is Magic, yet underrated

patarapolw profile image Pacharapol Withayasakpunt Updated on ・2 min read

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.

GitHub logo 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
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

Now, you can use Pug inside Markdown.

^^pug.
  h1 Hello
Enter fullscreen mode Exit fullscreen mode

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)
          }
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
// 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)
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Discussion

pic
Editor guide
Collapse
bholmesdev profile image
Ben Holmes

This is exactly what I've been looking for on my personal site! Wanted to find a neat way to mix markdown into my HTML, but writing markup in a raw .md file got messy fast. This is an awesome solution. Thanks for pointing this out 😁