How-tos  Scripts  Pricing  Testimonials  Support  Newsletter

Tested on OpenBSD 6.3, 6.4, and macOS 10.14 with lowdown and Markdown.pl

Make a static site with find(1), grep(1), and lowdown or Markdown.pl

ssg is a static site generator written in shell. Optionally it converts Markdown files to HTML with lowdown(1) or Markdown.pl.

Unless a page has <HTML> tag ssg5 extracts its title from <H1> tag, wraps the page with _header.html, _footer.html.

Then copies everything (excluding .*, CVS, and _*) from src to dst directory.

ssg4 180 LoC. Enlarge, enhance, zoom!

Install

On OpenBSD:

$ mkdir -p bin
$ ftp -Vo bin/ssg5 https://rgz.ee/bin/ssg5
ssg5       100% |*********************|    4916      00:00
$ chmod +x bin/ssg5
$ doas pkg_add lowdown
quirks-2.414 signed on 2018-03-28T14:24:37Z
lowdown-0.3.1: ok
$

Or on macOS:

$ mkdir -p bin
$ curl -s https://rgz.ee/bin/ssg5 > bin/ssg5
$ curl -s https://rgz.ee/bin/Markdown.pl > bin/Markdown.pl
$ chmod +x bin/ssg5 bin/Markdown.pl
$

lowdown(1) and Markdown.pl are optional. They are required only if there are any *.md files.

Usage

Make sure ssg5 and lowdown or Markdown.pl are in your $PATH:

$ PATH="$HOME/bin:$PATH"
$ mkdir src dst
$ echo '# Hello, World!' > src/index.md
$ echo '<html><title></title>' > src/_header.md
$ bin/ssg5 src dst 'Test' 'http://www'
./index.md
[ssg] 1 files, 1 url
$ find dst
dst
dst/.files
dst/index.html
dst/sitemap.xml
$ open dst/index.html

Markdown and HTML files

HTML files from src have greater priority than Markdown ones. ssg5 converts Markdown files from src to HTML in dst and then copies HTML files from src to dst. In the following example src/a.html wins:

src/a.md   -> dst/a.html
src/a.html -> dst/a.html

Favicon

Make sure you have /favicon.png in place.

Some browsers fetch /favicon.ico despite what you specified in the <LINK> tag, so you can use an empty one (180 bytes) as a placeholder.

Sitemap

ssg5 generates sitemap.xml with the list of all page. Don’t forget to add absolute URL of the sitemap to your robot.txt.
For example:

user-agent: *
sitemap: https://rgz.ee/sitemap.xml

RSS

To generate RSS feeds use rssg, then add their URLs to _header.html.
For example:

<link rel="alternate" type="application/atom+xml" href="/rss.xml">

Incremental updates

On every run ssg5 saves a list of files in dst/.files and updates only newer files. If no files were modified after that, ssg5 does nothing.

$ bin/ssg5 src dst 'Test' 'https://www'
[ssg] no files, 1 url
$

To force the update delete dst/.files and re-run ssg5.

$ rm dst/.files
$ bin/ssg5 src dst 'Test' 'https://www'
index.md
[ssg] 1 file, 1 url
$

Watch

Save this helper to ~/bin/sssg. It re-runs ssg5 with entr(1) on every file change.

$ cat $HOME/bin/sssg
#!/bin/sh
while :
do
    find . -type f ! -path '*/.*' |
    entr -d "$HOME/bin/ssg5" . "$1" "$(date)" '//www'
done
$

Install entr(1):

$ doas pkg_add entr
quirks-2.414 signed on 2018-03-28T14:24:37Z
entr-4.0: ok
$

Start the helper and keep it running:

$ ~/bin/s /var/www/htdocs/www
[ssg] 1 file, 1 url

Users

blog.solobsd.org
bloguslibrus.fr
bsdjobs.com
cryogenix.net
dethronedemperor.com
grosu.nl
h3artbl33d.nl
high5.nl
matthewgraybosch.com
mvidal.net
openbsd.amsterdam
openbsd.space
romanzolotarev.com — obviously ;)
runbsd.info
stockersolutions.com
why-vi.rocks


Thanks to Devin Teske for helping with awk(1), Kristaps Dzonsons for lowdown(1), and Eric Radman for entr(1).


© 2008–2019 Roman Zolotarev  User Agreement  Privacy Policy