From 206d9a650dc851e401dfd831e7c781dfb68a1dc5 Mon Sep 17 00:00:00 2001 From: "N0\\A" Date: Tue, 5 May 2026 19:59:44 +0200 Subject: [PATCH] feat/whatever: cleanup --- kewt.sh | 176 +++++++---------------------------------------- lib/builder.sh | 166 ++++++++++---------------------------------- lib/config.sh | 75 ++++++++++---------- lib/generator.sh | 27 +------- lib/metadata.sh | 98 ++++++++++++++++++++++++++ lib/runtime.sh | 131 +++++++++++++++++++++++++++++++++++ 6 files changed, 330 insertions(+), 343 deletions(-) create mode 100644 lib/metadata.sh create mode 100644 lib/runtime.sh diff --git a/kewt.sh b/kewt.sh index 0c1e89d..13c511b 100755 --- a/kewt.sh +++ b/kewt.sh @@ -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 diff --git a/lib/builder.sh b/lib/builder.sh index e200870..d98f2b3 100644 --- a/lib/builder.sh +++ b/lib/builder.sh @@ -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 diff --git a/lib/config.sh b/lib/config.sh index a8a33db..d6ce81a 100644 --- a/lib/config.sh +++ b/lib/config.sh @@ -59,42 +59,43 @@ DEFAULT_TMPL=' ' -title="kewt" -style="kewt" -lang="en" -draft_by_default="false" -footer="made with kewt" -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 kewt" -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 kewt" + 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 diff --git a/lib/generator.sh b/lib/generator.sh index b521b4c..4492657 100644 --- a/lib/generator.sh +++ b/lib/generator.sh @@ -23,29 +23,6 @@ escape_html_attr() { -e 's//\>/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) diff --git a/lib/metadata.sh b/lib/metadata.sh new file mode 100644 index 0000000..35b2825 --- /dev/null +++ b/lib/metadata.sh @@ -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/^[_\-]//') +} diff --git a/lib/runtime.sh b/lib/runtime.sh new file mode 100644 index 0000000..ddbf252 --- /dev/null +++ b/lib/runtime.sh @@ -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" ]; } +}