Compare commits
2 Commits
d30b078411
...
46b3656161
Author | SHA1 | Date | |
---|---|---|---|
46b3656161 | |||
ea64bc70fc |
54
css.nix
54
css.nix
@ -1,19 +1,43 @@
|
|||||||
{utils}: let
|
{lib, ...}: let
|
||||||
inherit (utils) mapAttrsToList concatStringsSep isList toString map;
|
l = lib // builtins;
|
||||||
|
t = l.types;
|
||||||
|
|
||||||
evalCssValue = value:
|
evalCssValue = value:
|
||||||
if isList value
|
if l.isList value
|
||||||
then concatStringsSep ", " (map toString value)
|
then l.concatStringsSep ", " (l.map toString value)
|
||||||
else toString value;
|
else l.toString value;
|
||||||
evalInner = inner: concatStringsSep " " (mapAttrsToList (name: value: "${name}: ${evalCssValue value};") inner);
|
evalInner = inner:
|
||||||
css = maybeAttrs:
|
l.concatStringsSep
|
||||||
if isList maybeAttrs
|
" "
|
||||||
then concatStringsSep " " maybeAttrs
|
(
|
||||||
else concatStringsSep " " (mapAttrsToList (name: inner: "${name} { ${evalInner inner} }") maybeAttrs);
|
l.mapAttrsToList
|
||||||
|
(name: value: "${name}: ${evalCssValue value};")
|
||||||
|
inner
|
||||||
|
);
|
||||||
|
eval = maybeAttrs:
|
||||||
|
if l.isList maybeAttrs
|
||||||
|
then l.concatStringsSep " " maybeAttrs
|
||||||
|
else
|
||||||
|
l.concatStringsSep
|
||||||
|
" "
|
||||||
|
(
|
||||||
|
l.mapAttrsToList
|
||||||
|
(name: inner: "${name} { ${evalInner inner} }")
|
||||||
|
maybeAttrs
|
||||||
|
);
|
||||||
|
css = {
|
||||||
|
__functor = self: arg: eval arg;
|
||||||
|
media = rule: inner: ''
|
||||||
|
@media (${rule}) { ${eval inner} }
|
||||||
|
'';
|
||||||
|
};
|
||||||
in {
|
in {
|
||||||
inherit css;
|
options = {
|
||||||
|
html-nix.lib.css = l.mkOption {
|
||||||
media = rule: inner: ''
|
type = t.raw;
|
||||||
@media (${rule}) { ${css inner} }
|
};
|
||||||
'';
|
};
|
||||||
|
config = {
|
||||||
|
html-nix.lib.css = css;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
8
default.nix
Normal file
8
default.nix
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./html.nix
|
||||||
|
./css.nix
|
||||||
|
./pkgs-lib.nix
|
||||||
|
./templaters
|
||||||
|
];
|
||||||
|
}
|
3
examples/default.nix
Normal file
3
examples/default.nix
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
imports = [./site.nix];
|
||||||
|
}
|
@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
tags,
|
|
||||||
pkgs,
|
|
||||||
}:
|
|
||||||
with pkgs.htmlNix; let
|
|
||||||
index = with tags;
|
|
||||||
html [
|
|
||||||
(body [
|
|
||||||
(p "Hello world!")
|
|
||||||
(mkLink "./ex.html" "say bye")
|
|
||||||
])
|
|
||||||
];
|
|
||||||
|
|
||||||
ex = with tags;
|
|
||||||
html [
|
|
||||||
(body [
|
|
||||||
(p "Bye world!")
|
|
||||||
(mkLink "./index.html" "go back")
|
|
||||||
])
|
|
||||||
];
|
|
||||||
|
|
||||||
site = {
|
|
||||||
"index.html" = index;
|
|
||||||
"ex.html" = ex;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
mkServeFromSite site
|
|
@ -1,12 +1,12 @@
|
|||||||
{
|
topArgs: {
|
||||||
pkgs,
|
perSystem = {config, ...}: let
|
||||||
lib,
|
html-nix = config.html-nix.lib;
|
||||||
}: let
|
siteServe = html-nix.mkServeFromSite (html-nix.mkSiteFrom {
|
||||||
inherit (pkgs) htmlNix;
|
src = ./site;
|
||||||
src = ./site;
|
templater = topArgs.config.html-nix.lib.templaters.simple;
|
||||||
in
|
local = true;
|
||||||
htmlNix.mkServeFromSite (htmlNix.mkSiteFrom {
|
});
|
||||||
inherit src;
|
in {
|
||||||
templater = lib.templaters.basic;
|
apps.site.program = "${siteServe}/bin/serve";
|
||||||
local = true;
|
};
|
||||||
})
|
}
|
||||||
|
@ -6,4 +6,6 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
AAAAAAAAAAa `rust` `test` aaaaaaaaaaaa
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur condimentum felis risus, ac tempor eros mollis ac. Curabitur dictum justo magna, a tristique nibh euismod at. Nullam at laoreet quam, a facilisis massa. Vestibulum iaculis euismod lorem non consequat. Quisque elementum pharetra egestas. Mauris in enim facilisis, pretium lacus vitae, accumsan diam. Praesent ut finibus mauris, eget iaculis lorem. Cras pharetra lectus varius, volutpat odio sit amet, pulvinar lectus. Aliquam malesuada erat a enim rutrum viverra. Nullam blandit nec enim eu egestas. Duis venenatis aliquet cursus. Phasellus non posuere lectus, sed rhoncus mi. Quisque ut ornare dui. Ut eget elit ac leo aliquam aliquam.
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur condimentum felis risus, ac tempor eros mollis ac. Curabitur dictum justo magna, a tristique nibh euismod at. Nullam at laoreet quam, a facilisis massa. Vestibulum iaculis euismod lorem non consequat. Quisque elementum pharetra egestas. Mauris in enim facilisis, pretium lacus vitae, accumsan diam. Praesent ut finibus mauris, eget iaculis lorem. Cras pharetra lectus varius, volutpat odio sit amet, pulvinar lectus. Aliquam malesuada erat a enim rutrum viverra. Nullam blandit nec enim eu egestas. Duis venenatis aliquet cursus. Phasellus non posuere lectus, sed rhoncus mi. Quisque ut ornare dui. Ut eget elit ac leo aliquam aliquam.
|
@ -1,8 +0,0 @@
|
|||||||
tags:
|
|
||||||
with tags;
|
|
||||||
html [
|
|
||||||
(body [
|
|
||||||
(p "Hello,")
|
|
||||||
(p "world!")
|
|
||||||
])
|
|
||||||
]
|
|
61
flake.lock
61
flake.lock
@ -1,27 +1,12 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"flakeUtils": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1644229661,
|
|
||||||
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1644972330,
|
"lastModified": 1680668850,
|
||||||
"narHash": "sha256-6V2JFpTUzB9G+KcqtUR1yl7f6rd9495YrFECslEmbGw=",
|
"narHash": "sha256-mQMg13yRsS0LXVzaeoSPwqgPO6yhkGzGewPgMSqXSv8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "19574af0af3ffaf7c9e359744ed32556f34536bd",
|
"rev": "4a65e9f64e53fdca6eed31adba836717a11247d2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -31,10 +16,46 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs-lib": {
|
||||||
|
"locked": {
|
||||||
|
"dir": "lib",
|
||||||
|
"lastModified": 1680213900,
|
||||||
|
"narHash": "sha256-cIDr5WZIj3EkKyCgj/6j3HBH4Jj1W296z7HTcWj1aMA=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "e3652e0735fbec227f342712f180f4f21f0594f2",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"dir": "lib",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1680392223,
|
||||||
|
"narHash": "sha256-n3g7QFr85lDODKt250rkZj2IFS3i4/8HBU2yKHO3tqw=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "dcc36e45d054d7bb554c9cdab69093debd91a0b5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flakeUtils": "flakeUtils",
|
"nixpkgs": "nixpkgs",
|
||||||
"nixpkgs": "nixpkgs"
|
"parts": "parts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
60
flake.nix
60
flake.nix
@ -1,57 +1,19 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
flakeUtils.url = "github:numtide/flake-utils";
|
parts.url = "github:hercules-ci/flake-parts";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs = inp:
|
||||||
self,
|
inp.parts.lib.mkFlake {inputs = inp;} {
|
||||||
flakeUtils,
|
debug = true;
|
||||||
nixpkgs,
|
systems = ["x86_64-linux"];
|
||||||
}: let
|
imports = [
|
||||||
utils = import ./utils.nix;
|
./default.nix
|
||||||
|
./examples
|
||||||
lib = {
|
];
|
||||||
# Convert Nix expressions to HTML
|
flake = {
|
||||||
tags = import ./tags.nix {inherit utils;};
|
flakeModule = ./default.nix;
|
||||||
# Convert Nix expressions to CSS
|
|
||||||
css = import ./css.nix {inherit utils;};
|
|
||||||
|
|
||||||
# Various site templaters
|
|
||||||
templaters = {
|
|
||||||
# Basic templater with purecss, mobile responsive layout and supports posts
|
|
||||||
basic = import ./templaters/basic.nix;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = flakeUtils.lib.eachDefaultSystem (system: let
|
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
|
||||||
in {
|
|
||||||
lib = {
|
|
||||||
pkgsLib = import ./pkgs-lib.nix {
|
|
||||||
inherit pkgs;
|
|
||||||
utils = utils // {inherit (lib) tags css;};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
apps = with flakeUtils.lib; {
|
|
||||||
site = mkApp {
|
|
||||||
drv = import ./examples/site.nix {inherit lib pkgs;};
|
|
||||||
name = "serve";
|
|
||||||
};
|
|
||||||
basicServe = mkApp {
|
|
||||||
drv = import ./examples/serve.nix {
|
|
||||||
inherit (lib) tags;
|
|
||||||
inherit pkgs;
|
|
||||||
};
|
|
||||||
name = "serve";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
examples = {
|
|
||||||
tags = import ./examples/tags.nix lib.tags;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
in
|
|
||||||
outputs // {lib = outputs.lib // lib;};
|
|
||||||
}
|
}
|
||||||
|
49
html.nix
Normal file
49
html.nix
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{lib, ...}: let
|
||||||
|
l = lib // builtins;
|
||||||
|
|
||||||
|
evalAttrs = attrs:
|
||||||
|
l.concatStrings
|
||||||
|
(
|
||||||
|
l.mapAttrsToList
|
||||||
|
(name: value: " ${name}=\"${value}\"")
|
||||||
|
attrs
|
||||||
|
);
|
||||||
|
evalChildren = children:
|
||||||
|
if l.isList children
|
||||||
|
then l.concatStrings children
|
||||||
|
else children;
|
||||||
|
tag = name: maybeAttrs:
|
||||||
|
if l.isAttrs maybeAttrs
|
||||||
|
then (children: "<${name}${evalAttrs maybeAttrs}>${evalChildren children}</${name}>")
|
||||||
|
else tag name {} maybeAttrs;
|
||||||
|
noChildrenTag = name: attrs: "<${name} ${evalAttrs attrs}>";
|
||||||
|
|
||||||
|
tagsToGen =
|
||||||
|
(l.map (n: "h${l.toString n}") (l.range 1 6))
|
||||||
|
++ ["ul" "li" "html" "head" "body" "div" "p"]
|
||||||
|
++ ["a" "title" "code" "pre" "nav" "article" "script"];
|
||||||
|
tags = l.genAttrs tagsToGen tag;
|
||||||
|
|
||||||
|
noChildrenTagsToGen = ["link" "meta" "hr"];
|
||||||
|
noChildrenTags = l.genAttrs noChildrenTagsToGen noChildrenTag;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
html-nix.lib.html = l.mkOption {
|
||||||
|
type = l.types.raw;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
html-nix.lib.html =
|
||||||
|
tags
|
||||||
|
// noChildrenTags
|
||||||
|
// {
|
||||||
|
inherit tag;
|
||||||
|
mkLink = url: tags.a {href = url;};
|
||||||
|
mkStylesheet = url:
|
||||||
|
noChildrenTags.link {
|
||||||
|
rel = "stylesheet";
|
||||||
|
href = url;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
222
pkgs-lib.nix
222
pkgs-lib.nix
@ -1,97 +1,145 @@
|
|||||||
{
|
{
|
||||||
utils,
|
lib,
|
||||||
pkgs,
|
flake-parts-lib,
|
||||||
|
...
|
||||||
}: let
|
}: let
|
||||||
pkgBin = name: "${pkgs.${name}}/bin/${name}";
|
l = lib // builtins;
|
||||||
|
recursiveAttrPaths = set: let
|
||||||
|
flattenIfHasList = x:
|
||||||
|
if (l.isList x) && (l.any l.isList x)
|
||||||
|
then l.concatMap flattenIfHasList x
|
||||||
|
else [x];
|
||||||
|
|
||||||
mkServePathScript = path:
|
recurse = path: set: let
|
||||||
pkgs.writeScriptBin "serve" ''
|
g = name: value:
|
||||||
${pkgs.nodePackages.http-server}/bin/http-server -c-1 ${path}
|
if l.isAttrs value
|
||||||
'';
|
then recurse (path ++ [name]) value
|
||||||
|
else path ++ [name];
|
||||||
mkSitePath = site: let
|
in
|
||||||
inherit (utils) recursiveAttrPaths concatStringsSep map;
|
l.mapAttrsToList g set;
|
||||||
inherit (pkgs.lib) mapAttrsRecursive init last getAttrFromPath;
|
|
||||||
|
|
||||||
convertToPath = path: value:
|
|
||||||
if builtins.isPath value
|
|
||||||
then value
|
|
||||||
else pkgs.writeText (concatStringsSep "-" path) value;
|
|
||||||
fileAttrPaths = recursiveAttrPaths site;
|
|
||||||
texts = mapAttrsRecursive convertToPath site;
|
|
||||||
mkCreateFileCmd = path: value: let p = concatStringsSep "/" (init path); in "mkdir -p \"$out/${p}\" && ln -s \"${value}\" \"$out/${p}/${last path}\"";
|
|
||||||
createFileCmds = map (path: mkCreateFileCmd path (getAttrFromPath path texts)) fileAttrPaths;
|
|
||||||
in
|
in
|
||||||
pkgs.runCommandLocal "site-path" {} ''
|
flattenIfHasList (recurse [] set);
|
||||||
mkdir -p $out
|
|
||||||
${concatStringsSep "\n" createFileCmds}
|
|
||||||
'';
|
|
||||||
|
|
||||||
parseMarkdown = name: contents:
|
|
||||||
pkgs.runCommandLocal name {} ''
|
|
||||||
printf ${pkgs.lib.escapeShellArg contents} | ${pkgBin "pandoc"} -f gfm > $out
|
|
||||||
'';
|
|
||||||
in {
|
in {
|
||||||
inherit mkServePathScript mkSitePath parseMarkdown;
|
options = {
|
||||||
|
perSystem =
|
||||||
|
flake-parts-lib.mkPerSystemOption
|
||||||
|
({...}: {
|
||||||
|
options = {
|
||||||
|
html-nix.lib = {
|
||||||
|
mkServeFromSite = l.mkOption {
|
||||||
|
type = with l.types; functionTo package;
|
||||||
|
};
|
||||||
|
mkSiteFrom = l.mkOption {
|
||||||
|
type = with l.types; functionTo attrs;
|
||||||
|
};
|
||||||
|
mkSitePathFrom = l.mkOption {
|
||||||
|
type = l.types.raw;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
perSystem = {pkgs, ...}: let
|
||||||
|
pkgBin = name: "${pkgs.${name}}/bin/${name}";
|
||||||
|
|
||||||
mkServeFromSite = site: mkServePathScript (mkSitePath site);
|
mkServePathScript = path:
|
||||||
mkSiteFrom = {
|
pkgs.writeScriptBin "serve" ''
|
||||||
src,
|
${pkgs.nodePackages.http-server}/bin/http-server -c-1 ${path}
|
||||||
templater,
|
|
||||||
local ? false,
|
|
||||||
}: let
|
|
||||||
inherit (utils) readDir readFile fromTOML mapAttrsToList sort elemAt;
|
|
||||||
inherit (pkgs.lib) nameValuePair head splitString pipe removeSuffix mapAttrs';
|
|
||||||
|
|
||||||
postsRendered = let
|
|
||||||
path = src + "/posts";
|
|
||||||
in
|
|
||||||
pipe (readDir path) [
|
|
||||||
(mapAttrsToList (
|
|
||||||
name: _:
|
|
||||||
nameValuePair
|
|
||||||
(head (splitString "." name))
|
|
||||||
(readFile (parseMarkdown name (readFile (path + "/${name}"))))
|
|
||||||
))
|
|
||||||
(sort (
|
|
||||||
p: op: let
|
|
||||||
extractDate = name: splitString "-" (head (splitString "_" name));
|
|
||||||
getPart = name: el: removeSuffix "0" (elemAt (extractDate name) el);
|
|
||||||
d = getPart p.name;
|
|
||||||
od = getPart op.name;
|
|
||||||
in
|
|
||||||
!(((d 0) > (od 0)) && ((d 1) > (od 1)) && ((d 2) > (od 2)))
|
|
||||||
))
|
|
||||||
];
|
|
||||||
pagesRendered = let
|
|
||||||
path = src + "/pages";
|
|
||||||
in
|
|
||||||
mapAttrs'
|
|
||||||
(
|
|
||||||
name: _:
|
|
||||||
nameValuePair
|
|
||||||
(head (splitString "." name))
|
|
||||||
(readFile (parseMarkdown name (readFile (path + "/${name}"))))
|
|
||||||
)
|
|
||||||
(readDir path);
|
|
||||||
siteConfig = fromTOML (readFile (src + "/config.toml"));
|
|
||||||
baseurl =
|
|
||||||
if local
|
|
||||||
then "http://localhost:8080"
|
|
||||||
else siteConfig.baseurl or (throw "Need baseurl");
|
|
||||||
|
|
||||||
context = {
|
|
||||||
inherit utils pkgs baseurl;
|
|
||||||
config = siteConfig;
|
|
||||||
posts = postsRendered;
|
|
||||||
pages = pagesRendered;
|
|
||||||
site = {
|
|
||||||
"robots.txt" = ''
|
|
||||||
User-agent: *
|
|
||||||
Allow: /
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
mkSitePath = site: let
|
||||||
|
convertToPath = path: value:
|
||||||
|
if builtins.isPath value
|
||||||
|
then value
|
||||||
|
else pkgs.writeText (l.concatStringsSep "-" path) value;
|
||||||
|
fileAttrPaths = recursiveAttrPaths site;
|
||||||
|
texts = l.mapAttrsRecursive convertToPath site;
|
||||||
|
mkCreateFileCmd = path: value: let
|
||||||
|
p = l.concatStringsSep "/" (l.init path);
|
||||||
|
in "mkdir -p \"$out/${p}\" && ln -s \"${value}\" \"$out/${p}/${l.last path}\"";
|
||||||
|
createFileCmds =
|
||||||
|
l.map
|
||||||
|
(path: mkCreateFileCmd path (l.getAttrFromPath path texts))
|
||||||
|
fileAttrPaths;
|
||||||
|
in
|
||||||
|
pkgs.runCommandLocal "site-path" {} ''
|
||||||
|
mkdir -p $out
|
||||||
|
${l.concatStringsSep "\n" createFileCmds}
|
||||||
|
'';
|
||||||
|
|
||||||
|
parseMarkdown = name: contents:
|
||||||
|
pkgs.runCommandLocal name {} ''
|
||||||
|
printf ${l.escapeShellArg contents} | ${pkgBin "pandoc"} -f gfm > $out
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
html-nix.lib = {
|
||||||
|
mkSitePathFrom = mkSitePath;
|
||||||
|
mkServeFromSite = site: mkServePathScript (mkSitePath site);
|
||||||
|
mkSiteFrom = {
|
||||||
|
src,
|
||||||
|
templater,
|
||||||
|
local ? false,
|
||||||
|
}: let
|
||||||
|
postsRendered = let
|
||||||
|
path = src + "/posts";
|
||||||
|
in
|
||||||
|
l.pipe (l.readDir path) [
|
||||||
|
(l.mapAttrsToList (
|
||||||
|
name: _: let
|
||||||
|
__displayName = l.head (l.splitString "." name);
|
||||||
|
_displayName = l.splitString "_" __displayName;
|
||||||
|
id = l.replaceStrings [" "] ["_"] __displayName;
|
||||||
|
in {
|
||||||
|
inherit id;
|
||||||
|
displayName = l.last _displayName;
|
||||||
|
date = l.head _displayName;
|
||||||
|
content = l.readFile (parseMarkdown id (l.readFile (path + "/${name}")));
|
||||||
|
}
|
||||||
|
))
|
||||||
|
(l.sort (
|
||||||
|
p: op: let
|
||||||
|
extractDate = date: l.splitString "-" date;
|
||||||
|
getPart = date: el: l.removeSuffix "0" (l.elemAt (extractDate date) el);
|
||||||
|
d = getPart p.date;
|
||||||
|
od = getPart op.date;
|
||||||
|
in
|
||||||
|
!(((d 0) > (od 0)) && ((d 1) > (od 1)) && ((d 2) > (od 2)))
|
||||||
|
))
|
||||||
|
];
|
||||||
|
pagesRendered = let
|
||||||
|
path = src + "/pages";
|
||||||
|
in
|
||||||
|
l.mapAttrsToList
|
||||||
|
(
|
||||||
|
name: _: rec {
|
||||||
|
displayName = l.head (l.splitString "." name);
|
||||||
|
id = l.replaceStrings [" "] ["_"] displayName;
|
||||||
|
content = l.readFile (parseMarkdown id (l.readFile (path + "/${name}")));
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(l.readDir path);
|
||||||
|
siteConfig = l.fromTOML (l.readFile (src + "/config.toml"));
|
||||||
|
baseurl =
|
||||||
|
if local
|
||||||
|
then "http://localhost:8080"
|
||||||
|
else siteConfig.baseurl or (throw "Need baseurl");
|
||||||
|
|
||||||
|
context = {
|
||||||
|
inherit lib baseurl;
|
||||||
|
config = siteConfig;
|
||||||
|
posts = postsRendered;
|
||||||
|
pages = pagesRendered;
|
||||||
|
site = {
|
||||||
|
"robots.txt" = ''
|
||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
(templater context).site;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
};
|
||||||
(templater context).site;
|
|
||||||
}
|
}
|
||||||
|
34
tags.nix
34
tags.nix
@ -1,34 +0,0 @@
|
|||||||
{utils}: let
|
|
||||||
inherit (utils) concatStrings mapAttrsToList genAttrs isAttrs isList range toString;
|
|
||||||
|
|
||||||
evalAttrs = attrs: concatStrings (mapAttrsToList (name: value: " ${name}=\"${value}\"") attrs);
|
|
||||||
evalChildren = children:
|
|
||||||
if isList children
|
|
||||||
then concatStrings children
|
|
||||||
else children;
|
|
||||||
tag = name: maybeAttrs:
|
|
||||||
if isAttrs maybeAttrs
|
|
||||||
then (children: "<${name}${evalAttrs maybeAttrs}>${evalChildren children}</${name}>")
|
|
||||||
else tag name {} maybeAttrs;
|
|
||||||
noChildrenTag = name: attrs: "<${name} ${evalAttrs attrs}>";
|
|
||||||
|
|
||||||
tagsToGen =
|
|
||||||
(map (n: "h${toString n}") (range 1 6))
|
|
||||||
++ ["ul" "li" "html" "head" "body" "div" "p"]
|
|
||||||
++ ["a" "title" "code" "pre" "nav" "article" "script"];
|
|
||||||
tags = genAttrs tag tagsToGen;
|
|
||||||
|
|
||||||
noChildrenTagsToGen = ["link" "meta"];
|
|
||||||
noChildrenTags = genAttrs noChildrenTag noChildrenTagsToGen;
|
|
||||||
in
|
|
||||||
tags
|
|
||||||
// noChildrenTags
|
|
||||||
// {
|
|
||||||
inherit tag;
|
|
||||||
mkLink = url: tags.a {href = url;};
|
|
||||||
mkStylesheet = url:
|
|
||||||
noChildrenTags.link {
|
|
||||||
rel = "stylesheet";
|
|
||||||
href = url;
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,207 +1,222 @@
|
|||||||
{
|
{
|
||||||
utils,
|
|
||||||
posts,
|
|
||||||
pkgs,
|
|
||||||
config,
|
config,
|
||||||
pages,
|
lib,
|
||||||
site,
|
|
||||||
baseurl,
|
|
||||||
...
|
...
|
||||||
} @ context: let
|
}: let
|
||||||
inherit (utils) readFile mapAttrsToList mapAttrs tags fetchGit map elemAt foldl' concatStrings genAttrs toString;
|
l = lib // builtins;
|
||||||
inherit (pkgs.lib) optionalString optionalAttrs optional length splitString nameValuePair toInt range mapAttrs' singleton;
|
t = l.types;
|
||||||
inherit (builtins) listToAttrs;
|
inherit (config.html-nix.lib) html css;
|
||||||
|
|
||||||
stylesheets = map tags.mkStylesheet [
|
func = ctx: let
|
||||||
"https://unpkg.com/purecss@2.0.6/build/pure-min.css"
|
stylesheets = l.map html.mkStylesheet [
|
||||||
"https://unpkg.com/purecss@2.0.6/build/grids-responsive-min.css"
|
"https://unpkg.com/purecss@3.0.0/build/pure-min.css"
|
||||||
"${baseurl}/site.css"
|
"https://unpkg.com/purecss@3.0.0/build/grids-responsive-min.css"
|
||||||
];
|
"${ctx.baseurl}/site.css"
|
||||||
|
];
|
||||||
|
|
||||||
parsePostName = name: let
|
parsePostName = name: let
|
||||||
parts = splitString "_" name;
|
parts = l.splitString "_" name;
|
||||||
id = elemAt parts 1;
|
id = l.elemAt parts 1;
|
||||||
date = elemAt parts 0;
|
date = l.elemAt parts 0;
|
||||||
in {
|
in {
|
||||||
inherit id date;
|
inherit id date;
|
||||||
formatted = "${date} - ${id}";
|
formatted = "${date} - ${id}";
|
||||||
};
|
};
|
||||||
|
|
||||||
renderPost = {
|
renderPost = {
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
}: let
|
}: let
|
||||||
parsed = parsePostName name;
|
parsed = parsePostName name;
|
||||||
inherit (parsed) id date;
|
inherit (parsed) id date;
|
||||||
in
|
in
|
||||||
with tags;
|
with html;
|
||||||
article [
|
article [
|
||||||
(a {
|
(a {
|
||||||
href = "#${id}";
|
href = "#${id}";
|
||||||
class = "postheader";
|
class = "postheader";
|
||||||
} (h2 {inherit id;} id))
|
} (h2 {inherit id;} id))
|
||||||
(h3 ("date: " + date))
|
(h3 ("date: " + date))
|
||||||
value
|
value
|
||||||
|
];
|
||||||
|
|
||||||
|
pagesSection = with html;
|
||||||
|
[
|
||||||
|
(div {class = "pure-u-1";} (a {
|
||||||
|
href = "${ctx.baseurl}/";
|
||||||
|
class = "pagelink";
|
||||||
|
} "home"))
|
||||||
|
]
|
||||||
|
++ (l.map
|
||||||
|
(name:
|
||||||
|
div {class = "pure-u-1";} (a {
|
||||||
|
href = "${ctx.baseurl}/${name}/";
|
||||||
|
class = "pagelink";
|
||||||
|
}
|
||||||
|
name))
|
||||||
|
(l.mapAttrsToList (name: _: name) ctx.pages))
|
||||||
|
++ [
|
||||||
|
(div {class = "pure-u-1";} (a {
|
||||||
|
href = "${ctx.baseurl}/posts/";
|
||||||
|
class = "pagelink";
|
||||||
|
} "posts"))
|
||||||
];
|
];
|
||||||
|
|
||||||
pagesSection =
|
postsLinks = with html;
|
||||||
[
|
l.singleton
|
||||||
(tags.div {class = "pure-u-1";} (tags.a {
|
(ul (
|
||||||
href = "${baseurl}/";
|
l.map
|
||||||
class = "pagelink";
|
(
|
||||||
} "home"))
|
post:
|
||||||
]
|
li (
|
||||||
++ (map
|
a {href = "${ctx.baseurl}/${post.name}";}
|
||||||
(name:
|
(parsePostName post.name).formatted
|
||||||
tags.div {class = "pure-u-1";} (tags.a {
|
)
|
||||||
href = "${baseurl}/${name}/";
|
)
|
||||||
class = "pagelink";
|
ctx.posts
|
||||||
}
|
));
|
||||||
name))
|
|
||||||
(mapAttrsToList (name: _: name) pages))
|
|
||||||
++ [
|
|
||||||
(tags.div {class = "pure-u-1";} (tags.a {
|
|
||||||
href = "${baseurl}/posts/";
|
|
||||||
class = "pagelink";
|
|
||||||
} "posts"))
|
|
||||||
];
|
|
||||||
|
|
||||||
postsRendered = map renderPost posts;
|
postsSectionContent = with html;
|
||||||
|
[
|
||||||
postsLinks = with tags;
|
(a {
|
||||||
singleton
|
href = "#posts";
|
||||||
(ul (
|
class = "postheader";
|
||||||
map
|
} (h1 "posts"))
|
||||||
(
|
|
||||||
post:
|
|
||||||
li (
|
|
||||||
a {href = "${baseurl}/${post.name}";}
|
|
||||||
(parsePostName post.name).formatted
|
|
||||||
)
|
|
||||||
)
|
|
||||||
posts
|
|
||||||
));
|
|
||||||
|
|
||||||
postsSectionContent = with tags;
|
|
||||||
[
|
|
||||||
(a {
|
|
||||||
href = "#posts";
|
|
||||||
class = "postheader";
|
|
||||||
} (h1 "posts"))
|
|
||||||
]
|
|
||||||
++ postsLinks;
|
|
||||||
|
|
||||||
sidebarSection = optionalString ((length pagesSection) > 0) (
|
|
||||||
with tags;
|
|
||||||
nav {class = "sidebar";} [
|
|
||||||
(div {class = "pure-g";} pagesSection)
|
|
||||||
]
|
]
|
||||||
);
|
++ postsLinks;
|
||||||
|
|
||||||
mkPage = content:
|
sidebarSection = l.optionalString ((l.length pagesSection) > 0) (
|
||||||
with tags; ''
|
with html;
|
||||||
<!DOCTYPE html>
|
nav {class = "sidebar";} [
|
||||||
${html [
|
(div {class = "pure-g";} pagesSection)
|
||||||
(head (stylesheets
|
]
|
||||||
++ [
|
|
||||||
(title config.title)
|
|
||||||
(meta {
|
|
||||||
name = "viewport";
|
|
||||||
content = "width=device-width, initial-scale=1";
|
|
||||||
})
|
|
||||||
]))
|
|
||||||
(body ''
|
|
||||||
${script "0"}
|
|
||||||
${sidebarSection}
|
|
||||||
${div {class = "content";} content}
|
|
||||||
'')
|
|
||||||
]}
|
|
||||||
'';
|
|
||||||
|
|
||||||
indexPage = mkPage (context.indexContent or postsSectionContent);
|
|
||||||
|
|
||||||
pagesAndPosts =
|
|
||||||
pages
|
|
||||||
// listToAttrs (
|
|
||||||
map (post: nameValuePair post.name (renderPost post)) posts
|
|
||||||
);
|
);
|
||||||
|
|
||||||
stylesheet = with utils.css; let
|
mkPage = content:
|
||||||
marginMobile = {
|
with html; ''
|
||||||
margin-left = "3%";
|
<!DOCTYPE html>
|
||||||
margin-right = "3%";
|
${html.html [
|
||||||
};
|
(head (stylesheets
|
||||||
in
|
++ [
|
||||||
css [
|
(title ctx.config.title)
|
||||||
(css (
|
(meta {
|
||||||
(
|
name = "viewport";
|
||||||
mapAttrs'
|
content = "width=device-width, initial-scale=1";
|
||||||
(name: value: nameValuePair value {content = "\"${concatStrings (map (_: "#") (range 1 (toInt name)))} \"";})
|
})
|
||||||
(genAttrs (n: "h${toString n}:before") (map toString (range 1 6)))
|
]))
|
||||||
)
|
(body ''
|
||||||
// {
|
${script "0"}
|
||||||
body = {
|
${sidebarSection}
|
||||||
font-family = ["Raleway" "Helvetica" "Arial" "sans-serif"];
|
${div {class = "content";} content}
|
||||||
background = "#111111";
|
'')
|
||||||
color = "#eeeeee";
|
]}
|
||||||
};
|
'';
|
||||||
pre = {
|
|
||||||
font-family = ["Iosevka Term" "Iosevka" "monospace"];
|
|
||||||
background = "#171A21";
|
|
||||||
color = "#eeeeee";
|
|
||||||
};
|
|
||||||
"a,a:hover" = {
|
|
||||||
color = "#ffd814";
|
|
||||||
text-decoration = "none";
|
|
||||||
};
|
|
||||||
"a:hover" = {
|
|
||||||
text-decoration = "underline";
|
|
||||||
};
|
|
||||||
"a.postheader,a.postheader:hover" = {
|
|
||||||
color = "#fc6711";
|
|
||||||
};
|
|
||||||
"a.pagelink,a.pagelink:hover" = {
|
|
||||||
color = "#ffd814";
|
|
||||||
};
|
|
||||||
"div.content" = {
|
|
||||||
margin-top = "5%";
|
|
||||||
margin-bottom = "5%";
|
|
||||||
margin-left = "20%";
|
|
||||||
margin-right = "25%";
|
|
||||||
};
|
|
||||||
"nav.sidebar" = {
|
|
||||||
position = "fixed";
|
|
||||||
margin-left = "3%";
|
|
||||||
padding-top = 0;
|
|
||||||
z-index = 1000;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
))
|
|
||||||
(media "max-width: 48em" {
|
|
||||||
"nav.sidebar" =
|
|
||||||
{
|
|
||||||
position = "relative";
|
|
||||||
margin-top = "5%";
|
|
||||||
}
|
|
||||||
// marginMobile;
|
|
||||||
"div.content" =
|
|
||||||
{
|
|
||||||
margin-top = 0;
|
|
||||||
}
|
|
||||||
// marginMobile;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
in {
|
|
||||||
inherit stylesheets sidebarSection mkPage stylesheet;
|
|
||||||
|
|
||||||
site =
|
indexPage = mkPage (ctx.indexContent or postsSectionContent);
|
||||||
site
|
|
||||||
// {
|
pagesAndPosts =
|
||||||
"index.html" = indexPage;
|
ctx.pages
|
||||||
"posts"."index.html" = mkPage postsSectionContent;
|
// l.listToAttrs (
|
||||||
"404.html" = mkPage (tags.h1 "No such page");
|
map (post: l.nameValuePair post.name (renderPost post)) ctx.posts
|
||||||
"site.css" = stylesheet;
|
);
|
||||||
}
|
|
||||||
// (mapAttrs (name: value: {"index.html" = mkPage value;}) pagesAndPosts)
|
stylesheet = let
|
||||||
// optionalAttrs (context ? resources) {inherit (context) resources;};
|
marginMobile = {
|
||||||
|
margin-left = "3%";
|
||||||
|
margin-right = "3%";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
css [
|
||||||
|
(css (
|
||||||
|
(
|
||||||
|
l.mapAttrs'
|
||||||
|
(
|
||||||
|
name: value:
|
||||||
|
l.nameValuePair
|
||||||
|
value
|
||||||
|
{
|
||||||
|
content = "\"${l.concatStrings (l.map (_: "#") (l.range 1 (l.toInt name)))} \"";
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(
|
||||||
|
l.genAttrs
|
||||||
|
(l.map l.toString (l.range 1 6))
|
||||||
|
(n: "h${l.toString n}:before")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
// {
|
||||||
|
body = {
|
||||||
|
font-family = ["Raleway" "Helvetica" "Arial" "sans-serif"];
|
||||||
|
background = "#111111";
|
||||||
|
color = "#eeeeee";
|
||||||
|
};
|
||||||
|
pre = {
|
||||||
|
font-family = ["Iosevka Term" "Iosevka" "monospace"];
|
||||||
|
background = "#171A21";
|
||||||
|
color = "#eeeeee";
|
||||||
|
};
|
||||||
|
"a,a:hover" = {
|
||||||
|
color = "#ffd814";
|
||||||
|
text-decoration = "none";
|
||||||
|
};
|
||||||
|
"a:hover" = {
|
||||||
|
text-decoration = "underline";
|
||||||
|
};
|
||||||
|
"a.postheader,a.postheader:hover" = {
|
||||||
|
color = "#fc6711";
|
||||||
|
};
|
||||||
|
"a.pagelink,a.pagelink:hover" = {
|
||||||
|
color = "#ffd814";
|
||||||
|
};
|
||||||
|
"div.content" = {
|
||||||
|
margin-top = "5%";
|
||||||
|
margin-bottom = "5%";
|
||||||
|
margin-left = "20%";
|
||||||
|
margin-right = "25%";
|
||||||
|
};
|
||||||
|
"nav.sidebar" = {
|
||||||
|
position = "fixed";
|
||||||
|
margin-left = "3%";
|
||||||
|
padding-top = 0;
|
||||||
|
z-index = 1000;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
))
|
||||||
|
(css.media "max-width: 48em" {
|
||||||
|
"nav.sidebar" =
|
||||||
|
{
|
||||||
|
position = "relative";
|
||||||
|
margin-top = "5%";
|
||||||
|
}
|
||||||
|
// marginMobile;
|
||||||
|
"div.content" =
|
||||||
|
{
|
||||||
|
margin-top = 0;
|
||||||
|
}
|
||||||
|
// marginMobile;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
in {
|
||||||
|
inherit stylesheets sidebarSection mkPage stylesheet;
|
||||||
|
|
||||||
|
site =
|
||||||
|
ctx.site
|
||||||
|
// {
|
||||||
|
"index.html" = indexPage;
|
||||||
|
"posts"."index.html" = mkPage postsSectionContent;
|
||||||
|
"404.html" = mkPage (html.h1 "No such page");
|
||||||
|
"site.css" = stylesheet;
|
||||||
|
}
|
||||||
|
// (l.mapAttrs (name: value: {"index.html" = mkPage value;}) pagesAndPosts)
|
||||||
|
// l.optionalAttrs (ctx ? resources) {inherit (ctx) resources;};
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
html-nix.lib.templaters.basic = l.mkOption {
|
||||||
|
type = t.functionTo t.attrs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
html-nix.lib.templaters.basic = func;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
6
templaters/default.nix
Normal file
6
templaters/default.nix
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./basic.nix
|
||||||
|
./simple
|
||||||
|
];
|
||||||
|
}
|
151
templaters/simple/default.nix
Normal file
151
templaters/simple/default.nix
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
l = lib // builtins;
|
||||||
|
t = l.types;
|
||||||
|
inherit (config.html-nix.lib) html css;
|
||||||
|
|
||||||
|
func = ctx: let
|
||||||
|
stylesheets = l.map html.mkStylesheet ["${ctx.baseurl}/site.css"];
|
||||||
|
stylesheet = import ./stylesheet.nix {inherit css l;};
|
||||||
|
|
||||||
|
renderPost = post:
|
||||||
|
with html;
|
||||||
|
article [
|
||||||
|
(h1 {inherit (post) id;} post.displayName)
|
||||||
|
(h4 {class = "nohashtag";} ("date: " + post.date))
|
||||||
|
post.content
|
||||||
|
];
|
||||||
|
|
||||||
|
mkPage = {
|
||||||
|
content,
|
||||||
|
titleStr ? ctx.config.title,
|
||||||
|
}:
|
||||||
|
with html; ''
|
||||||
|
<!DOCTYPE html>
|
||||||
|
${html.html [
|
||||||
|
(head (stylesheets
|
||||||
|
++ [
|
||||||
|
(title titleStr)
|
||||||
|
(meta {
|
||||||
|
name = "viewport";
|
||||||
|
content = "width=device-width, initial-scale=1";
|
||||||
|
})
|
||||||
|
]))
|
||||||
|
(body ''
|
||||||
|
${script "0"}
|
||||||
|
${div (l.flatten [
|
||||||
|
navBar
|
||||||
|
(hr {})
|
||||||
|
content
|
||||||
|
])}
|
||||||
|
'')
|
||||||
|
]}
|
||||||
|
'';
|
||||||
|
|
||||||
|
navBar = with html;
|
||||||
|
nav (
|
||||||
|
[
|
||||||
|
(a {
|
||||||
|
href = "${ctx.baseurl}/";
|
||||||
|
class = "novisited";
|
||||||
|
} "home")
|
||||||
|
]
|
||||||
|
++ (
|
||||||
|
l.map
|
||||||
|
(
|
||||||
|
page:
|
||||||
|
" "
|
||||||
|
+ (
|
||||||
|
a {
|
||||||
|
href = "${ctx.baseurl}/${page.id}/";
|
||||||
|
class = "novisited";
|
||||||
|
}
|
||||||
|
page.displayName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ctx.pages
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
postsLinks = with html;
|
||||||
|
l.singleton
|
||||||
|
(ul (
|
||||||
|
l.map
|
||||||
|
(
|
||||||
|
post:
|
||||||
|
li (
|
||||||
|
a {href = "${ctx.baseurl}/${post.id}";}
|
||||||
|
"${post.date} - ${post.displayName}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ctx.posts
|
||||||
|
));
|
||||||
|
|
||||||
|
postsSectionContent = [(html.h1 "posts")] ++ postsLinks;
|
||||||
|
|
||||||
|
postsRendered = l.listToAttrs (
|
||||||
|
l.map
|
||||||
|
(post:
|
||||||
|
l.nameValuePair post.id {
|
||||||
|
content = renderPost post;
|
||||||
|
name = post.displayName;
|
||||||
|
})
|
||||||
|
ctx.posts
|
||||||
|
);
|
||||||
|
pagesRendered = l.listToAttrs (
|
||||||
|
l.map
|
||||||
|
(page:
|
||||||
|
l.nameValuePair page.id {
|
||||||
|
content = page.content;
|
||||||
|
name = page.displayName;
|
||||||
|
})
|
||||||
|
ctx.pages
|
||||||
|
);
|
||||||
|
|
||||||
|
indexPage = mkPage {
|
||||||
|
content = ctx.indexContent or postsSectionContent;
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
inherit stylesheets mkPage stylesheet;
|
||||||
|
|
||||||
|
site =
|
||||||
|
ctx.site
|
||||||
|
// {
|
||||||
|
"index.html" = indexPage;
|
||||||
|
"posts"."index.html" = mkPage {
|
||||||
|
content = postsSectionContent;
|
||||||
|
titleStr = "posts - ${ctx.config.title}";
|
||||||
|
};
|
||||||
|
"404.html" = mkPage {
|
||||||
|
content = html.h1 {class = "nohashtag";} "page not found";
|
||||||
|
titleStr = "page not found - ${ctx.config.title}";
|
||||||
|
};
|
||||||
|
"site.css" = stylesheet;
|
||||||
|
}
|
||||||
|
// (
|
||||||
|
l.mapAttrs
|
||||||
|
(
|
||||||
|
name: value: {
|
||||||
|
"index.html" = mkPage {
|
||||||
|
content = value.content;
|
||||||
|
titleStr = "${value.name} - ${ctx.config.title}";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(pagesRendered // postsRendered)
|
||||||
|
)
|
||||||
|
// l.optionalAttrs (ctx ? resources) {inherit (ctx) resources;};
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
html-nix.lib.templaters.simple = l.mkOption {
|
||||||
|
type = t.uniq (t.functionTo t.attrs);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
html-nix.lib.templaters.simple = func;
|
||||||
|
};
|
||||||
|
}
|
88
templaters/simple/stylesheet.nix
Normal file
88
templaters/simple/stylesheet.nix
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
css,
|
||||||
|
l,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
colors = {
|
||||||
|
light = rec {
|
||||||
|
fg = "#000";
|
||||||
|
bg = "#faf9f6";
|
||||||
|
code-bg = fg;
|
||||||
|
code-fg = bg;
|
||||||
|
link = "#1f51ff";
|
||||||
|
link-visited = "#9d00ff";
|
||||||
|
};
|
||||||
|
dark = rec {
|
||||||
|
fg = "#eee";
|
||||||
|
bg = "#111";
|
||||||
|
code-bg = "#333";
|
||||||
|
code-fg = fg;
|
||||||
|
link = "#007fff";
|
||||||
|
link-visited = "#bf40bf";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
headers = extra:
|
||||||
|
l.genAttrs
|
||||||
|
(l.map l.toString (l.range 1 6))
|
||||||
|
(n: "h${l.toString n}${extra}");
|
||||||
|
in
|
||||||
|
css [
|
||||||
|
(css (
|
||||||
|
l.mapAttrs'
|
||||||
|
(
|
||||||
|
name: value:
|
||||||
|
l.nameValuePair
|
||||||
|
value
|
||||||
|
{
|
||||||
|
content = ''"${l.concatStrings (l.map (_: "#") (l.range 1 (l.toInt name)))} "'';
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(headers ":before")
|
||||||
|
))
|
||||||
|
(css (
|
||||||
|
l.mapAttrs'
|
||||||
|
(_: value: l.nameValuePair value {content = ''""'';})
|
||||||
|
(headers ".nohashtag:before")
|
||||||
|
))
|
||||||
|
(css {
|
||||||
|
body = {
|
||||||
|
font-family = ["sans-serif"];
|
||||||
|
color = colors.light.fg;
|
||||||
|
background = colors.light.bg;
|
||||||
|
max-width = "650px";
|
||||||
|
margin = "40px auto";
|
||||||
|
};
|
||||||
|
"pre,code" = {
|
||||||
|
font-family = ["monospace"];
|
||||||
|
background = colors.light.code-bg;
|
||||||
|
color = colors.light.code-fg;
|
||||||
|
padding = "4px";
|
||||||
|
border-radius = "4px";
|
||||||
|
};
|
||||||
|
"pre code" = {
|
||||||
|
padding = 0;
|
||||||
|
border-radius = 0;
|
||||||
|
};
|
||||||
|
a = {
|
||||||
|
color = colors.light.link;
|
||||||
|
text-decoration = "none";
|
||||||
|
};
|
||||||
|
"a:hover".text-decoration = "underline";
|
||||||
|
"a:visited".color = colors.light.link-visited;
|
||||||
|
"a.novisited:visited".color = colors.light.link;
|
||||||
|
"h1,h2,h3".line-height = "1.2";
|
||||||
|
})
|
||||||
|
(css.media "prefers-color-scheme: dark" {
|
||||||
|
body = {
|
||||||
|
color = colors.dark.fg;
|
||||||
|
background = colors.dark.bg;
|
||||||
|
};
|
||||||
|
"pre,code" = {
|
||||||
|
color = colors.dark.code-fg;
|
||||||
|
background = colors.dark.code-bg;
|
||||||
|
};
|
||||||
|
a.color = colors.dark.link;
|
||||||
|
"a:visited".color = colors.dark.link-visited;
|
||||||
|
"a.novisited:visited".color = colors.dark.link;
|
||||||
|
})
|
||||||
|
]
|
38
utils.nix
38
utils.nix
@ -1,38 +0,0 @@
|
|||||||
let
|
|
||||||
inherit (builtins) isAttrs isList map any concatMap concatStringsSep listToAttrs genList;
|
|
||||||
|
|
||||||
mapAttrsToList = f: attrs: map (name: f name attrs.${name}) (builtins.attrNames attrs);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
inherit mapAttrsToList;
|
|
||||||
|
|
||||||
recursiveAttrPaths = set: let
|
|
||||||
flattenIfHasList = x:
|
|
||||||
if (isList x) && (any isList x)
|
|
||||||
then concatMap flattenIfHasList x
|
|
||||||
else [x];
|
|
||||||
|
|
||||||
recurse = path: set: let
|
|
||||||
g = name: value:
|
|
||||||
if isAttrs value
|
|
||||||
then recurse (path ++ [name]) value
|
|
||||||
else path ++ [name];
|
|
||||||
in
|
|
||||||
mapAttrsToList g set;
|
|
||||||
in
|
|
||||||
flattenIfHasList (recurse [] set);
|
|
||||||
|
|
||||||
concatStrings = concatStringsSep "";
|
|
||||||
genAttrs = f: names:
|
|
||||||
listToAttrs (map (n: {
|
|
||||||
name = n;
|
|
||||||
value = f n;
|
|
||||||
})
|
|
||||||
names);
|
|
||||||
|
|
||||||
range = first: last:
|
|
||||||
if first > last
|
|
||||||
then []
|
|
||||||
else genList (n: first + n) (last - first + 1);
|
|
||||||
}
|
|
||||||
// builtins
|
|
Loading…
Reference in New Issue
Block a user