Mercurial
changeset 64:a30944e5719e
Added vibe coded markdown to html script since it is useful for me. Updated Dowa so that it can be compiled without dirnet for windows.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Tue, 23 Dec 2025 15:18:46 -0800 |
| parents | fff1b048dda6 |
| children | ecb6ee6a22c3 |
| files | dowa/BUILD dowa/d_memory.c dowa/dowa.h dowa/dowa_test.c gui_ze/gui_ze.bzl markdown_converter/BUILD markdown_converter/main.js markdown_converter/markdown_to_html.js mrjunejune/BUILD mrjunejune/pages/markdown_to_html/index.html seobeo/seobeo.h seobeo/seobeo_internal.h |
| diffstat | 12 files changed, 577 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/dowa/BUILD Tue Dec 23 14:00:37 2025 -0800 +++ b/dowa/BUILD Tue Dec 23 15:18:46 2025 -0800 @@ -1,6 +1,19 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library") load("@rules_cc//cc:cc_test.bzl", "cc_test") +# TODO: Fix so that we can just define in the header instead of defining in the cc_library because this is ass. +cc_library( + name = "dowa_generic", + srcs = [ + "d_string.c", + "d_memory.c", + ], + hdrs = [ + "dowa.h", + "dowa_internal.h" + ], + visibility = ["//visibility:public"], +) cc_library( name = "dowa", @@ -12,6 +25,7 @@ "dowa.h", "dowa_internal.h" ], + copts = ["-DDIRECTORY"], visibility = ["//visibility:public"], )
--- a/dowa/d_memory.c Tue Dec 23 14:00:37 2025 -0800 +++ b/dowa/d_memory.c Tue Dec 23 15:18:46 2025 -0800 @@ -474,6 +474,7 @@ printf("-----------\n"); } +#ifdef DIRECTORY int Dowa_HashMap_Cache_Folder(Dowa_PHashMap p_hash_map, const char *folder_path) { if (!p_hash_map || !folder_path) @@ -503,12 +504,12 @@ FILE *f = fopen(fullpath, "rb"); if (!f) { perror("fopen"); continue; } + // Allocate exact file size (no extra byte for null terminator) void *buf = p_hash_map->p_arena ? - Dowa_Arena_Allocate(p_hash_map->p_arena, size + 1) : - malloc(size + 1); + Dowa_Arena_Allocate(p_hash_map->p_arena, size) : + malloc(size); if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; } - if (fread(buf, 1, size, f) != size) { perror("fread"); @@ -518,8 +519,8 @@ } fclose(f); - ((char *)buf)[size] = '\0'; - Dowa_HashMap_Push_Value_With_Type(p_hash_map, entry->d_name, buf, size + 1, DOWA_HASH_MAP_TYPE_STRING); + // Store file data as-is without null terminator (for binary files like images) + Dowa_HashMap_Push_Value_With_Type(p_hash_map, entry->d_name, buf, size, DOWA_HASH_MAP_TYPE_STRING); if (!p_hash_map->p_arena) Dowa_Free(buf); // Dowa_HashMap_PushValue made its own copy } @@ -550,3 +551,4 @@ closedir(dir); return 0; } +#endif
--- a/dowa/dowa.h Tue Dec 23 14:00:37 2025 -0800 +++ b/dowa/dowa.h Tue Dec 23 15:18:46 2025 -0800 @@ -11,6 +11,7 @@ // Maybe move this into seobeo file directly? #include <dirent.h> // some functions loop through files #endif + #include <math.h> // I am not re-writing stuff I guess... #include <sys/stat.h> @@ -119,8 +120,10 @@ // --- Utility Functions --- // /* Prints all entries in the hashmap to stdout for debugging purposes. */ extern void Dowa_HashMap_Print(Dowa_PHashMap map); +#ifdef DIRECTORY /* Loads all files from the specified folder into the hashmap. Uses file names as keys and file contents as values. Returns 0 on success, or -1 on failure. */ extern int Dowa_HashMap_Cache_Folder(Dowa_PHashMap map, const char *folder_path); +#endif #endif
--- a/dowa/dowa_test.c Tue Dec 23 14:00:37 2025 -0800 +++ b/dowa/dowa_test.c Tue Dec 23 15:18:46 2025 -0800 @@ -2,6 +2,7 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#define DIRECTORY #include "dowa.h" int main(void)
--- a/gui_ze/gui_ze.bzl Tue Dec 23 14:00:37 2025 -0800 +++ b/gui_ze/gui_ze.bzl Tue Dec 23 15:18:46 2025 -0800 @@ -143,13 +143,17 @@ def _move_files_into_dir_impl(ctx): srcs = ctx.files.srcs + outs = [] for src in srcs: out = ctx.actions.declare_file(ctx.attr.dest + "/" + src.basename) - ctx.actions.symlink( - output = out, - target_file = src, + ctx.actions.run_shell( + inputs = [src], + outputs = [out], + command = "cp \"$1\" \"$2\"", + arguments = [src.path, out.path], ) - return [DefaultInfo(files = depset([out]))] + outs.append(out) + return [DefaultInfo(files = depset(outs))] move_files_into_dir = rule( implementation = _move_files_into_dir_impl,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/markdown_converter/BUILD Tue Dec 23 15:18:46 2025 -0800 @@ -0,0 +1,9 @@ +filegroup( + name = "markdown_to_html", + srcs = glob([ + "**/*.js", + ], allow_empty=True), + visibility = ["//visibility:public"], +) + +
--- a/markdown_converter/main.js Tue Dec 23 14:00:37 2025 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -// # -// ## -// []() -// _ _ -// * * -// 1. -// - -// \s\s -// - -function Lexer(character) { -} - -/** - * @params - * value: string - */ -function mardownConverter(value) { - let i = 0; - let character; - const domElements = []; - while (i < value.length) { - character = value[i] - switch(character) { - case "#": { - if - const dom = document.createElement("h1"); - domElements.append(dom) - } - case "_": { - } - case "_" { - } - case "*" { - } - default { - return character; - } - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/markdown_converter/markdown_to_html.js Tue Dec 23 15:18:46 2025 -0800 @@ -0,0 +1,269 @@ +/** + * Simple Markdown to HTML Converter + * Supports: headers, bold, italic, links, lists, code blocks, line breaks + */ + +/** + * Create heading element (H1-H6) + * @param {string} text - The heading text + * @param {number} level - Heading level (1-6) + * @returns {HTMLElement} + */ +function createHeadingElement(text, level) { + const h = document.createElement(`H${level}`); + const t = document.createTextNode(text.trim()); + h.appendChild(t); + return h; +} + +/** + * Create paragraph element + * @param {string} text - The paragraph text + * @returns {HTMLElement} + */ +function createParagraphElement(text) { + const p = document.createElement("P"); + p.innerHTML = processInlineMarkdown(text.trim()); + return p; +} + +/** + * Create link element + * @param {string} text - Link text + * @param {string} url - Link URL + * @returns {HTMLElement} + */ +function createLinkElement(text, url) { + const a = document.createElement("A"); + a.href = url; + a.textContent = text; + return a; +} + +/** + * Create unordered list element + * @param {Array<string>} items - List items + * @returns {HTMLElement} + */ +function createUnorderedList(items) { + const ul = document.createElement("UL"); + items.forEach(item => { + const li = document.createElement("LI"); + li.innerHTML = processInlineMarkdown(item.trim()); + ul.appendChild(li); + }); + return ul; +} + +/** + * Create ordered list element + * @param {Array<string>} items - List items + * @returns {HTMLElement} + */ +function createOrderedList(items) { + const ol = document.createElement("OL"); + items.forEach(item => { + const li = document.createElement("LI"); + li.innerHTML = processInlineMarkdown(item.trim()); + ol.appendChild(li); + }); + return ol; +} + +/** + * Create code block element + * @param {string} code - Code content + * @returns {HTMLElement} + */ +function createCodeBlock(code) { + const pre = document.createElement("PRE"); + const codeEl = document.createElement("CODE"); + codeEl.textContent = code; + pre.appendChild(codeEl); + return pre; +} + +/** + * Create blockquote element + * @param {string} text - Quote text + * @returns {HTMLElement} + */ +function createBlockquote(text) { + const blockquote = document.createElement("BLOCKQUOTE"); + blockquote.innerHTML = processInlineMarkdown(text.trim()); + return blockquote; +} + +/** + * Create horizontal rule + * @returns {HTMLElement} + */ +function createHorizontalRule() { + return document.createElement("HR"); +} + +/** + * Process inline markdown (bold, italic, code, links) + * @param {string} text - Text with inline markdown + * @returns {string} HTML string + */ +function processInlineMarkdown(text) { + // Links: [text](url) + text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>'); + + // Images:  + text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1">'); + + // Bold: **text** or __text__ + text = text.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>'); + text = text.replace(/__([^_]+)__/g, '<strong>$1</strong>'); + + // Italic: *text* or _text_ + text = text.replace(/\*([^*]+)\*/g, '<em>$1</em>'); + text = text.replace(/_([^_]+)_/g, '<em>$1</em>'); + + // Inline code: `code` + const x = /`([^`]+)`/g; + text = text.replace(x, '<code>$1</code>'); + + // Strikethrough: ~~text~~ + text = text.replace(/~~([^~]+)~~/g, '<del>$1</del>'); + + // Line breaks: two spaces at end of line + text = text.replace(/ \n/g, '<br>\n'); + + return text; +} + +/** + * Main markdown converter function + * @param {string} value - Markdown string + * @returns {Array<HTMLElement>} Array of DOM elements + */ +function markdownConverter(value) { + const lines = value.split('\n'); + const domElements = []; + let i = 0; + + while (i < lines.length) { + const line = lines[i]; + const trimmedLine = line.trim(); + + // Skip empty lines + if (trimmedLine === '') { + i++; + continue; + } + + if (trimmedLine.startsWith('#')) + { + const match = trimmedLine.match(/^(#{1,6})\s+(.+)$/); + if (match) { + const level = match[1].length; + const text = match[2]; + domElements.push(createHeadingElement(text, level)); + i++; + continue; + } + } + + if (trimmedLine.startsWith('```')) { + let codeContent = ''; + i++; // Skip opening ``` + while (i < lines.length && !lines[i].trim().startsWith('```')) { + codeContent += lines[i] + '\n'; + i++; + } + domElements.push(createCodeBlock(codeContent)); + i++; // Skip closing ``` + continue; + } + + // Blockquote: > + if (trimmedLine.startsWith('>')) { + let quoteContent = ''; + while (i < lines.length && lines[i].trim().startsWith('>')) { + quoteContent += lines[i].trim().substring(1).trim() + ' '; + i++; + } + domElements.push(createBlockquote(quoteContent)); + continue; + } + + // Horizontal rule: ---, ***, ___ + if (trimmedLine.match(/^(-{3,}|\*{3,}|_{3,})$/)) { + domElements.push(createHorizontalRule()); + i++; + continue; + } + + // Unordered list: -, *, + + if (trimmedLine.match(/^[-*+]\s+/)) { + const listItems = []; + while (i < lines.length && lines[i].trim().match(/^[-*+]\s+/)) { + listItems.push(lines[i].trim().substring(2)); + i++; + } + domElements.push(createUnorderedList(listItems)); + continue; + } + + // Ordered list: 1., 2., etc. + if (trimmedLine.match(/^\d+\.\s+/)) { + const listItems = []; + while (i < lines.length && lines[i].trim().match(/^\d+\.\s+/)) { + listItems.push(lines[i].trim().replace(/^\d+\.\s+/, '')); + i++; + } + domElements.push(createOrderedList(listItems)); + continue; + } + + // Regular paragraph + let paragraphContent = ''; + while (i < lines.length && lines[i].trim() !== '' && + !lines[i].trim().match(/^(#{1,6}\s|[-*+]\s|\d+\.\s|>|```|---|\*\*\*|___)/)) { + paragraphContent += lines[i] + ' '; + i++; + } + if (paragraphContent.trim()) { + domElements.push(createParagraphElement(paragraphContent)); + } + } + + return domElements; +} + +/** + * Helper function to append all elements to a container + * @param {HTMLElement} container - Container element + * @param {string} markdown - Markdown string + */ +function renderMarkdown(container, markdown) { + const elements = markdownConverter(markdown); + elements.forEach(el => container.appendChild(el)); +} + +// Example usage: +// const markdown = ` +// # Heading 1 +// ## Heading 2 +// +// This is a paragraph with **bold** and *italic* text. +// +// - List item 1 +// - List item 2 +// +// 1. Ordered item 1 +// 2. Ordered item 2 +// +// [Link text](https://example.com) +// `; +// +// const container = document.getElementById('content'); +// renderMarkdown(container, markdown); + +// Export for use in other files +if (typeof module !== 'undefined' && module.exports) { + module.exports = { markdownConverter, renderMarkdown }; +}
--- a/mrjunejune/BUILD Tue Dec 23 14:00:37 2025 -0800 +++ b/mrjunejune/BUILD Tue Dec 23 15:18:46 2025 -0800 @@ -7,6 +7,7 @@ name = "compiled_ts", srcs = [ "//playground:hello", + "//markdown_converter:markdown_to_html" ], dest = "pages", )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mrjunejune/pages/markdown_to_html/index.html Tue Dec 23 15:18:46 2025 -0800 @@ -0,0 +1,257 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Markdown to HTML Converter</title> + <style> + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + line-height: 1.6; + padding: 20px; + max-width: 1200px; + margin: 0 auto; + background: #f5f5f5; + } + + .container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; + margin-top: 20px; + } + + .panel { + background: white; + border-radius: 8px; + padding: 20px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + } + + h1 { + color: #333; + margin-bottom: 20px; + } + + textarea { + width: 100%; + height: 500px; + padding: 15px; + border: 1px solid #ddd; + border-radius: 4px; + font-family: 'Courier New', monospace; + font-size: 14px; + resize: vertical; + } + + #output { + min-height: 500px; + padding: 15px; + border: 1px solid #ddd; + border-radius: 4px; + background: #fafafa; + } + + #output h1, #output h2, #output h3, #output h4, #output h5, #output h6 { + margin: 20px 0 10px 0; + color: #333; + } + + #output h1 { font-size: 2em; } + #output h2 { font-size: 1.5em; } + #output h3 { font-size: 1.3em; } + + #output p { + margin: 10px 0; + } + + #output ul, #output ol { + margin: 10px 0; + padding-left: 30px; + } + + #output li { + margin: 5px 0; + } + + #output code { + background: #f4f4f4; + padding: 2px 6px; + border-radius: 3px; + font-family: 'Courier New', monospace; + font-size: 0.9em; + } + + #output pre { + background: #282c34; + color: #abb2bf; + padding: 15px; + border-radius: 4px; + overflow-x: auto; + margin: 10px 0; + } + + #output pre code { + background: none; + color: inherit; + padding: 0; + } + + #output blockquote { + border-left: 4px solid #ddd; + padding-left: 15px; + margin: 10px 0; + color: #666; + font-style: italic; + } + + #output a { + color: #0066cc; + text-decoration: none; + } + + #output a:hover { + text-decoration: underline; + } + + #output hr { + border: none; + border-top: 2px solid #ddd; + margin: 20px 0; + } + + #output img { + max-width: 100%; + height: auto; + } + + #output strong { + font-weight: bold; + } + + #output em { + font-style: italic; + } + + #output del { + text-decoration: line-through; + } + + button { + background: #0066cc; + color: white; + border: none; + padding: 10px 20px; + border-radius: 4px; + cursor: pointer; + font-size: 16px; + margin-top: 10px; + } + + button:hover { + background: #0052a3; + } + + .header { + text-align: center; + margin-bottom: 30px; + } + + .label { + font-weight: bold; + margin-bottom: 10px; + color: #555; + } + + @media (max-width: 768px) { + .container { + grid-template-columns: 1fr; + } + } + </style> +</head> +<body> + <div class="header"> + <h1>Markdown to HTML Converter</h1> + </div> + + <div class="container"> + <div class="panel"> + <div class="label">Markdown Input</div> + <textarea id="input" placeholder="Type your markdown here..."># Welcome to Markdown Converter + +## Features + +This converter supports: + +- **Bold text** and *italic text* +- [Links](https://example.com) +- `inline code` +- ~~strikethrough~~ + +### Lists + +1. Ordered lists +2. Like this one +3. With numbers + +- Unordered lists +- Use dashes +- Or asterisks + +### Code Blocks + +``` +function example() { + return "Hello World"; +} +``` + +### Blockquotes + +> This is a blockquote +> It can span multiple lines + +--- + +### Images + + + +**Try editing this text!**</textarea> + </div> + + <div class="panel"> + <div class="label">HTML Output</div> + <div id="output"></div> + </div> + </div> + + <script src="/markdown_to_html.js"></script> + <script> + const input = document.getElementById('input'); + const output = document.getElementById('output'); + + function convert() { + // Clear previous output + output.innerHTML = ''; + + // Convert and render + const markdown = input.value; + renderMarkdown(output, markdown); + } + + // Convert on input + input.addEventListener('input', convert); + + // Initial conversion + convert(); + </script> +</body> +</html>
--- a/seobeo/seobeo.h Tue Dec 23 14:00:37 2025 -0800 +++ b/seobeo/seobeo.h Tue Dec 23 15:18:46 2025 -0800 @@ -8,6 +8,11 @@ * Library for starting TCP, UDP server and serving static file or path. */ +// Define DIRECTORY before any includes to enable directory operations in dowa.h +#ifndef DIRECTORY +#define DIRECTORY +#endif + #include <stdio.h> #include <stdlib.h> #include <unistd.h>