M README => README +42 -11
@@ 1,23 1,56 @@
wersh
-Static site generation with POSIX shell scripts, loosely inspired by werc[1].
+Static site generation with POSIX shell scripts, loosely inspired by werc.
USAGE
wersh [-w] [input] [output]
-Sources [input]/**.sh and writes the output to [output]/**. Input defaults to ./
-and output defaults to _site/.
+wersh takes files from input/**.sh, converts them into scripts with wersh.awk,
+then sources these scripts to produce output files as output/**. Files that
+don't match *.sh are copied directly to the output. Any files or directories
+that begin with _ are ignored.
-Files that don't match *.sh are copied directly. Files and directories that
-match _* are not used.
+Files parsed with wersh.awk produce scripts. Any line prefixed with % will be
+added to the script, and any line without will be automatically output by the
+target script. Run wersh.awk < input > output to get an idea of how it works.
-When your script executes, the working directory is set to input.
+PREPROCESSING
-The special file _config.sh will be sourced for all scripts if present.
+You can use a preprocessor to convert script output into some other format. For
+example, to convert script output to markdown:
--w will use inotifywait to watch for changes, then automatically recompile your
-site. This is only supported on Linux.
+% preprocessor="hoedown"
+
+Your script output will be piped into the preprocessor, and its output used as
+your script output.
+
+ENVIRONMENT
+
+When your script executes, the working directory is set to the input directory
+and the following variables are available:
+
+- root: top level input directory
+- input: path to the input file being processed
+- output: path to the output file
+- outputdir: top level output directory
+
+The wsource function is also available, which behaves like the source builtin,
+but it will run the file through wersh.awk first. This is useful for making
+templates or including files.
+
+TEMPLATES
+
+The recommended method for making templates is to overwrite the render()
+function in the template script and source the template script from any files
+that will use it. The render() function is piped the preprocessed script output
+and is expected to print the final output. You may use wersh.awk for your
+template - any output lines are printed directly during the render() function.
+
+SITE-WIDE CONFIGURATION
+
+If present, the special file _config.sh will be sourced. Note that it will not
+be preprocessed by wersh.awk.
EXAMPLES
@@ 27,5 60,3 @@ See example/ for an example wersh site. Run the following:
lighttpd -Df lighttpd.conf
Then browse to http://localhost:8080 to check out the example site.
-
-[1] http://werc.cat-v.org/
M example/_config.sh => example/_config.sh +10 -4
@@ 1,7 1,3 @@
-function hoedown() {
- /usr/bin/hoedown --tables --fenced-code
-}
-
pages="page-one.html.sh page-two.html.sh"
function page_title() {
@@ 14,3 10,13 @@ function page_title() {
;;
esac
}
+
+case $input in
+ *.html.sh)
+ preprocessor="hoedown --tables --fenced-code"
+ wsource _templates/layout.html.sh
+ ;;
+ *.scss.sh)
+ preprocessor="sassc -s -t compressed"
+ ;;
+esac
M example/_templates/layout.html.sh => example/_templates/layout.html.sh +5 -6
@@ 1,14 1,13 @@
-cat <<EOF
+% function render() {
<!doctype html>
<html>
<head>
- <title>${title:-Test site}</title>
+% echo "<title>${title:-Test site}</title>"
<link rel="stylesheet" type="text/css" href="/css/main.css" />
</head>
<body>
-EOF
-content
-cat <<EOF
+% cat
</body>
</html>
-EOF
+% }
+
M example/css/main.css.sh => example/css/main.css.sh +2 -2
@@ 1,4 1,5 @@
-cat <<EOF | sassc -s -t compressed
+% # vim: set ft=sass :
+
html
body {
max-width: 500px;
@@ 16,4 17,3 @@ img {
margin: 0 auto;
max-height: 300px;
}
-EOF
M example/index.html.sh => example/index.html.sh +8 -14
@@ 1,24 1,22 @@
-function content() {
- cat <<EOF | hoedown
+% # vim: set ft=markdown :
# wersh
Static site generation with POSIX shell scripts, loosely inspired by
[werc](http://werc.cat-v.org).
This page is a shell script: [example/index.html.sh](/index.html.sh). Files
-ending with *.sh are sourced and their stdout is written to the corresponding output file.
+ending with \*.sh are sourced and their stdout is written to the corresponding
+output 'file'.
## Pages
Since it's a shell script, you can do pretty much anything you want. This list
of pages is dynamically generated:
-EOF
- for page in $pages
- do
- echo "* [$(page_title "$page")](${page%%.sh})" | hoedown
- done
- cat <<EOF | hoedown
+% for page in $pages
+% do
+% emit "* [$(page_title "$page")](${page%%.sh})"
+% done
## Static content
@@ 26,8 24,4 @@ Files that don't end in *.sh are automatically copied into the output
directory, like this one:

-EOF
-}
-
-. _templates/layout.html.sh
-cp index.html.sh "$outputdir"/index.html.sh
+% cp index.html.sh "$outputdir"/index.html.sh
M example/page-one.html.sh => example/page-one.html.sh +1 -5
@@ 1,10 1,6 @@
-function content() {
- cat <<EOF | hoedown
+% # vim: set ft=markdown :
# Page one
This is a test page.
[back](/)
-EOF
-}
-. _templates/layout.html.sh
M example/page-two.html.sh => example/page-two.html.sh +1 -5
@@ 1,10 1,6 @@
-function content() {
- cat <<EOF | hoedown
+% # vim: set ft=markdown :
# Page two
This is a test page.
[back](/)
-EOF
-}
-. _templates/layout.html.sh
M wersh => wersh +29 -3
@@ 6,6 6,7 @@ function usage() {
exit 1
}
+_bin=$(readlink -f $0)
_single=
_watch=
_n=0
@@ 27,20 28,45 @@ do
done
[ $_n -ne 0 ] && shift $_n
+function render() {
+ cat -
+}
+
+function emit() {
+ if [ "$_rendering" == "t" ]
+ then
+ printf "%s\n" "$@"
+ else
+ content="$content
+$@"
+ fi
+}
+
function escape() {
sed -e 's/</\</g' -e 's/>/\>/g'
}
+function wsource() {
+ local _file=$(mktemp)
+ $(dirname $_bin)/wersh.awk < "$1" > "$_file"
+ source "$_file"
+ rm "$_file"
+}
+
+preprocessor="cat"
+
if [ -n "$_single" ]
then
[ $# -ne 4 ] && usage
root=$(readlink -f $1)
outputdir=$(readlink -f $2)
output=$3
- _input=$(readlink -f "$4")
+ input=$4
cd $root
[ -e "$root"/_config.sh ] && . "$root"/_config.sh
- . "$_input"
+ wsource $input
+ _rendering=t
+ printf "%s" "$content" | $preprocessor | render
elif [ -n "$_watch" ]
then
[ $# -gt 2 ] && usage
@@ 67,7 93,7 @@ else
_output=${_output%.sh}
echo "Generating $_output from $_input"
mkdir -p $(dirname "$_output")
- $0 -s "$root" "$_outputdir" "$_output" "$_input" > "$_output"
+ $0 -s "$root" "$_outputdir" "$_output" "${_input#$root/}" > "$_output"
done
find "$root" -type f -not -name "*.sh" -not -path "*/_*/*" -not -name "_*" | \
while IFS= read -r _input
A wersh.awk => wersh.awk +20 -0
@@ 0,0 1,20 @@
+#!/usr/bin/awk -f
+BEGIN { mode="line" }
+{
+ if (mode == "line") {
+ if ($0 ~ /^%%%$/) {
+ mode="block";
+ } else if ($0 ~ /^%.*$/) {
+ print substr($0, 3);
+ } else {
+ gsub(/'/, "'\"'\"'", $0);
+ print "emit '" $emit "'";
+ }
+ } else if (mode == "block") {
+ if ($0 ~ /^%%%$/) {
+ mode="line";
+ } else {
+ print $0;
+ }
+ }
+}