From 87bd2b828b01ebcb616cdd8202508b742574c90b Mon Sep 17 00:00:00 2001 From: Spencer Brower <6729162+sbrow@users.noreply.github.com> Date: Fri, 10 Jul 2026 18:10:38 -0400 Subject: [PATCH] feat: Post index gets rendered. --- render.odin | 178 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 127 insertions(+), 51 deletions(-) diff --git a/render.odin b/render.odin index 99f9cfc..002cade 100644 --- a/render.odin +++ b/render.odin @@ -7,6 +7,12 @@ import "core:strings" SITE_TITLE :: "One Idiot Developer" SITE_DESC :: "This is fine...right?" +@(rodata) +MONTHS: [12]string = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", +} + CSS :: ` body { background: #020617; color: #e2e8f0; font-family: system-ui, sans-serif; max-width: 720px; margin: 0 auto; padding: 2rem; line-height: 1.6; } a { color: #7dd3fc; } @@ -31,6 +37,8 @@ NAV :: ` ` render_site :: proc(pages: []Page, output_dir: string) { + sort_pages_by_date(pages) + for page in pages { html := render_page_html(page) write_page(output_dir, page.permalink, html) @@ -39,37 +47,27 @@ render_site :: proc(pages: []Page, output_dir: string) { home_html := render_home_html(pages) write_file(fmt.tprintf("%s/index.html", output_dir), home_html) - fmt.printfln("Rendered %d pages to %s", len(pages) + 1, output_dir) + posts_html := render_posts_html(pages) + write_page(output_dir, "/posts/", posts_html) + + fmt.printfln("Rendered %d pages to %s", len(pages) + 2, output_dir) } render_page_html :: proc(page: Page) -> string { - return fmt.aprintf( - ` - - - - - %s | %s - - - -%s
+ body := fmt.aprintf( + `

%s

%s %s
- - `, - page.title, - SITE_TITLE, - CSS, - NAV, page.title, render_date(page), page.body_html, ) + title := fmt.tprintf("%s | %s", page.title, SITE_TITLE) + return render_chrome(title, body) } render_home_html :: proc(pages: []Page) -> string { @@ -77,25 +75,65 @@ render_home_html :: proc(pages: []Page) -> string { defer delete(items) for page in pages { - if page.type != .Post { - continue - } - date_short := page.date - if len(date_short) > 10 { - date_short = date_short[:10] - } - star := "" - if page.is_starred { - star = " \xe2\x98\x85" - } - append( - &items, - fmt.aprintf(`
  • %s %s
  • `, page.permalink, page.title, date_short, star), - ) + append(&items, render_post_item(page)) } post_list := strings.join(items[:], "\n") + body := fmt.aprintf( + `
    +
    +

    %s

    +

    %s

    +
    + +
    +`, + SITE_TITLE, + SITE_DESC, + post_list, + ) + + return render_chrome(SITE_TITLE, body) +} + +render_posts_html :: proc(pages: []Page) -> string { + parts: [dynamic]string + defer delete(parts) + + append(&parts, "
    \n

    Posts

    \n") + + current_year := "" + open := false + for page in pages { + if page.type != .Post { + continue + } + year := get_year(page.date) + if year != current_year { + if open { + append(&parts, " \n") + } + open = true + current_year = year + append(&parts, fmt.aprintf("

    %s

    \n
    \n \n") + } + append(&parts, "
    \n") + + body := strings.join(parts[:], "") + title := fmt.tprintf("Posts | %s", SITE_TITLE) + return render_chrome(title, body) +} + +render_chrome :: proc(page_title: string, body: string) -> string { return fmt.aprintf( ` @@ -106,24 +144,32 @@ render_home_html :: proc(pages: []Page) -> string { -%s
    -
    -

    %s

    -

    %s

    -
    - -
    +%s%s `, - SITE_TITLE, + page_title, CSS, NAV, - SITE_TITLE, - SITE_DESC, - post_list, + body, + ) +} + +render_post_item :: proc(page: Page) -> string { + date_html := "" + if page.date != "" { + date_html = fmt.aprintf(" ", format_date(page.date)) + } + star := "" + if page.is_starred { + star = " \xe2\x98\x85" + } + return fmt.aprintf( + `
  • %s%s%s
  • `, + page.permalink, + page.title, + date_html, + star, ) } @@ -131,11 +177,41 @@ render_date :: proc(page: Page) -> string { if page.date == "" { return "" } - date_short := page.date - if len(date_short) > 10 { - date_short = date_short[:10] + return fmt.aprintf(` ` + "\n", page.date, format_date(page.date)) +} + +format_date :: proc(iso: string) -> string { + if len(iso) < 10 { + return iso + } + year := iso[:4] + month_num := (int(iso[5]) - 0x30) * 10 + (int(iso[6]) - 0x30) + day_num := (int(iso[8]) - 0x30) * 10 + (int(iso[9]) - 0x30) + + if month_num < 1 || month_num > 12 { + return iso[:10] + } + + return fmt.aprintf("%d %s %s", day_num, MONTHS[month_num - 1], year) +} + +get_year :: proc(iso: string) -> string { + if len(iso) < 4 { + return "" + } + return iso[:4] +} + +sort_pages_by_date :: proc(pages: []Page) { + for i in 1..= 0 && pages[j].date < key.date { + pages[j + 1] = pages[j] + j -= 1 + } + pages[j + 1] = key } - return fmt.aprintf(` ` + "\n", page.date, date_short) } write_page :: proc(output_dir: string, permalink: string, html: string) { @@ -145,7 +221,7 @@ write_page :: proc(output_dir: string, permalink: string, html: string) { } dir := fmt.tprintf("%s/%s", output_dir, rel) - if err := os.make_directory_all(dir); err != nil { + if err := os.make_directory_all(dir); err != nil && err != .Exist { fmt.eprintfln("thor: cannot create %s: %v", dir, err) return }