howdy/ui/export

Write the CSS for a published site to a file.

The runtime route in ui.stylesheet only knows classes that have been rendered, and differs between nodes. For publishing, write one file from a known list of classes instead. Put a script module in your project and run it with gleam run -m tasks/css:

// src/tasks/css.gleam
import howdy/ui/export
import howdy/ui/theme
import my_styles

pub fn main() {
  let assert Ok(Nil) =
    export.new(theme.default_themes())
    |> export.classes(my_styles.all())
    |> export.write(to: "priv/static/ui.css")
}

The built-in components are always included. Serve the file with howdy/static and link it from pages with page.stylesheet, adding whatever cache-busting you use for other assets:

howdy.controller(static.new(from: "priv/static") |> static.at("/assets") |> static.max_age(seconds: 31_536_000) |> static.build)
page.stylesheet(page, at: "/assets/ui.css?v=" <> my_app.version)

The output is minified and deterministic: the same classes give the same bytes on every machine, in the configured class-list order.

Types

A file under construction.

pub opaque type Export

Values

pub fn classes(
  export: Export,
  classes: List(css.Class),
) -> Export

Add classes of your own, usually the all list of a styles module.

pub fn minify(css: String) -> String

Conservatively compact generated CSS. Preserve descendant-selector spaces before colons and whitespace inside strings and arithmetic expressions. Inputs with escapes, comments or URLs are returned unchanged: handling their token boundaries requires a full CSS tokenizer.

pub fn new(themes: theme.Themes) -> Export

Start with the themes the site offers and the built-in components: their classes and the rules they register with style.rule.

pub fn rules(
  export: Export,
  rules: List(#(String, String)),
) -> Export

Add CSS of your own that components register with style.rule, such as the rules list of a copied component. Each name is written once.

pub fn to_css(export: Export) -> String

The finished CSS in configured class order, then the rules, conservatively minified.

pub fn write(
  export: Export,
  to path: String,
) -> Result(Nil, simplifile.FileError)

Write the CSS to path, creating parent directories as needed.

✨ Search Document