Split tags and archives into their own components
This commit is contained in:
parent
89402f5dce
commit
a00a808618
3 changed files with 140 additions and 109 deletions
70
src/scriptorium/rendering/views/archives.gleam
Normal file
70
src/scriptorium/rendering/views/archives.gleam
Normal 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([], _)
|
||||
}
|
|
@ -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(
|
||||
|
|
58
src/scriptorium/rendering/views/tags.gleam
Normal file
58
src/scriptorium/rendering/views/tags.gleam
Normal 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([], _)
|
||||
}
|
Loading…
Reference in a new issue