From 0e7aa0451fb99829d157e05fde86df77c6ade634 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 12 Oct 2024 22:31:23 +0200 Subject: [PATCH] atom: add atom feed to website for posts --- defaultClasses.lua | 10 +++- source/nl/netsoj/chris/blog/constants.d | 4 +- source/nl/netsoj/chris/blog/interfaces/http.d | 59 ++++++++++++++++++- source/nl/netsoj/chris/blog/model/page.d | 5 +- translations/mijnblog.en_GB.po | 6 ++ translations/mijnblog.nl_NL.po | 6 ++ translations/mijnblog.pot | 30 +++++++++- views/parts/page.dt | 1 + 8 files changed, 115 insertions(+), 6 deletions(-) diff --git a/defaultClasses.lua b/defaultClasses.lua index b1ddd6f..2e5dba6 100644 --- a/defaultClasses.lua +++ b/defaultClasses.lua @@ -14,6 +14,14 @@ function get_default_code_class(meta) end end +function make_image_url_absolute (img) + if img.src:sub(1,1) == '/' then + img.src = os.getenv 'WEBROOT' .. img.src + end + return img +end + return {{Meta = get_default_code_class}, {Code = add_default_code_class}, - {CodeBlock = add_default_code_class}} + {CodeBlock = add_default_code_class}, + {Image = make_image_url_absolute}} diff --git a/source/nl/netsoj/chris/blog/constants.d b/source/nl/netsoj/chris/blog/constants.d index 8b665d3..b483152 100644 --- a/source/nl/netsoj/chris/blog/constants.d +++ b/source/nl/netsoj/chris/blog/constants.d @@ -1,8 +1,10 @@ /** * Constants which are passed to templates while rendering. */ -class Constants { +struct Constants { public static immutable string SITE_NAME = "Chris Josten's site"; + public static immutable string SITE_HOST = "chris.netsoj.nl"; public static immutable string SITE_URL = "https://chris.netsoj.nl"; + public static immutable string SITE_AUTHOR = "Chris Josten"; public static immutable string COPYRIGHT = "© Chris Josten, 2020"; } diff --git a/source/nl/netsoj/chris/blog/interfaces/http.d b/source/nl/netsoj/chris/blog/interfaces/http.d index b5a325e..db15abb 100644 --- a/source/nl/netsoj/chris/blog/interfaces/http.d +++ b/source/nl/netsoj/chris/blog/interfaces/http.d @@ -1,6 +1,11 @@ +import std.algorithm : map, maxElement; +import std.format : format; +import std.string: join; + import vibe.d; import cache; +import constants; import article; import page; import project; @@ -141,7 +146,59 @@ public: // If no slug is supplied, it will be adjusted to "index" req.params.addField("slug", "index"); mixin(singleResponseMixin("pages", "pages/page.dt")); - } + } + + @path("/feeds/posts.atom") + void getPostFeed(HTTPServerRequest req, HTTPServerResponse res) { + Article[] articleList = articles.sortedList; + + DateTime lastUpdated = articleList.map!"a.firstPublished()".maxElement; + + string response = q"EOS + + + %s + %s + %s + + + urn:uuid:036f1087-7fcd-466d-866d-78a0c60038cd + %s + %s + +EOS" + .format( + lastUpdated.toISOExtString() ~ "Z", + trWeb("template.feed.title").format(trWeb("template.feed.posts.title")), + Constants.SITE_URL ~ "/static/img/logo.png", + Constants.SITE_URL, + Constants.SITE_URL, + Constants.SITE_AUTHOR, + articleList.map!((article) { + return q"EOS + + %s + + %s + %s + %s + %s + %s + + +EOS" + .format(article.title, + Constants.SITE_URL ~ "/posts/" ~ article.slug, + "tag:" ~ Constants.SITE_HOST ~ ",2024:blog:posts:" ~ article.slug, + article.firstPublished().toISOExtString() ~ "Z", + article.updated().toISOExtString() ~ "Z", + article.excerpt(), + htmlEscape(article.content()) + ); + }).join() + ); + res.writeBody(response, "application/atom+xml"); + } } /** diff --git a/source/nl/netsoj/chris/blog/model/page.d b/source/nl/netsoj/chris/blog/model/page.d index 97f3141..26cc8e2 100644 --- a/source/nl/netsoj/chris/blog/model/page.d +++ b/source/nl/netsoj/chris/blog/model/page.d @@ -7,6 +7,7 @@ import std.stdio; import dyaml; import vibe.vibe; +import constants; import utils; @safe: @@ -107,10 +108,12 @@ class Page { "-f", "markdown", "-t", "html", "--lua-filter", "defaultClasses.lua"]; + string[string] env; + env["WEBROOT"] = Constants.SITE_URL; if (shiftHeader != 0) args ~= "--shift-heading-level-by=" ~ to!string(shiftHeader); - ProcessPipes pandoc = pipeProcess(args); + ProcessPipes pandoc = pipeProcess(args, Redirect.all, env); pandoc.stdin.write(source); pandoc.stdin.writeln(); pandoc.stdin.flush(); diff --git a/translations/mijnblog.en_GB.po b/translations/mijnblog.en_GB.po index e660461..dcf2d5c 100644 --- a/translations/mijnblog.en_GB.po +++ b/translations/mijnblog.en_GB.po @@ -20,3 +20,9 @@ msgid "template.page.copyright" msgstr "© Chris Josten, 2024. If not specified otherwise, all content on this " "website is " "licensed under the CC-BY 4.0" + +msgid "template.feed.title" +msgstr "%s | Chris's website" + +msgid "template.feed.posts.title" +msgstr "Posts" diff --git a/translations/mijnblog.nl_NL.po b/translations/mijnblog.nl_NL.po index 3fd9c16..9eac5b2 100644 --- a/translations/mijnblog.nl_NL.po +++ b/translations/mijnblog.nl_NL.po @@ -32,3 +32,9 @@ msgstr "Contact" msgid "template.page.copyright" msgstr "© Chris Josten, 2024. Tenzij anders vermeld staat, valt alle inhoud op deze webstek " " onder de CC-BY 4.0" + +msgid "template.feed.title" +msgstr "%s | Chris z'n webstekkie" + +msgid "template.feed.posts.title" +msgstr "Berichten" diff --git a/translations/mijnblog.pot b/translations/mijnblog.pot index 4d4a992..dcf2d5c 100644 --- a/translations/mijnblog.pot +++ b/translations/mijnblog.pot @@ -1,2 +1,28 @@ -msgid "page.header-bottom-text" -msgstr "" +msgid "template.page.name" +msgstr "Chris's website" + +msgid "template.page.html_language" +msgstr "en-GB" + +msgid "template.menu.home" +msgstr "Home" + +msgid "template.menu.posts" +msgstr "Posts" + +msgid "template.menu.projects" +msgstr "Projects" + +msgid "template.menu.contact" +msgstr "Contact" + +msgid "template.page.copyright" +msgstr "© Chris Josten, 2024. If not specified otherwise, all content on this " +"website is " +"licensed under the CC-BY 4.0" + +msgid "template.feed.title" +msgstr "%s | Chris's website" + +msgid "template.feed.posts.title" +msgstr "Posts" diff --git a/views/parts/page.dt b/views/parts/page.dt index 1c2e1a5..7990c91 100644 --- a/views/parts/page.dt +++ b/views/parts/page.dt @@ -6,6 +6,7 @@ html(prefix="og: http://ogp.me/ns#") //- Kick off loading the css as fast as possible meta(name="viewport", content="width=device-width; initial-scale=1") link(rel="stylesheet", href="/static/style/base.css") + link(rel="alternate", href="/feeds/posts.atom", type="application/atom+xml", title=trWeb("template.feed.title").format(trWeb("template.feed.posts.title"))) - string page_image = "/static/img/logo.png"; - string page_title;