diff --git a/dub.json b/dub.json
index 1bf5803..e654948 100644
--- a/dub.json
+++ b/dub.json
@@ -5,7 +5,7 @@
"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",
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 #{content.author}
- | 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