-- | Clear to write, read and edit DSL for writing HTML -- -- See "Lucid.Html5" for a complete list of Html5 combinators. That -- module is re-exported from this module for your convenience. -- -- See "Lucid.Base" for lower level functions like -- `makeElement`, `makeAttribute`, 'termRaw', etc. module Lucid (-- * Intro -- $intro renderText ,renderBS ,renderTextT ,renderBST ,renderToFile -- * Running -- $running ,execHtmlT ,evalHtmlT ,runHtmlT -- * Types ,Html ,HtmlT ,Attribute -- * Classes -- $overloaded ,Term(..) ,ToHtml(..) ,With(..) -- * Re-exports ,module Lucid.Html5) where import Lucid.Base import Lucid.Html5 -- $intro -- -- HTML terms in Lucid are written with a postfix ‘@_@’ to indicate data -- rather than code. Some examples: -- -- 'p_', 'class_', 'table_', 'style_' -- -- Note: If you're testing in the REPL you need to add a type annotation to -- indicate that you want HTML. In normal code your top-level -- declaration signatures handle that. -- -- For GHCi: -- -- @ -- :set -XOverloadedStrings -XExtendedDefaultRules@ -- import Lucid -- @ -- -- In a module: @{-\# LANGUAGE OverloadedStrings, ExtendedDefaultRules \#-}@ -- -- Plain text is written like this, and is automatically escaped: -- -- >>> "123 < 456" :: Html () -- 123 < 456 -- -- Except some elements, like 'script_': -- -- >>> script_ "alert('Hello!' > 12)" :: Html () -- <script>alert('Hello!' > 12)</script> -- -- 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 (remember to import "Data.Monoid"): -- -- >>> 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> -- -- >>> p_ [data_ "zot" "foo",checked_] "Go!" :: Html () -- <p data-zot="foo" checked>go</p> -- -- Attribute and element terms are not conflicting: -- -- >>> style_ [style_ "inception"] "Go deeper." :: Html () -- <style style="inception">Go deeper.</style> -- -- 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!")) -- @ -- -- Elements (and some attributes) are variadic and overloaded, see the -- 'Term' class for more explanation about that. -- -- For proper rendering you can easily run some HTML immediately with: -- -- >>> renderText (p_ "Hello!") -- > "<p>Hello!</p>" -- -- >>> 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. -- $overloaded -- -- To support convenient use of HTML terms, HTML terms are -- overloaded. Here are the following types possible for an element -- term accepting attributes and/or children: -- -- @ -- p_ :: Term arg result => arg -> result -- p_ :: Monad m => [Attribute] -> HtmlT m () -> HtmlT m () -- p_ :: Monad m => HtmlT m () -> HtmlT m () -- @ -- -- The first is the generic form. The latter two are the possible -- types for an element. -- -- Elements that accept no content are always concrete: -- -- @ -- input_ :: Monad m => [Attribute] -> HtmlT m () -- @ -- -- And some attributes share the same name as attributes, so you can -- also overload them as attributes: -- -- @ -- style_ :: TermRaw arg result => arg -> result -- style_ :: Monad m => [Attribute] -> Text -> HtmlT m () -- style_ :: Monad m => Text -> HtmlT m () -- style_ :: Text -> Attribute -- @ -- $running -- -- If the above rendering functions aren't suited for your purpose, -- you can run the monad directly and use the more low-level blaze -- `Builder`, which has a plethora of output modes in -- "Blaze.ByteString.Builder".