mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
refactor: weights are now wrapped in a Maybe.
This commit is contained in:
+2
-2
@@ -20,7 +20,7 @@ Page :: struct {
|
|||||||
description: string,
|
description: string,
|
||||||
date: string,
|
date: string,
|
||||||
year: string,
|
year: string,
|
||||||
weight: int,
|
weight: Maybe(int),
|
||||||
lastmod: string,
|
lastmod: string,
|
||||||
menus: map[string]Menu_Entry,
|
menus: map[string]Menu_Entry,
|
||||||
content: string,
|
content: string,
|
||||||
@@ -254,7 +254,7 @@ load_page :: proc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
page.year = get_year(page.date)
|
page.year = get_year(page.date)
|
||||||
page.weight = fm.weight if fm.weight != 0 else DEFAULT_WEIGHT
|
page.weight = fm.weight
|
||||||
page.lastmod = fm.lastmod
|
page.lastmod = fm.lastmod
|
||||||
page.draft = fm.draft
|
page.draft = fm.draft
|
||||||
page.starred = fm.isStarred
|
page.starred = fm.isStarred
|
||||||
|
|||||||
+4
-4
@@ -10,7 +10,7 @@ Frontmatter :: struct {
|
|||||||
date: string,
|
date: string,
|
||||||
lastmod: string,
|
lastmod: string,
|
||||||
publishDate: string,
|
publishDate: string,
|
||||||
weight: int,
|
weight: Maybe(int),
|
||||||
menus: json.Value,
|
menus: json.Value,
|
||||||
layout: string,
|
layout: string,
|
||||||
og: Open_Graph,
|
og: Open_Graph,
|
||||||
@@ -85,7 +85,7 @@ json_get_bool :: proc(obj: json.Object, key: string) -> bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
json_get_int :: proc(obj: json.Object, key: string) -> int {
|
json_get_int :: proc(obj: json.Object, key: string) -> Maybe(int) {
|
||||||
if v, ok := obj[key]; ok {
|
if v, ok := obj[key]; ok {
|
||||||
switch val in v {
|
switch val in v {
|
||||||
case json.Integer:
|
case json.Integer:
|
||||||
@@ -93,10 +93,10 @@ json_get_int :: proc(obj: json.Object, key: string) -> int {
|
|||||||
case json.Float:
|
case json.Float:
|
||||||
return int(val)
|
return int(val)
|
||||||
case json.Boolean, json.String, json.Array, json.Object, json.Null:
|
case json.Boolean, json.String, json.Array, json.Object, json.Null:
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
json_get_open_graph :: proc(obj: json.Object, key: string) -> Open_Graph {
|
json_get_open_graph :: proc(obj: json.Object, key: string) -> Open_Graph {
|
||||||
|
|||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "core:fmt"
|
|
||||||
|
|
||||||
Ctx :: struct {
|
|
||||||
title: string,
|
|
||||||
using page: Page,
|
|
||||||
site: Site,
|
|
||||||
}
|
|
||||||
|
|
||||||
Page :: struct {
|
|
||||||
title: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
Site :: struct {
|
|
||||||
title: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
main :: proc() {
|
|
||||||
site := Ctx {
|
|
||||||
site = Site{title = "foo"},
|
|
||||||
page = Page{title = "bar"},
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.printfln("%+v", site)
|
|
||||||
fmt.printf("%+v", site)
|
|
||||||
}
|
|
||||||
+14
-14
@@ -12,12 +12,12 @@ DEFAULT_WEIGHT :: 10
|
|||||||
Menu_Entry :: struct {
|
Menu_Entry :: struct {
|
||||||
name: string,
|
name: string,
|
||||||
url: string,
|
url: string,
|
||||||
weight: int,
|
weight: Maybe(int),
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse_page_menus converts raw frontmatter JSON into map[string]Menu_Entry.
|
// parse_page_menus converts raw frontmatter JSON into map[string]Menu_Entry.
|
||||||
// Supports three forms:
|
// Supports three forms:
|
||||||
// "menus": "main" → {main: {name=title, url=permalink, weight=0}}
|
// "menus": "main" → {main: {name=title, url=permalink, weight=nil}}
|
||||||
// "menus": ["main", "footer"] → {main: {...}, footer: {...}}
|
// "menus": ["main", "footer"] → {main: {...}, footer: {...}}
|
||||||
// "menus": {"main": {"weight": 30}} → {main: {name=title, url=permalink, weight=30}}
|
// "menus": {"main": {"weight": 30}} → {main: {name=title, url=permalink, weight=30}}
|
||||||
parse_page_menus :: proc(
|
parse_page_menus :: proc(
|
||||||
@@ -37,7 +37,6 @@ parse_page_menus :: proc(
|
|||||||
result[string(v)] = Menu_Entry {
|
result[string(v)] = Menu_Entry {
|
||||||
name = page.title,
|
name = page.title,
|
||||||
url = page.permalink,
|
url = page.permalink,
|
||||||
weight = DEFAULT_WEIGHT,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case json.Array:
|
case json.Array:
|
||||||
@@ -45,9 +44,8 @@ parse_page_menus :: proc(
|
|||||||
for item in v {
|
for item in v {
|
||||||
if s, ok := item.(json.String); ok {
|
if s, ok := item.(json.String); ok {
|
||||||
result[string(s)] = Menu_Entry {
|
result[string(s)] = Menu_Entry {
|
||||||
name = page.title,
|
name = page.title,
|
||||||
url = page.permalink,
|
url = page.permalink,
|
||||||
weight = DEFAULT_WEIGHT,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warnf("menus: ignoring non-string item in menus array: %v", item)
|
log.warnf("menus: ignoring non-string item in menus array: %v", item)
|
||||||
@@ -57,15 +55,15 @@ parse_page_menus :: proc(
|
|||||||
case json.Object:
|
case json.Object:
|
||||||
result = make(map[string]Menu_Entry, allocator)
|
result = make(map[string]Menu_Entry, allocator)
|
||||||
for menu_name, entry_val in v {
|
for menu_name, entry_val in v {
|
||||||
weight := DEFAULT_WEIGHT
|
weight: Maybe(int) = nil
|
||||||
if entry_obj, ok := entry_val.(json.Object); ok {
|
if entry_obj, ok := entry_val.(json.Object); ok {
|
||||||
if w, ok := entry_obj["weight"]; ok {
|
if w, ok := entry_obj["weight"]; ok {
|
||||||
#partial switch wval in w {
|
switch wval in w {
|
||||||
case json.Integer:
|
case json.Integer:
|
||||||
weight = int(wval)
|
weight = int(wval)
|
||||||
case json.Float:
|
case json.Float:
|
||||||
weight = int(wval)
|
weight = int(wval)
|
||||||
case:
|
case json.Boolean, json.String, json.Array, json.Object, json.Null:
|
||||||
log.warnf(
|
log.warnf(
|
||||||
"menus: '%s' entry 'weight' must be a number, got %v",
|
"menus: '%s' entry 'weight' must be a number, got %v",
|
||||||
menu_name,
|
menu_name,
|
||||||
@@ -166,9 +164,9 @@ merge_page_menus :: proc(site: ^Site) {
|
|||||||
if _, ok := page_entries[menu_name]; !ok {
|
if _, ok := page_entries[menu_name]; !ok {
|
||||||
page_entries[menu_name] = make([dynamic]Menu_Entry, 0, 4, alloc)
|
page_entries[menu_name] = make([dynamic]Menu_Entry, 0, 4, alloc)
|
||||||
}
|
}
|
||||||
// Effective weight: per-menu weight if explicit, else page.weight
|
// Effective weight: per-menu weight if set, else page.weight
|
||||||
effective := entry.weight
|
effective := entry.weight
|
||||||
if effective == DEFAULT_WEIGHT {
|
if effective == nil {
|
||||||
effective = page.weight
|
effective = page.weight
|
||||||
}
|
}
|
||||||
append(&page_entries[menu_name], Menu_Entry{
|
append(&page_entries[menu_name], Menu_Entry{
|
||||||
@@ -235,7 +233,7 @@ collect_auto_menus :: proc(site: ^Site) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !skip {
|
if !skip {
|
||||||
append(&entries, Menu_Entry{name = name, url = url, weight = DEFAULT_WEIGHT})
|
append(&entries, Menu_Entry{name = name, url = url})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +261,9 @@ collect_auto_menus :: proc(site: ^Site) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compare_menu_entries :: proc(a, b: Menu_Entry) -> int {
|
compare_menu_entries :: proc(a, b: Menu_Entry) -> int {
|
||||||
if a.weight != b.weight do return a.weight - b.weight
|
aw := a.weight.? or_else DEFAULT_WEIGHT
|
||||||
|
bw := b.weight.? or_else DEFAULT_WEIGHT
|
||||||
|
if aw != bw do return aw - bw
|
||||||
return strings.compare(a.name, b.name)
|
return strings.compare(a.name, b.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ parse_config_menus :: proc(
|
|||||||
|
|
||||||
name := ""
|
name := ""
|
||||||
url := ""
|
url := ""
|
||||||
weight := DEFAULT_WEIGHT
|
weight: Maybe(int) = nil
|
||||||
|
|
||||||
if v, ok := entry_obj["name"]; ok {
|
if v, ok := entry_obj["name"]; ok {
|
||||||
if s, ok2 := v.(json.String); ok2 {
|
if s, ok2 := v.(json.String); ok2 {
|
||||||
|
|||||||
+40
-24
@@ -30,7 +30,7 @@ test_menus_string_form :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, ok, "expected 'main' menu")
|
testing.expect(t, ok, "expected 'main' menu")
|
||||||
testing.expect_value(t, entry.name, "About")
|
testing.expect_value(t, entry.name, "About")
|
||||||
testing.expect_value(t, entry.url, "/about/")
|
testing.expect_value(t, entry.url, "/about/")
|
||||||
testing.expect_value(t, entry.weight, DEFAULT_WEIGHT)
|
testing.expect(t, entry.weight == nil, "string form should have nil weight")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
@@ -81,7 +81,7 @@ test_menus_object_no_weight :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, len(menus) == 1)
|
testing.expect(t, len(menus) == 1)
|
||||||
entry, ok := menus["main"]
|
entry, ok := menus["main"]
|
||||||
testing.expect(t, ok)
|
testing.expect(t, ok)
|
||||||
testing.expect_value(t, entry.weight, DEFAULT_WEIGHT)
|
testing.expect(t, entry.weight == nil, "object without weight key should have nil weight")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
@@ -139,7 +139,7 @@ test_menus_object_non_object_value :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, len(menus) == 1, "entry created with defaults")
|
testing.expect(t, len(menus) == 1, "entry created with defaults")
|
||||||
entry, ok := menus["main"]
|
entry, ok := menus["main"]
|
||||||
testing.expect(t, ok)
|
testing.expect(t, ok)
|
||||||
testing.expect_value(t, entry.weight, DEFAULT_WEIGHT)
|
testing.expect(t, entry.weight == nil, "non-object value should have nil weight")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
@@ -154,7 +154,7 @@ test_menus_non_numeric_weight :: proc(t: ^testing.T) {
|
|||||||
menus := parse_page_menus(parse_raw(`{"main": {"weight": "30"}}`), page, context.allocator)
|
menus := parse_page_menus(parse_raw(`{"main": {"weight": "30"}}`), page, context.allocator)
|
||||||
entry, ok := menus["main"]
|
entry, ok := menus["main"]
|
||||||
testing.expect(t, ok)
|
testing.expect(t, ok)
|
||||||
testing.expect_value(t, entry.weight, DEFAULT_WEIGHT)
|
testing.expect(t, entry.weight == nil, "non-numeric weight should have nil weight")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
@@ -204,12 +204,12 @@ test_menus_null_json :: proc(t: ^testing.T) {
|
|||||||
@(test)
|
@(test)
|
||||||
test_sort_weight_orders_correctly :: proc(t: ^testing.T) {
|
test_sort_weight_orders_correctly :: proc(t: ^testing.T) {
|
||||||
entries := []Menu_Entry {
|
entries := []Menu_Entry {
|
||||||
{name = "Zeta", url = "/z/", weight = DEFAULT_WEIGHT},
|
{name = "Zeta", url = "/z/"},
|
||||||
{name = "Alpha", url = "/a/", weight = 5},
|
{name = "Alpha", url = "/a/", weight = 5},
|
||||||
{name = "Beta", url = "/b/", weight = 1},
|
{name = "Beta", url = "/b/", weight = 1},
|
||||||
}
|
}
|
||||||
sort_menu_entries(entries)
|
sort_menu_entries(entries)
|
||||||
// weight 1 first, then weight 5, then default weight 10
|
// weight 1 first, then weight 5, then nil (DEFAULT_WEIGHT)
|
||||||
testing.expect_value(t, entries[0].name, "Beta")
|
testing.expect_value(t, entries[0].name, "Beta")
|
||||||
testing.expect_value(t, entries[1].name, "Alpha")
|
testing.expect_value(t, entries[1].name, "Alpha")
|
||||||
testing.expect_value(t, entries[2].name, "Zeta")
|
testing.expect_value(t, entries[2].name, "Zeta")
|
||||||
@@ -218,9 +218,9 @@ test_sort_weight_orders_correctly :: proc(t: ^testing.T) {
|
|||||||
@(test)
|
@(test)
|
||||||
test_sort_equal_weights_alphabetical :: proc(t: ^testing.T) {
|
test_sort_equal_weights_alphabetical :: proc(t: ^testing.T) {
|
||||||
entries := []Menu_Entry {
|
entries := []Menu_Entry {
|
||||||
{name = "Zebra", url = "/z/", weight = DEFAULT_WEIGHT},
|
{name = "Zebra", url = "/z/"},
|
||||||
{name = "Apple", url = "/a/", weight = DEFAULT_WEIGHT},
|
{name = "Apple", url = "/a/"},
|
||||||
{name = "Mango", url = "/m/", weight = DEFAULT_WEIGHT},
|
{name = "Mango", url = "/m/"},
|
||||||
}
|
}
|
||||||
sort_menu_entries(entries)
|
sort_menu_entries(entries)
|
||||||
testing.expect_value(t, entries[0].name, "Apple")
|
testing.expect_value(t, entries[0].name, "Apple")
|
||||||
@@ -231,19 +231,35 @@ test_sort_equal_weights_alphabetical :: proc(t: ^testing.T) {
|
|||||||
@(test)
|
@(test)
|
||||||
test_sort_mixed_weights :: proc(t: ^testing.T) {
|
test_sort_mixed_weights :: proc(t: ^testing.T) {
|
||||||
entries := []Menu_Entry {
|
entries := []Menu_Entry {
|
||||||
{name = "Charlie", url = "/c/", weight = DEFAULT_WEIGHT},
|
{name = "Charlie", url = "/c/"},
|
||||||
{name = "Alpha", url = "/a/", weight = DEFAULT_WEIGHT},
|
{name = "Alpha", url = "/a/"},
|
||||||
{name = "Bravo", url = "/b/", weight = 3},
|
{name = "Bravo", url = "/b/", weight = 3},
|
||||||
{name = "Delta", url = "/d/", weight = 1},
|
{name = "Delta", url = "/d/", weight = 1},
|
||||||
}
|
}
|
||||||
sort_menu_entries(entries)
|
sort_menu_entries(entries)
|
||||||
// weight 1 (Delta), weight 3 (Bravo), then default weight alphabetical (Alpha, Charlie)
|
// weight 1 (Delta), weight 3 (Bravo), then nil weight alphabetical (Alpha, Charlie)
|
||||||
testing.expect_value(t, entries[0].name, "Delta")
|
testing.expect_value(t, entries[0].name, "Delta")
|
||||||
testing.expect_value(t, entries[1].name, "Bravo")
|
testing.expect_value(t, entries[1].name, "Bravo")
|
||||||
testing.expect_value(t, entries[2].name, "Alpha")
|
testing.expect_value(t, entries[2].name, "Alpha")
|
||||||
testing.expect_value(t, entries[3].name, "Charlie")
|
testing.expect_value(t, entries[3].name, "Charlie")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
test_sort_explicit_zero_before_nil :: proc(t: ^testing.T) {
|
||||||
|
// Explicit weight 0 is distinguishable from unset (nil → DEFAULT_WEIGHT).
|
||||||
|
// This is the key behavioral improvement of Maybe(int).
|
||||||
|
entries := []Menu_Entry {
|
||||||
|
{name = "Unset", url = "/u/"},
|
||||||
|
{name = "ExplicitZero", url = "/0/", weight = 0},
|
||||||
|
{name = "ExplicitFive", url = "/5/", weight = 5},
|
||||||
|
}
|
||||||
|
sort_menu_entries(entries)
|
||||||
|
// weight 0 first, then weight 5, then nil (DEFAULT_WEIGHT = 10)
|
||||||
|
testing.expect_value(t, entries[0].name, "ExplicitZero")
|
||||||
|
testing.expect_value(t, entries[1].name, "ExplicitFive")
|
||||||
|
testing.expect_value(t, entries[2].name, "Unset")
|
||||||
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_config_weight_parsing_and_sort :: proc(t: ^testing.T) {
|
test_config_weight_parsing_and_sort :: proc(t: ^testing.T) {
|
||||||
arena: mem.Dynamic_Arena
|
arena: mem.Dynamic_Arena
|
||||||
@@ -268,7 +284,7 @@ test_config_weight_parsing_and_sort :: proc(t: ^testing.T) {
|
|||||||
testing.expect_value(t, main[0].name, "Light")
|
testing.expect_value(t, main[0].name, "Light")
|
||||||
testing.expect_value(t, main[0].weight, 1)
|
testing.expect_value(t, main[0].weight, 1)
|
||||||
testing.expect_value(t, main[1].name, "Default")
|
testing.expect_value(t, main[1].name, "Default")
|
||||||
testing.expect_value(t, main[1].weight, DEFAULT_WEIGHT)
|
testing.expect(t, main[1].weight == nil, "entry without weight should be nil")
|
||||||
testing.expect_value(t, main[2].name, "Heavy")
|
testing.expect_value(t, main[2].name, "Heavy")
|
||||||
testing.expect_value(t, main[2].weight, 20)
|
testing.expect_value(t, main[2].weight, 20)
|
||||||
}
|
}
|
||||||
@@ -296,7 +312,7 @@ test_json_get_int_missing :: proc(t: ^testing.T) {
|
|||||||
obj, _ := json.parse_string(`{}`, spec = .JSON)
|
obj, _ := json.parse_string(`{}`, spec = .JSON)
|
||||||
defer json.destroy_value(obj)
|
defer json.destroy_value(obj)
|
||||||
o, _ := obj.(json.Object)
|
o, _ := obj.(json.Object)
|
||||||
testing.expect_value(t, json_get_int(o, "weight"), 0)
|
testing.expect(t, json_get_int(o, "weight") == nil, "missing key should return nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
@@ -304,7 +320,7 @@ test_json_get_int_non_numeric :: proc(t: ^testing.T) {
|
|||||||
obj, _ := json.parse_string(`{"weight": "5"}`, spec = .JSON)
|
obj, _ := json.parse_string(`{"weight": "5"}`, spec = .JSON)
|
||||||
defer json.destroy_value(obj)
|
defer json.destroy_value(obj)
|
||||||
o, _ := obj.(json.Object)
|
o, _ := obj.(json.Object)
|
||||||
testing.expect_value(t, json_get_int(o, "weight"), 0)
|
testing.expect(t, json_get_int(o, "weight") == nil, "non-numeric should return nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- sort_pages tests ---
|
// --- sort_pages tests ---
|
||||||
@@ -313,13 +329,13 @@ test_json_get_int_non_numeric :: proc(t: ^testing.T) {
|
|||||||
test_sort_pages_weight_primary :: proc(t: ^testing.T) {
|
test_sort_pages_weight_primary :: proc(t: ^testing.T) {
|
||||||
pages := make(#soa[dynamic]Page, 0, 3)
|
pages := make(#soa[dynamic]Page, 0, 3)
|
||||||
defer delete(pages)
|
defer delete(pages)
|
||||||
append(&pages, Page{title = "Gamma", date = "2025-01-03", weight = DEFAULT_WEIGHT})
|
append(&pages, Page{title = "Gamma", date = "2025-01-03"})
|
||||||
append(&pages, Page{title = "Alpha", date = "2025-01-01", weight = 5})
|
append(&pages, Page{title = "Alpha", date = "2025-01-01", weight = 5})
|
||||||
append(&pages, Page{title = "Beta", date = "2025-01-02", weight = 1})
|
append(&pages, Page{title = "Beta", date = "2025-01-02", weight = 1})
|
||||||
|
|
||||||
sort_pages(pages[:])
|
sort_pages(pages[:])
|
||||||
|
|
||||||
// weight 1, weight 5, then default weight 10
|
// weight 1, weight 5, then nil weight (DEFAULT_WEIGHT)
|
||||||
testing.expect_value(t, pages.title[0], "Beta")
|
testing.expect_value(t, pages.title[0], "Beta")
|
||||||
testing.expect_value(t, pages.title[1], "Alpha")
|
testing.expect_value(t, pages.title[1], "Alpha")
|
||||||
testing.expect_value(t, pages.title[2], "Gamma")
|
testing.expect_value(t, pages.title[2], "Gamma")
|
||||||
@@ -329,13 +345,13 @@ test_sort_pages_weight_primary :: proc(t: ^testing.T) {
|
|||||||
test_sort_pages_equal_weights_by_date :: proc(t: ^testing.T) {
|
test_sort_pages_equal_weights_by_date :: proc(t: ^testing.T) {
|
||||||
pages := make(#soa[dynamic]Page, 0, 3)
|
pages := make(#soa[dynamic]Page, 0, 3)
|
||||||
defer delete(pages)
|
defer delete(pages)
|
||||||
append(&pages, Page{title = "Old", date = "2025-01-01", weight = DEFAULT_WEIGHT})
|
append(&pages, Page{title = "Old", date = "2025-01-01"})
|
||||||
append(&pages, Page{title = "New", date = "2025-06-01", weight = DEFAULT_WEIGHT})
|
append(&pages, Page{title = "New", date = "2025-06-01"})
|
||||||
append(&pages, Page{title = "Mid", date = "2025-03-01", weight = DEFAULT_WEIGHT})
|
append(&pages, Page{title = "Mid", date = "2025-03-01"})
|
||||||
|
|
||||||
sort_pages(pages[:])
|
sort_pages(pages[:])
|
||||||
|
|
||||||
// All same weight → date descending
|
// All nil weight → date descending
|
||||||
testing.expect_value(t, pages.title[0], "New")
|
testing.expect_value(t, pages.title[0], "New")
|
||||||
testing.expect_value(t, pages.title[1], "Mid")
|
testing.expect_value(t, pages.title[1], "Mid")
|
||||||
testing.expect_value(t, pages.title[2], "Old")
|
testing.expect_value(t, pages.title[2], "Old")
|
||||||
@@ -345,14 +361,14 @@ test_sort_pages_equal_weights_by_date :: proc(t: ^testing.T) {
|
|||||||
test_sort_pages_mixed :: proc(t: ^testing.T) {
|
test_sort_pages_mixed :: proc(t: ^testing.T) {
|
||||||
pages := make(#soa[dynamic]Page, 0, 4)
|
pages := make(#soa[dynamic]Page, 0, 4)
|
||||||
defer delete(pages)
|
defer delete(pages)
|
||||||
append(&pages, Page{title = "DefaultOld", date = "2025-01-01", weight = DEFAULT_WEIGHT})
|
append(&pages, Page{title = "DefaultOld", date = "2025-01-01"})
|
||||||
append(&pages, Page{title = "DefaultNew", date = "2025-06-01", weight = DEFAULT_WEIGHT})
|
append(&pages, Page{title = "DefaultNew", date = "2025-06-01"})
|
||||||
append(&pages, Page{title = "Heavy", date = "2025-03-01", weight = 20})
|
append(&pages, Page{title = "Heavy", date = "2025-03-01", weight = 20})
|
||||||
append(&pages, Page{title = "Light", date = "2025-02-01", weight = 1})
|
append(&pages, Page{title = "Light", date = "2025-02-01", weight = 1})
|
||||||
|
|
||||||
sort_pages(pages[:])
|
sort_pages(pages[:])
|
||||||
|
|
||||||
// weight 1, weight 10 (DefaultNew by date), weight 10 (DefaultOld by date), weight 20
|
// weight 1, nil weight (DefaultNew by date), nil weight (DefaultOld by date), weight 20
|
||||||
testing.expect_value(t, pages.title[0], "Light")
|
testing.expect_value(t, pages.title[0], "Light")
|
||||||
testing.expect_value(t, pages.title[1], "DefaultNew")
|
testing.expect_value(t, pages.title[1], "DefaultNew")
|
||||||
testing.expect_value(t, pages.title[2], "DefaultOld")
|
testing.expect_value(t, pages.title[2], "DefaultOld")
|
||||||
|
|||||||
+2
-2
@@ -387,8 +387,8 @@ sort_pages :: proc(pages: #soa[]Page) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compare_pages :: proc(pages: #soa[]Page, j: int, key: Page) -> int {
|
compare_pages :: proc(pages: #soa[]Page, j: int, key: Page) -> int {
|
||||||
wj := pages.weight[j]
|
wj := pages.weight[j].? or_else DEFAULT_WEIGHT
|
||||||
wk := key.weight
|
wk := key.weight.? or_else DEFAULT_WEIGHT
|
||||||
if wj != wk do return wj - wk
|
if wj != wk do return wj - wk
|
||||||
// Equal weight → date descending
|
// Equal weight → date descending
|
||||||
if pages.date[j] < key.date do return 1
|
if pages.date[j] < key.date do return 1
|
||||||
|
|||||||
Reference in New Issue
Block a user