]> git.immae.eu Git - github/fretlink/blazeT.git/blob - README.md
fixed compilation error for GHC 7.6.3, 7.8.4, 7.10.3
[github/fretlink/blazeT.git] / README.md
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)
2
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)
6 libraries.
7
8 # Why?
9
10 While blaze's `Markup` and `Html` types have `Monad` instances and can
11 leverage the the concise `do` notation, they do not satisfy
12 the
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.
15
16 ## Use Cases
17
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
20 anymore.
21
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
27 mind.
28
29 The reason of existence of this library is its use
30 in [Lykah](http://johannesgerer.com/Lykah), which powers my personal
31 website
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.
37
38 # How to use it?
39
40 ## Backwards compatible
41
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
44 compatible:
45
46 Simply replace your `module Text.Blaze.*` imports with `module
47 Text.BlazeT.*` and it should give the same results.
48
49 For usage of blaze check out
50 their [documentation](https://jaspervdj.be/blaze/).
51
52 ## Unleash the monads
53
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)):
61
62 ```Haskell
63 {-# LANGUAGE OverloadedStrings #-}
64
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)
69
70 -- Backwords compatible Blaze HTML
71 old :: Markup
72 old = do
73 p $ "created with blaze-html"
74
75 -- BlazeT HTML with lifted IO actions
76 new :: MarkupT IO ()
77 new = do
78 time <- lift getCurrentTime
79 p $ string $ "created with blazeT at " ++ show time
80
81 main :: IO ()
82 main = do
83 putStrLn $ renderMarkup old
84 putStrLn =<< execWith renderMarkup new
85
86 ```
87
88 prints:
89
90 ```HTML
91 <p>created with blaze-html</p>
92 <p>created with blazeT at 2016-10-26 01:09:16.969147361 UTC</p>
93 ```
94
95 # Installation
96
97 1. To make it available on your system (or sandbox) use `cabal install blazeT`.
98
99 2. To play around with the source, obtain by cloning this repo or use
100 `cabal get blazet`, enter the directory and run:
101
102 ```bash
103 cabal sandbox init #optional
104 cabal install
105 ```
106
107 # Documentation on [Hackage](https://hackage.haskell.org/package/blazeT)
108
109 # Implementation
110
111 ... is contained
112 in
113 [Text.BlazeT.Internals](https://hackage.haskell.org/package/blazeT/docs/Text-BlazeT-Internals.html).
114
115 Everything is build around the simple `newtype` definition of the
116 `MarkupT` transformer, which makes use
117 the
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`:
120
121 ```Haskell
122 newtype MarkupT m a = MarkupT { fromMarkupT :: WriterT B.Markup m a }
123 ```
124
125 The old `Text.Blaze.Markup` type is replaced by a rank-2 version of
126 the transformer:
127
128 ```Haskell
129 type Markup = forall m . Monad m => MarkupT m ()
130 ```
131
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`:
135
136 ```Haskell
137 wrapMarkupT :: Monad m => B.Markup -> MarkupT m ()
138 wrapMarkupT = tell
139 ```
140 Wrapping functions that modify `Blaze.Markup` is simply `WriterT.censor`:
141
142 ```Haskell
143 wrapMarkupT2 :: Monad m => (B.Markup -> B.Markup) -> MarkupT m a -> MarkupT m a
144 wrapMarkupT2 = censor
145 ```
146