|
|
|
@ -1,19 +1,16 @@
|
|
|
|
|
let
|
|
|
|
|
elems = import ./elems.nix;
|
|
|
|
|
html = import ./html.nix;
|
|
|
|
|
in rec {
|
|
|
|
|
processMd = md:
|
|
|
|
|
rec {
|
|
|
|
|
processMd = elems: md:
|
|
|
|
|
if builtins.isPath md
|
|
|
|
|
then processStr (builtins.readFile md)
|
|
|
|
|
else processStr md;
|
|
|
|
|
then processStr elems (builtins.readFile md)
|
|
|
|
|
else processStr elems md;
|
|
|
|
|
|
|
|
|
|
recReadMd = root:
|
|
|
|
|
recReadMd = toPage: elems: root:
|
|
|
|
|
assert builtins.isPath root;
|
|
|
|
|
builtins.mapAttrs (path: type:
|
|
|
|
|
if type == "directory"
|
|
|
|
|
then recReadMd (root + (/. + path))
|
|
|
|
|
else if type == "regular"
|
|
|
|
|
then mdToPage (root + (/. + path))
|
|
|
|
|
then toPage (processMd elems (root + (/. + path)))
|
|
|
|
|
else throw "Cannot read ${path}, file type ${type}") (builtins.readDir root);
|
|
|
|
|
|
|
|
|
|
recFixAppendix = site:
|
|
|
|
@ -28,19 +25,13 @@ in rec {
|
|
|
|
|
|
|
|
|
|
fixAppendix = builtins.replaceStrings [".md"] [".html"];
|
|
|
|
|
|
|
|
|
|
readDir = root: recFixAppendix (recReadMd root);
|
|
|
|
|
readDir = toPage: elems: root: recFixAppendix (recReadMd toPage elems root);
|
|
|
|
|
|
|
|
|
|
mdToPage = md:
|
|
|
|
|
html.document {
|
|
|
|
|
head = [];
|
|
|
|
|
body = elems.main (elems.article (processMd md));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
splitList = block:
|
|
|
|
|
map listItem (builtins.filter (s: builtins.isString s && s != "")
|
|
|
|
|
splitList = elems: block:
|
|
|
|
|
map listItem elems (builtins.filter (s: builtins.isString s && s != "")
|
|
|
|
|
(builtins.split "\n" block));
|
|
|
|
|
|
|
|
|
|
listItem = str: let
|
|
|
|
|
listItem = elems: str: let
|
|
|
|
|
li = builtins.match "- (.*)" str;
|
|
|
|
|
checkbox = builtins.match "- \\[(.)] (.*)" str;
|
|
|
|
|
checked = builtins.elemAt checkbox 0;
|
|
|
|
@ -58,47 +49,48 @@ in rec {
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
replace = regex: apply: block:
|
|
|
|
|
assert builtins.isString block; (let
|
|
|
|
|
m = builtins.match regex block;
|
|
|
|
|
before = builtins.elemAt m 0;
|
|
|
|
|
after = toString (builtins.elemAt m (matchCount - 1));
|
|
|
|
|
matchCount = builtins.length m;
|
|
|
|
|
if toString block == ""
|
|
|
|
|
then ""
|
|
|
|
|
else
|
|
|
|
|
(let
|
|
|
|
|
match = builtins.match regex block;
|
|
|
|
|
before = builtins.elemAt match 0;
|
|
|
|
|
matchCount = builtins.length match;
|
|
|
|
|
after = builtins.elemAt match (matchCount - 1);
|
|
|
|
|
in
|
|
|
|
|
if m == null
|
|
|
|
|
if match == null
|
|
|
|
|
then block
|
|
|
|
|
else
|
|
|
|
|
(
|
|
|
|
|
if before == null
|
|
|
|
|
then ""
|
|
|
|
|
else replace regex apply before
|
|
|
|
|
replace regex apply before
|
|
|
|
|
)
|
|
|
|
|
+ (apply m)
|
|
|
|
|
+ (apply match)
|
|
|
|
|
+ after);
|
|
|
|
|
|
|
|
|
|
rule = matcher: apply: blocks:
|
|
|
|
|
map (block:
|
|
|
|
|
if builtins.isString block
|
|
|
|
|
then replace matcher apply block
|
|
|
|
|
else block)
|
|
|
|
|
blocks;
|
|
|
|
|
if builtins.isString blocks
|
|
|
|
|
then replace matcher apply blocks
|
|
|
|
|
else if builtins.isList blocks
|
|
|
|
|
then map (replace matcher apply) blocks
|
|
|
|
|
else throw "replace rule should be applied to string or list of strings";
|
|
|
|
|
|
|
|
|
|
applyRules = i: rules: input: let
|
|
|
|
|
applyRules = index: rules: input: let
|
|
|
|
|
group =
|
|
|
|
|
if builtins.isString input
|
|
|
|
|
then [input]
|
|
|
|
|
else input;
|
|
|
|
|
len = builtins.length rules;
|
|
|
|
|
rule = builtins.elemAt rules i;
|
|
|
|
|
next = i + 1;
|
|
|
|
|
rule = builtins.elemAt rules index;
|
|
|
|
|
next = index + 1;
|
|
|
|
|
in
|
|
|
|
|
assert i < len;
|
|
|
|
|
assert index < len;
|
|
|
|
|
if next < len
|
|
|
|
|
then rule (applyRules next rules group)
|
|
|
|
|
else rule group;
|
|
|
|
|
|
|
|
|
|
basicRule = matcher: elem: rule matcher (m: elem (builtins.elemAt m 1));
|
|
|
|
|
|
|
|
|
|
processStr = applyRules 0 [
|
|
|
|
|
processStr = elems: applyRules 0 [
|
|
|
|
|
(basicRule (wrap "\\^") elems.sup)
|
|
|
|
|
(basicRule (wrap "~") elems.sub)
|
|
|
|
|
(basicRule (wrap "\\*") elems.em)
|
|
|
|
@ -111,8 +103,8 @@ in rec {
|
|
|
|
|
(rule (contains "\\[(.*)]\\((.*)\\)") (m: let
|
|
|
|
|
href = builtins.elemAt m 2;
|
|
|
|
|
text = builtins.elemAt m 1;
|
|
|
|
|
in (elems.a href text)))
|
|
|
|
|
list
|
|
|
|
|
in (elems.a {inherit href;} text)))
|
|
|
|
|
(list elems)
|
|
|
|
|
(basicRule "(.*\n\n)?(.+)\n(.*)?" elems.p)
|
|
|
|
|
(basicRule "(.*\n\n)?```(.*)```(.*)?" (elems.textarea {readonly = true;}))
|
|
|
|
|
(basicRule (containsBreak "###### ([^\n]+)") (elems.h6))
|
|
|
|
@ -121,18 +113,25 @@ in rec {
|
|
|
|
|
(basicRule (containsBreak "### ([^\n]+)") (elems.h3))
|
|
|
|
|
(basicRule (containsBreak "## ([^\n]+)") (elems.h2))
|
|
|
|
|
(basicRule (containsBreak "# ([^\n]+)") (elems.h1))
|
|
|
|
|
(basicRule (containsBreak "<(${linkmatcher})>") (m: elems.a m m))
|
|
|
|
|
(basicRule (containsBreak "<(${linkmatcher})>") (m: elems.a {href = m;} m))
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
list = rule "((.*)(\n([^-\n][^\n]+)?\n))?((- [^\n]+\n)+)(.*)" (
|
|
|
|
|
l: (elems.ul (basicRule "(.*\n)?- ([^\n]+)\n(.*)" (m:
|
|
|
|
|
elems.li (basicRule "()\\[(.)] (.*)" (check:
|
|
|
|
|
list = elems: let
|
|
|
|
|
addCheckboxes = basicRule "()\\[(.)] (.*)" (check:
|
|
|
|
|
elems.input {
|
|
|
|
|
type = "checkbox";
|
|
|
|
|
checked = check != " ";
|
|
|
|
|
disabled = true;
|
|
|
|
|
}) [m])) [(builtins.elemAt l 4)]))
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
listitems =
|
|
|
|
|
basicRule "(.*\n)?- ([^\n]+)\n(.*)" (contents:
|
|
|
|
|
elems.li (addCheckboxes contents));
|
|
|
|
|
in (rule "((.*)(\n([^-\n][^\n]+)?\n))?((- [^\n]+\n)+)(.*)" (
|
|
|
|
|
match: let
|
|
|
|
|
listString = builtins.elemAt match 4;
|
|
|
|
|
in (elems.ul (listitems listString))
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
linkmatcher = "[-[:alnum:].%?&#=:/]+";
|
|
|
|
|
contains = matcher: "(.*)?${matcher}(.*)";
|
|
|
|
|