web preview + finish-ish markdown
ordered lists, superscript, tables and some fixes
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
|||||||
*.js
|
*.js
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
|
tsconfig-node.json
|
||||||
|
tsconfig-web.json
|
||||||
26
index.html
Normal file
26
index.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<title>Makoto Markdown Editor</title>
|
||||||
|
<link href="/styles/style.css" rel="stylesheet">
|
||||||
|
<link href="/styles/makoto.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="grid-container">
|
||||||
|
<div id="editor-container" class="section">
|
||||||
|
<!--<textarea id="editor" placeholder="Type in some markdown..."></textarea>-->
|
||||||
|
<ol id="editor" contenteditable>
|
||||||
|
<li>markdown goes here...</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
<div id="preview-container" class="section">
|
||||||
|
<label for="dark-theme-toggle">Dark Theme</label><input id="dark-theme-toggle" type="checkbox">
|
||||||
|
<div id="rendered-text">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="/web.js" type="module"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
23
index.ts
23
index.ts
@@ -17,6 +17,12 @@ Quirks
|
|||||||
```
|
```
|
||||||
- If a language for the code block is provided, the parser will add a css class "code-<language name>" to the resulting code block div (which btw has class code-block)
|
- If a language for the code block is provided, the parser will add a css class "code-<language name>" to the resulting code block div (which btw has class code-block)
|
||||||
- All elements should be able to be used in block quotes (ok, not really a quirk). In code blocks, the code in the code block must also start with "> " of course
|
- All elements should be able to be used in block quotes (ok, not really a quirk). In code blocks, the code in the code block must also start with "> " of course
|
||||||
|
- Superscripts are supported! "^1^" become "<sup>1</sup>". Use these for footnotes too, I'm not implementing those.
|
||||||
|
- Underlined headers are not supported, just use a header and a horizontal rule
|
||||||
|
- Nested blockquotes won't work
|
||||||
|
- The first row of a table will be assumed to be the header row, and don't bother with a row of dashes after it.
|
||||||
|
- Also, the pipe ("|") in tables is mandatory at the end of the row, otherwise weird things will happen.
|
||||||
|
- Bold, italic, and other elements are not supported in tables
|
||||||
-
|
-
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -45,6 +51,8 @@ test_assert_equal(parse_md_to_html("**test abc** *a*\n## **ch*ch**"), "<p><b>tes
|
|||||||
|
|
||||||
test_assert_equal(parse_md_to_html("****a*"), "<p><b></b>a*</p>", "bold italic test 2");
|
test_assert_equal(parse_md_to_html("****a*"), "<p><b></b>a*</p>", "bold italic test 2");
|
||||||
|
|
||||||
|
test_assert_equal(parse_md_to_html("**burger** *b*ca*\n**with no fries**"), "<p><b>burger</b> <i>b</i>ca*</p>\n<p><b>with no fries</b></p>", "bold italic test 3");
|
||||||
|
|
||||||
test_assert_equal(parse_md_to_html("---\n--\n----\n--a-\n---"), "<hr>\n<p>--</p>\n<hr>\n<p>--a-</p>\n<hr>", "horizontal rule test");
|
test_assert_equal(parse_md_to_html("---\n--\n----\n--a-\n---"), "<hr>\n<p>--</p>\n<hr>\n<p>--a-</p>\n<hr>", "horizontal rule test");
|
||||||
|
|
||||||
test_assert_equal(parse_md_to_html("\\*\\*cheese\\*\\*\n*\\*cheese\\*\\*"), "<p>**cheese**</p>\n<p><i>*cheese*</i></p>", "backslash test");
|
test_assert_equal(parse_md_to_html("\\*\\*cheese\\*\\*\n*\\*cheese\\*\\*"), "<p>**cheese**</p>\n<p><i>*cheese*</i></p>", "backslash test");
|
||||||
@@ -63,12 +71,23 @@ test_assert_equal(parse_md_to_html("```\nif time == 420:\n weed()\n```"), "<d
|
|||||||
|
|
||||||
test_assert_equal(parse_md_to_html("## testing\n```markdown\n# title\n i like **cheeseburgers** and `code`\n```\n```"), "<h2 id=\"header-0\">testing</h2>\n<div class=\"code-block code-markdown\">\n# title<br>\n i like **cheeseburgers** and `code`<br>\n</div>\n<p><code></code>`</p>", "code block test 2");
|
test_assert_equal(parse_md_to_html("## testing\n```markdown\n# title\n i like **cheeseburgers** and `code`\n```\n```"), "<h2 id=\"header-0\">testing</h2>\n<div class=\"code-block code-markdown\">\n# title<br>\n i like **cheeseburgers** and `code`<br>\n</div>\n<p><code></code>`</p>", "code block test 2");
|
||||||
|
|
||||||
|
test_assert_equal(parse_md_to_html("> ```\n> if\n> b\n> a\n> ```"), "<blockquote>\n<div class=\"code-block\">\nif<br>\n b<br>\na<br>\n</div>\n</blockquote>", "code block test 2")
|
||||||
|
|
||||||
test_assert_equal(parse_md_to_html("test\n> test\n> ## TEST\n> **beach**\n> `wee`\n> # dd"), "<p>test</p>\n<blockquote>\n<p>test</p>\n<h2 id=\"header-0\">TEST</h2>\n<p><b>beach</b></p>\n<p><code>wee</code></p>\n<h1 id=\"header-1\">dd</h1>\n</blockquote>", "block quote test 1");
|
test_assert_equal(parse_md_to_html("test\n> test\n> ## TEST\n> **beach**\n> `wee`\n> # dd"), "<p>test</p>\n<blockquote>\n<p>test</p>\n<h2 id=\"header-0\">TEST</h2>\n<p><b>beach</b></p>\n<p><code>wee</code></p>\n<h1 id=\"header-1\">dd</h1>\n</blockquote>", "block quote test 1");
|
||||||
|
|
||||||
test_assert_equal(parse_md_to_html("> ```\n> alert('e')\n> ```"), "<blockquote>\n<div class=\"code-block\">\nalert('e')<br>\n</div>\n</blockquote>", "block quote test 2");
|
test_assert_equal(parse_md_to_html("> ```\n> alert('e')\n> ```"), "<blockquote>\n<div class=\"code-block\">\nalert('e')<br>\n</div>\n</blockquote>", "block quote test 2");
|
||||||
|
|
||||||
//todo: ordered lists, unordered lists, tables
|
test_assert_equal(parse_md_to_html("> a\n\n> b"), "<blockquote>\n<p>a</p>\n</blockquote>\n<blockquote>\n<p>b</p>\n</blockquote>", "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"), "<blockquote>\n<ul>\n<li>burger</li>\n</ul>\n<p>-winter melons</p>\n<p>abcdefg</p>\n<ul>\n<li>fries</li>\n</ul>\n</blockquote>\n<ul>\n<li>p<b>i</b>zza</li>\n</ul>\n<p>abacus</p>", "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"), "<ol>\n<li>a</li>\n<li>b</li>\n<li>c</li>\n</ol>\n<p>5. should <i>fail</i></p>\n<blockquote>\n<ol>\n<li>d</li>\n<li>e</li>\n</ol>\n</blockquote>\n<p>3. should fail too</p>", "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"), "<ol>\n<li>uno</li>\n<li>dos</li>\n<li>tres</li>\n<li>cuatro</li>\n<li>cinco</li>\n<li>seis</li>\n<li>siete</li>\n<li>ocho</li>\n<li>nueve</li>\n<li>diez</li>\n<li>once</li>\n</ol>", "ordered lists test 2");
|
||||||
|
|
||||||
|
test_assert_equal(parse_md_to_html("a ^ace^ base\n```js\n^sup^\n```\ne=mc^2\n^ea^"), "<p>a <sup>ace</sup> base</p>\n<div class=\"code-block code-js\">\n^sup^<br>\n</div>\n<p>e=mc^2</p>\n<p><sup>ea</sup></p>", "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"), "<table>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n<tr>\n<td>d</td>\n<td>e</td>\n<td>f</td>\n</tr>\n</table>\n<h1 id=\"header-0\">a</h1>", "basic table test");
|
||||||
|
|
||||||
console.log(`Total Passed: \x1B[32m${passed_tests}/${total_tests}\x1B[m\nTotal Failed: \x1B[31m${failed_tests}/${total_tests}\x1B[m`);
|
console.log(`Total Passed: \x1B[32m${passed_tests}/${total_tests}\x1B[m\nTotal Failed: \x1B[31m${failed_tests}/${total_tests}\x1B[m`);
|
||||||
|
|||||||
191
makoto.ts
191
makoto.ts
@@ -37,7 +37,13 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
|
|||||||
let space_start: boolean = false;
|
let space_start: boolean = false;
|
||||||
let in_blockquote: boolean = false;
|
let in_blockquote: boolean = false;
|
||||||
let in_unordered_list: boolean = false;
|
let in_unordered_list: boolean = false;
|
||||||
|
let blockquote_list: boolean = false;
|
||||||
|
let in_ordered_list: boolean = false;
|
||||||
let ordered_list_num: number = 0;
|
let ordered_list_num: number = 0;
|
||||||
|
let in_superscript: boolean = false;
|
||||||
|
let in_table: boolean = false;
|
||||||
|
let in_table_header: boolean = false;
|
||||||
|
let table_item: string = "";
|
||||||
|
|
||||||
//loop through characters
|
//loop through characters
|
||||||
let chars: string = md;
|
let chars: string = md;
|
||||||
@@ -165,6 +171,16 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
|
|||||||
if ((was_image || was_link) && char === ")") {
|
if ((was_image || was_link) && char === ")") {
|
||||||
add_char = false;
|
add_char = false;
|
||||||
}
|
}
|
||||||
|
//handle table row ending thing?
|
||||||
|
if (in_table && char === "|") {
|
||||||
|
in_table = false;
|
||||||
|
add_char = false;
|
||||||
|
if (in_table_header) {
|
||||||
|
html_line += `<th>${table_item}</th>\n</tr>\n</table>`;
|
||||||
|
} else {
|
||||||
|
html_line += `<td>${table_item}</td>\n</tr>\n</table>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
//if previous character is also newline, there hasn't been opportunity to add a <p>, so add it!
|
//if previous character is also newline, there hasn't been opportunity to add a <p>, so add it!
|
||||||
if (chars[i-1] === "\n") {
|
if (chars[i-1] === "\n") {
|
||||||
html_line = "<p>";
|
html_line = "<p>";
|
||||||
@@ -183,17 +199,89 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
|
|||||||
add_char = false;
|
add_char = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//ending superscript
|
||||||
|
if (in_superscript && char === "^") {
|
||||||
|
html_line += "</sup>";
|
||||||
|
in_superscript = false;
|
||||||
|
add_char = false;
|
||||||
|
}
|
||||||
if (add_char) {
|
if (add_char) {
|
||||||
html_line += char;
|
html_line += char;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (in_asterisk) {
|
||||||
|
//bold/italic never ended
|
||||||
|
if (asterisk_num === 1) {
|
||||||
|
//remove the last <i> and replace it with a *
|
||||||
|
let split: string[] = html_line.split("<i>");
|
||||||
|
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 += "<i>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (asterisk_num === 2) {
|
||||||
|
//remove the last <b> and replace it with a **
|
||||||
|
let split: string[] = html_line.split("<b>");
|
||||||
|
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 += "<b>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asterisk_num = 0;
|
||||||
|
asterisk_out_num = 0;
|
||||||
|
in_asterisk = false;
|
||||||
|
}
|
||||||
|
if (in_superscript) {
|
||||||
|
//superscript never ended
|
||||||
|
//remove the last <sup> and replace it with a ^
|
||||||
|
let split: string[] = html_line.split("<sup>");
|
||||||
|
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 += "<sup>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in_superscript = false;
|
||||||
|
}
|
||||||
|
//ending table row
|
||||||
|
if (in_table) {
|
||||||
|
in_table_header = false;
|
||||||
|
html_line += "</tr>\n";
|
||||||
|
}
|
||||||
html += html_line;
|
html += html_line;
|
||||||
if (html_line.startsWith("<p>")) {
|
if (html_line.startsWith("<p>")) {
|
||||||
html += "</p>\n";
|
html += "</p>\n";
|
||||||
} else if ((html_line.startsWith("<li>") || html_line.startsWith("<ul>")) && in_unordered_list) {
|
} else if ((html_line.startsWith("<li>") || html_line.startsWith("<ul>") || html_line.startsWith("<ol>")) && (in_unordered_list || in_ordered_list)) {
|
||||||
html += "</li>\n";
|
html += "</li>\n";
|
||||||
if (i === chars.length-1) {
|
if (in_ordered_list) {
|
||||||
|
ordered_list_num++;
|
||||||
|
}
|
||||||
|
if (i === chars.length-1 && in_unordered_list) {
|
||||||
html += "</ul>";
|
html += "</ul>";
|
||||||
|
//set it to false, not that it matters
|
||||||
|
blockquote_list = false;
|
||||||
|
} else if (i === chars.length-1 && in_ordered_list) {
|
||||||
|
html += "</ol>";
|
||||||
|
//set it to false, not that it matters
|
||||||
|
blockquote_list = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
html_line = "";
|
html_line = "";
|
||||||
@@ -229,6 +317,11 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
|
|||||||
html += "\n";
|
html += "\n";
|
||||||
}
|
}
|
||||||
html += "</blockquote>";
|
html += "</blockquote>";
|
||||||
|
in_blockquote = false;
|
||||||
|
} else if (in_blockquote && char === "\n" && chars[i-1] === "\n") {
|
||||||
|
//two new lines in a row means blockquote ends
|
||||||
|
html += "</blockquote>\n";
|
||||||
|
in_blockquote = false;
|
||||||
}
|
}
|
||||||
heading_level = 0;
|
heading_level = 0;
|
||||||
if (i === chars.length - 1) {
|
if (i === chars.length - 1) {
|
||||||
@@ -243,7 +336,20 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
|
|||||||
html += "<blockquote>\n";
|
html += "<blockquote>\n";
|
||||||
continue;
|
continue;
|
||||||
} else if (in_blockquote && chars[i-1] === "\n" && (char !== ">" || chars[i+1] !== " ")) {
|
} else if (in_blockquote && chars[i-1] === "\n" && (char !== ">" || chars[i+1] !== " ")) {
|
||||||
html_line = "</blockquote>\n";
|
if (blockquote_list) {
|
||||||
|
//end list if list started in blockquote and blockquote ends
|
||||||
|
blockquote_list = false;
|
||||||
|
if (in_unordered_list) {
|
||||||
|
html += "</ul>\n</blockquote>\n";
|
||||||
|
} else if (in_ordered_list) {
|
||||||
|
html += "</ol>\n</blockquote>\n";
|
||||||
|
}
|
||||||
|
ordered_list_num = 0;
|
||||||
|
in_ordered_list = false;
|
||||||
|
in_unordered_list = false;
|
||||||
|
} else {
|
||||||
|
html += "</blockquote>\n";
|
||||||
|
}
|
||||||
in_blockquote = false;
|
in_blockquote = false;
|
||||||
} else if (char === ">" && chars[i+1] === " " && (chars[i-1] === "\n" || i === 0)) {
|
} else if (char === ">" && chars[i+1] === " " && (chars[i-1] === "\n" || i === 0)) {
|
||||||
//do not add the '>' to the html
|
//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) {
|
} else if (in_code_block) {
|
||||||
//do not render markdown inside code blocks... obviously
|
//do not render markdown inside code blocks... obviously
|
||||||
//preserve spaces at the beginning of lines
|
//preserve spaces at the beginning of lines
|
||||||
if (char === " " && space_start) {
|
if (in_blockquote && ((char === " " && chars.slice(i-2, i) === "\n>") || (char === ">" && chars[i-1] === "\n" && chars[i+1] === " "))) {
|
||||||
html_line += " ";
|
|
||||||
} else 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
|
//do not add the blockquote syntax thing "> " to the codeblock
|
||||||
|
} else if (char === " " && space_start) {
|
||||||
|
html_line += " ";
|
||||||
} else {
|
} else {
|
||||||
space_start = false;
|
space_start = false;
|
||||||
html_line += char;
|
html_line += char;
|
||||||
@@ -315,18 +421,42 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//handle unordered lists
|
//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!!
|
//it's a unordered list bullet point!!
|
||||||
if (!in_unordered_list) {
|
if (!in_unordered_list || (!in_blockquote && blockquote_list)) {
|
||||||
html_line = "<ul>\n<li>";
|
html_line = "<ul>\n<li>";
|
||||||
|
blockquote_list = false;
|
||||||
} else {
|
} else {
|
||||||
html_line = "<li>";
|
html_line = "<li>";
|
||||||
}
|
}
|
||||||
in_unordered_list = true;
|
in_unordered_list = true;
|
||||||
|
if (in_blockquote) {
|
||||||
|
blockquote_list = true;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
} else if (in_unordered_list && ((chars[i-1] === "\n" && char !== "-") || (chars[i-2] === "\n" && char !== " "))) {
|
} 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_line += "</ul>\n";
|
html += "</ul>\n";
|
||||||
in_unordered_list = false;
|
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 = "<ol>\n<li>";
|
||||||
|
in_ordered_list = true;
|
||||||
|
} else {
|
||||||
|
html_line = "<li>";
|
||||||
|
}
|
||||||
|
if (in_blockquote) {
|
||||||
|
blockquote_list = true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (in_ordered_list && ((chars[i-ol_num_length-2] === "\n" && chars.slice(i-ol_num_length-1, i+1) !== `${ordered_list_num+1}. ` && !in_blockquote) || (in_blockquote && chars[i-ol_num_length-4] === "\n" && chars.slice(i-ol_num_length-3, i+1) !== `> ${ordered_list_num+1}. `))) {
|
||||||
|
html += "</ol>\n";
|
||||||
|
ordered_list_num = 0;
|
||||||
|
in_ordered_list = false;
|
||||||
|
blockquote_list = false;
|
||||||
}
|
}
|
||||||
//handle code
|
//handle code
|
||||||
if (char === "`" && !in_code) {
|
if (char === "`" && !in_code) {
|
||||||
@@ -371,6 +501,35 @@ export function parse_md_to_html_with_warnings(md: string): ParseResult {
|
|||||||
html_line += char;
|
html_line += char;
|
||||||
continue;
|
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 += "<table>\n<tr>\n";
|
||||||
|
} else {
|
||||||
|
//just a new table row
|
||||||
|
html += "<tr>\n";
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (in_table && char === "|") {
|
||||||
|
if (in_table_header) {
|
||||||
|
html_line += `<th>${table_item}</th>\n`;
|
||||||
|
} else {
|
||||||
|
html_line += `<td>${table_item}</td>\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 += "</table>\n";
|
||||||
|
} else if (in_table) {
|
||||||
|
table_item += char;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
//handle heading levels
|
//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 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
|
//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) {
|
} else if (char !== "*" && in_asterisk) {
|
||||||
asterisk_out_num = 0;
|
asterisk_out_num = 0;
|
||||||
}
|
}
|
||||||
|
//handle superscripts
|
||||||
|
if (char === "^") {
|
||||||
|
if (in_superscript) {
|
||||||
|
in_superscript = false;
|
||||||
|
html_line += "</sup>";
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
in_superscript = true;
|
||||||
|
html_line += "<sup>";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
//
|
//
|
||||||
if (end_add_char) {
|
if (end_add_char) {
|
||||||
html_line += char;
|
html_line += char;
|
||||||
|
|||||||
34
styles/makoto.css
Normal file
34
styles/makoto.css
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
blockquote {
|
||||||
|
margin: 0;
|
||||||
|
margin: 8px 0px;
|
||||||
|
padding: 4px 8px 4px 0px;
|
||||||
|
border-left: 8px solid #727272;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 4px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-block {
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
background-color: #d8d8d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: 2px 5px;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
58
styles/style.css
Normal file
58
styles/style.css
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
#grid-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
padding: 17px;
|
||||||
|
height: 100%;
|
||||||
|
width: 49vw;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor-container {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 95%;
|
||||||
|
width: calc(100% - 15px);
|
||||||
|
height: 95%;
|
||||||
|
margin: 0;
|
||||||
|
word-break: break-all;
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
font-size: 0.9em;
|
||||||
|
padding: 3px;
|
||||||
|
padding-left: 35px;
|
||||||
|
margin-left: 15px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor li::marker {
|
||||||
|
color: #727272;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rendered-text {
|
||||||
|
padding: 5px;
|
||||||
|
word-break: break-all;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rendered-text.dark {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rendered-text.dark .code-block {
|
||||||
|
color: #2d2d2d;
|
||||||
|
}
|
||||||
52
web.ts
Normal file
52
web.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { parse_md_to_html_with_warnings, ParseResult } from './makoto.js';
|
||||||
|
import type { Warning } from './endosulfan.js';
|
||||||
|
|
||||||
|
let editor: HTMLTextAreaElement = document.getElementById("editor")! as HTMLTextAreaElement;
|
||||||
|
let preview: HTMLElement = document.getElementById("rendered-text")!;
|
||||||
|
let dark_theme_toggle: HTMLInputElement = document.getElementById("dark-theme-toggle")! as HTMLInputElement;
|
||||||
|
|
||||||
|
let unedited: boolean = true;
|
||||||
|
|
||||||
|
function render_warnings(warnings: Warning[]) {
|
||||||
|
console.log(warnings)
|
||||||
|
warnings.forEach((warning: Warning) => {
|
||||||
|
if (warning.line_number) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const refresh_html = () => {
|
||||||
|
let parsed: ParseResult = parse_md_to_html_with_warnings(editor.innerText);
|
||||||
|
render_warnings(parsed.warnings);
|
||||||
|
preview.innerHTML = parsed.html;
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.addEventListener("keyup", refresh_html);
|
||||||
|
document.addEventListener("click", (e: MouseEvent) => {
|
||||||
|
if (e.target === editor && unedited) {
|
||||||
|
(editor.children[0] as HTMLElement).innerText = "";
|
||||||
|
unedited = false;
|
||||||
|
refresh_html();
|
||||||
|
} else if (e.target !== editor && editor.innerText.trim() === "") {
|
||||||
|
(editor.children[0] as HTMLElement).innerText = "markdown goes here...";
|
||||||
|
unedited = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const theme_change = () => {
|
||||||
|
if (dark_theme_toggle.checked) {
|
||||||
|
preview.classList.add("dark");
|
||||||
|
} else {
|
||||||
|
preview.classList.remove("dark");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dark_theme_toggle.addEventListener("change", theme_change);
|
||||||
|
|
||||||
|
refresh_html();
|
||||||
|
theme_change();
|
||||||
|
|
||||||
|
if (editor.innerText !== "markdown goes here...") {
|
||||||
|
unedited = false;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user