Add more support for internationalisation, style changes
This commit is contained in:
parent
5506163cba
commit
46bea4fa58
19
defaultClasses.lua
Normal file
19
defaultClasses.lua
Normal 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
|
@ -22,6 +22,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.hide-big {
|
||||
display: none;
|
||||
}
|
||||
|
@ -31,6 +32,7 @@
|
|||
--colour-bg: #f0f0f0;
|
||||
--colour-bg-main: #ddd;
|
||||
--colour-bg-code: #ccc;
|
||||
--colour-bg-highlight: #f9f890;
|
||||
--colour-fg: #000000;
|
||||
--colour-fg-highlight: #7f0602;
|
||||
--colour-fg-lineno: #111;
|
||||
|
@ -45,6 +47,7 @@
|
|||
--colour-bg: #101010;
|
||||
--colour-bg-main: #333;
|
||||
--colour-bg-code: #222;
|
||||
--colour-bg-highlight: #727000;
|
||||
--colour-fg: #ffffff;
|
||||
--colour-fg-highlight: #fc918d;
|
||||
--colour-fg-lineno: #ccc;
|
||||
|
@ -71,6 +74,12 @@ body > section.header-navigation {
|
|||
padding: 2em;
|
||||
}
|
||||
|
||||
@media (pointer: coarse) {
|
||||
body > section.header-navigation li {
|
||||
padding: 0.25em 0;
|
||||
}
|
||||
}
|
||||
|
||||
body > footer {
|
||||
flex: 0 0 200px;
|
||||
padding: 2em;
|
||||
|
@ -81,7 +90,6 @@ body > section.header-navigation > header {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
body > section.header-navigation > header > img {
|
||||
width: 100%;
|
||||
max-width: 160px;
|
||||
|
@ -176,6 +184,10 @@ dl.project-platforms-technologies {
|
|||
border-bottom: 1px dotted var(--colour-fg);
|
||||
}
|
||||
|
||||
dt + dd.tag {
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
background-color: #ccc;
|
||||
|
@ -266,3 +278,39 @@ a:hover {
|
|||
color: var(--colour-fg);
|
||||
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: ''
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,3 +60,4 @@ code span.st { color: var(--colour-fg-code-string); } /* String */
|
|||
code span.va { color: #19177c; } /* Variable */
|
||||
code span.vs { color: #4070a0; } /* VerbatimString */
|
||||
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||||
code span:target { background-color: var(--colour-bg-highlight); }
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
body {
|
||||
background: red;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
11
source/app.d
11
source/app.d
|
@ -169,17 +169,6 @@ public:
|
|||
//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.
|
||||
*
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -88,6 +88,7 @@ class Page {
|
|||
this.m_slug = this.m_title;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -102,7 +103,8 @@ class Page {
|
|||
public static string parseMarkdown(string source, int shiftHeader = 0) {
|
||||
string[] args = ["pandoc",
|
||||
"-f", "markdown",
|
||||
"-t", "html"];
|
||||
"-t", "html",
|
||||
"--lua-filter", "defaultClasses.lua"];
|
||||
|
||||
if (shiftHeader != 0) args ~= "--shift-heading-level-by=" ~ to!string(shiftHeader);
|
||||
|
||||
|
@ -117,7 +119,7 @@ class Page {
|
|||
while ((line = pandoc.stdout.readln()) !is null) {
|
||||
result ~= line;
|
||||
debug {
|
||||
logf("Pandoc stdout: %s", line);
|
||||
//logf("Pandoc stdout: %s", line);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import std.array;
|
||||
import std.algorithm;
|
||||
import std.typecons;
|
||||
|
||||
import dyaml;
|
||||
import vibe.vibe;
|
||||
|
@ -12,6 +13,7 @@ import utils;
|
|||
* Represents a project, like an unfinished application
|
||||
*/
|
||||
class Project : Page {
|
||||
alias Link= Tuple!(string, "name", string, "url");
|
||||
protected immutable string PROJECT_ICON_DIR = IMG_DIR ~ "projects/icons/";
|
||||
protected immutable string PROJECT_IMAGE_DIR = IMG_DIR ~ "projects/images/";
|
||||
protected string m_state;
|
||||
|
@ -20,7 +22,7 @@ class Project : Page {
|
|||
protected string m_icon;
|
||||
protected string[] m_images;
|
||||
protected string m_description;
|
||||
protected string m_sourceCode;
|
||||
protected Link[] m_sourceCode = [];
|
||||
|
||||
/**
|
||||
* Creates a project from a file
|
||||
|
@ -39,7 +41,13 @@ class Project : Page {
|
|||
this.m_images = headerNode.getArray!string("images", [])
|
||||
.map!(x => PROJECT_IMAGE_DIR ~ x).array;
|
||||
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; }
|
||||
|
@ -48,6 +56,6 @@ class Project : Page {
|
|||
@property string icon() { return m_icon; }
|
||||
@property string[] images() { return m_images; }
|
||||
@property string description() { return m_description; }
|
||||
@property string sourceCode() { return m_sourceCode; }
|
||||
@property Link[] sourceCode() { return m_sourceCode; }
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ import vibe.d;
|
|||
import app;
|
||||
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) {
|
||||
|
||||
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;
|
||||
} catch(page.ArticleParseException e) {
|
||||
warningf("Could not parse %s", change.path.toString());
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
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.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/\">"
|
||||
|
|
|
@ -11,9 +11,21 @@ msgstr ""
|
|||
"Language: nl\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"
|
||||
msgstr "Chris z'n webstekkie"
|
||||
|
||||
msgid "template.page.html_language"
|
||||
msgstr "nl-NL"
|
||||
|
||||
msgid "template.page.copyright"
|
||||
msgstr "© 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>"
|
||||
|
|
|
@ -13,7 +13,7 @@ block extra_meta_data
|
|||
meta(name="og:article:modified_time", content=content.updated.toISOExtString)
|
||||
|
||||
block content
|
||||
article(itemscope, itemtype="https://schema.org/BlogPosting")
|
||||
article(itemscope, itemtype="https://schema.org/BlogPosting", lang="#{content.language}")
|
||||
- import utils;
|
||||
header
|
||||
h1.title(itemprop="headline") #{content.title}
|
||||
|
|
|
@ -12,4 +12,4 @@ block sidebar
|
|||
block content
|
||||
header
|
||||
h1.title #{content.title}
|
||||
section !{content.content}
|
||||
section(lang="#{content.language}") !{content.content}
|
||||
|
|
|
@ -8,7 +8,7 @@ block meta_data
|
|||
block sidebar
|
||||
|
||||
block content
|
||||
section
|
||||
section(lang="#{content.language}")
|
||||
header.project-header
|
||||
img.project-icon(src="#{content.icon}", alt="Icon of #{content.title}")
|
||||
div
|
||||
|
@ -31,4 +31,8 @@ block content
|
|||
dt Technologies
|
||||
- foreach(technology; content.technologies)
|
||||
dd.tag #{technology}
|
||||
dt Source code
|
||||
- foreach(sourceCodeLink; content.sourceCode)
|
||||
dd
|
||||
a(href="#{sourceCodeLink.url}", rel="external") #{sourceCodeLink.name}
|
||||
| !{content.content}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
doctype html
|
||||
html(prefix="og: http://ogp.me/ns#")
|
||||
- import constants;
|
||||
- import vibe.d;
|
||||
head
|
||||
//- Kick off loading the css as fast as possible
|
||||
meta(name="viewport", content="width=device-width; initial-scale=1")
|
||||
|
@ -40,7 +41,7 @@ html(prefix="og: http://ogp.me/ns#")
|
|||
body
|
||||
- void menuItem(string text, string link)
|
||||
li
|
||||
a(href="#{link}") #{text}
|
||||
a(href="#{link}") #{trWeb(text)}
|
||||
|
||||
section.header-navigation
|
||||
header
|
||||
|
@ -48,9 +49,9 @@ html(prefix="og: http://ogp.me/ns#")
|
|||
p& template.page.name
|
||||
nav
|
||||
ul
|
||||
- menuItem("home", "/");
|
||||
- menuItem("posts", "/posts/");
|
||||
- menuItem("projects", "/projects/");
|
||||
- menuItem("template.menu.home", "/");
|
||||
- menuItem("template.menu.posts", "/posts/");
|
||||
- menuItem("template.menu.projects", "/projects/");
|
||||
block sidebar
|
||||
footer.hide-small
|
||||
block footer
|
||||
|
|
Loading…
Reference in a new issue