//// 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) }) }