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