Use translations, fix 'old' style.

This commit is contained in:
Chris Josten 2021-03-10 18:30:32 +01:00
parent ed2926fb16
commit 75a4e86ea1
15 changed files with 103 additions and 139 deletions

View file

@ -5,10 +5,10 @@
"copyright": "Copyright © 2019, Chris Josten", "copyright": "Copyright © 2019, Chris Josten",
"dependencies": { "dependencies": {
"dyaml": "~>0.8.0", "dyaml": "~>0.8.0",
"vibe-d": "~>0.8.6" "vibe-d": "~>0.9.0"
}, },
"description": "A blog based on Markdown and JSON", "description": "A blog based on Markdown and JSON",
"license": "AGPLv3", "license": "AGPLv3",
"name": "mijnblog", "name": "mijnblog",
"stringImportPaths": ["views", "translations"] "stringImportPaths": ["views", "translations"],
} }

View file

@ -1,21 +1,21 @@
{ {
"fileVersion": 1, "fileVersion": 1,
"versions": { "versions": {
"botan": "1.12.10", "botan": "1.12.19",
"botan-math": "1.0.3", "botan-math": "1.0.3",
"diet-ng": "1.6.0", "diet-ng": "1.7.5",
"dyaml": "0.8.0", "dyaml": "0.8.3",
"eventcore": "0.8.48", "eventcore": "0.9.13",
"fswatch": "0.5.0", "fswatch": "0.5.0",
"libasync": "0.8.4", "libasync": "0.8.6",
"libevent": "2.0.2+2.0.16", "libevent": "2.0.2+2.0.16",
"memutils": "0.4.13", "memutils": "1.0.4",
"mir-linux-kernel": "1.0.1", "mir-linux-kernel": "1.0.1",
"openssl": "1.1.6+1.0.1g", "openssl": "1.1.6+1.0.1g",
"stdx-allocator": "2.77.5", "stdx-allocator": "2.77.5",
"taggedalgebraic": "0.11.7", "taggedalgebraic": "0.11.19",
"tinyendian": "0.2.0", "tinyendian": "0.2.0",
"vibe-core": "1.7.0", "vibe-core": "1.13.0",
"vibe-d": "0.8.6" "vibe-d": "0.9.3"
} }
} }

View file

@ -4,21 +4,32 @@ body {
justify-content: flex-start; 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 { a:hover {
cursor: url(old/cursor-over.gif), auto; cursor: url(old/cursor-over.gif), auto;
} }
body > nav { .header-navigation {
background-color: yellow; background-color: cyan;
color: black;
} }
body > nav ul { .header-navigation> nav ul {
padding-left: 2em; padding-left: 2em;
list-style-image: url(old/bullet.gif); list-style-image: url(old/bullet.gif);
} }
body > main { body main {
background-color: black; background-color: green;
color: white; color: white;
border-image: url(old/skull-border.gif) 33% / 2em round; border-image: url(old/skull-border.gif) 33% / 2em round;
/*border-left-width: 10px !important; /*border-left-width: 10px !important;
@ -27,7 +38,7 @@ body > main {
.title { .title {
width: 100%; width: 100%;
background-color: green; color: orange;
} }
pre { pre {
@ -35,7 +46,7 @@ pre {
} }
blockquote, .screenshots, code{ blockquote, .screenshots, code{
background: #0000ff; background: darkgreen;
border-left: #0000cc 6px solid; border-left: #0000cc 6px solid;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

View file

@ -75,7 +75,102 @@ void addCachingHeader(bool publicCache = true)(ref HTTPServerResponse res) {
res.headers["Cache-Control"] = header; res.headers["Cache-Control"] = header;
} }
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");
}
}
/** /**
* 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);
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);
mixin(singleResponseMixin("articles", "pages/article.dt"));
}
/**
* Generates response for /posts and /palen
*/
@path("/posts/")
void getArticleOverview(HTTPServerRequest req, HTTPServerResponse res) {
addCachingHeader(res);
render!("pages/article-list.dt", articleList);
}
/**
* Generates response for /projects and /projecten
*/
@path("/projects/")
void getProjectOverview(HTTPServerRequest req, HTTPServerResponse res) {
addCachingHeader(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);
mixin(singleResponseMixin("projects", "pages/project.dt"));
}
/**
* Generate response for a page
*/
@path("/:slug")
void getPage(HTTPServerRequest req, HTTPServerResponse res) {
addCachingHeader(res);
//getSingle!(Page, "pages/page.dt")(pages, req, res);
mixin(singleResponseMixin("pages", "pages/page.dt"));
}
@path("/")
void getIndexPage(HTTPServerRequest req, HTTPServerResponse res) {
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);
mixin(singleResponseMixin("pages", "pages/page.dt"));
}
/**
* Template method for fetching a single page for a subclass of page. * Template method for fetching a single page for a subclass of page.
* Params: * Params:
* T = the data structure/class to be passed as template parameter. Must have a slug parameter. * T = the data structure/class to be passed as template parameter. Must have a slug parameter.
@ -85,84 +180,6 @@ void addCachingHeader(bool publicCache = true)(ref HTTPServerResponse res) {
* res = The server response to write to. * 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 TranslationContext {
import std.typetuple;
enum enforceExistingKeys = true;
alias languages = TypeTuple!("en_GB", "nl_NL");
mixin translationModule!"mijnblog";
}
@translationContext!TranslationContext
class MijnBlog {
/**
* 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);
}
/**
* Generates response for /posts and /palen
*/
@path("/posts/")
void getArticleOverview(HTTPServerRequest req, HTTPServerResponse res) {
addCachingHeader(res);
render!("pages/article-list.dt", articleList)(res);
}
/**
* Generates response for /projects and /projecten
*/
@path("/projects/")
void getProjectOverview(HTTPServerRequest req, HTTPServerResponse res) {
addCachingHeader(res);
render!("pages/project-list.dt", projectList)(res);
}
/**
* 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);
}
/**
* Generate response for a page
*/
@path("/:slug")
void getPage(HTTPServerRequest req, HTTPServerResponse res) {
addCachingHeader(res);
getSingle!(Page, "pages/page.dt")(pages, req, res);
}
@path("/")
void getIndexPage(HTTPServerRequest req, HTTPServerResponse res) {
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);
}
} }
/** /**
@ -189,15 +206,6 @@ void main() {
URLRouter router = new URLRouter; URLRouter router = new URLRouter;
router.get("/static/*", serveStaticFiles("./public/", fSettings)); router.get("/static/*", serveStaticFiles("./public/", fSettings));
router.registerWebInterface(new MijnBlog); 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); listenHTTP(settings, router);

View file

@ -1,2 +1,7 @@
msgid "page.header-bottom-text" msgid "template.page.name"
msgstr "Chris's website" msgstr "Chris's website"
msgid "template.page.copyright"
msgstr "© Chris Josten, 2021. If not specified otherwise, all content on this"
"website is <a rel=\"license\" href=\"https://creativecommons.org/licenses/by/4.0/\">"
"licensed under the CC-BY 4.0</a>"

View file

@ -11,5 +11,9 @@ msgstr ""
"Language: nl\n" "Language: nl\n"
"X-Generator: Poedit 2.3.1\n" "X-Generator: Poedit 2.3.1\n"
msgid "Chris's website" msgid "template.page.name"
msgstr "Chris z'n webstekkie" msgstr "Chris z'n webstekkie"
msgid "template.page.copyright"
msgstr "&copy; Chris Josten, 2021. Tenzij anders vermeld staat, valt alle inhoud op deze webstek"
"<a rel=\"license\" href=\"https://creativecommons.org/licenses/by/4.0/\"> onder de CC-BY 4.0</a>"

View file

@ -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}&hellip;

View file

@ -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 <span itemprop="author">#{content.author}</span>
| on <time datetime="#{content.firstPublished.toISOExtString}" itemprop="datePublished">#{content.firstPublished.toHumanString}</time>
- if (content.isModified)
|, updated on <time datetime="#{content.updated.toISOExtString}" itemprop="dateModified">#{content.updated.toHumanString}</time>
section(itemprop="articleBody") !{content.content}

View file

@ -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}

View file

@ -1,4 +1,4 @@
extends /parts/page.dt extends parts/page
block meta_data block meta_data
- page_title = content.title; - page_title = content.title;

View file

@ -1,4 +1,4 @@
extends /parts/page.dt extends parts/page
block header block header
title Projects - Chris Netsoj.nl title Projects - Chris Netsoj.nl

View file

@ -1,4 +1,4 @@
extends /parts/page extends parts/page
block meta_data block meta_data
- page_title = content.title; - page_title = content.title;
- page_url = "/project/" ~ content.slug; - page_url = "/project/" ~ content.slug;

View file

@ -1,5 +1,2 @@
p p
small small& template.page.copyright
| &copy; Chris Josten, 2020. If not specified otherwise, all content on this
| website is <a rel="license" href="https://creativecommons.org/licenses/by/4.0/">
| licensed under the CC-BY 4.0</a>.

View file

@ -45,7 +45,7 @@ html(prefix="og: http://ogp.me/ns#")
section.header-navigation section.header-navigation
header 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") 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 nav
ul ul
- menuItem("home", "/"); - menuItem("home", "/");
@ -54,10 +54,10 @@ html(prefix="og: http://ogp.me/ns#")
block sidebar block sidebar
footer.hide-small footer.hide-small
block footer block footer
include /parts/footer.dt include parts/footer
main main
block content block content
footer.hide-big footer.hide-big
block footer block footer
include /parts/footer.dt include parts/footer