webnomad/render

381 lines
9.2 KiB
Bash
Executable File

#!/usr/bin/env zsh
#
# WebNomad, your slick and static website publisher
#
# Copyright (C) 2012-2014 Denis Roio <jaromil@dyne.org>
#
# This source code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# Please refer to the GNU Public License for more details.
#
# You should have received a copy of the GNU Public License along with
# this source code; if not, write to:
# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
VERSION=0.5
QUIET=0
SYS=`dirname $0`
source $SYS/utils
CMD="$1"
{ test -r config.zsh } || {
error "Directory not configured for WebNomad. First use /webnomad/init"
exit 1 }
####################################
# Base configuration
# base to be added to all urls
# used by test to have all css and js in place
baseurl=""
# destination directory to render
# also used by test to substitute pub/
destination="pub"
# web root for all urls
WEB_ROOT=""
# prefix to all indexed files
# this can be a full path on the filesystem
INDEX_PREFIX=""
# thumbnail size
THUMB_SIZE=256
source config.zsh
####################################
typeset -h dst # full path to destination for render_ functions
typeset -alU includecss # array of css files to include
typeset -alU includejs # array of js files to include
typeset -alU fonts # array of available fonts
# string match case insensitive
unsetopt CASE_GLOB
notice "Rendering your website"
act "Title: $B $TITLE $r"
render_header() {
cat <<EOF
<!DOCTYPE html>
<html>
<head>
<title>$TITLE</title>
<meta name="description" content="$DESCRIPTION" />
<meta name="keywords" content="$KEYWORDS" />
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="Generator" content="WebNomad $VERSION - http://dyne.org/software/webnomad" />
<meta name="MSSmartTagsPreventParsing" content="True" />
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements
http://html5shim.googlecode.com/svn/trunk/html5.js -->
<!--[if lt IE 9]>
<script src="js/html5.js"></script>
<![endif]-->
<!-- Bootstrap -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="${baseurl}css/bootstrap.min.css" rel="stylesheet" />
<link href="${baseurl}css/bootstrap-responsive.min.css" rel="stylesheet" />
EOF
{ test -r views/css/custom.css } && {
cat <<EOF
<link href="${baseurl}css/custom.css" rel="stylesheet" />
EOF
}
# add css needed for internal functions
for c in $includecss; do
cat <<EOF
<link href="${baseurl}css/${c}" rel="stylesheet" />
EOF
cp $SYS/css/${c} ${destination}/css/
done
{ test -f ${destination}/css/custom.fonts.css } && {
cat <<EOF
<link href="${baseurl}css/custom.fonts.css" rel="stylesheet" />
EOF
}
# add any argument string to header
{ test "$1" = "" } || { print "${@}"; print }
# add the user configured header
cat tmpl/header.html
}
render_footer() {
cat tmpl/footer.html
cat <<EOF
</div><!--/.container-->
EOF
# add any string argument to the footer
{ test "$1" = "" } || { print "${@}"; print }
# insert and copy all js files
for i in $includejs; do
cat <<EOF
<script type="text/javascript" src="${baseurl}/js/$i"></script>
EOF
{ test -r $SYS/js/$i } && {
cp $SYS/js/$i $destination/js }
done
# if test mode then render the test footer
{ test "$destination" = "test" } && {
render_test_footer }
cat <<EOF
</body>
</html>
EOF
}
render_html() {
#######################################
## we support the <markdown> tag inline
tmp="tmp.$RANDOM"
awk 'BEGIN { srand(); markdown=0; }
/^<markdown>/ { markdown=1; out="tmp.md" rand(); print out; next }
/^<\/markdown>/ { markdown=0; next }
{ if(markdown==1) { print $0 >out; next } else { print $0 } }
' > $tmp
# first pass marks the markdown parts and saves them separate
mds=(`find . -name 'tmp.md*'`)
{ test "${#mds}" = "0" } || {
# second pass substituted saved parts with rendered markdown
act -n "${#mds} markdown fields "
# check which markdown parser is available in PATH
command -v markdown > /dev/null
if [ "$?" = "0" ]; then parser=markdown
else command -v multimarkdown > /dev/null
if [ "$?" = "0"]; then parser=multimarkdown; fi
fi
for i in $mds; do
md=`basename $i`
newtemp="tmp.$RANDOM"
cat $tmp | awk '
/^'"$md"'/ { system("cat '"$md"' | '"$parser"'"); next }
{ print $0; }' > $newtemp
rm $tmp; tmp=$newtemp
done
}
cat $tmp
# clean up from temporary files
rm -f tmp.*
}
index() {
# render_header "<link rel=\"stylesheet\" href=\"css/blueimp-gallery.min.css\" />"
{ test -d "$1" } || { error "cannot index directory not found: $1"; return 1 }
source $SYS/index
dirs=`find "$1" -type d`
basedir=`dirname "$1"`
# setup paths for test
{ test "$destination" = "test" } && {
LINK_PREFIX="file://$1"
WEB_ROOT="file://`PWD=${SYS} pwd`/test"
notice "Test settings for indexing"
act "SYS = $SYS"
act "WEB_ROOT = $WEB_ROOT"
}
for d in ${(f)dirs}; do
dir="${d##*${basedir}}"
mkdir -p "${destination}/$dir"
render_header > "${destination}/$dir/index.html"
cat tmpl/navbar.html >> "${destination}/$dir/index.html"
pushd "${destination}/$dir"
cat <<EOF >> index.html
<div class="container-fluid">
<div class="span6">
EOF
index_dir "$d" >> index.html
# if there is a README put it besides
{ test -r "${d}/README.md" } && {
cat <<EOF >> index.html
</div>
<div class="span3">
EOF
maruku --html --html-frag -o - "${d}/README.md" >> index.html
}
cat <<EOF >> index.html
</div>
</div>
<p>&nbsp;</p>
EOF
popd
render_footer >> "${destination}/$dir/index.html"
done
}
read_meta() {
tmp=`head -n 3 | awk '
!/^#/ { next }
/title/ { printf "title=\""; for(i=3;i<=NF;i++) printf "%s ", $i; printf "\";" }
/description/ { printf "description=\""; for(i=3;i<=NF;i++) printf "%s ", $i; printf "\";" }
/keywords/ { printf "keywords=\""; for(i=3;i<=NF;i++) printf "%s ", $i; printf "\";" }
'`
eval "$tmp"
}
{ test "$1" = "source" } && { return 0 }
{ test "$1" = "test" } && {
act "Local test rendering inside test/"
source $SYS/test }
# prepare all fonts
source $SYS/fonts
# Main
mkdir -p ${destination}/css
mkdir -p ${destination}/js
cat << EOF > ${destination}/.htaccess
DirectoryIndex index index.html index.php
DefaultType text/html
EOF
act -n "Clean up all temp files ... "
temps=(`find "$destination" -type f -name 'temp-*'`)
for t in $temps; do rm -f $t; done
print "done"
# publish all .txt files as-is
# useful for robots.txt
txts=(`find views -maxdepth 1 -type f -name '*.txt'`)
for t in $txts; do
txt=`basename $t`
dst="${destination}/$txt"
act "publishing plain text: $txt"
cp $t ${destination}/$txt
done
# render all HTML views
htmls=(`find views -type f -name '*.html'`)
for src in $htmls; do
# read meta commands
cat ${src} | read_meta
# compute destination file
dst="${destination}/`basename ${src%.*}`${EXTENSION}"
render_header > $dst
# close <head> as nothing else is needed
cat <<EOF >> $dst
</head> <!-- end of <head> -->
<body>
<div class="container">
EOF
# don't forget the navbar
cat tmpl/navbar.html >> $dst
cat <<EOF >> $dst
<p>&nbsp;</p>
<article>
EOF
# render html
act -n "Html rendering: $B $dst $r"
cat $src | render_html >> $dst
cat <<EOF >> $dst
</article>
<p>&nbsp;</p>
<p>&nbsp;</p>
EOF
# includejs=(js/bootstrap.min.js)
render_footer >> $dst
act "done"
done
# render all image galleries
source $SYS/gallery
gals=(`find views -type f -name '*.gal'`)
gals+=(`find views -type f -name '*.gallery'`)
for src in $gals; do
cat ${src} | read_meta
dst="${destination}/`basename ${src%.*}`"
act -n "Gallery rendering: $B $dst $r ... "
cat $src | render_gallery > $dst
print "done"
done
# render all directory indexes
idxs=(`find views -type f -name '*.idx'`)
idxs+=(`find views -type f -name '*.index'`)
{ test ${#idxs} = 0 } || {
for idx in $idxs; do
notice "Directory index rendering: $idx"
source ${idx}
done
# copy icons only if needed
rsync -rlt "$SYS/icons" "${destination}/"
}
# copy to destination all subdirs in views/
for m in `find views -mindepth 1 -type d `; do
act -n "publishing $B $m $r ... "
rsync -r $m ${destination}/
print "done"
done
# if the whole website is a "slideshow" (set in config.zsh) then we start with
# a full screen slideshow of all uploaded photos, cycling random every time.
# galleries are supported and can be linked in menu and pages.
{ test "$WEBSITE" = "slideshow" } && {
notice "Site is configured as slideshow"
# generate a list of all images (removing duplicates)
act "Indexing all images ... "
find pub -iname '*.jpg' | sed -e 's/^pub\///g' -e 's/^.\/pub\///g' -e "s@'@@g" | sort | uniq \
| render_gallery views/index.html > ${destination}/index
}
notice "Website refreshed."
# { test "$DIR" = "." } || { sleep 10 }