#!/bin/bash # Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2017 # # This file is part of webgen, # a small template engine for easy management of small websites. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 # as published by the Free Software Foundation. # # webgen 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. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this software; see the file COPYING. If not, write to # the Free Software Foundation, 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # Prefixes: # - Include # + Normal page # ~ Dynamically generated page # = Raw mode file. # # Special/Config file # Special files: # -header Is included before all [+~] pages # -end Is included after all [+~] pages # -menu-mid Is included after after menu file (if exists) on all [+~] pages. # -faq_eoh ??? # ?FAQ Will be rendered as FAQ. # ?NEWS Will be rendered as NEWS. # CONFIG: OUT=`pwd` TPLS=tpl/ HEADER=header END=end PAGE_SUFFIX='.html' DEFAULT_MENU='-menu-none' PREPROCESSOR='none' POSTPROCESSOR='none' LANGUAGE='' TEMPLATES='' # CODE: setup() { if [ -e $TPLS -o -e Makefile ] then echo 'Error: Environment already initialized.' >&2 exit 1 fi mkdir $TPLS cd $TPLS touch \#section-index touch \#menu-index touch ./-menu-none touch ./-menu-mid { echo '' echo '
' echo 'This is the webgen demo page. This page was generated by
webgen --setup.' } > ./+index { echo ' ' echo '' } > ./-end cat > ../Makefile <<'EOL' # (mostly) Universal Makefile for webgen. # Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2017 # # This file is part of webgen, # a small template engine for easy management of small websites. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 # as published by the Free Software Foundation. # # webgen 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. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this software; see the file COPYING. If not, write to # the Free Software Foundation, 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # Settings: # This is the list of languages you want to generate output for. # Use 'default' for default rendering. # Examples: 'default', 'default en de'. # Note: Files are only generated in non-default language if # there is a translation (tpl/#translate$TPL.$LANG). LANGUAGES=default # This is the webgen binary to use. # Default (using webgen in $PATH): webgen WEBGEN=webgen # Code: ifdef DESTDIR WEBGEN += --destdir $(DESTDIR) endif # Get list of all templates first: TEMPLATES=$(shell $(WEBGEN) --list) # Now calculate the list of targets. Better don't!: TARGETS = $(patsubst =%,%,$(filter =%,$(TEMPLATES))) $(foreach tpl,$(filter-out =%,$(TEMPLATES)),$(foreach lang,$(LANGUAGES),$(if $(findstring default,$(lang)),$(patsubst +%,%,$(tpl:~%=%)).html,$(if $(wildcard tpl/\#translate$(tpl).$(lang)),$(patsubst +%,%,$(tpl:~%=%)).$(lang).html)))) # Common phony targets: all: $(TARGETS) clean: rm -f $(TARGETS) new: clean all distclean: clean # Declare them as phony: .PHONY: all clean new distclean # Actual rule to run webgen and calculation of all prerequisites: .SECONDEXPANSION: $(TARGETS): $$(shell $(WEBGEN) --list-dependencies $$@) $(WEBGEN) $@ #ll EOL } list_tpls() { cd $TPLS ls -1 -- +* \~* =* 2> /dev/null } list_dependencies() { cd $TPLS case "$1" in '+'*|'~'*) _tpl=`ls -1 -- "$1" 2> /dev/null` ;; '='*) echo "$TPLS$1" return ;; *'.'*'.html') _mask=`echo "$1" | cut -d. -f1` _lang=`echo "$1" | cut -d. -f2` _tpl=`ls -1 -- ?"$_mask.$_lang" ="$_mask.$_lang".html 2> /dev/null` if [ -z "$_tpl" ] then _tpl=`ls -1 -- ?"$_mask" 2> /dev/null` fi [ "$LANGUAGE" = '' ] && LANGUAGE="$_lang" case "$_tpl" in '='*) echo "$TPLS$_tpl" return; ;; esac ;; *'.html') _mask=`echo "$1" | cut -d. -f1` _tpl=`ls -1 -- ?"$_mask" ="$_mask".html 2> /dev/null` case "$_tpl" in '='*) echo "$TPLS$_tpl" return; ;; esac ;; *) _tpl="=$1" ;; esac if [ "$_tpl" = '' ] then echo "Template not found: $1" >&2 exit 1 fi MENU=$(grep --no-filename -- "^$_tpl[^a-zA-Z0-9-]" '#menu-index'* | sed 's/^[^ \t]*[ \t]*[ \t]//'); { printf "%s\n" $_tpl -header -end $MENU if [ "$LANGUAGE" != '' ] then ls -1 -- "#translate" "#translate.$LANGUAGE" "#translate$_tpl" "#translate$_tpl.$LANGUAGE" 2> /dev/null fi ls -1 -- -menu-mid \#menu-index* \#section-index* 2> /dev/null if [ "$CLEANTPLNAME" = 'FAQ' ] then find FAQ/ -type d -not -wholename \*CVS\* | sed 's#^FAQ/##;' | grep -v ^$ find FAQ/ -type f -not -wholename \*CVS\* -and -name \*.faq fi if [ "$CLEANTPLNAME" = 'NEWS' ] then ls -1 -- NEWS/*.news 2> /dev/null fi } | sed 's#^#tpl/#' } show_help() { echo "Usage: webgen [--preprocessor PP] [--postprocessor OP] [--language LANG] [{+|~|=}][TPL]" echo " or: webgen [--language LANG] --list-dependencies [{+|~|=}]TPL" echo " or: webgen --setup" echo " or: webgen --list" echo " or: webgen --help" } while [ ! -z "$1" ] do case "$1" in '--preprocessor') PREPROCESSOR="$2" shift ;; '--postprocessor') POSTPROCESSOR="$2" shift ;; '--language') if [ "$2" = 'default' ] then LANGUAGE='' else LANGUAGE="$2" fi shift ;; '--destdir') mkdir -p "$2" pushd "$2" > /dev/null OUT=`pwd` popd > /dev/null shift; ;; '--setup') setup exit 0 ;; '--list') list_tpls exit 0 ;; '--list-dependencies') list_dependencies $2 exit 0 ;; '--help') show_help exit 0 ;; '--'*) echo "Error: Unknown option: $1" >&2 exit 1 ;; *) TEMPLATES="$TEMPLATES $1" ;; esac shift done cd $TPLS cat_file() { _file="$1" if [ -n "$LANGUAGE" -a -r "$_file.$LANGUAGE" ] then _file="$_file.$LANGUAGE" fi case "$PREPROCESSOR" in none) cat -- "$_file" ;; cpp) cpp -P -o - -D__TEMPLATE__="\"$_tpl\"" -D__TEMPLATE_CLEAN__="\"$CLEANTPLNAME\"" -D __OUTPUT_FILE__="\"$OF\"" ./"$_file" ;; *) echo "Error: Unknown preprocessor: $PREPROCESSOR" >&2 ;; esac } postprocessor() { _of="$1" case "$POSTPROCESSOR" in none) cat - > "$_of" ;; xmllint) xmllint -o "$_of" --format - ;; xmllint-html) xmllint -o "$_of" --format --html - ;; *) echo "Error: Unknown postprocessor: $POSTPROCESSOR" >&2 ;; esac } gen_news() { if [ ! -d NEWS/ ] then return 1 fi ls -1t NEWS/*.news | while read line do title=`echo "$line" | sed 's/.news$//; s#^NEWS/##;'` e=`echo "$title" | sed 's/[^a-zA-Z0-9]/_/g'` _t=`stat --format='%Z %U' "$line"` ctime=`echo "$_t" | cut -d' ' -f1` user=`echo "$_t" | cut -d' ' -f2` ctime_lr=`date --date "1970-01-01 00:00:00 UTC + ${ctime}sec"` echo "
$ctime_lr by $user
" echo "" sed 's#^$#
#' < "$line" echo "
" done } gen_faq() { find FAQ/ -type d -not -wholename \*CVS\* | sed 's#^FAQ/##;' | grep -v ^$ | sort > "$OF.FAQCATS" find FAQ/ -type f -not -wholename \*CVS\* -and -name \*.faq | sed 's#^FAQ/##; s#\.faq$##' | sort > "$OF.FAQINDEX" echo echo "" sed 's#^$#
#' < "FAQ/$cat/$q.faq" echo "
" done done < "$OF.FAQCATS" echo } proc_page() { _tpl="$1" CLEANTPLNAME=$(echo "$_tpl" | sed 's/^[\-\+\~]//') if [ "$LANGUAGE" = '' ] then LANGUAGE_SUFFIX='' TRANSLATE_REGEX='s/(translate:\(.*\):)/\1/' else LANGUAGE_SUFFIX=".$LANGUAGE" TRANSLATE_REGEX=`grep "^$LANGUAGE[[:space:]]" "#translate" "#translate$LANGUAGE_SUFFIX" "#translate$_tpl" "#translate$_tpl$LANGUAGE_SUFFIX" 2> /dev/null | sed 's/^[^\t]*\t\t*\([^\t]*\)\t\t*\(.*\)$/s|(translate:\1:)|\2|g;/'`'s/(translate:\(.*\):)/\1/' fi OF="$OUT"/"$CLEANTPLNAME""$LANGUAGE_SUFFIX""$PAGE_SUFFIX" echo "Compiling $CLEANTPLNAME ($LANGUAGE) -> $OF" SECTIONS=`for _sec in $(grep --no-filename -- "^$_tpl[^a-zA-Z0-9-]" '#section-index'* | sed 's/^[^ \t]*[ \t]*[ \t]//'); do O=''; for i in $(tr . ' ' <<<"$_sec"); do O="$O.$i"; echo $O; done; done`' .ALL' # echo "Sections: $SECTIONS" SECTIONS_REGEX=$(for _sec in $SECTIONS; do echo "s/(section==$_sec:\([^)]*\):)/\1/g;"; done; echo "s/(section==.*:.*:)//g") MENU=$(grep --no-filename -- "^$_tpl[^a-zA-Z0-9-]" '#menu-index'* | sed 's/^[^ \t]*[ \t]*[ \t]//'); [ "$MENU" = '' ] && MENU="$DEFAULT_MENU" { cat_file -$HEADER [ -n "$MENU" ] && cat_file "$MENU" [ -e -menu-mid ] && cat_file -menu-mid cat_file $_tpl [ "$CLEANTPLNAME" = 'FAQ' ] && gen_faq [ "$CLEANTPLNAME" = 'NEWS' ] && gen_news cat_file -$END } | \ sed "$SECTIONS_REGEX" | \ sed "$TRANSLATE_REGEX" | \ sed 's#href="[+~]\([^"\#(]*\)(same-language)\(\#*[^"]*\)"#href="\1'"$LANGUAGE_SUFFIX""$PAGE_SUFFIX"'\2"#g; s#href="(same-page)\([^"\#(]*\)\(\#*[^"]*\)"#href="'"$CLEANTPLNAME"'\1'"$PAGE_SUFFIX"'\2"#g; s#href="[+~]\([^"\#]*\)\(\#*[^"]*\)"#href="\1'"$PAGE_SUFFIX"'\2"#g; s#href="=\([^"]*\)"#href="\1"#g' | postprocessor "$OF" } proc_raw() { _tpl="$1" CLEANTPLNAME=$(echo "$_tpl" | sed 's/^=//') OF="$OUT"/"$CLEANTPLNAME" echo "Compiling $CLEANTPLNAME -> $OF" cat_file "$_tpl" | postprocessor "$OF" } proc() { _mode="$1" shift; _old_lang="$LANGUAGE" for x in "$@" do if [ -f "$x" ] then x=`echo "$x" | sed 's#^\./##'` if [ "$_mode" != 'raw' ] then case "$x" in *.*) LANGUAGE=`echo "$x" | cut -d. -f2` x=`echo "$x" | cut -d. -f1` ;; esac fi proc_$_mode "$x" LANGUAGE="$_old_lang" fi done } if [ -z "$TEMPLATES" ] then TEMPLATES="+ ~ =" fi for i in $TEMPLATES do case "$i" in '+'|'~') proc page ./"$i"* ;; '=') proc raw ./"$i"* ;; '+'*|'~'*) proc page ./$i ;; '='*) proc raw ./$i ;; *'.html') _mask=`echo "$i" | sed 's/\.html$//'` proc page ./[\+\~]"$_mask" proc raw ./[=]"$_mask".html ;; *) proc page ./[\+\~]$i proc raw ./[=]$i ;; esac done exit 0; #ll