summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorCase Duckworth2022-08-08 10:54:08 -0500
committerCase Duckworth2022-08-08 10:54:08 -0500
commitd641dd302a643877f1d6eef364011180180f93fb (patch)
treeca74a4e2b785864924e2d2ba3a1ff63132e9e5d8
parentAdd Makefile (diff)
downloadht-novel.tar.gz
ht-novel.zip
Uh, thangs novel
-rwxr-xr-xht127
-rwxr-xr-xht.awk26
2 files changed, 104 insertions, 49 deletions
diff --git a/ht b/ht index c8cef5c..39f86d0 100755 --- a/ht +++ b/ht
@@ -35,31 +35,43 @@ EOF
35main() { 35main() {
36 configure "$@" 36 configure "$@"
37 shift $((OPTIND - 1)) 37 shift $((OPTIND - 1))
38 test $# -eq 0 && usage 1
39
38 prepare 40 prepare
39 static_copy 41 static_copy
40 42
41 for input; do 43 for input; do
42 page_write "$PAGE_TEMPLATE" "$input" 44 case "$input" in
45 _* | */_*) continue ;;
46 *) page_write "$PAGE_TEMPLATE" "$input" ;;
47 esac
43 done 48 done
44 49
45 if [ -n "$INDEXEACH" ]; then 50 if okp && [ -n "$INDEXEACH" ]; then
46 index_write "$INDEX_TEMPLATE" "$INDEXEACH" "$OUTD/$INDEXNAME" 51 index_write "$INDEX_TEMPLATE" "$INDEXEACH" "$OUTD/$INDEXNAME"
47 fi 52 fi
48 if [ -n "$FEEDEACH" ]; then 53 if okp && [ -n "$FEEDEACH" ]; then
49 index_write "$FEED_TEMPLATE" "$FEEDEACH" "$OUTD/$FEEDNAME" 54 index_write "$FEED_TEMPLATE" "$FEEDEACH" "$OUTD/$FEEDNAME"
50 fi 55 fi
56
51 printf 'Done. ' >&2 57 printf 'Done. ' >&2
52 if test -f "$WORKD/ok"; then 58 if okp; then
53 eprint "No errors reported." 59 eprint "No errors reported."
54 else 60 else
55 eprint "There were errors." 61 eprint "There were errors."
56 fi 62 fi
57} 63}
58 64
65htawk_resolve() {
66 if ! command -v ht.awk 2>/dev/null; then
67 print ./ht.awk
68 fi
69}
70
59configure() { 71configure() {
60 OUTD="${HT_OUT_DIR:-./out}" 72 OUTD="${HT_OUT_DIR:-./out}"
61 WORKD="${HT_WORKD:-/tmp/ht}" 73 WORKD="${HT_WORKD:-/tmp/ht}"
62 PROC="${HT_PROC:-./ht.awk}" # XXX: Needs better resolution 74 PROC="${HT_PROC:-$(htawk_resolve)}"
63 BASEURL="${HT_BASEURL:-https://example.com}" 75 BASEURL="${HT_BASEURL:-https://example.com}"
64 PAGE_TEMPLATE="${HT_PAGE_TEMPLATE:-./page.tmpl.htm}" 76 PAGE_TEMPLATE="${HT_PAGE_TEMPLATE:-./page.tmpl.htm}"
65 INDEX_TEMPLATE="${HT_INDEX_TEMPLATE:-./index.tmpl.htm}" 77 INDEX_TEMPLATE="${HT_INDEX_TEMPLATE:-./index.tmpl.htm}"
@@ -94,7 +106,7 @@ configure() {
94 fi 106 fi
95 107
96 # shellcheck disable=2034 # BASEURL is used in templates 108 # shellcheck disable=2034 # BASEURL is used in templates
97 while getopts hBo:w:p:i:I:f:F:u:s:S: opt; do 109 while getopts ho:w:p:P:i:I:f:F:u:Bs:S: opt; do
98 case "$opt" in 110 case "$opt" in
99 h) usage ;; 111 h) usage ;;
100 o) OUTD="$OPTARG" ;; 112 o) OUTD="$OPTARG" ;;
@@ -113,16 +125,17 @@ configure() {
113 esac 125 esac
114 done 126 done
115 127
128 STATICOUT="${HT_STATIC_OUTPUT_DIR:-${OUTD}/static}"
116 INDEX="$WORKD/index.txt" 129 INDEX="$WORKD/index.txt"
117} 130}
118 131
119prepare() { 132prepare() {
120 test -n "$WORKD" && rm -rf "$WORKD" 133 test -n "$WORKD" && rm -rf "$WORKD"
121 mkdir -p "$OUTD" "$WORKD" 134 mkdir -p "$OUTD" "$WORKD"
122 test -x "$PROC" || { 135 if ! test -x "$PROC"; then
123 eprint "Can't find processor: $PROC" 136 eprint "Can't find processor: $PROC"
124 exit 2 137 exit 2
125 } 138 fi
126 touch "$WORKD/ok" 139 touch "$WORKD/ok"
127} 140}
128 141
@@ -136,6 +149,14 @@ eprint() {
136 print "$@" >&2 149 print "$@" >&2
137} 150}
138 151
152okp() {
153 test -f "$WORKD/ok"
154}
155
156notok() {
157 rm "$WORKD/ok" 2>/dev/null
158}
159
139olderp() { # olderp REF OTHER 160olderp() { # olderp REF OTHER
140 # Is REF older than OTHER ? Necessary b/c test -ot is not POSIX. 161 # Is REF older than OTHER ? Necessary b/c test -ot is not POSIX.
141 a="$1" 162 a="$1"
@@ -174,6 +195,7 @@ uptodate() { # uptodate FILE DEPENDENCIES... # && return
174 file="$1" 195 file="$1"
175 shift 196 shift
176 for dep in "$@"; do 197 for dep in "$@"; do
198
177 olderp "$dep" "$file" && uptodate=0 199 olderp "$dep" "$file" && uptodate=0
178 done 200 done
179 return $uptodate 201 return $uptodate
@@ -182,28 +204,21 @@ uptodate() { # uptodate FILE DEPENDENCIES... # && return
182### File conversion 204### File conversion
183 205
184template_expand() { # template_expand TEMPLATES... 206template_expand() { # template_expand TEMPLATES...
185 end="tmpl_$(date +%s)_${count:=0}" 207 if test "$noproc"; then
186 eval "$( 208 cat -
187 print "cat <<$end" 209 else
188 cat "$@" 210 end="tmpl_$(date +%s)_${count:=0}"
189 print 211 eval "$(
190 print "$end" 212 print "cat <<$end"
191 )" 213 cat "$@"
192 count=$((count + 1)) 214 print
215 print "$end"
216 )" && count=$((count + 1))
217 fi
193} 218}
194 219
195meta_save() { # meta_save [-c COMMENTCH] [-m METACH] META_FILE < INPUT 220meta_save() { # meta_save META_FILE < INPUT
196 COMMENTCH=';' 221 sed -n "s/^;;@//p" 2>/dev/null | tee "$1"
197 METACH='@'
198 while getopts c:m: opt; do
199 case "$opt" in
200 c) COMMENTCH="$OPTARG" ;;
201 m) METACH="$OPTARG" ;;
202 *) ;;
203 esac
204 done
205 shift $((OPTIND - 1))
206 sed -n "s/^${COMMENTCH}${COMMENTCH}${METACH}//p" 2>/dev/null | tee "$1"
207} 222}
208 223
209meta_clear() { # meta_clear META_FILE 224meta_clear() { # meta_clear META_FILE
@@ -219,27 +234,38 @@ meta_clear() { # meta_clear META_FILE
219page_write() { # html_write TEMPLATE INPUT 234page_write() { # html_write TEMPLATE INPUT
220 template="$1" 235 template="$1"
221 file="$2" 236 file="$2"
237 noproc= # File can set `noproc' in their metadata to not be processed.
238
239 if ! test -f "$file"; then
240 eprint "ERROR: File doesn't exist: $file"
241 notok
242 return 1
243 fi
222 244
223 fn="${file##*/}" 245 fn="${file##*/}"
224 fn="${fn%%.*}" 246 fn="${fn%%.*}"
225 out="${OUTD}/${fn}/index.html" 247 out="${OUTD}/${fn}/index.html"
226 mkdir -p "${out%/*}" 248 mkdir -p "${out%/*}"
227 meta="$WORKD/${fn}.meta" 249 meta="$WORKD/${fn}.meta"
250 body="$WORKD/${fn}.body"
228 251
229 eval "$(meta_save "$meta" <"$file")" 252 eval "$(meta_save "$meta" <"$file")"
230 stat -c "%Y ${fn} $meta" "$file" >>"$INDEX" 253 stat -c "%Y ${fn} $meta" "$file" >>"$INDEX"
231 254
232 uptodate "$out" "$template" "$file" && return 255 # uptodate "$out" "$template" "$file" && return
233 256
234 eprint "Page: $file -> $out" 257 eprint "Page: $file -> $out"
235 if 258 test "$noproc" || "$PROC" "$file" >"$body"
236 ! "$PROC" "$file" | 259 if ! [ -f "$body" ]; then
237 tee "$WORKD/${fn}.body" | 260 eprint "ERROR: Conversion: $file"
238 template_expand "$template" >"$out" 261 notok
239 then 262 return 2
240 eprint "$file -> $out ... ERROR!" 263 fi
241 rm "$WORKD/ok" 264 test "$noproc" || body="$(template_expand "${body}")"
242 return 265 if ! template_expand "$template" >"$out"; then
266 eprint "ERROR: Expansion: $file"
267 notok
268 return 3
243 fi 269 fi
244 meta_clear "$meta" 270 meta_clear "$meta"
245} 271}
@@ -249,8 +275,10 @@ index_write() { # index_write TEMPLATE EACH OUTFILE
249 each="$2" 275 each="$2"
250 out="$3" 276 out="$3"
251 277
252 test -f "$INDEX" || return 1 278 if ! test -f "$INDEX"; then
253 uptodate "$out" "$template" "$INDEX" && return 279 : >"$INDEX"
280 fi
281 # uptodate "$out" "$template" "$INDEX" && return
254 282
255 eprint "Index: $out" 283 eprint "Index: $out"
256 # shellcheck disable=2034 # file and time can be used in `each' 284 # shellcheck disable=2034 # file and time can be used in `each'
@@ -258,9 +286,11 @@ index_write() { # index_write TEMPLATE EACH OUTFILE
258 while IFS=' ' read -r time file meta; do 286 while IFS=' ' read -r time file meta; do
259 # shellcheck disable=1090 287 # shellcheck disable=1090
260 . "$meta" 288 . "$meta"
289 # shellcheck disable=2154 # noindex is a file var
290 [ "$noindex" ] && continue
261 if ! item="$(eval print "\"$each\"")"; then 291 if ! item="$(eval print "\"$each\"")"; then
262 eprint "ERROR: couldn't add '$file' to $out" 292 eprint "ERROR: couldn't add '$file' to $out"
263 rm "$WORKD/ok" 293 notok
264 fi 294 fi
265 print "$item" 295 print "$item"
266 meta_clear "$meta" 296 meta_clear "$meta"
@@ -271,14 +301,17 @@ index_write() { # index_write TEMPLATE EACH OUTFILE
271### Static files 301### Static files
272 302
273static_copy() { # static_copy 303static_copy() { # static_copy
274 test -d "$STATICD" || return 1 304 if ! test -d "$STATICD"; then
275 if command -v rsync 2>/dev/null; then 305 return 1
276 eprint rsync -avz "$STATICD/" "$STATICOUT/"
277 rsync -avz "$STATICD/" "$STATICOUT/"
278 else
279 eprint cp -r "$STATICD"/* "$STATICOUT/"
280 cp -r "$STATICD"/* "$STATICOUT/"
281 fi 306 fi
307 mkdir -p "$STATICOUT"
308 for f in "$STATICD"/*; do
309 if [ -d "$f" ]; then
310 cp -r "$f" "$STATICOUT/"
311 else
312 cp "$f" "$STATICOUT/"
313 fi
314 done
282} 315}
283 316
284### Do the thing 317### Do the thing
diff --git a/ht.awk b/ht.awk index 7581cdb..c15ccc0 100755 --- a/ht.awk +++ b/ht.awk
@@ -62,6 +62,10 @@ $0 ~ ("^" COMMENT_DELIM) {
62 } else { 62 } else {
63 sep = "\n" 63 sep = "\n"
64 } 64 }
65 # Sanitize HTML
66 gsub(/&/, "\\\\\\&amp;", $0)
67 gsub(/</, "\\\\\\&lt;", $0)
68 gsub(/>/, "\\\\\\&gt;", $0)
65 # Loop through BLOCK_TYPES 69 # Loop through BLOCK_TYPES
66 for (bt in BLOCK_TYPES) { 70 for (bt in BLOCK_TYPES) {
67 if (match($0, "^" bt "[ \t]*")) { 71 if (match($0, "^" bt "[ \t]*")) {
@@ -105,8 +109,26 @@ $0 ~ ("^" COMMENT_DELIM) {
105 if (match($0, "^" lt "[ \t]*")) { 109 if (match($0, "^" lt "[ \t]*")) {
106 $0 = substr($0, RSTART + RLENGTH) 110 $0 = substr($0, RSTART + RLENGTH)
107 templ = LINE_TYPES[lt] 111 templ = LINE_TYPES[lt]
108 while (match(templ, /\$[0-9]+/)) { 112 while (match(templ, /\$[0-9-]+/)) {
109 sub(/\$[0-9]+/, $(substr(templ, RSTART + 1, RLENGTH - 1)), templ) 113 if (substr(templ, RSTART + 1, 1) == "-") {
114 # Up to $field
115 f = ""
116 n = substr(templ, RSTART + 2, RLENGTH - 2)
117 for (i = 1; i <= n; i++) {
118 f = f (f ? " " : "") $i
119 }
120 sub(/\$[0-9-]+/, f, templ)
121 } else if (substr(templ, RSTART + RLENGTH - 1, 1) == "-") {
122 # $Field to end
123 f = ""
124 n = substr(templ, RSTART + 1, RLENGTH - 2)
125 for (i = n; i <= NF; i++) {
126 f = f (f ? " " : "") $i
127 }
128 sub(/\$[0-9-]+/, f, templ)
129 } else {
130 sub(/\$[0-9]+/, $(substr(templ, RSTART + 1, RLENGTH - 1)), templ)
131 }
110 } 132 }
111 $0 = templ 133 $0 = templ
112 } 134 }