maud/components
Customizable component configuration for rendering Markdown into Lustre elements.
This module defines the Components type, a record of view functions that control
how each Markdown construct is rendered. Use default() for standard HTML output,
or override individual components to apply custom styling.
Usage
import maud/components
// Use defaults
let c = components.default()
// Override specific components via piping
let c =
components.default()
|> components.h1(fn(_attributes, _id, children) { html.h1([attribute.class("title")], children) })
|> components.p(fn(_attributes, children) { html.p([attribute.class("body")], children) })
Types
Text alignment for table cells.
pub type Alignment {
Left
Center
Right
}
Constructors
-
LeftLeft-aligned text (the default for most table cells).
-
CenterCenter-aligned text.
-
RightRight-aligned text.
A record of view functions that control how each Markdown element is rendered.
Components are rendered bottom-up: children are rendered first, then passed
to the parent component function as a List(Element(a)). When implementing
a custom component, you must pass the children into the element you return,
otherwise they will not appear in the output.
Components for every element that can carry author-supplied attributes
(a, blockquote, code, h1–h6, img, p, pre) receive a
Dict(String, String) of those attributes as their first argument. These
are the annotations (for example a class or key/value pair) attached to the
element in the source document, letting a component react to per-element
styling instead of resorting to content sniffing.
pub type Components(a) {
Components(
a: fn(
dict.Dict(String, String),
String,
option.Option(String),
List(element.Element(a)),
) -> element.Element(a),
blockquote: fn(
dict.Dict(String, String),
List(element.Element(a)),
) -> element.Element(a),
checkbox: fn(Bool) -> element.Element(a),
code: fn(
dict.Dict(String, String),
option.Option(String),
List(element.Element(a)),
) -> element.Element(a),
del: fn(List(element.Element(a))) -> element.Element(a),
em: fn(List(element.Element(a))) -> element.Element(a),
footnote: fn(Int, List(element.Element(a))) -> element.Element(
a,
),
h1: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
h2: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
h3: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
h4: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
h5: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
h6: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
hr: fn() -> element.Element(a),
img: fn(
dict.Dict(String, String),
String,
String,
option.Option(String),
) -> element.Element(a),
li: fn(List(element.Element(a))) -> element.Element(a),
mark: fn(List(element.Element(a))) -> element.Element(a),
ol: fn(option.Option(Int), List(element.Element(a))) -> element.Element(
a,
),
p: fn(dict.Dict(String, String), List(element.Element(a))) -> element.Element(
a,
),
pre: fn(dict.Dict(String, String), List(element.Element(a))) -> element.Element(
a,
),
strong: fn(List(element.Element(a))) -> element.Element(a),
table: fn(List(element.Element(a))) -> element.Element(a),
tbody: fn(List(element.Element(a))) -> element.Element(a),
td: fn(Alignment, List(element.Element(a))) -> element.Element(
a,
),
th: fn(Alignment, List(element.Element(a))) -> element.Element(
a,
),
thead: fn(List(element.Element(a))) -> element.Element(a),
tr: fn(List(element.Element(a))) -> element.Element(a),
ul: fn(List(element.Element(a))) -> element.Element(a),
)
}
Constructors
-
Components( a: fn( dict.Dict(String, String), String, option.Option(String), List(element.Element(a)), ) -> element.Element(a), blockquote: fn( dict.Dict(String, String), List(element.Element(a)), ) -> element.Element(a), checkbox: fn(Bool) -> element.Element(a), code: fn( dict.Dict(String, String), option.Option(String), List(element.Element(a)), ) -> element.Element(a), del: fn(List(element.Element(a))) -> element.Element(a), em: fn(List(element.Element(a))) -> element.Element(a), footnote: fn(Int, List(element.Element(a))) -> element.Element( a, ), h1: fn( dict.Dict(String, String), String, List(element.Element(a)), ) -> element.Element(a), h2: fn( dict.Dict(String, String), String, List(element.Element(a)), ) -> element.Element(a), h3: fn( dict.Dict(String, String), String, List(element.Element(a)), ) -> element.Element(a), h4: fn( dict.Dict(String, String), String, List(element.Element(a)), ) -> element.Element(a), h5: fn( dict.Dict(String, String), String, List(element.Element(a)), ) -> element.Element(a), h6: fn( dict.Dict(String, String), String, List(element.Element(a)), ) -> element.Element(a), hr: fn() -> element.Element(a), img: fn( dict.Dict(String, String), String, String, option.Option(String), ) -> element.Element(a), li: fn(List(element.Element(a))) -> element.Element(a), mark: fn(List(element.Element(a))) -> element.Element(a), ol: fn(option.Option(Int), List(element.Element(a))) -> element.Element( a, ), p: fn(dict.Dict(String, String), List(element.Element(a))) -> element.Element( a, ), pre: fn(dict.Dict(String, String), List(element.Element(a))) -> element.Element( a, ), strong: fn(List(element.Element(a))) -> element.Element(a), table: fn(List(element.Element(a))) -> element.Element(a), tbody: fn(List(element.Element(a))) -> element.Element(a), td: fn(Alignment, List(element.Element(a))) -> element.Element( a, ), th: fn(Alignment, List(element.Element(a))) -> element.Element( a, ), thead: fn(List(element.Element(a))) -> element.Element(a), tr: fn(List(element.Element(a))) -> element.Element(a), ul: fn(List(element.Element(a))) -> element.Element(a), )
Values
pub fn a(
components: Components(a),
view: fn(
dict.Dict(String, String),
String,
option.Option(String),
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the a component used for links.
The first argument is the link’s attributes, the second is the link href, the third is an optional title, and the fourth is the list of children elements.
Examples
components.default()
|> components.a(fn(_attributes, href, _title, children) {
html.a([attribute.href(href), attribute.class("link")], children)
})
pub fn blockquote(
components: Components(a),
blockquote: fn(
dict.Dict(String, String),
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the blockquote component used for block quotes.
The first argument is the blockquote’s attributes, the second is the list of children elements.
Examples
components.default()
|> components.blockquote(fn(_attributes, children) {
html.blockquote([attribute.class("quote")], children)
})
pub fn checkbox(
components: Components(a),
checkbox: fn(Bool) -> element.Element(a),
) -> Components(a)
Set the checkbox component used for task list checkboxes.
The first argument indicates whether the checkbox is checked.
pub fn code(
components: Components(a),
code: fn(
dict.Dict(String, String),
option.Option(String),
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the code component used for inline code and code blocks.
The first argument is the code’s attributes (only fenced code blocks carry
these; inline code receives an empty dictionary). The second argument is the
optional language identifier (e.g. Some("gleam") for fenced code blocks
with a language tag, None for inline code). The third is the children.
Examples
components.default()
|> components.code(fn(_attributes, language, children) {
case language {
option.Some(lang) ->
html.code([attribute.class("lang-" <> lang)], children)
option.None -> html.code([attribute.class("code")], children)
}
})
pub fn default() -> Components(a)
Return the default components, rendering each Markdown element as its corresponding HTML element without additional attributes or styling.
Examples
let c = components.default()
pub fn del(
components: Components(a),
del: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the del component used for strikethrough text.
Examples
components.default()
|> components.del(fn(children) {
html.del([attribute.class("strikethrough")], children)
})
pub fn em(
components: Components(a),
em: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the em component used for emphasized (italic) text.
pub fn footnote(
components: Components(a),
footnote: fn(Int, List(element.Element(a))) -> element.Element(
a,
),
) -> Components(a)
Set the footnote component used for footnote references.
The first argument is the footnote number, the second is the children elements.
Note: the default implementation renders a forward reference only (no back-link from the footnote body to the reference site).
pub fn h1(
components: Components(a),
h1: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the h1 component used for level 1 headings.
The first argument is the heading’s attributes, the second is the heading id, the third is the children elements.
Examples
components.default()
|> components.h1(fn(_attributes, id, children) {
html.h1([attribute.id(id), attribute.class("heading")], children)
})
pub fn h2(
components: Components(a),
h2: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the h2 component used for level 2 headings.
The first argument is the heading’s attributes, the second is the heading id, the third is the children elements.
pub fn h3(
components: Components(a),
h3: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the h3 component used for level 3 headings.
The first argument is the heading’s attributes, the second is the heading id, the third is the children elements.
pub fn h4(
components: Components(a),
h4: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the h4 component used for level 4 headings.
The first argument is the heading’s attributes, the second is the heading id, the third is the children elements.
pub fn h5(
components: Components(a),
h5: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the h5 component used for level 5 headings.
The first argument is the heading’s attributes, the second is the heading id, the third is the children elements.
pub fn h6(
components: Components(a),
h6: fn(
dict.Dict(String, String),
String,
List(element.Element(a)),
) -> element.Element(a),
) -> Components(a)
Set the h6 component used for level 6 headings.
The first argument is the heading’s attributes, the second is the heading id, the third is the children elements.
pub fn hr(
components: Components(a),
hr: fn() -> element.Element(a),
) -> Components(a)
Set the hr component used for thematic breaks (horizontal rules).
pub fn img(
components: Components(a),
img: fn(
dict.Dict(String, String),
String,
String,
option.Option(String),
) -> element.Element(a),
) -> Components(a)
Set the img component used for images.
The first argument is the image’s attributes, the second is the image URI, the third is the alt text extracted from the image’s inline content, and the fourth is an optional title.
pub fn li(
components: Components(a),
li: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the li component used for list items.
pub fn mark(
components: Components(a),
mark: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the mark component used for highlighted text.
pub fn ol(
components: Components(a),
ol: fn(option.Option(Int), List(element.Element(a))) -> element.Element(
a,
),
) -> Components(a)
Set the ol component used for ordered lists.
The first argument is an optional start number, the second is the list of children elements.
pub fn p(
components: Components(a),
p: fn(dict.Dict(String, String), List(element.Element(a))) -> element.Element(
a,
),
) -> Components(a)
Set the p component used for paragraphs.
The first argument is the paragraph’s attributes, the second is the list of children elements.
pub fn pre(
components: Components(a),
pre: fn(dict.Dict(String, String), List(element.Element(a))) -> element.Element(
a,
),
) -> Components(a)
Set the pre component used for preformatted code blocks.
The first argument is the code block’s attributes, the second is the list of children elements.
pub fn strong(
components: Components(a),
strong: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the strong component used for bold text.
pub fn table(
components: Components(a),
table: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the table component used for tables.
pub fn tbody(
components: Components(a),
tbody: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the tbody component used for table body groups.
pub fn td(
components: Components(a),
td: fn(Alignment, List(element.Element(a))) -> element.Element(
a,
),
) -> Components(a)
Set the td component used for table data cells.
The first argument is the column alignment, the second is the list of children elements.
pub fn th(
components: Components(a),
th: fn(Alignment, List(element.Element(a))) -> element.Element(
a,
),
) -> Components(a)
Set the th component used for table header cells.
The first argument is the column alignment, the second is the list of children elements.
pub fn thead(
components: Components(a),
thead: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the thead component used for table header groups.
pub fn tr(
components: Components(a),
tr: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the tr component used for table rows.
pub fn ul(
components: Components(a),
ul: fn(List(element.Element(a))) -> element.Element(a),
) -> Components(a)
Set the ul component used for unordered lists.