mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
feat: Added page to template context.
This commit is contained in:
@@ -220,7 +220,7 @@ Templates use Mustache with template inheritance (`{{<base}}` / `{{$block}}`):
|
|||||||
<!-- page.html (content layout) -->
|
<!-- page.html (content layout) -->
|
||||||
{{<base}}
|
{{<base}}
|
||||||
{{$main}}
|
{{$main}}
|
||||||
<main><article><h1>{{page_title}}</h1>{{&content}}</article></main>
|
<main><article><h1>{{page.title}}</h1>{{&content}}</article></main>
|
||||||
{{/main}}
|
{{/main}}
|
||||||
{{/base}}
|
{{/base}}
|
||||||
```
|
```
|
||||||
@@ -240,7 +240,7 @@ Base_Data :: struct {
|
|||||||
}
|
}
|
||||||
Page_Data :: struct {
|
Page_Data :: struct {
|
||||||
using base: Base_Data, // fields promoted via reflection fallback
|
using base: Base_Data, // fields promoted via reflection fallback
|
||||||
page_title: string,
|
page.title: string,
|
||||||
date: string, // raw ISO 8601; formatted via `| format` in templates
|
date: string, // raw ISO 8601; formatted via `| format` in templates
|
||||||
}
|
}
|
||||||
Home_Data :: struct {
|
Home_Data :: struct {
|
||||||
@@ -249,7 +249,7 @@ Home_Data :: struct {
|
|||||||
}
|
}
|
||||||
Section_Data :: struct {
|
Section_Data :: struct {
|
||||||
using base: Base_Data,
|
using base: Base_Data,
|
||||||
page_title: string,
|
page.title: string,
|
||||||
posts: [dynamic]Page_Context, // flat list; year grouping done in template via pipe
|
posts: [dynamic]Page_Context, // flat list; year grouping done in template via pipe
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
- [ ] consider adding a limit to the context stack in mustache.
|
- [ ] consider adding a limit to the context stack in mustache.
|
||||||
- [ ] better diagnostics for syntax errors in treesitter.
|
- [ ] better diagnostics for syntax errors in treesitter.
|
||||||
- [x] Add heading ids as a default on extension.
|
- [x] Add heading ids as a default on extension.
|
||||||
|
- [ ] show "stack traces" in template error diagnostics
|
||||||
|
- [ ] starred must be a param.
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||
@@ -32,6 +34,11 @@
|
|||||||
- [ ] can markdown extensions run in parallel?
|
- [ ] can markdown extensions run in parallel?
|
||||||
- [ ] enforce MAX_SLUG_LENGTH
|
- [ ] enforce MAX_SLUG_LENGTH
|
||||||
|
|
||||||
|
## Remove Privileged content
|
||||||
|
|
||||||
|
- [ ] `group_by` currently requires a computed `year` field on the page.
|
||||||
|
- We should replace this with `{{ pages | group_by (date | "2006") }}` or similar
|
||||||
|
|
||||||
|
|
||||||
## Memory Management
|
## Memory Management
|
||||||
|
|
||||||
@@ -145,6 +152,7 @@ main :: proc () {
|
|||||||
- [ ] `new site` set up new project
|
- [ ] `new site` set up new project
|
||||||
- [ ] warn/error when unknown key used in mustache.
|
- [ ] warn/error when unknown key used in mustache.
|
||||||
- [ ] Import/export packages. Hugo, jekyll, WordPress, etc.
|
- [ ] Import/export packages. Hugo, jekyll, WordPress, etc.
|
||||||
|
- [ ] opt-in "strict_keys" mode. in this mode, key lookups may not view parent objects.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
|||||||
+13
-2
@@ -7,6 +7,7 @@ import "core:fmt"
|
|||||||
import "core:log"
|
import "core:log"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
// Fields with underscores should never be set by the user.
|
// Fields with underscores should never be set by the user.
|
||||||
Page :: struct {
|
Page :: struct {
|
||||||
@@ -18,12 +19,13 @@ Page :: struct {
|
|||||||
title: string,
|
title: string,
|
||||||
description: string,
|
description: string,
|
||||||
date: string,
|
date: string,
|
||||||
|
year: string,
|
||||||
lastmod: string,
|
lastmod: string,
|
||||||
menu: string,
|
menu: string,
|
||||||
content: string,
|
content: string,
|
||||||
og: Open_Graph,
|
og: Open_Graph,
|
||||||
draft: bool,
|
draft: bool,
|
||||||
is_starred: bool,
|
starred: bool,
|
||||||
_is_index: bool `private`,
|
_is_index: bool `private`,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,9 +233,18 @@ load_page :: proc(
|
|||||||
page.title = fm.title
|
page.title = fm.title
|
||||||
page.description = fm.description
|
page.description = fm.description
|
||||||
page.date = fm.date
|
page.date = fm.date
|
||||||
|
if page.date == "" {
|
||||||
|
info, stat_err := os.stat(file_path, context.allocator)
|
||||||
|
if stat_err == nil {
|
||||||
|
page.date, _ = time.time_to_rfc3339(info.modification_time, 0, false, context.allocator)
|
||||||
|
os.file_info_delete(info, context.allocator)
|
||||||
|
log.warnf("no date in frontmatter for %s, using file modification time: %s", file_path, page.date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
page.year = get_year(page.date)
|
||||||
page.lastmod = fm.lastmod
|
page.lastmod = fm.lastmod
|
||||||
page.draft = fm.draft
|
page.draft = fm.draft
|
||||||
page.is_starred = fm.isStarred
|
page.starred = fm.isStarred
|
||||||
page.menu = fm.menu
|
page.menu = fm.menu
|
||||||
page.layout = fm.layout if fm.layout != "" else infer_layout(section, is_index)
|
page.layout = fm.layout if fm.layout != "" else infer_layout(section, is_index)
|
||||||
page.og = fm.og
|
page.og = fm.og
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{{$main}}
|
{{$main}}
|
||||||
<main>
|
<main>
|
||||||
<article>
|
<article>
|
||||||
<h1>{{page_title}}</h1>
|
<h1>{{page.title}}</h1>
|
||||||
{{#date_iso}} <time class="subtitle" datetime="{{date_iso}}">{{date_display}}</time>
|
{{#date_iso}} <time class="subtitle" datetime="{{date_iso}}">{{date_display}}</time>
|
||||||
{{/date_iso}} {{&content}}
|
{{/date_iso}} {{&content}}
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{{<base}}
|
{{<base}}
|
||||||
{{$main}}
|
{{$main}}
|
||||||
<main>
|
<main>
|
||||||
<h1>{{page_title}}</h1>
|
<h1>{{page.title}}</h1>
|
||||||
{{&content}}
|
{{&content}}
|
||||||
{{#posts | group_by year}}
|
{{#posts | group_by year}}
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Inner :: struct {
|
|||||||
|
|
||||||
Outer :: struct {
|
Outer :: struct {
|
||||||
title: string,
|
title: string,
|
||||||
page_title: string,
|
page.title: string,
|
||||||
inner: Inner,
|
inner: Inner,
|
||||||
numbers: [3]int,
|
numbers: [3]int,
|
||||||
}
|
}
|
||||||
@@ -150,8 +150,8 @@ test_validate_map_path_silent :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_suggest_correction_exact :: proc(t: ^testing.T) {
|
test_suggest_correction_exact :: proc(t: ^testing.T) {
|
||||||
available := []string{"title", "page_title", "body"}
|
available := []string{"title", "page.title", "body"}
|
||||||
testing.expect_value(t, suggest_correction(available, "page_titel"), "page_title")
|
testing.expect_value(t, suggest_correction(available, "page_titel"), "page.title")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
|
|||||||
+13
-35
@@ -19,35 +19,14 @@ Template_Context :: struct {
|
|||||||
og: Open_Graph,
|
og: Open_Graph,
|
||||||
date_format: string,
|
date_format: string,
|
||||||
timezone: ^datetime.TZ_Region,
|
timezone: ^datetime.TZ_Region,
|
||||||
|
page: Page,
|
||||||
// Page Data
|
|
||||||
page_title: string,
|
|
||||||
date: string,
|
|
||||||
|
|
||||||
// Home data
|
// Home data
|
||||||
pages: [dynamic]Page_Context,
|
pages: [dynamic]Page,
|
||||||
|
|
||||||
// Section Data
|
// Section Data
|
||||||
// TODO: Remove "posts" from the Odin code
|
// TODO: Remove "posts" from the Odin code
|
||||||
posts: [dynamic]Page_Context,
|
posts: [dynamic]Page,
|
||||||
}
|
|
||||||
|
|
||||||
Page_Context :: struct {
|
|
||||||
permalink: string,
|
|
||||||
title: string,
|
|
||||||
starred: bool,
|
|
||||||
date: string,
|
|
||||||
year: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
build_page_context :: proc(page: Page) -> Page_Context {
|
|
||||||
return Page_Context {
|
|
||||||
permalink = page.permalink,
|
|
||||||
title = page.title,
|
|
||||||
starred = page.is_starred,
|
|
||||||
date = page.date,
|
|
||||||
year = get_year(page.date),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_template :: proc(vfs: ^VFS, virtual_path: string) -> mustache.Template {
|
load_template :: proc(vfs: ^VFS, virtual_path: string) -> mustache.Template {
|
||||||
@@ -268,9 +247,8 @@ render_page_html :: proc(
|
|||||||
) -> string {
|
) -> string {
|
||||||
ctx := ctx
|
ctx := ctx
|
||||||
ctx.title = fmt.tprintf("%s | %s", page.title, site.title)
|
ctx.title = fmt.tprintf("%s | %s", page.title, site.title)
|
||||||
ctx.page_title = page.title
|
ctx.page = page
|
||||||
ctx.content = page.content
|
ctx.content = page.content
|
||||||
ctx.date = page.date
|
|
||||||
ctx.og = og_for_page(site.og, page)
|
ctx.og = og_for_page(site.og, page)
|
||||||
return render_template(content_tpl, ctx, partials)
|
return render_template(content_tpl, ctx, partials)
|
||||||
}
|
}
|
||||||
@@ -282,13 +260,12 @@ render_home_html :: proc(
|
|||||||
partials: map[string]mustache.Template,
|
partials: map[string]mustache.Template,
|
||||||
ctx: Template_Context,
|
ctx: Template_Context,
|
||||||
) -> string {
|
) -> string {
|
||||||
list_pages := make([dynamic]Page_Context)
|
list_pages := make([dynamic]Page, 0, 8, context.temp_allocator)
|
||||||
defer delete(list_pages)
|
|
||||||
for page in site.pages {
|
for page in site.pages {
|
||||||
if page._is_index {
|
if page._is_index {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
append(&list_pages, build_page_context(page))
|
append(&list_pages, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := ctx
|
ctx := ctx
|
||||||
@@ -309,24 +286,25 @@ render_section :: proc(
|
|||||||
partials: map[string]mustache.Template,
|
partials: map[string]mustache.Template,
|
||||||
ctx: Template_Context,
|
ctx: Template_Context,
|
||||||
) -> string {
|
) -> string {
|
||||||
posts := make([dynamic]Page_Context)
|
posts := make([dynamic]Page, 0, len(site.pages) / 2, context.temp_allocator)
|
||||||
defer delete(posts)
|
|
||||||
for page in site.pages {
|
for page in site.pages {
|
||||||
if page.section != section || page._is_index {
|
if page.section != section || page._is_index {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
append(&posts, build_page_context(page))
|
append(&posts, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := ctx
|
ctx := ctx
|
||||||
if has_index {
|
if has_index {
|
||||||
ctx.content = section_index.content
|
ctx.content = section_index.content
|
||||||
ctx.page_title = section_index.title
|
ctx.page = section_index
|
||||||
ctx.title = fmt.tprintf("%s | %s", section_index.title, site.title)
|
ctx.title = fmt.tprintf("%s | %s", section_index.title, site.title)
|
||||||
ctx.og = og_for_page(site.og, section_index)
|
ctx.og = og_for_page(site.og, section_index)
|
||||||
} else {
|
} else {
|
||||||
ctx.page_title = capitalize(section)
|
ctx.page = Page {
|
||||||
ctx.title = fmt.tprintf("%s | %s", capitalize(section), site.title)
|
title = capitalize(section),
|
||||||
|
}
|
||||||
|
ctx.title = fmt.tprintf("%s | %s", ctx.page.title, site.title)
|
||||||
ctx.og.title = capitalize(section)
|
ctx.og.title = capitalize(section)
|
||||||
ctx.og.description = ""
|
ctx.og.description = ""
|
||||||
ctx.og.url = fmt.tprintf("%s/%s/", site.base_url, section)
|
ctx.og.url = fmt.tprintf("%s/%s/", site.base_url, section)
|
||||||
|
|||||||
Reference in New Issue
Block a user