generate.sh - static-site-scripts - static site generator shellscripts
 (HTM) git clone git://git.codemadness.org/static-site-scripts
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       generate.sh (8477B)
       ---
            1 #!/bin/sh
            2 # site title (part of ${pagetitle} probably).
            3 sitetitle="Codemadness"
            4 # site language.
            5 sitelang="en"
            6 # main site domain.
            7 sitedomain="http://www.codemadness.nl"
            8 # relative site url, can be "/blog" or something.
            9 siteurlrel=""
           10 # full site url.
           11 siteurlfull="${sitedomain}${siteurlrel}"
           12 # site keywords (global default), don't use too many.
           13 sitekeywords="blog, suckless, dwm-hiltjo"
           14 # site description (global default).
           15 sitedescription="blog with various projects and articles about computer-related things"
           16 # site mail used for contact "mail link".
           17 sitemail="hiltjo@AT@codemadness.DOT.org"
           18 # site author (global).
           19 siteauthor="hiltjo"
           20 # site last updated (default use date when script was run).
           21 siteupdated=$(date "+%Y-%m-%dT%H:%M:%SZ")
           22 # directories containing content and metadata.
           23 # NOTE: it's recommended to use absolute paths here, use "." for current directory.
           24 pagesdir="pages"
           25 # Output dir.
           26 outputdir="output"
           27 # Markdown processor: default: is "smu".
           28 markdown="smu"
           29 
           30 #gnudate(fmt,date)
           31 gnudate() {
           32         date "+$1" -d "$2"
           33 }
           34 
           35 #bsddate(fmt,date)
           36 bsddate() {
           37         date -j "+$1" "$(printf '%s' "$2" | tr -Cd '[:digit:]')"
           38 }
           39 
           40 # added for compatibility with GNU and BSD date.
           41 alias formatdate='gnudate'
           42 if ! gnudate '%Y' '2015-01-01 00:00' 2>/dev/null; then
           43         alias formatdate='bsddate'
           44 fi
           45 
           46 #makeid(title), format "Some title" to "some-title".
           47 makeid() {
           48         printf '%s\n' "$1" | tr '[:upper:]' '[:lower:]' | \
           49                 sed -e 's@[^[:alnum:]]\{1,\}@-@g' -e 's@-*$@@g' -e 's@^-*@@g'
           50 }
           51 
           52 # initial values for page variables, use some site vars as global defaults.
           53 pagereset() {
           54         id=""
           55         title=""
           56         url=""
           57         description="${sitedescription}"
           58         keywords="${sitekeywords}"
           59         author="${siteauthor}"
           60         content=""
           61         tags=""
           62         categories=""
           63         timecreated=""
           64         datecreated=""
           65         timeupdated=""
           66         dateupdated=""
           67 }
           68 
           69 pageread() {
           70         meta="$1"
           71         . "${meta}" # source page metadata.
           72         basename=$(basename "${meta}" ".sh")
           73         datecreated=$(printf '%s' "${timecreated}" | cut -b 1-10)
           74         dateupdated=$(printf '%s' "${timeupdated}" | cut -b 1-10)
           75 
           76         # if ${id} is empty and title is set: create id based on title.
           77         if test -z "${id}" && test -n "${title}"; then
           78                 id=$(makeid "${title}")
           79         fi
           80         if test -z "${id}"; then
           81                 printf 'Warning: $id or $title not set in "%s", skipping...\n' "${meta}" >&2
           82                 return 1
           83         fi
           84         if test -z "${url}"; then
           85                 url="${id}.html"
           86         fi
           87         outfile="${id}.html"
           88         urlfull="${siteurlfull}/${outfile}"
           89         filename=""
           90         # ${content} not set; try data from filetypes.
           91         if test -z "${content}"; then
           92                 if test -f "${pagesdir}/${basename}.html"; then
           93                         filename="${pagesdir}/${basename}.html"
           94                         content=$(cat "${filename}")
           95                 elif test -f "${pagesdir}/${basename}.md"; then
           96                         filename="${pagesdir}/${basename}.md"
           97                         content=$("${markdown}" "${filename}")
           98                 fi
           99         fi
          100         created="<strong>Created on:</strong> ${datecreated}<br/>"
          101         if test "${datecreated}" != "${dateupdated}"; then
          102                 created="${created}<strong>Last update on:</strong> ${dateupdated}<br/>"
          103         fi
          104 }
          105 
          106 pageheader() {
          107         # prefix page title with site title, make sure its neatly formatted.
          108         if test -z "${title}"; then
          109                 pagetitle="${sitetitle}"
          110         else
          111                 pagetitle="${title} - ${sitetitle}"
          112         fi
          113         cat <<!__EOF__
          114 <!DOCTYPE html>
          115 <html dir="ltr" lang="${sitelang}">
          116         <head>
          117                 <title>${pagetitle}</title>
          118                 <link rel="stylesheet" href="style.css" type="text/css" media="screen" />
          119                 <link rel="stylesheet" href="print.css" type="text/css" media="print" />
          120                 <link rel="alternate" type="application/rss+xml" title="${sitetitle} RSS Feed" href="rss.xml" />
          121                 <link rel="alternate" type="application/atom+xml" title="${sitetitle} Atom Feed" href="atom.xml" />
          122                 <link rel="icon" type="image/png" href="/favicon.png" />
          123                 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          124                 <meta http-equiv="Content-Language" content="${sitelang}" />
          125                 <meta content="width=device-width" name="viewport" />
          126                 <meta content="${keywords}" name="keywords" />
          127                 <meta content="${description}" name="description" />
          128                 <meta content="${author}" name="author" />
          129         </head>
          130         <body>
          131                 <div id="menuwrap">
          132                         <div id="menu">
          133                                 <span id="links">
          134                                         <a href="index.html" title="Blog">Blog</a> |
          135                                         <a href="http://git.codemadness.org/" title="Some of my projects">Git</a> |
          136                                         <a href="https://github.com/hiltjo/" title="Some of my projects on github">Github</a>
          137                                 </span>
          138                                 <span id="links-contact">
          139                                         <span class="hidden"> | </span>
          140                                         <a href="rss.xml" title="RSS feed">RSS</a> |
          141                                         <a href="atom.xml" title="Atom feed">Atom</a> |
          142                                         <a href="mailto:${sitemail}" title="Mail me">Mail</a>
          143                                 </span>
          144                         </div>
          145                 </div>
          146                 <hr class="hidden" />
          147                 <div id="mainwrap">
          148                         <div id="main">
          149 !__EOF__
          150 }
          151 
          152 pagecontent() {
          153         pageheader
          154         cat <<!__EOF__
          155                 <h1><a href="">${title}</a></h1>
          156                 <em>${created}</em>
          157                 ${content}
          158 !__EOF__
          159         pagefooter
          160 }
          161 
          162 pagefooter() {
          163         cat <<!__EOF__
          164                         </div>
          165                 </div>
          166         </body>
          167 </html>
          168 !__EOF__
          169 }
          170 
          171 if ! test -d "${pagesdir}"; then
          172         printf 'Error: pages directory "%s" not found.\n' "${pagesdir}" >&2
          173         exit 1
          174 fi
          175 
          176 # process single page as argument (handy for testing a single page).
          177 if test -n "$1"; then
          178         pagereset
          179         pageread "$1" || exit 1
          180         pagecontent
          181         exit 0
          182 fi
          183 
          184 # try to make output dir.
          185 mkdir -p "${outputdir}"
          186 
          187 # truncate urllist.txt (sitemap).
          188 > "${outputdir}/urllist.txt"
          189 # content for RSS, Atom sitemap and index, this is appended as a string.
          190 contentindex=""
          191 contentrss=""
          192 contentatom=""
          193 contentsitemap=""
          194 while read -r meta; do
          195         pagereset
          196         pageread "${meta}" || continue
          197         pagecontent > "${outputdir}/${outfile}"
          198 
          199         # index / posts item: append.
          200         contentindex="${contentindex}$(cat <<!__EOF__
          201                 <tr><td>${dateupdated}</td>
          202                 <td><a href="${url}" title="${description}">${title}</a></td></tr>
          203 !__EOF__
          204 )"
          205 
          206         # RSS item: append.
          207         # NOTE: GMT timezone is hard-coded because %z is not consistent,
          208         # change accordingly.
          209         contentrsspubdate=$(formatdate "%a, %d %b %Y %H:%M:%S GMT" "${timeupdated}")
          210         contentrss="${contentrss}$(
          211         cat <<!__EOF__
          212         <item>
          213                 <title>${title}</title>
          214                 <link>${urlfull}</link>
          215                 <pubDate>${contentrsspubdate}</pubDate>
          216                 <author>${author}</author>
          217                 <guid isPermaLink="false">${urlfull}</guid>
          218                 <description><![CDATA[${description}]]></description>
          219         </item>
          220 !__EOF__
          221 )"
          222 
          223         # Atom item: append.
          224         contentatomupdated=$(formatdate "%Y-%m-%dT%H:%M:%SZ" "${timeupdated}")
          225         contentatompublished=$(formatdate "%Y-%m-%dT%H:%M:%SZ" "${timecreated}")
          226         contentatom="${contentatom}$(
          227         cat <<!__EOF__
          228         <entry>
          229                 <title type="html"><![CDATA[${title}]]></title>
          230                 <link rel="alternate" type="text/html" href="${urlfull}" />
          231                 <id>${urlfull}</id>
          232                 <updated>${contentatomupdated}</updated>
          233                 <published>${contentatompublished}</published>
          234                 <author>
          235                         <name>${author}</name>
          236                         <uri>${siteurlfull}</uri>
          237                 </author>
          238                 <summary type="html"><![CDATA[${description}]]></summary>
          239         </entry>
          240 !__EOF__
          241 )"
          242 
          243         # sitemap: sitemap.xml, append item.
          244         contentsitemap="${contentsitemap}<url><loc>${urlfull}</loc></url>"
          245 
          246         # sitemap: urllist.txt, append item, write directly to file, because
          247         # this is just a plain-text list.
          248         printf '%s\n' "${urlfull}" >> "${outputdir}/urllist.txt"
          249 done <<!FILELIST
          250 $(find "${pagesdir}" -type f -name "*.sh" | sort -rn)
          251 !FILELIST
          252 # process pages (reverse numeric order).
          253 # NOTE: above heredoc is used to make sure content* variables are known
          254 # in the scope after the while loop (subshell / pipes prevents this in a
          255 # standard manner).
          256 
          257 # index HTML page (index.html).
          258 pagereset
          259 title="Posts"
          260 (pageheader
          261 cat <<!__EOF__
          262         <h1>${title}</h1>
          263         <table>
          264                 ${contentindex}
          265         </table>
          266 !__EOF__
          267 pagefooter) > "${outputdir}/index.html"
          268 
          269 # RSS feed (rss.xml).
          270 cat <<!__EOF__ > "${outputdir}/rss.xml"
          271 <?xml version="1.0" encoding="UTF-8"?>
          272 <rss version="2.0">
          273         <channel>
          274                 <title>${sitetitle}</title>
          275                 <link>${siteurlfull}</link>
          276                 <description>${sitedescription}</description>
          277                 <language>${sitelang}</language>
          278                 ${contentrss}
          279         </channel>
          280 </rss>
          281 !__EOF__
          282 
          283 # Atom feed (atom.xml).
          284 cat <<!__EOF__ > "${outputdir}/atom.xml"
          285 <?xml version="1.0" encoding="UTF-8"?>
          286 <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="${sitelang}">
          287         <title type="text">${sitetitle}</title>
          288         <subtitle type="text">${sitedescription}</subtitle>
          289         <updated>${siteupdated}</updated>
          290         <link rel="alternate" type="text/html" href="${siteurlfull}" />
          291         <id>${siteurlfull}/atom.xml</id>
          292         <link rel="self" type="application/atom+xml" href="${siteurlfull}/atom.xml" />
          293         ${contentatom}
          294 </feed>
          295 !__EOF__
          296 
          297 # sitemap (sitemap.xml).
          298 cat <<!__EOF__ > "${outputdir}/sitemap.xml"
          299 <?xml version="1.0" encoding="UTF-8"?><urlset>${contentsitemap}</urlset>
          300 !__EOF__