Lucid HTML DSL

repository·master·Indexed 43 days ago

https://github.com/chrisdone/lucid

A domain-specific language for writing HTML in Haskell. Lucid uses a postfix underscore convention for elements and attributes (e.g., p_, class_) and supports nesting via function application, monoidal append (<>), and monadic sequencing. It provides automatic escaping for text and attributes to prevent XSS and supports rendering to Text or ByteString via renderText and renderBS. The library can be integrated into monad transformer stacks using renderTextT and lift.

Tokens
1.4K
Snippets
6
Records
9
Agent score
50%

What's inside Lucid

  1. Introduction to Lucid DSL

    master

    Lucid is a DSL for writing HTML in Haskell. It uses a postfix underscore (_) to distinguish HTML elements (data) from standard Haskell functions (code).

    Core Syntax Patterns

    • Elements: Written with a postfix underscore (e.g., p_, div_, table_).
    • Nesting: Elements are nested using function application.
    • Juxtaposition: Elements can be placed side-by-side using monoidal append (<>) or monadic sequencing (do blocks).
    • Attributes: Attributes are set by providing an argument list before the content. Attributes also use the postfix underscore (e.g., class_, style_).
    • Text: Plain text is automatically escaped to prevent XSS.
    -- Nesting via function application
    table_ (tr_ (td_ (p_ "Hello, World!")))
    
    -- Juxtaposition via monoidal append
    p_ "hello" <> p_ "sup"
    
    -- Juxtaposition via monadic sequencing
    div_ (do p_ "hello"; p_ "sup")
    
    -- Setting attributes
    p_ [class_ "brand"] "Lucid Inc"
  2. Choose between lucid1 and lucid2

    master

    Lucid is a Domain Specific Language (DSL) for writing HTML. The repository contains two distinct versions:

    • lucid2: The latest version. If you are starting a new project, use this version. It is released on Hackage as lucid2.
    • lucid1: The original version. It is released on Hackage as lucid.

    Refer to the changelog in the lucid2 directory to understand the differences between the two versions.

  3. Important constraints and behaviors in Lucid

    master

    When using Lucid, keep the following behaviors in mind:

    • Attribute Escaping: Attributes are automatically escaped. You cannot write arbitrary JavaScript directly inside an attribute string. To execute JS, use an event handler attribute like onclick_ "foo()".
    • Attribute Order: Attributes are rendered in the exact order they are written in your Haskell code.
    • Text Escaping: Plain text is automatically escaped (e.g., < becomes &lt;).
  4. How to nest and sequence HTML elements in Lucid

    master

    Lucid provides multiple ways to structure HTML content:

    1. Nesting via Function Application: Use standard function application for simple hierarchies.
    2. Monoidal Append: Use the <> operator to juxtapose elements.
    3. Monadic Sequencing: Use do notation within a block to sequence multiple elements.

    Note: Plain text is automatically escaped when using OverloadedStrings and ExtendedDefaultRules extensions.

    -- Nesting
    table_ (tr_ (td_ (p_ "Hello, World!")))
    
    -- Juxtaposition (Monoidal)
    p_ "hello" <> p_ "sup"
    
    -- Sequencing (Monadic)
    div_ (do p_ "hello"; p_ "sup")
  5. Transforming Lucid HTML with Monad Transformers

    master

    Lucid can be used within a monad transformer stack. You can use lift to access parent monads (like Reader) while generating HTML. For example, you can use renderTextT to render HTML while pulling values from a Reader context.

    runReader (renderTextT (html_ (body_ (do name <- lift ask
                                                p_ [class_ "name"] (toHtml name))))) 
              ("Chris" :: String)
  6. Transform Lucid HTML using Monad Transformers

    master

    Lucid can be used within a monad transformer stack. You can use renderTextT (or similar transformer versions) and lift to access parent monads (like Reader or State) while generating HTML.

    runReader (renderTextT (html_ (body_ (do name <- lift ask
                                                p_ [class_ "name"] (toHtml name))))) 
             ("Chris" :: String)
  7. Set attributes on HTML elements

    master

    Attributes are set by providing a list of attribute functions as the first argument to an element function. Attributes are rendered in the order they are written in the code.

    Important: Attributes are escaped. To include JavaScript, use the attribute name (e.g., onclick_ "foo()") rather than trying to write raw script inside the attribute value.

    -- Single attribute
    p_ [class_ "brand"] "Lucid Inc"
    
    -- Multiple attributes
    td_ [class_ "top", colspan_ "2", style_ "color:red"] (p_ "Hello!")
  8. Render Lucid HTML to Text or Bytes

    master

    To convert Lucid HTML definitions into actual output, use the following rendering functions:

    • renderText: Renders the HTML to a Text value.
    • renderBS: Renders the HTML to a ByteString.

    For low-level control, you can run the monad directly via execHtml to use the Blaze.ByteString.Builder output modes.

    -- Render to Text
    renderText (p_ "Hello!")
    
    -- Render to ByteString
    renderBS (p_ [style_ "color:red"] "Hello!")
  9. Introduction to Lucid HTML DSL

    master

    Lucid is a Domain Specific Language (DSL) for writing HTML in Haskell. It uses a postfix underscore (_) convention for HTML tags to distinguish them from data.

    Key syntax patterns:

    • Elements: Written as functions with a postfix underscore (e.g., p_, div_, table_).
    • Nesting: Achieved via function application: `tag_ (child_