https://github.com/clark800/stp
minimalist extensible templating static site generator in 100 lines of POSIX shell
https://github.com/clark800/stp
posix posix-sh posix-shell shell shell-script shellscript static-site static-site-generator template-engine template-processor
Last synced: 5 months ago
JSON representation
minimalist extensible templating static site generator in 100 lines of POSIX shell
- Host: GitHub
- URL: https://github.com/clark800/stp
- Owner: clark800
- License: mit
- Created: 2023-05-03T22:54:23.000Z (almost 3 years ago)
- Default Branch: master
- Last Pushed: 2024-12-29T20:39:59.000Z (about 1 year ago)
- Last Synced: 2025-09-26T04:02:56.632Z (6 months ago)
- Topics: posix, posix-sh, posix-shell, shell, shell-script, shellscript, static-site, static-site-generator, template-engine, template-processor
- Language: Shell
- Homepage:
- Size: 197 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
stp
===
`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
Quick Start
-----------
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.
1. Install the [smd](https://github.com/clark800/smd) markdown renderer.
2. In the `stp` directory, run `./make`
3. `sudo ./make install`
4. `cp -r stp/config /.stp`
5. `cd `
6. `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.
How it works
------------
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:
```shell
eval "printf '%s\\n' \"$(sed 's/\\*\(["`]\)/\\\1/g' "$path")\""
```
This is a simplified markdown to HTML template:
```html
$TITLE
$(breadcrumb)
$(input | smd)
```
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.
Recursive templates
-------------------
Templates can recursively instantiate other templates, which allows you to extract common parts like headers and footers. The above template could be refactored to:
```html
$(instantiate header.html)
$(input | smd)
$(instantiate footer.html)
```
Now the `header` and `footer` templates can be reused in other templates.
Plugins
-------
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.