#!/usr/bin/env bash # # Convert all the Markdown files in doc/ to HTML. # This requires `kramdown` to be available on the path. # `tidy` and `checklink` (from Debian's w3c-linkchecker package) are used to # test the output and must also be available and on the path. # Run this from the root directory of the repository. # The output directory can be specified as the first option. if [ "$#" -gt 1 ]; then echo "Usage: $0 [output_dir/]"; exit 1; elif [ "$#" -eq 1 ]; then output_dir=$1; else output_dir=doc/html; fi # If the header and footer already exist, they will not be overwritten. template_html_header="${output_dir}/template.html.header"; template_html_footer="${output_dir}/template.html.footer"; template_html_sidebar="${output_dir}/template.html.sidebar"; if ! command -v kramdown &>/dev/null then echo "kramdown not installed! Cannot build documentation."; exit 1; fi if ! command -v tidy &>/dev/null then echo "tidy not installed! Cannot build documentation."; exit 1; fi if ! command -v checklink &>/dev/null then echo "checklink not installed! Cannot build documentation."; exit 1; fi if [ ! -d doc/ ]; then echo "Run this script from the root of the mlpack repository."; exit 1; fi # Define utility function to run kramdown and turn an .md file to an .html file. run_kramdown() { input_file=$1; # This converts, e.g., ./doc/user/index.md -> doc/html/user/index.html. tmp=${input_file#./doc/}; # Strip leading ./doc/. output_file="$output_dir/${tmp%.md}.html"; # Determine what the link root is. If we're in the root directory, it's # nothing, otherwise it's one of more '../'s. dir_name=$(dirname $tmp); link_root=""; if [[ "$dir_name" != "." ]]; then levels_below_root=`echo $dir_name | awk -F'/' '{ print NF }'`; link_root=$(printf '../%.0s' `seq 1 $levels_below_root`); fi # Make the enclosing directory if needed. out_dir=`dirname "$output_file"`; mkdir -p "$out_dir"; # Kramdown doesn't detect languages correctly with the "```" fence; instead it # needs the "~~~" fence. sed 's/^```/~~~/' $input_file > $input_file.tmp; # Our documentation is full of relative links, like # [name](other_file.md#anchor). We need these to turn into links to the # rendered HTML file, like [name](other_file.html#anchor). We'll do this with # regular expressions... # # - Note that this assumes there are no spaces in any filenames. # - We also only catch the second part of the link '](' because the name of # the link could be spread on multiple lines. # # We start by trying to catch a special case of README.md, which our # documentation puts in a slightly different place. In addition, because # README.md is being moved to the root of the documentation, we must adjust # links in that file differently. if [[ $input_file != "README.md" ]]; then sed -i "s|\]([./]*README.md)|](${link_root}README.html)|g" $input_file.tmp; sed -i "s|\]([./]*README.md#[0-9]-\([^ ]*\))|](${link_root}README.html#\1)|g" $input_file.tmp; sed -i 's/\](\([^ ]*\).md)/](\1.html)/g' $input_file.tmp; sed -i 's/\](\([^ ]*\).md#\([^ ]*\))/](\1.html#\2)/g' $input_file.tmp; else sed -i 's/\](doc\/\([^ ]*\).md)/](\1.html)/g' $input_file.tmp; sed -i 's/\](doc\/\([^ ]*\).md#\([^ ]*\))/](\1.html#\2)/g' $input_file.tmp; # The README specifically has a link to GOVERNANCE.md, but we want to # preserve that. We're not building that file into Markdown. sed -i 's|(./GOVERNANCE.md)|(https://github.com/mlpack/mlpack/blob/master/GOVERNANCE.md)|' $input_file.tmp; # Ugh! Github naming of anchors is different than kramdown, and so we have # to adjust all the table-of-contents anchor links in the README (and in # that file only). sed -i 's/\](#[0-9][0-9]-\([^ ]*\))/](#\1)/g' $input_file.tmp; sed -i 's/\](#[0-9]-\([^ ]*\))/](#\1)/g' $input_file.tmp; sed -i 's/\](#[0-9][0-9]\([^ ]*\))/](#\1)/g' $input_file.tmp; sed -i 's/\](#[0-9]\([^ ]*\))/](#\1)/g' $input_file.tmp; fi # Replace any links to source files with a link to the current version of the # source file on Github. sed -i 's/\](\/src\/\([^ ]*\)\.hpp)/](https:\/\/github.com\/mlpack\/mlpack\/blob\/master\/src\/\1.hpp)/' $input_file.tmp; # If this is binding documentation or quickstart documentation, don't set the # default language to C++. set_lang=1; if [[ `dirname $input_file` == "./doc/user/bindings" ]]; then set_lang=0; elif [[ `dirname $input_file` == "./doc/quickstart" ]]; then if [[ `basename $input_file .md` != "cpp" ]]; then set_lang=0; fi fi if [[ "$set_lang" == "0" ]]; then kramdown \ -x parser-gfm \ --syntax-highlighter rouge \ --auto_ids \ $input_file.tmp > "$output_file.tmp" || exit 1; else kramdown \ -x parser-gfm \ --syntax-highlighter rouge \ --syntax-highlighter-opts '{ default_lang: c++ }' \ --auto_ids \ $input_file.tmp > "$output_file.tmp" || exit 1; fi cat "$template_html_header" | sed "s|LINKROOT|$link_root|" > "$output_file"; # Create the sidebar. Extract anchors from the page, unless we are looking at # index.md, since the permanent part of the sidebar links all over index.md # anyway. if [[ $input_file != "doc/index.md" ]] && [[ ! -f ${input_file/%.md/.sidebar.html} ]]; then cat "$template_html_sidebar" | sed "s|LINKROOT|$link_root|" >> "$output_file"; create_page_sidebar_section "$output_file.tmp" "$output_file" "$dir_name"; elif [[ -f ${input_file/%.md/.sidebar.html} ]]; then echo "Using custom sidebar..."; # Some pages may have a custom sidebar HTML file. (Specifically, # generated language bindings.) cat "${input_file/%.md/.sidebar.html}" | sed "s|LINKROOT|$link_root|" \ >> "$output_file"; fi # Add clickable anchors to h2 and h3 headers. echo "