qsgen2/qsgen2

904 lines
33 KiB
Plaintext
Raw Normal View History

2024-01-31 16:51:48 +01:00
#!/usr/bin/zsh
2024-01-28 18:24:38 +01:00
# Quick Site Generator 2 is a static website generator inspired by Nikola.
# It is written for the Z shell (zsh) because that's what I use and also because I like it better than Bash.
#
# This script is an almost complete rewrite of my old script because it became overly complicated and
# had way too many bugs, even though it worked on simple sites.
#
# qsgen2 uses different templates and its own formattings tags to generate the static HTML pages.
#
# The file structure in the project directory should look like this:
#
# .blog_cache
# .pages_cache
# config
# index.tpl
# templates/
# templates/<theme>/pages.tpl
# templates/<theme>/blogs.tpl
# templates/<theme>/blog_index.tpl
# blog/
# blog/2024-01-26-1.blog
#
# Explanation of the file structure.
# The file 'config' contains the settings for this specific project.
# The file 'index.tpl' is what becomes index.html that is served to the public.
# The 'templates/' directory contains the templates used to generate the pages and blog posts.
# The 'blog/' directory contains the blog posts. The date format of the files are used to create a blog/index.html with the newest post first.
#
# Contents of the file 'config' --> CHANGE THESE <--
# export site_name="The name of the website"
# - This is the project directory
# export project_dir=${HOME}/www/vikingo
# - This is where the generated files will be put
# export www_root=${HOME}/www_root/smelror.com
# #################################################################################################
# I don't think these need to be here as they'll always be in the same place with the same names
2024-01-30 16:01:24 +01:00
# export pages=${project_dir}/themes/<theme>/pages.tpl
# export blogs=${project_dir}/themes/<theme>/blogs.tpl
# export blog_list=${project_dir}/themes/<theme>/blog_list.tpl
# export blog_index=${project_dir}/themes/<theme>/blog_index.tpl
2024-01-28 18:24:38 +01:00
###################################################################################################
# export blog_in_index=false
2024-02-02 12:34:06 +01:00
VERSION="0.2.0 alpha" # Tue-2024-01-30
2024-01-29 15:41:09 +01:00
QSGEN="Quick Site Generator 2"
2024-01-28 18:24:38 +01:00
# Set to true or false
# This will show debug information from almost every function in this script
2024-01-29 21:41:48 +01:00
debug=false
2024-01-28 18:24:38 +01:00
function include () {
2024-01-29 15:06:36 +01:00
# This function is used to include other functions that will normally be in
# ${HOME}/bin/include/
2024-01-28 18:24:38 +01:00
# Edit this path to reflect your installation
2024-01-29 15:06:36 +01:00
local inc_file=${HOME}/bin/include/${1}.inc
2024-01-28 18:24:38 +01:00
if [[ ! -f ${inc_file} ]]; then
2024-01-29 15:06:36 +01:00
local inc_opt=$( echo ${1} | cut -d\/ -f2 )
echo "Supplied option \"${inc_opt}\" is not a valid include."
2024-01-28 18:24:38 +01:00
else
builtin source ${inc_file} ${2}
fi
}
2024-01-29 15:06:36 +01:00
# Including some colors to the script
2024-01-28 18:24:38 +01:00
include common/colors
2024-01-31 22:34:28 +01:00
echo "${magenta}${blue_bg} ${QSGEN} ${end}${white}${blue_bg}${VERSION} ${end}"
2024-01-28 19:34:30 +01:00
function _version() {
echo "${yellow}- Created by kekePower - 2018-$(date +%Y)${end}"
2024-01-28 19:33:09 +01:00
echo "${yellow}- https://github.com/kekePower/qsgen2/${end}"
2024-01-31 16:20:39 +01:00
echo "${yellow}- See '${1} help' for more information.${end}"
2024-01-28 19:33:09 +01:00
exit
}
2024-01-28 19:33:09 +01:00
function _help() {
echo "This is where I'll write the Help documentation."
2024-01-28 18:24:38 +01:00
exit
}
if [[ "$1" == "version" || "$1" == "-v" || "$1" == "--version" ]]; then
_version ${0:t}
elif [[ "$1" == "help" || "$1" == "-h" || "$1" == "--help" ]]; then
_help ${0:t}
fi
2024-01-28 18:24:38 +01:00
# Loading Zsh modules
zmodload zsh/files
# Check for, an source, the config file for this specific website
if [[ -f $(pwd)/config ]]; then
2024-01-31 16:51:48 +01:00
if (${debug}); then echo "${red}Config file found and sourced${end}\n- ${yellow} - $(pwd)/config${end}"; fi
2024-01-28 18:24:38 +01:00
# CONFIG=$(pwd)/config
builtin source $(pwd)/config
else
echo "${red}Cannot find configuration file.${end}"
echo "${yellow} - Please create the file 'config' in your project directory.${end}"
exit
fi
2024-01-31 17:50:56 +01:00
2024-01-28 18:24:38 +01:00
if (${debug}); then
2024-01-31 17:32:56 +01:00
qsconfig=$( cat $(pwd)/config | grep -v \# | awk '{print substr($0, index($0, " ") + 1)}' )
2024-01-28 18:24:38 +01:00
echo "${red}Contents of Config file:${end}"
2024-01-31 17:32:56 +01:00
for qslines in ${qsconfig}
2024-01-31 16:51:48 +01:00
do
2024-01-31 17:32:56 +01:00
echo "${yellow}${qslines}${end}"
2024-01-31 16:51:48 +01:00
done
2024-01-28 18:24:38 +01:00
fi
function _msg() {
# Use this function to write out messages based on their type
# Types are: std=green - info=yellow - debug=red other=bold_yellow
# Usage: _msg <type> "<message>"
case ${1} in
std)
echo "${green}${2}${end}"
;;
info)
echo "${yellow}${2}${end}"
;;
debug)
echo "${red}${2}${end}"
;;
other)
echo "${bold_yellow}${2}${end}"
;;
*)
2024-01-31 16:20:39 +01:00
echo "${2}"
;;
2024-01-31 17:56:24 +01:00
esac
}
# Let's check if qsgen2 can generate this site by checking if 'generator' is available
2024-01-31 16:20:39 +01:00
if [[ ! ${generator} ]] || [[ -d $(pwd)/.git ]]; then
_msg other "${0:t} cannot parse this site. Exiting."
exit
fi
# We define the variable 'engine' based on what's in the 'config' file.
2024-01-28 18:24:38 +01:00
if [[ ${generator} == "native" ]]; then
# Usage: ${engine} ${1} - Where 1 is the file you want to convert
2024-01-28 18:24:38 +01:00
engine=_html
2024-02-01 17:56:50 +01:00
export file_ext=tpl
2024-01-28 18:24:38 +01:00
elif [[ ${generator} == "markdown" ]]; then
if [[ ! -f /usr/local/bin/pandoc ]]; then
_msg other "Please install Pandoc."
2024-02-02 12:34:06 +01:00
_msg other "https://github.com/jgm/pandoc/releases"
2024-01-28 18:24:38 +01:00
exit
else
2024-01-31 16:20:39 +01:00
# Usage: ${engine} ${1} - Where 1 is the file you want parsed
engine=/usr/local/bin/pandoc
2024-02-02 09:50:01 +01:00
# function engine() {
#
# local command="/usr/bin/Markdown.pl"
# local c-opts=
#
# $(command) "$1"
#
# # Assign the output to the global variable named by $1
# # eval "$1=\${result}"
#
# # echo "${(P)1}"
# }
2024-02-01 17:56:50 +01:00
export file_ext=md
fi
2024-01-28 18:24:38 +01:00
fi
2024-02-02 12:36:11 +01:00
2024-02-01 18:03:53 +01:00
if (${debug}) _msg debug "Using the ${generator} engine for files: ${file_ext}"
2024-01-28 18:24:38 +01:00
2024-01-29 19:05:36 +01:00
# Define cache files for blogs and pages
2024-01-28 18:24:38 +01:00
blog_cache_file="${project_dir}/.blog_cache"
pages_cache_file="${project_dir}/.pages_cache"
builtin cd ${project_dir}
# Let's put these here for now.
export today=$( date "+%Y-%m-%d - %T" )
export blogdate=$( date +%a-%Y-%b-%d )
2024-01-28 18:24:38 +01:00
# Let's create arrays of all the files we'll be working on
function _list_pages() {
2024-02-02 12:36:11 +01:00
local debug=false
export no_pages_found=false
# Temporarily set null_glob for this function
setopt local_options null_glob
# Check if there are any .blog files in the blog directory
2024-02-01 18:07:25 +01:00
local pages_files=$(ls *${file_ext})
if (( ${#pages_files} == 0 )); then
if (${debug}); then _msg debug "_list_pages: No Pages found."; fi
export no_pages_found=true
return
fi
2024-02-01 17:58:14 +01:00
for file in $( echo ${pages_files} ); do
2024-02-01 18:01:25 +01:00
if (${debug}) _msg debug "_list_pages: Adding file to array: ${file}"
pages_file_array+=("$file")
done
}
2024-01-31 22:22:22 +01:00
function _list_blogs() {
2024-01-31 21:04:19 +01:00
local debug=false
2024-01-31 22:22:22 +01:00
export no_blogs_found=false
2024-01-31 21:04:19 +01:00
2024-01-31 21:08:08 +01:00
# Temporarily set null_glob for this function
setopt local_options null_glob
# Check if there are any .blog files in the blog directory
local blog_files=(blog/*.blog)
if (( ${#blog_files} == 0 )); then
2024-01-31 22:22:22 +01:00
if (${debug}); then _msg debug "_list_blogs: No blog files found."; fi
export no_blogs_found=true
return
fi
2024-01-31 21:08:08 +01:00
for file in $( ls -har blog/*.blog ); do
2024-01-31 21:08:08 +01:00
blogs_file_array+=("$file")
done
}
2024-01-28 18:24:38 +01:00
# BLOG CACHE
function _blog_cache() {
local debug=false
2024-01-31 22:22:22 +01:00
_list_blogs
# Create an associative array for the blog cache
typeset -A blog_cache
# Load the existing blog cache
if [[ -f $blog_cache_file ]]; then
while IFS=':' read -r name hash; do
blog_cache[$name]=$hash
2024-01-31 17:13:54 +01:00
if (${debug}) _msg debug "_blog_cache: HASH VALUE: ${blog_cache[${name}]}"
done < "$blog_cache_file"
fi
2024-01-28 18:24:38 +01:00
# Initialize the array for storing blog files to process
make_blog_array=()
2024-01-28 18:24:38 +01:00
# Process blog files
2024-01-31 22:22:22 +01:00
for blog_file in ${blogs_file_array[@]}; do
# Compute the current blog file hash
current_hash=$(md5sum "$blog_file" | awk '{print $1}')
2024-01-28 18:24:38 +01:00
2024-01-31 17:13:54 +01:00
if (${debug}) _msg debug "1. _blog_cache: ${blog_file}"
if (${debug}) _msg debug "2. _blog_cache: current_cache: ${current_hash}"
# Check if the blog file is new or has changed
if [[ ${blog_cache[$blog_file]} != "$current_hash" ]]; then
2024-01-31 17:13:54 +01:00
if (${debug}) _msg debug "3. _blog_cache: new_cache_file: ${blog_file}$"
if (${debug}) _msg debug "4. _blog_cache: new_current_cache: ${current_hash}"
# Blog file is new or has changed; add it to the processing array
make_blog_array+=("$blog_file")
# Update the blog cache with the new hash
blog_cache[$blog_file]=$current_hash
fi
done
2024-01-28 18:24:38 +01:00
# Rebuild the blog cache file from scratch
: >| "$blog_cache_file" # Truncate the file before writing
for name in "${(@k)blog_cache}"; do
echo "$name:${blog_cache[$name]}" >> "$blog_cache_file"
done
2024-01-28 18:24:38 +01:00
}
# PAGES CACHE
# Returns the array pages_array()
2024-01-28 18:24:38 +01:00
function _pages_cache() {
2024-02-02 12:36:11 +01:00
local debug=false
# Create an associative array for the pages cache
typeset -A pages_cache
2024-02-01 17:59:15 +01:00
_list_pages
# Load the existing pages cache
if [[ -f $pages_cache_file ]]; then
while IFS=':' read -r name hash; do
pages_cache[$name]=$hash
if (${debug}) _msg debug "PAGES HASH VALUE: ${pages_cache[${name}]}"
done < "$pages_cache_file"
2024-01-28 18:24:38 +01:00
fi
# Initialize the array for storing pages files to process
pages_array=()
# Process pages files
for file in ${pages_file_array[@]}; do
# Compute the current blog file hash
current_hash=$(md5sum "$file" | awk '{print $1}')
if (${debug}) _msg debug "1. pages_cache: ${pages_cache[$file]}"
2024-02-01 18:18:35 +01:00
if (${debug}) _msg debug "1. _pages_cache: current_cache: ${current_hash}"
# Check if the pages file is new or has changed
if [[ ${pages_cache[$file]} != "$current_hash" ]]; then
2024-01-31 17:13:54 +01:00
if (${debug}) _msg debug "2. _pages_cache: pages_file: ${pages_cache[$file]}"
if (${debug}) _msg debug "2. _pages_cache: current_cache: ${current_hash}"
# Pages file is new or has changed; add it to the processing array
pages_array+=("$file")
# Update the pages cache with the new hash
pages_cache[$file]=$current_hash
fi
done
# Rebuild the pages cache file from scratch
: >| "$pages_cache_file" # Truncate the file before writing
for name in "${(@k)pages_cache}"; do
echo "$name:${pages_cache[$name]}" >> "$pages_cache_file"
done
2024-01-28 18:24:38 +01:00
}
function _last_updated() {
2024-01-31 07:43:08 +01:00
# This function updates #updated and #version tags in the provided string for buffers
2024-01-30 09:26:34 +01:00
local content="${1}"
local debug=false
if (${debug}) _msg debug "_last_updated: Setting date and version in footer"
2024-01-30 09:26:34 +01:00
# Perform the replacements
local updated_content=$(echo "${content}" | sed \
2024-02-01 16:58:42 +01:00
-e "s|#updated|${today}|" \
2024-01-30 09:26:34 +01:00
-e "s|#version|${QSGEN} ${VERSION}|")
# Return the updated content
echo "${updated_content}"
2024-01-28 18:24:38 +01:00
}
function _f_last_updated() {
2024-01-31 07:43:08 +01:00
# This function updates #updated and #version tags in the provided string in files
local content="${1}"
local debug=false
if (${debug}) _msg debug "_f_last_updated: Setting date and version in footer of file ${1}"
# Perform the replacements
tee < ${content} | sed \
2024-02-01 16:58:42 +01:00
-e "s|#updated|${today}|" \
2024-01-30 15:29:28 +01:00
-e "s|#version|${QSGEN} ${VERSION}|" \
> ${content}
}
function _file_to_lower() {
2024-01-31 17:13:54 +01:00
local filename="${1}"
# Replace spaces with dashes
filename="${filename// /-}"
# Convert to lowercase and remove invalid characters
filename=$(echo "${filename}" | sed -e 's/^[^a-zA-Z0-9_.]+//g' -e 's/[^a-zA-Z0-9_-]+/-/g')
2024-01-29 23:28:03 +01:00
echo ${filename}
}
2024-01-28 18:24:38 +01:00
function _pages() {
# This function generates all the new and updated Pages
2024-01-28 18:24:38 +01:00
local debug=true
2024-01-28 18:24:38 +01:00
2024-01-30 00:39:30 +01:00
# Load the cache for Pages
if (${debug}) _msg debug "_pages: Running function _pages_cache"
2024-01-30 00:39:30 +01:00
_pages_cache
if (( ${#pages_array[@]} > 0 )); then
# If pages_array is not empty, we do work
if (${debug}) _msg debug "_pages: pages_array is not empty"
for pages_in_array in ${pages_array[@]}
do
2024-01-30 14:12:44 +01:00
if (${debug}) _msg debug "_pages: Setting Pages template"
2024-01-30 16:01:24 +01:00
local pages=${project_dir}/themes/${theme}/pages.tpl
2024-01-30 14:12:44 +01:00
# Let's check if we can access the pages.tpl file.
# It not, exit script.
if [[ ! -f ${pages} ]]; then
_msg info "Unable to find the Pages template: ${pages}"
2024-01-30 14:12:44 +01:00
exit
else
# Read template once
if (${debug}) _msg debug "_pages: Reading Pages template into pages_tpl"
2024-01-30 14:12:44 +01:00
pages_tpl="$(<${pages})"
fi
_msg std "Generating Page: ${pages_in_array}"
# Read the file once
2024-01-31 17:13:54 +01:00
if (${debug}) _msg debug "_pages: Loading page_content once - ${pages_in_array}"
local page_content="$(<${pages_in_array})"
2024-01-29 22:39:05 +01:00
# Grab the title from the Page
if (${debug}) _msg debug "_pages: Grepping for page_title"
2024-01-31 07:43:08 +01:00
local page_title=$( echo ${page_content} | head -2 | grep \#title | cut -d= -f2 )
if (${debug}) _msg debug "_pages: ${page_title}"
2024-01-30 00:42:34 +01:00
# Remove the #title line from the buffer. No longer needed.
if (${debug}) _msg debug "_pages: Removing #title line from page_content"
2024-01-31 07:43:08 +01:00
local page_content=$( echo ${page_content} | grep -v \#title )
2024-01-30 00:42:34 +01:00
2024-01-30 09:39:54 +01:00
# HTML'ify the page content
if (${debug}) _msg debug "_pages: Running engine on ${pages_in_array}"
if [[ ${file_ext} == "tpl" ]]; then
local page_content=$( ${engine} "$page_content" )
2024-02-02 16:09:11 +01:00
2024-01-30 09:39:54 +01:00
# Look for links, images and videos and convert them if present.
if (${debug}) _msg debug "_pages: Checking for #link, #showimg and #ytvideo in page_content"
2024-02-02 16:09:11 +01:00
if [[ $( echo ${page_content} | grep \#link ) ]]; then
if (${debug}) _msg debug "_pages: #link is present, run _link: page_content"
2024-01-31 07:43:08 +01:00
local page_content=$( _link "${page_content}" )
2024-02-02 16:09:11 +01:00
fi
if [[ $( echo ${page_content} | grep \#showimg ) ]]; then
if (${debug}) _msg debug "_pages: #showimg is present, run _image: page_content"
2024-01-31 07:43:08 +01:00
local page_content=$( _image "${page_content}" )
2024-02-02 16:09:11 +01:00
fi
if [[ $( echo ${page_content} | grep \#ytvideo ) ]]; then
if (${debug}) _msg debug "_pages: #ytvideo is present, run _youtube: page_content"
2024-01-31 07:43:08 +01:00
local page_content=$( _youtube "${page_content}" )
2024-02-02 16:09:11 +01:00
fi
2024-02-02 10:55:39 +01:00
elif [[ ${file_ext} == "md" ]]; then
local page_content=$(echo "$page_content" | ${engine})
fi
2024-01-30 09:39:54 +01:00
# Replace every #pagetitle in pages_tpl
if (${debug}) _msg debug "_pages: Replacing #pagetitle in pages_tpl"
2024-01-31 07:43:08 +01:00
local pages_tpl=$( echo ${pages_tpl} | perl -pe "s|#pagetitle|${page_title}|gs" )
2024-01-30 09:39:54 +01:00
# Replace every #tagline in pages_tpl
if (${debug}) _msg debug "_pages: Replacing tagline"
2024-01-31 07:43:08 +01:00
local pages_tpl=$( echo ${pages_tpl} | perl -pe "s|#tagline|${site_tagline}|gs" )
2024-01-30 00:32:59 +01:00
# Replace #updated with today's date and #version with Name and Version to footer
if (${debug}) _msg debug "_pages: _last_updated in pages_tpl"
2024-01-31 07:43:08 +01:00
local pages_tpl=$( _last_updated ${pages_tpl} )
2024-01-29 22:57:49 +01:00
# Always use lowercase for file names
if (${debug}) _msg debug "_pages: Lowercase filnames, always"
2024-01-31 07:43:08 +01:00
local pages_title_lower=$( _file_to_lower "${pages_in_array}" )
2024-02-01 16:53:30 +01:00
# Clean up unused tags, if any
if (${debug}) _msg debug "_pages: Running _cleanup"
local pages_tpl=$( _cleanup "${pages_tpl}" )
# Write pages_tpl to disk
_msg std "Writing ${www_root}/${pages_title_lower%.*}.html to disk."
echo "${pages_tpl}" > ${www_root}/${pages_title_lower%.*}.html
done
2024-01-30 00:38:25 +01:00
export new_updated_pages=true
2024-01-30 00:38:25 +01:00
else
2024-02-02 16:09:11 +01:00
2024-01-31 17:13:54 +01:00
_msg info "No new or updated Pages"
export new_updated_pages=false
2024-02-02 16:09:11 +01:00
fi
2024-01-28 18:24:38 +01:00
}
function _blogs() {
2024-01-30 10:27:22 +01:00
# This function either generates blog files or exports metadata based on the argument
2024-02-01 10:21:49 +01:00
local debug=false
2024-01-30 10:27:22 +01:00
2024-01-31 22:22:22 +01:00
# Running function _list_blogs
if (${debug}) _msg debug "_blogs: Running function _list_blogs"
_list_blogs
2024-01-28 18:24:38 +01:00
# Running function _blog_cache
if (${debug}) _msg debug "_blogs: Running function _blog_cache"
2024-01-28 18:24:38 +01:00
_blog_cache
2024-01-30 10:27:22 +01:00
2024-01-28 18:24:38 +01:00
if (( ${#make_blog_array[@]} > 0 )); then
2024-01-30 15:19:33 +01:00
# Declare the array to hold metadata strings for each blog
BLOG_META_STR_ARRAY=()
2024-01-30 10:27:22 +01:00
# Regular blog creation process
2024-01-30 15:07:30 +01:00
#if [[ ! ${mode} ]]; then
2024-01-30 10:27:22 +01:00
2024-01-30 16:01:24 +01:00
if [[ -f ${project_dir}/themes/${theme}/blogs.tpl ]]; then
local blog_tpl=$(<"${project_dir}/themes/${theme}/blogs.tpl")
2024-01-30 11:09:55 +01:00
else
2024-01-31 17:13:54 +01:00
_msg info "Unable to find theme template for Blogs."
2024-01-30 11:09:55 +01:00
exit
fi
2024-01-30 10:41:17 +01:00
2024-01-30 10:27:22 +01:00
for blog in "${make_blog_array[@]}"; do
2024-01-30 11:20:38 +01:00
if (${debug}) _msg debug "_blogs: Processing pre-data for ${blog}"
2024-01-30 11:20:38 +01:00
local content="$(<"${blog}")"
local sdate btitle ingress body blog_index blog_dir blog_url
# Extract blog information
2024-01-30 11:54:45 +01:00
sed -i "s/GETDATE/${blogdate}/" ${blog}
2024-01-30 11:20:38 +01:00
# Array sdate = Name day=1, Year=2, Month=3, Number day=4
2024-01-30 12:38:55 +01:00
sdate=( $( echo ${content} | grep DATE | sed "s|DATE\ ||" | sed "s|\-|\ |g" ) )
btitle=$( echo ${content} | grep BLOG_TITLE | cut -d' ' -f2- )
ingress=$( echo ${content} | sed "s/'/\\\'/g" | xargs | grep -Po "#INGRESS_START\K(.*?)#INGRESS_STOP" | sed "s|\ \#INGRESS_STOP||" | sed "s|^\ ||" )
2024-01-30 11:54:45 +01:00
body=$( echo ${content} | sed "s/'/\\\'/g" | xargs | grep -Po "#BODY_START\K(.*?)#BODY_STOP" | sed "s|\ \#BODY_STOP||" | sed "s|^\ ||" )
2024-01-30 11:20:38 +01:00
2024-01-31 07:43:08 +01:00
blog_index=$(echo "${btitle:l}" | sed 's/ /_/g; s/,//g; s/\.//g; s/://g; s/[()]//g')
2024-01-30 11:20:38 +01:00
blog_dir="/blog/${sdate[2]}/${sdate[3]:l}/${sdate[4]}"
blog_url="${blog_dir}/${blog_index}.html"
if (${debug}) _msg debug "_blogs: Adding data for ${blog} to array to export"
2024-01-30 15:19:33 +01:00
# Concatenate all metadata into a single string for the current blog
local metadata_str="SDATE: ${sdate[@]}||BTITLE: ${btitle}||INGRESS: ${ingress}||URL: ${blog_url}"
# Append this metadata string to the array
BLOG_META_STR_ARRAY+=("${metadata_str}")
if (${debug}) _msg debug "_blogs: Processing ${blog}"
2024-01-30 12:24:46 +01:00
_msg std "Generating blog ${blog_index}.html"
2024-01-30 10:37:36 +01:00
# Prepare the blog template
if (${debug}) _msg debug "_blogs: Processing substitutes in ${blog}"
2024-01-30 10:51:31 +01:00
local blog_content=$(echo "${blog_tpl}" | perl -pe "s|BLOGTITLE|${btitle}|g")
blog_content=$(echo "${blog_content}" | perl -pe "s|CALADAY|${sdate[1]}|g")
blog_content=$(echo "${blog_content}" | perl -pe "s|CALNDAY|${sdate[4]}|g")
blog_content=$(echo "${blog_content}" | perl -pe "s|CALMONTH|${sdate[3]}|g")
blog_content=$(echo "${blog_content}" | perl -pe "s|CALYEAR|${sdate[2]}|g")
blog_content=$(echo "${blog_content}" | perl -pe "s|BLOGURL|${blog_url}|g")
2024-01-30 10:48:59 +01:00
blog_content=$(echo "${blog_content}" | perl -pe "s|\QINGRESS\E|${ingress}|g")
2024-01-30 10:44:54 +01:00
blog_content=$(echo "${blog_content}" | perl -pe "s|\QBODY\E|${body}|g")
if (${debug}) _msg debug "_blogs: Running function _html for ${blog}"
2024-01-30 10:37:36 +01:00
# Apply transformations
blog_content="$(_html "${blog_content}")"
2024-01-30 11:09:55 +01:00
# Look for links, images and videos and convert them if present.
if (${debug}) _msg debug "_blogs: Checking for #link, #showimg and #ytvideo in blog_content"
2024-01-30 11:09:55 +01:00
if [[ $( echo ${blog_content} | grep \#link ) ]]; then
2024-02-01 16:53:30 +01:00
if (${debug}) _msg debug "_blogs: #link is present, run _link: blog_content"
2024-01-30 11:09:55 +01:00
blog_content="$(_link "${blog_content}")"
fi
if [[ $( echo ${blog_content} | grep \#showimg ) ]]; then
2024-02-01 16:53:30 +01:00
if (${debug}) _msg debug "_blogs: #showimg is present, run _link: blog_content"
2024-01-30 11:09:55 +01:00
blog_content="$(_image "${blog_content}")"
fi
if [[ $( echo ${blog_content} | grep \#ytvideo ) ]]; then
2024-02-01 16:53:30 +01:00
if (${debug}) _msg debug "_blogs: #ytvideo is present, run _link: blog_content"
2024-01-30 11:09:55 +01:00
blog_content="$(_youtube "${blog_content}")"
2024-02-01 16:53:30 +01:00
fi
2024-01-30 10:37:36 +01:00
blog_content="$(_last_updated "${blog_content}")"
2024-02-01 16:53:30 +01:00
blog_content="$(_cleanup "${blog_content}")"
2024-01-30 10:37:36 +01:00
# Create directory if it doesn't exist
if (${debug}) _msg debug "_blogs: Creating directoty ${www_root}/${blog_dir}"
2024-01-30 11:22:12 +01:00
[[ ! -d "${www_root}/${blog_dir}" ]] && mkdir -p "${www_root}/${blog_dir}"
2024-01-30 10:27:22 +01:00
2024-01-30 10:37:36 +01:00
# Write to file
if (${debug}) _msg debug "_blogs: Writing blog to disk: ${www_root}${blog_url}"
2024-01-30 10:37:36 +01:00
echo "${blog_content}" > "${www_root}${blog_url}"
unset sdate btitle ingress body blog_index blog_dir blog_url
2024-01-30 15:12:52 +01:00
done
2024-01-30 15:19:33 +01:00
# Now BLOG_META_STR_ARRAY contains the metadata string for each blog post
export BLOG_META_STR_ARRAY
2024-01-31 20:26:17 +01:00
export new_updated_blogs=true
2024-01-30 11:20:38 +01:00
2024-01-30 10:38:58 +01:00
else
2024-01-31 17:13:54 +01:00
_msg info "No new or updated Blogs detected."
2024-01-31 20:26:17 +01:00
export new_updated_blogs=false
2024-01-28 18:24:38 +01:00
fi
2024-02-01 16:53:30 +01:00
_blog_idx_for_index
_blog_index
2024-01-28 18:24:38 +01:00
}
function _blog_idx_for_index() {
2024-01-30 13:42:01 +01:00
# This function generates the file blog/index.tmp.html
2024-01-28 18:24:38 +01:00
local debug=false
2024-01-30 13:52:06 +01:00
if (${debug}) _msg debug "_blog_idx_for_index: Initiating function"
2024-01-30 14:52:17 +01:00
2024-01-30 16:01:24 +01:00
local blog_list_tpl=$(<${project_dir}/themes/${theme}/blog_list.tpl)
2024-01-28 18:24:38 +01:00
2024-01-30 13:08:04 +01:00
# Truncate file before writing new one
2024-01-30 13:14:46 +01:00
: >| "${project_dir}/blog/index.tmp.html"
2024-01-30 13:08:04 +01:00
2024-01-31 17:28:28 +01:00
if (${debug}) _msg debug "_blog_idx_for_index: BLOG_META_STR_ARRAY: ${BLOG_META_STR_ARRAY[@]}"
2024-01-30 14:56:43 +01:00
2024-01-30 13:10:39 +01:00
for meta_str in ${BLOG_META_STR_ARRAY[@]}
2024-01-30 12:24:46 +01:00
do
if (${debug}) _msg debug "_blog_idx_for_index: meta_str from BLOG_META_STR_ARRAY from _blogs"
2024-01-31 17:28:28 +01:00
if (${debug}) _msg debug "_blog_idx_for_index: ${meta_str}"
2024-01-30 15:57:48 +01:00
local debug=false
2024-01-30 13:08:04 +01:00
# Split meta_str into individual metadata components
local -a meta_array=("${(@s/||/)meta_str}")
# Initialize variables to store each component
local sdate=""
local btitle=""
local ingress=""
local url=""
# Iterate over each component and extract information
if (${debug}) _msg debug "_blog_idx_for_index: Iterate over each component and extract information"
2024-01-30 13:08:04 +01:00
for component in "${meta_array[@]}"; do
2024-01-30 15:57:48 +01:00
local debug=false
2024-01-30 13:08:04 +01:00
case "${component}" in
2024-01-30 13:12:42 +01:00
SDATE:*) sdate=${component#SDATE: } ;;
2024-01-30 13:08:04 +01:00
BTITLE:*) btitle=${component#BTITLE: } ;;
INGRESS:*) ingress=${component#INGRESS: } ;;
URL:*) url=${component#URL: } ;;
2024-01-30 13:24:18 +01:00
esac
2024-01-30 13:09:42 +01:00
2024-01-30 13:25:59 +01:00
local adate=( $( echo ${sdate} ) )
local bdate="${adate[1]} - ${adate[4]}/${adate[3]}/${adate[2]}"
2024-01-30 14:25:23 +01:00
blog_list_content=$(echo "${blog_list_tpl}" | perl -pe "s|BLOGURL|${url}|g")
2024-01-30 13:25:59 +01:00
blog_list_content=$(echo "${blog_list_content}" | perl -pe "s|BLOGTITLE|${btitle}|g")
blog_list_content=$(echo "${blog_list_content}" | perl -pe "s|INGRESS|${ingress}|g")
blog_list_content=$(echo "${blog_list_content}" | perl -pe "s|BLOGDATE|${bdate}|g")
2024-01-30 13:20:23 +01:00
2024-01-30 13:09:42 +01:00
done
2024-01-30 14:52:17 +01:00
if (${debug}) _msg debug "_blog_idx_for_index: Writing _blog_idx_for_index to file: ${project_dir}/blog/index.tmp.html"
if (${debug}) _msg debug "_blog_idx_for_index: blog_list_content = ${blog_list_content}"
2024-01-30 13:25:59 +01:00
echo ${blog_list_content} >> ${project_dir}/blog/index.tmp.html
2024-01-30 14:52:17 +01:00
2024-01-30 12:24:46 +01:00
done
2024-01-28 18:24:38 +01:00
}
function _blog_index() {
2024-01-28 18:24:38 +01:00
# This function generates the /blog/index.html file that gets its data from _blog_list_for_index()
2024-01-31 20:26:17 +01:00
# ${new_updated_blogs} comes from the function _blogs if anything new or updated is detected
if [[ ${blog_in_index} == "false" ]] && [[ ${new_updated_blogs} = "true" ]]; then
if (${debug}) _msg debug "Running function _blog_index"
if (${debug}) _msg debug "_blog_index: blog_in_index = ${blog_in_index}"
2024-01-31 20:26:17 +01:00
_msg std "Updating the Blog Index file"
local debug=false
2024-01-31 07:43:08 +01:00
local blog_index=$(<${project_dir}/themes/${theme}/blog_index.tpl)
local blog_index_list=$(<${project_dir}/blog/index.tmp.html)
2024-01-31 17:35:21 +01:00
blog_index_content=$(echo "${blog_index}" | perl -pe "s|BODY|${blog_index_list}|g")
echo "${blog_index_content}" > ${www_root}/blog/index.html
_f_last_updated ${www_root}/blog/index.html
2024-01-30 16:26:52 +01:00
fi
2024-01-31 20:26:17 +01:00
2024-01-30 16:26:52 +01:00
}
2024-02-02 16:09:11 +01:00
function _add_blog_list_to_index() {
local debug=true
# Let's find the file 'index.tpl' and add the blog if blog_in_index is true
if [[ ${new_updated_blogs} == "true" ]] && [[ ${blog_in_index} == "true" ]]; then
if (${debug}) _msg debug "_pages: Inserting blog list to index.html"
local blog_index_list=$(<${project_dir}/blog/index.tmp.html)
2024-02-02 16:10:58 +01:00
local site_index_file=$(<${www_root}/index.html)
2024-02-02 16:09:11 +01:00
awk -v new_body="$site_index_file" '{sub(/BLOGINDEX/, new_body)} 1' <(echo "${blog_index_list}")
fi
}
2024-01-31 17:28:28 +01:00
function _sitemap() {
2024-01-28 18:24:38 +01:00
# Check if sitemap is set to true and if there are updated Blogs or Pages before updating the sitemap.xml file.
if [[ ${sitemap} == "true" ]] && ( [[ ${new_updated_blogs} == "true" ]] || [[ ${new_updated_pages} == "true" ]] ); then
2024-01-31 20:38:52 +01:00
_msg info "Updating sitemap.xml"
2024-01-30 16:26:52 +01:00
local sitemap_file="${www_root}/sitemap.xml"
# Find all HTML files and store them in an array
local -a html_files=("${(@f)$(find "${www_root}" -type f -name "*.html")}")
# Start of the XML file
2024-01-30 16:54:36 +01:00
echo '<?xml version="1.0" encoding="UTF-8"?>' > ${sitemap_file}
2024-01-30 17:02:04 +01:00
echo "<!-- Sitemap generated by ${QSGEN} ${VERSION} - https://github.com/kekePower/qsgen2 -->" >> ${sitemap_file}
2024-01-30 16:59:13 +01:00
echo "<?xml-stylesheet type=\"text/xsl\" href=\"${site_url}/css/default-sitemap.xsl?sitemap=page\"?>" >> ${sitemap_file}
2024-01-30 16:54:36 +01:00
echo '<urlset' >> ${sitemap_file}
echo ' xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"' >> ${sitemap_file}
echo ' xmlns:xhtml="http://www.w3.org/1999/xhtml"' >> ${sitemap_file}
echo ' xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"' >> ${sitemap_file}
echo '>' >> ${sitemap_file}
2024-01-30 16:26:52 +01:00
# Add each URL to the sitemap
for file in "${html_files[@]}"; do
# Remove www_root from the path and prepend site_url
2024-01-30 16:29:03 +01:00
local url="${site_url}${file#$www_root}"
2024-01-30 16:46:38 +01:00
local lastmod=$(stat -c %y "${file}" 2>/dev/null | cut -d' ' -f1,2 | sed 's/ /T/' | sed 's/\..*$//')
2024-01-30 16:26:52 +01:00
2024-01-30 16:54:36 +01:00
echo " <url>" >> ${sitemap_file}
echo " <loc>${url}</loc>" >> ${sitemap_file}
2024-01-30 16:59:13 +01:00
echo " <lastmod><![CDATA[${lastmod}+01:00]]></lastmod>" >> "${sitemap_file}"
2024-01-30 16:54:36 +01:00
echo " <changefreq><![CDATA[always]]></changefreq>" >> ${sitemap_file}
echo " <priority><![CDATA[1]]></priority>" >> ${sitemap_file}
echo " </url>" >> ${sitemap_file}
2024-01-30 16:26:52 +01:00
done
# End of the XML file
echo '</urlset>' >> "${sitemap_file}"
2024-01-31 17:28:28 +01:00
if (${debug}); then _msg debug "Sitemap generated at ${sitemap_file}"; fi
fi
2024-01-30 16:26:52 +01:00
2024-01-28 18:24:38 +01:00
}
function _link() {
# This converts #link tags to actual clickable links in a provided string
2024-01-28 18:24:38 +01:00
local content="${1}"
local modified_content=""
2024-01-28 18:24:38 +01:00
local debug=false
# Process the content line by line
echo "${content}" | while IFS= read -r line; do
2024-01-28 18:24:38 +01:00
if [[ ${line} == *"#link"* ]]; then
if (${debug}) _msg debug "_link: URL_MAIN(line): ${line}"
2024-01-28 18:24:38 +01:00
# Extract the URL and the link text
local url_full=$(echo "${line}" | awk -F'#link ' '{print $2}' | awk -F'¤' '{print $1 "¤" $2}')
local url_dest=$(echo "${url_full}" | awk -F'¤' '{print $1}')
local url_txt=$(echo "${url_full}" | awk -F'¤' '{print $2}')
2024-01-28 18:24:38 +01:00
if (${debug}) _msg debug "_link_ URL: ${url_dest}"
if (${debug}) _msg debug "_link: Text: ${url_txt}"
2024-01-28 18:24:38 +01:00
# Form the replacement HTML link
local modified_link="<a href=\"${url_dest}\">${url_txt}"
if [[ ${url_dest} =~ ^https?:// ]]; then
# Add external link icon for external URLs
modified_link+="<img class=\"exticon\" alt=\"External site icon\" src=\"/images/ext-url.png\" width=\"16\" />"
fi
modified_link+="</a>"
line=${line//"#link ${url_full}"/${modified_link}}
2024-01-28 18:24:38 +01:00
fi
modified_content+="${line}\n"
done
2024-01-28 18:24:38 +01:00
# Return the modified content
echo -e "${modified_content}"
2024-01-28 18:24:38 +01:00
}
function _image() {
# This replaces #showimg tags with actual HTML img tags in a provided string
2024-01-28 18:24:38 +01:00
local content="${1}"
local modified_content=""
local debug=false
# Process the content line by line
echo "${content}" | while IFS= read -r line; do
if [[ ${line} == *"#showimg"* ]]; then
if (${debug}) _msg debug "_image: Processing line: ${line}"
# Extract image link and alt text
local img_link=$(echo "${line}" | awk -F'#showimg ' '{print $2}')
local image=$(echo "${img_link}" | awk -F'¤' '{print $1}')
local img_alt=$(echo "${img_link}" | awk -F'¤' '{print $2}')
# Determine the source of the image
local real_image=""
if [[ ${image} =~ ^https?:// ]]; then
real_image=${image}
elif [[ ${image} =~ ^\/ ]]; then
real_image=${image}
else
real_image="/images/${image}"
fi
# Form the replacement HTML image tag
local img_tag="<img src=\"${real_image}\" alt=\"${img_alt}\" width=\"500\" />"
line=${line//"#showimg ${img_link}"/${img_tag}}
fi
modified_content+="${line}\n"
done
# Return the modified content
echo -e "${modified_content}"
2024-01-28 18:24:38 +01:00
}
function _youtube() {
# This embeds a YouTube video in a provided string
2024-01-28 18:24:38 +01:00
local content="${1}"
local modified_content=""
local debug=false
# Process the content line by line
echo "${content}" | while IFS= read -r line; do
if [[ ${line} == *"#ytvideo"* ]]; then
if (${debug}) _msg debug "_youtube: Processing line: ${line}"
# Extract YouTube video ID
local yt_id=$(echo "${line}" | awk -F'#ytvideo ' '{print $2}')
# Form the replacement YouTube iframe embed
local yt_iframe="<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/${yt_id}\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen></iframe>"
line=${line//"#ytvideo ${yt_id}"/${yt_iframe}}
fi
modified_content+="${line}\n"
done
2024-01-28 18:24:38 +01:00
# Return the modified content
echo -e "${modified_content}"
2024-01-28 18:24:38 +01:00
}
function _cleanup() {
# This removes tags used in the templates that may be left over for some reason
local content="${1}"
local debug=false
2024-01-28 18:24:38 +01:00
if (${debug}) _msg debug "_cleanup: Cleaning up tags in content"
# Perform the cleanup
local cleaned_content=$(echo "${content}" | sed \
-e "s|¤||g" \
-e "s|#showimg\ ||g" \
-e "s|#ytvideo\ ||g" \
-e "s|#link\ ||g")
2024-01-28 18:24:38 +01:00
# Return the cleaned content
echo "${cleaned_content}"
2024-01-28 18:24:38 +01:00
}
_html() {
2024-02-01 15:53:48 +01:00
local content="$1"
2024-01-30 09:39:54 +01:00
local debug=false
2024-01-28 18:24:38 +01:00
2024-02-01 16:02:09 +01:00
if ${debug}; then
echo "_html: Converting QStags in content"
fi
2024-02-01 15:53:48 +01:00
2024-02-01 16:02:09 +01:00
# Use perl to convert QStags to HTML
perl -0777 -pe '
2024-02-01 15:53:48 +01:00
BEGIN {
2024-02-01 16:02:09 +01:00
@tags = (
"#BR", "<br/>\n",
2024-02-01 16:05:23 +01:00
"#BD", "<b>", "#EBD", "</b>",
2024-02-01 16:02:09 +01:00
"#I", "<i>", "#EI", "</i>\n",
"#P", "<p>", "#EP", "</p>\n",
"#Q", "<blockquote>", "#EQ", "</blockquote>\n",
"#C", "<code>", "#EC", "</code>\n",
"#H1", "<h1>", "#EH1", "</h1>\n",
"#H2", "<h2>", "#EH2", "</h2>\n",
"#H3", "<h3>", "#EH3", "</h3>\n",
"#H4", "<h4>", "#EH4", "</h4>\n",
"#H5", "<h5>", "#EH5", "</h5>\n",
"#H6", "<h6>", "#EH6", "</h6>\n",
"#STRONG", "<strong>", "#ESTRONG", "</strong>\n",
"#EM", "<em>", "#EEM", "</em>\n",
"#DV", "<div>", "#EDV", "</div>\n",
"#SPN", "<span>", "#ESPN", "</span>\n",
"#UL", "<ul>", "#EUL", "</ul>\n",
"#OL", "<ol>", "#EOL", "</ol>\n",
"#LI", "<li>", "#ELI", "</li>\n",
"#U", "<u>", "#EU", "</u>\n",
"#TBL", "<table>", "#ETBL", "</table>\n",
"#TR", "<tr>", "#ETR", "</tr>\n",
"#TD", "<td>", "#ETD", "</td>\n",
"#TH", "<th>", "#ETH", "</th>\n",
"#ART", "<article>", "#EART", "</article>\n",
"#SEC", "<section>", "#ESEC", "</section>\n",
"#ASIDE", "<aside>", "#EASIDE", "</aside>\n",
"#NAV", "<nav>", "#ENAV", "</nav>\n",
"#BTN", "<button>", "#EBTN", "</button>\n",
"#SEL", "<select>", "#ESEL", "</select>\n",
"#OPT", "<option>", "#EOPT", "</option>\n",
"#LT", "&lt;", "#GT", "&gt;", "#NUM", "&num;"
2024-02-01 15:53:48 +01:00
);
}
2024-02-01 16:02:09 +01:00
for (my $i = 0; $i < $#tags; $i += 2) {
my $tag = $tags[$i];
my $html = $tags[$i + 1];
s/\Q$tag\E/$html/g;
2024-02-01 15:53:48 +01:00
}
' <<< "$content"
2024-01-28 18:24:38 +01:00
}
# Time to test the first function
2024-01-30 13:42:01 +01:00
_blogs
2024-01-30 16:26:52 +01:00
_pages
2024-02-02 16:09:11 +01:00
_add_blog_list_to_index
2024-01-31 17:47:14 +01:00
_sitemap