improvements

This commit is contained in:
dusk 2022-07-30 12:42:09 +03:00
parent 5bca7064e4
commit 8c562cd257
Signed by: dusk
GPG Key ID: 1D8F8FAF2294D6EA
9 changed files with 303 additions and 226 deletions

11
css.nix
View File

@ -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: ''

View File

@ -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

View File

@ -1,10 +1,12 @@
{ pkgs, lib }:
let
{
pkgs,
lib,
}: let
inherit (pkgs) htmlNix;
src = ./site;
in
htmlNix.mkServeFromSite (htmlNix.mkSiteFrom {
inherit src;
templater = lib.templaters.basic;
local = true;
})
htmlNix.mkServeFromSite (htmlNix.mkSiteFrom {
inherit src;
templater = lib.templaters.basic;
local = true;
})

View File

@ -1,7 +1,8 @@
tags: with tags;
html [
(body [
(p "Hello,")
(p "world!")
])
]
tags:
with tags;
html [
(body [
(p "Hello,")
(p "world!")
])
]

View File

@ -4,50 +4,54 @@
flakeUtils.url = "github:numtide/flake-utils";
};
outputs = { self, flakeUtils, nixpkgs }:
let
utils = import ./utils.nix;
outputs = {
self,
flakeUtils,
nixpkgs,
}: let
utils = import ./utils.nix;
lib = {
# Convert Nix expressions to HTML
tags = import ./tags.nix {inherit utils;};
# 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.legacyPackagse.${system};
in {
lib = {
# Convert Nix expressions to HTML
tags = import ./tags.nix { inherit utils; };
# 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;
pkgsLib = import ./pkgs-lib.nix {
inherit pkgs;
utils = utils // {inherit (lib) tags css;};
};
};
overlay = final: prev: {
htmlNix = (import ./pkgs-lib.nix { pkgs = prev; utils = utils // { inherit (lib) tags css; }; }) // lib;
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";
};
};
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; };
name = "serve";
};
basicServe = mkApp {
drv = import ./examples/serve.nix { inherit (lib) tags; inherit pkgs; };
name = "serve";
};
};
examples = {
tags = import ./examples/tags.nix lib.tags;
};
}));
examples = {
tags = import ./examples/tags.nix lib.tags;
};
});
in
outputs // {lib = outputs.lib // lib;};
}

View File

@ -1,93 +1,104 @@
{ utils, pkgs }:
let
{
utils,
pkgs,
}: let
pkgBin = name: "${pkgs.${name}}/bin/${name}";
mkServePathScript = path: pkgs.writeScriptBin "serve" ''
#!${pkgs.stdenv.shell}
cd ${path}
${pkgBin "caddy"} run --config Caddyfile
'';
mkServePathScript = path:
pkgs.writeScriptBin "serve" ''
#!${pkgs.stdenv.shell}
cd ${path}
${pkgBin "caddy"} run --config Caddyfile
'';
mkSitePath = site:
let
inherit (utils) recursiveAttrPaths concatStringsSep map;
inherit (pkgs.lib) mapAttrsRecursive init last getAttrFromPath;
mkSitePath = site: let
inherit (utils) recursiveAttrPaths concatStringsSep map;
inherit (pkgs.lib) mapAttrsRecursive init last getAttrFromPath;
fileAttrPaths = recursiveAttrPaths site;
texts = mapAttrsRecursive (path: value: pkgs.writeText (concatStringsSep "-" path) value) 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
pkgs.runCommandLocal "site-path" { } ''
fileAttrPaths = recursiveAttrPaths site;
texts = mapAttrsRecursive (path: value: pkgs.writeText (concatStringsSep "-" path) value) 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
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
inherit (utils) readDir readFile fromTOML mapAttrsToList sort elemAt;
inherit (pkgs.lib) nameValuePair head splitString pipe removeSuffix mapAttrs';
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
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: /
'';
"Caddyfile" = ''
${baseurl}
handle_errors {
rewrite * /{http.error.status_code}.html
file_server
}
file_server
'';
};
};
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: /
'';
"Caddyfile" = ''
${baseurl}
handle_errors {
rewrite * /{http.error.status_code}.html
file_server
}
file_server
'';
};
};
in
(templater context).site;
}

View File

@ -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 // {
inherit tag;
mkLink = url: tags.a { href = url; };
mkStylesheet = url: noChildrenTags.link { rel = "stylesheet"; href = url; };
}
tags
// noChildrenTags
// {
inherit tag;
mkLink = url: tags.a {href = url;};
mkStylesheet = url:
noChildrenTags.link {
rel = "stylesheet";
href = url;
};
}

View File

@ -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,67 +17,96 @@ let
"${baseurl}/site.css"
];
renderPost = { name, value }:
let
parts = splitString "_" name;
id = elemAt parts 1;
in
with tags; article [
(a { href = "#${id}"; class = "postheader"; } (h2 { inherit id; } id))
(h3 ("date: " + (elemAt parts 0)))
value
];
renderPost = {
name,
value,
}: let
parts = splitString "_" name;
id = elemAt parts 1;
in
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 ++ [
(title config.title)
(meta { name = "viewport"; content = "width=device-width, initial-scale=1"; })
]))
(body (sidebarSection ++ [ (div { class = "content"; } content) ]))
(head (stylesheets
++ [
(title config.title)
(meta {
name = "viewport";
content = "width=device-width, initial-scale=1";
})
]))
(body (sidebarSection ++ [(div {class = "content";} content)]))
]}
'';
stylesheet =
with utils.css;
let
marginMobile = {
margin-left = "3%";
margin-right = "3%";
};
in
stylesheet = with utils.css; let
marginMobile = {
margin-left = "3%";
margin-right = "3%";
};
in
css [
(css (
(
mapAttrs'
(name: value: nameValuePair value { content = "\"${concatStrings (map (_: "#") (range 1 (toInt name)))} \""; })
(genAttrs (n: "h${toString n}:before") (map toString (range 1 6)))
) // {
(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" = {
position = "relative";
margin-top = "5%";
} // marginMobile;
"div.content" = {
margin-top = 0;
} // marginMobile;
"nav.sidebar" =
{
position = "relative";
margin-top = "5%";
}
// marginMobile;
"div.content" =
{
margin-top = 0;
}
// marginMobile;
})
];
in
{
in {
inherit stylesheets sidebarSection mkPage stylesheet;
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);
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);
}

View File

@ -3,34 +3,36 @@ let
mapAttrsToList = f: attrs: map (name: f name attrs.${name}) (builtins.attrNames attrs);
in
{
inherit mapAttrsToList;
{
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:
if isAttrs value
then recurse (path ++ [ name ]) value
else path ++ [ name ];
in
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);
flattenIfHasList (recurse [] set);
concatStrings = concatStringsSep "";
genAttrs = f: names: listToAttrs (map (n: { name = n; value = (f n); }) names);
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
range = first: last:
if first > last
then []
else genList (n: first + n) (last - first + 1);
}
// builtins