ssg5

Static site generator used for foxide.xyz
Log | Files | Refs | README | LICENSE

ssg5 (4891B)


      1 main() {
      2 	test -n "$1" || usage
      3 	test -n "$2" || usage
      4 	test -n "$3" || usage
      5 	test -n "$4" || usage
      6 	test -d "$1" || no_dir "$1"
      7 	test -d "$2" || no_dir "$2"
      8 
      9 	src=$(readlink_f "$1")
     10 	dst=$(readlink_f "$2")
     11 
     12 	IGNORE=$(
     13 		if ! test -f "$src/.ssgignore"; then
     14 			printf ' ! -path "*/.*"'
     15 			return
     16 		fi
     17 		while read -r x; do
     18 			test -n "$x" || continue
     19 			printf ' ! -path "*/%s*"' "$x"
     20 		done <"$src/.ssgignore"
     21 	)
     22 
     23 	# files
     24 
     25 	title="$3"
     26 
     27 	h_file="$src/_header.html"
     28 	f_file="$src/_footer.html"
     29 	test -f "$f_file" && FOOTER=$(cat "$f_file") && export FOOTER
     30 	test -f "$h_file" && HEADER=$(cat "$h_file") && export HEADER
     31 
     32 	list_dirs "$src" |
     33 		(cd "$src" && cpio -pdu "$dst")
     34 
     35 	fs=$(
     36 		if test -f "$dst/.files"; then
     37 			list_affected_files "$src" "$dst/.files"
     38 		else
     39 			list_files "$1"
     40 		fi
     41 	)
     42 
     43 	if test -n "$fs"; then
     44 		echo "$fs" | tee "$dst/.files"
     45 
     46 		if echo "$fs" | grep -q '\.md$'; then
     47 			if test -x "$(which lowdown 2>/dev/null)"; then
     48 				echo "$fs" | grep '\.md$' |
     49 					render_md_files_lowdown "$src" "$dst" "$title"
     50 			else
     51 				if test -x "$(which Markdown.pl 2>/dev/null)"; then
     52 					echo "$fs" | grep '\.md$' |
     53 						render_md_files_Markdown_pl "$src" "$dst" "$title"
     54 				else
     55 					echo "couldn't find lowdown nor Markdown.pl"
     56 					exit 3
     57 				fi
     58 			fi
     59 		fi
     60 
     61 		echo "$fs" | grep '\.html$' |
     62 			render_html_files "$src" "$dst" "$title"
     63 
     64 		echo "$fs" | grep -Ev '\.md$|\.html$' |
     65 			(cd "$src" && cpio -pu "$dst")
     66 	fi
     67 
     68 	printf '[ssg] ' >&2
     69 	print_status 'file, ' 'files, ' "$fs" >&2
     70 
     71 	# sitemap
     72 
     73 	base_url="$4"
     74 	date=$(date +%Y-%m-%d)
     75 	urls=$(list_pages "$src")
     76 
     77 	test -n "$urls" &&
     78 		render_sitemap "$urls" "$base_url" "$date" >"$dst/sitemap.xml"
     79 
     80 	print_status 'url' 'urls' "$urls" >&2
     81 	echo >&2
     82 }
     83 
     84 readlink_f() {
     85 	file="$1"
     86 	cd "$(dirname "$file")"
     87 	file=$(basename "$file")
     88 	while test -L "$file"; do
     89 		file=$(readlink "$file")
     90 		cd "$(dirname "$file")"
     91 		file=$(basename "$file")
     92 	done
     93 	dir=$(pwd -P)
     94 	echo "$dir/$file"
     95 }
     96 
     97 print_status() {
     98 	test -z "$3" && printf 'no %s' "$2" && return
     99 
    100 	echo "$3" | awk -v singular="$1" -v plural="$2" '
    101 	END {
    102 		if (NR==1) printf NR " " singular
    103 		if (NR>1) printf NR " " plural
    104 	}'
    105 }
    106 
    107 usage() {
    108 	echo "usage: ${0##*/} src dst title base_url" >&2
    109 	exit 1
    110 }
    111 
    112 no_dir() {
    113 	echo "${0##*/}: $1: No such directory" >&2
    114 	exit 2
    115 }
    116 
    117 list_dirs() {
    118 	cd "$1" && eval "find . -type d ! -name '.' ! -path '*/_*' $IGNORE"
    119 }
    120 
    121 list_files() {
    122 	cd "$1" && eval "find . -type f ! -name '.' ! -path '*/_*' $IGNORE"
    123 }
    124 
    125 list_dependant_files() {
    126 	e="\\( -name '*.html' -o -name '*.md' -o -name '*.css' -o -name '*.js' \\)"
    127 	cd "$1" && eval "find . -type f ! -name '.' ! -path '*/_*' $IGNORE $e"
    128 }
    129 
    130 list_newer_files() {
    131 	cd "$1" && eval "find . -type f ! -name '.' $IGNORE -newer $2"
    132 }
    133 
    134 has_partials() {
    135 	grep -qE '^./_.*\.html$|^./_.*\.js$|^./_.*\.css$'
    136 }
    137 
    138 list_affected_files() {
    139 	fs=$(list_newer_files "$1" "$2")
    140 
    141 	if echo "$fs" | has_partials; then
    142 		list_dependant_files "$1"
    143 	else
    144 		echo "$fs"
    145 	fi
    146 }
    147 
    148 render_html_files() {
    149 	while read -r f; do
    150 		render_html_file "$3" <"$1/$f" >"$2/$f"
    151 	done
    152 }
    153 
    154 render_md_files_lowdown() {
    155 	while read -r f; do
    156 		lowdown \
    157 			--html-no-escapehtml \
    158 			--html-no-skiphtml \
    159 			--parse-no-metadata \
    160 			--parse-no-autolink <"$1/$f" |
    161 			render_html_file "$3" \
    162 				>"$2/${f%\.md}.html"
    163 	done
    164 }
    165 
    166 render_md_files_Markdown_pl() {
    167 	while read -r f; do
    168 		Markdown.pl <"$1/$f" |
    169 			render_html_file "$3" \
    170 				>"$2/${f%\.md}.html"
    171 	done
    172 }
    173 
    174 render_html_file() {
    175 	# h/t Devin Teske
    176 	awk -v title="$1" '
    177 	{ body = body "\n" $0 }
    178 	END {
    179 		body = substr(body, 2)
    180 		if (body ~ /<\/?[Hh][Tt][Mm][Ll]/) {
    181 			print body
    182 			exit
    183 		}
    184 		if (match(body, /<[[:space:]]*[Hh]1(>|[[:space:]][^>]*>)/)) {
    185 			t = substr(body, RSTART + RLENGTH)
    186 			sub("<[[:space:]]*/[[:space:]]*[Hh]1.*", "", t)
    187 			gsub(/^[[:space:]]*|[[:space:]]$/, "", t)
    188 			if (t) title = t " &mdash; " title
    189 		}
    190 		n = split(ENVIRON["HEADER"], header, /\n/)
    191 		for (i = 1; i <= n; i++) {
    192 			if (match(tolower(header[i]), "<title></title>")) {
    193 				head = substr(header[i], 1, RSTART - 1)
    194 				tail = substr(header[i], RSTART + RLENGTH)
    195 				print head "<title>" title "</title>" tail
    196 			} else print header[i]
    197 		}
    198 		print body
    199 		print ENVIRON["FOOTER"]
    200 	}'
    201 }
    202 
    203 list_pages() {
    204 	e="\\( -name '*.html' -o -name '*.md' \\)"
    205 	cd "$1" && eval "find . -type f ! -path '*/.*' ! -path '*/_*' $IGNORE $e" |
    206 		sed 's#^./##;s#.md$#.html#;s#/index.html$#/#'
    207 }
    208 
    209 render_sitemap() {
    210 	urls="$1"
    211 	base_url="$2"
    212 	date="$3"
    213 
    214 	echo '<?xml version="1.0" encoding="UTF-8"?>'
    215 	echo '<urlset'
    216 	echo 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
    217 	echo 'xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9'
    218 	echo 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"'
    219 	echo 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
    220 	echo "$urls" |
    221 		sed -E 's#^(.*)$#<url><loc>'"$base_url"'/\1</loc><lastmod>'"$date"'</lastmod><priority>1.0</priority></url>#'
    222 	echo '</urlset>'
    223 }
    224 
    225 main "$@"