build
1#!/bin/sh
2
3# ---------------------------- global variables ----------------------------- #
4SITE_DOMAIN="noxz.tech"
5SITE_TITLE="noxz.tech | "
6SITE_MAIN_TITLE="noxz.tech"
7SITE_AUTHOR="Chris Noxz"
8SITE_ICON_PNG="//[site]/pub/logo.png"
9SITE_ICON_SVG="//[site]/pub/logo.svg"
10SITE_CSS="//[site]/pub/style.css"
11SITE_GIT_REPO_ROOT="${HOME}/mnt/src/z0noxz"
12SITE_GIT_COMMIT_PH="repo-logs"
13SITE_GIT_COMMIT_COUNT="100"
14SITE_WWW=
15SITE_HTML=
16SITE_REPLACE_DOT=1
17# ------------------------------ config files ------------------------------- #
18CFG_DIR="./config"
19# ------------------------ groff configuration files ------------------------ #
20CFG_GROFF_WWW_MACRO="${CFG_DIR}/www.conf"
21CFG_GROFF_EQN="${CFG_DIR}/eqn.conf"
22CFG_GROFF_PIC="${CFG_DIR}/pic.conf"
23# ---------------------- main html configuration files ---------------------- #
24CFG_MAIN_HTML="${CFG_DIR}/main.html"
25# ---------------------- git html configuration files ----------------------- #
26CFG_GIT_REPOS_HTML="${CFG_DIR}/git_repos.html"
27CFG_GIT_HEAD_HTML="${CFG_DIR}/git_head.html"
28# --------------------- sitemap.xml configuration files --------------------- #
29CFG_SITEMAP_XML="${CFG_DIR}/sitemap.xml"
30CFG_SITEMAP_XML_ITEM="${CFG_DIR}/sitemap_item.xml"
31# ------------------------ pinned tag configuration ------------------------ #
32CFG_PINNED_TAG="pinned"
33
34
35# helper function to fix dot files if asked to do so
36# shellcheck disable=SC2120
37fix_dot_file() {
38 if [ ${SITE_REPLACE_DOT} -ne 1 ]; then
39 if [ ! -t 0 ]; then
40 cat -
41 elif [ -n "${1}" ]; then
42 echo "${1}"
43 fi
44 else
45 if [ ! -t 0 ]; then
46 cat -
47 elif [ -n "${1}" ]; then
48 echo "${1}"
49 fi \
50 | sed \
51 -e "s,/\.,/_\.,g" \
52 -e "s,^\.,_\.,g"
53 fi
54}
55
56# helper function to html encode stdin
57# shellcheck disable=SC2120
58html_encode() {
59 if [ ! -t 0 ]; then
60 cat -
61 elif [ -n "$1" ]; then
62 echo "$1"
63 fi \
64 | sed \
65 -e 's/&/\&/g' \
66 -e 's/"/\"/g' \
67 -e 's/</\</g' \
68 -e 's/>/\>/g'
69}
70
71# helper function to produce awk safe strings
72# shellcheck disable=SC2120
73awk_safe() {
74 if [ ! -t 0 ]; then
75 cat -
76 elif [ -n "$1" ]; then
77 echo "$1"
78 fi \
79 | sed \
80 -e 's/\\/\\\\/g' \
81 -e 's/\&/\\\\\&/g'
82}
83
84print_loading() {
85 >&2 printf '[%s*%s] %-.100s ' \
86 "$(tput setaf 4)" \
87 "$(tput sgr 0)" \
88 "${1} $(for _ in $(seq 1 100); do printf '.'; done)"
89}
90
91print_done() {
92 >&2 printf '[%sdone%s]\n' \
93 "$(tput setaf 2)" \
94 "$(tput sgr 0)"
95}
96
97# arg 1: site root eg. ../noxz-sites/noxz.tech
98# arg 2: current site eg. ../noxz-sites/noxz.tech/guides/groff
99render_main_menu() {
100 # variables used in main menu
101 menu_root="${1}"
102 menu_current="${2}"
103 menu_active=""
104 menu_output=""
105 menu_buffer=""
106 menu_home="$(printf '<li><a href="//%s/">home</a></li>' "${SITE_DOMAIN}")"
107
108 # check if both directories exist
109 [ ! -d "${menu_root}" ] && return
110 [ ! -d "${menu_current}" ] && return
111
112 # remove trailing slashes if existing
113 menu_root=$(dirname "${menu_root}/*")
114 menu_current=$(dirname "${menu_current}/*")
115
116 # make sure current directory is a subdirectory of root
117 echo "${menu_current}" | grep -qv "^${menu_root}" && return
118
119 # root menu
120 if [ "${menu_root}" = "${menu_current}" ]; then
121 menu_home="$(echo "${menu_home}" | sed 's/<li/<li class="active"/')"
122 for f in "${menu_current}"/*; do
123 [ ! -d "${f}" ] && continue # only process directories
124 [ -f "${f}/.buildignore" ] && continue # skip buildignore
125
126 ff="$(echo "${f}" | sed "s?^${menu_root}?//${SITE_DOMAIN}?")"
127 fn="$(echo "${f##*/}" | sed -e 's/__/: /g' -e 's/_/ /g')"
128 menu_output=$(printf '%s<li><a href="%s">%s</a></li>' \
129 "${menu_output}" \
130 "${ff}" \
131 "${fn}")
132 done
133 fi
134
135 # run until root directory is the current one
136 while [ "${menu_root}" != "${menu_current}" ]; do
137
138 # handle children of first current
139 if [ "${menu_current}" = "${2}" ]; then
140 for f in "${menu_current}"/*; do
141 [ ! -d "${f}" ] && continue # only process directories
142 [ -f "${f}/.buildignore" ] && continue # skip buildignore
143 menu_output="$(printf '%s<li' "${menu_output}")"
144 ff="$(echo "${f}" | sed "s?^${menu_root}?//${SITE_DOMAIN}?")"
145 fn="$(echo "${f##*/}" | sed -e 's/__/: /g' -e 's/_/ /g')"
146 menu_output=$(printf '%s><a href="%s">%s</a></li>' \
147 "${menu_output}" \
148 "${ff}" \
149 "${fn}")
150 done
151 fi
152
153 menu_active="${menu_current}" # mark current as active
154 menu_current="${menu_current%/*}" # mark parent as current
155
156 # handle all siblings
157 for f in "${menu_current}"/*; do
158 [ ! -d "${f}" ] && continue # only process directories
159 [ -f "${f}/.buildignore" ] && continue # skip buildignore
160
161 menu_buffer=$(printf '%s<li' "${menu_buffer}")
162 ff="$(echo "${f}" | sed "s?^${menu_root}?//${SITE_DOMAIN}?")"
163 fn="$(echo "${f##*/}" | sed -e 's/__/: /g' -e 's/_/ /g')"
164 if [ "${f}" = "${menu_active}" ]; then # treat active different
165 menu_buffer=$(printf '%s class="active"><a href="%s">%s</a>'\
166 "${menu_buffer}" \
167 "${ff}" \
168 "${fn}")
169 # dump output to buffer if existing (sub menu)
170 [ "${menu_output}" != "" ] \
171 && menu_buffer=$(printf '%s<ul>%s</ul>' \
172 "${menu_buffer}" \
173 "${menu_output}")
174 menu_buffer=$(printf '%s</li>' "${menu_buffer}")
175 else
176 menu_buffer=$(printf '%s><a href="%s">%s</a></li>' \
177 "${menu_buffer}" \
178 "${ff}" \
179 "${fn}")
180 fi
181 done
182 menu_output="${menu_buffer}"
183 menu_buffer=""
184 done
185 printf '<ul id="main-nav">%s%s</ul>' \
186 "${menu_home}" \
187 "${menu_output}" \
188 | sed \
189 -e 's,\(<\(ul\|li\)[^>]*>\|</ul>\),\n\1,2g' \
190 -e 's,\(</ul>\)\(</li>\),\1\n\2,g' \
191 | awk '
192 BEGIN {
193 level=0
194 }
195
196 /<\/ul>/ {
197 level--
198 }
199
200 /^<\/li>$/ {
201 level--
202 }
203
204 {
205 for (i=0; i<level; i++)
206 printf "\t"
207 print
208 }
209
210 /<ul[^>]*>/ {
211 level++
212 }
213
214 /<li[^>]*>.*<\/a>$/ {
215 level++
216 }
217 '
218}
219
220render_main_menu_extra() {
221 printf '<li><a class="%s" href="%s">%s</a></li>\n' \
222 "pin" "//[site]/articles/tags/pinned" "pinned articles" \
223 "howto" "//[site]/articles/tags/howto" "how to" \
224 "twtxt" "//[site]/twtxt.txt" "twtxt" \
225 "source" "//[site]/git/" "source" \
226 | awk \
227 '
228 BEGIN {
229 printf "<ul id=\"extra-nav\">\n"
230 }
231
232 {
233 printf "\t%s\n", $0
234 }
235
236 END {
237 printf "</ul>\n"
238 }
239 '
240}
241
242render_articles() {
243 # copy tag list from tags page
244 [ -z "${2}" ] && sed -e 's,\.ARTTAG "\([^"]*\)",.ARTTAG "tags/\1",g' \
245 "${1}"/articles/tags/index.www
246 echo .DIVS articles
247 [ -n "${2}" ] && printf '.ULS\n'
248 if [ "${2}" != "${CFG_PINNED_TAG}" ]; then
249 find "${1}"/articles -name .metadata | while read -r article
250 do
251 grep "^.ds YEAR" "${article}" | sed 's/^.ds YEAR[^0-9]*//g'
252 done | sort -ru
253 else
254 # merge every year for pinned articles, to sort them alphabetically
255 echo
256 fi | while read -r year
257 do
258 [ -z "${2}" ] && printf '.HnS 1\n%s\n.HnE\n\.ULS\n' "${year}"
259 if [ -z "${2}" ]; then
260 grep -l "^.ds YEAR.*${year}" "${1}"/articles/*/.metadata
261 else # filter by tag
262 grep -l "^${2}$" "${1}"/articles/*/.tags \
263 | sed 's/\.tags$/.metadata/g' \
264 | xargs -I{} grep -l "^.ds YEAR.*${year}" "{}"
265 fi | xargs -I{} awk -v name="{}" -v tag="${2}" -v cfg_pinned_tag="${CFG_PINNED_TAG}" '
266 BEGIN {
267 title = ""
268 year = ""
269 month = ""
270 day = ""
271 gsub(/\/.metadata/,"",name)
272 gsub(/^([^\/]|\/)*\//,"",name)
273 printf ".LI\\n "
274 }
275 /^\.ds TITLE.*$/ {
276 for(i=3;i<=NF;i++) {
277 title = title$i
278 if (i != NF)
279 title = title" "
280 }
281 }
282 /^\.ds YEAR.*$/ {
283 year = $3
284 }
285 /^\.ds MONTH.*$/ {
286 month = substr($3,1,3)
287 }
288 /^\.ds DAY.*$/ {
289 day = $3
290 }
291 END {
292 if (tag == cfg_pinned_tag)
293 printf ".URL \"../../%s\" \"%s\"\n", name, title
294 else if (tag != "")
295 printf "%s %s, %s \\(em\\n .URL \"../../%s\" \"%s\"\n", day, month, year, name, title
296 else
297 printf "%s %s \\(em\\n .URL \"%s\" \"%s\"\n", day, month, name, title
298 }
299 ' "{}" | if [ "${2}" = "${CFG_PINNED_TAG}" ]; then
300 sort -k 4
301 else
302 sort -k 3Mr -k 2nr
303 fi | sed -e 's/\\n /\n/g'
304 [ -z "${2}" ] && printf '.ULE\n'
305 done
306 [ -n "${2}" ] && printf '.ULE\n'
307 echo .DIVE
308}
309
310
311
312# fix for grohtml not reliably working for picture extraction
313extract_pictures() {
314 base_path="${SITE_WWW%/*}"
315 pic=""
316 tex=""
317 tex_type=""
318 in_pic=0
319 in_tex=0
320 i=0
321
322 tex_template() {
323 case "$1" in
324 tikz)
325 cat <<-LATEX
326 \\documentclass[tikz,border=10pt]{standalone}
327 \\usepackage{xcolor}
328 \\usepackage{tikz}
329 \\usepackage{ifthen}
330 \\begin{document}
331 \\begin{tikzpicture}
332 ${tex}
333 \\end{tikzpicture}
334 \\end{document}
335 LATEX
336 ;;
337 equation|*)
338 cat <<-LATEX
339 \\documentclass{article}
340 \\usepackage{amsmath}
341 \\usepackage{amssymb}
342 \\usepackage{xcolor}
343 \\newcommand{\\hi}[1]{\\textcolor{red}{#1}}
344 \\pagestyle{empty}
345 \\begin{document}
346 ${tex}
347 \\end{document}
348 LATEX
349 ;;
350 esac
351 }
352
353 cat - | while read -r line; do
354 # extract LaTeX
355 if [ $in_tex -eq 0 ] && echo "${line}" | grep -q '^\.TEXS'; then
356 in_tex=1
357 tex_type=$(echo "${line}" | awk '{print $2}')
358 tex_type=${tex_type:-equation}
359 tex=""
360 continue
361 fi
362 # render and save TEX instance as a svg image
363 if [ $in_tex -eq 1 ] && [ "$(echo ${line} | grep '^\.TEXE')" = ".TEXE" ]; then
364 in_tex=0
365
366 # generate svg from tex
367 tex=$(printf '%s' "${tex}" | sed -e '1s/^\n*//' -e '$s/\n*$//')
368 tex_template "${tex_type}" | tex2svg - - | awk "
369 /<svg/ {
370 match(\$0, /viewBox='([0-9.e+-]+) ([0-9.e+-]+) ([0-9.e+-]+) ([0-9.e+-]+)'/, vb)
371 match(\$0, /width='([0-9.e+-]+)pt'/, w)
372 match(\$0, /height='([0-9.e+-]+)pt'/, h)
373
374 if (vb[0] && w[0] && h[0]) {
375 padding = 1
376 minx = vb[1] - padding
377 miny = vb[2] - padding
378 vbw = vb[3] + padding * 2
379 vbh = vb[4] + padding * 2
380 width = w[1] + padding * 2
381 height = h[1] + padding * 2
382
383 sub(/width='[0-9.e+-]+pt'/, \"width='\" width \"pt'\")
384 sub(/height='[0-9.e+-]+pt'/, \"height='\" height \"pt'\")
385 sub(/viewBox='[^']+'/, \"viewBox='\" minx \" \" miny \" \" vbw \" \" vbh \"'\")
386 }
387 }
388 { print }" > "${base_path}/tex-${i}.svg"
389
390 printf '.SVG tex-%s.svg "tex tex-%s"\n' "${i}" "${tex_type}"
391
392 i=$((i+1))
393 fi
394 # catch and save every TEX instance
395 if [ $in_tex -eq 1 ]; then
396 if [ -z "${tex}" ]; then
397 tex="${line}"
398 else
399 tex="$(printf '%s\n%s' "${tex}" "${line}")"
400 fi
401 else
402 printf '%s\n' "${line}"
403 fi
404 done
405}
406
407prerender() {
408 base_path="${SITE_WWW%/*}"
409 title=""
410 author=""
411 date=""
412
413 [ -f "${base_path}"/.metadata ] && while read -r line; do
414 case "$line" in
415 \.ds\ TITLE*) title="$(echo ${line#*TITLE})";;
416 \.ds\ DATE*) date="$(echo ${line#*DATE})";;
417 \.ds\ AUTHOR*) author="$(echo ${line#*AUTHOR})";;
418 esac
419 printf '%s\n' "${line}"
420 done < "${base_path}"/.metadata
421
422 [ -n "$title" ] && printf '\n.ll 10i\n\n.HnS 0\n\\*[TITLE]\n.HnE\n\n'
423 [ -n "$author" ] && printf '.P article-author\n\\*[AUTHOR]\n\n'
424 [ -n "$date" ] && printf '.P article-date\n\\*[DATE]\n\n'
425
426 # print tags, if existing, at bottom of page
427 [ -f "${base_path}"/.tags ] \
428 && printf '\n.DIVS wrap-list\n.ULS\n' \
429 && while read -r tag; do
430 if [ "${tag}" != "${CFG_PINNED_TAG}" ]; then
431 tag_safe="$(echo "${tag}" | tr \ _)"
432 printf '.LI\n.CLURL "../tags/%s" art-tag "%s"\n' "${tag_safe}" "${tag}"
433 fi
434 done < "${base_path}"/.tags && printf '.ULE\n.DIVE\n\n'
435
436 [ -f "${base_path}"/.edit ] \
437 && sed "${base_path}"/.edit \
438 -e 's/^START \([0-9-]*\)$/.LI \1\n.ULS/g' \
439 -e 's/^\t\(.*\)$/.LI\n\1/g' \
440 -e 's/^END$/.ULE/g' \
441 -e '1 i\.DIVS edit-note\n.HnS 2\nEdit notice\n.HnE\n.DLS' \
442 -e '$ a .DLE\n.DIVE\n'
443
444 cat - | while read -r line; do
445 if echo "${line}" | grep -E '\{:articles(#[^#]*)?:\}' 2>/dev/null 1>&2; then
446 render_articles "$1" \
447 "$(echo "${line}" | sed 's/\([^#]*#\?\)\(.*\)\(:.*$\)/\2/')"
448 else
449 printf '%s\n' "${line}"
450 fi
451 done
452}
453
454render_main_content() {
455 awk '
456 # Grohtml (post-html.cpp) has a hard coded max length:
457 # https://git.savannah.gnu.org/cgit/groff.git/tree/src/devices/grohtml/post-html.cpp
458 # 51: #define MAX_LINE_LENGTH 60
459 # This creates a problem when printing words longer than 60 characters -
460 # creating an extra blank line before the word. Further more grohtml
461 # actually do not print code blocks using <code> or <pre> so blank lines
462 # that are supposed to be printed are instead ignored. These following
463 # awk scripts together with some extensions of the www-macros (see.
464 # www.conf) are supposed to fix these issues.
465
466 BEGIN { # initialize variables
467 _inblock=0
468 }
469
470 /\.COS/ {
471 _inblock=1
472 }
473
474 /\.COE/ {
475 _inblock=0
476 }
477
478 { # normal: no fixes applied
479 if (!_inblock) {
480 print
481 next
482 }
483 }
484
485 ## INSIDE CODE BLOCK ##
486
487 # replace blank lines with extended BR macro
488 /^$/ {
489 print ".COMMENT-BR"
490 next
491 }
492
493 /\047/ { # replace apostrophe
494 gsub(/\047/, "\\\[aq\]", $0);
495 }
496
497 /\~/ { # replace tilde
498 gsub(/\~/, "\\\[ti\]", $0);
499 }
500
501 /\^/ { # replace circumflex
502 gsub(/\^/, "\\\[ha\]", $0);
503 }
504
505 /\t/ { # replace tabs with 4 spaces
506 gsub(/\t/, " ", $0);
507 }
508
509 { # very ugly fix to preserve spaces (see if this can be imporoved upon)
510 # NOTE: angle brackets will be encoded by groff!
511 gsub(/\s{2}/, "<!--space--><!--space-->", $0)
512 gsub(/<!--space-->\s/, "<!--space--><!--space-->", $0)
513 print
514 }
515 ' "${SITE_WWW}" \
516 | extract_pictures "$1" \
517 | prerender "$1" \
518 | cat "${CFG_GROFF_WWW_MACRO}" - \
519 | groff \
520 -Thtml -e -mwww -k \
521 -I"${SITE_WWW%/*}/grohtml-" \
522 | awk '
523 # --------------------------------------------
524 # somewhat messy fix for code block formatting
525 # --------------------------------------------
526 BEGIN { # initialize variables
527 _inblock=0
528 _break=0
529 }
530
531 /<pre><code>/ { # signal start of code block
532 _inblock=1
533 }
534
535 /<\/code><\/pre>/ { # signal end of code block
536 _inblock=0
537 }
538
539 { # normal: no fixes applied
540 if (!_inblock) {
541 print
542 next
543 }
544 }
545
546 ## INSIDE CODE BLOCK ##
547
548 /^$/ { # fix: skip blank lines in code blocks
549 next
550 }
551
552 { # handle general code block instances
553 # replace placeholders
554 gsub(/<!--space-->/, " ", $0); # groff has now encoded angle brackets
555 gsub(/<!--break-->/, "", $0);
556
557 if (!_break)
558 printf " "
559 _break=0
560 }
561
562 /<br[^>]*>/ { # signal line break
563 _break=1
564 }
565
566 {
567 gsub(/<br[^>]*>/, "\n", $0);
568 printf "%s", $0
569 }
570 ' \
571 | sed \
572 -e 's/<p style[^>]*>/<p>/g' \
573 -e 's/<dd>/<dd><p>/g' \
574 -e 's/<p><!--/<!--/g' -e 's/--><\/p>/-->/g' \
575 -e 's/\[at\]/<span>\@<\/span>/g' \
576 -e 's/\(src\|alt\)="[^"]*\(\(eqn\|pic\)-[0-9]*.png\)/\1="\2/g' \
577 -e 's/\(<img src="\(eqn\|pic\)-[0-9]*.\(png\|svg\)" alt="[^"]*"\)[^>]*>/<p class="\2">\1\/><\/p>/g' \
578 -e 's/<p align="\(left\|center\|right\)"[^>]*>/<p class="\1">/g' \
579 -e 's/<pre><code>/<div class="code-wrap"><pre><code>/g' \
580 -e 's/<\/code><\/pre>/<\/code><\/pre><\/div>/g' \
581 | tidy -asxhtml \
582 | sed -e '/^\s*<dd><\/dd>$/d' \
583 | awk '
584 /<body>/{
585 flag=1
586 next
587 }
588
589 /<\/body>/{
590 flag=0
591 }
592
593 flag
594 ' \
595 | awk '
596 BEGIN { # initialize variables
597 _inblock=0
598 }
599
600 { # normal: no fixes applied
601 if (NR > 1 && !_inblock) {
602 printf "<!--padding-->"
603 }
604 print
605 }
606 /<pre><code>/ { # signal start of code block
607 _inblock=1
608 }
609
610 /<\/code><\/pre>/ { # signal end of code block
611 _inblock=0
612 }
613 '
614}
615
616render_main() {
617 main_current="${2}"
618
619 [ ! -d "${main_current}" ] && return
620 main_current=$(dirname "${main_current}/*")
621
622 [ -f "${main_current}/index.www" ] && SITE_WWW="${main_current}/index.www" || return
623 [ -f "${main_current}/.metadata" ] && SITE_TITLE="${SITE_TITLE}$(grep '\.ds TITLE' "${main_current}/.metadata" | sed 's/\.ds\ TITLE\s*/.ll 10i\n/g' | groff -Tutf8 | sed -n '1,1p')"
624 SITE_HTML="${SITE_WWW%.*}.html"
625
626 print_loading "Rendering ${main_current}"
627
628 awk \
629 -v var_author="$(awk_safe "${SITE_AUTHOR}")" \
630 -v var_title="$(awk_safe "${SITE_TITLE}")" \
631 -v var_favicon="$(awk_safe "${SITE_ICON_PNG}")" \
632 -v var_stylesheet="$(awk_safe "${SITE_CSS}")" \
633 -v var_logo="$(awk_safe "${SITE_ICON_SVG}")" \
634 -v var_main_title="$(awk_safe "${SITE_MAIN_TITLE}")" \
635 -v var_menu="$(render_main_menu "$1" "$2" | awk_safe)" \
636 -v var_menu_extra="$(render_main_menu_extra | awk_safe)" \
637 -v var_content="$(render_main_content "$1" 2>/dev/null | awk_safe)" \
638 -v var_year="$(date +%Y)" \
639 '
640 /\{:menu:\}/{
641 padding=$0
642 gsub(/{:.*:}$/, "", padding)
643 gsub(/\n/, "\n" padding, var_menu)
644 }
645
646 /\{:menu_extra:\}/{
647 padding=$0
648 gsub(/{:.*:}$/, "", padding)
649 gsub(/\n/, "\n" padding, var_menu_extra)
650 }
651
652 /\{:content:\}/{
653 padding=$0
654 gsub(/{:.*:}$/, "", padding)
655 gsub(/<!--padding-->/, padding, var_content)
656 }
657
658 {
659 gsub(/\{:author:\}/, var_author)
660 gsub(/\{:title:\}/, var_title)
661 gsub(/\{:favicon:\}/, var_favicon)
662 gsub(/\{:stylesheet:\}/, var_stylesheet)
663 gsub(/\{:logo:\}/, var_logo)
664 gsub(/\{:main_title:\}/, var_main_title)
665 gsub(/\{:sub_title:\}/, var_sub_title)
666 gsub(/\{:menu:\}/, var_menu)
667 gsub(/\{:menu_extra:\}/, var_menu_extra)
668 gsub(/\{:content:\}/, var_content)
669 gsub(/\{:year:\}/, var_year)
670 print
671 }
672 ' "${CFG_MAIN_HTML}" > "${SITE_HTML}"
673
674 print_done
675}
676
677render_git_commit() {
678 git_commit_files="$(git -C "${1}" whatchanged "${2}"^! | grep '^:.*$' | cut -d' ' -f5 | sed 's/\t/:/g')"
679 git -C "${1}" show --stat=1000 --stat-graph-width=20 "${2}" \
680 --format="format:%H%n%P%n%aN%n%aE%n%aD%n%B%H" \
681 | sed 's/{\(.*\) => \(.*\)}/\1/g' \
682 | html_encode | awk -v flist="${git_commit_files}" -v base="//${1}" '
683 BEGIN {
684 marker=""; files=0; split(flist, farr, "\n");
685 for (i in farr) {
686 split(farr[i], ftmp, ":");
687 farr[i,1] = substr(ftmp[1], 1, 1);
688 farr[i,2] = ftmp[2];
689 farr[i,3] = ftmp[3];
690 }
691 }
692 {
693 switch (NR) {
694 case 1:
695 marker=$0
696 printf "<pre>\n"
697 printf "<b>commit</b>: <a href=\"%s/commit/%s.html\">%s</a>\n",base,$0,$0
698 break
699 case 2:
700 printf "<b>parent</b>: <a href=\"%s/commit/%s.html\">%s</a>\n",base,$0,$0
701 break
702 case 3:
703 printf "<b>author</b>: %s",$0
704 break
705 case 4:
706 if ($0 != "") { printf " <<a href=\"mailto:%s\">%s</a>>",$0,$0 }
707 printf "\n"
708 break
709 case 5:
710 printf "<b>date</b>: %s\n",$0
711 printf "</pre>\n"
712 break
713 case 6:
714 printf "<pre class=\"body\">\n"
715 default:
716 if (files) {
717 for (i in farr) {
718 if ($1 == farr[i,2]) {
719 printf "<tr>"
720 printf "<td>%s</td><td><a href=\"#f%d\">%s</a>",farr[i,1],i,farr[i,2]
721 if (farr[i,3] != "") {
722 printf " → <a href=\"#f%d\">%s</a>",i,farr[i,3]
723 }
724 printf "</td>",$3
725 printf "<td>%s</td>",$3
726 printf "<td><span class=\"i\">"
727 p=1
728 for (j = 1; j <= length($4); j++) {
729 if (p && substr($4, j, 1) != "+") {
730 p=0; printf "</span><span class=\"d\">"
731 }
732 printf "%s",substr($4,j,1)
733 }
734 printf "</span></td>"
735 print "</tr>"
736 next
737 }
738 }
739 sub(/^[ \t\r\n]+/, "", $0)
740 printf "</table>\n%s\n",$0
741 } else {
742 if (marker != "" && marker == $0) { printf "</pre>\n<table>\n"; files=1 }
743 else { print }
744 }
745 break
746 }
747 }'
748 echo "<hr />"
749 git -C "${1}" show "${2}" --format="" | html_encode | awk -v flist="${git_commit_files}" '
750 BEGIN {
751 indiff=0; files=0; h=0; l=0 split(flist, farr, "\n");
752 for (i in farr) {
753 split(farr[i], ftmp, ":");
754 farr[i,1] = ftmp[1];
755 farr[i,2] = ftmp[2];
756 }
757 print "<pre>"
758 }
759 /^diff --git/ {
760 indiff=1
761 if (match($0, /^diff --git a\/(.*) b\/(.*)$/, m)) {
762 for (i in farr) {
763 if (m[1] == farr[i,2]) {
764 printf "<b>diff --git"
765 printf " a/<a id=\"f%d\" href=\"#f%d\">%s</a>",i,i,m[1]
766 printf " b/<a href=\"#f%d\">%s</a>",i,m[2]
767 printf "</b>\n"
768 if (m[1] != m[2]) {
769 printf "<b class=\"r\">rename %s → ",m[1]
770 printf "%s</b>\n",m[2]
771 }
772 next
773 }
774 }
775 }
776 next
777 }
778 /^@@/ {
779 indiff=0
780 printf "<a href=\"#h%d\" id=\"h%d\" class=\"h\">%s</a>\n",h,h++,$0
781 next
782 }
783 /^\+.*$/ {
784 if (indiff) { next }
785 printf "<a href=\"#l%d\" id=\"l%d\" class=\"i\">%s</a>\n",l,l++,$0
786 next
787 }
788 /^\-.*$/ {
789 if (indiff) { next }
790 printf "<a href=\"#l%d\" id=\"l%d\" class=\"d\">%s</a>\n",l,l++,$0
791 next
792 }
793 {
794 if (indiff) { next }
795 print
796 }
797 END {
798 print "</pre>"
799 }'
800}
801
802render_git_file() {
803 printf '\t<span class="git-file">%s</span>\n\t<hr />\n' "${2}"
804 if git -C "${1}" diff 4b825dc642cb6eb9a060e54bf8d69288fbee4904 \
805 --numstat HEAD -- "${2}" | grep '^-' >/dev/null 2>&1; then
806 printf '\t%s\n' "binary file."
807 else
808 git -C "${1}" cat-file "HEAD:${2}" -p \
809 | html_encode \
810 | awk '
811 BEGIN {
812 print "<pre>"
813 }
814
815 {
816 print "<a class=\"line\" href=\"#l" NR "\" id=\"l" NR "\">" NR "</a>" $0
817 }
818
819 END {
820 print "</pre>"
821 }
822 '
823 fi
824}
825
826render_git_repo() {
827 repo_path="${SITE_GIT_REPO_ROOT}/$2"
828 repo_path_head="${1}/${2}/head.html.tmp"
829 repo_path_log="${1}/${2}/log.html.tmp"
830 repo_path_files="${1}/${2}/files.html.tmp"
831 repo_path_file="${1}/${2}/file"
832 repo_path_commit="${1}/${2}/commit"
833 repo_path_tags="${1}/${2}/tags.html.tmp"
834 repo_path_archive="${1}/${2}/archive"
835 repo_name="${2%.*}"
836 repo_description=""
837 repo_menu="$(
838 printf '<a href="//%s/log.html">Log</a>' "${1}/${2}"
839 printf ' | <a href="//%s/files.html">Files</a>' "${1}/${2}"
840 git -C "${1}/${2}" describe --tags >/dev/null 2>&1 && \
841 printf ' | <a href="//%s/tags.html">Tags</a>' "${1}/${2}"
842 git -C "${1}/${2}" show HEAD:README >/dev/null 2>&1 && \
843 printf ' | <a href="//%s/file/README.html">README</a>' "${1}/${2}"
844 git -C "${1}/${2}" show HEAD:LICENSE >/dev/null 2>&1 && \
845 printf ' | <a href="//%s/file/LICENSE.html">LICENSE</a>' "${1}/${2}"
846 )"
847
848 rsync -a --delete-before "${repo_path}/" "${1}/${2##*/}"
849 git -C "${1}/${2##*/}" --bare update-server-info
850 ln -s "refs" "${1}/${2##*/}/info/refs?service=git-upload-pack"
851
852 repo_description="$(< "${1}/${2}"/description html_encode)"
853
854 # create archive files (for each tag)
855 mkdir "${repo_path_archive}"
856 git -C "${1}/${2}" tag \
857 | xargs -I{} git -C "${1}/${2}" archive \
858 --format=tar.gz --prefix="${repo_name}-{}/" \
859 -o "archive/${repo_name}-{}.tar.gz" "{}"
860
861 # create preview files
862 mkdir "${repo_path_file}"
863 git -C "${1}/${2}" ls-tree \
864 -r --format="%(objectmode)%x0a%(path)" HEAD \
865 | grep '^100[0-9][0-9][0-9]$' -A1 \
866 | grep -v '^--$\|^100[0-9][0-9][0-9]$' \
867 | while read -r file; do
868 file_path="$(echo "${repo_path_file}/${file}" | fix_dot_file)"
869 mkdir -p "${file_path%/*}"
870 render_git_file "${1}/${2}" "${file}" > "${file_path}.html.tmp"
871 done
872
873 # create commit files
874 mkdir "${repo_path_commit}"
875 git -C "${1}/${2}" log --pretty="format:%H" \
876 | grep . \
877 | while read -r file; do
878 file_path="$(echo "${repo_path_commit}/${file}")"
879 mkdir -p "${file_path%/*}"
880 render_git_commit "${1}/${2}" "${file}" > "${file_path}.html.tmp"
881 done
882
883
884 # render common html head
885 awk \
886 -v var_site="$(awk_safe "${1}")" \
887 -v var_repo="$(awk_safe "${2}")" \
888 -v var_logo="$(awk_safe "${SITE_ICON_SVG}")" \
889 -v var_name="$(awk_safe "${repo_name}")" \
890 -v var_description="$(awk_safe "${repo_description}")" \
891 -v var_menu="$(awk_safe "${repo_menu}")" \
892 '
893 {
894 gsub(/\{:site:\}/, var_site)
895 gsub(/\{:repo:\}/, var_repo)
896 gsub(/\{:logo:\}/, var_logo)
897 gsub(/\{:name:\}/, var_name)
898 gsub(/\{:description:\}/, var_description)
899 gsub(/\{:menu:\}/, var_menu)
900 print
901 }
902 ' "${CFG_GIT_HEAD_HTML}" > "${repo_path_head}"
903
904 # render log
905 git -C "${1}/${2}" log \
906 --pretty="format:%ai%n%s%n%an%n%H" \
907 | html_encode \
908 | awk '
909 BEGIN {
910 printf "\t<table id=\"log\">\n"
911 printf "\t\t<tr class=\"nohi\">"
912 printf "<td>Date</td>"
913 printf "<td>Commit message</td>"
914 printf "<td>Author</td>"
915 printf "<td>Commit</td>"
916 printf "</tr>\n"
917 printf "\t\t<tbody>\n"
918 }
919
920 {
921 entry[(NR-1) % 4] = $0
922 if (NR % 4 == 0) {
923 printf "\t\t\t<tr>"
924 for (i = 0; i < 4; i++) {
925 if (i == 1) {
926 printf "<td><a href=\"commit/%s.html\">%s</a></td>",entry[3],entry[i]
927 } else if (i == 3) {
928 printf "<td><a href=\"commit/%s.html\">%*.*s</a></td>",entry[i],8,8,entry[i]
929 } else {
930 printf "<td>%s</td>",entry[i]
931 }
932 }
933 printf "</tr>\n"
934 }
935 }
936
937 END {
938 printf "\t\t</tbody>\n"
939 printf "\t</table>\n"
940 }
941 ' > "${repo_path_log}"
942
943 # render files
944 git -C "${1}/${2}" ls-tree \
945 -r --format="%(objectmode)%x0a%(path)%x0a%(objectsize)" HEAD \
946 | html_encode \
947 | fix_dot_file \
948 | awk '
949 function dotrep(data)
950 {
951 output = data
952 gsub(/\/_\./, "/.", output)
953 gsub(/^_\./, ".", output)
954 return output
955 }
956
957 function oct2sym(data)
958 {
959 type = substr(data, 0, 3)
960 if (type == "100") {
961 type = "-"
962 } else if (type == "060") {
963 type = "b"
964 } else if (type == "020") {
965 type = "c"
966 } else if (type == "040") {
967 type = "d"
968 } else if (type == "010") {
969 type = "p"
970 } else if (type == "120") {
971 type = "l"
972 } else if (type == "140") {
973 type = "s"
974 } else {
975 type = "?"
976 }
977
978 sym = substr(data, 4, 3)
979 gsub("0", "---", sym)
980 gsub("1", "--x", sym)
981 gsub("2", "-w-", sym)
982 gsub("3", "-wx", sym)
983 gsub("4", "r--", sym)
984 gsub("5", "r-x", sym)
985 gsub("6", "rw-", sym)
986 gsub("7", "rwx", sym)
987 return type sym
988 }
989
990 BEGIN {
991 printf "\t<table id=\"files\">\n"
992 printf "\t\t<tr class=\"nohi\">"
993 printf "<td>Mode</td>"
994 printf "<td>Name</td>"
995 printf "<td>Size</td>"
996 printf "</tr>\n"
997 printf "\t\t<tbody>\n"
998 }
999
1000 {
1001 entry[(NR-1) % 3] = $0
1002 if (NR % 3 == 0) {
1003 printf "\t\t\t<tr>"
1004 for (i = 0; i < 3; i++) {
1005 if (i == 1 && substr(entry[0], 0, 3) == "100") {
1006 printf "<td><a href=\"file/%s.html\">%s</a></td>", entry[i], dotrep(entry[i])
1007 } else {
1008 printf "<td>%s</td>", i == 0 ? oct2sym(entry[i]) : entry[i]
1009 }
1010 }
1011 printf "</tr>\n"
1012 }
1013 }
1014
1015 END {
1016 printf "\t\t</tbody>\n"
1017 printf "\t</table>\n"
1018 }
1019 ' > "${repo_path_files}"
1020
1021 # render tags
1022 git -C "${1}/${2}" log \
1023 --no-walk --tags --pretty="format:%S%n%ai%n%an%n%h" \
1024 | html_encode \
1025 | awk '
1026 BEGIN {
1027 printf "\t<table id=\"tags\">\n"
1028 printf "\t\t<tr class=\"nohi\">"
1029 printf "<td>Name</td>"
1030 printf "<td>Date</td>"
1031 printf "<td>Author</td>"
1032 printf "<td>Commit</td>"
1033 printf "</tr>\n"
1034 printf "\t\t<tbody>\n"
1035 }
1036
1037 {
1038 entry[(NR-1) % 4] = $0
1039 if (NR % 4 == 0) {
1040 printf "\t\t\t<tr>"
1041 for (i = 0; i < 4; i++) {
1042 if (i == 0) {
1043 printf "<td><a href=\"./archive/__REPONAME__-%s.tar.gz\">%s</a></td>",entry[i],entry[i]
1044 } else {
1045 printf "<td>%s</td>",entry[i]
1046 }
1047 }
1048 printf "</tr>\n"
1049 }
1050 }
1051
1052 END {
1053 printf "\t\t</tbody>\n"
1054 printf "\t</table>\n"
1055 }
1056 ' | sed "s/__REPONAME__/${repo_name}/g" > "${repo_path_tags}"
1057
1058 # create redirection to README if it exists, else symlink to log
1059 git -C "${1}/${2}" show HEAD:README >/dev/null 2>&1 && \
1060 printf '<meta http-equiv="refresh" content="0; url=%s" />' \
1061 "${repo_path_file##*/}/README.html" \
1062 > "${1}/${2}/index.html"
1063
1064 [ ! -f "${1}/${2}/index.html" ] && ln -s "log.html" "${1}/${2}/index.html"
1065}
1066
1067render_git() {
1068 git_repos=
1069 git_forks=
1070 git_discs=
1071 git_buffer=
1072 git_pp=
1073 git_owner=
1074 git_description=
1075 git_index="${1}/index.html"
1076
1077 for repo in "${SITE_GIT_REPO_ROOT}"/*; do
1078 git_pp="${repo##*/}"
1079 git_pp="${git_pp%.*}"
1080 print_loading "Rendering repo ${git_pp}"
1081 git_owner="$(< "${repo}"/owner html_encode)"
1082 git_description="$(< "${repo}"/description html_encode)"
1083 git_buffer=$(
1084 printf '<tr><td><a href="%s">%s</a></td><td>%s</td><td>%s</td><td>%s</td></tr>' \
1085 "//${1}/${repo##*/}" \
1086 "${git_pp}" \
1087 "${git_description}" \
1088 "${git_owner}" \
1089 "$(git -C "${repo}" log -1 --format=%ai)")
1090
1091 if [ -f "$repo/fork" ]; then
1092 git_forks="$(printf '%s%s' "${git_forks}" "${git_buffer}")"
1093 elif [ -f "$repo/discontinued" ]; then
1094 git_discs="$(printf '%s%s' "${git_discs}" "${git_buffer}")"
1095 else
1096 git_repos="$(printf '%s%s' "${git_repos}" "${git_buffer}")"
1097 fi
1098
1099 render_git_repo "${1}" "${repo##*/}"
1100 print_done
1101 done
1102
1103 awk \
1104 -v var_author="$(awk_safe "${SITE_AUTHOR}")" \
1105 -v var_title="$(awk_safe "Repositories")" \
1106 -v var_favicon="$(awk_safe "${SITE_ICON_PNG}")" \
1107 -v var_stylesheet="$(awk_safe "${SITE_CSS}")" \
1108 -v var_logo="$(awk_safe "${SITE_ICON_SVG}")" \
1109 -v var_repos="$(awk_safe "${git_repos}" | sed 's/<tr>/\n\0/2g')" \
1110 -v var_forks="$(awk_safe "${git_forks}" | sed 's/<tr>/\n\0/2g')" \
1111 -v var_discs="$(awk_safe "${git_discs}" | sed 's/<tr>/\n\0/2g')" \
1112 '
1113 /\{:repos:\}/{
1114 padding=$0
1115 gsub(/{:.*:}$/, "", padding)
1116 gsub(/\n/, "\n" padding, var_repos)
1117 }
1118
1119 /\{:forks:\}/{
1120 padding=$0
1121 gsub(/{:.*:}$/, "", padding)
1122 gsub(/\n/, "\n" padding, var_forks)
1123 }
1124
1125 /\{:discs:\}/{
1126 padding=$0
1127 gsub(/{:.*:}$/, "", padding)
1128 gsub(/\n/, "\n" padding, var_dics)
1129 }
1130
1131 {
1132 gsub(/\{:author:\}/, var_author)
1133 gsub(/\{:title:\}/, var_title)
1134 gsub(/\{:favicon:\}/, var_favicon)
1135 gsub(/\{:stylesheet:\}/, var_stylesheet)
1136 gsub(/\{:logo:\}/, var_logo)
1137 gsub(/\{:repos:\}/, var_repos)
1138 gsub(/\{:forks:\}/, var_forks)
1139 gsub(/\{:discs:\}/, var_discs)
1140 print
1141 }
1142 ' "${CFG_GIT_REPOS_HTML}" > "${git_index}"
1143
1144 # complete html-files from html.tmp files
1145 find "${1}" -mindepth 2 -type f -name "*.html.tmp" | while read -r file; do
1146 [ "${file##*/}" = "head.html.tmp" ] && continue
1147 {
1148 awk '1;/<body>/{exit}' "${git_index}"
1149 cat "${file%%.git/*}.git/head.html.tmp"
1150 cat "${file}"
1151 awk '/<\/body>/,0' "${git_index}"
1152 } > "${file%.*}"
1153 done
1154
1155 # remove all html.tmp files
1156 find "${1}" -mindepth 2 -type f -name "*.html.tmp" -exec rm -f {} \;
1157}
1158
1159render_git_commits() {
1160 _tmp_file="$(mktemp "${TMPDIR:-/tmp/}$(basename "$0").repolog.XXXXXX")"
1161
1162 for repo in "${SITE_GIT_REPO_ROOT}"/*; do
1163 a=${repo##*/}
1164 c="//${1}/git/${a}/commit"
1165 a="<a href=\"//${1}/git/${a}\">${a%.*}</a>"
1166 git -C "${repo}" log -n "${SITE_GIT_COMMIT_COUNT}" \
1167 --no-merges \
1168 --pretty="format:%at:%ai [$a] <a href=\"$c/%H.html\">%s</a>"
1169 echo
1170 done \
1171 | sort -r \
1172 | sed "${SITE_GIT_COMMIT_COUNT}q" \
1173 | sed -e 's/^[^:]*://g' \
1174 | awk -v var_domain="$1" '
1175 BEGIN {
1176 print "<ul class=\"repo-log\">";
1177 }
1178
1179 {
1180 printf "<li><span class=\"log-date\">%s %s %s</span>",$1,$2,$3;
1181 $1=$2=$3="";
1182 $0=$0;
1183 }
1184
1185 NF=NF {
1186 printf "%s</li>\n",$0
1187 }
1188
1189 END {
1190 printf "<li>[<a href=\"//%s/git/\">...</a>]</li></ul>\n",var_domain
1191 }
1192 ' > "${_tmp_file}"
1193
1194 find "${1}" -type f -name 'index.html' -exec \
1195 sed -i {} -e "
1196 /^.*<!--placeholder:${SITE_GIT_COMMIT_PH}-->.*$/ {
1197 r ${_tmp_file}
1198 d
1199 }
1200 " \;
1201
1202 rm -f "${_tmp_file}"
1203}
1204
1205generate_sitemap() {
1206 _sitemap="${1}/pub/sitemap.xml"
1207
1208 awk \
1209 -v var_items="$(
1210 find -L "${1}" -type f -name 'index.html' \
1211 | html_encode \
1212 | awk \
1213 -v format_item="$(cat "${CFG_SITEMAP_XML_ITEM}")\n" \
1214 '
1215 {
1216 gsub(/[^\/]*$/, "")
1217 printf format_item, $0
1218 }
1219 ' | awk_safe
1220 )" \
1221 '
1222 {
1223 gsub(/\{:items:\}/, var_items)
1224 print
1225 }
1226 ' "${CFG_SITEMAP_XML}" > "${_sitemap}"
1227}
1228
1229main() {
1230 # check if build is possible
1231 if [ "$1" = "check" ]; then
1232 [ -d "${SITE_GIT_REPO_ROOT}" ] || exit 50
1233
1234 missing=0
1235 for cmd in tex2svg awk; do
1236 if ! command -v "$cmd" >/dev/null 2>&1; then
1237 echo "ERROR: '$cmd' is missing"
1238 missing=1
1239 fi
1240 done
1241 [ "$missing" -eq 0 ] || exit 52
1242 fi
1243
1244 # make sure both arguments, if existing, are directories
1245 [ -n "$1" ] && [ ! -d "$1" ] && return
1246 [ -n "$2" ] && [ ! -d "$2" ] && return
1247
1248 if [ -z "$2" ] && [ -z "${BUILDONLY}" ]; then
1249 print_loading "Running the prerequisite script"
1250 # make sure site/git is removed before rendering (to avoid it in menu)
1251 rm -rf "${1}/git"
1252
1253 # make sure tag pages are removed before creating them
1254 rm -rf "${1}"/articles/tags
1255
1256 # create tags directory
1257 mkdir -p "${1}"/articles/tags
1258 touch "${1}"/articles/tags/.buildignore
1259 echo "index.html" > "${1}"/articles/tags/.assemble
1260 echo ".ds TITLE Tags" > "${1}"/articles/tags/.metadata
1261
1262 printf '.DIVS wrap-list\n.ULS\n' > "${1}"/articles/tags/index.www
1263 # manage tags
1264 find "${1}"/articles -name .tags -exec cat {} \; | sort -u | while read -r tag
1265 do
1266 tag_safe="$(echo "${tag}" | tr \ _)"
1267 mkdir -p "${1}"/articles/tags/"${tag_safe}"
1268 touch "${1}"/articles/tags/"${tag_safe}"/.buildignore
1269 [ "${tag}" != "${CFG_PINNED_TAG}" ] && \
1270 printf '.URL ../.. Articles\ntagged "%s"\n' "${tag}" > "${1}"/articles/tags/"${tag_safe}"/index.www
1271 echo "{:articles#${tag}:}" >> "${1}"/articles/tags/"${tag_safe}"/index.www
1272 echo "index.html" > "${1}"/articles/tags/"${tag_safe}"/.assemble
1273 echo ".ds TITLE #${tag}" > "${1}"/articles/tags/"${tag_safe}"/.metadata
1274
1275 if [ "${tag}" != "${CFG_PINNED_TAG}" ]; then
1276 # append tag to tags page
1277 printf '.LI\n.ARTTAG "%s" "%s" "%s"\n' \
1278 "${tag_safe}" "${tag}" \
1279 "$(grep "^${tag}$" "${1}"/articles/*/.tags | wc -l)" \
1280 >> "${1}"/articles/tags/index.www
1281 fi
1282 done
1283 printf '.ULE\n' >> "${1}"/articles/tags/index.www
1284 printf '.DIVE\n' >> "${1}"/articles/tags/index.www
1285 print_done
1286
1287 # main render, executes sub render (see below)
1288 find "$1" -depth -type d \
1289 -exec test -e '{}/index.www' \; \
1290 -exec "$0" "$1" {} \;
1291
1292 # render git commits into place holders
1293 print_loading "Rendering git commits"
1294 render_git_commits "$1"
1295 print_done
1296
1297 # render git
1298 [ "${SKIPGIT-SKIP}" = "SKIP" ] && render_git "git.${1}"
1299
1300 # move git.site to site/git
1301 cp -r "git.${1}" "${1}/git"
1302
1303 # create symlinks for each repo, as such: {repo} -> {repo}.git
1304 find "${1}/git" -type d -name "*.git" \
1305 -execdir sh -c 'ln -s "${1}" "${1%.*}"' sh {} \;
1306
1307 # translate git.site to site/git
1308 print_loading "Translate git site into ./git"
1309 find "${1}/git" -type f -name "*.html" | while read -r file; do
1310 sed -i "s,\"//\[site\]/,\"//[site]/git/,g" "$file"
1311 sed -i "s,\"//git.${1}/,\"//${1}/git/,g" "$file"
1312 sed -i "s,https://git.${1}/,https://${1}/git/,g" "$file"
1313 sed -i "s,\"//\[root\]/,\"//[site]/,g" "$file"
1314 done
1315 print_done
1316
1317 # convert absolute paths to relative, so that they work with IPFS
1318 print_loading "Converting absolute paths to relative"
1319 find "${1}" -type f -name "*.html" | while read -r file; do
1320 count="$(echo "$file" | tr -cd '/' | wc -c)"
1321 sed -i "s,\"//\(${1}\|\[site\]\)/,\"$(
1322 seq -f "../%g" -s '' 2 "$count" | sed 's/[0-9]//g'
1323 ),g" "$file"
1324
1325 # remove redundant prefix from references
1326 grep -o '="../[^"]*"' "$file" \
1327 | sed -e 's/^="//g' -e 's/"$//g' | while read -r path; do
1328 rel="$(realpath --relative-to="${file%/*}" "${file%/*}/${path}")"
1329 rel="$(echo $rel | sed \
1330 -e 's/\./\\./g' \
1331 -e 's/\&/\\&/g' \
1332 )"
1333 ref="$(echo $path | sed \
1334 -e 's/\./\\./g' \
1335 -e 's/\&/\\&/g' \
1336 )"
1337 sed "s,=\"$ref\",=\"$rel\",g" -i "$file"
1338 done
1339
1340 done
1341 print_done
1342
1343 # generate sitemaps
1344 print_loading "Generating sitemaps"
1345 generate_sitemap "${1}"
1346 print_done
1347 elif [ -z "$2" ] && [ ! -z "${BUILDONLY}" ]; then
1348
1349 render_main "$1" "${BUILDONLY}"
1350
1351 # convert absolute paths to relative, so that they work with IPFS
1352 print_loading "Converting absolute paths to relative"
1353 find "${BUILDONLY}" -type f -name "*.html" | while read -r file; do
1354 count="$(echo "$file" | tr -cd '/' | wc -c)"
1355 sed -i "s,\"//\(${1}\|\[site\]\)/,\"$(
1356 seq -f "../%g" -s '' 2 "$count" | sed 's/[0-9]//g'
1357 ),g" "$file"
1358
1359 # remove redundant prefix from references
1360 grep -o '="../[^"]*"' "$file" \
1361 | sed -e 's/^="//g' -e 's/"$//g' | while read -r path; do
1362 rel="$(realpath --relative-to="${file%/*}" "${file%/*}/${path}")"
1363 rel="$(echo $rel | sed \
1364 -e 's/\./\\./g' \
1365 -e 's/\&/\\&/g' \
1366 )"
1367 ref="$(echo $path | sed \
1368 -e 's/\./\\./g' \
1369 -e 's/\&/\\&/g' \
1370 )"
1371 sed "s,=\"$ref\",=\"$rel\",g" -i "$file"
1372 done
1373
1374 done
1375 print_done
1376
1377 elif [ -n "$2" ]; then
1378 [ ! -z ${BUILDONLY} ] && [ "${BUILDONLY}" != "${2}" ] && return
1379
1380 # sub render
1381 render_main "$1" "$2"
1382 fi
1383}
1384
1385main "${1:-$SITE_DOMAIN}" "$2"