improvements
This commit is contained in:
parent
5bca7064e4
commit
8c562cd257
11
css.nix
11
css.nix
@ -1,15 +1,16 @@
|
||||
{ utils }:
|
||||
let
|
||||
{utils}: let
|
||||
inherit (utils) mapAttrsToList concatStringsSep isList toString map;
|
||||
|
||||
evalCssValue = value: if isList value then concatStringsSep ", " (map toString value) else toString value;
|
||||
evalCssValue = value:
|
||||
if isList value
|
||||
then concatStringsSep ", " (map toString value)
|
||||
else toString value;
|
||||
evalInner = inner: concatStringsSep " " (mapAttrsToList (name: value: "${name}: ${evalCssValue value};") inner);
|
||||
css = maybeAttrs:
|
||||
if isList maybeAttrs
|
||||
then concatStringsSep " " maybeAttrs
|
||||
else concatStringsSep " " (mapAttrsToList (name: inner: "${name} { ${evalInner inner} }") maybeAttrs);
|
||||
in
|
||||
{
|
||||
in {
|
||||
inherit css;
|
||||
|
||||
media = rule: inner: ''
|
||||
|
@ -1,6 +1,8 @@
|
||||
{ tags, pkgs }:
|
||||
with pkgs.htmlNix;
|
||||
let
|
||||
{
|
||||
tags,
|
||||
pkgs,
|
||||
}:
|
||||
with pkgs.htmlNix; let
|
||||
index = with tags;
|
||||
html [
|
||||
(body [
|
||||
@ -17,6 +19,9 @@ let
|
||||
])
|
||||
];
|
||||
|
||||
site = { "index.html" = index; "ex.html" = ex; };
|
||||
site = {
|
||||
"index.html" = index;
|
||||
"ex.html" = ex;
|
||||
};
|
||||
in
|
||||
mkServeFromSite site
|
||||
mkServeFromSite site
|
||||
|
@ -1,10 +1,12 @@
|
||||
{ pkgs, lib }:
|
||||
let
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
}: let
|
||||
inherit (pkgs) htmlNix;
|
||||
src = ./site;
|
||||
in
|
||||
htmlNix.mkServeFromSite (htmlNix.mkSiteFrom {
|
||||
htmlNix.mkServeFromSite (htmlNix.mkSiteFrom {
|
||||
inherit src;
|
||||
templater = lib.templaters.basic;
|
||||
local = true;
|
||||
})
|
||||
})
|
||||
|
@ -1,7 +1,8 @@
|
||||
tags: with tags;
|
||||
html [
|
||||
tags:
|
||||
with tags;
|
||||
html [
|
||||
(body [
|
||||
(p "Hello,")
|
||||
(p "world!")
|
||||
])
|
||||
]
|
||||
]
|
||||
|
40
flake.nix
40
flake.nix
@ -4,15 +4,18 @@
|
||||
flakeUtils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, flakeUtils, nixpkgs }:
|
||||
let
|
||||
outputs = {
|
||||
self,
|
||||
flakeUtils,
|
||||
nixpkgs,
|
||||
}: let
|
||||
utils = import ./utils.nix;
|
||||
|
||||
lib = {
|
||||
# Convert Nix expressions to HTML
|
||||
tags = import ./tags.nix { inherit utils; };
|
||||
tags = import ./tags.nix {inherit utils;};
|
||||
# Convert Nix expressions to CSS
|
||||
css = import ./css.nix { inherit utils; };
|
||||
css = import ./css.nix {inherit utils;};
|
||||
|
||||
# Various site templaters
|
||||
templaters = {
|
||||
@ -21,27 +24,26 @@
|
||||
};
|
||||
};
|
||||
|
||||
overlay = final: prev: {
|
||||
htmlNix = (import ./pkgs-lib.nix { pkgs = prev; utils = utils // { inherit (lib) tags css; }; }) // lib;
|
||||
outputs = flakeUtils.lib.eachDefaultSystem (system: let
|
||||
pkgs = nixpkgs.legacyPackagse.${system};
|
||||
in {
|
||||
lib = {
|
||||
pkgsLib = import ./pkgs-lib.nix {
|
||||
inherit pkgs;
|
||||
utils = utils // {inherit (lib) tags css;};
|
||||
};
|
||||
in
|
||||
{ inherit overlay; } //
|
||||
(flakeUtils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; overlays = [ overlay ]; };
|
||||
in
|
||||
{
|
||||
lib = 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; };
|
||||
drv = import ./examples/site.nix {inherit lib pkgs;};
|
||||
name = "serve";
|
||||
};
|
||||
basicServe = mkApp {
|
||||
drv = import ./examples/serve.nix { inherit (lib) tags; inherit pkgs; };
|
||||
drv = import ./examples/serve.nix {
|
||||
inherit (lib) tags;
|
||||
inherit pkgs;
|
||||
};
|
||||
name = "serve";
|
||||
};
|
||||
};
|
||||
@ -49,5 +51,7 @@
|
||||
examples = {
|
||||
tags = import ./examples/tags.nix lib.tags;
|
||||
};
|
||||
}));
|
||||
});
|
||||
in
|
||||
outputs // {lib = outputs.lib // lib;};
|
||||
}
|
||||
|
51
pkgs-lib.nix
51
pkgs-lib.nix
@ -1,15 +1,17 @@
|
||||
{ utils, pkgs }:
|
||||
let
|
||||
{
|
||||
utils,
|
||||
pkgs,
|
||||
}: let
|
||||
pkgBin = name: "${pkgs.${name}}/bin/${name}";
|
||||
|
||||
mkServePathScript = path: pkgs.writeScriptBin "serve" ''
|
||||
mkServePathScript = path:
|
||||
pkgs.writeScriptBin "serve" ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
cd ${path}
|
||||
${pkgBin "caddy"} run --config Caddyfile
|
||||
'';
|
||||
|
||||
mkSitePath = site:
|
||||
let
|
||||
mkSitePath = site: let
|
||||
inherit (utils) recursiveAttrPaths concatStringsSep map;
|
||||
inherit (pkgs.lib) mapAttrsRecursive init last getAttrFromPath;
|
||||
|
||||
@ -18,35 +20,39 @@ let
|
||||
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
|
||||
pkgs.runCommandLocal "site-path" { } ''
|
||||
pkgs.runCommandLocal "site-path" {} ''
|
||||
mkdir -p $out
|
||||
${concatStringsSep "\n" createFileCmds}
|
||||
'';
|
||||
|
||||
parseMarkdown = name: contents:
|
||||
pkgs.runCommandLocal name { } ''
|
||||
pkgs.runCommandLocal name {} ''
|
||||
printf ${pkgs.lib.escapeShellArg contents} | ${pkgBin "pandoc"} -f gfm > $out
|
||||
'';
|
||||
in
|
||||
{
|
||||
in {
|
||||
inherit mkServePathScript mkSitePath parseMarkdown;
|
||||
|
||||
mkServeFromSite = site: mkServePathScript (mkSitePath site);
|
||||
mkSiteFrom = { src, templater, local ? false }:
|
||||
let
|
||||
mkSiteFrom = {
|
||||
src,
|
||||
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
|
||||
postsRendered = let
|
||||
path = src + "/posts";
|
||||
in
|
||||
pipe (readDir path) [
|
||||
(mapAttrsToList (name: _:
|
||||
(mapAttrsToList (
|
||||
name: _:
|
||||
nameValuePair
|
||||
(head (splitString "." name))
|
||||
(readFile (parseMarkdown name (readFile (path + "/${name}"))))
|
||||
))
|
||||
(sort (p: op:
|
||||
let
|
||||
(sort (
|
||||
p: op: let
|
||||
extractDate = name: splitString "-" (head (splitString "_" name));
|
||||
getPart = name: el: removeSuffix "0" (elemAt (extractDate name) el);
|
||||
d = getPart p.name;
|
||||
@ -55,17 +61,22 @@ in
|
||||
!(((d 0) > (od 0)) && ((d 1) > (od 1)) && ((d 2) > (od 2)))
|
||||
))
|
||||
];
|
||||
pagesRendered =
|
||||
let path = src + "/pages"; in
|
||||
pagesRendered = let
|
||||
path = src + "/pages";
|
||||
in
|
||||
mapAttrs'
|
||||
(name: _:
|
||||
(
|
||||
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");
|
||||
baseurl =
|
||||
if local
|
||||
then "http://localhost:8080"
|
||||
else siteConfig.baseurl or (throw "Need baseurl");
|
||||
|
||||
context = {
|
||||
inherit utils pkgs baseurl;
|
||||
|
28
tags.nix
28
tags.nix
@ -1,23 +1,31 @@
|
||||
{ utils }:
|
||||
let
|
||||
{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;
|
||||
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;
|
||||
else tag name {} maybeAttrs;
|
||||
noChildrenTag = name: attrs: "<${name} ${evalAttrs attrs}>";
|
||||
|
||||
tagsToGen = [ "html" "head" "body" "div" "p" "a" "title" "code" "pre" "nav" "article" ] ++ (map (n: "h${toString n}") (range 1 6));
|
||||
tagsToGen = ["html" "head" "body" "div" "p" "a" "title" "code" "pre" "nav" "article"] ++ (map (n: "h${toString n}") (range 1 6));
|
||||
tags = genAttrs tag tagsToGen;
|
||||
|
||||
noChildrenTagsToGen = [ "link" "meta" ];
|
||||
noChildrenTagsToGen = ["link" "meta"];
|
||||
noChildrenTags = genAttrs noChildrenTag noChildrenTagsToGen;
|
||||
in
|
||||
tags // noChildrenTags // {
|
||||
tags
|
||||
// noChildrenTags
|
||||
// {
|
||||
inherit tag;
|
||||
mkLink = url: tags.a { href = url; };
|
||||
mkStylesheet = url: noChildrenTags.link { rel = "stylesheet"; href = url; };
|
||||
}
|
||||
mkLink = url: tags.a {href = url;};
|
||||
mkStylesheet = url:
|
||||
noChildrenTags.link {
|
||||
rel = "stylesheet";
|
||||
href = url;
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,13 @@
|
||||
{ utils, posts, pkgs, config, pages, site, baseurl, ... }@context:
|
||||
let
|
||||
{
|
||||
utils,
|
||||
posts,
|
||||
pkgs,
|
||||
config,
|
||||
pages,
|
||||
site,
|
||||
baseurl,
|
||||
...
|
||||
} @ context: let
|
||||
inherit (utils) readFile mapAttrsToList mapAttrs tags fetchGit map elemAt foldl' concatStrings genAttrs toString;
|
||||
inherit (pkgs.lib) optional length splitString nameValuePair toInt range mapAttrs';
|
||||
|
||||
@ -9,48 +17,76 @@ let
|
||||
"${baseurl}/site.css"
|
||||
];
|
||||
|
||||
renderPost = { name, value }:
|
||||
let
|
||||
renderPost = {
|
||||
name,
|
||||
value,
|
||||
}: let
|
||||
parts = splitString "_" name;
|
||||
id = elemAt parts 1;
|
||||
in
|
||||
with tags; article [
|
||||
(a { href = "#${id}"; class = "postheader"; } (h2 { inherit id; } id))
|
||||
with tags;
|
||||
article [
|
||||
(a {
|
||||
href = "#${id}";
|
||||
class = "postheader";
|
||||
} (h2 {inherit id;} id))
|
||||
(h3 ("date: " + (elemAt parts 0)))
|
||||
value
|
||||
];
|
||||
|
||||
pagesSection =
|
||||
(map
|
||||
(name: tags.div { class = "pure-u-1"; } (tags.a { href = "${baseurl}/${name}/"; class = "pagelink"; } name))
|
||||
(mapAttrsToList (name: _: name) pages)) ++ [ (tags.div { class = "pure-u-1"; } (tags.a { href = "${baseurl}/"; class = "pagelink"; } "posts")) ];
|
||||
(name:
|
||||
tags.div {class = "pure-u-1";} (tags.a {
|
||||
href = "${baseurl}/${name}/";
|
||||
class = "pagelink";
|
||||
}
|
||||
name))
|
||||
(mapAttrsToList (name: _: name) pages))
|
||||
++ [
|
||||
(tags.div {class = "pure-u-1";} (tags.a {
|
||||
href = "${baseurl}/";
|
||||
class = "pagelink";
|
||||
} "posts"))
|
||||
];
|
||||
|
||||
postsSectionContent = with tags; [
|
||||
(a { href = "#posts"; class = "postheader"; } (h1 "posts"))
|
||||
] ++ (map renderPost posts);
|
||||
postsSectionContent = with tags;
|
||||
[
|
||||
(a {
|
||||
href = "#posts";
|
||||
class = "postheader";
|
||||
} (h1 "posts"))
|
||||
]
|
||||
++ (map renderPost posts);
|
||||
|
||||
sidebarSection = optional ((length pagesSection) > 0) (
|
||||
with tags; nav { class = "sidebar"; } ([
|
||||
(a { href = "#pages"; class = "postheader"; } (h1 "pages"))
|
||||
(div { class = "pure-g"; } pagesSection)
|
||||
])
|
||||
with tags;
|
||||
nav {class = "sidebar";} [
|
||||
(a {
|
||||
href = "#pages";
|
||||
class = "postheader";
|
||||
} (h1 "pages"))
|
||||
(div {class = "pure-g";} pagesSection)
|
||||
]
|
||||
);
|
||||
|
||||
mkPage = content: with tags;
|
||||
''
|
||||
mkPage = content:
|
||||
with tags; ''
|
||||
<!DOCTYPE html>
|
||||
${html [
|
||||
(head (stylesheets ++ [
|
||||
(head (stylesheets
|
||||
++ [
|
||||
(title config.title)
|
||||
(meta { name = "viewport"; content = "width=device-width, initial-scale=1"; })
|
||||
(meta {
|
||||
name = "viewport";
|
||||
content = "width=device-width, initial-scale=1";
|
||||
})
|
||||
]))
|
||||
(body (sidebarSection ++ [ (div { class = "content"; } content) ]))
|
||||
(body (sidebarSection ++ [(div {class = "content";} content)]))
|
||||
]}
|
||||
'';
|
||||
|
||||
stylesheet =
|
||||
with utils.css;
|
||||
let
|
||||
stylesheet = with utils.css; let
|
||||
marginMobile = {
|
||||
margin-left = "3%";
|
||||
margin-right = "3%";
|
||||
@ -60,16 +96,17 @@ let
|
||||
(css (
|
||||
(
|
||||
mapAttrs'
|
||||
(name: value: nameValuePair value { content = "\"${concatStrings (map (_: "#") (range 1 (toInt name)))} \""; })
|
||||
(name: value: nameValuePair value {content = "\"${concatStrings (map (_: "#") (range 1 (toInt name)))} \"";})
|
||||
(genAttrs (n: "h${toString n}:before") (map toString (range 1 6)))
|
||||
) // {
|
||||
)
|
||||
// {
|
||||
body = {
|
||||
font-family = [ "Raleway" "Helvetica" "Arial" "sans-serif" ];
|
||||
font-family = ["Raleway" "Helvetica" "Arial" "sans-serif"];
|
||||
background = "#111111";
|
||||
color = "#eeeeee";
|
||||
};
|
||||
pre = {
|
||||
font-family = [ "Iosevka Term" "Iosevka" "monospace" ];
|
||||
font-family = ["Iosevka Term" "Iosevka" "monospace"];
|
||||
background = "#171A21";
|
||||
color = "#eeeeee";
|
||||
};
|
||||
@ -101,22 +138,28 @@ let
|
||||
}
|
||||
))
|
||||
(media "max-width: 48em" {
|
||||
"nav.sidebar" = {
|
||||
"nav.sidebar" =
|
||||
{
|
||||
position = "relative";
|
||||
margin-top = "5%";
|
||||
} // marginMobile;
|
||||
"div.content" = {
|
||||
}
|
||||
// marginMobile;
|
||||
"div.content" =
|
||||
{
|
||||
margin-top = 0;
|
||||
} // marginMobile;
|
||||
}
|
||||
// marginMobile;
|
||||
})
|
||||
];
|
||||
in
|
||||
{
|
||||
in {
|
||||
inherit stylesheets sidebarSection mkPage stylesheet;
|
||||
|
||||
site = site // {
|
||||
site =
|
||||
site
|
||||
// {
|
||||
"index.html" = mkPage postsSectionContent;
|
||||
"404.html" = mkPage (tags.h1 "No such page");
|
||||
"site.css" = stylesheet;
|
||||
} // (mapAttrs (name: value: { "index.html" = mkPage value; }) pages);
|
||||
}
|
||||
// (mapAttrs (name: value: {"index.html" = mkPage value;}) pages);
|
||||
}
|
||||
|
36
utils.nix
36
utils.nix
@ -3,34 +3,36 @@ let
|
||||
|
||||
mapAttrsToList = f: attrs: map (name: f name attrs.${name}) (builtins.attrNames attrs);
|
||||
in
|
||||
{
|
||||
{
|
||||
inherit mapAttrsToList;
|
||||
|
||||
recursiveAttrPaths = set:
|
||||
let
|
||||
recursiveAttrPaths = set: let
|
||||
flattenIfHasList = x:
|
||||
if (isList x) && (any isList x)
|
||||
then concatMap flattenIfHasList x
|
||||
else [ x ];
|
||||
else [x];
|
||||
|
||||
recurse = path: set:
|
||||
let
|
||||
g =
|
||||
name: value:
|
||||
recurse = path: set: let
|
||||
g = name: value:
|
||||
if isAttrs value
|
||||
then recurse (path ++ [ name ]) value
|
||||
else path ++ [ name ];
|
||||
then recurse (path ++ [name]) value
|
||||
else path ++ [name];
|
||||
in
|
||||
mapAttrsToList g set;
|
||||
in
|
||||
flattenIfHasList (recurse [ ] set);
|
||||
flattenIfHasList (recurse [] set);
|
||||
|
||||
concatStrings = concatStringsSep "";
|
||||
genAttrs = f: names: listToAttrs (map (n: { name = n; value = (f n); }) names);
|
||||
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
|
||||
if first > last
|
||||
then []
|
||||
else genList (n: first + n) (last - first + 1);
|
||||
}
|
||||
// builtins
|
||||
|
Loading…
Reference in New Issue
Block a user