Working with Soupault
I wrote this website using Soupault as the SSG1. You might have not heard of it before, its a smaller tool and it is not written in JavaScript.
The idea behind soupault is to chain together other tools that do one thing (and do them well). That's why I also use these tools in my SSG pipeline:
Use Case | Tool |
---|---|
Syntax Highlighting | highlight |
Style Pre-processing | Sass |
Markdown rendering | Pandoc |
PNG Compression | pngquant |
The pipeline
It essentially works like this:
- Transform page files (in my case markdown files) through the applicable page processor (pandoc)
-
Run widgets, which are small functions that transform the generated
HTML
-
Identify
<code>
blocks and run their content throughhighlight
- Run some other widgets (see below)
-
Identify
-
Transform assets using asset processors
- Convert scss files to css
- Compress png files with pngquant
Widgets
Some interesting widgets I use on my site:
Inject MathJax on blog posts
[widgets.inject-mathjax] widget = "insert_html" html = '<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js"></script>' selector = "body" section = "blog"
Highlight code blocks
[widgets.unwrap-code] widget = "unwrap" # Custom plugin, see plugins below selector = 'pre > code' [widgets.highlight] widget = "preprocess_element" selector = 'pre[class]' command = 'highlight -O html -f --syntax=$(echo $ATTR_CLASS) --inline-css --style=darkplus' after = "unwrap-code"
Plugins
I wrote some plugins for this website, which you might have a use for as well:
Fill the
content of <time>
tags with a formatted date
time_tags = HTML.select(page, "time") local index = 1 while time_tags[index] do time_tag = time_tags[index] datetime = HTML.get_attribute(time_tag, "datetime") if datetime then formatted_date = Date.reformat(datetime, { "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d" }, "%b %d, %Y") HTML.replace_content(time_tag, HTML.create_text(formatted_date)) end index = index + 1 end
Unwrap nodes
This will remove the parent node, but keeps the content.
selector = config["selector"] tags = HTML.select(page, selector) local index = 1 while tags[index] do tag = tags[index] HTML.unwrap(tag) index = index + 1 end
Use it:
[widgets.unwrap-code] widget = "unwrap" selector = 'pre > code'
Wikilinks
Transforms wikilinks (created from pandoc) to absolute urls.
wikilink_tags = HTML.select(page, "a.wikilink") current_href = nil function is_match(item) file = Sys.strip_extensions(Sys.basename(item.page_file)) if file == current_href then return 1 end return nil end index = 1 while wikilink_tags[index] do wikilink_tag = wikilink_tags[index] href = HTML.get_attribute(wikilink_tag, "href") if href then current_href = href values = Table.find_values(is_match, site_index) value = values[1] if value then HTML.set_attribute(wikilink_tag, "href", value["url"]) if value["title"] then HTML.replace_content(wikilink_tag, HTML.create_text(value["title"])) end else Log.warning("No link target found for href: " .. href) HTML.set_attribute(wikilink_tag, "href", "#") HTML.add_class(wikilink_tag, "unresolved") end end index = index + 1 end
And for images and similar tags:
tags = HTML.select_all_of(page, { "img[src]", "audio[src]" }) index = 1 while tags[index] do tag = tags[index] src = HTML.get_attribute(tag, "src") if src and not String.starts_with(src, "http") then fixed_src = "/assets/attachments/" .. src HTML.set_attribute(tag, "src", fixed_src) end index = index + 1 end
Other config snippets
Snippets that are neither plugins nor widgets, but still might be interesting:
My pandoc config
[preprocessors] md = "pandoc --no-highlight --template=pandoc/template.html --from=gfm+wikilinks_title_after_pipe+autolink_bare_uris+alerts --mathjax"
Template
$if(title)$ <h1>$title$</h1> $endif$ $if(pubDate)$ <div class="date-meta"> <time datetime="$pubDate$" class="pubDate"><!-- filled by soupault --></time></p> $if(updatedDate)$ <div class="last-update"> <span>(Last update: </span><time datetime="$updatedDate$" class="updatedDate"><!-- filled by soupault --></time><span>)</span> </div> $endif$ </div> $endif$ $body$ $if(featured)$ <meta name="x-featured" content="true"> $endif$
-
Static Site Generator↩︎