custom configuration support
- custom extensions - custom filters - ignore files matching given patterns
This commit is contained in:
parent
f7affcaca7
commit
ad7a86f1c5
6
Makefile
6
Makefile
@ -7,20 +7,20 @@ all:
|
||||
@echo Compiled
|
||||
|
||||
install: all
|
||||
@echo Installing zod executables to ${PREFIX}/bin
|
||||
@echo Installing zod executable to ${PREFIX}/bin
|
||||
@mkdir -p ${PREFIX}/bin
|
||||
@cp bin/zod ${PREFIX}/bin
|
||||
@cp bin/zod_render ${PREFIX}/bin
|
||||
@echo Installing awk lib files to ${AWKLIB}
|
||||
@mkdir -p ${AWKLIB}
|
||||
@cp lib/render.awk ${AWKLIB}
|
||||
@cp lib/markdown.awk ${AWKLIB}
|
||||
@cp lib/config.awk ${AWKLIB}
|
||||
@cp lib/opt_builder.awk ${AWKLIB}
|
||||
@echo Installation Complete
|
||||
|
||||
uninstall:
|
||||
@echo Uninstalling zod executable
|
||||
@rm ${PREFIX}/bin/zod
|
||||
@rm ${PREFIX}/bin/zod_render
|
||||
@echo Uninstalling awk lib files
|
||||
@rm -rf ${AWKLIB}
|
||||
@echo Uninstallation Complete
|
||||
|
92
bin/zod.template
Normal file → Executable file
92
bin/zod.template
Normal file → Executable file
@ -13,12 +13,94 @@ _zod_error() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
_zod_config() {
|
||||
cat - "$cfg" <<!
|
||||
[parse]
|
||||
htm,html
|
||||
[parse_convert]
|
||||
md awk -f "$zod_lib/markdown.awk"
|
||||
[ignore]
|
||||
helpers.awk
|
||||
*.layout
|
||||
*.meta
|
||||
config
|
||||
!
|
||||
}
|
||||
|
||||
_zod_find_opt_builder() {
|
||||
phase="$1"
|
||||
_zod_config |
|
||||
awk -f "$zod_lib/config.awk" \
|
||||
-f "$zod_lib/opt_builder.awk" \
|
||||
-v phase="$phase"
|
||||
}
|
||||
|
||||
_zod_destination() {
|
||||
file="$1"
|
||||
# Find the target directory if one must be created
|
||||
subdir="${file%/*}"
|
||||
subdir="${subdir#$proj}"
|
||||
if [ "$subdir" ]; then
|
||||
destination="$target$subdir"
|
||||
mkdir -p "$destination"
|
||||
else
|
||||
# There is no directory to create in target,
|
||||
# i.e. file is in the root of the project
|
||||
destination="$target"
|
||||
fi
|
||||
echo $destination;
|
||||
}
|
||||
|
||||
_zod_render() {
|
||||
file="$1"
|
||||
ext="${file##*.}"
|
||||
meta="${file%.$ext}.meta"
|
||||
|
||||
set -- -f "$zod_lib/config.awk"
|
||||
set -- "$@" -f "$zod_lib/render.awk"
|
||||
[ -f "$proj/helpers.awk" ] && set -- "$@" -f "$proj/helpers.awk"
|
||||
set -- "$@" -
|
||||
[ -f "$proj/global.meta" ] && set -- "$@" "$proj/global.meta"
|
||||
[ -f "$meta" ] && set -- "$@" "$meta"
|
||||
set -- "$@" "$file"
|
||||
[ -f "$proj/main.layout" ] && set -- "$@" "$proj/main.layout"
|
||||
|
||||
page="${file##*/}"
|
||||
page="${page%.$ext}.html"
|
||||
destination=$(_zod_destination "$file")
|
||||
_zod_config | awk "$@" > "$destination/$page"
|
||||
}
|
||||
|
||||
_zod_copy() {
|
||||
file="$1"
|
||||
destination="$(_zod_destination "$file")"
|
||||
cp "$file" "$destination"
|
||||
}
|
||||
|
||||
_zod_exec() {
|
||||
phase="$@"
|
||||
set -- "$proj" -type f
|
||||
for instruction in $(_zod_find_opt_builder "$phase" "$cfg"); do
|
||||
inst=$(echo $instruction | sed 's/"//g')
|
||||
case $inst in
|
||||
or ) set -- "$@" -o;;
|
||||
not ) set -- "$@" !;;
|
||||
* ) set -- "$@" -name "$inst";;
|
||||
esac
|
||||
done
|
||||
find "$@" | while read -r file; do
|
||||
case "$phase" in
|
||||
render ) _zod_render "$file";;
|
||||
copy ) _zod_copy "$file";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
[ "$#" -ne 2 ] && { echo "usage: zod projectdir targetdir"; exit; }
|
||||
[ ! -d "$proj" ] && _zod_error "project directory does not exist"
|
||||
[ ! -d "$target" ] && _zod_error "target directory does not exist"
|
||||
|
||||
find "$proj" -type f \
|
||||
! -name "*.layout" \
|
||||
! -name "*.meta" \
|
||||
! -name "helpers.awk" \
|
||||
-exec zod_render "$zod_lib" "$proj" "$target" {} \;
|
||||
[ -f "$proj/.zod/config" ] && cfg="$proj/.zod/config"
|
||||
|
||||
_zod_exec "render"
|
||||
_zod_exec "copy"
|
||||
|
@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
# render a zodiac page
|
||||
# zod_render zodlibdir projdir targetdir md_builtin [files]
|
||||
|
||||
zod_lib="$1"
|
||||
proj="$2"
|
||||
target="$3"
|
||||
md_builtin="$4"
|
||||
f="$5"
|
||||
|
||||
# source zod sh functions
|
||||
. $zod_lib/zod_functions
|
||||
|
||||
ext=${f##*.}
|
||||
meta=${f%.$ext}.meta
|
||||
|
||||
set -- -f "$zod_lib/render.awk"
|
||||
[ -f "$proj/helpers.awk" ] && set -- "$@" -f "$proj/helpers.awk"
|
||||
set -- "$@" -v markdown_filter_cmd="$md_builtin"
|
||||
[ -f "$proj/global.meta" ] && set -- "$@" $proj/global.meta
|
||||
[ -f "$meta" ] && set -- "$@" $meta
|
||||
set -- "$@" "$f"
|
||||
|
||||
find "$proj" -type f -name "*.partial" -o -name "*.layout"
|
||||
while read -r part; do
|
||||
set -- "$@" "$part"
|
||||
done
|
||||
|
||||
page=${f##*/}
|
||||
page=${page%.$ext}.html
|
||||
__zod_destination "$proj" "$target" "$f"
|
||||
awk "$@" > "$destination/$page"
|
@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# return a list of all supported file extensions
|
||||
|
||||
zod_lib="$1"
|
||||
filter_opts="$2"
|
||||
|
||||
awk -f "$zod_lib/supported_extensions.awk" "$filter_opts"
|
@ -5,9 +5,10 @@ function load_helpers() {
|
||||
}
|
||||
|
||||
function page_title( title) {
|
||||
if ("title" in data) {
|
||||
return data["title"] " - " data["site_title"]
|
||||
if (data["title"]) {
|
||||
title = data["title"] " - " data["site_title"]
|
||||
} else {
|
||||
return data["site_title"]
|
||||
title = data["site_title"]
|
||||
}
|
||||
return title
|
||||
}
|
||||
|
@ -6,10 +6,14 @@
|
||||
<title>{{page_title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
{{>header}}
|
||||
<header>
|
||||
<h1><a href="/">{{site_title}}</a></h1>
|
||||
</header>
|
||||
<article>
|
||||
{{{yield}}}
|
||||
</article>
|
||||
{{>footer}}
|
||||
<footer>
|
||||
<p>powered by static files</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
44
lib/config.awk
Normal file
44
lib/config.awk
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# Parse zodiac config
|
||||
#
|
||||
|
||||
# Ignore comments and empty lines
|
||||
action == "config" && (NF == 0 || /^;/) {
|
||||
next
|
||||
}
|
||||
|
||||
# Get the current section
|
||||
action == "config" && (/^\[/ && match($0, /\[([[:alnum:]_]).*\]/)) {
|
||||
section = substr($0, (RSTART + 1), (RLENGTH - 2))
|
||||
next
|
||||
}
|
||||
|
||||
# Get filters in the parse section
|
||||
action == "config" && section == "parse" {
|
||||
n = split($0, exts, ",")
|
||||
for (i in exts) {
|
||||
ext = exts[i]
|
||||
gsub(/ /, "", ext)
|
||||
filter[ext] = "none"
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
# Get filters in the parse_convert section
|
||||
action == "config" && section == "parse_convert" && (NF > 1) {
|
||||
ext_list = $1
|
||||
cmd = $2
|
||||
n = split(ext_list, exts, ",")
|
||||
for (i in exts) {
|
||||
ext = exts[i]
|
||||
gsub(/ /, "", ext)
|
||||
filter[ext] = cmd
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
# Get ignore patterns
|
||||
action == "config" && section == "ignore" {
|
||||
ignore[ignore_count++] = $0
|
||||
next
|
||||
}
|
35
lib/opt_builder.awk
Normal file
35
lib/opt_builder.awk
Normal file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# Build find options
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
section = "none"
|
||||
action = "config"
|
||||
}
|
||||
|
||||
END {
|
||||
for (ext in filter) {
|
||||
exts[ext_count++] = "\"" "*." ext "\""
|
||||
}
|
||||
for (i = 0; i < length(ignore); i++) {
|
||||
instructions[inst_count++] = "not"
|
||||
instructions[inst_count++] = "\"" ignore[i] "\""
|
||||
}
|
||||
if (phase == "render") {
|
||||
instructions[inst_count++] = exts[0]
|
||||
for (i = 1; i < length(exts); i++) {
|
||||
instructions[inst_count++] = "or"
|
||||
instructions[inst_count++] = exts[i]
|
||||
}
|
||||
} else if (phase == "copy") {
|
||||
for (i = 0; i < length(exts); i++) {
|
||||
instructions[inst_count++] = "not"
|
||||
instructions[inst_count++] = exts[i]
|
||||
}
|
||||
}
|
||||
# print all instructions
|
||||
for (i = 0; i < length(instructions); i++) {
|
||||
instruction = instruction " " instructions[i]
|
||||
}
|
||||
print instruction
|
||||
}
|
@ -1,47 +1,30 @@
|
||||
# render.awk - Awk-based templating
|
||||
#
|
||||
# Render a zodiac page
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
action = "none"
|
||||
ext = "none"
|
||||
main_content_type = "_main"
|
||||
main = "_main"
|
||||
helpers_loaded = "no"
|
||||
layout = ""
|
||||
filter_cmds["htm"] = "none"
|
||||
filter_cmds["html"] = "none"
|
||||
filter_cmds["md"] = markdown_filter_cmd
|
||||
}
|
||||
|
||||
{
|
||||
split(FILENAME, parts, ".")
|
||||
ext = parts[length(parts)]
|
||||
if (ext == "config") {
|
||||
if ((FILENAME == "config") || (FILENAME == "-")) {
|
||||
action = "config"
|
||||
} else if (ext == "meta") {
|
||||
action = "meta"
|
||||
} else if (ext == "layout") {
|
||||
action = "layout"
|
||||
} else {
|
||||
# not a known extension, assuming this line
|
||||
# is from a page
|
||||
content_extension = ext
|
||||
action = "page"
|
||||
filter_ext = ext
|
||||
}
|
||||
}
|
||||
|
||||
# Process lines from config
|
||||
# Also ignore comments and empty lines
|
||||
action == "config" && (NF > 0) && (!/^;.*/) {
|
||||
split($0, filter_kv, ": ")
|
||||
split(filter_kv[1], filter_extensions, ",")
|
||||
filter_cmd = filter_kv[2]
|
||||
|
||||
for (i = 1; i <= length(filter_extensions); i++) {
|
||||
filter_cmds[filter_extensions[i]] = filter_cmd
|
||||
}
|
||||
|
||||
next
|
||||
}
|
||||
|
||||
# Process lines from meta files
|
||||
action == "meta" {
|
||||
split($0, kv, ": ")
|
||||
@ -58,14 +41,14 @@ action != "meta" && helpers_loaded == "no" && helpers == "yes" {
|
||||
|
||||
# Process lines from the page
|
||||
action == "page" {
|
||||
if (!contents[main_content_type]) {
|
||||
contents[main_content_type] = bind_data($0)
|
||||
if (!contents[main]) {
|
||||
contents[main] = bind_data($0)
|
||||
|
||||
# save the extension for this content type
|
||||
# to find the appropriate filter to render it
|
||||
content_extensions[main_content_type] = ext
|
||||
filter_exts[main] = ext
|
||||
} else {
|
||||
contents[main_content_type] = contents[main_content_type] "\n" bind_data($0)
|
||||
contents[main] = contents[main] "\n" bind_data($0)
|
||||
}
|
||||
next
|
||||
}
|
||||
@ -75,7 +58,7 @@ action == "layout" {
|
||||
|
||||
# replace yield with rendered content
|
||||
if (match($0, /{{{yield}}}/)) {
|
||||
sub(/{{{yield}}}/, render_content(main_content_type))
|
||||
sub(/{{{yield}}}/, render_content(main))
|
||||
}
|
||||
|
||||
if (layout == "") {
|
||||
@ -89,14 +72,14 @@ END {
|
||||
if (layout != "") {
|
||||
print layout
|
||||
} else {
|
||||
print render_content(main_content_type)
|
||||
print render_content(main)
|
||||
}
|
||||
}
|
||||
|
||||
function bind_data(txt, tag, key) {
|
||||
if (match(txt, /{{([^}]*)}}/)) {
|
||||
tag = substr(txt, RSTART, RLENGTH)
|
||||
match(tag, /(\w|[?]).*[^}]/)
|
||||
match(tag, /([[:alnum:]_]|[?]).*[^}]/)
|
||||
key = substr(tag, RSTART, RLENGTH)
|
||||
gsub(tag, data[key], txt)
|
||||
return bind_data(txt, data)
|
||||
@ -105,14 +88,14 @@ function bind_data(txt, tag, key) {
|
||||
}
|
||||
}
|
||||
|
||||
function render_content(type, ext_key, content_extension, filter_cmd, txt) {
|
||||
function render_content(type, ext_key, filter_ext, filter_cmd, txt) {
|
||||
ext_key = type "_ext"
|
||||
|
||||
# Get the extension of the content type
|
||||
content_extension = content_extensions[type]
|
||||
filter_ext = filter_exts[type]
|
||||
|
||||
# Get the appropriate filter command for this extension
|
||||
filter_cmd = filter_cmds[content_extension]
|
||||
filter_cmd = filter[filter_ext]
|
||||
|
||||
# Get the text of the content for the given type
|
||||
txt = contents[type]
|
||||
@ -125,6 +108,7 @@ function render_content(type, ext_key, content_extension, filter_cmd, txt) {
|
||||
}
|
||||
|
||||
function run_filter(cmd, txt, rand_date, tmpfile, rendered_txt, date_cmd, markdown_cmd, line) {
|
||||
# TODO use mktemp instead
|
||||
date_cmd = "date +%Y%m%d%H%M%S"
|
||||
date_cmd | getline rand_date
|
||||
close(date_cmd)
|
||||
|
@ -1,22 +0,0 @@
|
||||
BEGIN {
|
||||
extensions="md html"
|
||||
}
|
||||
|
||||
# Process lines from config
|
||||
# Also ignore comments and empty lines
|
||||
(NF > 0) && (!/^;.*/) {
|
||||
split($0, filter_kv, ": ")
|
||||
split(filter_kv[1], filter_extensions, ",")
|
||||
|
||||
for (i = 1; i <= length(filter_extensions); i++) {
|
||||
ext = filter_extensions[i]
|
||||
if (!match(extensions, ext)) {
|
||||
extensions = extensions " " ext
|
||||
}
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
END {
|
||||
print extensions
|
||||
}
|
Loading…
Reference in New Issue
Block a user