HandBrake-docs/build-docs
2016-04-13 17:06:40 -04:00

224 lines
8.5 KiB
Bash
Executable File

#!/bin/bash
# vars
SELF="${BASH_SOURCE[0]}"
BASE_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)
BASE_DIR="${BASE_DIR:-$(pwd)}"
CONFIG="${BASE_DIR}/config.yaml"
DOCS_DIR="${BASE_DIR}/docs"
SOURCE_DIR="${BASE_DIR}/source"
TEMPLATE_DIR="${BASE_DIR}/templates"
TOOLS_DIR="${BASE_DIR}/tools"
# dependencies
MARKDOWN="${BASE_DIR}/tools/discount/markdown"
DEPS=("${MARKDOWN}")
# optional dependencies
PARALLEL=$(which parallel)
# creates bash variables from yaml records
# https://gist.github.com/pkuczynski/8665367
function parse_yaml {
local prefix=$2
local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 |
awk -F$fs '{
indent = length($1)/2;
vname[indent] = $2;
for (i in vname) {if (i > indent) {delete vname[i]}}
if (length($3) > 0) {
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
}
}'
}
# checks for required external tools
function check_dependencies { # takes 1 argument
local DEPS ERROR
DEPS=("${1}");
ERROR=false
for DEP in ${DEPS[@]}; do
if echo "${DEP}" | grep '/' >/dev/null 2>&1 && [[ ! -x "${DEP}" ]]; then
ERROR=true
elif ! hash "${DEP}" >/dev/null 2>&1; then
ERROR=true
fi
done
if [[ "${ERROR}" == true ]]; then
echo "Error: Unable to find command '${DEP#$BASE_DIR/}'." >&2
return 1
fi
}
# builds document(s) from a single source file
function build_source {
local SOURCE BASE_RELPATH DEST DEST_NAME YAML DOCUMENT_Title DOCUMENT_Project DOCUMENT_Project_URL DOCUMENT_Project_Version DOCUMENT_Language DOCUMENT_Language_Code DOCUMENT_Text_Encoding DOCUMENT_Authors DOCUMENT_Copyright DOCUMENT_License DOCUMENT_License_URL DOCUMENT_Redirect_URL DOCUMENT_Content TEMPLATE_Scripts TEMPLATE_Styles
SOURCE="${1}"
BASE_RELPATH="${SOURCE#$DOCS_DIR/}" # strip abs prefix
BASE_RELPATH="${BASE_RELPATH//[^\/]}" # leave only slashes
BASE_RELPATH="${BASE_RELPATH//[\/]/../}" # slashes to dirs
DEST="${SOURCE%.markdown}"
DEST_NAME="${DEST##*/}"
DOCUMENT_Content="${DEST}.html.temp"
# check for yaml header
YAML=false
if head -n 1 "${SOURCE}" | grep '^---$' >/dev/null 2>&1; then
YAML=true
fi
if [[ "${YAML}" == true ]]; then
# split yaml and markdown
awk '{ drop = 0; } /^---$/ { if (NR==1) { drop = 1 } else if (NR>1) { exit } else { drop = 0; next } } drop == 0 { print }' "${SOURCE}" > "${DEST}.yaml"
mv "${SOURCE}" "${DEST}.markdown.temp"
tail -n +$(wc -l "${DEST}.yaml" | awk '{ print $1+3 }') "${DEST}.markdown.temp" > "${SOURCE}"
rm -f "${DEST}.markdown.temp"
# parse yaml
eval $(parse_yaml "${DEST}.yaml" "DOCUMENT_")
fi
# process authors
DOCUMENT_Authors=$(echo "${DOCUMENT_Authors}" | sed -e 's/,[^ ]/, /g' -e 's/[ ]*<[^,]*>//g' -e 's/\(.*\), /\1, and /')
DELIM_NUM=$(grep -o ',' <<< "${DOCUMENT_Authors}" | wc -l)
if [[ "${DELIM_NUM}" -eq 1 ]]; then
DOCUMENT_Authors=$(echo "${DOCUMENT_Authors}" | sed -e 's/,//')
fi
# preprocess markdown to add implicit figures
sed -E \
-e 's|^!\[(.+)]\([ ]*(.+)[ ]*"(.+)"[ ]*\)$|<figure><a href="\2"><img src="\2" alt="\1" /></a><figcaption>\3</figcaption></figure>|' \
-i.sedbak "${SOURCE}"
# convert preprocessed markdown document to html
"${MARKDOWN}" -fdlextra -ffencedcode -ffootnote -fgithubtags "${SOURCE}" > "${DOCUMENT_Content}"
# copy main template
if [[ "${DOCUMENT_Redirect_URL:-}" != "" ]]; then
cp "${TEMPLATE_Redirect}" "${DEST}.html"
else
cp "${TEMPLATE_Base}" "${DEST}.html"
fi
# inject meta, title, styles, document, scripts
sed -E \
-e '/\{\{[ ]*template\.meta[ ]*\}\}/{r '"${TEMPLATE_Meta}" -e 'd;}' \
-e '/\{\{[ ]*template\.title[ ]*\}\}/{r '"${TEMPLATE_Title}" -e 'd;}' \
-e '/\{\{[ ]*template\.document[ ]*\}\}/{r '"${TEMPLATE_Document}" -e 'd;}' \
-i.sedbak "${DEST}.html"
# omit header and footer templates from license documents
if [[ "${DEST_NAME}" == "license" ]] || [[ "${DEST_NAME}" == "license-summary" ]]; then
sed -E \
-e 's|\{\{[ ]*template\.header[ ]*\}\}||g' \
-e 's|\{\{[ ]*template\.footer[ ]*\}\}||g' \
-i.sedbak "${DEST}.html"
fi
# inject header, content, footer
sed -E \
-e '/\{\{[ ]*template\.header[ ]*\}\}/{r '"${TEMPLATE_Header}" -e 'd;}' \
-e '/\{\{[ ]*document\.content[ ]*\}\}/{r '"${DOCUMENT_Content}" -e 'd;}' \
-e '/\{\{[ ]*template\.footer[ ]*\}\}/{r '"${TEMPLATE_Footer}" -e 'd;}' \
-i.sedbak "${DEST}.html"
# process custom tags
TEMPLATE_Scripts=""
for SCRIPT in ${TEMPLATE_Scripts_array[@]}; do
TEMPLATE_Scripts+="<script src=\"${BASE_RELPATH}${SCRIPT}\" charset=\"utf-8\"></script>"
done
TEMPLATE_Styles=""
for STYLE in ${TEMPLATE_Styles_array[@]}; do
TEMPLATE_Styles+="<link rel=\"stylesheet\" href=\"${BASE_RELPATH}${STYLE}\" />"
done
sed -E \
-e 's|\{\{[ ]*template\.scripts[ ]*\}\}|'"${TEMPLATE_Scripts:-}"'|g' \
-e 's|\{\{[ ]*template\.styles[ ]*\}\}|'"${TEMPLATE_Styles:-}"'|g' \
-e 's|\{\{[ ]*document\.title[ ]*\}\}|'"${DOCUMENT_Title:-}"'|g' \
-e 's|\{\{[ ]*document\.project[ ]*\}\}|'"${DOCUMENT_Project:-}"'|g' \
-e 's|\{\{[ ]*document\.project-url[ ]*\}\}|'"${DOCUMENT_Project_URL:-}"'|g' \
-e 's|\{\{[ ]*document\.project-version[ ]*\}\}|'"${DOCUMENT_Project_Version:-}"'|g' \
-e 's|\{\{[ ]*document\.language[ ]*\}\}|'"${DOCUMENT_Language:-}"'|g' \
-e 's|\{\{[ ]*document\.language-code[ ]*\}\}|'"${DOCUMENT_Language_Code:-}"'|g' \
-e 's|\{\{[ ]*document\.text-encoding[ ]*\}\}|'"${DOCUMENT_Text_Encoding:-}"'|g' \
-e 's|\{\{[ ]*document\.authors[ ]*\}\}|'"${DOCUMENT_Authors:-}"'|g' \
-e 's|\{\{[ ]*document\.copyright[ ]*\}\}|'"${DOCUMENT_Copyright:-}"'|g' \
-e 's|\{\{[ ]*document\.license[ ]*\}\}|'"${DOCUMENT_License:-}"'|g' \
-e 's|\{\{[ ]*document\.license-abbr[ ]*\}\}|'"${DOCUMENT_License_Abbr:-}"'|g' \
-e 's|\{\{[ ]*document\.license-url[ ]*\}\}|'"${DOCUMENT_License_URL:-}"'|g' \
-e 's|\{\{[ ]*document\.redirect-url[ ]*\}\}|'"${DOCUMENT_Redirect_URL:-}"'|g' \
-e 's|\{\{[ ]*base\.relpath[ ]*\}\}|'"${BASE_RELPATH:-}"'|g' \
-i.sedbak "${DEST}.html"
# postprocess
sed -E \
-e 's|<p><figure>|<figure>|' \
-e 's|</figure></p>|</figure>|' \
-i.sedbak "${DEST}.html"
# clean up
rm -f "${DEST}.yaml"
rm -f "${DEST}.markdown"
rm -f "${DEST}.markdown.sedbak"
rm -f "${DEST}.html.temp"
rm -f "${DEST}.html.sedbak"
}
# base directory (absolute)
cd "${BASE_DIR}"
# check deps
check_dependencies "${DEPS[@]}" || exit 1
# parse config
if [[ -e "${CONFIG}" ]]; then
eval $(parse_yaml "${CONFIG}" "CONFIG_")
else
echo "Configuration file not found." >&2
exit 1
fi
# parse template config
TEMPLATE_DIR+="/${CONFIG_Template}"
TEMPLATE_CONFIG="${TEMPLATE_DIR}/template.yaml"
if [[ -e "${TEMPLATE_CONFIG}" ]]; then
eval $(parse_yaml "${TEMPLATE_CONFIG}" "TEMPLATE_")
TEMPLATE_Base="${TEMPLATE_DIR}/${TEMPLATE_Base}"
TEMPLATE_Meta="${TEMPLATE_DIR}/${TEMPLATE_Meta}"
TEMPLATE_Title="${TEMPLATE_DIR}/${TEMPLATE_Title}"
TEMPLATE_Document="${TEMPLATE_DIR}/${TEMPLATE_Document}"
TEMPLATE_Header="${TEMPLATE_DIR}/${TEMPLATE_Header}"
TEMPLATE_Footer="${TEMPLATE_DIR}/${TEMPLATE_Footer}"
TEMPLATE_Redirect="${TEMPLATE_DIR}/${TEMPLATE_Redirect}"
TEMPLATE_Fonts_array=($(echo "${TEMPLATE_Fonts}" | sed -e "s/,[ ]*/ /g"))
TEMPLATE_Scripts_array=($(echo "${TEMPLATE_Scripts}" | sed -e "s/,[ ]*/ /g"))
TEMPLATE_Styles_array=($(echo "${TEMPLATE_Styles}" | sed -e "s/,[ ]*/ /g"))
else
echo "Template configuration file not found." >&2
exit 1
fi
# build single
if [[ "${1:-}" != "" ]]; then
build_source "${1}"
exit 0
fi
# build all
mkdir -p "${DOCS_DIR}"
$(GLOBIGNORE='*.gitkeep'; rm -rf "${DOCS_DIR}"/*)
cp -R "${SOURCE_DIR}"/* "${DOCS_DIR}"/
for REF in ${TEMPLATE_Fonts_array[@]} ${TEMPLATE_Scripts_array[@]} ${TEMPLATE_Styles_array[@]}; do
FILE="${REF%\?*}"
mkdir -p "${DOCS_DIR}/${FILE%/*}"
cp "${TEMPLATE_DIR}/${FILE}" "${DOCS_DIR}/${FILE}"
done
SOURCES=($(find "${DOCS_DIR}" | sed 's/^\.\///' | grep -i '.markdown'))
if [[ "${PARALLEL:-}" != "" ]]; then
export -f build_source
"${PARALLEL}" "${SELF}" ::: "${SOURCES[@]}"
else
for SOURCE in ${SOURCES[@]}; do
build_source "${SOURCE}"
done
fi
# done
exit 0