Current section

Files

Jump to
scriptorium src scriptorium compiler.gleam
Raw

src/scriptorium/compiler.gleam

//// Compiling means turning post and page content into HTML. By default this
//// content is Markdown that is compiled with Marked.js.
import gleam/dict.{type Dict}
import gleam/list
import gleam/option
import scriptorium/models/database.{type Database, type PostID}
import scriptorium/models/page.{type Page}
import scriptorium/models/post.{type Post}
import scriptorium/utils/marked
import scriptorium/utils/ordered_tree
/// Compiled post content: strings that contain HTML.
pub type PostContent {
PostContent(full: String, short: option.Option(String))
}
/// A post and its compiled content.
pub type CompiledPost {
CompiledPost(orig: Post, content: PostContent)
}
/// A page and its compiled content.
pub type CompiledPage {
CompiledPage(orig: Page, content: String)
}
/// A function to compile the given string content into an HTML string.
pub type Compiler =
fn(String, Database) -> String
/// Structure where the compilation results are stored.
pub type CompileDatabase {
CompileDatabase(posts: Dict(PostID, CompiledPost), pages: List(CompiledPage))
}
/// The default compiler that uses Marked.js with default settings.
pub fn default_compiler(content: String, _db: Database) {
marked.default_parse(content)
}
/// Compile contents of the database using the given compiler.
pub fn compile(db: Database, compiler: Compiler) {
CompileDatabase(
posts: compile_posts(db, compiler),
pages: compile_pages(db, compiler),
)
}
/// Compile all posts in the database using the given compiler.
pub fn compile_posts(
db: Database,
compiler: Compiler,
) -> Dict(PostID, CompiledPost) {
let posts =
database.get_posts_with_ids(db, ordered_tree.Asc)
|> list.map(fn(post_with_id) {
let content = compiler(post_with_id.post.content, db)
let short_content =
option.map(post_with_id.post.short_content, compiler(_, db))
#(
post_with_id.id,
CompiledPost(
post_with_id.post,
content: PostContent(full: content, short: short_content),
),
)
})
dict.from_list(posts)
}
/// Compile all pages in the database using the given compiler.
pub fn compile_pages(db: Database, compiler: Compiler) {
database.pages(db)
|> list.map(fn(page) {
let content = compiler(page.content, db)
CompiledPage(orig: page, content: content)
})
}