mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
feat: Post index gets rendered.
This commit is contained in:
+127
-51
@@ -7,6 +7,12 @@ import "core:strings"
|
|||||||
SITE_TITLE :: "One Idiot Developer"
|
SITE_TITLE :: "One Idiot Developer"
|
||||||
SITE_DESC :: "This is fine...right?"
|
SITE_DESC :: "This is fine...right?"
|
||||||
|
|
||||||
|
@(rodata)
|
||||||
|
MONTHS: [12]string = {
|
||||||
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
|
||||||
|
}
|
||||||
|
|
||||||
CSS :: `
|
CSS :: `
|
||||||
body { background: #020617; color: #e2e8f0; font-family: system-ui, sans-serif; max-width: 720px; margin: 0 auto; padding: 2rem; line-height: 1.6; }
|
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; }
|
a { color: #7dd3fc; }
|
||||||
@@ -31,6 +37,8 @@ NAV :: `
|
|||||||
`
|
`
|
||||||
|
|
||||||
render_site :: proc(pages: []Page, output_dir: string) {
|
render_site :: proc(pages: []Page, output_dir: string) {
|
||||||
|
sort_pages_by_date(pages)
|
||||||
|
|
||||||
for page in pages {
|
for page in pages {
|
||||||
html := render_page_html(page)
|
html := render_page_html(page)
|
||||||
write_page(output_dir, page.permalink, html)
|
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)
|
home_html := render_home_html(pages)
|
||||||
write_file(fmt.tprintf("%s/index.html", output_dir), home_html)
|
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 {
|
render_page_html :: proc(page: Page) -> string {
|
||||||
return fmt.aprintf(
|
body := fmt.aprintf(
|
||||||
`<!DOCTYPE html>
|
`<main>
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>%s | %s</title>
|
|
||||||
<style>%s</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
%s<main>
|
|
||||||
<article>
|
<article>
|
||||||
<h1>%s</h1>
|
<h1>%s</h1>
|
||||||
%s %s
|
%s %s
|
||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`,
|
`,
|
||||||
page.title,
|
|
||||||
SITE_TITLE,
|
|
||||||
CSS,
|
|
||||||
NAV,
|
|
||||||
page.title,
|
page.title,
|
||||||
render_date(page),
|
render_date(page),
|
||||||
page.body_html,
|
page.body_html,
|
||||||
)
|
)
|
||||||
|
title := fmt.tprintf("%s | %s", page.title, SITE_TITLE)
|
||||||
|
return render_chrome(title, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
render_home_html :: proc(pages: []Page) -> string {
|
render_home_html :: proc(pages: []Page) -> string {
|
||||||
@@ -77,25 +75,65 @@ render_home_html :: proc(pages: []Page) -> string {
|
|||||||
defer delete(items)
|
defer delete(items)
|
||||||
|
|
||||||
for page in pages {
|
for page in pages {
|
||||||
if page.type != .Post {
|
append(&items, render_post_item(page))
|
||||||
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(` <li><a href="%s">%s</a> <time>%s</time>%s</li>`, page.permalink, page.title, date_short, star),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
post_list := strings.join(items[:], "\n")
|
post_list := strings.join(items[:], "\n")
|
||||||
|
|
||||||
|
body := fmt.aprintf(
|
||||||
|
`<main>
|
||||||
|
<header>
|
||||||
|
<h1>%s</h1>
|
||||||
|
<p>%s</p>
|
||||||
|
</header>
|
||||||
|
<ul>
|
||||||
|
%s
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
`,
|
||||||
|
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, "<main>\n <h1>Posts</h1>\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, " </ul>\n")
|
||||||
|
}
|
||||||
|
open = true
|
||||||
|
current_year = year
|
||||||
|
append(&parts, fmt.aprintf(" <h2>%s</h2>\n <hr>\n <ul>\n", year))
|
||||||
|
}
|
||||||
|
append(&parts, render_post_item(page))
|
||||||
|
append(&parts, "\n")
|
||||||
|
}
|
||||||
|
if open {
|
||||||
|
append(&parts, " </ul>\n")
|
||||||
|
}
|
||||||
|
append(&parts, "</main>\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(
|
return fmt.aprintf(
|
||||||
`<!DOCTYPE html>
|
`<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@@ -106,24 +144,32 @@ render_home_html :: proc(pages: []Page) -> string {
|
|||||||
<style>%s</style>
|
<style>%s</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
%s<main>
|
%s%s
|
||||||
<header>
|
|
||||||
<h1>%s</h1>
|
|
||||||
<p>%s</p>
|
|
||||||
</header>
|
|
||||||
<ul>
|
|
||||||
%s
|
|
||||||
</ul>
|
|
||||||
</main>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`,
|
`,
|
||||||
SITE_TITLE,
|
page_title,
|
||||||
CSS,
|
CSS,
|
||||||
NAV,
|
NAV,
|
||||||
SITE_TITLE,
|
body,
|
||||||
SITE_DESC,
|
)
|
||||||
post_list,
|
}
|
||||||
|
|
||||||
|
render_post_item :: proc(page: Page) -> string {
|
||||||
|
date_html := ""
|
||||||
|
if page.date != "" {
|
||||||
|
date_html = fmt.aprintf(" <time>%s</time>", format_date(page.date))
|
||||||
|
}
|
||||||
|
star := ""
|
||||||
|
if page.is_starred {
|
||||||
|
star = " \xe2\x98\x85"
|
||||||
|
}
|
||||||
|
return fmt.aprintf(
|
||||||
|
` <li><a href="%s">%s</a>%s%s</li>`,
|
||||||
|
page.permalink,
|
||||||
|
page.title,
|
||||||
|
date_html,
|
||||||
|
star,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,11 +177,41 @@ render_date :: proc(page: Page) -> string {
|
|||||||
if page.date == "" {
|
if page.date == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
date_short := page.date
|
return fmt.aprintf(` <time datetime="%s">%s</time>` + "\n", page.date, format_date(page.date))
|
||||||
if len(date_short) > 10 {
|
}
|
||||||
date_short = date_short[:10]
|
|
||||||
|
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..<len(pages) {
|
||||||
|
key := pages[i]
|
||||||
|
j := i - 1
|
||||||
|
for j >= 0 && pages[j].date < key.date {
|
||||||
|
pages[j + 1] = pages[j]
|
||||||
|
j -= 1
|
||||||
|
}
|
||||||
|
pages[j + 1] = key
|
||||||
}
|
}
|
||||||
return fmt.aprintf(` <time datetime="%s">%s</time>` + "\n", page.date, date_short)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write_page :: proc(output_dir: string, permalink: string, html: string) {
|
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)
|
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)
|
fmt.eprintfln("thor: cannot create %s: %v", dir, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user