⚠️ ssg.sh reads from the source directory and reads from and writes to the destination directory. it will delete any unexpected files in the destination. use with caution!
ssg.sh builds static websites by converting markdown to html, applying templates, executing site scripts, honoring ignore files, zipping content, and copying other files unchanged. on subsequent runs, it only updates what has changed.
it's a 10 kb shell script with an optional dependency on lowdown.
ssg.sh works on openbsd, macos, and with minor
adjustments should work on most unix-like systems.
create a source directory with a markdown file and run ssg.sh:
$ mkdir src $ echo '# hello, world!' > src/index.md $ ssg.sh src dst md index.md > index.html md index.md > index.html.gz c0a431cc4f351f9135d001314c846fccf3f6eea0ee8b4c332e947fc5dd224321 $
on the first run, index.md is converted to index.html and gzipped. the final
line is the sha256 hash of the dst directory.
check files in dst:
$ find dst dst dst/.ssg.dst dst/.ssg.src dst/index.html dst/index.html.gz $
ssg.sh created dst directory and generated four files:
.ssg.dst contains hashes for all files in dst,.ssg.src—for files in src,index.html generated from index.md,index.html.gz—its gzipped version, useful for
httpd.the html file is simply the output generated by lowdown:
$ cat dst/index.html <h1 id="hello-world">hello, world!</h1> $
if nothing changed in src and you run it again:
$ ssg.sh src dst c0a431cc4f351f9135d001314c846fccf3f6eea0ee8b4c332e947fc5dd224321 $
it does nothing but prints the same sha256 hash.
each directory may have an .ssg.template file with simplified mustache:
{{title}} extracted from <h1> tag of a page,{{site}} is dirname of src,{{content}} is the content of a page,{{#title}}...{{/title}} renders its content only when title is defined.create the first template and re-run ssg.sh:
$ echo '<html>
<title>{{#title}}{{title}}: {{/title}}{{site}}</title>
<body>{{content}}<body>
</html>' >src/.ssg.template
$ ssg.sh src dst
template .ssg.template
md index.md, .ssg.template > index.html
md index.md, .ssg.template > index.html.gz
9216cbb74e6df54892539c1c80dd2f9ee17ce13ea0922f5aef6cc9aab6712a5f
$
if html file contains <html> tag then no template applied. otherwise, when an
html page is rendered, ssg.sh locates the nearest template in the current
directory or walks up the directory tree until it reaches the src directory.
now index.html should be wrapped with the template:
$ cat dst/index.html <html> <title>hello, world!: src</title> <body><h1 id="hello-world">hello, world!</h1><body> </html> $
each directory may have an .ssg.ignore file with list of file names to ignore.
directory names should end with /. wildcards are allowed.
$ mkdir src/.git $ echo >src/.git/index $ echo '.git/' >src/.ssg.ignore $ ssg.sh src dst ignore .ssg.ignore 9216cbb74e6df54892539c1c80dd2f9ee17ce13ea0922f5aef6cc9aab6712a5f $
same sha256 hash, no change in dst.
any directory may contain multiple .ssg.*.sh site scripts. each script must:
src and the second as dst,see also: .ssg.sitemap.sh, .ssg.logo.sh, .ssg.example.sh, txt2img.sh
all other files (unless ignored) are copied verbatim, then gzipped unless they
are *.png, *.jpg, *.gif, *.mp4, *.zip, or *.gz.
if a .gz file already exists alongside a file, that file is not gzipped.
ssg.sh aborts on any collision. examples include index.html and index.md
in the same directory, or a script generating dst/main.css when src/main.css
already exists.