From 876f7675489fe6bf81cfef1fa6053670eff83f9c Mon Sep 17 00:00:00 2001 From: Spencer Brower <6729162+sbrow@users.noreply.github.com> Date: Tue, 4 Aug 2026 12:53:01 -0400 Subject: [PATCH] feat: Added deflist markdown extension. --- AGENTS.md | 4 +- TODOS.md | 1 + flake.nix | 1 + markdown/deflists.odin | 197 ++++++++++++++++++++++++++++++++++++ markdown/deflists_test.odin | 104 +++++++++++++++++++ markdown/footnotes.odin | 18 +--- markdown/markdown.odin | 10 +- site/content/docs.md | 4 +- 8 files changed, 317 insertions(+), 22 deletions(-) create mode 100644 markdown/deflists.odin create mode 100644 markdown/deflists_test.odin diff --git a/AGENTS.md b/AGENTS.md index e77f61b..45f939b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -79,6 +79,7 @@ thor/ | | `sectionate.odin` | `wrap_sections` — splits HTML at `
tags. Result lives in context.temp_allocator. +render_inline_md :: proc(text: string) -> string { + raw := cm.markdown_to_html_from_string(text, {.Unsafe}) + defer cm.free_string(raw) + return strings.clone(strip_p_tags(raw), context.temp_allocator) +} + +// strip_p_tags removes surrounding
if the HTML is a single paragraph. +strip_p_tags :: proc(html: string) -> string { + s := html + if len(s) > 0 && s[len(s) - 1] == '\n' { + s = s[:len(s) - 1] + } + if strings.has_prefix(s, "") && strings.has_suffix(s, "
") { + return s[3:len(s) - 4] + } + return s +} + diff --git a/markdown/deflists_test.odin b/markdown/deflists_test.odin new file mode 100644 index 0000000..c076b4a --- /dev/null +++ b/markdown/deflists_test.odin @@ -0,0 +1,104 @@ +#+test +package markdown + +import "core:strings" +import "core:testing" + +@(test) +test_single_entry :: proc(t: ^testing.T) { + input := "term\n\n: definition" + result := convert_deflists(input, context.temp_allocator) + expected := "codecontent"))
+ testing.expect(t, strings.contains(result, "assets"))
+ testing.expect(t, strings.contains(result, "") && strings.has_suffix(s, "
") { - return s[3:len(s) - 4] - } - return s -} - diff --git a/markdown/markdown.odin b/markdown/markdown.odin index af6e5be..ecaa3f2 100644 --- a/markdown/markdown.odin +++ b/markdown/markdown.odin @@ -12,9 +12,10 @@ Extension :: enum { Highlight, Sections, HeadingIDs, + DefLists, } -DEFAULT_EXTENSIONS :: bit_set[Extension]{.Emoji, .Sidenotes, .Alerts, .HeadingIDs} +DEFAULT_EXTENSIONS :: bit_set[Extension]{.Emoji, .Sidenotes, .Alerts, .HeadingIDs, .DefLists} // Caller is responsible for freeing string process :: proc( @@ -29,6 +30,9 @@ process :: proc( if .Sidenotes in ext { clean_body, side_notes, margin_notes = strip_definitions(body) } + if .DefLists in ext { + clean_body = convert_deflists(clean_body, allocator) + } original_html := cm.markdown_to_html_from_string(clean_body, {.Unsafe}) html := strings.clone(original_html, allocator) cm.free_string(original_html) @@ -71,6 +75,8 @@ parse_extension_list :: proc(s: string) -> (result: bit_set[Extension]) { result += {.Sections} case "heading_ids": result += {.HeadingIDs} + case "deflists": + result += {.DefLists} } } return result @@ -94,6 +100,8 @@ apply_extension_config :: proc(ext: ^bit_set[Extension], config: json.Object) { if enabled {ext^ += {.Sections}} else {ext^ -= {.Sections}} case "heading_ids": if enabled {ext^ += {.HeadingIDs}} else {ext^ -= {.HeadingIDs}} + case "deflists": + if enabled {ext^ += {.DefLists}} else {ext^ -= {.DefLists}} } } } diff --git a/site/content/docs.md b/site/content/docs.md index 4009194..5aec496 100644 --- a/site/content/docs.md +++ b/site/content/docs.md @@ -82,9 +82,7 @@ TODO: Describe TODO: Don't forget to highlight differences from Hugo. -## Templates[^tempmod] - -[^tempmod]: Template modification is an "advanced" feature, and shoud probably be discussed later in the page. (or possibly in the guide.) +## Templates Sites are built using one or more template files written in an extended version of [mustache](https://mustache.github.io) templates. The [mustache manual](https://mustache.github.io/mustache.5.html) has great explainations and a lot of examples if you want to know more, but I'll summarize them for you here.