From aa547f522941c9ba3c60dd0083305c59f717cedd Mon Sep 17 00:00:00 2001 From: keni7385 Date: Sat, 4 Jun 2022 00:09:16 +0300 Subject: Initial commit --- .../notes/a-simple-static-website-generator.html | 307 +++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 _pages/notes/a-simple-static-website-generator.html (limited to '_pages/notes/a-simple-static-website-generator.html') diff --git a/_pages/notes/a-simple-static-website-generator.html b/_pages/notes/a-simple-static-website-generator.html new file mode 100644 index 0000000..e5399a8 --- /dev/null +++ b/_pages/notes/a-simple-static-website-generator.html @@ -0,0 +1,307 @@ +TITLE="Andrea Corsini's Notes - A simple static website generator" +DESCRIPTION="I share and explain my simple static website generator, written in SHell scriptng from scratch." +--- +
+
+

A simple static website generator (sswg)

+ +
+ + +

Why bother creating another static website generator? There are so many + awesome projects out in the open source community, such as Jekyll, Hugo, + just to name few of them. Well, I wanted to have something dead simple, but + also flexible enough to be easily customized. So I wrote my own simple + static website generator (sswg) using SHell scripting.

+ + +

This is possible because I don't need many features yet. In the future, I + could end up in switching to a proper generator. Anyway, for the time being I + can just use mine and share it here. Hopefully, it could be useful for other + folks that want to practice shell scripting, and/or want to implement their + website generator.

+ +

Here, you will find the original version and its rationale. Most likely, + the generator will change to cope with my website needs. You can find the + current version in my git + repository.

+ +

Features

+

At the time of writing, I am a simple person. I just want to: +

+

+ +

Anything more than that is not necessary at the moment. For example, I + don't need Markdown or other languages to write pages, plain HTML is good + enough. In the future, it would be nice to have some extra features, like + automatic generation of RSS and Table of Content (TOC).

+ +

Folder structure

+

My sswg is just a tiny shell script to include in the website root. In this + way, it can be versioned along all the other website code. The script expect + to find a folder tree similar to

+ + + ├── _assets
+ │    ├── style.css
+ │    ├── favicon.ico
+ │    ├── images
+ │    │     └── picture.png
+ │    └── rss.xml
+ ├── _footer.t.html
+ ├── _header.t.html
+ ├── _pages
+ │     ├── email.html
+ │     ├── index.html
+ │     ├── my-notes.html
+ │     ├── notes
+ │     │     └── a-simple-static-website-generator.html
+ │     └── privacy-policy.html
+ └── sswg.sh +
+ +

Only the elements in bold are mandatory. The other files and folders + are there to showcase. Once the script is invoked with ./sswg.sh, + sswg will regenerate the website to the output folder, named _static. + Any content of the direcorty _asset will be copied to the root + of _static. The content of template + files _header.t.html and _footer.t.html are preposed + and appended to each HTML page, respectively. The sswg will copy to the output + folder all the HTML files contained in _page, as well as + sub-directories and images.

+ +

The output folder _static for this example will result in

+ + + ├── style.css
+ ├── favicon.ico
+ ├── images
+ │     └── picture.png
+ ├── rss.xml
+ ├── email.html
+ ├── index.html
+ ├── my-notes.html
+ ├── notes
+ │     └── a-simple-static-website-generator.html
+ └── privacy-policy.html
+
+ + +

Add a webpage

+

Each HTML page in the directory _page only contains the main + content, while header and footer are shared in every page. Thus we don't need + to copy them every time.

+ +

So, adding a page is very easy. Save every new page within the + folder _page, or in one of its subfolders. Start with the first + two lines by defining the title and description for this page, by using the + macro T‍ITLE and D‍ESCRIPTION from sswg custom syntax. Then + separate the macro from the rest of the page with 3 dashes "---". + For example:

+ + |
+  |T‍ITLE="My new web page"
+  |D‍ESCRIPTION="This page contains information about..."
+  |---
+  |<h2>TI‍TLE</h2>
+  |# This is a sswg comment.
+  |<p>A page can contain whatever valid HTML code.</p>
+  |
+ +# Test comment. +

The example also shows comments syntaxt. Every line which starts with a + hash mark # is considered as a source comment. Hence, it won't be copied in + the final static HTML page.

+ +

Header and Footer templates

+

Inside _header.t.html write the page content from the DOCTYPE + tag, to the navigation of your page, until the beginning of your main content. + Use the macros TI‍TLE and D‍ESCRIPTION for HTML title + and meta description. The generator will overwrite them with the value specified + within the HTML page. Here an example of header templete:

+ + |
+  |<!DOCTYPE html>
+  |<html>
+  |  <head>
+  |    <title>TI‍TLE</title>
+  |    <meta name="description" content="DE‍SCRIPTION">
+  |    <link rel="stylesheet" type="text/css" href="/css/style.css" media="screen">
+  |    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+  |  </head>
+  |
+  |  <body>
+  |    <header>
+  |      <h1>Generic website title</h1>
+  |      <div>
+  |        <aside>I believe in personal digital freedom</aside>
+  |        <nav>
+  |          <a href="/index.html">Home</a> |
+  |          <a href="/my-notes.html">My notes</a> |
+  |          <a href="/email.html">Email</a>
+  |        </nav>
+  |      </div>
+  |    </header>
+  |    <main>
+  |
+ +

Similarly to the header, _footer.t.html contains all the rest + of the website to be inserted at the end of each page. No macro substitution + is needed in this file. Here an example:

+ + |
+  |    </main>
+  |    <footer>
+  |      <p><a href="/rss.xml"><img src="/images/feed.svg">Feed RSS</a>.
+  |      <p>Copyright &copy; 2020-2021 Acme -
+  |      <a href="/privacy-policy.html">Privacy policy</a></p>
+  |    </footer>
+  |  </body>
+  |</html>
+  |
+ +

Inserting verbatim source code

+

I would like the HTML code assembled by sswg to maintain a proper + indentation. Therefore, the script takes care about indenting the page + contents between the header and footer templates. However, this is an issue + for the verbatim source code.

+ +

Indeed, any sort of white-spaces indentation added to the content of the + code block tags (<pre>...</pre>) is interpreted by + browsers as white-space characters of the verbatim code. Therefore, the + white-space characters will appear in the code blocks, resulting in unwanted + spaces.

+ +

To solve this issue, I decided to prepose every code block with a pipe + character |. The sswg script will take care in removing the pipe and + white-space characters. For example, the code

+ + |
+  |    |<pre>
+  |    |cd
+  |    |ls -la
+  |    |</pre>
+  |
+ +

will be transformed into the HTML source code

+ + |
+  |<pre>
+  |cd
+  |ls -la
+  |</pre>
+  |
+ +

Code step by step

+

By the time you will read this article, the code might have changed. So you + will find the current version in the + repository git.andreacorsini.xyz/sswg.

+ +

For what concern the early static website generator script, it starts by + setting constants for folders and template elements:

+ + |
+  |#!/bin/sh
+  |
+  |SSWG_OUTPUT_DIR="_static"
+  |SSWG_ASSETS_DIR="_assets"
+  |SSWG_PAGES_DIR="_pages"
+  |SSWG_HEADER_TEMPLATE="_header.t.html"
+  |SSWG_FOOTER_TEMPLATE="_footer.t.html"
+  |
+ +

Second, the output folder _static is cleaned:

+ + |
+  |rm -rf "$SSWG_OUTPUT_DIR"
+  |mkdir "$SSWG_OUTPUT_DIR"
+  |
+ +

So, be careful if you copied something inside it. It is wiser to copy + external files into _assets, as they will be automatically copied + back into _static:

+ + |
+  |cp -r "$SSWG_ASSETS_DIR"/* "$SSWG_OUTPUT_DIR"/.
+  |
+ +

Then, we can finally generate each HTML page:

+ |
+  |for page in $(find "$SSWG_PAGES_DIR" -iname '*.html' -o \
+  |                   -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png');
+  |do
+  |    filename="$SSWG_OUTPUT_DIR/${page##$SSWG_PAGES_DIR/}"
+  |    mkdir -p "`dirname $filename`"
+  |
+  |    if [ "${filename##*.}" = "html" ]; then
+  |
+ +

Prepose the header template:

+ |
+  |        cat "$SSWG_HEADER_TEMPLATE" >> "$filename"
+  |
+ +

Indentation in the page content to match the header level:

+ |
+  |        cat "$page" | awk '
+  |        BEGIN {print ""}
+  |        FNR>3 {print "      " $0}
+  |        END {print ""}' >> "$filename"
+  |
+ +

Append the footer template:

+ |
+  |        cat "$SSWG_FOOTER_TEMPLATE" >> "$filename"
+  |
+ +

To perform the macro substitution, firstly shell-evaluate the first two + lines of the page. They are supposed to contain a shell-like declaration of the + variables TI‍TLE and DES‍CRIPTION. Secondly, each macro can be + substituted in the whole document.

+ |
+  |        eval `cat "$page" | awk 'FNR<3'`
+  |        sed -i'' "s@TI‍TLE@$TIT‍LE@g" "$filename"
+  |        sed -i'' "s@DES‍CRIPTION@$DES‍CRIPTION@g" "$filename"
+  |
+ +

We can now remove comments and pipe + white-spaces:

+ |
+  |        sed -i'' "/^[ \t]*#/d" "$filename"
+  |        sed -i'' "s/^[ \t]*|//g" "$filename"
+  |
+ +

Continue with the rest of the script. If we are not reading an HTML file, + it could be either an image or a folder. Just copy it to its destination + in _static:

+ + |
+  |    else
+  |        cp $page $filename
+  |    fi;
+  |done;
+  |
+ +
+

Conclusion

+

Static website generators are valid lightweight alternatives to more + complicate and larger content management systems (CMS), such as Wordpress. + They are normally simple to use, requires no databases, neither complicated + install procedures. Users are in control throught text files.

+ +

This post showed how to write a simple static website generator (sswg) to get our + web pages started. So far, the generator script has only bare-bones + functionalities, but it is simple enough to be extended with additional + features.

+ +

I hope you found this post useful and interesting. Don't hesitate to + contact me for any questions or comments.

+ +
-- cgit v1.2.3-70-g09d2