A simple static website generator, heavily inspired by sw & co
sws fills a niche that didn't really need to be filled: that of static website generators. It does so following the footsteps of sw and swx, but adding a simple plugin system for when some more complexity is required.
The base script (sws
) behaves like sw
, turning a nested folder structure containing markup files into something that can be viewed by a browser, but it can do more than that: it can be templated using a very simple syntax that allows for easy embedding of shell snippets, and sample plugins to handle blogs/simple wikis are included in the distribution.
It does everything with (mostly/hopefully) POSIX-sh-compliant shell scripts, sed, grep, awk and ed, and less than four hundred lines of code between the core script and plugins. As for the why - I wanted something simple, but not quite as simple as sw
, and I was in the mood for some shell scripting and wheel re-inventing.
sws does not need to be installed. It can be copied/symlinked into a directory somewhere in $PATH
, but it'll work just fine by slapping it somewhere Make (or whatever is been used to invoke it) can find it.
$ sws SOURCE DESTINATION
After loading _config
, generating the templates and loading the contents of the _plugins
directory (if any), sws will go through each file in SOURCE
and either copy them or convert them to HTML to put them in the DESTINATION
directory.
This can be automated - especially when dealing with multiple sub-sites with their own plugins - by putting the calls in a Makefile.
sws supports a very simple syntax for metadata, in the style of the refer troff preprocessor. Metadata fields are single-line, and begin with a percent sign (%
) immediately followed by an uppercase letter, a space, and some data.
Conventionally, the following meanings have been assigned to the various letters, and they are used by sws for the same purpose:
%T
: title of the work;%A
: author;%D
: date of publication;%K
: keywords/tags, space-separated;%X
: summary.
sws can be configured by setting environment variables, either by exporting them or by adding them to the _config
file of the source directory. It uses the following variables:
MARKDOWN
: path to/command to convert markdown source into HTML.find_opts_pre
andfind_opts_post
: options to be passed to thefind
command tasked with finding all the files to parse inside the source directory.head_tmpl
,foot_tmpl
andplugins_foldr
: paths pointing at the_header
and_footer
files, or_plugins
directory, if they are not contained within the same directory as the_config
file.
sws uses a very simple templating system, processing files with an awk script to turn them into shell functions.
Lines starting with %
are passed through without any processing, allowing the embedding of shell code for loops and conditionals, while lines that do not are simply echoed out. Variables can be embedded with the {{variable}}
syntax, and likewise for subshells ({{(shell)}}
, but they cannot contain the }
character).
Template example:
<!DOCTYPE html>
<html lang="{{lang}}">
<head>
<title>{{site_title}}</title>
% for style in $css; do
<link rel="stylesheet" type="text/css" href="/css/{{style}}.css">
% done
</head>
sws will load (source) all the files or symlinks inside the _plugins
subdirectory of the main directory. They can modify or extend how sws works, either by overriding its functions or by adding hooks.
get_meta FILE FIELD
: given a filename, returns the contents ofFIELD
if present.sws_skip FILE
: given a filename, returnstrue
if that file should not be handled by sws (by default this means thatFILE
's basename starts with an underscore).sws_handle FILE
: given a filename, either copies it to the destination directory or invokessws_markup
andsws_page
to create the corresponding page. It also sets thename
andbare
variables.sws_markup FILE
: strips the metadata fromFILE
and either pipes it to a document converter or copies it straight to the output.sws_page
: expects HTML markup on stdin, and invokes the header and footer templates while taking care of setting thepage_title
andprefix
variables.
src
: the source directory.dst
: the destination directory.from
: the path of the current file being handled.name
: the path where the file will be put after being processed.bare
: the basename of the current file/page, minus the extension.prefix
: relative path leading to the root of the site, used for example to link to CSS and other assets.
Hooks are called in FIFO order, and can be added by using the add_hook
function to the pre_site
, pre_page
, post_page
and post_site
phase.
Syntax:
add_hook PHASE FUNCTION
pre_site
and post_site
are executed only once per sws call, immediately before and after processing the files in the source directory. The post_page
hook is called, once for every file, after copying the file/creating a page from it.
A few sample plugins are included in the sws distribution.
A simple weblog plugin, it handles the creation of a chronological archive, a RSS feed and of an index page containing the last published article and links to the previous ones.
It can be minimally configured by setting the blog_show_older
variable, which defaults to ten and which is the number of items (besides the very last article) that will be linked from the index page.
A very simple static wiki compiler, preprocessing markdown sources to handle wikilinks and appending a list of backlinks to each page. An index of all the pages in the wiki is also created under all.html
.
The syntax for wikilinks is [[Description|Target]]
, with the description part being optional. Wikilinks pointing at inexistent pages are not linked and instead flagged with a superscript ?
.
It overrides sws_markup
, ignoring HTML files to pipe markdown files into the wikify
function (a thin wrapper around an Awk script) before getting to the markdown processor.
Handles the creation of tag pages for a wiki or blog, extracting tag information from the %K
metadata field, listing pages in reverse chronological order (newer first). These will be put in thetag
sub-directory.
Copyright (c) 2018 mftrhu mftrhu+github@inventati.org
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.