mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
Compare commits
4 Commits
565115c30c
...
0dc6cc117f
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dc6cc117f | |||
| d10b832f3f | |||
| c3efbf80f0 | |||
| 177117e471 |
@@ -3,8 +3,6 @@
|
||||
- Look at the source for 3 template languages that support mustache syntax,
|
||||
and see how they implement the tempaltes, then pick the best one. One of them
|
||||
should be Hugo / go.
|
||||
- [ ] Deal with the favicon
|
||||
- [ ] Icon support.
|
||||
- [ ] robots.txt?
|
||||
- [ ] Evaluate Tufte CSS — borrow sidenote CSS or replace TailwindCSS entirely
|
||||
- Option B: Steal Tufte's sidenote/margin-note CSS (adapt for dark theme), keep TailwindCSS
|
||||
@@ -17,4 +15,3 @@
|
||||
- [ ] Nix build integration — main flake runs thor + tailwindcss instead of Hugo
|
||||
- [ ] Copy-to-clipboard button on code blocks (was in Hugo's custom-head.html)
|
||||
- [ ] OpenGraph meta tags
|
||||
- [ ] utteranc.es comments on posts
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
ICON_HOME :: `<svg aria-hidden="true" class="hi-svg-inline h-6 w-6" fill="none" height="1em" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="1em"><path d="m3 9 9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>`
|
||||
|
||||
ICON_GITHUB :: `<svg aria-hidden="true" class="hi-svg-inline h-7 w-7" fill="none" height="1em" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="1em"><path d="M15 22v-4a4.8 4.8.0 00-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35.0-3.5.0.0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35.0 3.5A5.403 5.403.0 004 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"/><path d="M9 18c-4.51 2-5-2-7-2"/></svg>`
|
||||
|
||||
ICON_RSS :: `<svg aria-hidden="true" class="hi-svg-inline h-7 w-7" fill="none" height="1em" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="1em"><path d="M4 11a9 9 0 019 9"/><path d="M4 4a16 16 0 0116 16"/><circle cx="5" cy="19" r="1"/></svg>`
|
||||
|
||||
ICON_CHEVRON_UP :: `<svg aria-hidden="true" class="hi-svg-inline h-10 w-10" fill="none" height="1em" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="1em"><path d="m18 15-6-6-6 6"/></svg>`
|
||||
|
||||
ICON_STAR :: `<svg aria-hidden="true" class="hi-svg-inline h-3.5 w-3.5 text-yellow-500 align-baseline mr-2" fill="currentColor" height="1em" viewBox="0 0 16 16" width="1em"><path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/></svg>`
|
||||
+31
-9
@@ -26,9 +26,6 @@ render_site :: proc(pages: []Page, content_path: string, output_dir: string, bas
|
||||
}
|
||||
}
|
||||
|
||||
// Copy static assets (avatar, favicon, etc.)
|
||||
copy_static_assets(content_path, output_dir)
|
||||
|
||||
// Render individual content pages (skip home)
|
||||
for page in pages {
|
||||
if page.type == .Home {
|
||||
@@ -58,6 +55,13 @@ render_site :: proc(pages: []Page, content_path: string, output_dir: string, bas
|
||||
sitemap := generate_sitemap(pages, base_url)
|
||||
write_file(fmt.tprintf("%s/sitemap.xml", output_dir), sitemap)
|
||||
|
||||
// Copy static assets (avatar, favicon, etc.)
|
||||
copy_static_assets(content_path, output_dir)
|
||||
|
||||
// Generate robots.txt
|
||||
robots := fmt.aprintf("User-agent: *\nAllow: /\nSitemap: %s/sitemap.xml\n", base_url)
|
||||
write_file(fmt.tprintf("%s/robots.txt", output_dir), robots)
|
||||
|
||||
total := len(pages) + 1
|
||||
if !has_home {
|
||||
total += 1
|
||||
@@ -66,17 +70,30 @@ render_site :: proc(pages: []Page, content_path: string, output_dir: string, bas
|
||||
}
|
||||
|
||||
render_page_html :: proc(page: Page, site_title: string) -> string {
|
||||
comments := ""
|
||||
if page.type == .Post {
|
||||
comments = `
|
||||
<script src="https://utteranc.es/client.js"
|
||||
repo="sbrow/sbrow.github.io"
|
||||
issue-term="pathname"
|
||||
label="Comment"
|
||||
theme="github-dark"
|
||||
crossorigin="anonymous"
|
||||
async></script>`
|
||||
}
|
||||
|
||||
body := fmt.aprintf(
|
||||
`<main>
|
||||
<article class="prose">
|
||||
<h1>%s</h1>
|
||||
%s %s
|
||||
</article>
|
||||
</article>%s
|
||||
</main>
|
||||
`,
|
||||
page.title,
|
||||
render_date(page),
|
||||
page.body_html,
|
||||
comments,
|
||||
)
|
||||
title := fmt.tprintf("%s | %s", page.title, site_title)
|
||||
return render_chrome(title, body)
|
||||
@@ -150,6 +167,7 @@ render_posts_html :: proc(pages: []Page, site_title: string) -> string {
|
||||
}
|
||||
|
||||
render_chrome :: proc(page_title: string, body: string) -> string {
|
||||
header := fmt.aprintf(HEADER, ICON_HOME)
|
||||
return fmt.aprintf(
|
||||
`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@@ -163,8 +181,9 @@ render_chrome :: proc(page_title: string, body: string) -> string {
|
||||
</head>
|
||||
<body>
|
||||
%s%s<footer>
|
||||
<a href="https://github.com/sbrow" target="_blank" rel="noopener noreferrer me" title="Github">GitHub</a>
|
||||
<a href="/index.xml" target="_blank" rel="noopener noreferrer me" title="Rss">RSS</a>
|
||||
<a class="goto-top opacity-0" href="#">%s</a>
|
||||
<a href="https://github.com/sbrow" target="_blank" rel="noopener noreferrer me" title="Github">%s</a>
|
||||
<a href="/index.xml" target="_blank" rel="noopener noreferrer me" title="Rss">%s</a>
|
||||
<p class="pt-5 prose">Proudly built with <a href="https://odin-lang.org/">Odin</a> and <a href="https://tailwindcss.com/">Tailwindcss</a></p>
|
||||
<p><small>©</small> 2026</p>
|
||||
</footer>
|
||||
@@ -174,8 +193,11 @@ render_chrome :: proc(page_title: string, body: string) -> string {
|
||||
</html>
|
||||
`,
|
||||
page_title,
|
||||
HEADER,
|
||||
header,
|
||||
body,
|
||||
ICON_CHEVRON_UP,
|
||||
ICON_GITHUB,
|
||||
ICON_RSS,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -183,7 +205,7 @@ HEADER :: `
|
||||
<header>
|
||||
<nav>
|
||||
<ul>
|
||||
<li class="mr-auto"><a href="/">Home</a></li>
|
||||
<li class="mr-auto"><a href="/">%s</a></li>
|
||||
<li><a href="/ideas/">Ideas</a></li>
|
||||
<li><a href="/posts/">Posts</a></li>
|
||||
</ul>
|
||||
@@ -202,7 +224,7 @@ render_post_item :: proc(page: Page) -> string {
|
||||
}
|
||||
star := ""
|
||||
if page.is_starred {
|
||||
star = `<span class="text-yellow-500 mr-2">★</span>`
|
||||
star = ICON_STAR
|
||||
}
|
||||
return fmt.aprintf(
|
||||
` <li class="flex justify-between"><a href="%s">%s</a><span>%s%s</span></li>`,
|
||||
|
||||
Reference in New Issue
Block a user