1 # blazeT [![Build Status](https://travis-ci.org/johannesgerer/blazeT.svg?branch=master)](https://travis-ci.org/johannesgerer/blazeT) [![Hackage](https://img.shields.io/hackage/v/blazeT.svg)](https://hackage.haskell.org/package/blazeT)
3 A true monad (transformer) version of the
4 [blaze-markup](https://hackage.haskell.org/package/blaze-markup) and
5 [blaze-html](https://hackage.haskell.org/package/blaze-html)
10 While blaze's `Markup` and `Html` types have `Monad` instances and can
11 leverage the the concise `do` notation, they do not satisfy
13 [Monad Laws](https://hackage.haskell.org/package/base-4.8.0.0/docs/Control-Monad.html#t:Monad) and
14 thus cannot be used as Monads, let alone Monad transformers.
18 The `MarkupT` Monad Transformer enables us to write Markup (e.g. HTML)
19 templates that have access to all those Monads you cannot live without
22 Accessing an environment
23 ([MonadReader](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html)),
24 accumulating log or other diagnostic output
25 ([MonadWriter](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Writer-Class.html)),
26 doing `IO` (like database access) are the first things that come to
29 The reason of existence of this library is its use
30 in [Lykah](http://johannesgerer.com/Lykah), which powers my personal
32 [http://johannesgerer.com](http://johannesgerer.com/johannesgerer.com). In
33 Lykah, the HTML templates have access to the whole site structure (to
34 build things like menus or blog post lists) and automatically check,
35 insert and keep track of referenced pages and assets, which turns out
36 to be very useful functionality of a static website generator.
40 ## Backwards compatible
42 The library is intended to serve as a drop-in replacement for the
43 `blaze-markup` and `blaze-html` libraries and should be backwards
46 Simply replace your `module Text.Blaze.*` imports with `module
47 Text.BlazeT.*` and it should give the same results.
49 For usage of blaze check out
50 their [documentation](https://jaspervdj.be/blaze/).
54 [Text.BlazeT](https://hackage.haskell.org/package/blazeT/docs/Text-BlazeT.html)
55 exports `runWith` and `execWith`, which work on any
56 `Text.BlazeT.Renderer.*`. The rendered markup will be returned within
57 the base monad, whose actions can be
58 [`lift`ed](https://hackage.haskell.org/package/transformers-0.5.2.0/docs/Control-Monad-Trans-Class.html)
59 into the Markup, as shown in the following example (from
60 [here](src/Readme.hs)):
63 {-# LANGUAGE OverloadedStrings #-}
65 import Data.Time (getCurrentTime)
66 import Text.BlazeT.Html5 hiding (main)
67 import Text.BlazeT.Renderer.String
68 import Control.Monad.Trans.Class (lift)
70 -- Backwords compatible Blaze HTML
73 p $ "created with blaze-html"
75 -- BlazeT HTML with lifted IO actions
78 time <- lift getCurrentTime
79 p $ string $ "created with blazeT at " ++ show time
83 putStrLn $ renderMarkup old
84 putStrLn =<< execWith renderMarkup new
91 <p>created with blaze-html</p>
92 <p>created with blazeT at 2016-10-26 01:09:16.969147361 UTC</p>
97 1. To make it available on your system (or sandbox) use `cabal install blazeT`.
99 2. To play around with the source, obtain by cloning this repo or use
100 `cabal get blazet`, enter the directory and run:
103 cabal sandbox init #optional
107 # Documentation on [Hackage](https://hackage.haskell.org/package/blazeT)
113 [Text.BlazeT.Internals](https://hackage.haskell.org/package/blazeT/docs/Text-BlazeT-Internals.html).
115 Everything is build around the simple `newtype` definition of the
116 `MarkupT` transformer, which makes use
118 [Monoid](https://hackage.haskell.org/package/base-4.7.0.2/docs/Data-Monoid.html) instance
119 of `Blaze.Markup` and is basically a `WriterT` writing `Blaze.Markup`:
122 newtype MarkupT m a = MarkupT { fromMarkupT :: WriterT B.Markup m a }
125 The old `Text.Blaze.Markup` type is replaced by a rank-2 version of
129 type Markup = forall m . Monad m => MarkupT m ()
132 Wrappers used to lift all `Blaze` entities into `BlazeT` are trivially
133 expressible using basic `WriterT` class methods. Wrapping
134 `Blaze.Markup` is simply `WriterT.tell`:
137 wrapMarkupT :: Monad m => B.Markup -> MarkupT m ()
140 Wrapping functions that modify `Blaze.Markup` is simply `WriterT.censor`:
143 wrapMarkupT2 :: Monad m => (B.Markup -> B.Markup) -> MarkupT m a -> MarkupT m a
144 wrapMarkupT2 = censor