diff --git a/public/css/colours.css b/public/css/colours.css index 838d262..0504eda 100644 --- a/public/css/colours.css +++ b/public/css/colours.css @@ -22,6 +22,7 @@ pre.codeblock { --string: #a3be8c; --function: #b48ead; --number: #81a1c1; + --comment: #8fbcbb; } pre.codeblock span.keyword { @@ -43,3 +44,7 @@ pre.codeblock span.function { pre.codeblock span.number { color: var(--number) } + +pre.codeblock span.comment { + color: var(--comment) +} diff --git a/public/js/code_highlighter.js b/public/js/code_highlighter.js index ff3690c..d883e61 100644 --- a/public/js/code_highlighter.js +++ b/public/js/code_highlighter.js @@ -1,43 +1,141 @@ const highlight = (map, source) => { - let output = source; + let output = ""; - output = output.replace(/("[^"]+")/g, `$1`) + let i = 0; - for (let keyword of map.keywords) { - output = output.replaceAll(keyword, `${keyword}`) + while (i < source.length) { + for (f of map.rules) { + let p = f((j) => source[i + j], (j) => { i += j }); + if (p != undefined) + output += p; + } + + output += source[i++]; } - for (let keyword of map.altkeywords) { - output = output.replaceAll(keyword, `${keyword}`) - } - - // TODO: predicate for function calls to be replaced - // for (let func in map.functions) { - // output = output.replace(func, `${func}`) - // } - - output = output.replace(/(\d+)/g, `$1`) - return output; } -const maps = { - cpp: { - keywords: [ - "auto", - "void", - "struct" - ], - altkeywords: [ - "const", - "static", - "int", - "std::string", - "std::unique_ptr", - "char", - "public", - "private", - "protected" - ], +const match = (m) => (peek, take) => { + for (let i = 0; i < m.length; i++) + if (peek(i) != m[i]) + return false; + take(m.length); + return true; +} +const take_until = (p) => (peek, take) => { + let b = ""; + while (!p()) { + b += peek(0); + take(1); } + return b; +} + +const simpleHighlight = (c) => (keyword) => (peek, take) => { + if (match(keyword)(peek, take)) + return `${keyword}`; +} + +const keyword = simpleHighlight("keyword"); +const altKeyword = simpleHighlight("keyword-alt"); + +const comment = (prefix) => (peek, take) => { + if (match(prefix)(peek, take)) { + let b = prefix; + b += take_until(() => peek(0) == "\n")(peek, take); + return `${b}` + } +} + +const multiline_comment = (prefix, suffix) => (peek, take) => { + if (match(prefix)(peek, take)) { + let b = prefix; + b += take_until(() => match(suffix)(peek, take))(peek, take); + b += suffix; + return `${b}` + } +} + +const string = (c) => (peek, take) => { + if (match(c)(peek, take)) { + let b = c; + b += take_until(() => match(c)(peek,take))(peek, take); + b += c; + return `${b}` + } +} + +// keywords: [ +// "auto", +// "void", +// "struct" +// ], +// altkeywords: [ +// "const", +// "static", +// "int", +// "std::string", +// "std::unique_ptr", +// "char", +// "public", +// "private", +// "protected" +// ], + +const maps = { + + cpp: { + rules: [ + comment("//"), + multiline_comment("/*", "*/"), + + string("\""), + // single char + (peek, take) => { + if (peek(0) == "'") { + let b = peek(1); + take(3); + return `'${b}'`; + } + }, + + keyword("auto"), + keyword("void"), + keyword("class"), + keyword("struct"), + keyword("std::string"), + + altKeyword("const"), + altKeyword("static"), + altKeyword("int"), + altKeyword("char"), + altKeyword("private"), + altKeyword("public"), + altKeyword("protected"), + altKeyword("abstract"), + altKeyword("override"), + altKeyword("return"), + ], + }, + + nix: { + rules: [ + comment("#"), + + string("\""), + string("''"), + + keyword("@"), + keyword("nixpkgs"), + keyword("builtins"), + + altKeyword("let"), + altKeyword("in"), + altKeyword("with"), + altKeyword("inherit"), + altKeyword("import"), + ], + }, + }; diff --git a/public/js/md2html.js b/public/js/md2html.js index 7e25c74..d0894ba 100644 --- a/public/js/md2html.js +++ b/public/js/md2html.js @@ -67,29 +67,27 @@ const md2tokens = (markdown, newline) => { case '*': finish(); advance(); + newline=false; + newline_count=0; let depth_em = 1; let type = "em"; if (match("*")) { type = "bold"; depth_em = 2; - } - let found_match = () => { - for (let j = 0; j < depth_em; j++) { - if (markdown[i + j] != "*") - return false + if (match("*")) { + type = "embold"; + depth_em = 3; } - return true } - while (!found_match()) { - current_string += markdown[i]; - if (!advance()) - break; + current_string = capture_until_predicate((i) => { let found = true; for (let j = 0; j < depth_em; j++) { if (markdown[i + j] != "*") { found = false; break; } } return found; }) + + for (let j=0;j { case '`': finish(); advance(); + newline=false; + newline_count=0; let stop = (i) => markdown[i] == "`"; let type_c = "inlinecode"; let language = ""; @@ -209,7 +209,7 @@ const md2tokens = (markdown, newline) => { current_string = capture_until_predicate(stop); tokens.push({ type: type_c, content: current_string, language: language }); current_string = ""; - if (type_c == "codeblock") { advance(); advance(); } // remove trailing ` + if (type_c == "codeblock") { advance(); advance(); newline_count=2; } // remove trailing ` break; default: @@ -247,6 +247,9 @@ const tokens2html = (tokens) => { case "em": output += `${token.content}` break; + case "embold": + output += `${token.content}` + break; case "header": output += `${token.content}` break; @@ -273,6 +276,9 @@ const tokens2html = (tokens) => { case "link": output += `${token.text}`; break; + + default: + throw "Unknown token type " + token.type; } } diff --git a/public/posts/index.html b/public/posts/index.html index e509212..31fe201 100644 --- a/public/posts/index.html +++ b/public/posts/index.html @@ -19,6 +19,10 @@ text-justify: auto; } + ul,ol { + margin-top:0; + } + img { background-color: var(--background-text); diff --git a/public/posts/test.md b/public/posts/test.md new file mode 100644 index 0000000..02f5bd7 --- /dev/null +++ b/public/posts/test.md @@ -0,0 +1,65 @@ +0 +Test +# H1 +## H2 +### H3 +#### H4 +##### H5 + +This is regular text + +[This is a link](#) + +*italic text* + +**bold text** + +***bold italic*** + +`this is an inline code block` + +``` +this is a code block +``` + +```cpp +/* + * TEST CPP CODEBLOCK + */ +void main(int argc, char** argv) { + std::string this = "c++ code block"; + return 0; +} + +class TestClass : AbstractTestClass { +public: + TestClass(); + ~TestClass(); +private: + void DoStuff() override { + // do some stuff + } +}; +``` + +```nix +{ ... }: +let + this = "a nix code block"; +in +{ + posts.test.content = '' + multiline string + ''; + + website.backend = (pkgs.callPackage (import gitlab:SpoodyTheOne/webbisitey) {}); +} +``` + +- List +- Test +- here + +![test broken image](broken_image.png) +![test image](/test.png) +![test image](/test.png "Image with caption")