process markdown files

This commit is contained in:
tristan 2024-01-01 17:31:04 +00:00
parent 496d3667de
commit c29ff7b22e
7 changed files with 213 additions and 80 deletions

View file

@ -51,6 +51,7 @@ nix build .#raw
- [ ] links
- [X] codeblocks
- [ ] subscript
- [ ] highlight
- [ ] italics
- [ ] bold
- [X] highlight
- [X] italics
- [X] bold

View file

@ -4,9 +4,11 @@ let
H = n:
let
v = if n < 1 then
builtins.trace "attempted to make heading size ${toString n} (min is 1)" 1
builtins.trace "attempted to make heading size ${toString n} (min is 1)"
1
else if n > 6 then
builtins.trace "attempted to make heading size ${toString n} (max is 6)" 6
builtins.trace "attempted to make heading size ${toString n} (max is 6)"
6
else
n;
in html.tag "h${toString v}" { };
@ -49,29 +51,81 @@ in rec {
h = heading block;
c = code block;
ul = list block;
in (if h.matched then h.block else
if c.matched then c.block else
if ul.matched then ul.block else
elems.p block));
in (if h.matched then
h.block
else if c.matched then
c.block
else if ul.matched then
ul.block
else
elems.p (processStr block)));
heading = block: matchThen "(#+) (.*)" block (m:
let
l = builtins.stringLength (builtins.elemAt m 0);
in H l (builtins.elemAt m 1));
heading = block:
matchThen "(#+) (.*)" block (m:
let l = builtins.stringLength (builtins.elemAt m 0);
in H l (builtins.elemAt m 1));
code = block: matchThen "(```)(.*)(```)" block (m:
elems.code (builtins.elemAt m 1));
code = block:
matchThen "(```)(.*)(```)" block (m: elems.code (builtins.elemAt m 1));
list = block: matchThen (let item = "- .+"; in "(${item}\n)*(${item}\n?)") block (m:
elems.List (builtins.filter ( s: builtins.isString s && s!="" ) (builtins.split "[:blank:]*- " block)));
list = block:
matchThen (let item = "- .+";
in ''
(${item}
)*(${item}
?)'') block (m:
elems.List (builtins.filter (s: builtins.isString s && s != "")
(builtins.split "[:blank:]*- " block)));
replace = matcher: apply: block:
(let
m = builtins.match matcher block;
before = let v = builtins.elemAt m 0; in if v == null then "" else v;
inner = builtins.elemAt m 1;
after = builtins.elemAt m 2;
in if m == null then
block
else
(replace matcher apply before) + (apply inner) + after);
rule = matcher: apply: blocks:
map (b: if builtins.isString b then replace matcher apply b else b) blocks;
applyRules = i: rules: input:
let
group = if builtins.isString input then [ input ] else input;
len = builtins.length rules;
rule = builtins.elemAt rules i;
next = i + 1;
in assert i < len;
if next < len then rule (applyRules next rules group) else rule group;
processStr = applyRules 0 [
(rule (wrap "\\^") elems.sup)
(rule (wrap "~") elems.sub)
(rule (wrap "\\*") elems.em)
(rule (wrap "`") elems.code)
(rule (wrap "==") elems.mark)
(rule (wrap "~~") elems.del)
(rule (wrap "\\*\\*") elems.strong)
(rule (contains "<([-[:alnum:].%?&#=:/]+)>") (m: elems.a m m))
];
contains = matcher: "(.* )?${matcher}(.*)";
wrap = matcher: contains "${matcher}(.+)${matcher}";
matchThen = matcher: block: func:
let
m = builtins.match matcher block;
in
if m == null then dontMatch block
else { matched = true; block = func m; };
let m = builtins.match matcher block;
in if m == null then
dontMatch block
else {
matched = true;
block = func m;
};
dontMatch = block: { matched = false; inherit block; };
dontMatch = block: {
matched = false;
inherit block;
};
}

View file

@ -1,9 +1,14 @@
# yeee
ye
I need some *emphasis*...
&amp;
that's **bold**!
<a href="dir">dir</a>
<a href="/">home</a>
==mark== the important parts.
but ~~forget the rest~~.
drink lot's of H ~2~O ^if you want^!
<https://www.markdownguide.org/basic-syntax/>

View file

@ -22,10 +22,13 @@ let
v;
out = (if safeToPrint then
builtins.toJSON
(undunder (if throws then (builtins.tryEval actual).value else actual))
builtins.toJSON (undunder (if throws then
(builtins.tryEval actual).value
else {
inherit actual expected;
}))
else
''{"msg": "refusing to print"}'');
''{"msg": "cannot be stringified ):"}'');
success =
if throws then (builtins.tryEval actual).success == false else (a == e);
@ -33,7 +36,9 @@ let
in if success then ''
echo 'it ${msg}'
'' else
builtins.trace "FAILED ${msg}" ''
builtins.trace "FAILED ${msg}" (let file = builtins.toFile "value" out;
in ''
echo FAILED ${msg}
echo '${out}' | jq '.'
''
echo '${file}'
cat '${file}' | jq '.'
'')

View file

@ -19,55 +19,132 @@ in with md; [
expected = elems.h6 "super ultra tiny heading";
})
(it "makes a code block" (
let code = ''
this is my code
''; in {
actual = mdBlock ''
```${code}```'';
(it "makes a code block" (let
code = ''
this is my code
'';
in {
actual = mdBlock "```${code}```";
expected = elems.code code;
}))
(it "matches a list of one element" (
{
(it "matches a list of one element" ({
actual = list ''
- something
- something
'';
expected = { matched = true; block = elems.List ["something\n"];};
expected = {
matched = true;
block = elems.List [''
something
''];
};
}))
(it "matches a list of many elements" (
{
(it "matches a list of many elements" ({
actual = list ''
- something
- something else
- something
- something else
'';
expected = { matched = true; block = elems.List ["something\n" "something else\n"];};
expected = {
matched = true;
block = elems.List [
''
something
''
''
something else
''
];
};
}))
(it "matches a list with no whitespace around" (
{
actual = list
"- something\n- something else";
expected = { matched = true; block = elems.List ["something\n" "something else"];};
(it "matches a list with no whitespace around" ({
actual = list ''
- something
- something else'';
expected = {
matched = true;
block = elems.List [
''
something
''
"something else"
];
};
}))
(it "doesnt match not a list" (
let
str = "blah blah";
in
{
(it "doesnt match not a list" (let str = "blah blah";
in {
actual = list str;
expected = { matched = false; block = str;};
expected = {
matched = false;
block = str;
};
}))
(it "makes a list" (
{
(it "makes a list" ({
actual = mdBlock ''
- something
'';
expected = elems.List ["something\n"];
expected = elems.List [''
something
''];
}))
(it "finds surrounded parts" ({
actual = replace (wrap "\\*\\*") elems.strong ''
this text **may** contain **bold** words inside it.
'';
expected = [
"this text"
(elems.strong "may")
"contain"
(elems.strong "bold")
''
words inside it.
''
];
asString = true;
}))
(it "surrounds in list of elems" ({
actual = rule (wrap "\\*") elems.em [
"this text"
(elems.strong "may")
"*or may not* contain"
(elems.strong "bold")
"words *inside* it."
];
expected = [
"this text"
(elems.strong "may")
(elems.em "or may not")
"contain"
(elems.strong "bold")
"words"
(elems.em "inside")
"it."
];
asString = true;
}))
(it "processes whole string with all rules" ({
actual = processStr ''
this text **may** *or may not* contain **bold** words *inside* it.
'';
expected = [
"this text"
(elems.strong "may")
(elems.em "or may not")
"contain"
(elems.strong "bold")
"words"
(elems.em "inside")
''
it.
''
];
asString = true;
}))
(it "processes md block" {
@ -92,10 +169,8 @@ in with md; [
})
(it "converts markdown to a page" {
actual = mdToPage ./blog/index.md;
expected = ''
<html lang="en"><head ><title >markdown file</title></head> <body ><h1 >yeee</h1> <p >ye</p> <p >&amp;</p> <p ><a href="dir">dir</a>
<a href="/">home</a></p> <p ></p></body></html>'';
actual = toString (mdToPage ./blog/index.md) + "\n";
expected = builtins.readFile ./out/index.html;
asString = true;
})

1
testing/out/index.html Normal file
View file

@ -0,0 +1 @@
<html lang="en"><head ><title >markdown file</title></head> <body ><h1 >yeee</h1> <p >I need some <em >emphasis</em>...</p> <p >that's <strong >bold</strong>!</p> <p ><mark >mark</mark> the important parts.</p> <p >but <del >forget the rest</del>.</p> <p >drink lot's of H <sub >2</sub>O <sup >if you want</sup>!</p> <p ><a href="https://www.markdownguide.org/basic-syntax/">https://www.markdownguide.org/basic-syntax/</a></p> <p ></p></body></html>

View file

@ -238,30 +238,22 @@ in with site; [
}))
(it "throws with a list for a page" ({
actual = copyTo "." {
page = [];
};
actual = copyTo "." { page = [ ]; };
throws = true;
}))
(it "throws with null for a page" ({
actual = copyTo "." {
page = null;
};
actual = copyTo "." { page = null; };
throws = true;
}))
(it "throws with a bool for a page" ({
actual = copyTo "." {
page = true;
};
actual = copyTo "." { page = true; };
throws = true;
}))
(it "throws with a number for a page" ({
actual = copyTo "." {
page = 5;
};
actual = copyTo "." { page = 5; };
throws = true;
}))