Current section

Files

Jump to
arctic src arctic.gleam
Raw

src/arctic.gleam

import birl.{type Time}
import gleam/dict.{type Dict}
import gleam/option.{type Option}
import gleam/order.{type Order}
import gleam/result
import gleam/string
import lustre/element.{type Element}
import snag.{type Result}
/// A particular organization of pages,
/// written either in custom markup or raw HTML.
/// A collection might be a set of products, or blog posts, or wiki entries.
/// A dedicated page can be generated to show off the pages in a collection,
/// and RSS feeds and whatnot can also be generated from the set of pages.
/// The pages are pulled from a particular directory,
/// and parsed and rendered a particular way,
/// that might be different from other collections.
/// See `arctic/collection` for more.
pub type Collection {
Collection(
directory: String,
parse: fn(String, String) -> Result(Page),
index: Option(fn(List(CacheablePage)) -> Element(Nil)),
feed: Option(#(String, fn(List(CacheablePage)) -> String)),
ordering: fn(Page, Page) -> Order,
render: fn(Page) -> Element(Nil),
raw_pages: List(RawPage),
)
}
/// A single page in a collection.
/// These must have an ID to distinguish from other pages in the collection,
/// and a body of HTML elements.
/// Any other metadata can be added (stringly typed),
/// and there are a variety of privileged metadata fields
/// like `.title` and `.date` that are actual typed properties.
/// However, these fields are optional.
/// See `arctic/page` for more.
pub type Page {
Page(
id: String,
body: List(Element(Nil)),
metadata: Dict(String, String),
title: String,
blerb: String,
tags: List(String),
date: Option(Time),
)
}
pub type CacheablePage {
CachedPage(path: String, metadata: Dict(String, String))
NewPage(Page)
}
pub fn to_dummy_page(c: CacheablePage) -> Page {
case c {
CachedPage(_, metadata) -> {
let title = metadata |> dict.get("title") |> result.unwrap("")
let blerb = metadata |> dict.get("blerb") |> result.unwrap("")
let tags =
metadata
|> dict.get("tags")
|> result.map(string.split(_, on: ","))
|> result.unwrap([])
let date =
metadata
|> dict.get("date")
|> result.try(birl.parse)
|> option.from_result
Page(get_id(c), [], metadata:, title:, blerb:, tags:, date:)
}
NewPage(p) -> p
}
}
pub fn get_id(p: CacheablePage) -> String {
case p {
CachedPage(_, metadata) -> {
let assert Ok(id) = dict.get(metadata, "id")
id
}
NewPage(page) -> page.id
}
}
pub fn output_path(input_path: String) -> String {
let assert [start, ""] = string.split(input_path, ".txt")
"arctic_build/" <> start <> "/index.html"
}
/// A collection whose pages have been processed from the files.
pub type ProcessedCollection {
ProcessedCollection(collection: Collection, pages: List(CacheablePage))
}
/// A page that is just HTML produced by hand.
pub type RawPage {
RawPage(id: String, html: Element(Nil))
}
/// An Arctic configuration, describing all the collections, pages, parsing rules, etc.
pub type Config {
Config(
render_home: fn(List(ProcessedCollection)) -> Element(Nil),
main_pages: List(RawPage),
collections: List(Collection),
render_spa: Option(fn(Element(Nil)) -> Element(Nil)),
)
}