Files
kewt/kewt.sh

322 lines
9.3 KiB
Bash
Executable File

#!/bin/sh
die() {
echo "Error: $1" >&2
exit 1
}
script_dir=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd)
awk_dir="$script_dir/awk"
KEWT_TMPDIR=$(mktemp -d "/tmp/kewt_run.XXXXXX")
trap 'rm -rf "$KEWT_TMPDIR"' EXIT
trap 'exit 0' HUP INT TERM
. "$script_dir/lib/config.sh"
. "$script_dir/lib/commands.sh"
. "$script_dir/lib/generator.sh"
. "$script_dir/lib/builder.sh"
src=""
out=""
new_mode="false"
new_title=""
post_mode="false"
post_title=""
positional_count=0
watch_mode="false"
serve_mode="false"
while [ $# -gt 0 ]; do
case "$1" in
--help|-h)
usage
exit 0
;;
--new)
new_mode="true"
if [ $# -gt 1 ] && [ "${2#-}" = "$2" ]; then
new_title="$2"
shift
fi
;;
--version|-v)
echo "kewt version git"
exit 0
;;
--dump-zsh-completions)
cat <<'EOFCOMPS'
#compdef kewt
_kewt() {
local -a args
args=(
'--help[Show help message]'
'(-h)--help[Show help message]'
'(-)--new[Create a new site directory]'
'(-)--update[Update site.conf and template.html with latest defaults]'
'(-)--post[Create a new empty post file in the configured posts_dir]'
'(-)--generate-template[Generate a new template file]'
'(-v --version)'{-v,--version}'[Show version information]'
'--from[Source directory]:directory:_directories'
'--to[Output directory]:directory:_directories'
'(-w --watch)'{-w,--watch}'[Watch for file changes and rebuild automatically]'
'(-s --serve)'{-s,--serve}'[Start a local HTTP server after building]::port:'
)
_arguments -S -C $args '*: :_directories'
}
_kewt "$@"
EOFCOMPS
exit 0
;;
--post)
post_mode="true"
if [ $# -gt 1 ] && [ "${2#-}" = "$2" ]; then
post_title="$2"
shift
fi
;;
--generate-template)
generate_template_path="template.html"
if [ $# -gt 1 ] && [ "${2#-}" = "$2" ]; then
generate_template_path="$2"
shift
fi
generate_template "$generate_template_path"
;;
--update)
update_dir="."
if [ $# -gt 1 ] && [ "${2#-}" = "$2" ]; then
update_dir="$2"
shift
fi
update_site "$update_dir"
;;
--from)
[ $# -lt 2 ] && die "--from requires a value."
src="$2"
shift
;;
--to)
[ $# -lt 2 ] && die "--to requires a value."
out="$2"
shift
;;
--watch|-w)
watch_mode="true"
;;
--serve|-s)
serve_mode="true"
if [ $# -ge 2 ] && echo "$2" | grep -qE '^[0-9]+$'; then
serve_port="$2"
shift
fi
;;
--*)
die "Unknown option: $1"
;;
*)
positional_count=$((positional_count + 1))
if [ "$positional_count" -eq 1 ]; then
if [ -z "$src" ]; then src="$1"; else die "Source already set (use either positional or --from)."; fi
elif [ "$positional_count" -eq 2 ]; then
if [ -z "$out" ]; then out="$1"; else die "Output already set (use either positional or --to)."; fi
else
die "Too many positional arguments."
fi
;;
esac
shift
done
[ "$new_mode" = "true" ] && create_new_site "$new_title"
if [ -z "$src" ]; then
if [ "$post_mode" = "true" ] && [ -f "./site.conf" ]; then
src="."
else
src="site"
fi
fi
[ -z "$out" ] && out="out"
src="${src%/}"
out="${out%/}"
if [ ! -d "$src" ]; then
if [ "$src" = "site" ]; then
usage
exit 1
else
die "Source directory '$src' does not exist."
fi
fi
IGNORE_ARGS="-name '.kewtignore' -o -path '$src/.*'"
if [ -f "$src/.kewtignore" ]; then
while IFS= read -r line || [ -n "$line" ]; do
case "$line" in
''|'#'*) continue ;;
esac
pattern=$(echo "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
[ -z "$pattern" ] && continue
pattern_clean="${pattern#/}"
pattern_clean="${pattern_clean%/}"
if echo "$pattern" | grep -q "/"; then
IGNORE_ARGS="$IGNORE_ARGS -o -path '$src/$pattern_clean' -o -path '$src/$pattern_clean/*'"
else
IGNORE_ARGS="$IGNORE_ARGS -o -name '$pattern_clean'"
fi
done < "$src/.kewtignore"
fi
find "$src" -name .kewtignore > "$KEWT_TMPDIR/kewt_ignore"
while read -r ki; do
d="${ki%/.kewtignore}"
if [ "$d" != "$src" ] && [ "$d" != "." ]; then
IGNORE_ARGS="$IGNORE_ARGS -o -path '$d' -o -path '$d/*'"
fi
done < "$KEWT_TMPDIR/kewt_ignore"
rm -f "$KEWT_TMPDIR/kewt_ignore"
HIDE_ARGS="-name '.kewtignore' -o -name '.kewthide' -o -name '.kewtpreserve' -o -path '$src/.*'"
if [ -f "$src/.kewthide" ]; then
while IFS= read -r line || [ -n "$line" ]; do
case "$line" in
''|'#'*) continue ;;
esac
pattern=$(echo "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
[ -z "$pattern" ] && continue
pattern_clean="${pattern#/}"
pattern_clean="${pattern_clean%/}"
if echo "$pattern" | grep -q "/"; then
HIDE_ARGS="$HIDE_ARGS -o -path '$src/$pattern_clean' -o -path '$src/$pattern_clean/*'"
else
HIDE_ARGS="$HIDE_ARGS -o -name '$pattern_clean'"
fi
done < "$src/.kewthide"
fi
find "$src" -name .kewthide > "$KEWT_TMPDIR/kewt_hide"
while read -r kh; do
d="${kh%/.kewthide}"
if [ "$d" != "$src" ] && [ "$d" != "." ]; then
HIDE_ARGS="$HIDE_ARGS -o -path '$d' -o -path '$d/*'"
fi
done < "$KEWT_TMPDIR/kewt_hide"
rm -f "$KEWT_TMPDIR/kewt_hide"
PRESERVE_ARGS="-false"
if [ -f "$src/.kewtpreserve" ]; then
while IFS= read -r line || [ -n "$line" ]; do
case "$line" in
''|'#'*) continue ;;
esac
pattern=$(echo "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
[ -z "$pattern" ] && continue
pattern_clean="${pattern#/}"
pattern_clean="${pattern_clean%/}"
if echo "$pattern" | grep -q "/"; then
PRESERVE_ARGS="$PRESERVE_ARGS -o -path '$src/$pattern_clean' -o -path '$src/$pattern_clean/*'"
else
PRESERVE_ARGS="$PRESERVE_ARGS -o -name '$pattern_clean'"
fi
done < "$src/.kewtpreserve"
fi
find "$src" -name .kewtpreserve > "$KEWT_TMPDIR/kewt_preserve"
while read -r kp; do
d="${kp%/.kewtpreserve}"
if [ "$d" != "$src" ] && [ "$d" != "." ]; then
PRESERVE_ARGS="$PRESERVE_ARGS -o -path '$d' -o -path '$d/*'"
fi
done < "$KEWT_TMPDIR/kewt_preserve"
rm -f "$KEWT_TMPDIR/kewt_preserve"
load_config "./site.conf"
load_config "$src/site.conf"
if [ -n "$posts_dir" ]; then
HIDE_ARGS="$HIDE_ARGS -o -path '$src/$posts_dir/*'"
fi
[ "$post_mode" = "true" ] && create_new_post "$src" "$post_title"
asset_version=""
if [ "$versioning" = "true" ]; then
asset_version="?v=$(date +%s)"
fi
template="$src/template.html"
[ -f "$template" ] || template="./template.html"
if [ ! -f "$template" ]; then
template="$KEWT_TMPDIR/default_template.html"
printf '%s\n' "$DEFAULT_TMPL" > "$template"
fi
[ -d "$out" ] && rm -rf "$out"
mkdir -p "$out"
nav=$(generate_nav "$src")
extra_links=$(nav_links_html)
if [ -n "$extra_links" ]; then
nav="$nav
$extra_links"
fi
if [ -n "$nav_extra" ]; then
nav="$nav
$nav_extra"
fi
build_site
if [ "$serve_mode" = "true" ]; then
port="${serve_port:-8000}"
if command -v python3 >/dev/null 2>&1; then
python3 -m http.server "$port" -d "$out" >/dev/null 2>&1 &
server_pid=$!
echo "Serving '$out' on http://localhost:$port (python3)"
elif command -v busybox >/dev/null 2>&1; then
busybox httpd -f -p "$port" -h "$out" >/dev/null 2>&1 &
server_pid=$!
echo "Serving '$out' on http://localhost:$port (busybox)"
else
die "Neither python3 nor busybox httpd is available to serve."
fi
trap 'kill $server_pid 2>/dev/null; rm -rf "$KEWT_TMPDIR"' EXIT
trap 'kill $server_pid 2>/dev/null; exit 0' HUP INT TERM
fi
if [ "$watch_mode" = "true" ]; then
echo "Watching for changes in '$src'..."
touch "$KEWT_TMPDIR/watch_mark"
while true; do
sleep 1
changed="$(find "$src" -type f -newer "$KEWT_TMPDIR/watch_mark" 2>/dev/null | head -n 1)"
[ -z "$changed" ] && [ -f "site.conf" ] && [ "site.conf" -nt "$KEWT_TMPDIR/watch_mark" ] && changed="site.conf"
[ -z "$changed" ] && [ -f "$src/site.conf" ] && [ "$src/site.conf" -nt "$KEWT_TMPDIR/watch_mark" ] && changed="$src/site.conf"
[ -z "$changed" ] && [ -f "$template" ] && [ "$template" -nt "$KEWT_TMPDIR/watch_mark" ] && changed="$template"
[ -z "$changed" ] && [ -d "$script_dir/styles" ] && changed="$(find "$script_dir/styles" -type f -newer "$KEWT_TMPDIR/watch_mark" 2>/dev/null | head -n 1)"
if [ -n "$changed" ]; then
echo ""
echo "Change detected, rebuilding..."
build_site
touch "$KEWT_TMPDIR/watch_mark"
fi
done
elif [ "$serve_mode" = "true" ]; then
wait "$server_pid"
fi