mirror of
https://github.com/HandBrake/HandBrake-docs.git
synced 2025-12-11 04:35:53 -06:00
315 lines
13 KiB
Bash
Executable File
315 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# vars
|
|
SELF="${BASH_SOURCE[0]}"
|
|
SELF_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)
|
|
SELF_DIR="${SELF_DIR:-$(pwd)}"
|
|
CONFIG="${SELF_DIR}/config.yaml"
|
|
DOCS_DIR="${SELF_DIR}/docs"
|
|
SOURCE_DIR="${SELF_DIR}/source"
|
|
TEMPLATE_DIR="${SELF_DIR}/templates"
|
|
TOOLS_BIN="${SELF_DIR}/tools/local/bin"
|
|
|
|
# dependencies
|
|
MARKDOWN="${TOOLS_BIN}/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 { # check_dependencies $DEP1 $DEP2 ...
|
|
local DEPS ERRORS
|
|
DEPS=("${@}");
|
|
ERRORS=()
|
|
for DEP in ${DEPS[@]}; do
|
|
if echo "${DEP}" | grep '/' >/dev/null 2>&1 && [[ ! -x "${DEP}" ]]; then
|
|
ERRORS+=("${DEP}")
|
|
elif ! hash "${DEP}" >/dev/null 2>&1; then
|
|
ERRORS+=("${DEP}")
|
|
fi
|
|
done
|
|
if [[ "${#ERRORS[@]}" -ne 0 ]]; then
|
|
echo "dependencies: ${DEPS[@]}"
|
|
echo "unable to find command(s): ${ERRORS[*]}" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# transforms a string
|
|
function string_filter {
|
|
local STRING FILTERS
|
|
STRING=("${1}");
|
|
shift 1
|
|
FILTERS=("${@}")
|
|
for FILTER in ${FILTERS[@]}; do
|
|
case "${FILTER}" in
|
|
'slug')
|
|
STRING=$(echo "${STRING}" | sed -E -e 's/[ _]+/-/g' -e 's/[^-a-zA-Z0-9.]//g' -e 's/(^-+)|(-+$)//' | awk '{ print tolower($0) }')
|
|
;;
|
|
esac
|
|
done
|
|
echo -n "${STRING}"
|
|
}
|
|
|
|
# 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 NAVIGATION_PARTIAL NAVIGATION_RELPATH 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
|
|
BASE_RELPATH="${BASE_RELPATH:-./}" # empty to current dir
|
|
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 /' -e 's/\([^,]\) /\1\\\ /g')
|
|
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}"
|
|
# select output type
|
|
if [[ "${CONFIG_Embeddable:-}" != true ]]; then
|
|
if [[ "${DOCUMENT_Redirect_URL:-}" != "" ]]; then
|
|
# full html redirect only
|
|
cp "${TEMPLATE_Redirect}" "${DEST}.html"
|
|
else
|
|
# full html content
|
|
cp "${TEMPLATE_Base}" "${DEST}.html"
|
|
fi
|
|
else
|
|
# partial html
|
|
cp "${TEMPLATE_Document}" "${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"
|
|
# 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"
|
|
# inject nav
|
|
sed -E \
|
|
-e '/\{\{[ ]*template\.nav[ ]*\}\}/{r '"${TEMPLATE_Nav:-}" -e 'd;}' \
|
|
-i.sedbak "${DEST}.html"
|
|
# process includes
|
|
NAVIGATION_PARTIAL="${DOCS_DIR}/$(string_filter \"${DOCUMENT_Language_Code:-.}\" slug)/$(string_filter \"${DOCUMENT_Project_Version:-.}\" slug)/${CONFIG_Navigation%.markdown}.partial.html"
|
|
NAVIGATION_RELPATH="${BASE_RELPATH#../../}"
|
|
if [[ -e "${NAVIGATION_PARTIAL}" ]] && [[ "${DOCUMENT_Type}" == "article" ]]; then
|
|
sed -E \
|
|
-e 's|<h1>([^<]+)</h1>|<h1><a href="'"${NAVIGATION_RELPATH}${CONFIG_Navigation%.markdown}.html"'">\1</a></h1>|' \
|
|
-e 's|(<a href=")([^.])|\1'"${NAVIGATION_RELPATH}"'\2|g' \
|
|
-e 's|<a (href="[^"]*'"${DEST_NAME}.html"'"[^>]*)>([^<>]+)</a>|<a \1 class="selected">\2</a>|g' \
|
|
"${NAVIGATION_PARTIAL}" > "${DEST}.nav.partial.html"
|
|
sed -E \
|
|
-e '/\{\{[ ]*include\.navigation[ ]*\}\}/{r '"${DEST}.nav.partial.html" -e 'd;}' \
|
|
-i.sedbak "${DEST}.html"
|
|
else
|
|
sed -E \
|
|
-e '/\{\{[ ]*include\.navigation[ ]*\}\}/d' \
|
|
-i.sedbak "${DEST}.html"
|
|
fi
|
|
# process template 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\.type[ ]*\}\}|'"${DOCUMENT_Type:-}"'|g' \
|
|
-e 's|\{\{[ ]*document\.project[ ]*\}\}|'"${DOCUMENT_Project:-}"'|g' \
|
|
-e 's|\{\{[ ]*document\.project slug[ ]*\}\}|'$(string_filter "${DOCUMENT_Project:-}" slug)'|g' \
|
|
-e 's|\{\{[ ]*document\.project-url[ ]*\}\}|'"${DOCUMENT_Project_URL:-}"'|g' \
|
|
-e 's|\{\{[ ]*document\.project-version[ ]*\}\}|'"${DOCUMENT_Project_Version:-}"'|g' \
|
|
-e 's|\{\{[ ]*document\.project-version slug[ ]*\}\}|'$(string_filter "${DOCUMENT_Project_Version:-}" slug)'|g' \
|
|
-e 's|\{\{[ ]*document\.language[ ]*\}\}|'"${DOCUMENT_Language:-}"'|g' \
|
|
-e 's|\{\{[ ]*document\.language slug[ ]*\}\}|'$(string_filter "${DOCUMENT_Language:-}" slug)'|g' \
|
|
-e 's|\{\{[ ]*document\.language-code[ ]*\}\}|'"${DOCUMENT_Language_Code:-}"'|g' \
|
|
-e 's|\{\{[ ]*document\.language-code slug[ ]*\}\}|'$(string_filter "${DOCUMENT_Language_Code:-}" slug)'|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\.license-url rel[ ]*\}\}|'"${BASE_RELPATH}${CONFIG_License%.markdown}.html"'|g' \
|
|
-e 's|\{\{[ ]*document\.redirect-url[ ]*\}\}|'"${DOCUMENT_Redirect_URL:-}"'|g' \
|
|
-e 's|\{\{[ ]*base\.relpath[ ]*\}\}|'"${BASE_RELPATH:-}"'|g' \
|
|
-i.sedbak "${DEST}.html"
|
|
# process comment tags
|
|
sed -E \
|
|
-e 's|<!--[ ]*\.([^ ]*)[ ]*-->|<div class="\1">|g' \
|
|
-e 's|<!--[ ]*\#([^ ]*)[ ]*-->|<div id="\1">|g' \
|
|
-e 's|<!--[ ]*\/([.#])([^ ]*)[ ]*-->|</div><!-- /\1\2 -->|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}.nav.partial.html"
|
|
rm -f "${DEST}.html.temp"
|
|
rm -f "${DEST}.html.sedbak"
|
|
|
|
}
|
|
|
|
# base directory (absolute)
|
|
cd "${SELF_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_Nav="${TEMPLATE_DIR}/${TEMPLATE_Nav}"
|
|
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
|
|
if [[ "${1:-}" != "" ]]; then
|
|
# single source
|
|
build_source "${1}"
|
|
else
|
|
# everything
|
|
# assets
|
|
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
|
|
|
|
# navigation
|
|
cd "${SOURCE_DIR}"
|
|
LANGUAGES=()
|
|
while IFS= read -r -d '' x; do
|
|
LANGUAGES+=("$(basename "${x}")")
|
|
done < <(find . -maxdepth 1 -type d -not -name '.*' -print0)
|
|
for LANGUAGE in "${LANGUAGES[@]}"; do
|
|
cd "${LANGUAGE}"
|
|
VERSIONS=()
|
|
while IFS= read -r -d '' x; do
|
|
VERSIONS+=("$(basename "${x}")")
|
|
done < <(find . -maxdepth 1 -type d -not -name '.*' -print0)
|
|
for VERSION in "${VERSIONS[@]}"; do
|
|
cd "${VERSION}"
|
|
if [[ -e "${CONFIG_Navigation}" ]]; then
|
|
NAVIGATION_PARTIAL="${DOCS_DIR}/${LANGUAGE}/${VERSION}/${CONFIG_Navigation%.markdown}.partial.html"
|
|
cp "${CONFIG_Navigation}" "${NAVIGATION_PARTIAL}"
|
|
if head -n 1 "${NAVIGATION_PARTIAL}" | grep '^---$' >/dev/null 2>&1; then
|
|
# remove yaml
|
|
tail -n +$(awk '{ drop = 0; } /^---$/ { if (NR==1) { drop = 1 } else if (NR>1) { exit } else { drop = 0; next } } drop == 0 { print }' "${NAVIGATION_PARTIAL}" | wc -l | awk '{ print $1+3 }') "${NAVIGATION_PARTIAL}" > "${NAVIGATION_PARTIAL}.temp"
|
|
else
|
|
cp "${NAVIGATION_PARTIAL}" "${NAVIGATION_PARTIAL}.temp"
|
|
fi
|
|
"${MARKDOWN}" -fdlextra -ffencedcode -ffootnote -fgithubtags "${NAVIGATION_PARTIAL}.temp" > "${NAVIGATION_PARTIAL}"
|
|
rm -f "${NAVIGATION_PARTIAL}.temp"
|
|
fi
|
|
cd "${SOURCE_DIR}/${LANGUAGE}"
|
|
done
|
|
cd "${SOURCE_DIR}"
|
|
done
|
|
cd "${SELF_DIR}"
|
|
|
|
# sources
|
|
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
|
|
|
|
# clean up
|
|
find "${DOCS_DIR}" -name '*.partial.html' -exec rm -f {} \;
|
|
fi
|
|
|
|
# done
|
|
exit 0
|