Split tags and archives into their own components

This commit is contained in:
Mikko Ahlroth 2024-05-06 19:35:17 +03:00
parent 89402f5dce
commit a00a808618
3 changed files with 140 additions and 109 deletions

View file

@ -0,0 +1,70 @@
//// The archives component renders all the years and months where there are
//// posts as nested unordered lists.
import gleam/dict
import gleam/int
import gleam/list
import lustre/attribute.{href}
import lustre/element.{text}
import lustre/element/html.{a, li, ul}
import scriptorium/config.{type Configuration}
import scriptorium/models/database.{type Database}
import scriptorium/utils/date
import scriptorium/utils/ordered_tree
pub fn view(db: Database, config: Configuration) {
db
|> database.years()
|> dict.to_list()
|> list.sort(fn(a, b) { int.compare(a.0, b.0) })
|> list.fold([], fn(year_archive, year) {
let #(year, months) = year
[
li([], [
a(
[
href(config.paths.html(
config.paths.root
<> config.paths.list_page(config.paths.year(year), 1),
)),
],
[text(int.to_string(year))],
),
ul(
[],
list.fold(date.months, [], fn(month_archive, month) {
case dict.get(months, month) {
Ok(posts) -> [
li([], [
a(
[
href(config.paths.html(
config.paths.root
<> config.paths.list_page(
config.paths.month(year, month),
1,
),
)),
],
[
text(
date.month_to_string(month)
<> " ("
<> int.to_string(ordered_tree.length(posts))
<> ")",
),
],
),
]),
..month_archive
]
Error(_) -> month_archive
}
}),
),
]),
..year_archive
]
})
|> ul([], _)
}

View file

@ -1,10 +1,7 @@
import gleam/dict
import gleam/float
import gleam/int
import gleam/list
import gleam/option
import gleam/string
import lustre/attribute.{attribute, href, id, name, rel, role, style, type_}
import lustre/attribute.{attribute, href, id, name, rel, role, type_}
import lustre/element.{type Element, text}
import lustre/element/html.{
a, body, footer, h1, head, header, html, li, link, main, meta, nav, p, section,
@ -13,10 +10,8 @@ import lustre/element/html.{
import scriptorium/config.{type Configuration}
import scriptorium/models/database.{type Database}
import scriptorium/models/menu.{type MenuItem}
import scriptorium/utils/date
import scriptorium/utils/ordered_tree
const tag_min_size = 0.5
import scriptorium/rendering/views/archives
import scriptorium/rendering/views/tags
/// The base view pre-renders some content once, so that it can be reused for every render.
pub type PreRendered {
@ -24,13 +19,20 @@ pub type PreRendered {
}
pub fn generate(db: Database, config: Configuration) {
let pre_rendered = pre_render(db, config)
let pre_rendered = pre_render(db, config, tags.view, archives.view)
fn(inner: Element(Nil), extra_meta: List(Element(Nil)), title_prefix: String) {
view(db, config, pre_rendered, inner, extra_meta, title_prefix)
}
}
fn pre_render(db, config) -> PreRendered {
/// Pre-render the tag and archive elements using the given tags and archives
/// components.
pub fn pre_render(
db: Database,
config: Configuration,
tags: fn(Database, Configuration) -> Element(Nil),
archives: fn(Database, Configuration) -> Element(Nil),
) -> PreRendered {
PreRendered(tags: tags(db, config), archives: archives(db, config))
}
@ -110,105 +112,6 @@ fn view(
])
}
fn tags(db: Database, config: Configuration) {
let tags =
db
|> database.tags()
|> dict.map_values(fn(_key, posts) {
int.to_float(ordered_tree.length(posts))
})
let most_posts =
tags
|> dict.values()
|> list.fold(0.0, float.max)
tags
|> dict.to_list()
|> list.sort(fn(a, b) {
string.compare(string.lowercase(a.0), string.lowercase(b.0))
})
|> list.map(fn(item) {
let #(tag, post_count) = item
let percentage =
float.round(
{
{ { post_count /. most_posts } *. { 1.0 -. tag_min_size } }
+. tag_min_size
}
*. 100.0,
)
li([], [
a(
[
href(config.paths.html(config.paths.root <> config.paths.tag(tag))),
style([#("font-size", int.to_string(percentage) <> "%")]),
],
[text(tag)],
),
])
})
|> ul([], _)
}
fn archives(db: Database, config: Configuration) {
db
|> database.years()
|> dict.to_list()
|> list.sort(fn(a, b) { int.compare(a.0, b.0) })
|> list.fold([], fn(year_archive, year) {
let #(year, months) = year
[
li([], [
a(
[
href(config.paths.html(
config.paths.root
<> config.paths.list_page(config.paths.year(year), 1),
)),
],
[text(int.to_string(year))],
),
ul(
[],
list.fold(date.months, [], fn(month_archive, month) {
case dict.get(months, month) {
Ok(posts) -> [
li([], [
a(
[
href(config.paths.html(
config.paths.root
<> config.paths.list_page(
config.paths.month(year, month),
1,
),
)),
],
[
text(
date.month_to_string(month)
<> " ("
<> int.to_string(ordered_tree.length(posts))
<> ")",
),
],
),
]),
..month_archive
]
Error(_) -> month_archive
}
}),
),
]),
..year_archive
]
})
|> ul([], _)
}
fn menu(menu: List(MenuItem)) {
nav([], [
ul(

View file

@ -0,0 +1,58 @@
//// The tags component renders tags of the database as a tag cloud with tags of
//// varying sizes as an unordered list.
import gleam/dict
import gleam/float
import gleam/int
import gleam/list
import gleam/string
import lustre/attribute.{href, style}
import lustre/element.{text}
import lustre/element/html.{a, li, ul}
import scriptorium/config.{type Configuration}
import scriptorium/models/database.{type Database}
import scriptorium/utils/ordered_tree
const tag_min_size = 0.5
pub fn view(db: Database, config: Configuration) {
let tags =
db
|> database.tags()
|> dict.map_values(fn(_key, posts) {
int.to_float(ordered_tree.length(posts))
})
let most_posts =
tags
|> dict.values()
|> list.fold(0.0, float.max)
tags
|> dict.to_list()
|> list.sort(fn(a, b) {
string.compare(string.lowercase(a.0), string.lowercase(b.0))
})
|> list.map(fn(item) {
let #(tag, post_count) = item
let percentage =
float.round(
{
{ { post_count /. most_posts } *. { 1.0 -. tag_min_size } }
+. tag_min_size
}
*. 100.0,
)
li([], [
a(
[
href(config.paths.html(config.paths.root <> config.paths.tag(tag))),
style([#("font-size", int.to_string(percentage) <> "%")]),
],
[text(tag)],
),
])
})
|> ul([], _)
}