Big commit, mostly adding best-practice changes to the script.

1. Added lines at the top to exit the script if any command in
the script fails.
2. Quoted all variable accesses.
3. Redirected error messages to stderr.
4. Used '[[' and ']]' in 'if' statements.
5. Added a debug mode, that can be triggered by setting the TRACE
environment variable to 1.
6. Used 'dirname' instead of 'PWD'. Therefore, in order to use the
script, you must place it in the same directory as your website
files. However, you can run it from anywhere as long as it is in
the correct location.
master
Aadhavan Srinivasan 8 months ago
parent cc3bdae903
commit 45a136dfc3

@ -1,24 +1,32 @@
#!/bin/bash
#!/usr/bin/env bash
BASE_PATH="$PWD"
set -o errexit # Stop executing when a command fails
set -o nounset # Stop executing when accessing an unset variable
set -o pipefail # Treat a pipeline as failing, even if one command in the pipeline fails
if [[ "${TRACE-0}" == "1" ]]; then set -o xtrace; fi # Enable tracing (output of each command) if the TRACE variable is set
BASE_PATH="$(dirname "$0")"
check_for_dirs() {
if [ ! -d "${BASE_PATH}/source" ]; then
echo "ERROR: 'source' folder does not exist. Your content is sourced from this folder."
if [[ ! -d "${BASE_PATH}/source" ]]; then
echo "ERROR: 'source' folder does not exist. Your content is sourced from this folder." >&2
exit
fi
if [ -d "${BASE_PATH}/temp" ]; then
echo "ERROR: You have an existing 'temp' folder. Please delete this folder, and run the script again."
if [[ -d "${BASE_PATH}/temp" ]]; then
echo "ERROR: You have an existing 'temp' folder. Please delete this folder, and run the script again." >&2
exit
fi
if [ ! -f "${BASE_PATH}/header.html" ]; then
echo "ERROR: You do not have a header.html file. This file is used as a global header. Please create this file, and run the script again."
if [[ ! -f "${BASE_PATH}/header.html" ]]; then
echo "ERROR: You do not have a header.html file. This file is used as a global header. Please create this file, and run the script again." >&2
exit
fi
if [ ! -f "${BASE_PATH}/footer.html" ]; then
echo "ERROR: You do not have a footer.html file. This file is used as a global footer. Please create this file, and run the script again."
if [[ ! -f "${BASE_PATH}/footer.html" ]]; then
echo "ERROR: You do not have a footer.html file. This file is used as a global footer. Please create this file, and run the script again." >&2
exit
fi
@ -36,12 +44,12 @@ setup_output_dir() {
}
del_files_in_output() {
find $BASE_PATH/output -type f -name "*.md" -delete #Delete all .md files (which were copied over from 'source') in 'output'
find "$BASE_PATH/output" -type f -name "*.md" -delete #Delete all .md files (which were copied over from 'source') in 'output'
}
read_metadata() {
# Read the metadata from the top of a .md file into a string
metadata=$(awk 'BEGIN{RS = "\n\n"} {print $0}; {exit}' $1) # Reads from the .md file until a double-newline is encountered
metadata=$(awk 'BEGIN{RS = "\n\n"} {print $0}; {exit}' "$1") # Reads from the .md file until a double-newline is encountered
}
convert_to_array() {
@ -57,52 +65,52 @@ convert_to_array() {
}
add_date_to_array() {
if [[ "${meta_array[date]}" == "auto" ]]; then # If the date is set to 'auto'
if [[ "${meta_array[date]-}" == "auto" ]]; then # If the date is set to 'auto'
meta_array["date"]="$(date -r $1 +'%b %d, %Y')"
fi
}
add_header_and_footer() {
# Copy header to temporary location
cp $BASE_PATH/header.html $BASE_PATH/temp/temp_header.html
cp "$BASE_PATH/header.html" "$BASE_PATH/temp/temp_header.html"
# Check for relevant metadata, and perform corresponding action
if test -z "${meta_array[date]}"; then #If there is no date
sed -i '$ d' $BASE_PATH/temp/temp_header.html # remove the 'date published' section of the header
if [[ ! -v "meta_array["date"]" ]]; then # If there is no date
sed -i '$ d' "$BASE_PATH/temp/temp_header.html" # remove the 'date published' section of the header
fi
if [[ "${meta_array[noappend]}" == "true" ]]; then
sed -i 's/ - Two More Cents//g' $BASE_PATH/temp/temp_header.html # 'noappend' removes the suffix from the title
if [[ "${meta_array[noappend]-}" == "true" ]]; then
sed -i 's/ - Two More Cents//g' "$BASE_PATH/temp/temp_header.html" # 'noappend' removes the suffix from the title
fi
# Add header
cat $BASE_PATH/temp/temp_header.html | cat - $1 > $BASE_PATH/temp/temp.html
cat "$BASE_PATH/temp/temp_header.html" | cat - "$1" > "$BASE_PATH/temp/temp.html"
# Add footer
echo >> $BASE_PATH/temp/temp.html
cat $BASE_PATH/footer.html >> $BASE_PATH/temp/temp.html
echo >> "$BASE_PATH/temp/temp.html" # Add newline
cat "$BASE_PATH/footer.html" >> "$BASE_PATH/temp/temp.html"
# Move temp file to original location
mv $BASE_PATH/temp/temp.html $1
mv "$BASE_PATH/temp/temp.html" "$1"
}
add_header_and_footer_to_index() {
# Add header
cat $BASE_PATH/header.html | head -n -1 | cat - $1 > $BASE_PATH/temp/temp.html # For the index page, remove the last line of the header (date published)
cat "$BASE_PATH/header.html" | head -n -1 | cat - "$1" > "$BASE_PATH/temp/temp.html" # For the index page, remove the last line of the header (date published)
# Add footer
echo >> $BASE_PATH/temp/temp.html
cat $BASE_PATH/footer.html >> $BASE_PATH/temp/temp.html
echo >> "$BASE_PATH/temp/temp.html" # Add newline
cat "$BASE_PATH/footer.html" >> "$BASE_PATH/temp/temp.html"
# Move temp file to original location
mv $BASE_PATH/temp/temp.html $1
mv "$BASE_PATH/temp/temp.html" "$1"
}
replace_vars() {
# Loop through the keys of the 'meta_array' array, search for all occurences of the key in the HTML doc, and replace them with the corresponding value..
for arr_key in "${!meta_array[@]}"; do
meta_array[$arr_key]=${meta_array[$arr_key]/\//\\/} # Escape all forward slashes in the value
sed -i "s/[\$][\$]$arr_key[\$][\$]/${meta_array[$arr_key]}/g" $1
meta_array["$arr_key"]="${meta_array["$arr_key"]/\//\\/}" # Escape all forward slashes in the value
sed -i "s/[\$][\$]$arr_key[\$][\$]/${meta_array[$arr_key]}/g" "$1"
done
}
@ -110,30 +118,30 @@ replace_vars() {
md_to_html() {
# Convert .md files from 'source' and place them into the correct locations into 'output'
files=$(find $BASE_PATH/source -name "*.md")
files=$(find "$BASE_PATH/source" -name "*.md")
for file in $files; do
read_metadata $file # Sets the 'metadata' variable
read_metadata "$file" # Sets the 'metadata' variable
convert_to_array "$metadata" #Sets the 'meta_array' array
add_date_to_array "$file" #Uses 'meta_array' array
# Copy file to temp dir and strip metadata
cp $file $BASE_PATH/temp/
cp "$file" "$BASE_PATH/temp/"
let num_lines=$(echo "$metadata" | wc -l)+1
sed -i "1,${num_lines}d" $BASE_PATH/temp/`basename $file`
sed -i "1,${num_lines}d" "$BASE_PATH/temp/$(basename "$file")"
# Construct path for output file
path_for_output=$(realpath --relative-to="${BASE_PATH}/source" $file)
path_for_output=$(realpath --relative-to="${BASE_PATH}/source" "$file")
path_for_output="${BASE_PATH}/output/${path_for_output}"
path_for_output="$(dirname $path_for_output)/$(basename $path_for_output .md).html"
# Convert the file (using the given filters), and place the output in the correct location
pandoc --lua-filter pandoc_filters/* -f markdown --wrap=preserve $BASE_PATH/temp/`basename $file` > ${path_for_output}
rm $BASE_PATH/temp/*
pandoc --lua-filter "$BASE_PATH"/pandoc_filters/* -f markdown --wrap=preserve "$BASE_PATH/temp/$(basename "$file")" > "${path_for_output}"
rm "$BASE_PATH"/temp/*
add_header_and_footer $path_for_output # Uses 'meta_array' array
replace_vars $path_for_output #Uses 'meta_array' array
add_header_and_footer "$path_for_output" # Uses 'meta_array' array
replace_vars "$path_for_output" #Uses 'meta_array' array
unset metadata meta_key meta_value meta_array
done
@ -141,11 +149,12 @@ md_to_html() {
gen_sorted_file_list() { # Generate a list of the HTMl files, sorted by when they were last modified (read from the contents of the HTML file)
files=$(find $BASE_PATH/output -name "*.html")
files=$(find "$BASE_PATH/output" -name "*.html")
local date_mod
for file in $files; do
if grep -q "date-published" $file; then
echo "$file" >> $BASE_PATH/temp/file_listing.txt # Write files that have a date published to a temp file (we only want the files with date modified, because only these files can be listed with their date on the site map)
if grep -q "date-published" "$file" ; then
echo "$file" >> "$BASE_PATH/temp/file_listing.txt" # Write files that have a date published to a temp file (we only want the files with date modified, because only these files can be listed with their date on the site map)
date_mod+=$(cat "$file" | grep "date-published" | awk -F'[<>]' '{print $3}' \
| cut -d' ' -f '1,2' --complement | tr -d "," | awk '{print $2" "$1" "$3}' \
@ -155,16 +164,16 @@ gen_sorted_file_list() { # Generate a list of the HTMl files, sorted by when the
# Line 2 re-arranges this information, and converts it into DD MM YY format
# Line 3 converts this into a UNIX timestamp
date_mod+=$'\n'
date_mod+=$'\n'
fi
done
date_mod=$(echo "$date_mod" | head -n -1) # Remove last (empty) line from variable
echo "$date_mod" > $BASE_PATH/temp/date_mod.txt # Write the corresponding 'date modified' timestamps to a temp file
date_mod=$(echo "${date_mod-}" | head -n -1) # Remove last (empty) line from variable
echo "${date_mod-}" > "$BASE_PATH/temp/date_mod.txt" # Write the corresponding 'date modified' timestamps to a temp file
paste $BASE_PATH/temp/file_listing.txt $BASE_PATH/temp/date_mod.txt > $BASE_PATH/temp/new_file_list.txt # Combine file list and date modified into a single file
paste "$BASE_PATH/temp/file_listing.txt" "$BASE_PATH/temp/date_mod.txt" > "$BASE_PATH/temp/new_file_list.txt" # Combine file list and date modified into a single file
sorted_file_list=$(sort -r -k 2 $BASE_PATH/temp/new_file_list.txt) # Sort the data in the file based on the timestamp (from newest to oldest), and store it into a variable
sorted_file_list=$(sort -r -k 2 "$BASE_PATH/temp/new_file_list.txt") # Sort the data in the file based on the timestamp (from newest to oldest), and store it into a variable
sorted_file_list=$(echo "$sorted_file_list" | awk '{print $1}') # Store only the first column (the file path) in the variable
}
@ -173,16 +182,16 @@ gen_index_page() { # Generate an index page (site map) that includes links to th
index_file_html="<nav class=\"toc\">"$'\n' # Variable to store the body HTML of the index page; enclose the list in a nav
for file in $1; do
title=$(cat $file | grep "<title>" | head -n 1 | awk -F'[<>]' '{print $3}') # Find the title of the web page
title=$(cat "$file" | grep "<title>" | head -n 1 | awk -F'[<>]' '{print $3}') # Find the title of the web page
suffix=" - Two More Cents"
title=${title%"$suffix"} # Remove the website name from it
title="${title%"$suffix"}" # Remove the website name from it
pub_date=$(cat $file | grep "date-published" | head -n 1 | awk -F'[<>]' '{print $3}') # Find the date published
pub_date=$(cat "$file" | grep "date-published" | head -n 1 | awk -F'[<>]' '{print $3}') # Find the date published
prefix="Published on " # Find date published of webpage
pub_date=${pub_date#"$prefix"} # Remove the prefix from it
pub_date="${pub_date#"$prefix"}" # Remove the prefix from it
pub_date=$(echo "$pub_date" | tr -d "," | awk '{print $2" "$1" "$3}' | date -f - +"%m/%d/%Y") # Re-arrange the date and convert to mm/dd/yy
file_path=$(realpath --relative-to="${BASE_PATH}/output" $file)
file_path=$(realpath --relative-to="${BASE_PATH}/output" "$file")
index_file_html+="<li><time>${pub_date}</time> - <a href=\"$file_path\">$title</a></li>" # Add a line of HTML containing the date and title of the article
index_file_html+=$'\n'
@ -200,14 +209,14 @@ gen_index_page() { # Generate an index page (site map) that includes links to th
}
copy_things_in() {
cp ${BASE_PATH}/styles.css ${BASE_PATH}/output/
cp -r ${BASE_PATH}/files ${BASE_PATH}/output/
cp -r ${BASE_PATH}/fonts ${BASE_PATH}/output/
cp "${BASE_PATH}/styles.css" "${BASE_PATH}/output/"
cp -r "${BASE_PATH}/files" "${BASE_PATH}/output/"
cp -r "${BASE_PATH}/fonts" "${BASE_PATH}/output/"
}
clean_up() {
rm -r ${BASE_PATH}/temp
rm -r "${BASE_PATH}/temp"
}

Loading…
Cancel
Save