feat/whatever: cleanup

This commit is contained in:
2026-05-05 19:59:44 +02:00
parent 105dce7d40
commit 206d9a650d
6 changed files with 330 additions and 343 deletions

176
kewt.sh
View File

@@ -13,9 +13,11 @@ trap 'rm -rf "$KEWT_TMPDIR"' EXIT
trap 'exit 0' HUP INT TERM
. "$script_dir/lib/config.sh"
. "$script_dir/lib/metadata.sh"
. "$script_dir/lib/commands.sh"
. "$script_dir/lib/generator.sh"
. "$script_dir/lib/builder.sh"
. "$script_dir/lib/runtime.sh"
src=""
out=""
@@ -27,6 +29,7 @@ post_title=""
positional_count=0
watch_mode="false"
serve_mode="false"
serve_port=""
while [ $# -gt 0 ]; do
case "$1" in
@@ -129,9 +132,17 @@ EOFCOMPS
*)
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
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
if [ -z "$out" ]; then
out="$1"
else
die "Output already set (use either positional or --to)."
fi
else
die "Too many positional arguments."
fi
@@ -158,138 +169,25 @@ if [ ! -d "$src" ]; then
if [ "$src" = "site" ]; then
usage
exit 1
else
die "Source directory '$src' does not exist."
fi
die "Source directory '$src' does not exist."
fi
IGNORE_ARGS="-name '.kewtignore' -o -path '$src/.*'"
BASE_IGNORE_ARGS=$(build_rule_args "$src" ".kewtignore" "-name '.kewtignore' -o -path '$src/.*'")
BASE_HIDE_ARGS=$(build_rule_args "$src" ".kewthide" "-name '.kewtignore' -o -name '.kewthide' -o -name '.kewtpreserve' -o -path '$src/.*'")
PRESERVE_ARGS=$(build_rule_args "$src" ".kewtpreserve" "-false")
IGNORE_ARGS="$BASE_IGNORE_ARGS"
HIDE_ARGS="$BASE_HIDE_ARGS"
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
refresh_build_context
[ "$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
if [ "$clean_mode" = "true" ]; then
[ -d "$out" ] && rm -rf "$out"
fi
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
@@ -315,45 +213,17 @@ if [ "$watch_mode" = "true" ]; then
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)"
changed=$(watch_for_changes "$KEWT_TMPDIR/watch_mark")
if [ -n "$changed" ]; then
echo ""
echo "Change detected, rebuilding..."
if [ "$clean_mode" = "true" ]; then
find "$out" -mindepth 1 -delete 2>/dev/null
fi
load_config "./site.conf"
load_config "$src/site.conf"
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
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
refresh_build_context
build_site
touch "$KEWT_TMPDIR/watch_mark"
fi

View File

@@ -12,6 +12,21 @@ needs_rebuild() {
return 1
}
write_content_warning_outputs() {
_source_file="$1"
_content_out_file="$2"
_content_rel_url="$3"
_target_url="$4"
_landing_out_file="$5"
_is_home="$6"
is_cw_content_page="true"
render_markdown "$_source_file" "$_is_home" "$_target_url" > "$_content_out_file"
is_cw_content_page="false"
generate_content_warning_page "$fm_title" "$fm_content_warning" "$_content_rel_url" "$_target_url" "$_landing_out_file" "false"
}
build_site() {
echo "Building site from '$src' to '$out'..."
@@ -45,7 +60,7 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
if [ "$has_custom_index" = "false" ] || [ "$has_list" = "true" ]; then
is_posts_dir="false"
if [ -n "$posts_dir" ] && { [ "$rel_dir" = "$posts_dir" ] || [ "./$rel_dir" = "$posts_dir" ]; }; then
if is_posts_directory_rel "$rel_dir"; then
is_posts_dir="true"
fi
if [ "$single_file_index" = "true" ] && [ "$is_posts_dir" = "false" ] && [ "$has_list" = "false" ]; then
@@ -61,12 +76,7 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
content_out_file="$out_dir/content.html"
content_rel_url="/$rel_dir/content.html"
[ "$rel_dir" = "." ] && content_rel_url="/content.html"
is_cw_content_page="true"
render_markdown "$md_file" "$is_home" "$target_url" > "$content_out_file"
is_cw_content_page="false"
generate_content_warning_page "$fm_title" "$fm_content_warning" "$content_rel_url" "$target_url" "$out_dir/index.html" "false"
write_content_warning_outputs "$md_file" "$content_out_file" "$content_rel_url" "$target_url" "$out_dir/index.html" "$is_home"
else
render_markdown "$md_file" "$is_home" "$target_url" > "$out_dir/index.html"
fi
@@ -89,7 +99,7 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
sort_args=""
# If this is the posts dir reverse
if [ "$rel_dir" = "$posts_dir" ] || [ "./$rel_dir" = "$posts_dir" ]; then
if is_posts_directory_rel "$rel_dir"; then
sort_args="-r"
fi
@@ -105,73 +115,35 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
echo "${name}|- [${name}/](${name}/index.html)" >> "$temp_entries"
elif [ "${entry%.md}" != "$entry" ]; then
label="${name%.md}"
# Parse frontmatter for date/title/draft
parse_frontmatter "$entry"
set_post_metadata "$entry" ""
[ "$fm_draft" = "true" ] && continue
# Try to get first heading
post_h="$fm_title"
if [ -z "$post_h" ]; then
post_h=$(grep -m 1 '^# ' "$entry" | sed 's/^# *//')
if [ -n "$post_h" ]; then
post_h=$(echo "$post_h" | sed -e 's/\[//g' -e 's/\]//g' -e 's/!//g' -e 's/\*//g' -e 's/_//g' -e 's/`//g' -e 's/([^)]*)//g' | sed 's/\\//g')
fi
fi
post_h="$post_heading"
is_post_entry="false"
if [ "$rel_dir" = "$posts_dir" ] || [ "./$rel_dir" = "$posts_dir" ]; then
if is_posts_directory_rel "$rel_dir"; then
is_post_entry="true"
fi
if [ -n "$post_h" ]; then
if [ "$is_post_entry" = "true" ]; then
# Use frontmatter date if available, else parse from filename
if [ -n "$fm_date" ]; then
p_date=$(echo "$fm_date" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
p_time=""
if echo "$fm_date" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?[0-9]\{2\}[:\-][0-9]\{2\}'; then
p_time=$(echo "$fm_date" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
if [ -n "$post_time" ]; then
label="$post_h - $post_date $post_time"
else
p_date=$(echo "${name%.md}" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
p_time="00:00"
if echo "${name%.md}" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}[:\-][0-9]\{2\}'; then
p_time=$(echo "${name%.md}" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
fi
if [ -n "$p_time" ]; then
label="$post_h - $p_date $p_time"
else
label="$post_h - $p_date"
label="$post_h - $post_date"
fi
else
label="$post_h"
fi
elif [ "$is_post_entry" = "true" ]; then
# No heading; use date
if [ -n "$fm_date" ]; then
p_date=$(echo "$fm_date" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
p_time=""
if echo "$fm_date" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?[0-9]\{2\}[:\-][0-9]\{2\}'; then
p_time=$(echo "$fm_date" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
if [ -n "$p_time" ]; then
label="$p_date $p_time"
else
label="$p_date"
fi
if [ -n "$post_time" ]; then
label="$post_date $post_time"
else
p_date=$(echo "${name%.md}" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
p_time="00:00"
if echo "${name%.md}" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}[:\-][0-9]\{2\}'; then
p_time=$(echo "${name%.md}" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
label="$p_date $p_time"
label="$post_date"
fi
fi
if [ "$is_post_entry" = "true" ]; then
sort_key="${p_date} ${p_time}"
sort_key="${post_date} ${post_time}"
else
sort_key="$name"
fi
@@ -319,12 +291,7 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type d -print" | sort | while
content_out_file="$out_dir/content.html"
content_rel_url="/$rel_dir/content.html"
[ "$rel_dir" = "." ] && content_rel_url="/content.html"
is_cw_content_page="true"
render_markdown "$temp_index" "$is_home" "$target_url" > "$content_out_file"
is_cw_content_page="false"
generate_content_warning_page "$fm_title" "$fm_content_warning" "$content_rel_url" "$target_url" "$out_dir/index.html" "false"
write_content_warning_outputs "$temp_index" "$content_out_file" "$content_rel_url" "$target_url" "$out_dir/index.html" "$is_home"
else
render_markdown "$temp_index" "$is_home" "$target_url" > "$out_dir/index.html"
fi
@@ -373,7 +340,7 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type f -print" | sort | while
fi
is_posts_dir_2="false"
if [ -n "$posts_dir" ] && { [ "$dir_rel" = "$posts_dir" ] || [ "./$dir_rel" = "$posts_dir" ]; }; then
if is_posts_directory_rel "$dir_rel"; then
is_posts_dir_2="true"
fi
@@ -395,12 +362,7 @@ eval "find \"$src\" \( $IGNORE_ARGS \) -prune -o -type f -print" | sort | while
content_out_file="$out/${rel_path%.md}-content.html"
content_rel_url="/${rel_path%.md}-content.html"
orig_rel_url="/${rel_path%.md}.html"
is_cw_content_page="true"
render_markdown "$file" "$is_home" "$orig_rel_url" > "$content_out_file"
is_cw_content_page="false"
generate_content_warning_page "$fm_title" "$fm_content_warning" "$content_rel_url" "$orig_rel_url" "$out_file" "false"
write_content_warning_outputs "$file" "$content_out_file" "$content_rel_url" "$orig_rel_url" "$out_file" "$is_home"
else
render_markdown "$file" "$is_home" > "$out_file"
fi
@@ -466,61 +428,20 @@ if [ "$generate_feed" = "true" ] && [ -n "$base_url" ]; then
find "$src" -type f -name '*.md' -path "*${posts_dir:-__no_posts__}*" -print | while IFS= read -r post_file; do
post_basename=$(basename "$post_file" .md)
# Parse frontmatter to get date
parse_frontmatter "$post_file"
[ "$fm_draft" = "true" ] && continue
if [ -n "$fm_date" ]; then
post_date=$(echo "$fm_date" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
post_time="00:00"
if echo "$fm_date" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?[0-9]\{2\}[:\-][0-9]\{2\}'; then
post_time=$(echo "$fm_date" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
else
post_date=$(echo "$post_basename" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
post_time="00:00"
if echo "$post_basename" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}[:\-][0-9]\{2\}'; then
post_time=$(echo "$post_basename" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
fi
set_post_datetime "$fm_date" "$post_basename"
echo "${post_date} ${post_time}|${post_file}" >> "$temp_feed_files"
done
LC_ALL=C sort -r "$temp_feed_files" | cut -d'|' -f2- | while IFS= read -r post_file; do
post_basename=$(basename "$post_file" .md)
# Parse frontmatter
parse_frontmatter "$post_file"
[ "$fm_draft" = "true" ] && continue
# Use frontmatter date, fallback to filename
if [ -n "$fm_date" ]; then
post_date=$(echo "$fm_date" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
post_time="00:00"
if echo "$fm_date" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?[0-9]\{2\}[:\-][0-9]\{2\}'; then
post_time=$(echo "$fm_date" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
else
post_date=$(echo "$post_basename" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
post_time="00:00"
if echo "$post_basename" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}[:\-][0-9]\{2\}'; then
post_time=$(echo "$post_basename" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
set_post_metadata "$post_file" "Post"
if [ -z "$post_heading" ] && [ -n "$post_slug" ] && ! echo "$post_slug" | grep -q '^[0-9]\+$'; then
post_heading=$(echo "$post_slug" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)}1')
fi
post_slug=$(echo "$post_basename" | sed -e 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}[:\-][0-9]\{2\}//' -e 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}//' -e 's/^[_\-]//')
post_heading="$fm_title"
if [ -z "$post_heading" ]; then
post_heading=$(grep -m 1 '^# ' "$post_file" | sed 's/^# *//')
fi
if [ -z "$post_heading" ]; then
if [ -n "$post_slug" ] && ! echo "$post_slug" | grep -q '^[0-9]\+$'; then
post_heading=$(echo "$post_slug" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)}1')
else
post_heading="Post"
fi
fi
post_heading=$(echo "$post_heading" | sed -e 's/\[//g' -e 's/\]//g' -e 's/!//g' -e 's/\*//g' -e 's/_//g' -e 's/`//g' -e 's/([^)]*)//g' | sed 's/\\//g')
feed_post_title="$post_heading - $post_date $post_time"
rel_path="${post_file#"$src"}"
@@ -607,21 +528,8 @@ if [ "$generate_search" = "true" ] || [ "$generate_tags" = "true" ]; then
parse_frontmatter "$md_file"
[ "$fm_draft" = "true" ] && continue
md_heading="$fm_title"
if [ -z "$md_heading" ]; then
md_heading=$(grep -m 1 '^# ' "$md_file" | sed 's/^# *//; s/ *$//')
if [ -n "$md_heading" ]; then
md_heading=$(echo "$md_heading" | sed -e 's/\[//g' -e 's/\]//g' -e 's/!//g' -e 's/\*//g' -e 's/_//g' -e 's/`//g' -e 's/([^)]*)//g' | sed 's/\\//g')
fi
fi
if [ -z "$md_heading" ]; then
basename_no_ext=$(basename "$md_file" .md)
if [ "$basename_no_ext" != "index" ] && [ "$basename_no_ext" != "404_gen" ]; then
md_heading=$(echo "$basename_no_ext" | awk '{print toupper(substr($0,1,1)) substr($0,2)}')
else
md_heading="$title - Page"
fi
fi
markdown_title_from_file "$md_file" "$title - Page"
md_heading="$markdown_title"
if [ "$generate_search" = "true" ]; then
if [ -z "$fm_content_warning" ] || [ "$include_cw_pages_in_search" = "true" ]; then

View File

@@ -59,42 +59,43 @@ DEFAULT_TMPL='<!doctype html>
</body>
</html>'
title="kewt"
style="kewt"
lang="en"
draft_by_default="false"
footer="made with <a href=\"https://kewt.krzak.org\">kewt</a>"
dir_indexes="true"
single_file_index="true"
flatten="false"
order=""
home_name="Home"
show_home_in_nav="true"
nav_links=""
nav_extra=""
footer="made with <a href=\"https://kewt.krzak.org\">kewt</a>"
logo=""
display_logo="false"
display_title="true"
logo_as_favicon="true"
favicon=""
generate_page_title="true"
error_page="not_found.html"
versioning="false"
enable_header_links="true"
base_url=""
generate_feed="false"
feed_file="rss.xml"
posts_dir=""
posts_per_page="12"
custom_admonitions=""
cw_hide_url="true"
generate_tags="false"
tags_dir="tags"
generate_search="false"
search_in_footer="false"
search_in_header="false"
include_cw_pages_in_search="false"
reset_config() {
title="kewt"
style="kewt"
lang="en"
draft_by_default="false"
dir_indexes="true"
single_file_index="true"
flatten="false"
order=""
home_name="Home"
show_home_in_nav="true"
nav_links=""
nav_extra=""
footer="made with <a href=\"https://kewt.krzak.org\">kewt</a>"
logo=""
display_logo="false"
display_title="true"
logo_as_favicon="true"
favicon=""
generate_page_title="true"
error_page="not_found.html"
versioning="false"
enable_header_links="true"
base_url=""
generate_feed="false"
feed_file="rss.xml"
posts_dir=""
posts_per_page="12"
custom_admonitions=""
cw_hide_url="true"
generate_tags="false"
tags_dir="tags"
generate_search="false"
search_in_footer="false"
search_in_header="false"
include_cw_pages_in_search="false"
}
load_config() {
[ -f "$1" ] || return
@@ -160,3 +161,5 @@ load_config() {
esac
done < "$1"
}
reset_config

View File

@@ -23,29 +23,6 @@ escape_html_attr() {
-e 's/</\&lt;/g' \
-e 's/>/\&gt;/g'
}
parse_frontmatter() {
_fm_file="$1"
_fm_out="$KEWT_TMPDIR/fm_vals.txt"
: > "$_fm_out"
awk -v fm_out="$_fm_out" -f "$awk_dir/frontmatter.awk" "$_fm_file" > /dev/null
fm_title=""
fm_date=""
fm_draft=""
fm_description=""
fm_content_warning=""
fm_tags=""
while IFS='=' read -r _fk _fv; do
case "$_fk" in
title) fm_title="$_fv" ;;
date) fm_date="$_fv" ;;
draft) fm_draft="$_fv" ;;
description) fm_description="$_fv" ;;
content_warning) fm_content_warning="$_fv" ;;
tags) fm_tags="$_fv" ;;
esac
done < "$_fm_out"
rm -f "$_fm_out"
}
nav_links_html() {
[ -n "$nav_links" ] || return
@@ -233,9 +210,9 @@ render_markdown() {
if [ "$is_home" = "true" ] && [ -n "$home_name" ]; then
page_title="$home_name - $title"
else
first_heading=$(grep -m 1 '^# ' "$file" | sed 's/^# *//; s/ *$//')
first_heading=$(first_heading_from_markdown "$file")
if [ -n "$first_heading" ]; then
first_heading=$(echo "$first_heading" | sed -e 's/\[//g' -e 's/\]//g' -e 's/!//g' -e 's/\*//g' -e 's/_//g' -e 's/`//g' -e 's/([^)]*)//g' | sed 's/\\//g')
first_heading=$(strip_markdown_text "$first_heading")
page_title="$first_heading - $title"
else
basename_no_ext=$(basename "$file" .md)

98
lib/metadata.sh Normal file
View File

@@ -0,0 +1,98 @@
parse_frontmatter() {
_fm_file="$1"
_fm_out="$KEWT_TMPDIR/fm_vals.txt"
: > "$_fm_out"
awk -v fm_out="$_fm_out" -f "$awk_dir/frontmatter.awk" "$_fm_file" > /dev/null
fm_title=""
fm_date=""
fm_draft=""
fm_description=""
fm_content_warning=""
fm_tags=""
while IFS='=' read -r _fk _fv; do
case "$_fk" in
title) fm_title="$_fv" ;;
date) fm_date="$_fv" ;;
draft) fm_draft="$_fv" ;;
description) fm_description="$_fv" ;;
content_warning) fm_content_warning="$_fv" ;;
tags) fm_tags="$_fv" ;;
esac
done < "$_fm_out"
rm -f "$_fm_out"
}
strip_markdown_text() {
printf '%s' "$1" | sed \
-e 's/\[//g' \
-e 's/\]//g' \
-e 's/!//g' \
-e 's/\*//g' \
-e 's/_//g' \
-e 's/`//g' \
-e 's/([^)]*)//g' \
-e 's/\\//g'
}
first_heading_from_markdown() {
grep -m 1 '^# ' "$1" | sed 's/^# *//; s/ *$//'
}
markdown_title_from_file() {
_title_file="$1"
_title_default="$2"
parse_frontmatter "$_title_file"
markdown_title="$fm_title"
if [ -z "$markdown_title" ]; then
markdown_title=$(first_heading_from_markdown "$_title_file")
if [ -n "$markdown_title" ]; then
markdown_title=$(strip_markdown_text "$markdown_title")
fi
fi
if [ -z "$markdown_title" ]; then
basename_no_ext=$(basename "$_title_file" .md)
if [ "$basename_no_ext" != "index" ] && [ "$basename_no_ext" != "404_gen" ]; then
markdown_title=$(echo "$basename_no_ext" | awk '{print toupper(substr($0,1,1)) substr($0,2)}')
else
markdown_title="$_title_default"
fi
fi
}
set_post_datetime() {
_raw_date="$1"
_fallback_name="$2"
if [ -n "$_raw_date" ]; then
post_date=$(echo "$_raw_date" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
post_time=""
if echo "$_raw_date" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?[0-9]\{2\}[:\-][0-9]\{2\}'; then
post_time=$(echo "$_raw_date" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}[ T_-]\?\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
return
fi
post_date=$(echo "$_fallback_name" | sed 's/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/')
post_time="00:00"
if echo "$_fallback_name" | grep -q '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}[:\-][0-9]\{2\}'; then
post_time=$(echo "$_fallback_name" | sed 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-\([0-9]\{2\}[:\-][0-9]\{2\}\).*/\1/' | tr '-' ':')
fi
}
set_post_metadata() {
_post_file="$1"
_default_title="$2"
_basename_no_ext=$(basename "$_post_file" .md)
markdown_title_from_file "$_post_file" "$_default_title"
post_heading="$markdown_title"
set_post_datetime "$fm_date" "$_basename_no_ext"
post_slug=$(echo "$_basename_no_ext" | sed \
-e 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2\}[:\-][0-9]\{2\}//' \
-e 's/^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}//' \
-e 's/^[_\-]//')
}

131
lib/runtime.sh Normal file
View File

@@ -0,0 +1,131 @@
trim_whitespace() {
printf '%s' "$1" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//'
}
append_find_rule() {
_expr="$1"
_rule="$2"
if [ -n "$_expr" ]; then
printf '%s -o %s\n' "$_expr" "$_rule"
else
printf '%s\n' "$_rule"
fi
}
append_pattern_rules_from_file() {
_expr="$1"
_root="$2"
_file="$3"
while IFS= read -r line || [ -n "$line" ]; do
case "$line" in
''|'#'*) continue ;;
esac
pattern=$(trim_whitespace "$line")
[ -z "$pattern" ] && continue
pattern_clean="${pattern#/}"
pattern_clean="${pattern_clean%/}"
if echo "$pattern" | grep -q "/"; then
_expr=$(append_find_rule "$_expr" "-path '$_root/$pattern_clean'")
_expr=$(append_find_rule "$_expr" "-path '$_root/$pattern_clean/*'")
else
_expr=$(append_find_rule "$_expr" "-name '$pattern_clean'")
fi
done < "$_file"
printf '%s\n' "$_expr"
}
append_nested_marker_rules() {
_expr="$1"
_root="$2"
_marker="$3"
_tmp_file="$KEWT_TMPDIR/${_marker#*.}_paths"
find "$_root" -name "$_marker" > "$_tmp_file"
while IFS= read -r marker_path; do
marker_dir="${marker_path%/$marker}"
if [ "$marker_dir" != "$_root" ] && [ "$marker_dir" != "." ]; then
_expr=$(append_find_rule "$_expr" "-path '$marker_dir'")
_expr=$(append_find_rule "$_expr" "-path '$marker_dir/*'")
fi
done < "$_tmp_file"
rm -f "$_tmp_file"
printf '%s\n' "$_expr"
}
build_rule_args() {
_root="$1"
_marker="$2"
_base_expr="$3"
_expr="$_base_expr"
if [ -f "$_root/$_marker" ]; then
_expr=$(append_pattern_rules_from_file "$_expr" "$_root" "$_root/$_marker")
fi
_expr=$(append_nested_marker_rules "$_expr" "$_root" "$_marker")
printf '%s\n' "$_expr"
}
resolve_template_path() {
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
}
build_full_nav() {
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
}
refresh_build_context() {
reset_config
load_config "./site.conf"
load_config "$src/site.conf"
HIDE_ARGS="$BASE_HIDE_ARGS"
if [ -n "$posts_dir" ]; then
HIDE_ARGS=$(append_find_rule "$HIDE_ARGS" "-path '$src/$posts_dir/*'")
fi
asset_version=""
if [ "$versioning" = "true" ]; then
asset_version="?v=$(date +%s)"
fi
resolve_template_path
build_full_nav
}
watch_for_changes() {
_mark_file="$1"
changed="$(find "$src" -type f -newer "$_mark_file" 2>/dev/null | head -n 1)"
[ -z "$changed" ] && [ -f "site.conf" ] && [ "site.conf" -nt "$_mark_file" ] && changed="site.conf"
[ -z "$changed" ] && [ -f "$src/site.conf" ] && [ "$src/site.conf" -nt "$_mark_file" ] && changed="$src/site.conf"
[ -z "$changed" ] && [ -f "$template" ] && [ "$template" -nt "$_mark_file" ] && changed="$template"
[ -z "$changed" ] && [ -d "$script_dir/styles" ] && changed="$(find "$script_dir/styles" -type f -newer "$_mark_file" 2>/dev/null | head -n 1)"
printf '%s\n' "$changed"
}
is_posts_directory_rel() {
_rel_dir="$1"
[ -n "$posts_dir" ] && { [ "$_rel_dir" = "$posts_dir" ] || [ "./$_rel_dir" = "$posts_dir" ]; }
}