Add more support for internationalisation, style changes

This commit is contained in:
Chris Josten 2021-03-11 17:22:40 +01:00
parent 5506163cba
commit 46bea4fa58
16 changed files with 125 additions and 1461 deletions

19
defaultClasses.lua Normal file
View file

@ -0,0 +1,19 @@
local default_code_classes = {}
function add_default_code_class(el)
el.classes[#el.classes+1] = 'numberSource'
if #(el.classes) == 1 then
el.classes = default_code_classes
end
return el
end
function get_default_code_class(meta)
if meta['default-code-class'] then
default_code_classes = {pandoc.utils.stringify(meta['default-code-class'])}
end
end
return {{Meta = get_default_code_class},
{Code = add_default_code_class},
{CodeBlock = add_default_code_class}}

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,7 @@
} }
} }
.hide-big { .hide-big {
display: none; display: none;
} }
@ -31,6 +32,7 @@
--colour-bg: #f0f0f0; --colour-bg: #f0f0f0;
--colour-bg-main: #ddd; --colour-bg-main: #ddd;
--colour-bg-code: #ccc; --colour-bg-code: #ccc;
--colour-bg-highlight: #f9f890;
--colour-fg: #000000; --colour-fg: #000000;
--colour-fg-highlight: #7f0602; --colour-fg-highlight: #7f0602;
--colour-fg-lineno: #111; --colour-fg-lineno: #111;
@ -45,6 +47,7 @@
--colour-bg: #101010; --colour-bg: #101010;
--colour-bg-main: #333; --colour-bg-main: #333;
--colour-bg-code: #222; --colour-bg-code: #222;
--colour-bg-highlight: #727000;
--colour-fg: #ffffff; --colour-fg: #ffffff;
--colour-fg-highlight: #fc918d; --colour-fg-highlight: #fc918d;
--colour-fg-lineno: #ccc; --colour-fg-lineno: #ccc;
@ -71,6 +74,12 @@ body > section.header-navigation {
padding: 2em; padding: 2em;
} }
@media (pointer: coarse) {
body > section.header-navigation li {
padding: 0.25em 0;
}
}
body > footer { body > footer {
flex: 0 0 200px; flex: 0 0 200px;
padding: 2em; padding: 2em;
@ -81,7 +90,6 @@ body > section.header-navigation > header {
text-align: center; text-align: center;
} }
body > section.header-navigation > header > img { body > section.header-navigation > header > img {
width: 100%; width: 100%;
max-width: 160px; max-width: 160px;
@ -176,6 +184,10 @@ dl.project-platforms-technologies {
border-bottom: 1px dotted var(--colour-fg); border-bottom: 1px dotted var(--colour-fg);
} }
dt + dd.tag {
margin-left: 40px;
}
.tag { .tag {
display: inline-block; display: inline-block;
background-color: #ccc; background-color: #ccc;
@ -266,3 +278,39 @@ a:hover {
color: var(--colour-fg); color: var(--colour-fg);
text-decoration: underline solid; text-decoration: underline solid;
} }
@media print {
body {
background-color: initial;
flex-direction: column;
}
body > section.header-navigation {
display: none;
}
body > main {
max-width: 100%;
background-color: initial;
border: none;
}
div.sourceCode, .screenshots, figure {
background-color: initial;
}
.hide-big {
display: block !important;
}
.hide-small {
display: none !important;
}
a:after {
content: ' (' attr(href) ')';
}
.numberSource a:after {
content: ''
}
}

View file

@ -60,3 +60,4 @@ code span.st { color: var(--colour-fg-code-string); } /* String */
code span.va { color: #19177c; } /* Variable */ code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */ code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code span:target { background-color: var(--colour-bg-highlight); }

View file

@ -1,3 +0,0 @@
body {
background: red;
}

View file

@ -1,195 +0,0 @@
/* PrismJS 1.17.1
https://prismjs.com/download.html#themes=prism-solarizedlight&languages=markup+css+clike+javascript+c+cpp+d+java+json&plugins=line-numbers */
/*
Solarized Color Schemes originally by Ethan Schoonover
http://ethanschoonover.com/solarized
Ported for PrismJS by Hector Matos
Website: https://krakendev.io
Twitter Handle: https://twitter.com/allonsykraken)
*/
/*
SOLARIZED HEX
--------- -------
base03 #002b36
base02 #073642
base01 #586e75
base00 #657b83
base0 #839496
base1 #93a1a1
base2 #eee8d5
base3 #fdf6e3
yellow #b58900
orange #cb4b16
red #dc322f
magenta #d33682
violet #6c71c4
blue #268bd2
cyan #2aa198
green #859900
*/
code[class*="language-"],
pre[class*="language-"] {
color: #657b83; /* base00 */
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
background: #073642; /* base02 */
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
background: #073642; /* base02 */
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background-color: #fdf6e3; /* base3 */
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #93a1a1; /* base1 */
}
.token.punctuation {
color: #586e75; /* base01 */
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #268bd2; /* blue */
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.url,
.token.inserted {
color: #2aa198; /* cyan */
}
.token.entity {
color: #657b83; /* base00 */
background: #eee8d5; /* base2 */
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #859900; /* green */
}
.token.function,
.token.class-name {
color: #b58900; /* yellow */
}
.token.regex,
.token.important,
.token.variable {
color: #cb4b16; /* orange */
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
pre[class*="language-"].line-numbers {
position: relative;
padding-left: 3.8em;
counter-reset: linenumber;
}
pre[class*="language-"].line-numbers > code {
position: relative;
white-space: inherit;
}
.line-numbers .line-numbers-rows {
position: absolute;
pointer-events: none;
top: 0;
font-size: 100%;
left: -3.8em;
width: 3em; /* works for line-numbers below 1000 lines */
letter-spacing: -1px;
border-right: 1px solid #999;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.line-numbers-rows > span {
pointer-events: none;
display: block;
counter-increment: linenumber;
}
.line-numbers-rows > span:before {
content: counter(linenumber);
color: #999;
display: block;
padding-right: 0.8em;
text-align: right;
}

View file

@ -169,17 +169,6 @@ public:
//getSingle!(Page, "pages/page.dt")(pages, req, res); //getSingle!(Page, "pages/page.dt")(pages, req, res);
mixin(singleResponseMixin("pages", "pages/page.dt")); 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.
*
*/
} }
/** /**

View file

@ -88,6 +88,7 @@ class Page {
this.m_slug = this.m_title; this.m_slug = this.m_title;
infof("%s does not have a slug. Using %s", this.m_name, this.m_slug); infof("%s does not have a slug. Using %s", this.m_name, this.m_slug);
} }
this.m_language = headerNode.getOr!string("language", "unknown");
hasCalledSuper = true; hasCalledSuper = true;
} }
@ -102,7 +103,8 @@ class Page {
public static string parseMarkdown(string source, int shiftHeader = 0) { public static string parseMarkdown(string source, int shiftHeader = 0) {
string[] args = ["pandoc", string[] args = ["pandoc",
"-f", "markdown", "-f", "markdown",
"-t", "html"]; "-t", "html",
"--lua-filter", "defaultClasses.lua"];
if (shiftHeader != 0) args ~= "--shift-heading-level-by=" ~ to!string(shiftHeader); if (shiftHeader != 0) args ~= "--shift-heading-level-by=" ~ to!string(shiftHeader);
@ -117,7 +119,7 @@ class Page {
while ((line = pandoc.stdout.readln()) !is null) { while ((line = pandoc.stdout.readln()) !is null) {
result ~= line; result ~= line;
debug { debug {
logf("Pandoc stdout: %s", line); //logf("Pandoc stdout: %s", line);
} }
} }

View file

@ -1,5 +1,6 @@
import std.array; import std.array;
import std.algorithm; import std.algorithm;
import std.typecons;
import dyaml; import dyaml;
import vibe.vibe; import vibe.vibe;
@ -12,6 +13,7 @@ import utils;
* Represents a project, like an unfinished application * Represents a project, like an unfinished application
*/ */
class Project : Page { class Project : Page {
alias Link= Tuple!(string, "name", string, "url");
protected immutable string PROJECT_ICON_DIR = IMG_DIR ~ "projects/icons/"; protected immutable string PROJECT_ICON_DIR = IMG_DIR ~ "projects/icons/";
protected immutable string PROJECT_IMAGE_DIR = IMG_DIR ~ "projects/images/"; protected immutable string PROJECT_IMAGE_DIR = IMG_DIR ~ "projects/images/";
protected string m_state; protected string m_state;
@ -20,7 +22,7 @@ class Project : Page {
protected string m_icon; protected string m_icon;
protected string[] m_images; protected string[] m_images;
protected string m_description; protected string m_description;
protected string m_sourceCode; protected Link[] m_sourceCode = [];
/** /**
* Creates a project from a file * Creates a project from a file
@ -39,7 +41,13 @@ class Project : Page {
this.m_images = headerNode.getArray!string("images", []) this.m_images = headerNode.getArray!string("images", [])
.map!(x => PROJECT_IMAGE_DIR ~ x).array; .map!(x => PROJECT_IMAGE_DIR ~ x).array;
this.m_description = headerNode.getOr!string("description", "<no description>"); this.m_description = headerNode.getOr!string("description", "<no description>");
this.m_sourceCode = headerNode.getOr!string("sourceCode", null); if ("sourceCode" in headerNode) {
m_sourceCode.reserve(headerNode.length);
foreach(Node node; headerNode["sourceCode"]) {
m_sourceCode ~= tuple!("name", "url")(node.getOr!string("name", "link"),
node.getOr!string("url", "#"));
}
}
} }
@property string state() { return m_state; } @property string state() { return m_state; }
@ -48,6 +56,6 @@ class Project : Page {
@property string icon() { return m_icon; } @property string icon() { return m_icon; }
@property string[] images() { return m_images; } @property string[] images() { return m_images; }
@property string description() { return m_description; } @property string description() { return m_description; }
@property string sourceCode() { return m_sourceCode; } @property Link[] sourceCode() { return m_sourceCode; }
} }

View file

@ -9,6 +9,9 @@ import vibe.d;
import app; import app;
import page; import page;
/**
* Loads pages into memory and sets up a "watcher" to watch a directory for file changes.
*/
void initPages(T, string sortPred)(ref T[string] array, ref T*[] sortedRange, const string directory) { void initPages(T, string sortPred)(ref T[string] array, ref T*[] sortedRange, const string directory) {
bool addPage(string path) { bool addPage(string path) {
@ -86,7 +89,7 @@ void initPages(T, string sortPred)(ref T[string] array, ref T*[] sortedRange, co
} }
} }
} }
logf("Modified %s", newPage.slug); logf("%s modified: %s", typeid(T).stringof, newPage.slug);
array[newPage.slug] = newPage; array[newPage.slug] = newPage;
} catch(page.ArticleParseException e) { } catch(page.ArticleParseException e) {
warningf("Could not parse %s", change.path.toString()); warningf("Could not parse %s", change.path.toString());

View file

@ -1,6 +1,19 @@
msgid "template.page.name" msgid "template.page.name"
msgstr "Chris's website" 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.page.copyright" msgid "template.page.copyright"
msgstr "&copy; Chris Josten, 2021. If not specified otherwise, all content on this" msgstr "&copy; Chris Josten, 2021. If not specified otherwise, all content on this"
"website is <a rel=\"license\" href=\"https://creativecommons.org/licenses/by/4.0/\">" "website is <a rel=\"license\" href=\"https://creativecommons.org/licenses/by/4.0/\">"

View file

@ -11,9 +11,21 @@ msgstr ""
"Language: nl\n" "Language: nl\n"
"X-Generator: Poedit 2.3.1\n" "X-Generator: Poedit 2.3.1\n"
msgid "template.menu.home"
msgstr "Thuis"
msgid "template.menu.posts"
msgstr "Berichten"
msgid "template.menu.projects"
msgstr "Projecten"
msgid "template.page.name" msgid "template.page.name"
msgstr "Chris z'n webstekkie" msgstr "Chris z'n webstekkie"
msgid "template.page.html_language"
msgstr "nl-NL"
msgid "template.page.copyright" msgid "template.page.copyright"
msgstr "&copy; Chris Josten, 2021. Tenzij anders vermeld staat, valt alle inhoud op deze webstek" 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>" "<a rel=\"license\" href=\"https://creativecommons.org/licenses/by/4.0/\"> onder de CC-BY 4.0</a>"

View file

@ -13,7 +13,7 @@ block extra_meta_data
meta(name="og:article:modified_time", content=content.updated.toISOExtString) meta(name="og:article:modified_time", content=content.updated.toISOExtString)
block content block content
article(itemscope, itemtype="https://schema.org/BlogPosting") article(itemscope, itemtype="https://schema.org/BlogPosting", lang="#{content.language}")
- import utils; - import utils;
header header
h1.title(itemprop="headline") #{content.title} h1.title(itemprop="headline") #{content.title}

View file

@ -12,4 +12,4 @@ block sidebar
block content block content
header header
h1.title #{content.title} h1.title #{content.title}
section !{content.content} section(lang="#{content.language}") !{content.content}

View file

@ -8,7 +8,7 @@ block meta_data
block sidebar block sidebar
block content block content
section section(lang="#{content.language}")
header.project-header header.project-header
img.project-icon(src="#{content.icon}", alt="Icon of #{content.title}") img.project-icon(src="#{content.icon}", alt="Icon of #{content.title}")
div div
@ -31,4 +31,8 @@ block content
dt Technologies dt Technologies
- foreach(technology; content.technologies) - foreach(technology; content.technologies)
dd.tag #{technology} dd.tag #{technology}
dt Source code
- foreach(sourceCodeLink; content.sourceCode)
dd
a(href="#{sourceCodeLink.url}", rel="external") #{sourceCodeLink.name}
| !{content.content} | !{content.content}

View file

@ -1,6 +1,7 @@
doctype html doctype html
html(prefix="og: http://ogp.me/ns#") html(prefix="og: http://ogp.me/ns#")
- import constants; - import constants;
- import vibe.d;
head head
//- Kick off loading the css as fast as possible //- Kick off loading the css as fast as possible
meta(name="viewport", content="width=device-width; initial-scale=1") meta(name="viewport", content="width=device-width; initial-scale=1")
@ -40,7 +41,7 @@ html(prefix="og: http://ogp.me/ns#")
body body
- void menuItem(string text, string link) - void menuItem(string text, string link)
li li
a(href="#{link}") #{text} a(href="#{link}") #{trWeb(text)}
section.header-navigation section.header-navigation
header header
@ -48,9 +49,9 @@ html(prefix="og: http://ogp.me/ns#")
p& template.page.name p& template.page.name
nav nav
ul ul
- menuItem("home", "/"); - menuItem("template.menu.home", "/");
- menuItem("posts", "/posts/"); - menuItem("template.menu.posts", "/posts/");
- menuItem("projects", "/projects/"); - menuItem("template.menu.projects", "/projects/");
block sidebar block sidebar
footer.hide-small footer.hide-small
block footer block footer