summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid T. Sadler <davidtsadler@googlemail.com>2021-05-14 17:12:36 +0100
committerDavid T. Sadler <davidtsadler@googlemail.com>2021-05-14 17:12:36 +0100
commit5e627d4cbbfb46a05c8a704379d08955248b4ea3 (patch)
tree53fac13157bcca991acd4e00b68177a7a0ef0997
parent7c375848a271cb179938e35c94fb3a18a49bf43a (diff)
Add atom feeds
-rw-r--r--html_templates/default.html16
-rw-r--r--scripts/build.php6
-rw-r--r--scripts/functions.php197
-rw-r--r--src/index.gmi2
-rw-r--r--src/posts/arch/index.gmi2
-rw-r--r--src/posts/gemini/index.gmi2
-rw-r--r--src/posts/index.gmi2
-rw-r--r--src/posts/jigsaw/index.gmi2
-rw-r--r--src/posts/laravel/index.gmi2
-rw-r--r--src/posts/linux/index.gmi2
-rw-r--r--src/posts/markdown/index.gmi2
-rw-r--r--src/posts/netlify/index.gmi2
-rw-r--r--src/posts/nextcloud/index.gmi2
-rw-r--r--src/posts/php/index.gmi2
-rw-r--r--www_assets/css/site.css2
15 files changed, 183 insertions, 60 deletions
diff --git a/html_templates/default.html b/html_templates/default.html
index e7a133d..b9ce3b6 100644
--- a/html_templates/default.html
+++ b/html_templates/default.html
@@ -6,8 +6,18 @@
<title>{{ $title }}</title>
<link rel="shortcut icon" href="/images/favicon.png">
<link rel="stylesheet" href="/css/site.css">
+ <link href="/posts/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts"/>
+ <link href="/posts/arch/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About Arch"/>
+ <link href="/posts/gemini/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About Gemini"/>
+ <link href="/posts/jigsaw/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About Jigsaw"/>
+ <link href="/posts/laravel/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About Laravel"/>
+ <link href="/posts/linux/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About Linux"/>
+ <link href="/posts/markdown/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About Markdown"/>
+ <link href="/posts/netlify/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About Netlify"/>
+ <link href="/posts/nextcloud/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About Nextcloud"/>
+ <link href="/posts/php/atom.xml" type="application/atom+xml" rel="alternate" title="The Home of David T. Sadler - All Posts About PHP"/>
</head>
- <body>
- <section>{{ $contents }}</section>
- </body>
+ <body
+ <section>{{ $contents }}</section>
+ </body>
</html>
diff --git a/scripts/build.php b/scripts/build.php
index ecb0d9d..eecb677 100644
--- a/scripts/build.php
+++ b/scripts/build.php
@@ -104,9 +104,9 @@ if (!is_readable($assetsDiretory)) {
exit(1);
}
-$siteMetaData = getSiteMetaData($src);
+$pages = getPages($src, $geminiOutput, $wwwOutput);
-buildGeminiSite($siteMetaData, $geminiOutput);
+buildGeminiSite($pages);
-buildWWWSite($siteMetaData, $wwwOutput, $htmlTemplateDiretory, $assetsDiretory);
+buildWWWSite($pages, $hostname, $htmlTemplateDiretory, $assetsDiretory, $wwwOutput);
diff --git a/scripts/functions.php b/scripts/functions.php
index f1f4e1e..50acc22 100644
--- a/scripts/functions.php
+++ b/scripts/functions.php
@@ -18,7 +18,7 @@ function usage(): void
exit(1);
}
-function getSiteMetaData(string $src): array
+function getPages(string $src, string $geminiOutput, string $wwwOutput): array
{
$src = realpath($src);
@@ -27,57 +27,74 @@ function getSiteMetaData(string $src): array
\RecursiveIteratorIterator::SELF_FIRST
);
- $metaData = [];
+ $pages = [];
foreach ($iter as $fileInfo) {
if (!is_file($fileInfo->getRealPath())) {
continue;
}
- $metaData[] = getFileMetaData($src, $fileInfo);
+ $pages[] = getPageMetaData($fileInfo, $src, $geminiOutput, $wwwOutput);
}
- return $metaData;
+ return $pages;
}
-function getFileMetaData(string $src, \SplFileInfo $fileInfo): array
+function getPageMetaData(\SplFileInfo $fileInfo, string $src, string $geminiOutput, string $wwwOutput): array
{
$input = $fileInfo->getRealPath();
- $url = str_replace($src, '', $input);
+ $pathData = parsePath($input);
+
+ $geminiUrl = str_replace($src, '', $input);
+ $wwwUrl = str_replace('.gmi', '.html', $geminiUrl);
- $urlData = parseUrl($url);
$contentData = parseContent(file_get_contents($input));
return [
- 'input' => $input,
- 'url' => $url,
- 'date' => $urlData['date'],
- 'category' => $urlData['category'],
- 'isPost' => $urlData['isPost'],
- 'title' => $contentData['title'],
- 'author' => $contentData['author'],
+ 'input' => $input,
+ 'geminiUrl' => $geminiUrl,
+ 'wwwUrl' => $wwwUrl,
+ 'date' => $pathData['date'],
+ 'tag' => $pathData['tag'],
+ 'isPost' => $pathData['isPost'],
+ 'isTag' => $pathData['isTag'],
+ 'title' => $contentData['title'],
+ 'author' => $contentData['author'],
+ 'html' => gemtext2hmtl(file_get_contents($input)),
+ 'geminiOutput' => "$geminiOutput$geminiUrl",
+ 'wwwOutput' => "$wwwOutput$wwwUrl",
];
}
-function parseUrl(string $url): array
+function parsePath(string $path): array
{
$date = null;
- $category = null;
+ $tag = null;
$isPost = false;
+ $isTag = false;
/**
- * Assume that only posts have both a date and a category.
+ * Assume that only posts have both a date and a tag.
*/
- if (preg_match('/\/posts\/(.+)\/(\d\d\d\d-\d\d-\d\d)\//', $url, $matches) === 1) {
- $date = $matches[2];
- $category = $matches[1];
+ if (preg_match('/\/posts\/(.+)\/(\d\d\d\d-\d\d-\d\d)\//', $path, $matches) === 1) {
+ [, $tag, $date] = $matches;
+
$isPost = true;
}
+ /**
+ * Assume tags have an index file that contains related posts.
+ */
+ if (preg_match('/posts\/(?:[^\/]|\/\/)+\/index/', $path, $matches) === 1) {
+ $tag = explode('/', $matches[0])[1];
+ $isTag = true;
+ }
+
return [
- 'date' => $date,
- 'category' => $category,
- 'isPost' => $isPost,
+ 'date' => $date,
+ 'tag' => $tag,
+ 'isPost' => $isPost,
+ 'isTag' => $isTag,
];
}
@@ -100,28 +117,24 @@ function parseContent(string $content): array
];
}
-function buildGeminiSite(array $siteMetaData, string $output): void
+function buildGeminiSite(array $pages): void
{
- foreach ($siteMetaData as $fileMetaData) {
- $destFile = $output.DIRECTORY_SEPARATOR.$fileMetaData['url'];
-
- $destDirectory = dirname($destFile);
+ foreach ($pages as $page) {
+ $destDirectory = dirname($page['geminiOutput']);
if (!file_exists($destDirectory) && !mkdir($destDirectory, 0777, true)) {
echo "Unable to create Gemini site directory $destDirectory.";
exit(1);
}
- copy($fileMetaData['input'], $destFile);
+ copy($page['input'], $page['geminiOutput']);
}
}
-function buildWWWSite(array $siteMetaData, string $output, string $htmlTemplateDiretory, $assetsDiretory): void
+function buildWWWSite(array $pages, string $hostname, string $htmlTemplateDiretory, $assetsDiretory, string $output): void
{
- foreach ($siteMetaData as $fileMetaData) {
- $destFile = $output.DIRECTORY_SEPARATOR.$fileMetaData['url'];
-
- $destDirectory = dirname($destFile);
+ foreach ($pages as $page) {
+ $destDirectory = dirname($page['wwwOutput']);
if (!file_exists($destDirectory) && !mkdir($destDirectory, 0777, true)) {
echo "Unable to create WWW site directory $destDirectory.";
@@ -129,19 +142,21 @@ function buildWWWSite(array $siteMetaData, string $output, string $htmlTemplateD
}
file_put_contents(
- str_replace('.gmi', '.html', $destFile),
+ $page['wwwOutput'],
buildHtmlFile(
- $fileMetaData,
- gemtext2hmtl(file_get_contents($fileMetaData['input'])),
- $htmlTemplateDiretory
+ $page['title'],
+ $page['html'],
+ file_get_contents($htmlTemplateDiretory.DIRECTORY_SEPARATOR.'default.html')
)
);
}
copyWWWAssets($assetsDiretory, $output);
+
+ generateAtomFeeds($pages, $hostname);
}
-function buildHtmlFile(array $fileMetaData, string $contents, string $htmlTemplateDiretory): string
+function buildHtmlFile(string $title, string $contents, string $template): string
{
return str_replace(
[
@@ -149,10 +164,10 @@ function buildHtmlFile(array $fileMetaData, string $contents, string $htmlTempla
'{{ $contents }}'
],
[
- $fileMetaData['title'],
+ $title,
$contents,
],
- file_get_contents($htmlTemplateDiretory.DIRECTORY_SEPARATOR.'default.html')
+ $template
);
}
@@ -222,7 +237,9 @@ function gemtext2hmtl(string $gemtext): string
} elseif (preg_match(QUOTE, $line($index), $matches) === 1) {
$html[] = "<blockquote>$matches[1]</blockquote>";
} else {
- $html[] = "<p>{$line($index)}</p>";
+ if ($line($index) !== '') {
+ $html[] = "<p>{$line($index)}</p>";
+ }
}
$index++;
@@ -261,3 +278,99 @@ function copyWWWAssets(string $assetsDiretory, string $output): void
}
}
+function generateAtomFeeds(array $pages, string $hostname): void
+{
+ $posts = array_filter($pages, fn ($post) => $post['isPost']);
+
+ $tags = array_filter($pages, fn ($post) => $post['isTag']);
+
+ /**
+ * Sort by latest to previous date.
+ */
+ usort($posts, fn ($a, $b) => $b['date'] <=> $a['date']);
+
+ /**
+ * Group posts by tag.
+ */
+ $groupedPosts = array_reduce($posts, function ($carry, $post) {
+ $carry[$post['tag']][] = $post;
+
+ return $carry;
+ }, []);
+
+ /**
+ * Put posts with their tag page.
+ */
+ $tags = array_map(function ($tag) use ($groupedPosts) {
+ return array_merge($tag, ['posts' => $groupedPosts[$tag['tag']]]);
+ }, $tags);
+
+ foreach ($tags as $tag) {
+ tagToAtomFeed($tag, $hostname);
+ }
+
+ /**
+ * Get the page that lists all posts.
+ */
+ $allPostsIndex = array_values(array_filter($pages, fn ($post) => preg_match('/posts\/index/', $post['wwwUrl']) == 1))[0];
+
+ $allPostsIndex['posts'] = $posts;
+
+ tagToAtomFeed($allPostsIndex, $hostname);
+}
+
+function tagToAtomFeed(array $tag, string $hostname): void
+{
+ file_put_contents(
+ str_replace('index.html', 'atom.xml', $tag['wwwOutput']),
+ buildAtomFeed(
+ $tag['title'],
+ "https://$hostname".str_replace('index.html', 'atom.xml', $tag['wwwUrl']),
+ "https://$hostname".$tag['wwwUrl'],
+ $tag['posts'][0]['date'].'T12:00:00Z',
+ implode('', array_map(fn ($post) => postToAtomEntry($post, $hostname), $tag['posts']))
+ )
+ );
+}
+
+function postToAtomEntry(array $post, string $hostname): string
+{
+ return buildAtomEntry(
+ $post['title'],
+ "https://$hostname{$post['wwwUrl']}",
+ $post['author'],
+ "{$post['date']}T12:00:00Z",
+ $post['html'],
+ );
+}
+
+function buildAtomFeed(string $title, string $href, string $altHref, string $date, string $entries): string
+{
+ return <<<EOF_STR
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="text">$title</title>
+ <id>$href</id>
+ <link rel="alternate" type="text/html" href="$altHref"/>
+ <link rel="self" type="application/atom+xml" href="$href"/>
+ <updated>$date</updated>
+ $entries
+</feed>
+EOF_STR;
+}
+
+function buildAtomEntry(string $title, string $href, string $author, string $date, string $content): string
+{
+ return <<<EOF_STR
+<entry>
+ <title type="text">$title</title>
+ <id>$href</id>
+ <link rel="alternate" type="text/html" href="$href"/>
+ <author><name>$author</name></author>
+ <published>$date</published>
+ <updated>$date</updated>
+ <content>![CDATA[$content]]</content>
+</entry>
+EOF_STR;
+}
+
diff --git a/src/index.gmi b/src/index.gmi
index f8508a4..88a4810 100644
--- a/src/index.gmi
+++ b/src/index.gmi
@@ -1,4 +1,4 @@
-# The home of David T. Sadler
+# The Home of David T. Sadler
Hello and welcome to my little bit of the internet where I occasionally write about things that interest me. You might find my posts interesting or you might not and that's okay.
diff --git a/src/posts/arch/index.gmi b/src/posts/arch/index.gmi
index caf235d..52b4756 100644
--- a/src/posts/arch/index.gmi
+++ b/src/posts/arch/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged Arch
+# The Home of David T. Sadler - All Posts About Arch
=> /posts/arch/2020-09-07/installing-zsh-and-powerlevel10k-on-arch-linux/ 2020-09-07 - Installing Zsh and Powerlevel10k on Arch Linux
=> /posts/arch/2020-08-31/enabling-audio-in-arch-linux/ 2020-08-31 - Enabling Audio in Arch Linux
diff --git a/src/posts/gemini/index.gmi b/src/posts/gemini/index.gmi
index 8e39e23..6efe787 100644
--- a/src/posts/gemini/index.gmi
+++ b/src/posts/gemini/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged Gemini
+# The Home of David T. Sadler - All Posts About Gemini
=> /posts/gemini/2021-02-08/how-to-host-your-own-gemini-site-in-the-cloud/ 2021-02-08 - How to Host Your Own Gemini Site in the Cloud
diff --git a/src/posts/index.gmi b/src/posts/index.gmi
index c56b346..2aad1f8 100644
--- a/src/posts/index.gmi
+++ b/src/posts/index.gmi
@@ -1,4 +1,4 @@
-# David T. Sadler's Posts
+# The Home of David T. Sadler - All Posts
=> /posts/nextcloud/2021-02-15/accessing-nextcloud-with-webdav-on-arch/ 2021-02-15 - Accessing Nextcloud With WebDAV on Arch
=> /posts/gemini/2021-02-08/how-to-host-your-own-gemini-site-in-the-cloud/ 2021-02-08 - How to Host Your Own Gemini Site in the Cloud
diff --git a/src/posts/jigsaw/index.gmi b/src/posts/jigsaw/index.gmi
index c8752aa..d0700f2 100644
--- a/src/posts/jigsaw/index.gmi
+++ b/src/posts/jigsaw/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged Jigsaw
+# The Home of David T. Sadler - All Posts About Jigsaw
=> /posts/jigsaw/2020-06-01/scheduling-posts-in-jigsaw/ 2020-06-01 - Scheduling Posts in Jigsaw
diff --git a/src/posts/laravel/index.gmi b/src/posts/laravel/index.gmi
index 6227b2c..6ee13bd 100644
--- a/src/posts/laravel/index.gmi
+++ b/src/posts/laravel/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged Laravel
+# The Home of David T. Sadler - All Posts About Laravel
=> /posts/laravel/2020-12-21/installing-laravel-homestead-in-arch-linux/ 2020-12-21 - Installing Laravel Homestead in Arch Linux
=> /posts/laravel/2020-12-14/sqlstate-hy000-2002-php-network-getaddresses-getaddrinfo-failed/ 2020-12-14 - SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed
diff --git a/src/posts/linux/index.gmi b/src/posts/linux/index.gmi
index be90865..bb5e57a 100644
--- a/src/posts/linux/index.gmi
+++ b/src/posts/linux/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged Linux
+# The Home of David T. Sadler - All Posts About Linux
=> /posts/linux/2020-07-13/sudo-sorry-you-must-have-a-tty-to-run-sudo/ 2020-07-13 - Sudo: sorry, you must have a tty to run sudo
diff --git a/src/posts/markdown/index.gmi b/src/posts/markdown/index.gmi
index 73f9a8e..94a4717 100644
--- a/src/posts/markdown/index.gmi
+++ b/src/posts/markdown/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged Markdown
+# The Home of David T. Sadler - All Posts About Markdown
=> /posts/markdown/2020-03-30/creating-an-ebook-with-markdown/ 2020-03-30 - Creating an Ebook With Markdown
diff --git a/src/posts/netlify/index.gmi b/src/posts/netlify/index.gmi
index fa06136..3de8bee 100644
--- a/src/posts/netlify/index.gmi
+++ b/src/posts/netlify/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged Netlify
+# The Home of David T. Sadler - All Posts About Netlify
=> /posts/netlify/2020-06-08/publishing-jigsaw-posts-with-netlify-build-hooks/ 2020-06-08 - Publishing Jigsaw Posts With Netlify Build Hooks
diff --git a/src/posts/nextcloud/index.gmi b/src/posts/nextcloud/index.gmi
index b9eeba5..99d6201 100644
--- a/src/posts/nextcloud/index.gmi
+++ b/src/posts/nextcloud/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged Nextcloud
+# The Home of David T. Sadler - All Posts About Nextcloud
=> /posts/nextcloud/2021-02-15/accessing-nextcloud-with-webdav-on-arch/ 2021-02-15 - Accessing Nextcloud With WebDAV on Arch
diff --git a/src/posts/php/index.gmi b/src/posts/php/index.gmi
index f0238a7..4e40910 100644
--- a/src/posts/php/index.gmi
+++ b/src/posts/php/index.gmi
@@ -1,4 +1,4 @@
-# All Posts Tagged PHP
+# The Home of David T. Sadler - All Posts About PHP
=> /posts/php/2021-01-18/installing-php-8-for-windows-10/ 2021-01-18 - Installing PHP 8 for Windows 10
diff --git a/www_assets/css/site.css b/www_assets/css/site.css
index 394e3e7..8e80eca 100644
--- a/www_assets/css/site.css
+++ b/www_assets/css/site.css
@@ -1,3 +1,3 @@
section a {
- display: block;
+ display: block;
}