diff --git a/dub.json b/dub.json index 1bf5803..3d0bb41 100644 --- a/dub.json +++ b/dub.json @@ -5,10 +5,10 @@ "copyright": "Copyright © 2019, Chris Josten", "dependencies": { "dyaml": "~>0.8.0", - "vibe-d": "~>0.8.6" + "vibe-d": "~>0.9.0" }, "description": "A blog based on Markdown and JSON", "license": "AGPLv3", "name": "mijnblog", - "stringImportPaths": ["views", "translations"] + "stringImportPaths": ["views", "translations"], } diff --git a/dub.selections.json b/dub.selections.json index a285e5c..5518a38 100644 --- a/dub.selections.json +++ b/dub.selections.json @@ -1,21 +1,21 @@ { "fileVersion": 1, "versions": { - "botan": "1.12.10", + "botan": "1.12.19", "botan-math": "1.0.3", - "diet-ng": "1.6.0", - "dyaml": "0.8.0", - "eventcore": "0.8.48", + "diet-ng": "1.7.5", + "dyaml": "0.8.3", + "eventcore": "0.9.13", "fswatch": "0.5.0", - "libasync": "0.8.4", + "libasync": "0.8.6", "libevent": "2.0.2+2.0.16", - "memutils": "0.4.13", + "memutils": "1.0.4", "mir-linux-kernel": "1.0.1", "openssl": "1.1.6+1.0.1g", "stdx-allocator": "2.77.5", - "taggedalgebraic": "0.11.7", + "taggedalgebraic": "0.11.19", "tinyendian": "0.2.0", - "vibe-core": "1.7.0", - "vibe-d": "0.8.6" + "vibe-core": "1.13.0", + "vibe-d": "0.9.3" } } diff --git a/public/static/style/old.css b/public/static/style/old.css index 57f7e54..6eda75d 100644 --- a/public/static/style/old.css +++ b/public/static/style/old.css @@ -4,21 +4,32 @@ body { justify-content: flex-start; } +header { + border-bottom: solid 40px; + border-image: url(old/flames.gif) 0 0 200 0 round round; +} + +footer { + border-top: solid 40px; + border-image: url(old/flames.gif) 200 0 0 round round; +} + a:hover { cursor: url(old/cursor-over.gif), auto; } -body > nav { - background-color: yellow; +.header-navigation { + background-color: cyan; + color: black; } -body > nav ul { +.header-navigation> nav ul { padding-left: 2em; list-style-image: url(old/bullet.gif); } -body > main { - background-color: black; +body main { + background-color: green; color: white; border-image: url(old/skull-border.gif) 33% / 2em round; /*border-left-width: 10px !important; @@ -27,7 +38,7 @@ body > main { .title { width: 100%; - background-color: green; + color: orange; } pre { @@ -35,7 +46,7 @@ pre { } blockquote, .screenshots, code{ - background: #0000ff; + background: darkgreen; border-left: #0000cc 6px solid; } diff --git a/public/static/style/old/flames.gif b/public/static/style/old/flames.gif new file mode 100644 index 0000000..5da33a8 Binary files /dev/null and b/public/static/style/old/flames.gif differ diff --git a/source/app.d b/source/app.d index 0764e39..6898ae7 100644 --- a/source/app.d +++ b/source/app.d @@ -75,48 +75,53 @@ void addCachingHeader(bool publicCache = true)(ref HTTPServerResponse res) { res.headers["Cache-Control"] = header; } -/** - * Template method for fetching a single page for a subclass of page. - * Params: - * T = the data structure/class to be passed as template parameter. Must have a slug parameter. - * templ = The template to use when rendering. - * array = An associative array where the keys are slugs for parameters and the values the template parameter. - * req = The server request to consume. Assumes there is an slug parameter. - * res = The server response to write to. - * - */ -void getSingle(T, string templ)(ref T[string] array, HTTPServerRequest req, HTTPServerResponse res) { - string slug = req.params["slug"]; - OutputType outputType = getOutputType(slug); - enforceHTTP(slug in array, HTTPStatus.notFound, "Page not found"); - T content = array[slug]; - switch(outputType) with (OutputType) { - case MARKDOWN: - res.writeBody(content.contentSource, MIME_MARKDOWN); - break; - default: - case HTML: - res.render!(templ, content); - break; + +struct TranslateContext { + import std.typetuple; + + alias languages = TypeTuple!("en_GB", "nl_NL"); + mixin translationModule!"mijnblog"; + static string determineLanguage(scope HTTPServerRequest req) { + if ("lang" !in req.query) return req.determineLanguageByHeader(languages); // default behaviour using "Accept-Language" header + return req.query.get("lang", "en_GB"); } } -struct TranslationContext { - import std.typetuple; - enum enforceExistingKeys = true; - alias languages = TypeTuple!("en_GB", "nl_NL"); - mixin translationModule!"mijnblog"; -} +/** + * Generates boilerplate code for a single response. + * params: + * arrayName = The name of the associative array to take the items from. + * templateName = The name of the template to render. + */ +string singleResponseMixin(string arrayName, string templateName) { + return `string slug = req.params["slug"]; + OutputType outputType = getOutputType(slug); -@translationContext!TranslationContext + enforceHTTP(slug in ` ~ arrayName ~ `, HTTPStatus.notFound, "Page not found"); + auto content = ` ~ arrayName ~ `[slug]; + switch(outputType) with (OutputType) { + case MARKDOWN: + res.writeBody(content.contentSource, MIME_MARKDOWN); + break; + default: + case HTML: + render!("` ~ templateName ~ `", content); + break; + }`; + } + +@translationContext!TranslateContext class MijnBlog { + +public: /** * Generates response for /posts/:slug and /palen/:slug. */ @path("/posts/:slug") void getArticleSingle(string _slug, HTTPServerRequest req, HTTPServerResponse res) { - getSingle!(Article, "pages/article.dt")(articles, req, res); + //getSingle!(Article, "pages/article.dt")(articles, req, res); + mixin(singleResponseMixin("articles", "pages/article.dt")); } /** @@ -125,7 +130,7 @@ class MijnBlog { @path("/posts/") void getArticleOverview(HTTPServerRequest req, HTTPServerResponse res) { addCachingHeader(res); - render!("pages/article-list.dt", articleList)(res); + render!("pages/article-list.dt", articleList); } /** @@ -134,18 +139,17 @@ class MijnBlog { @path("/projects/") void getProjectOverview(HTTPServerRequest req, HTTPServerResponse res) { addCachingHeader(res); - render!("pages/project-list.dt", projectList)(res); + render!("pages/project-list.dt", projectList); } - - /** * Generate response for a project page */ @path("/projects/:slug") void getProject(HTTPServerRequest req, HTTPServerResponse res) { res.headers["Cache-Control"] = "public"; - getSingle!(Project, "pages/project.dt")(projects, req, res); + //getSingle!(Project, "pages/project.dt")(projects, req, res); + mixin(singleResponseMixin("projects", "pages/project.dt")); } /** * Generate response for a page @@ -153,7 +157,8 @@ class MijnBlog { @path("/:slug") void getPage(HTTPServerRequest req, HTTPServerResponse res) { addCachingHeader(res); - getSingle!(Page, "pages/page.dt")(pages, req, res); + //getSingle!(Page, "pages/page.dt")(pages, req, res); + mixin(singleResponseMixin("pages", "pages/page.dt")); } @path("/") @@ -161,8 +166,20 @@ class MijnBlog { addCachingHeader(res); // If no slug is supplied, it will be adjusted to "index" req.params.addField("slug", "index"); - getSingle!(Page, "pages/page.dt")(pages, req, res); - } + //getSingle!(Page, "pages/page.dt")(pages, req, res); + mixin(singleResponseMixin("pages", "pages/page.dt")); + } + + /** + * Template method for fetching a single page for a subclass of page. + * Params: + * T = the data structure/class to be passed as template parameter. Must have a slug parameter. + * templ = The template to use when rendering. + * array = An associative array where the keys are slugs for parameters and the values the template parameter. + * req = The server request to consume. Assumes there is an slug parameter. + * res = The server response to write to. + * + */ } /** @@ -189,15 +206,6 @@ void main() { URLRouter router = new URLRouter; router.get("/static/*", serveStaticFiles("./public/", fSettings)); router.registerWebInterface(new MijnBlog); - /*router.get("/posts/:slug", &articleGetSingle); - router.get("/palen/:slug", &articleGetSingle); - router.get("/posts/", &articleGetOverview); - router.get("/palen/", &articleGetOverview); - router.get("/projects/", &projectGetOverview); - router.get("/projects/:slug", &projectGet); - router.get("/projecten/:slug", &projectGet); - router.get("/:slug", &pageGet); - router.get("/", &pageGet);*/ listenHTTP(settings, router); diff --git a/translations/mijnblog.en_GB.po b/translations/mijnblog.en_GB.po index 2d4a957..51055b0 100644 --- a/translations/mijnblog.en_GB.po +++ b/translations/mijnblog.en_GB.po @@ -1,2 +1,7 @@ -msgid "page.header-bottom-text" +msgid "template.page.name" msgstr "Chris's website" + +msgid "template.page.copyright" +msgstr "© Chris Josten, 2021. If not specified otherwise, all content on this" +"website is " +"licensed under the CC-BY 4.0" diff --git a/translations/mijnblog.nl_NL.po b/translations/mijnblog.nl_NL.po index 0591aaf..903e98e 100644 --- a/translations/mijnblog.nl_NL.po +++ b/translations/mijnblog.nl_NL.po @@ -11,5 +11,9 @@ msgstr "" "Language: nl\n" "X-Generator: Poedit 2.3.1\n" -msgid "Chris's website" +msgid "template.page.name" msgstr "Chris z'n webstekkie" + +msgid "template.page.copyright" +msgstr "© Chris Josten, 2021. Tenzij anders vermeld staat, valt alle inhoud op deze webstek" +" onder de CC-BY 4.0" diff --git a/views/pages/article-list.dt b/views/pages/article-list.dt deleted file mode 100644 index 3e731d9..0000000 --- a/views/pages/article-list.dt +++ /dev/null @@ -1,25 +0,0 @@ -extends /parts/page.dt - -block header - title Posts - Netsoj.nl - -block sidebar - -block content - header - h1.title Post list - - import vibe.d; - - if (articleList.length == 0) - p No posts found - - else - - import utils; - - foreach(article; articleList) - article - header - a(href="/posts/#{article.slug}", rel="bookmark") - h2.title #{article.title} - p.subtitle - | By #{article.author} on #{article.firstPublished.toHumanString} - - if (article.firstPublished != article.updated) - |, updated on #{article.updated.toHumanString} - p #{article.excerpt}… diff --git a/views/pages/article.dt b/views/pages/article.dt deleted file mode 100644 index 03875ec..0000000 --- a/views/pages/article.dt +++ /dev/null @@ -1,25 +0,0 @@ -extends /parts/page - -block meta_data - - page_type = "article"; - - page_title = content.title; - - page_url = "/post/" ~ content.slug; - - page_description = content.excerpt; - -block extra_meta_data - meta(name="og:article:author:username", content=content.author) - meta(name="og:article:published_time", content=content.firstPublished.toISOExtString) - - if (content.isModified) - meta(name="og:article:modified_time", content=content.updated.toISOExtString) - -block content - article(itemscope, itemtype="https://schema.org/BlogPosting") - - import utils; - header - h1.title(itemprop="headline") #{content.title} - p.subtitle - | By - | on - - if (content.isModified) - |, updated on - section(itemprop="articleBody") !{content.content} diff --git a/views/pages/error.dt b/views/pages/error.dt deleted file mode 100644 index 7dbc7e2..0000000 --- a/views/pages/error.dt +++ /dev/null @@ -1,11 +0,0 @@ -extends /parts/page.dt - -block header - title #{error.message} - Netsoj.nl - -block sidebar - -block content - header - h1.title #{error.message} (#{error.code}) - pre #{error.debugMessage} diff --git a/views/pages/page.dt b/views/pages/page.dt index 6b01b2f..78cf7c2 100644 --- a/views/pages/page.dt +++ b/views/pages/page.dt @@ -1,4 +1,4 @@ -extends /parts/page.dt +extends parts/page block meta_data - page_title = content.title; diff --git a/views/pages/project-list.dt b/views/pages/project-list.dt index d127a3e..1b67453 100644 --- a/views/pages/project-list.dt +++ b/views/pages/project-list.dt @@ -1,4 +1,4 @@ -extends /parts/page.dt +extends parts/page block header title Projects - Chris Netsoj.nl diff --git a/views/pages/project.dt b/views/pages/project.dt index ada9ac1..5affaaf 100644 --- a/views/pages/project.dt +++ b/views/pages/project.dt @@ -1,4 +1,4 @@ -extends /parts/page +extends parts/page block meta_data - page_title = content.title; - page_url = "/project/" ~ content.slug; diff --git a/views/parts/footer.dt b/views/parts/footer.dt index b4a9fa1..1385b34 100644 --- a/views/parts/footer.dt +++ b/views/parts/footer.dt @@ -1,5 +1,2 @@ p - small - | © Chris Josten, 2020. If not specified otherwise, all content on this - | website is - | licensed under the CC-BY 4.0. + small& template.page.copyright diff --git a/views/parts/page.dt b/views/parts/page.dt index 06730e7..746e5b0 100644 --- a/views/parts/page.dt +++ b/views/parts/page.dt @@ -45,7 +45,7 @@ html(prefix="og: http://ogp.me/ns#") section.header-navigation header img.logo(src="/static/img/logo.png", alt="The logo of the website: the letter C drawn in an unprofessional manner with wobbly eyes on put on top") - p& Chris's website + p& template.page.name nav ul - menuItem("home", "/"); @@ -54,10 +54,10 @@ html(prefix="og: http://ogp.me/ns#") block sidebar footer.hide-small block footer - include /parts/footer.dt + include parts/footer main block content footer.hide-big block footer - include /parts/footer.dt + include parts/footer