#!/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}") # 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/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 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 SOURCE="${1}" 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 # preprocess markdown to add implicit figures sed -E \ -e 's|^!\[(.+)]\([ ]*(.+)[ ]*"(.+)"[ ]*\)$|
\1
\3
|' \ -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_Document}" "${DEST}.html" fi # 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 sed -E \ -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|

|
|' \ -e 's|

|
|' \ -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 # check template TEMPLATE_DIR+="/${CONFIG_Template}" if [[ ! -d "${TEMPLATE_DIR}" ]] || [[ ! -e "${TEMPLATE_DIR}/document.html" ]]; then echo "Template '${CONFIG_Template}' not found." >&2 exit 1 fi # template vars TEMPLATE_Document="${TEMPLATE_DIR}/document.html" TEMPLATE_Header="${TEMPLATE_DIR}/header.html" TEMPLATE_Footer="${TEMPLATE_DIR}/footer.html" TEMPLATE_Redirect="${TEMPLATE_DIR}/redirect.html" # clean docs dir mkdir -p "${DOCS_DIR}" $(GLOBIGNORE='*.gitkeep'; rm -rf "${DOCS_DIR}"/*) # build cp -R "${TEMPLATE_DIR}"/css "${TEMPLATE_DIR}"/fonts "${TEMPLATE_DIR}"/js "${SOURCE_DIR}"/* "${DOCS_DIR}"/ SOURCES=($(find "${DOCS_DIR}" | sed 's/^\.\///' | grep -i '.markdown')) for SOURCE in ${SOURCES[@]}; do BASE_RELPATH="${SOURCE#$DOCS_DIR/}" # strip abs prefix BASE_RELPATH="${BASE_RELPATH//[^\/]}" # leave only slashes BASE_RELPATH="${BASE_RELPATH//[\/]/../}" # slashes to dirs build_source "${SOURCE}" done # done exit 0