diff --git a/.gitignore b/.gitignore index 1838af2..87ffa6a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ *.js -tsconfig.json \ No newline at end of file +tsconfig.json +tsconfig-node.json +tsconfig-web.json \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..fa8a089 --- /dev/null +++ b/index.html @@ -0,0 +1,26 @@ + + +
+ + +tes test_assert_equal(parse_md_to_html("****a*"), "
a*
", "bold italic test 2"); +test_assert_equal(parse_md_to_html("**burger** *b*ca*\n**with no fries**"), "burger bca*
\nwith no fries
", "bold italic test 3"); + test_assert_equal(parse_md_to_html("---\n--\n----\n--a-\n---"), "--
\n--a-
\n**cheese**
\n*cheese*
", "backslash test"); @@ -63,12 +71,23 @@ test_assert_equal(parse_md_to_html("```\nif time == 420:\n weed()\n```"), "`
\n", "code block test 2") + test_assert_equal(parse_md_to_html("test\n> test\n> ## TEST\n> **beach**\n> `wee`\n> # dd"), "\nif\n
\n b
\na
\n
test
\n\n", "block quote test 1"); test_assert_equal(parse_md_to_html("> ```\n> alert('e')\n> ```"), "test
\nTEST
\nbeach
\n\n
weedd
\n
\n", "block quote test 2"); -//todo: ordered lists, unordered lists, tables +test_assert_equal(parse_md_to_html("> a\n\n> b"), "\nalert('e')\n
\n
\n\na
\n
\n", "block quote test 3"); -console.log(parse_md_to_html("- burger\n- fries\n- pizza")); +test_assert_equal(parse_md_to_html("> - burger\n> -winter melons\n> abcdefg\n> - fries\n- p**i**zza\nabacus"), "b
\n
\n\n\n
\n- burger
\n-winter melons
\nabcdefg
\n\n
\n- fries
\n
abacus
", "unordered lists test"); + +test_assert_equal(parse_md_to_html("1. a\n2. b\n3. c\n5. should *fail*\n> 1. d\n> 2. e\n3. should fail too"), "5. should fail
\n\n\n\n
\n- d
\n- e
\n
3. should fail too
", "ordered lists test 1") + +test_assert_equal(parse_md_to_html("1. uno\n2. dos\n3. tres\n4. cuatro\n5. cinco\n6. seis\n7. siete\n8. ocho\n9. nueve\n10. diez\n11. once"), "a ace base
\ne=mc^2
\nea
", "superscript test"); + +//I don't care about table edgecases. +test_assert_equal(parse_md_to_html("|a|b|c|\n|d|e|f|\n# a"), "| a | \nb | \nc | \n
|---|---|---|
| d | \ne | \nf | \n
, so add it! if (chars[i-1] === "\n") { html_line = "
";
@@ -183,17 +199,89 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
add_char = false;
}
}
+ //ending superscript
+ if (in_superscript && char === "^") {
+ html_line += "";
+ in_superscript = false;
+ add_char = false;
+ }
if (add_char) {
html_line += char;
}
}
+ if (in_asterisk) {
+ //bold/italic never ended
+ if (asterisk_num === 1) {
+ //remove the last and replace it with a *
+ let split: string[] = html_line.split("");
+ html_line = "";
+ for (let ii=0; ii < split.length; ii++) {
+ html_line += split[ii];
+ if (ii !== split.length-1) {
+ if (ii === split.length-2) {
+ html_line += "*";
+ } else {
+ html_line += "";
+ }
+ }
+ }
+ } else if (asterisk_num === 2) {
+ //remove the last and replace it with a **
+ let split: string[] = html_line.split("");
+ html_line = "";
+ for (let ii=0; ii < split.length; ii++) {
+ html_line += split[ii];
+ if (ii !== split.length-1) {
+ if (ii === split.length-2) {
+ html_line += "**";
+ } else {
+ html_line += "";
+ }
+ }
+ }
+ }
+ asterisk_num = 0;
+ asterisk_out_num = 0;
+ in_asterisk = false;
+ }
+ if (in_superscript) {
+ //superscript never ended
+ //remove the last and replace it with a ^
+ let split: string[] = html_line.split("");
+ html_line = "";
+ for (let ii=0; ii < split.length; ii++) {
+ html_line += split[ii];
+ if (ii !== split.length-1) {
+ if (ii === split.length-2) {
+ html_line += "^";
+ } else {
+ html_line += "";
+ }
+ }
+ }
+ in_superscript = false;
+ }
+ //ending table row
+ if (in_table) {
+ in_table_header = false;
+ html_line += "\n";
+ }
html += html_line;
if (html_line.startsWith(" ")) {
html += "")) && in_unordered_list) {
+ } else if ((html_line.startsWith("
";
+ //set it to false, not that it matters
+ blockquote_list = false;
+ } else if (i === chars.length-1 && in_ordered_list) {
+ html += "";
+ //set it to false, not that it matters
+ blockquote_list = false;
}
}
html_line = "";
@@ -229,6 +317,11 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
html += "\n";
}
html += "";
+ in_blockquote = false;
+ } else if (in_blockquote && char === "\n" && chars[i-1] === "\n") {
+ //two new lines in a row means blockquote ends
+ html += "\n";
+ in_blockquote = false;
}
heading_level = 0;
if (i === chars.length - 1) {
@@ -243,7 +336,20 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
html += "") || html_line.startsWith("
")) && (in_unordered_list || in_ordered_list)) {
html += "
\n";
continue;
} else if (in_blockquote && chars[i-1] === "\n" && (char !== ">" || chars[i+1] !== " ")) {
- html_line = "
\n";
+ if (blockquote_list) {
+ //end list if list started in blockquote and blockquote ends
+ blockquote_list = false;
+ if (in_unordered_list) {
+ html += "\n\n";
+ } else if (in_ordered_list) {
+ html += "\n\n";
+ }
+ ordered_list_num = 0;
+ in_ordered_list = false;
+ in_unordered_list = false;
+ } else {
+ html += "\n";
+ }
in_blockquote = false;
} else if (char === ">" && chars[i+1] === " " && (chars[i-1] === "\n" || i === 0)) {
//do not add the '>' to the html
@@ -304,10 +410,10 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
} else if (in_code_block) {
//do not render markdown inside code blocks... obviously
//preserve spaces at the beginning of lines
- if (char === " " && space_start) {
- html_line += " ";
- } else if (in_blockquote && ((char === " " && chars.slice(i-2, i) === "\n>") || (char === ">" && chars[i-1] === "\n" && chars[i+1] === " "))) {
+ if (in_blockquote && ((char === " " && chars.slice(i-2, i) === "\n>") || (char === ">" && chars[i-1] === "\n" && chars[i+1] === " "))) {
//do not add the blockquote syntax thing "> " to the codeblock
+ } else if (char === " " && space_start) {
+ html_line += " ";
} else {
space_start = false;
html_line += char;
@@ -315,18 +421,42 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
continue;
}
//handle unordered lists
- if (char === " " && chars[i-1] === "-" && (chars[i-2] === "\n" || i === 1)) {
+ if (char === " " && chars[i-1] === "-" && (chars[i-2] === "\n" || i === 1 || (in_blockquote && chars.slice(i-3, i-1) === "> " && (chars[i-4] === "\n" || i === 3)))) {
//it's a unordered list bullet point!!
- if (!in_unordered_list) {
+ if (!in_unordered_list || (!in_blockquote && blockquote_list)) {
html_line = "\n
\n";
+ } else if (in_unordered_list && ((((chars[i-1] === "\n" && char !== "-") || (chars[i-2] === "\n" && char !== " ")) && !blockquote_list) || (((chars[i-3] === "\n" && char !== "-") || (chars[i-4] === "\n" && char !== " ")) && blockquote_list))) {
+ html += "\n";
in_unordered_list = false;
+ blockquote_list = false;
+ }
+ //handle ordered lists
+ let ol_num_length: number = String(ordered_list_num+1).length;
+ if (char === " " && chars.slice(i-1-ol_num_length, i) === `${ordered_list_num+1}.` && (chars[i-ol_num_length-2] === "\n" || i === ol_num_length+1 || (in_blockquote && chars.slice(i-ol_num_length-3, i) === `> ${ordered_list_num+1}.` && (chars[i-ol_num_length-4] === "\n" || i === ol_num_length+3)))) {
+ if (ordered_list_num === 0) {
+ html_line = "\n
\n";
+ ordered_list_num = 0;
+ in_ordered_list = false;
+ blockquote_list = false;
}
//handle code
if (char === "`" && !in_code) {
@@ -371,6 +501,35 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
html_line += char;
continue;
}
+ //handle tables
+ if (char === "|" && (chars[i-1] === "\n" || i === 0 || (in_blockquote && chars.slice(i-2, i) === "> " && (chars[i-3] === "\n" || i === 3)))) {
+ if (!in_table) {
+ //start of table
+ in_table = true;
+ in_table_header = true;
+ html += "\n
\n";
+ } else if (in_table) {
+ table_item += char;
+ continue;
+ }
//handle heading levels
//ensure headings are continuous and have after it ("#a##" or "##abc" are not a valid headings), and are at the beginning of the line
//ensure headings are possible in block quotes
@@ -514,6 +673,18 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
} else if (char !== "*" && in_asterisk) {
asterisk_out_num = 0;
}
+ //handle superscripts
+ if (char === "^") {
+ if (in_superscript) {
+ in_superscript = false;
+ html_line += "\n";
+ } else {
+ //just a new table row
+ html += " \n";
+ }
+ continue;
+ } else if (in_table && char === "|") {
+ if (in_table_header) {
+ html_line += ` ${table_item} \n`;
+ } else {
+ html_line += `${table_item} \n`;
+ }
+ table_item = "";
+ continue;
+ } else if (in_table && ((chars[i-1] === "\n" && char !== "|") || (in_blockquote && chars[i-3] === "\n" && char !== "|"))) {
+ in_table = false;
+ table_item = "";
+ //table ends
+ html += "