static-site-scripts/gensite

304 lines
8.2 KiB
Bash
Executable File

#!/bin/sh
if ! [ -f "$PWD/config.cfg" ];then
cat << EOF > config.cfg
sitetitle=""
sitelang=""
sitedomain=""
siteurlrel=""
siteurlfull=""
sitekeywords=""
sitedescription=""
sitemail=""
siteauthor=""
siteupdated="$(date +%Y-%m-%d)"
siteprojects=""
EOF
else
source $PWD/config.cfg
fi
# directories containing content and metadata.
# NOTE: it's recommended to use absolute paths here, use "." for current directory.
pagesdir="pages"
# Output dir.
outputdir="output"
# Markdown processor: default: is "smu".
markdown="smu"
#gnudate(fmt,date)
gnudate() {
date "+$1" -d "$2" >/dev/null
}
#bsddate(fmt,date)
bsddate() {
date -j "+$1" "$(printf '%s' "$2" | tr -Cd '[:digit:]')" 2>/dev/null
}
# added for compatibility with GNU and BSD date.
alias formatdate='gnudate'
if ! gnudate '%Y' '2015-01-01 00:00' 2>/dev/null; then
alias formatdate='bsddate'
fi
#makeid(title), format "Some title" to "some-title".
makeid() {
printf '%s\n' "$1" | tr '[:upper:]' '[:lower:]' | \
sed -e 's@[^[:alnum:]]\{1,\}@-@g' -e 's@-*$@@g' -e 's@^-*@@g'
}
# initial values for page variables, use some site vars as global defaults.
pagereset() {
id=""
title=""
url=""
description="${sitedescription}"
keywords="${sitekeywords}"
author="${siteauthor}"
content=""
tags=""
categories=""
timecreated=""
datecreated=""
timeupdated=""
dateupdated=""
}
pageread() {
meta="$1"
. "${meta}" # source page metadata.
basename=$(basename "${meta}" ".sh")
datecreated=$(printf '%s' "${timecreated}" | cut -b 1-10)
dateupdated=$(printf '%s' "${timeupdated}" | cut -b 1-10)
# if ${id} is empty and title is set: create id based on title.
if test -z "${id}" && test -n "${title}"; then
id=$(makeid "${title}")
fi
if test -z "${id}"; then
printf 'Warning: $id or $title not set in "%s", skipping...\n' "${meta}" >&2
return 1
fi
if test -z "${url}"; then
url="${id}.html"
fi
outfile="${id}.html"
urlfull="${siteurlfull}/${outfile}"
filename=""
# ${content} not set; try data from filetypes.
if test -z "${content}"; then
if test -f "${pagesdir}/${basename}.html"; then
filename="${pagesdir}/${basename}.html"
content=$(cat "${filename}")
elif test -f "${pagesdir}/${basename}.md"; then
filename="${pagesdir}/${basename}.md"
content=$("${markdown}" "${filename}")
fi
fi
authors="<strong>Authors:</strong> ${author}<br/>"
created="<strong>Created on:</strong> ${datecreated}<br/>"
uuid="<strong>UUID:</strong> ${id}<br/>"
if test "${datecreated}" != "${dateupdated}"; then
created="${created}<strong>Last update on:</strong> ${dateupdated}<br/>"
fi
}
pageheader() {
# prefix page title with site title, make sure its neatly formatted.
if test -z "${title}"; then
pagetitle="${sitetitle}"
else
pagetitle="${title} - ${sitetitle}"
fi
cat <<!__EOF__
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/MarkUp/SCHEMA/xhtml11.xsd" dir="ltr" xml:lang="${sitelang}" lang="${sitelang}">
<head>
<title>${pagetitle}</title>
<link rel="stylesheet" type="text/css" href="style.css" />
<link rel="alternate" type="application/rss+xml" title="${sitetitle} RSS Feed" href="rss.xml" />
<link rel="alternate" type="application/atom+xml" title="${sitetitle} Atom Feed" href="atom.xml" />
<link rel="icon" type="image/png" href="favicon.png" />
<meta http-equiv="Content-Type" content="application/xhtml+xml;charset=utf-8" />
<meta http-equiv="Content-Language" content="${sitelang}" />
<meta content="width=device-width" name="viewport" />
<meta content="${keywords}" name="keywords" />
<meta content="${description}" name="description" />
<meta content="${author}" name="author" />
</head>
<body>
<div id="menuwrap">
<div id="menu">
<span id="links">
<a href="index.html" title="Main page">Index</a> |
<a href="${siteprojects}" title="Some of my projects">Projects</a> |
<a href="http://validator.w3.org/check?uri=${siteurlfull}">Valid XHTML 1.1</a>
</span>
<span id="links-contact">
<span class="hidden"> | </span>
<a href="rss.xml" title="RSS feed">RSS</a> |
<a href="atom.xml" title="Atom feed">Atom</a> |
<a href="mailto:${sitemail}" title="Mail me">Mail</a>
</span>
</div>
</div>
<hr class="hidden" />
<div id="mainwrap">
<div id="main">
!__EOF__
}
pagecontent() {
pageheader
cat <<!__EOF__
<h1><a href="">${title}</a></h1>
<em>${authors}</em>
<em>${created}</em>
<em>${uuid}</em>
${content}
!__EOF__
pagefooter
}
pagefooter() {
cat <<!__EOF__
</div>
</div>
</body>
</html>
!__EOF__
}
if ! test -d "${pagesdir}"; then
printf 'Error: pages directory "%s" not found.\n' "${pagesdir}" >&2
exit 1
fi
# process single page as argument (handy for testing a single page).
if test -n "$1"; then
pagereset
pageread "$1" || exit 1
pagecontent
exit 0
fi
# try to make output dir.
mkdir -p "${outputdir}"
# truncate urllist.txt (sitemap).
> "${outputdir}/urllist.txt"
# content for RSS, Atom sitemap and index, this is appended as a string.
contentindex=""
contentrss=""
contentatom=""
contentsitemap=""
while read -r meta; do
pagereset
pageread "${meta}" || continue
pagecontent > "${outputdir}/${outfile}"
# index / posts item: append.
contentindex="${contentindex}$(cat <<!__EOF__
<tr><td>${dateupdated}</td>
<td><a href="${url}" title="${description}">${title}</a></td></tr>
!__EOF__
)"
# RSS item: append.
# NOTE: GMT timezone is hard-coded because %z is not consistent,
# change accordingly.
contentrsspubdate=$(formatdate "%a, %d %b %Y %H:%M:%S GMT" "${timeupdated}")
contentrss="${contentrss}$(
cat <<!__EOF__
<item>
<title>${title}</title>
<link>${urlfull}</link>
<pubDate>${contentrsspubdate}</pubDate>
<author>${author}</author>
<guid isPermaLink="false">${urlfull}</guid>
<description><![CDATA[${description}]]></description>
</item>
!__EOF__
)"
# Atom item: append.
contentatomupdated=$(formatdate "%Y-%m-%dT%H:%M:%SZ" "${timeupdated}")
contentatompublished=$(formatdate "%Y-%m-%dT%H:%M:%SZ" "${timecreated}")
contentatom="${contentatom}$(
cat <<!__EOF__
<entry>
<title type="html"><![CDATA[${title}]]></title>
<link rel="alternate" type="text/html" href="${urlfull}" />
<id>${urlfull}</id>
<updated>${contentatomupdated}</updated>
<published>${contentatompublished}</published>
<author>
<name>${author}</name>
<uri>${siteurlfull}</uri>
</author>
<summary type="html"><![CDATA[${description}]]></summary>
</entry>
!__EOF__
)"
# sitemap: sitemap.xml, append item.
contentsitemap="${contentsitemap}<url><loc>${urlfull}</loc></url>"
# sitemap: urllist.txt, append item, write directly to file, because
# this is just a plain-text list.
printf '%s\n' "${urlfull}" >> "${outputdir}/urllist.txt"
done <<!FILELIST
$(find "${pagesdir}" -type f -name "*.sh" | sort -rn)
!FILELIST
# process pages (reverse numeric order).
# NOTE: above heredoc is used to make sure content* variables are known
# in the scope after the while loop (subshell / pipes prevents this in a
# standard manner).
# index HTML page (index.html).
pagereset
title="Posts"
(pageheader
cat <<!__EOF__
<h1>${title}</h1>
<table>
${contentindex}
</table>
!__EOF__
pagefooter) > "${outputdir}/index.html"
# RSS feed (rss.xml).
cat <<!__EOF__ > "${outputdir}/rss.xml"
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>${sitetitle}</title>
<link>${siteurlfull}</link>
<description>${sitedescription}</description>
<language>${sitelang}</language>
${contentrss}
</channel>
</rss>
!__EOF__
# Atom feed (atom.xml).
cat <<!__EOF__ > "${outputdir}/atom.xml"
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="${sitelang}">
<title type="text">${sitetitle}</title>
<subtitle type="text">${sitedescription}</subtitle>
<updated>${siteupdated}</updated>
<link rel="alternate" type="text/html" href="${siteurlfull}" />
<id>${siteurlfull}/atom.xml</id>
<link rel="self" type="application/atom+xml" href="${siteurlfull}/atom.xml" />
${contentatom}
</feed>
!__EOF__
# sitemap (sitemap.xml).
cat <<!__EOF__ > "${outputdir}/sitemap.xml"
<?xml version="1.0" encoding="UTF-8"?><urlset>${contentsitemap}</urlset>
!__EOF__