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/dict
|
||||||
import gleam/float
|
|
||||||
import gleam/int
|
|
||||||
import gleam/list
|
import gleam/list
|
||||||
import gleam/option
|
import gleam/option
|
||||||
import gleam/string
|
import lustre/attribute.{attribute, href, id, name, rel, role, type_}
|
||||||
import lustre/attribute.{attribute, href, id, name, rel, role, style, type_}
|
|
||||||
import lustre/element.{type Element, text}
|
import lustre/element.{type Element, text}
|
||||||
import lustre/element/html.{
|
import lustre/element/html.{
|
||||||
a, body, footer, h1, head, header, html, li, link, main, meta, nav, p, section,
|
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/config.{type Configuration}
|
||||||
import scriptorium/models/database.{type Database}
|
import scriptorium/models/database.{type Database}
|
||||||
import scriptorium/models/menu.{type MenuItem}
|
import scriptorium/models/menu.{type MenuItem}
|
||||||
import scriptorium/utils/date
|
import scriptorium/rendering/views/archives
|
||||||
import scriptorium/utils/ordered_tree
|
import scriptorium/rendering/views/tags
|
||||||
|
|
||||||
const tag_min_size = 0.5
|
|
||||||
|
|
||||||
/// The base view pre-renders some content once, so that it can be reused for every render.
|
/// The base view pre-renders some content once, so that it can be reused for every render.
|
||||||
pub type PreRendered {
|
pub type PreRendered {
|
||||||
|
@ -24,13 +19,20 @@ pub type PreRendered {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(db: Database, config: Configuration) {
|
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) {
|
fn(inner: Element(Nil), extra_meta: List(Element(Nil)), title_prefix: String) {
|
||||||
view(db, config, pre_rendered, inner, extra_meta, title_prefix)
|
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))
|
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)) {
|
fn menu(menu: List(MenuItem)) {
|
||||||
nav([], [
|
nav([], [
|
||||||
ul(
|
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