stp
(shell template processor) is an extensible static site generator and generic template processor in 100 lines of POSIX shell. Plugins for automatic generation of navigation links, index files, etc are another couple hundred lines.
Summary of features:
- Dynamic template engine based on shell command substitution (no new syntax)
- Recursive template instantiation
- Supports both source templates (e.g. markdown) and target templates (e.g. html)
- Extensible with plugins for template functions and generators
- Supports any combination of input formats and output formats
- The default configuration generates semantic HTML5 with classless CSS and no Javascript from a directory of markdown files
If you have a directory of markdown files, this will generate an HTML page for each markdown file in the same directory as the markdown file.
- Install the smd markdown renderer.
- In the
stp
directory, run./make
sudo ./make install
cp -r stp/config <your-markdown-directory>/.stp
cd <your-markdown-directory>
stp
If you want to use another markdown processor you can replace smd
in the md.to.html
template.
You can add =
annotations to markdown files if you want index files to show dates:
Title
=====
= published: 2023-09-30
= tags: blog
Main content
Another option is manually writing index.md
files which provides more flexibility and doesn't require =
annotations.
The main idea of stp
is to use shell command substitution and parameter expansion to instantiate templates. It does this by automatically escaping double quotes and backticks in the input, then eval
ing a printf
with the input placed inside shell script double quotes. The actual instantiation code is one line:
eval "printf '%s\\n' \"$(sed 's/\\*\(["`]\)/\\\1/g' "$path")\""
This is a simplified markdown to HTML template:
<html>
<head>
<meta name="generator" content="stp:$GENERATOR">
<title>$TITLE</title>
<link rel="stylesheet" href="/.stp/styles/default.css">
</head>
<body>
<header>
$(breadcrumb)
</header>
$(input | smd)
</body>
</html>
Instantiation will substitute the value of the shell variables for GENERATOR
and TITLE
, and run the code in the $()
brackets, substituting the output into the template. The input
function prints the contents of the current source file being processed, which is then stripped of metadata annotations with grep
, then processed with the smd
markdown processor to fill in the main content.
Templates can recursively instantiate other templates, which allows you to extract common parts like headers and footers. The above template could be refactored to:
$(instantiate header.html)
$(input | smd)
$(instantiate footer.html)
Now the header
and footer
templates can be reused in other templates.
Any .sh
shell script you place in the .stp/plugins
directory will be automatically imported when you run stp
and any functions imported from plugins will be available in all templates.
To avoid conflicts between plugins, each plugin should only define one top-level function and the name should be the same as the filename without the .sh
extension. Additional functions can be defined nested inside the top-level function starting with an underscore, which ensures they don't interfere with any top-level functions.