lucid: Clear to write, read and edit DSL for HTML

[ bsd3, library, web ] [ Propose Tags ] [ Report a vulnerability ]

Clear to write, read and edit DSL for HTML.

  • Names are consistent, and do not conflict with base or are keywords (all have suffix _)

  • Same combinator can be used for attributes and elements (e.g. style_)

  • For more, read the blog post

See the Lucid module for more documentation.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.0, 0.1, 0.2, 0.3, 0.4, 1.0, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6.0, 2.6.1, 2.7.0, 2.8.0, 2.8.1, 2.9.0, 2.9.1, 2.9.2, 2.9.3, 2.9.4, 2.9.5, 2.9.6, 2.9.7, 2.9.8, 2.9.8.1, 2.9.9, 2.9.10, 2.9.11, 2.9.12, 2.9.12.1, 2.9.13, 2.10.0, 2.11.0, 2.11.1, 2.11.20230408, 2.11.20250303 (info)
Change log CHANGELOG.md
Dependencies base (>=4.8 && <4.22), blaze-builder (>=0.4.0.0), bytestring (>=0.10.6.0), containers (>=0.5.6.2), hashable (>=1.2.3.2), mmorph (>=1.0.3), mtl (>=2.2), semigroups (>=0.16.1), text (>=1.2.0.2), transformers (>=0.4.2.0) [details]
Tested with ghc ==7.10.3, ghc ==8.0.2, ghc ==8.2.2, ghc ==8.4.4, ghc ==8.6.5, ghc ==8.8.4, ghc ==8.10.7, ghc ==9.0.1, ghc ==9.2.1, ghc ==9.4.1
License BSD-3-Clause
Copyright 2014-2021 Chris Done
Author Chris Done
Maintainer chrisdone@gmail.com
Category Web
Home page https://github.com/chrisdone/lucid
Source repo head: git clone https://github.com/chrisdone/lucid.git
Uploaded by ChrisDone at 2025-03-03T16:01:00Z
Distributions Arch:2.11.20230408, Debian:2.9.12, Fedora:2.11.20230408, LTSHaskell:2.11.20250303, NixOS:2.11.20230408, Stackage:2.11.20250303, openSUSE:2.11.20230408
Reverse Dependencies 82 direct, 110 indirect [details]
Downloads 47802 total (247 in the last 30 days)
Rating 2.5 (votes: 3) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2025-03-03 [all 1 reports]

Readme for lucid-2.11.20250303

[back to package description]

lucid Hackage Build Status

Clear to write, read and edit DSL for writing HTML

Table of Contents

Introduction

HTML terms in Lucid are written with a postfix ‘_’ to indicate data rather than code. Some examples:

p_, class_, table_, style_

See Lucid.Html5 for a complete list of Html5 combinators.

Plain text is written using the OverloadedStrings and ExtendedDefaultRules extensions, and is automatically escaped:

λ> "123 < 456" :: Html ()
123 &lt; 456

Elements nest by function application:

λ> table_ (tr_ (td_ (p_ "Hello, World!"))) :: Html ()
<table><tr><td><p>Hello, World!</p></td></tr></table>

Elements are juxtaposed via monoidal append:

λ> p_ "hello" <> p_ "sup" :: Html ()
<p>hello</p><p>sup</p>

Or monadic sequencing:

λ> div_ (do p_ "hello"; p_ "sup") :: Html ()
<div><p>hello</p><p>sup</p></div>

Attributes are set by providing an argument list:

λ> p_ [class_ "brand"] "Lucid Inc" :: Html ()
<p class="brand">Lucid Inc</p>

Here is a fuller example of Lucid:

table_ [rows_ "2"]
       (tr_ (do td_ [class_ "top",colspan_ "2",style_ "color:red"]
                    (p_ "Hello, attributes!")
                td_ "yay!"))
<table rows="2">
  <tr>
    <td style="color:red" colspan="2" class="top">
      <p>Hello, attributes!</p>
    </td>
    <td>yay!</td>
  </tr>
</table>

Rendering

For proper rendering you can easily run some HTML immediately with:

λ> renderText (p_ "Hello!")
"<p>Hello!</p>"

Or to bytes:

λ> renderBS (p_ [style_ "color:red"] "Hello!")
"<p style=\"color:red\">Hello!</p>"

For ease of use in GHCi, there is a Show instance, as demonstrated above.

If the above rendering functions aren't suited for your purpose, you can run the monad directly via execHtml and use the more low-level blaze Builder, which has a plethora of output modes in Blaze.ByteString.Builder.

See the documentation for the Lucid module for information about using it as a monad transformer.

Good to know

  • Attributes are escaped, so you cannot write arbitrary JavaScript in attributes. Instead, do something like onclick_ "foo()".
  • Attributes are rendered in the order that they are written in your Haskell code.

Transforming

You can use lift to call parent monads.

λ> runReader (renderTextT (html_ (body_ (do name <- lift ask
                                            p_ [class_ "name"] (toHtml name)))))
             ("Chris" :: String)
"<html><body><p class=\"name\">Chris</p></body></html>"