Current section
Files
Jump to
Current section
Files
src/scriptorium/rendering/views/meta.gleam
import gleam/dict
import gleam/list
import gleam/option
import gleam/result
import scriptorium/config.{type Configuration}
import scriptorium/models/database.{type Database}
import scriptorium/models/page
import scriptorium/models/post
import scriptorium/rendering/views.{type PageType, Other, Page, Post}
import lustre/attribute
import lustre/element/html
pub fn generate(_db: Database, config: Configuration) {
fn(page_type: PageType) {
list.flatten([
[
name_meta("author", config.author.name),
name_meta("description", description(page_type)),
// Schema.org
itemprop_meta("name", title(page_type)),
itemprop_meta("author", config.author.name),
itemprop_meta("headline", title(page_type)),
itemprop_meta("description", description(page_type)),
// Twitter/X card
name_meta("twitter:card", "summary_large_image"),
name_meta("twitter:site", ""),
name_meta("twitter:title", title(page_type)),
name_meta("twitter:description", description(page_type)),
name_meta("twitter:creator", ""),
// Open Graph
property_meta("og:title", title(page_type)),
property_meta("og:type", case page_type {
Post(..) | Page(..) -> "article"
_ -> "website"
}),
property_meta("og:description", description(page_type)),
property_meta("og:site_name", config.blog_name),
],
case page_type {
Post(post) -> {
let timestamp = post.to_iso8601(post)
let image =
post.headers
|> dict.from_list()
|> dict.get("image")
|> option.from_result()
[
property_meta("article:published_time", timestamp),
itemprop_meta("datePublished", timestamp),
property_meta(
"og:url",
config.blog_url <> config.paths.single_post(post),
),
..case image {
option.Some(image) -> [
name_meta("twitter:image", image),
property_meta("og:image", image),
itemprop_meta("image", image),
]
option.None -> []
}
]
}
Page(page) -> [
property_meta("og:url", config.blog_url <> config.paths.page(page)),
]
_ -> []
},
])
}
}
fn name_meta(name: String, content: String) {
meta("name", name, content)
}
fn itemprop_meta(itemprop: String, content: String) {
meta("itemprop", itemprop, content)
}
fn property_meta(property: String, content: String) {
meta("property", property, content)
}
fn meta(attr_name: String, attr_value: String, content: String) {
html.meta([
attribute.attribute(attr_name, attr_value),
attribute.attribute("content", content),
])
}
fn description(page_type: PageType) {
case page_type {
Post(post.Post(headers: headers, ..))
| Page(page.Page(headers: headers, ..)) ->
headers
|> dict.from_list()
|> dict.get("description")
|> result.unwrap("")
Other(description: description, ..) -> description
}
}
fn title(page_type: PageType) {
case page_type {
Post(post.Post(title: title, ..))
| Page(page.Page(title: title, ..))
| Other(title: title, ..) -> title
}
}