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