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 " — " 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 "$@"