Extend markdown parser for Hugo
12月 2, 2019 tech postI use Hugo for my blog and notes. And the most powerful thing I love in Hugo is Shortcodes. It’s a wrapper of html but support to use Hugo’s vars and functions. With shortcodes you can add a css class to your link or embed a code snippet from a Github link.
The thing is, typing a shortcodes such as {{<name "string1" "stirng2">}}
, is a little bit heavey for me especially when I want to edit my blog on iPhone, I can’t even type the {{}}
. So I start to investigate if there is a way to simplify this in Hugo.
I found that Hugo starts to use http://github.com/yuin/goldmark as its default markup engine since v0.60.0 and goldmark is easy to extend. It should be feasible to fork Hugo to use my own goldmark extensions.
Details for writing an extension for goldmark is out of scope of this post. Typical there are 3 steps:
- create AST
- define the parser
- define how to render it
You can find some examples in both https://github.com/yuin/goldmark/tree/master/extension and https://github.com/kaleocheng/goldmark-extensions.
I decided to use a new syntax to replace the long shortcodes syntax:
- {{<name "string1" "stirng2">}}
+ @name("string1", "string2")
It’s easier to type and readable for me. Next I forked and updated Hugo’s code, re-built it to use my extenions. It’s very straightforward:
- add extension package to
go.mod
and rungo mod tidy
to download - append new extensions in
Extensions
https://github.com/gohugoio/hugo/blob/master/markup/goldmark/goldmark_config/config.go#L44 and enable them in https://github.com/gohugoio/hugo/blob/master/markup/goldmark/goldmark_config/config.go#L19 - import extenions pkg and add them to
newMarkdown
https://github.com/gohugoio/hugo/blob/master/markup/goldmark/convert.go#L67 - install
mage
and re-build withmage hugo
use
replace github.com/xxx/xxx => /Users/xxx/localdir
ingo.mod
when you develop the extension package.
I also wrote an extension for $\LaTeX$ which parse $\TeX$ code by $...$
and $$...$$
. (In addition, I use a fork version of https://github.com/atishay/tex2svg as the backend to embedded $\TeX$ svg at build time).
Finally I have my own syntax in markdown:
- {{<book "The Old Man and The Sea" >}}
+ @book("The Old Man and the Sea")
- {{<refer "example.com" >}}
+ @refer("example.com")
- {{<latex x^2 + y^2 = 0 >}}
+ $x^2 + y^2 = 0$