Compare commits

...

13 commits

Author SHA1 Message Date
Chris Josten 0ad53b1a24 Update dub selections 2023-12-08 22:59:09 +01:00
Chris Josten 7bb5c65d90 Bump version to 0.0.3 2023-12-08 22:57:15 +01:00
Chris Josten 651668526d Update dmd version + dependencies 2023-12-08 22:52:11 +01:00
Chris Josten bdb7615044 Fix building on NixOS 2022-09-15 20:29:06 +02:00
Chris Josten 9a5aeb1526 Upgrade version number 2022-09-15 17:43:07 +02:00
Chris Josten cc526e88f0 Upgrade dependencies 2022-09-15 17:41:15 +02:00
Chris Josten 40eeb9d25a Fix whitespace 2022-05-30 12:48:57 +02:00
Chris Josten 16f25d8297 Update nix deps 2022-05-25 14:49:54 +02:00
Chris Josten 223ca8bc29 Workaround broken l10n, upgrade deps 2022-05-25 14:46:37 +02:00
Chris Josten 1d0d1a54b1 Fix crash caused by lastIndexOf returning negative numbers
The ArticleParser would crash when a negative number was returned by
lastIndexOf, since it was casted to an unsigned integer. This unsigned
integer then was used to allocate memory, which would allocate way to
much memory, causing a MemoryException and crashing the process.
2021-10-13 14:07:27 +02:00
Chris Josten 48b95c4a13 Article: parse document separators properly
Document separators should start with a newline, followed by three
dashes, followed by a newline again.
2021-10-11 15:15:12 +02:00
Chris Josten 75f5d447d6 Update dependencies Nix 2021-08-17 10:04:36 +02:00
Chris Josten e806dbf1cd Fix NixOS build 2021-06-27 12:50:21 +02:00
16 changed files with 150 additions and 81 deletions

View file

@ -11,5 +11,6 @@
"license": "AGPLv3",
"name": "mijnblog",
"targetType": "executable",
"stringImportPaths": ["views", "translations"]
"stringImportPaths": ["views", "translations"],
"versions": ["DeimosOpenSSL_3_0"]
}

View file

@ -3,19 +3,21 @@
"versions": {
"botan": "1.12.19",
"botan-math": "1.0.3",
"diet-ng": "1.7.5",
"dyaml": "0.8.3",
"eventcore": "0.9.13",
"diet-ng": "1.8.1",
"dyaml": "0.8.6",
"eventcore": "0.9.26",
"fswatch": "0.5.0",
"libasync": "0.8.6",
"libevent": "2.0.2+2.0.16",
"memutils": "1.0.4",
"memutils": "1.0.9",
"mir-linux-kernel": "1.0.1",
"openssl": "1.1.6+1.0.1g",
"openssl": "3.3.3",
"openssl-static": "1.0.2+3.0.8",
"stdx-allocator": "2.77.5",
"taggedalgebraic": "0.11.19",
"taggedalgebraic": "0.11.22",
"tinyendian": "0.2.0",
"vibe-core": "1.13.0",
"vibe-d": "0.9.3"
"vibe-container": "1.0.1",
"vibe-core": "2.5.1",
"vibe-d": "0.9.7"
}
}

View file

@ -51,49 +51,61 @@
fetch = {
type = "git";
url = "https://github.com/etcimon/memutils.git";
rev = "v1.0.4";
sha256 = "1m65iy03yl5km61ijk5ysapxc5mks9b15hmaqxpn111981qrqx9z";
rev = "v1.0.9";
sha256 = "08j9grn3l6gr275m392l0dfsx5ma6hs08gjfhh48hpy3v0bvb0ny";
fetchSubmodules = false;
date = "2020-02-02T20:53:12-05:00";
date = "2023-03-02T15:19:28-05:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/3pmdm9szxsqfvi2dv8b58vk7856g3gd8-memutils";
path = "/nix/store/glnf0ljd84mv6gzc9wgs1qq0vqqxvmzh-memutils";
};
} {
fetch = {
type = "git";
url = "https://github.com/s-ludwig/taggedalgebraic.git";
rev = "v0.11.19";
sha256 = "1mb4l9hhkzhwwj2v3m9l4g59q66msy15ky762wk5dv11viyfwrqb";
rev = "v0.11.22";
sha256 = "02iy90nwy0zzy25hwdqbcgd0w0lwzramcvi3pgyljhq0w0vl5hkq";
fetchSubmodules = false;
date = "2021-01-13T16:58:20+01:00";
date = "2021-05-20T21:00:02+02:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/qlw3bv0xqd0dl01hd9lcyk9cx7v9qhvi-taggedalgebraic";
path = "/nix/store/p8id0qb13j8pjdczflj2x35w6v63q4cx-taggedalgebraic";
};
} {
fetch = {
type = "git";
url = "https://github.com/vibe-d/vibe-core.git";
rev = "v1.13.0";
sha256 = "1zbx861dwmkp14pbzr4qyq71xsnlksx248x0a1q6afjmvvxiys8w";
url = "https://github.com/vibe-d/vibe-container.git";
rev = "v1.0.1";
sha256 = "0miynjmfzz340z3qw9mclaj6cyirzrpk528idr5yfmvl3jsi6wh8";
fetchSubmodules = false;
date = "2021-01-15T21:35:13+01:00";
date = "2023-11-27T09:12:47+01:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/zngy3z8hmdgjg8wl31d2qy194mhz0i09-vibe-core";
path = "/nix/store/2vnn20q8k335h5k078yk4lrxkp4y63pd-vibe-container";
};
} {
fetch = {
type = "git";
url = "https://github.com/vibe-d/vibe.d.git";
rev = "v0.9.3";
sha256 = "10a5njn2nq1z6gknmkg6m6wrbndzj19mpg5860ky6v12b9ks76z3";
rev = "v0.9.7";
sha256 = "1q4yvcaf36lmf29izg01x888v40snpwiph310nrlpr4gyhd834av";
fetchSubmodules = false;
date = "2021-01-29T11:37:00+01:00";
date = "2023-08-29T13:24:09+02:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/8r3h7npkhj9wq9lg64i3fih19hibpmg5-vibe.d";
path = "/nix/store/7fq089i7zib7m9hxyl75mlfy264d9gnx-vibe.d";
};
} {
fetch = {
type = "git";
url = "https://github.com/vibe-d/vibe-core.git";
rev = "v2.5.1";
sha256 = "1g66vyn9hivy8rmsdl1xg1vz41csq5k91c04yvp4wqbil9cwgqdr";
fetchSubmodules = false;
date = "2023-11-24T17:25:20+01:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/iddq1amvzic8fn4xa2317ykmkrkdr51y-vibe-core";
};
} {
fetch = {
@ -123,13 +135,13 @@
fetch = {
type = "git";
url = "https://github.com/rejectedsoftware/diet-ng.git";
rev = "v1.7.5";
sha256 = "1cymg3v924d499sbjagjf5dqv1pj196c55a2282knxgq18a3gynf";
rev = "v1.8.1";
sha256 = "11hrbvsxhipvcz9m1qlq92iaw0h35pzdy5rf7z8c4vx3hwjrnhni";
fetchSubmodules = false;
date = "2021-02-07T14:20:30+01:00";
date = "2022-04-22T11:38:43+02:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/5r6v9f7y9kwkb90ihgimqqryf6ls3kqq-diet-ng";
path = "/nix/store/xziliy9ah3s3ah8mslnxsw47n4w6wkca-diet-ng";
};
} {
fetch = {
@ -147,37 +159,37 @@
fetch = {
type = "git";
url = "https://github.com/D-Programming-Deimos/openssl.git";
rev = "v1.1.6+1.0.1g";
sha256 = "0ramqjyq4v7xpqwf4nf4ddmsg6yk2fbzn2d1yj4b6dla3q5lv9i3";
rev = "v3.3.3";
sha256 = "1634j4psp3qwgwhk2sa3jj6gvwv3i96hpg2wrdy9ihjhabnszn0f";
fetchSubmodules = false;
date = "2017-11-05T20:15:26+01:00";
date = "2023-09-14T12:05:32+00:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/jbfb5in6gzqs2byn1hdc1625yh8sx6j2-openssl";
path = "/nix/store/i3pgh154r80xvh4vsnl6srg6khmk5dg7-openssl";
};
} {
fetch = {
type = "git";
url = "https://github.com/vibe-d/eventcore.git";
rev = "v0.9.13";
sha256 = "0frxifhjwzyi35cv4pvv8k11a966fg76gqxdpmx9bsqbx750lrvz";
rev = "v0.9.26";
sha256 = "13bjs5v5l1387vi2ss4gvqlslhq33v9sn4pg7nis4r0wdw0zmlk1";
fetchSubmodules = false;
date = "2021-01-12T19:20:28+01:00";
date = "2023-09-16T09:46:45+02:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/yikgbvj61xhk6r3x8pc8lb7sp5smcn5q-eventcore";
path = "/nix/store/zy7ydasg4fwnim2m1mi4gzdg9l087wpb-eventcore";
};
} {
fetch = {
type = "git";
url = "https://github.com/kiith-sa/D-YAML.git";
rev = "v0.8.3";
sha256 = "13wy304xjbwkpgg7ilql1lkxkm83s87jm59ffnrg26slp7cx149q";
rev = "v0.8.6";
sha256 = "1bvidcxp1n65r4wmiqakyl8vjvhqh3gln9wbsmbxrx9mf6k0zv8h";
fetchSubmodules = false;
date = "2020-09-19T23:46:57+02:00";
date = "2022-05-15T16:18:02-03:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/3i8i56lkmw2xq3lxr5h66v909waq2mqg-D-YAML";
path = "/nix/store/zd0yayd1j11809j95sjs4gdqcngvkhbg-D-YAML";
};
} {
fetch = {
@ -191,4 +203,16 @@
leaveDotGit = false;
path = "/nix/store/6l82qf5nav5pkbvnrhcs5v9vwj5xycq3-libasync";
};
} {
fetch = {
type = "git";
url = "https://github.com/bildhuus/deimos-openssl-static.git";
rev = "v1.0.2+3.0.8";
sha256 = "00wllmfrjpq5ln3zs9qcqf4kq2i6bqbjxwj0jnxwwz125kfm55sy";
fetchSubmodules = false;
date = "2023-02-24T13:23:37+01:00";
deepClone = false;
leaveDotGit = false;
path = "/nix/store/g9shdkm450yg8c15rvqms8v09vql8z0l-deimos-openssl-static";
};
} ]

View file

@ -6,7 +6,11 @@ mkDubDerivation {
src = ./.;
dubJSON = ./dub.json;
selections = ./dub.selections.nix;
version = "0.0.1";
version = "0.0.3";
buildInputs = [ pkgs.openssl ];
propagatedBuildInputs = [ pkgs.nix-prefetch-git ];
extraDubFlags = "--override-config openssl/library-manual-version";
preBuild = ''
export DC=${pkgs.dmd}/bin/dmd
'';
}

View file

@ -1,7 +1,9 @@
{ pkgs ? import <nixpkgs> {},
stdenv ? pkgs.stdenv,
rdmd ? pkgs.rdmd,
lib ? pkgs.lib,
dtools ? pkgs.dtools or pkgs.rdmd,
dmd ? pkgs.dmd,
dcompiler ? dmd,
dub ? pkgs.dub }:
with stdenv;
@ -20,7 +22,7 @@ let
fromDub = dubDep: mkDerivation rec {
name = "${src.name}-${version}";
version = rev-to-version dubDep.fetch.rev;
nativeBuildInputs = [ rdmd dmd dub ];
nativeBuildInputs = [ dcompiler dtools dub ];
src = dep2src dubDep;
buildPhase = ''
@ -46,10 +48,18 @@ let
targetOf = package: "${package.targetPath or "."}/${package.targetName or package.name}";
# Remove reference to build tools and library sources
disallowedReferences = deps: [ dmd rdmd dub ] ++ builtins.map dep2src deps;
disallowedReferences = deps: [ dcompiler dtools dub ] ++ builtins.map dep2src deps;
removeExpr = refs: ''remove-references-to ${lib.concatMapStrings (ref: " -t ${ref}") refs}'';
# Like split, but only keep the matches
matches = regex: str: builtins.filter lib.isList (builtins.split regex str);
# Very primitive parsing of SDL files, but suffices for name, description, homepage, etc.
importSDL = path: builtins.foldl' (a: l: a // {"${lib.elemAt l 1}"=lib.elemAt l 2;}) {} (matches "(^|\n)([a-z]+) \"([^\"]+)\"" (builtins.readFile path));
importPackage = sdl: json: if builtins.pathExists sdl then importSDL sdl else lib.importJSON json;
in {
inherit fromDub;
@ -57,20 +67,23 @@ in {
src,
nativeBuildInputs ? [],
dubJSON ? src + "/dub.json",
dubSDL ? src + "/dub.sdl",
buildType ? "release",
extraDubFlags ? "",
selections ? src + "/dub.selections.nix",
deps ? import selections,
package ? importPackage dubSDL dubJSON,
passthru ? {},
package ? lib.importJSON dubJSON,
...
} @ attrs: stdenv.mkDerivation (attrs // {
} @ attrs: stdenv.mkDerivation ((removeAttrs attrs ["package" "deps" "selections" "dubJSON" "dubSDL"]) // {
pname = package.name;
nativeBuildInputs = [ rdmd dmd dub pkgs.removeReferencesTo ] ++ nativeBuildInputs;
nativeBuildInputs = [ dcompiler dtools dub pkgs.removeReferencesTo ] ++ nativeBuildInputs;
disallowedReferences = disallowedReferences deps;
passthru = passthru // {
inherit dub dmd rdmd pkgs;
inherit dub dcompiler dtools pkgs;
};
src = lib.cleanSourceWith {
@ -87,7 +100,7 @@ in {
export HOME=$PWD
${lib.concatMapStringsSep "\n" dub-add-local deps}
dub build -b release --combined --skip-registry=all
dub build -b ${buildType} --combined --skip-registry=all ${extraDubFlags}
runHook postBuild
'';
@ -97,7 +110,7 @@ in {
export HOME=$PWD
${lib.concatMapStringsSep "\n" dub-add-local deps}
dub test --combined --skip-registry=all
dub test --combined --skip-registry=all ${extraDubFlags}
runHook postCheck
'';
@ -113,6 +126,8 @@ in {
meta = lib.optionalAttrs (package ? description) {
description = package.description;
} // lib.optionalAttrs (package ? homepage) {
homepage = package.homepage;
} // attrs.meta or {};
} // lib.optionalAttrs (!(attrs ? version)) {
# Use name from dub.json, unless pname and version are specified

View file

@ -5,6 +5,7 @@ import article;
import page;
import project;
@safe:
/**
* Default ordering and list with pointers to ordered articles.

View file

@ -58,7 +58,7 @@ struct TranslateContext {
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");
return determineLanguageByHeader(req.query.get("lang", "en_GB"), languages);
}
}
@ -80,7 +80,7 @@ string singleResponseMixin(string arrayName, string templateName) {
break;
default:
case HTML:
render!("` ~ templateName ~ `", content);
res.render!("` ~ templateName ~ `", content);
break;
}`;
}

View file

@ -9,19 +9,29 @@ import cache;
import http;
import watcher;
void watchTask(T, C)(C *cache, string directory) @safe nothrow {
do {
try {
initPages!T(cache, directory);
} catch(Exception e) {
logWarn("Error while watching pages: " ~ e.msg);
}
} while(Task.getThis().running);
}
void main() {
startHTTPServer();
// Start indexing pages.
runTask({
initPages!Page(&pages, "pages");
watchTask!Page(&pages, "pages");
});
runTask({
initPages!Article(&articles, "articles");
watchTask!Article(&articles, "articles");
});
runTask({
initPages!Project(&projects, "projects");
watchTask!Project(&projects, "projects");
});
runApplication();
}

View file

@ -10,6 +10,7 @@ import vibe.d;
import page;
import utils;
@safe:
/**
* Represents an article on the blog
@ -34,9 +35,9 @@ class Article : Page {
// Find the first header and mark everything up to that as
if (m_excerpt is null) {
// an excerpt, used in search results.
const uint seperatorIndex = cast(uint) indexOf(m_contentSource, "---\n");
const long seperatorIndex = cast(long) lastIndexOf(m_contentSource, "---\n");
this.m_excerpt = this.m_contentSource[seperatorIndex + 4..$];
const uint firstHeaderIndex = cast(uint) indexOf(this.m_excerpt, '#');
const long firstHeaderIndex = indexOf(this.m_excerpt, '#');
if (firstHeaderIndex >= 0) {
this.m_excerpt = this.m_excerpt[0..firstHeaderIndex];
}

View file

@ -9,6 +9,7 @@ import vibe.vibe;
import utils;
@safe:
/**
* Exception thrown when a page has syntax errors e.g.
@ -51,11 +52,11 @@ class Page {
/**
* Creates a page from a file. This will read from the file and parse it.
*/
this(string file) {
this(string file) @safe {
this.m_name = file;
this.m_contentSource = readText(file);
// Find the seperator and split the string in two
const uint seperatorIndex = cast(uint) lastIndexOf(m_contentSource, "---\n");
const long seperatorIndex = lastIndexOf(m_contentSource, "\n---\n");
enforce!ArticleParseException(seperatorIndex >= 0);
string header = m_contentSource[0..seperatorIndex];

View file

@ -9,6 +9,8 @@ import page;
import utils;
import staticpaths;
@safe:
/**
* Represents a project, like an unfinished application
*/

View file

@ -1,6 +1,6 @@
import std.array;
import std.algorithm;
import std.experimental.logger;
//import std.experimental.logger;
import std.file;
import std.stdio;
import std.traits;
@ -13,27 +13,35 @@ import page;
/**
* Loads pages into memory and sets up a "watcher" to watch a directory for file changes.
*/
void initPages(T, C)(C *cache, const string directory)
void initPages(T, C)(C *cache, const string directory) @trusted
if (isImplicitlyConvertible!(T, Page)) {
NativePath watchingDir;
try {
watchingDir = getWorkingDirectory() ~ directory;
} catch(PathValidationException) {
logError("Cannot watch path " ~ directory);
return;
}
bool addPage(string path) {
try {
T newPage = new T(path);
logf("Added %s", newPage.slug);
logInfo("Added %s", newPage.slug);
cache.addItem(newPage);
return true;
} catch (page.ArticleParseException e) {
logf("Could not parse %s: %s", path, e);
logWarn("Could not parse %s: %s", path, e);
return false;
} catch (Exception e) {
logf("Other exception while parsing %s: %s", path, e);
logWarn("Other exception while parsing %s: %s", path, e);
return false;
}
}
// Initial scan
void scan(NativePath path, int level = 0) {
logf("Scanning %s", path.toString());
logInfo("Scanning %s", path.toString());
foreach(file; iterateDirectory(path)) {
if (file.isDirectory) {
scan(path ~ file.name, level + 1);
@ -43,11 +51,11 @@ void initPages(T, C)(C *cache, const string directory)
}
}
if (!existsFile(getWorkingDirectory() ~ directory)) {
createDirectory(getWorkingDirectory() ~ directory);
if (!existsFile(watchingDir)) {
createDirectory(watchingDir);
}
scan(getWorkingDirectory() ~ directory);
DirectoryWatcher watcher = watchDirectory(getWorkingDirectory() ~ directory, true);
scan(watchingDir);
DirectoryWatcher watcher = watchDirectory(watchingDir, true);
bool shouldStop = false;
while (!shouldStop) {
@ -55,16 +63,16 @@ void initPages(T, C)(C *cache, const string directory)
DirectoryChange[] changes;
shouldStop = !watcher.readChanges(changes);
foreach(change; changes) {
logf("=======[New changes]======");
logInfo("=======[New changes]======");
string[] changeTypes = ["added", "removed", "modified"];
logf("Path: %s, type: %s", change.path.toString(), changeTypes[change.type]);
logInfo("Path: %s, type: %s", change.path.toString(), changeTypes[change.type]);
if (endsWith(change.path.toString(), ".kate-swp")) continue;
switch (change.type) with (DirectoryChangeType){
case added:
try {
addPage(change.path.toString());
} catch(Exception e) {
warningf("Error while updating %s: %s", change.path.toString(), e.msg);
logWarn("Error while updating %s: %s", change.path.toString(), e.msg);
}
break;
case modified:
@ -73,16 +81,16 @@ void initPages(T, C)(C *cache, const string directory)
newPage = new T(change.path.toString());
cache.changeItem(newPage);
} catch(page.ArticleParseException e) {
warningf("Could not parse %s", change.path.toString());
logWarn("Could not parse %s", change.path.toString());
} catch (Exception e) {
warningf("Error while updating %s: %s", change.path.toString(), e.msg);
logWarn("Error while updating %s: %s", change.path.toString(), e.msg);
}
break;
case removed:
try {
cache.removeItemByName(change.path.toString());
} catch(Exception e) {
logf("Error while trying to remove %s: %s", T.stringof, e.msg);
logInfo("Error while trying to remove %s: %s", T.stringof, e.msg);
}
break;
default: break;

View file

@ -17,6 +17,6 @@ msgid "template.menu.contact"
msgstr "Contact"
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/\">"
"licensed under the CC-BY 4.0</a>"

View file

@ -30,5 +30,5 @@ msgid "template.menu.contact"
msgstr "Contact"
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>"

View file

@ -1,2 +1,2 @@
p
small& template.page.copyright
small !{trWeb("template.page.copyright")}

View file

@ -46,7 +46,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& template.page.name
p #{trWeb("template.page.name")}
nav
ul
- menuItem("template.menu.home", "/");