aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE20
-rw-r--r--README.md41
-rw-r--r--example/dst/.files11
-rw-r--r--example/dst/404.html33
-rw-r--r--example/dst/Articles/an-interesting-article/assets/stamps.webpbin0 -> 46960 bytes
-rw-r--r--example/dst/Articles/an-interesting-article/index.html37
-rw-r--r--example/dst/Articles/another-interesting-article/assets/japanese-train.webpbin0 -> 128168 bytes
-rw-r--r--example/dst/Articles/another-interesting-article/index.html37
-rw-r--r--example/dst/Articles/article3.html33
-rw-r--r--example/dst/Lists/board-games.html41
-rw-r--r--example/dst/Lists/movies.html41
-rw-r--r--example/dst/about.html33
-rw-r--r--example/dst/favicon.pngbin0 -> 393 bytes
-rw-r--r--example/dst/hed28
-rw-r--r--example/dst/index.html41
-rw-r--r--example/dst/sitemap.xml14
-rw-r--r--example/dst/style.css54
-rw-r--r--example/src/404.md3
-rw-r--r--example/src/Articles/an-interesting-article/assets/stamps.webpbin0 -> 46960 bytes
-rw-r--r--example/src/Articles/an-interesting-article/index.md12
-rw-r--r--example/src/Articles/another-interesting-article/assets/japanese-train.webpbin0 -> 128168 bytes
-rw-r--r--example/src/Articles/another-interesting-article/index.md12
-rw-r--r--example/src/Articles/article3.md8
-rw-r--r--example/src/Lists/board-games.md14
-rw-r--r--example/src/Lists/movies.md13
-rw-r--r--example/src/_footer.html2
-rw-r--r--example/src/_header.html28
-rw-r--r--example/src/about.md3
-rw-r--r--example/src/favicon.pngbin0 -> 393 bytes
-rw-r--r--example/src/style.css54
-rwxr-xr-xssg-blog288
31 files changed, 892 insertions, 9 deletions
diff --git a/LICENSE b/LICENSE
index b9c199c..0f23fe1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,8 +1,12 @@
-ISC License:
-
-Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1995-2003 by Internet Software Consortium
-
-Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+# Copyright 2018-2019 Roman Zolotarev <hi@romanzolotarev.com>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
diff --git a/README.md b/README.md
index ef54896..1e48f8c 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,42 @@
# ssg-blog
-A minor modification to the 'ssg' bash script to generate a simple blog \ No newline at end of file
+This is a modification to the simple static site generator '[ssg](https://romanzolotarev.com/bin/ssg)' by Roman Zolotarev. This generates a minimal blog index page with category headings.
+
+# Install / Usage
+
+See [https://romansolotarev.com/ssg.html](https://romanzolotarev.com/ssg.html) for documentation on ssg
+
+In short:
+1. Install [lowdown](https://kristaps.bsd.lv/lowdown/)
+2. Copy the `ssg` script somewhere in your path, e.g. `/usr/bin/`
+3. `chmod +x /usr/bin/ssg`
+4. `ssg src dst 'my-website-name' 'https://my-website.net'`
+
+ssg-blog checks for subdirectories in the src directory, each of which becomes a category heading (non-recursively). It will generate a sorted list of links to any .md file in those directory (including nested directories). Each .md file needs frontmatter including the title and a YYYY-MM-DD date like this to be included in the index page:
+
+```markdown
+---
+title: My Blog Post
+date: 2024-10-09
+---
+```
+
+## Example
+
+There is an example directory in this repo to show you how to set up the files (src) and what the output looks like (dst). Note how articles can be nested in subdirectories or not and that the articles titled index.md get links created without .html appended. This was the command used to generate the example output:
+
+```
+./ssg-blog example/src example/dst 'example-site-name' 'https://example.org'
+```
+
+## Change how categories are sorted
+
+The category headings are sorted alphabetically. If you want to change this, you have to edit the `sort` on this line:
+
+```
+find "$src" -mindepth 1 -maxdepth 1 -type d ! -path "*/.*" | sort |
+```
+
+# Alternatives
+
+You might also be interested in the similar fork [fmash16/ssg5](https://github.com/fmash16/ssg5) which generates a more traditional blog with pagination, keywords, and post previews.
diff --git a/example/dst/.files b/example/dst/.files
new file mode 100644
index 0000000..1611884
--- /dev/null
+++ b/example/dst/.files
@@ -0,0 +1,11 @@
+./style.css
+./Lists/board-games.md
+./Lists/movies.md
+./about.md
+./Articles/an-interesting-article/index.md
+./Articles/an-interesting-article/assets/stamps.webp
+./Articles/another-interesting-article/index.md
+./Articles/another-interesting-article/assets/japanese-train.webp
+./Articles/article3.md
+./404.md
+./favicon.png
diff --git a/example/dst/404.html b/example/dst/404.html
new file mode 100644
index 0000000..b56836c
--- /dev/null
+++ b/example/dst/404.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
+<h1>404 Not Found</h1>
+
+<p>I couldn't find that page.</p>
+</body>
+</html>
diff --git a/example/dst/Articles/an-interesting-article/assets/stamps.webp b/example/dst/Articles/an-interesting-article/assets/stamps.webp
new file mode 100644
index 0000000..9785ce7
--- /dev/null
+++ b/example/dst/Articles/an-interesting-article/assets/stamps.webp
Binary files differ
diff --git a/example/dst/Articles/an-interesting-article/index.html b/example/dst/Articles/an-interesting-article/index.html
new file mode 100644
index 0000000..412e359
--- /dev/null
+++ b/example/dst/Articles/an-interesting-article/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
+<h1>This is a very interesting article about stamps</h1>
+
+<p>Here is a picture of some cool stamps</p>
+
+<p><img src="assets/stamps.webp" alt="" title="" /></p>
+
+<p>Thank you for reading my nice article.</p>
+</body>
+</html>
diff --git a/example/dst/Articles/another-interesting-article/assets/japanese-train.webp b/example/dst/Articles/another-interesting-article/assets/japanese-train.webp
new file mode 100644
index 0000000..c4cab3e
--- /dev/null
+++ b/example/dst/Articles/another-interesting-article/assets/japanese-train.webp
Binary files differ
diff --git a/example/dst/Articles/another-interesting-article/index.html b/example/dst/Articles/another-interesting-article/index.html
new file mode 100644
index 0000000..31ef880
--- /dev/null
+++ b/example/dst/Articles/another-interesting-article/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
+<h1>I love trains</h1>
+
+<p>Aren't Japanese trains great? I particularly like the boxy ones. Here is a picture of a train:</p>
+
+<p><img src="assets/japanese-train.webp" alt="" title="" /></p>
+
+<p>Thank you for looking at this train</p>
+</body>
+</html>
diff --git a/example/dst/Articles/article3.html b/example/dst/Articles/article3.html
new file mode 100644
index 0000000..e34e43a
--- /dev/null
+++ b/example/dst/Articles/article3.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
+<h1>Article 3</h1>
+
+<p>Wow another one</p>
+</body>
+</html>
diff --git a/example/dst/Lists/board-games.html b/example/dst/Lists/board-games.html
new file mode 100644
index 0000000..1693d1b
--- /dev/null
+++ b/example/dst/Lists/board-games.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
+<h1>Board Games</h1>
+
+<p>Here are some board games I like:</p>
+
+<ol>
+<li>Puerto Rico</li>
+<li>Ascension: Chronicle of the Godslayer</li>
+<li>Twilight Struggle</li>
+</ol>
+
+<p>Play them with me, thanks.</p>
+</body>
+</html>
diff --git a/example/dst/Lists/movies.html b/example/dst/Lists/movies.html
new file mode 100644
index 0000000..a3499e5
--- /dev/null
+++ b/example/dst/Lists/movies.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
+<h1>A List of Movies</h1>
+
+<p>Here are my favorite movies</p>
+
+<ol>
+<li>Primer</li>
+<li>The Lighthouse</li>
+<li>Tetsuo: The Iron Man</li>
+</ol>
+
+<p>I hope you enjoyed this insightful article.</p>
+</body>
+</html>
diff --git a/example/dst/about.html b/example/dst/about.html
new file mode 100644
index 0000000..51897a4
--- /dev/null
+++ b/example/dst/about.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
+<h1>About</h1>
+
+<p>Here is an about page for my website</p>
+</body>
+</html>
diff --git a/example/dst/favicon.png b/example/dst/favicon.png
new file mode 100644
index 0000000..4c22246
--- /dev/null
+++ b/example/dst/favicon.png
Binary files differ
diff --git a/example/dst/hed b/example/dst/hed
new file mode 100644
index 0000000..d90b226
--- /dev/null
+++ b/example/dst/hed
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
diff --git a/example/dst/index.html b/example/dst/index.html
new file mode 100644
index 0000000..8deec2f
--- /dev/null
+++ b/example/dst/index.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
+<h1>Articles</h1>
+<ul>
+<li>2024-10-04: <a href="https://example.org/Articles/an-interesting-article/">This is a very interesting article about stamps</a></li>
+<li>2024-09-10: <a href="https://example.org/Articles/another-interesting-article/">I love trains</a></li>
+<li>2023-10-08: <a href="https://example.org/Articles/article3.html">This is a third article!</a></li>
+</ul>
+<h1>Lists</h1>
+<ul>
+<li>2024-07-12: <a href="https://example.org/Lists/board-games.html">Board games</a></li>
+<li>2022-06-05: <a href="https://example.org/Lists/movies.html">Movies</a></li>
+</ul>
+</body>
+</html>
diff --git a/example/dst/sitemap.xml b/example/dst/sitemap.xml
new file mode 100644
index 0000000..6c057b3
--- /dev/null
+++ b/example/dst/sitemap.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<urlset
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
+http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
+xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+<url><loc>https://example.org/Lists/board-games.html</loc><lastmod>2024-10-09</lastmod><priority>1.0</priority></url>
+<url><loc>https://example.org/Lists/movies.html</loc><lastmod>2024-10-09</lastmod><priority>1.0</priority></url>
+<url><loc>https://example.org/about.html</loc><lastmod>2024-10-09</lastmod><priority>1.0</priority></url>
+<url><loc>https://example.org/Articles/an-interesting-article/</loc><lastmod>2024-10-09</lastmod><priority>1.0</priority></url>
+<url><loc>https://example.org/Articles/another-interesting-article/</loc><lastmod>2024-10-09</lastmod><priority>1.0</priority></url>
+<url><loc>https://example.org/Articles/article3.html</loc><lastmod>2024-10-09</lastmod><priority>1.0</priority></url>
+<url><loc>https://example.org/404.html</loc><lastmod>2024-10-09</lastmod><priority>1.0</priority></url>
+</urlset>
diff --git a/example/dst/style.css b/example/dst/style.css
new file mode 100644
index 0000000..4489ae8
--- /dev/null
+++ b/example/dst/style.css
@@ -0,0 +1,54 @@
+html {
+ font-size: 100%;
+ font-family:sans-serif;
+ /* font-family:sans-serif; */
+ /* font:1.2em/1.62 sans-serif; */
+}
+
+body {
+ line-height: 1.6;
+ max-width:40em;
+ background-color: #ededed;
+ margin: auto;
+}
+
+.container {
+ text-align: center;
+}
+
+.container pre {
+ display: inline-block;
+ text-align: left;
+ line-height: 1.0;
+}
+
+#header {
+ text-decoration: none;
+ color: inherit;
+ font-size:125%;
+}
+
+#navigation {
+ font-family:monospace;
+ font-size:125%;
+}
+
+h1 { font-size: 1.4rem; }
+h2 { font-size: 1.2rem; }
+h3 { font-size: 1.0rem;}
+
+a:link, a:visited {
+ color: #2626FF;
+}
+
+a:hover, a:focus {
+ color: #4c4cFF;
+}
+
+li + li {
+ margin-top:1em;
+}
+
+ul img {
+ vertical-align:middle;
+}
diff --git a/example/src/404.md b/example/src/404.md
new file mode 100644
index 0000000..a0aa728
--- /dev/null
+++ b/example/src/404.md
@@ -0,0 +1,3 @@
+# 404 Not Found
+
+I couldn't find that page.
diff --git a/example/src/Articles/an-interesting-article/assets/stamps.webp b/example/src/Articles/an-interesting-article/assets/stamps.webp
new file mode 100644
index 0000000..9785ce7
--- /dev/null
+++ b/example/src/Articles/an-interesting-article/assets/stamps.webp
Binary files differ
diff --git a/example/src/Articles/an-interesting-article/index.md b/example/src/Articles/an-interesting-article/index.md
new file mode 100644
index 0000000..779f4b6
--- /dev/null
+++ b/example/src/Articles/an-interesting-article/index.md
@@ -0,0 +1,12 @@
+---
+title: This is a very interesting article about stamps
+date: 2024-10-04
+---
+
+# This is a very interesting article about stamps
+
+Here is a picture of some cool stamps
+
+![](assets/stamps.webp)
+
+Thank you for reading my nice article.
diff --git a/example/src/Articles/another-interesting-article/assets/japanese-train.webp b/example/src/Articles/another-interesting-article/assets/japanese-train.webp
new file mode 100644
index 0000000..c4cab3e
--- /dev/null
+++ b/example/src/Articles/another-interesting-article/assets/japanese-train.webp
Binary files differ
diff --git a/example/src/Articles/another-interesting-article/index.md b/example/src/Articles/another-interesting-article/index.md
new file mode 100644
index 0000000..4e5d9b7
--- /dev/null
+++ b/example/src/Articles/another-interesting-article/index.md
@@ -0,0 +1,12 @@
+---
+title: I love trains
+date: 2024-09-10
+---
+
+# I love trains
+
+Aren't Japanese trains great? I particularly like the boxy ones. Here is a picture of a train:
+
+![](assets/japanese-train.webp)
+
+Thank you for looking at this train
diff --git a/example/src/Articles/article3.md b/example/src/Articles/article3.md
new file mode 100644
index 0000000..c98ebba
--- /dev/null
+++ b/example/src/Articles/article3.md
@@ -0,0 +1,8 @@
+---
+title: This is a third article!
+date: 2023-10-08
+---
+
+# Article 3
+
+Wow another one
diff --git a/example/src/Lists/board-games.md b/example/src/Lists/board-games.md
new file mode 100644
index 0000000..6a40080
--- /dev/null
+++ b/example/src/Lists/board-games.md
@@ -0,0 +1,14 @@
+---
+title: Board games
+date: 2024-07-12
+---
+
+# Board Games
+
+Here are some board games I like:
+
+1. Puerto Rico
+2. Ascension: Chronicle of the Godslayer
+3. Twilight Struggle
+
+Play them with me, thanks.
diff --git a/example/src/Lists/movies.md b/example/src/Lists/movies.md
new file mode 100644
index 0000000..92d82e6
--- /dev/null
+++ b/example/src/Lists/movies.md
@@ -0,0 +1,13 @@
+---
+title: Movies
+date: 2022-06-05
+---
+# A List of Movies
+
+Here are my favorite movies
+
+1. Primer
+2. The Lighthouse
+3. Tetsuo: The Iron Man
+
+I hope you enjoyed this insightful article.
diff --git a/example/src/_footer.html b/example/src/_footer.html
new file mode 100644
index 0000000..308b1d0
--- /dev/null
+++ b/example/src/_footer.html
@@ -0,0 +1,2 @@
+</body>
+</html>
diff --git a/example/src/_header.html b/example/src/_header.html
new file mode 100644
index 0000000..d90b226
--- /dev/null
+++ b/example/src/_header.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <link rel="icon" type="image/png" href="https://example.org/favicon.png">
+ <link rel="stylesheet" href="style.css">
+ <title>Example</title>
+</head>
+<body>
+<div class="container">
+<a id="header" href="https://example.org">
+<pre>
+
+▄███▄ ▄ ██ █▀▄▀█ █ ▄▄ █ ▄███▄
+█▀ ▀ ▀▄ █ █ █ █ █ █ █ █ █ █▀ ▀
+██▄▄ █ ▀ █▄▄█ █ ▄ █ █▀▀▀ █ ██▄▄
+█▄ ▄▀ ▄ █ █ █ █ █ █ ███▄ █▄ ▄▀
+▀███▀ █ ▀▄ █ █ █ ▀ ▀███▀
+ ▀ █ ▀ ▀
+ ▀
+</pre>
+</a>
+<div id="navigation">
+<a href="https://example.org/">Home</a> -
+<a href="https://codeberg.org">Repos</a> -
+<a href="https://example.org/about.html">About</a>
+</div>
+</div>
diff --git a/example/src/about.md b/example/src/about.md
new file mode 100644
index 0000000..1b073d8
--- /dev/null
+++ b/example/src/about.md
@@ -0,0 +1,3 @@
+# About
+
+Here is an about page for my website
diff --git a/example/src/favicon.png b/example/src/favicon.png
new file mode 100644
index 0000000..4c22246
--- /dev/null
+++ b/example/src/favicon.png
Binary files differ
diff --git a/example/src/style.css b/example/src/style.css
new file mode 100644
index 0000000..4489ae8
--- /dev/null
+++ b/example/src/style.css
@@ -0,0 +1,54 @@
+html {
+ font-size: 100%;
+ font-family:sans-serif;
+ /* font-family:sans-serif; */
+ /* font:1.2em/1.62 sans-serif; */
+}
+
+body {
+ line-height: 1.6;
+ max-width:40em;
+ background-color: #ededed;
+ margin: auto;
+}
+
+.container {
+ text-align: center;
+}
+
+.container pre {
+ display: inline-block;
+ text-align: left;
+ line-height: 1.0;
+}
+
+#header {
+ text-decoration: none;
+ color: inherit;
+ font-size:125%;
+}
+
+#navigation {
+ font-family:monospace;
+ font-size:125%;
+}
+
+h1 { font-size: 1.4rem; }
+h2 { font-size: 1.2rem; }
+h3 { font-size: 1.0rem;}
+
+a:link, a:visited {
+ color: #2626FF;
+}
+
+a:hover, a:focus {
+ color: #4c4cFF;
+}
+
+li + li {
+ margin-top:1em;
+}
+
+ul img {
+ vertical-align:middle;
+}
diff --git a/ssg-blog b/ssg-blog
new file mode 100755
index 0000000..6eb7ed5
--- /dev/null
+++ b/ssg-blog
@@ -0,0 +1,288 @@
+#!/bin/sh -e
+#
+# https://rgz.ee/bin/ssg6
+# Copyright 2018-2019 Roman Zolotarev <hi@romanzolotarev.com>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+main() {
+ test -n "$1" || usage
+ test -n "$2" || usage
+ test -n "$3" || usage
+ test -n "$4" || usage
+ test -d "$1" || no_dir "$1"
+ test -d "$2" || no_dir "$2"
+
+ src=$(readlink_f "$1")
+ dst=$(readlink_f "$2")
+
+ IGNORE=$(
+ if ! test -f "$src/.ssgignore"; then
+ printf ' ! -path "*/.*"'
+ return
+ fi
+ while read -r x; do
+ test -n "$x" || continue
+ printf ' ! -path "*/%s*"' "$x"
+ done <"$src/.ssgignore"
+ )
+
+ # files
+
+ title="$3"
+
+ h_file="$src/_header.html"
+ f_file="$src/_footer.html"
+ test -f "$f_file" && FOOTER=$(cat "$f_file") && export FOOTER
+ test -f "$h_file" && HEADER=$(cat "$h_file") && export HEADER
+
+ list_dirs "$src" |
+ (cd "$src" && cpio -pdu "$dst")
+
+ fs=$(
+ if test -f "$dst/.files"; then
+ list_affected_files "$src" "$dst/.files"
+ else
+ list_files "$1"
+ fi
+ )
+
+ if test -n "$fs"; then
+ echo "$fs" | tee "$dst/.files"
+
+ if echo "$fs" | grep -q '\.md$'; then
+ if test -x "$(which lowdown 2>/dev/null)"; then
+ echo "$fs" | grep '\.md$' |
+ render_md_files_lowdown "$src" "$dst" "$title"
+ else
+ if test -x "$(which Markdown.pl 2>/dev/null)"; then
+ echo "$fs" | grep '\.md$' |
+ render_md_files_Markdown_pl "$src" "$dst" "$title"
+ else
+ echo "couldn't find lowdown nor Markdown.pl"
+ exit 3
+ fi
+ fi
+ fi
+
+ echo "$fs" | grep '\.html$' |
+ render_html_files "$src" "$dst" "$title"
+
+ echo "$fs" | grep -Ev '\.md$|\.html$' |
+ (cd "$src" && cpio -pu "$dst")
+ fi
+
+ printf '[ssg] ' >&2
+ print_status 'file, ' 'files, ' "$fs" >&2
+
+ # sitemap
+
+ base_url="$4"
+ date=$(date +%Y-%m-%d)
+ urls=$(list_pages "$src")
+
+ test -n "$urls" &&
+ render_sitemap "$urls" "$base_url" "$date" >"$dst/sitemap.xml"
+
+ render_index
+
+ print_status 'url' 'urls' "$urls" >&2
+ echo >&2
+
+}
+
+readlink_f() {
+ file="$1"
+ cd "$(dirname "$file")"
+ file=$(basename "$file")
+ while test -L "$file"; do
+ file=$(readlink "$file")
+ cd "$(dirname "$file")"
+ file=$(basename "$file")
+ done
+ dir=$(pwd -P)
+ echo "$dir/$file"
+}
+
+print_status() {
+ test -z "$3" && printf 'no %s' "$2" && return
+
+ echo "$3" | awk -v singular="$1" -v plural="$2" '
+ END {
+ if (NR==1) printf NR " " singular
+ if (NR>1) printf NR " " plural
+ }'
+}
+
+usage() {
+ echo "usage: ${0##*/} src dst title base_url" >&2
+ exit 1
+}
+
+no_dir() {
+ echo "${0##*/}: $1: No such directory" >&2
+ exit 2
+}
+
+list_dirs() {
+ cd "$1" && eval "find . -type d ! -name '.' ! -path '*/_*' $IGNORE"
+}
+
+list_files() {
+ cd "$1" && eval "find . -type f ! -name '.' ! -path '*/_*' $IGNORE"
+}
+
+list_dependant_files() {
+ e="\\( -name '*.html' -o -name '*.md' -o -name '*.css' -o -name '*.js' \\)"
+ cd "$1" && eval "find . -type f ! -name '.' ! -path '*/_*' $IGNORE $e"
+}
+
+list_newer_files() {
+ cd "$1" && eval "find . -type f ! -name '.' $IGNORE -newer $2"
+}
+
+has_partials() {
+ grep -qE '^./_.*\.html$|^./_.*\.js$|^./_.*\.css$'
+}
+
+list_affected_files() {
+ fs=$(list_newer_files "$1" "$2")
+
+ if echo "$fs" | has_partials; then
+ list_dependant_files "$1"
+ else
+ echo "$fs"
+ fi
+}
+
+render_html_files() {
+ while read -r f; do
+ render_html_file "$3" <"$1/$f" >"$2/$f"
+ done
+}
+
+render_md_files_lowdown() {
+ while read -r f; do
+ sed '1 { /^---/ { :a N; /\n---/! ba; d} }' "$1/$f" |
+ lowdown \
+ --html-no-escapehtml \
+ --html-no-skiphtml \
+ --parse-no-metadata \
+ --parse-no-autolink |
+ render_html_file "$3" \
+ >"$2/${f%\.md}.html"
+ done
+}
+
+render_md_files_Markdown_pl() {
+ while read -r f; do
+ sed '1 { /^---/ { :a N; /\n---/! ba; d} }' "$1/$f" |
+ Markdown.pl |
+ render_html_file "$3" \
+ >"$2/${f%\.md}.html"
+ done
+}
+
+render_html_file() {
+ # h/t Devin Teske
+ awk -v title="$1" '
+ { body = body "\n" $0 }
+ END {
+ body = substr(body, 2)
+ if (body ~ /<\/?[Hh][Tt][Mm][Ll]/) {
+ print body
+ exit
+ }
+ if (match(body, /<[[:space:]]*[Hh]1(>|[[:space:]][^>]*>)/)) {
+ t = substr(body, RSTART + RLENGTH)
+ sub("<[[:space:]]*/[[:space:]]*[Hh]1.*", "", t)
+ gsub(/^[[:space:]]*|[[:space:]]$/, "", t)
+ if (t) title = t " &mdash; " title
+ }
+ n = split(ENVIRON["HEADER"], header, /\n/)
+ for (i = 1; i <= n; i++) {
+ if (match(tolower(header[i]), "<title></title>")) {
+ head = substr(header[i], 1, RSTART - 1)
+ tail = substr(header[i], RSTART + RLENGTH)
+ print head "<title>" title "</title>" tail
+ } else print header[i]
+ }
+ print body
+ print ENVIRON["FOOTER"]
+ }'
+}
+
+list_pages() {
+ e="\\( -name '*.html' -o -name '*.md' \\)"
+ cd "$1" && eval "find . -type f ! -path '*/.*' ! -path '*/_*' $IGNORE $e" |
+ sed 's#^./##;s#.md$#.html#;s#/index.html$#/#'
+}
+
+
+render_index() {
+ output="$dst/index.html"
+ echo "$HEADER" > "$output"
+
+ find "$src" -mindepth 1 -maxdepth 1 -type d ! -path "*/.*" | sort |
+ while read -r category_dir; do
+ category=$(basename "$category_dir")
+
+ find "$category_dir" -type f \( -name "*.md" -o -name "index.md" \) ! -path "*/.*" |
+ while read -r article; do
+ title=$(sed -n '/^title: /s/title: //p' "$article" | head -n 1)
+ date=$(sed -n '/^date: /s/date: //p' "$article" | head -n 1)
+
+ article_url="${article#"$src"}"
+ article_url="${article_url%.md}.html"
+ if [ "${article_url##*/}" = "index.html" ]; then
+ article_url="${article_url%/index.html}/"
+ fi
+ article_url="${article_url#/}"
+
+ echo "$date|$title|$article_url" >> "/tmp/articles_$category.txt"
+ done
+
+ if [ -f "/tmp/articles_$category.txt" ]; then
+ echo "<h1>$category</h1>" >> "$output"
+ echo "<ul>" >> "$output"
+ sort -r "/tmp/articles_$category.txt" |
+ while IFS='|' read -r date title url; do
+ echo "<li>$date: <a href=\"$base_url/$url\">$title</a></li>" >> "$output"
+ done
+ echo "</ul>" >> "$output"
+ rm "/tmp/articles_$category.txt"
+ fi
+ done
+
+ echo "$FOOTER" >> "$output"
+}
+
+
+render_sitemap() {
+ urls="$1"
+ base_url="$2"
+ date="$3"
+
+ echo '<?xml version="1.0" encoding="UTF-8"?>'
+ echo '<urlset'
+ echo 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
+ echo 'xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9'
+ echo 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"'
+ echo 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
+ echo "$urls" |
+ sed -E 's#^(.*)$#<url><loc>'"$base_url"'/\1</loc><lastmod>'"$date"'</lastmod><priority>1.0</priority></url>#'
+ echo '</urlset>'
+}
+
+main "$@"