website/build.sh

184 lines
5.4 KiB
Bash
Raw Permalink Normal View History

2022-11-29 11:58:16 -06:00
#!/bin/sh
2024-03-13 20:37:38 -05:00
__BASE="${SHP_BASE:-"$PWD"}"
export _INCDIR="${SHP_INCDIR:-"${__BASE}/include"}"
export _BUILDDIR="${SHP_BUILDDIR:-"${__BASE}/build"}"
export _SRCDIR="${SHP_SRCDIR:-"${__BASE}/src"}"
2024-04-02 15:48:49 -05:00
export _NL="
2023-11-16 22:10:51 -06:00
"
2022-11-29 11:58:16 -06:00
2023-11-20 17:39:34 -06:00
# process an html formatted file either given or from stdin and output to stdout
# if a file is given, stdin is free to be used by any shp files it encounters
2023-11-16 22:10:51 -06:00
__process_shp() {
__SHLVL=$((__SHLVL + 1))
eval '__SH_FLAG'$__SHLVL'=""
__LINE_EXEC_'$__SHLVL'=""
2024-03-13 20:37:38 -05:00
while IFS= read -r __LINE'$__SHLVL'; do
2023-11-16 22:10:51 -06:00
if [ -z "$__SH_FLAG'$__SHLVL'" ]; then
case "$__LINE'$__SHLVL'" in
*"<?shp"*)
printf "%s" "${__LINE'$__SHLVL'%%<\?shp*}"
__LINE'$__SHLVL'="${__LINE'$__SHLVL'#*<\?shp}"
__SH_FLAG'$__SHLVL'=1
2023-11-12 23:03:02 -06:00
;;
2023-11-16 22:10:51 -06:00
*) echo "$__LINE'$__SHLVL'" ;;
2023-11-12 23:03:02 -06:00
esac
fi
2023-11-16 22:10:51 -06:00
if [ -n "$__SH_FLAG'$__SHLVL'" ]; then
2024-04-02 15:48:49 -05:00
__LINE_EXEC_'$__SHLVL'="$__LINE_EXEC_'$__SHLVL'$_NL$__LINE'$__SHLVL'"
2023-11-16 22:10:51 -06:00
case "$__LINE'$__SHLVL'" in
2023-11-12 23:03:02 -06:00
*"?>"*)
2023-11-16 22:10:51 -06:00
eval "${__LINE_EXEC_'$__SHLVL'%%\?>*}"
2024-03-16 03:33:36 -05:00
printf "%s" "${__LINE'$__SHLVL'#*\?>}"
2023-11-16 22:10:51 -06:00
__SH_FLAG'$__SHLVL'=""
__LINE_EXEC_'$__SHLVL'=""
2023-11-12 23:03:02 -06:00
;;
*) ;;
esac
fi
2024-03-16 03:33:36 -05:00
done '"${1:+"< \"\$1\""}"'
2023-11-16 22:10:51 -06:00
[ $__SH_FLAG'$__SHLVL' ] && eval "$__LINE_EXEC_'$__SHLVL'"'
__SHLVL=$((__SHLVL - 1))
2023-07-01 18:43:30 -05:00
}
2023-11-20 17:39:34 -06:00
__SHLVL=0
2023-07-01 18:43:30 -05:00
2024-04-03 10:21:25 -05:00
# lowdown wrapper function
__lowdown() {
lowdown --html-no-owasp --html-no-skiphtml --html-no-escapehtml --html-no-num-ent "$@" | \
sed -E '
s/&[lr]squo;/\&apos;/g
s/&ndash;/--/g
s/&[lr]dquo;/\&quot;/g
'
2024-04-03 10:21:25 -05:00
}
2023-11-16 22:10:51 -06:00
# process a pure markdown file
2023-11-12 23:03:02 -06:00
# uses a special file in _INCDIR, `markdown-template.sh` to create the html
2023-11-16 22:10:51 -06:00
__process_md() {
2024-03-16 03:33:36 -05:00
eval ' {
2024-03-13 20:37:38 -05:00
set_md_metadata
__process_shp "$_INCDIR"/_markdown-template.shp
2024-03-16 03:33:36 -05:00
}'"${1:+"< \"\$1\""}"
}
# to call when including a markdown file because we don't want to *process* the whole thing
__include_md() {
eval ' {
set_md_metadata
__lowdown
}'"${1:+"< \"\$1\""}"
}
2023-11-16 22:10:51 -06:00
# standard library
include() {
# if the path contains a slash, then treat it as-is
# else, try getting it from $_INCDIR
case "$1" in
*/*.md) __include_md "$1" ;;
*.md) __include_md "$_INCDIR"/"$1" ;;
2023-11-20 17:39:34 -06:00
*/*) __process_shp "$1" ;;
*) __process_shp "$_INCDIR"/"$1" ;;
2023-07-01 18:43:30 -05:00
esac
2023-11-16 22:10:51 -06:00
}
2024-03-13 20:37:38 -05:00
# set markdown metadata either given or from stdin
# why do we have this big eval here--why not use /dev/stdin?
# using /dev/stdin makes the input behave Very Weirdly, I can't really explain
# what is going on but it just doesn't work how one would expect
# this eval prevents a lengthy if-else statement
2024-03-16 03:33:36 -05:00
# I adapted this method to all other stuff that either accepts stdin or an argument
# for maximum portability, I guess. even though every relevant unix has /dev/stdin
# I guess it's paranoia for the accidentally swallowing stdin thing as well. whatever
2023-11-20 17:39:34 -06:00
set_md_metadata() {
2024-03-13 20:37:38 -05:00
eval ' {
# if 1st line isnt all -, skip setting metadata
IFS= read -r __first
case "$__first" in
2024-03-13 20:37:38 -05:00
*[!-]*) return ;;
2023-11-16 22:10:51 -06:00
esac
2024-03-13 20:37:38 -05:00
while IFS=" =" read -r __key __val; do
case "$__key" in
*[!-]*) eval "$__key=\$__val" ;;
*) return ;;
esac
done
} '"${1:+"< \"\$1\""}"
2023-11-16 22:10:51 -06:00
}
2024-03-13 20:37:38 -05:00
# good for inputs without many chars to escape
# so most titles, strings, etc.
# this is why it only accepts an argument and not stdin
2023-11-16 22:10:51 -06:00
escape() {
2024-03-13 20:37:38 -05:00
__ESC_STR=$*
# do this first to not create an infinite loop
while :; do
case "$__ESC_STR" in
*\&*) __ESC_STR_INT="${__ESC_STR%%&*}&amp;"; __ESC_STR="${__ESC_STR#*&}" ;;
*) __ESC_STR_INT="$__ESC_STR_INT$__ESC_STR"; break ;;
esac
done
__ESC_STR=$__ESC_STR_INT
while :; do
case "$__ESC_STR" in
*\<*) __ESC_STR="${__ESC_STR%<*}&lt;${__ESC_STR##*<}" ;;
*\>*) __ESC_STR="${__ESC_STR%>*}&gt;${__ESC_STR##*>}" ;;
*\"*) __ESC_STR="${__ESC_STR%\"*}&quot;${__ESC_STR##*\"}" ;;
*\'*) __ESC_STR="${__ESC_STR%\'*}&apos;${__ESC_STR##*\'}" ;;
2024-03-13 20:37:38 -05:00
*) break;
esac
done
printf '%s\n' "$__ESC_STR"
}
# good for large inputs with lots of chars to escape
# this means mostly full files, entire posts for putting in content for a feed
escapepipe() {
sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g' -e 's/"/\&quot;/g' -e "s/'/\\&apos;/g"
2023-11-16 22:10:51 -06:00
}
2024-03-16 03:33:36 -05:00
# build folder structure
2023-11-20 17:39:34 -06:00
find "$_SRCDIR" -type d -exec sh -c 'for d; do mkdir -p "$_BUILDDIR"/"${d#"$_SRCDIR"}"; done' sh {} +
# it's parallel time baby
# hopefully portable enough to not be an issue
__THREADS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null)"
[ $? -ne 0 ] \
&& echo 'unable to find number of cores! defaulting to 1 thread unless otherwise specified...' >&2 \
&& __THREADS=1
# make a parallel fifo/file descriptor we need
__fifo_para="$(mktemp -u -t "shpbuild.XXXXXX")"
mkfifo "$__fifo_para"
exec 9<>"$__fifo_para"
rm -f "$__fifo_para"
while [ "$__THREADS" -gt 0 ]; do
printf "\n" >&9 # start with THREADS amount of lines in fd 9 for later
__THREADS="$((__THREADS - 1))"
done
# read each line from fd 9, launch new program for each line
# print a line after program finished such that another one can take its place
__run_in_parallel() {
read -r __ <&9
{
"$@"
printf '\n' >&9
} &
}
while IFS= read -r _FILE; do
2024-01-02 17:30:37 -06:00
cd "${_FILE%/*}"
2024-04-03 03:18:21 -05:00
export _OUTFILE="$_BUILDDIR/${_FILE#"$_SRCDIR/"}"
2024-01-02 17:30:37 -06:00
case "${_FILE##*/}" in
2024-04-03 03:18:21 -05:00
*.[hH][tT][mM][lL]|*.[sS][hH][pP]) ( __run_in_parallel __process_shp "$_FILE" ) > "${_OUTFILE%.*}.html" ;;
*.[mM][dD]) ( __run_in_parallel __process_md "$_FILE" ) > "${_OUTFILE%.*}.html" ;;
*.[sS][hH]) ( __run_in_parallel . "$_FILE" ) ;; # don't autocopy. this is for code :)
2024-04-03 03:18:21 -05:00
*) __run_in_parallel cp -p "$_FILE" "$_OUTFILE" ;;
2023-11-16 22:10:51 -06:00
esac
done <<-EOF
2023-11-12 23:03:02 -06:00
$(find "$_SRCDIR" -type f)
EOF
2023-11-16 22:10:51 -06:00
[ -f "$_INCDIR/_postbuild.sh" ] && . "$_INCDIR/_postbuild.sh"