# HG changeset patch # User MrJuneJune # Date 1768872798 28800 # Node ID 295ac2e5ec00f61f4e328c3122cc7111b00f9623 # Parent f3084bca7317c5f954aa9bc3d6eee522fc42b045 [MrJuneJune] Created separate target for generating html from md. diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/BUILD --- a/mrjunejune/BUILD Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/BUILD Mon Jan 19 17:33:18 2026 -0800 @@ -56,6 +56,17 @@ data = [":src_files"], ) +# Run this to create html files +cc_binary( + name = "create_html_from_md", + srcs = ["create_html_from_md.c"], + deps = [ + "//markdown_converter:markdown_to_html_c", + "//dowa:dowa" + ], + data = [":src_files"], +) + # Release bundle bundle( name = "mrjunejune_server_bundle", @@ -66,26 +77,3 @@ name = "mrjunejune_server_debug_bundle", binary = ":mrjunejune_server_debug", ) - -# Experimenting with python to see if I can call it as ffi. -# load("@rules_python//python:py_binary.bzl", "py_binary") -# This was to use python ffi, but w/e -# cc_library( -# name = "mrjunejune_server_lib", -# srcs = ["server_entry.c"], -# deps = ["//seobeo:seobeo_server"], -# linkstatic = False, -# visibility = ["//visibility:public"], -# ) - -# py_binary( -# name = "python_server", -# srcs = ["python_server.py"], -# deps = [ -# ":mrjunejune_server_lib", -# "@pip_deps//:cffi", -# ], -# data = [":mrjunejune_server_lib"], -# ) - - diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/create_html_from_md.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mrjunejune/create_html_from_md.c Mon Jan 19 17:33:18 2026 -0800 @@ -0,0 +1,147 @@ +#include "markdown_converter/markdown_to_html.h" +#include "dowa/dowa.h" +#include + +#define BLOG_PATH "/home/june/zenbu/mrjunejune/src/blog/" +#define BLOG_HTML "" \ +"" \ +"" \ +" " \ +" " \ +" " \ +" %s - June's Blog" \ +" {{/parts/base_head.html}}" \ +" " \ +" " \ +" " \ +"" \ +"" \ +" {{/parts/header.html}}" \ +"
" \ +"%s" \ +"
" \ +" {{/parts/footer.html}}" \ +" "\ +"" + + +typedef struct { + char title[256]; + char description[512]; + char *content; // markdown content after frontmatter +} Blog_Metadata; + +// Parse frontmatter from markdown content +// Expected format: +// --- +// title: My Title +// description: My description +// --- +// markdown +static Blog_Metadata Parse_Blog_Frontmatter(const char *md_content) +{ + Blog_Metadata meta = {0}; + strcpy(meta.title, "Untitled"); + strcpy(meta.description, "A blog post by June"); + meta.content = (char *)md_content; + + if (!md_content) return meta; + + if (strncmp(md_content, "---", 3) != 0) + return meta; + + const char *end_delim = strstr(md_content + 3, "\n---"); + if (!end_delim) + return meta; + + const char *cursor = md_content + 4; // skip "---\n" + while (cursor < end_delim) + { + // whitespaces + while (cursor < end_delim && (*cursor == ' ' || *cursor == '\t')) cursor++; + + const char *line_end = cursor; + while (line_end < end_delim && *line_end != '\n') line_end++; + + const char *colon = cursor; + while (colon < line_end && *colon != ':') colon++; + + if (colon < line_end) { + size_t key_len = colon - cursor; + const char *value_start = colon + 1; + while (value_start < line_end && (*value_start == ' ' || *value_start == '\t')) value_start++; + size_t value_len = line_end - value_start; + + if (key_len == 5 && strncmp(cursor, "title", 5) == 0) + { + size_t copy_len = value_len < sizeof(meta.title) - 1 ? value_len : sizeof(meta.title) - 1; + strncpy(meta.title, value_start, copy_len); + meta.title[copy_len] = '\0'; + } + else if (key_len == 11 && strncmp(cursor, "description", 11) == 0) + { + size_t copy_len = value_len < sizeof(meta.description) - 1 ? value_len : sizeof(meta.description) - 1; + strncpy(meta.description, value_start, copy_len); + meta.description[copy_len] = '\0'; + } + } + + cursor = line_end + 1; + } + + meta.content = (char *)(end_delim + 4); + if (*meta.content == '\n') meta.content++; + + return meta; +} + +int main() +{ + Dowa_Arena *arena = Dowa_Arena_Create(1024 * 1024 * 5); + size_t buffer_sizes = 100 * 1024; + + char *files[] = { + BLOG_PATH"thoughts-on-ide/index.md", + BLOG_PATH"multithread-in-js/index.md", + BLOG_PATH"thoughts-on-tdd/index.md", + BLOG_PATH"my-seobeo-journey/index.md", + BLOG_PATH"wasm-bunny/index.md", + BLOG_PATH"optimizing-data-structures/index.md", + BLOG_PATH"websocket-demystified/index.md", + BLOG_PATH"optimizing-grass-rendering/index.md", + BLOG_PATH"wsl2-ssh/index.md" + }; + + for (int i = 0; i < 9; i++) + { + char *md_file_path = files[i]; + char *md_file = Dowa_Arena_Allocate(arena, buffer_sizes); + + FILE *file = fopen(md_file_path, "ro"); + fseek(file, 0, SEEK_END); + size_t file_length = ftell(file); + fseek(file, 0, SEEK_SET); + fread(md_file, 1, file_length, file); + + Blog_Metadata meta = Parse_Blog_Frontmatter(md_file); + char *md = markdown_to_html(meta.content); + char *ssr_body = Dowa_Arena_Allocate(arena, buffer_sizes); + char *final_body = Dowa_Arena_Allocate(arena, buffer_sizes); + snprintf(ssr_body, buffer_sizes, BLOG_HTML, meta.description, meta.title, md); + + int open_flags = O_RDWR | O_CREAT | O_EXCL; + size_t md_file_path_length = strlen(md_file_path); + md_file_path_length -= 3; // html + char *new_file_path = Dowa_Arena_Allocate(arena, 1024); + snprintf(new_file_path, 1024, "%.*s.html", (int)md_file_path_length, md_file_path); + + FILE *new_file_fd = fopen(new_file_path, "w+"); + if (!new_file_fd) + return; + printf("Saving to %s...\n", new_file_path); + fwrite(ssr_body, 1, buffer_sizes, new_file_fd); + fclose(new_file_fd); + } + return 0; +} + diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/main.c --- a/mrjunejune/main.c Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/main.c Mon Jan 19 17:33:18 2026 -0800 @@ -1,4 +1,3 @@ -// Debug mode is now controlled by build target: use //seobeo:seobeo_tcp_server_ws_debug #include "seobeo/seobeo.h" #include "markdown_converter/markdown_to_html.h" #include @@ -6,25 +5,6 @@ // UUID + /tmp/ + format (max 4) #define TMP_FILE_LENGTH 47 #define UUID_LEN 37 -#define BLOG_HTML "" \ -"" \ -"" \ -" " \ -" " \ -" Multi Threading in JS" \ -" {{/parts/base_head.html}}" \ -" " \ -" " \ -" " \ -"" \ -"" \ -" {{/parts/header.html}}" \ -"
" \ -"%s" \ -"
" \ -" {{/parts/footer.html}}" \ -" "\ -"" volatile sig_atomic_t stop_server = 0; static _Atomic uint32_t counter = 0; @@ -457,7 +437,6 @@ printf("DEBUG: Served and deleted file: %s (%zu bytes)\n", filename, file_size); - // Set proper Content-Length for binary data char *content_length = Dowa_Arena_Allocate(arena, 32); snprintf(content_length, 32, "%zu", file_size); @@ -481,33 +460,15 @@ Seobeo_Request_Entry *RenderBlog(Seobeo_Request_Entry *req, Dowa_Arena *arena) { - Seobeo_Log(SEOBEO_DEBUG, "[CURR], Blog\n"); Seobeo_Request_Entry *resp = NULL; + char *file_path = Dowa_Arena_Allocate(arena, 1024); void *blog_id_kv = Dowa_HashMap_Get_Ptr(req, ":blog_id"); - if (!blog_id_kv) - { - char *error_msg = "No Blog Id"; - Dowa_HashMap_Push_Arena(resp, "status", "404", arena); - Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena); - Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena); - return resp; - } + char *blog_id = ((Seobeo_Request_Entry*)blog_id_kv)->value; + snprintf(file_path, 1024, "/blog/%s/index.html", blog_id); - const char *blog_id = ((Seobeo_Request_Entry *)blog_id_kv)->value; - char *md_path = Dowa_Arena_Allocate(arena, 512); - sprintf(md_path, "/blog/%s/index.md", blog_id); - - size_t md_file_size = 0; - char *md_file = Seobeo_Web_LoadFile(md_path, &md_file_size); - - char *md = markdown_to_html(md_file); - size_t buffer_sizes = 100 * 1024; // TODO: Think about the sizes - char *ssr_body = Dowa_Arena_Allocate(arena, buffer_sizes); - char *final_body = Dowa_Arena_Allocate(arena, buffer_sizes); - - snprintf(ssr_body, 100*1024, BLOG_HTML, md); - Seobeo_Render_Html(final_body, ssr_body, arena); + char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024); + Seobeo_Render_Html_FilePath(final_body, file_path, arena); Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); return resp; } diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/multithread-in-js/index.html Binary file mrjunejune/src/blog/multithread-in-js/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/multithread-in-js/index.md --- a/mrjunejune/src/blog/multithread-in-js/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/multithread-in-js/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,3 +1,8 @@ +--- +title: Multithreading in JavaScript +description: Exploring how JavaScript evolved from single-threaded to supporting Worker Threads, with a practical example calculating prime numbers. +--- + # Multithreading in JavaScript I recently discussed various programming languages and their advantages with my new coworkers at Meta. During our conversation, we debated the topic of multithreading in JavaScript. My stance was that multithreading became possible in Node.js after certain versions, while my coworker believed it wasn't feasible due to JavaScript's original design. This led me to delve deeper into the topic and provide some code examples. diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/my-seobeo-journey/index.html Binary file mrjunejune/src/blog/my-seobeo-journey/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/my-seobeo-journey/index.md --- a/mrjunejune/src/blog/my-seobeo-journey/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/my-seobeo-journey/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,6 +1,11 @@ +--- +title: Creating Network Library in C +description: Building seobeo, a lightweight network library in C from scratch, exploring socket programming and web server development. +--- + # Creating Network Library in C -I’m so tired of modern web development. You want to spin up a simple web server, and suddenly you’re wrestling with a mountain of dependencies. Express, Fastify, whatever the flavor of the week is. They all promise simplicity, but dump a black hole of `node_modules` onto your machine. Have you ever actually looked inside? It’s insane. And all of them use React, Svelte, or whatever the current trend is for modern development. One time, I created a single React file using Bun and it had over 18k lines of JavaScript code lmao. And for what? To handle a simple HTTP request for a text file? +I'm so tired of modern web development. You want to spin up a simple web server, and suddenly you’re wrestling with a mountain of dependencies. Express, Fastify, whatever the flavor of the week is. They all promise simplicity, but dump a black hole of `node_modules` onto your machine. Have you ever actually looked inside? It’s insane. And all of them use React, Svelte, or whatever the current trend is for modern development. One time, I created a single React file using Bun and it had over 18k lines of JavaScript code lmao. And for what? To handle a simple HTTP request for a text file? diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/optimizing-data-structures/index.html Binary file mrjunejune/src/blog/optimizing-data-structures/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/optimizing-data-structures/index.md --- a/mrjunejune/src/blog/optimizing-data-structures/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/optimizing-data-structures/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,3 +1,8 @@ +--- +title: Optimizing Data Structures for Performance +description: Understanding how memory layout affects cache performance in C++ games, with examples of pointer indirection and contiguous data structures. +--- + ### Optimizing Data Structures for Performance In my professional experience as a full-stack engineer, I primarily work with languages like Python, JavaScript, and Ruby, which don’t provide strict control over memory management. Contract work requiring languages like C or C++ is rare, as most clients prefer "modern" languages that prioritize ease of use over low-level control. Even on the few occasions when I did write C or C++ code, my focus was not on performance optimization. However, I recently observed some C++ code that changed my perspective. diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/optimizing-grass-rendering/index.html Binary file mrjunejune/src/blog/optimizing-grass-rendering/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/optimizing-grass-rendering/index.md --- a/mrjunejune/src/blog/optimizing-grass-rendering/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/optimizing-grass-rendering/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,3 +1,8 @@ +--- +title: Optimizing Random Placement with Colour Noise +description: Comparing white noise and blue noise for natural object placement in game development, with optimization techniques for real-time rendering. +--- + # Optimizing Random Placement with Colour Noise ### Introduction diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/thoughts-on-ide/index.html Binary file mrjunejune/src/blog/thoughts-on-ide/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/thoughts-on-ide/index.md --- a/mrjunejune/src/blog/thoughts-on-ide/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/thoughts-on-ide/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,3 +1,8 @@ +--- +title: Thoughts on IDE +description: A reflection on modern IDE bloat, terminal proficiency, and why understanding the tools behind the buttons matters for developers. +--- + # Thoughts on IDE IDEs are crucial tools for developers. They are like a knife to a chef, a stethoscope to a doctor, or a pair of nice shoes to a basketball player. These tools significantly improve quality of life and directly impact how efficiently someone can work. That being said, they are not necessities. A chef can still cook with a dull knife, a doctor can diagnose with some degree of accuracy without a stethoscope, and LeBron will still dunk on you in office shoes. diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/thoughts-on-tdd/index.html Binary file mrjunejune/src/blog/thoughts-on-tdd/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/thoughts-on-tdd/index.md --- a/mrjunejune/src/blog/thoughts-on-tdd/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/thoughts-on-tdd/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,3 +1,8 @@ +--- +title: Thoughts on TDD +description: Examining Test-Driven Development practices, unit testing debates, and the challenges of implementing TDD effectively in real-world projects. +--- + # Thoughts on TDD Is testing important? Ask yourself that question. If you had to think about it for more than a few seconds, you’re either an inexperienced programmer or someone who has never had to release a product to a large group of users. Testing is not just important—it’s essential. It ensures that the software you release is less buggy and more stable because it allows you to catch issues before your customers do. That’s the "why" behind testing that everyone would agree to. diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/wasm-bunny/index.html Binary file mrjunejune/src/blog/wasm-bunny/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/wasm-bunny/index.md --- a/mrjunejune/src/blog/wasm-bunny/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/wasm-bunny/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,3 +1,8 @@ +--- +title: First Steps with C3 and Raylib on WebAssembly +description: Experimenting with C3 programming language and Raylib to build an interactive bunnymark benchmark compiled to WebAssembly. +--- + # First Steps with C3 and Raylib on WebAssembly Hi! This is my first blog post on this website, and hopefully, it’s the first of many, as I have some free time at the moment. diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/websocket-demystified/index.html Binary file mrjunejune/src/blog/websocket-demystified/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/websocket-demystified/index.md --- a/mrjunejune/src/blog/websocket-demystified/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/websocket-demystified/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,3 +1,8 @@ +--- +title: WebSocket Demystified +description: A deep dive into WebSocket internals, debunking the 65535 port myth and building a WebSocket implementation from scratch. +--- + # WebSocket Demystified WebSockets have been around for more than 10 years now. The [RFC 6455](https://www.rfc-editor.org/rfc/rfc6455) was dropped way back in 2011. This was inevitable. As apps got more complex, people wanted real bidirectional communication without resorting to hacky solutions like raw TCP connections with custom keys or the constant overhead of short/long polling. diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/wsl2-ssh/index.html Binary file mrjunejune/src/blog/wsl2-ssh/index.html has changed diff -r f3084bca7317 -r 295ac2e5ec00 mrjunejune/src/blog/wsl2-ssh/index.md --- a/mrjunejune/src/blog/wsl2-ssh/index.md Mon Jan 19 16:29:02 2026 -0800 +++ b/mrjunejune/src/blog/wsl2-ssh/index.md Mon Jan 19 17:33:18 2026 -0800 @@ -1,3 +1,7 @@ +--- +title: Build Your Own Cloudtop with WSL2 and SSH +description: A step-by-step guide to setting up SSH access to WSL2 from anywhere, including DNS, port forwarding, and dynamic DNS configuration. +--- Sorry for going MIA. I hadn’t had any programming-related ideas worth sharing lately, and nothing I wrote in my free time felt ready. But recently, something sparked my interest.