]> git.immae.eu Git - github/fretlink/blazeT.git/blame - README.md
fixed compilation error for GHC 7.6.3, 7.8.4, 7.10.3
[github/fretlink/blazeT.git] / README.md
CommitLineData
675085c2
JG
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
3A 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)
6libraries.
7
8# Why?
9
10While blaze's `Markup` and `Html` types have `Monad` instances and can
11leverage the the concise `do` notation, they do not satisfy
12the
13[Monad Laws](https://hackage.haskell.org/package/base-4.8.0.0/docs/Control-Monad.html#t:Monad) and
14thus cannot be used as Monads, let alone Monad transformers.
15
16## Use Cases
17
18The `MarkupT` Monad Transformer enables us to write Markup (e.g. HTML)
19templates that have access to all those Monads you cannot live without
20anymore.
21
22Accessing an environment
23([MonadReader](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html)),
24accumulating log or other diagnostic output
25([MonadWriter](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Writer-Class.html)),
26doing `IO` (like database access) are the first things that come to
27mind.
28
95eb4d6a 29The reason of existence of this library is its use
675085c2
JG
30in [Lykah](http://johannesgerer.com/Lykah), which powers my personal
31website
32[http://johannesgerer.com](http://johannesgerer.com/johannesgerer.com). In
33Lykah, the HTML templates have access to the whole site structure (to
95eb4d6a
JG
34build things like menus or blog post lists) and automatically check,
35insert and keep track of referenced pages and assets, which turns out
36to be very useful functionality of a static website generator.
675085c2
JG
37
38# How to use it?
39
40## Backwards compatible
41
42The library is intended to serve as a drop-in replacement for the
43`blaze-markup` and `blaze-html` libraries and should be backwards
44compatible:
45
46Simply replace your `module Text.Blaze.*` imports with `module
47Text.BlazeT.*` and it should give the same results.
48
49For usage of blaze check out
50their [documentation](https://jaspervdj.be/blaze/).
51
52## Unleash the monads
53
95eb4d6a
JG
54[Text.BlazeT](https://hackage.haskell.org/package/blazeT/docs/Text-BlazeT.html)
55exports `runWith` and `execWith`, which work on any
56`Text.BlazeT.Renderer.*`. The rendered markup will be returned within
57the 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)
59into the Markup, as shown in the following example (from
60[here](src/Readme.hs)):
675085c2 61
95eb4d6a
JG
62```Haskell
63{-# LANGUAGE OverloadedStrings #-}
64
65import Data.Time (getCurrentTime)
66import Text.BlazeT.Html5 hiding (main)
67import Text.BlazeT.Renderer.String
68import Control.Monad.Trans.Class (lift)
69
70-- Backwords compatible Blaze HTML
71old :: Markup
72old = do
73 p $ "created with blaze-html"
74
75-- BlazeT HTML with lifted IO actions
76new :: MarkupT IO ()
77new = do
78 time <- lift getCurrentTime
79 p $ string $ "created with blazeT at " ++ show time
80
81main :: IO ()
82main = do
83 putStrLn $ renderMarkup old
84 putStrLn =<< execWith renderMarkup new
85
86```
87
88prints:
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
971. To make it available on your system (or sandbox) use `cabal install blazeT`.
98
992. 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
103cabal sandbox init #optional
104cabal install
105```
106
107# Documentation on [Hackage](https://hackage.haskell.org/package/blazeT)
675085c2
JG
108
109# Implementation
110
95eb4d6a 111... is contained
675085c2
JG
112in
113[Text.BlazeT.Internals](https://hackage.haskell.org/package/blazeT/docs/Text-BlazeT-Internals.html).
114
95eb4d6a
JG
115Everything is build around the simple `newtype` definition of the
116`MarkupT` transformer, which makes use
117the
118[Monoid](https://hackage.haskell.org/package/base-4.7.0.2/docs/Data-Monoid.html) instance
119of `Blaze.Markup` and is basically a `WriterT` writing `Blaze.Markup`:
675085c2
JG
120
121```Haskell
122newtype MarkupT m a = MarkupT { fromMarkupT :: WriterT B.Markup m a }
123```
124
95eb4d6a
JG
125The old `Text.Blaze.Markup` type is replaced by a rank-2 version of
126the transformer:
127
128```Haskell
129type Markup = forall m . Monad m => MarkupT m ()
130```
131
675085c2 132Wrappers used to lift all `Blaze` entities into `BlazeT` are trivially
95eb4d6a
JG
133expressible using basic `WriterT` class methods. Wrapping
134`Blaze.Markup` is simply `WriterT.tell`:
675085c2
JG
135
136```Haskell
137wrapMarkupT :: Monad m => B.Markup -> MarkupT m ()
138wrapMarkupT = tell
139```
140Wrapping functions that modify `Blaze.Markup` is simply `WriterT.censor`:
141
142```Haskell
143wrapMarkupT2 :: Monad m => (B.Markup -> B.Markup) -> MarkupT m a -> MarkupT m a
144wrapMarkupT2 = censor
145```
146