Mercurial
diff mrjunejune/main.c @ 273:e02e2036ef84 default tip
add Layer 2 JRPG component system
Add reusable content and window modals, an isolated component sandbox, shared cyberpunk scroll areas, production-safe cache freshness, and server-rendered JRPG panel state.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Sat, 08 Aug 2026 02:08:08 -0700 |
| parents | 056790c4fb0d |
| children |
line wrap: on
line diff
--- a/mrjunejune/main.c Fri Aug 07 16:05:29 2026 -0700 +++ b/mrjunejune/main.c Sat Aug 08 02:08:08 2026 -0700 @@ -1214,12 +1214,145 @@ return resp; } +typedef struct { + const char *name; + const char *title; + const char *copy; + const char *works; +} Jrpg_Initial_Panel; + +static boolean Mjj_Replace_All( + char *buffer, + size_t capacity, + const char *needle, + const char *replacement) +{ + if (!buffer || !needle || !replacement || needle[0] == '\0') + return FALSE; + + size_t needle_length = strlen(needle); + size_t replacement_length = strlen(replacement); + char *match = strstr(buffer, needle); + while (match) + { + size_t current_length = strlen(buffer); + size_t offset = (size_t)(match - buffer); + size_t new_length = + current_length - needle_length + replacement_length; + if (new_length >= capacity) + return FALSE; + + memmove( + match + replacement_length, + match + needle_length, + current_length - offset - needle_length + 1); + memcpy(match, replacement, replacement_length); + match = strstr(match + replacement_length, needle); + } + return TRUE; +} + +static const Jrpg_Initial_Panel *Jrpg_Resolve_Initial_Panel( + Seobeo_Request_Entry *req) +{ + static const Jrpg_Initial_Panel panels[] = { + { + "resume", + "Resume", + "Member of Technical Staff and engineering leader with 10+ years " + "building AI agent platforms and production systems across Microsoft, " + "Meta, Google, and growth-stage companies.", + "<li><a href=\"/resume\" data-resume-modal>" + "<span>Full resume</span><small>Career dossier</small></a></li>" + "<li><a href=\"https://www.microsoft.com/en-us/microsoft-copilot/blog/" + "2026/02/26/copilot-tasks-from-answers-to-actions/\">" + "<span>Copilot Tasks</span><small>Agentic execution</small></a></li>" + }, + { + "tools", + "Tools", + "Useful browser tools backed by first-party C, WASM, media, and " + "document-processing systems.", + "<li><a href=\"/tools/markdown_to_html\" data-latest-tool " + "data-tool-url=\"/tools/markdown_to_html\">" + "<span>Markdown</span><small>Writing</small></a></li>" + "<li><a href=\"/tools/file_converter\" data-latest-tool " + "data-tool-url=\"/tools/file_converter\">" + "<span>Converter</span><small>Media</small></a></li>" + "<li><a href=\"/tools/hls_player\" data-latest-tool " + "data-tool-url=\"/tools/hls_player\">" + "<span>HLS Player</span><small>Streaming</small></a></li>" + }, + { + "blog", + "Blogs", + "Technical writing about networking, rendering, performance, developer " + "tooling, and experiments.", + "<li><a href=\"/blog\" data-blog-archive>" + "<span>All posts</span><small>Archive</small></a></li>" + }, + { + "conversations", + "Resume", + "", + "" + }, + }; + + const char *requested = NULL; + void *panel_kv = Dowa_HashMap_Get_Ptr(req, "query_panel"); + if (panel_kv) + requested = ((Seobeo_Request_Entry *)panel_kv)->value; + + for (size_t i = 0; i < sizeof(panels) / sizeof(panels[0]); ++i) + { + if (requested && strcmp(requested, panels[i].name) == 0) + return &panels[i]; + } + return &panels[0]; +} + Seobeo_Request_Entry *GetJrpg(Seobeo_Request_Entry *req, Dowa_Arena *arena) { Seobeo_Request_Entry *resp = NULL; char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP); if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/jrpg/index.html", arena)) return html_render_error(arena, "Internal Server Error"); + + const Jrpg_Initial_Panel *panel = Jrpg_Resolve_Initial_Panel(req); + boolean conversations = + strcmp(panel->name, "conversations") == 0 ? TRUE : FALSE; + const char *preview_selection = conversations ? "resume" : panel->name; + struct { + const char *token; + const char *value; + } replacements[] = { + {"__MJJ_PANEL__", panel->name}, + {"__MJJ_PREVIEW_SELECTION__", preview_selection}, + {"__MJJ_PREVIEW_TITLE__", panel->title}, + {"__MJJ_PREVIEW_COPY__", panel->copy}, + {"__MJJ_PREVIEW_WORKS__", panel->works}, + {"__MJJ_PREVIEW_HIDDEN__", conversations ? "hidden" : ""}, + {"__MJJ_ARCHIVE_HIDDEN__", conversations ? "" : "hidden"}, + {"__MJJ_RESUME_PRESSED__", + strcmp(panel->name, "resume") == 0 ? "true" : "false"}, + {"__MJJ_TOOLS_PRESSED__", + strcmp(panel->name, "tools") == 0 ? "true" : "false"}, + {"__MJJ_BLOG_PRESSED__", + strcmp(panel->name, "blog") == 0 ? "true" : "false"}, + {"__MJJ_CONVERSATIONS_PRESSED__", conversations ? "true" : "false"}, + }; + for (size_t i = 0; + i < sizeof(replacements) / sizeof(replacements[0]); + ++i) + { + if (!Mjj_Replace_All( + final_body, + HTML_PAGE_CAP, + replacements[i].token, + replacements[i].value)) + return html_render_error(arena, "Internal Server Error"); + } Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); Dowa_HashMap_Push_Arena(resp, "referrer-policy", "no-referrer", arena); return resp;