From 86d89e47d648770ae36dba01f7ae09d34f2ee171 Mon Sep 17 00:00:00 2001 From: Johannes Gerer Date: Wed, 26 Oct 2016 03:39:23 +0200 Subject: [PATCH] a --- README.md | 75 +++++++++++++++++++++++++----- src/Readme.hs | 23 +++++++++ src/Text/BlazeT.hs | 2 + src/Text/BlazeT/Internal.hs | 14 ++++++ src/Text/BlazeT/Renderer/Pretty.hs | 10 +--- src/Text/BlazeT/Renderer/String.hs | 8 +--- src/Text/BlazeT/Renderer/Text.hs | 50 ++++---------------- src/Text/BlazeT/Renderer/Utf8.hs | 34 ++------------ 8 files changed, 118 insertions(+), 98 deletions(-) create mode 100644 src/Readme.hs diff --git a/README.md b/README.md index 0169fab..853f1e2 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,14 @@ accumulating log or other diagnostic output doing `IO` (like database access) are the first things that come to mind. -The initial reason of existence of this library is its use +The reason of existence of this library is its use in [Lykah](http://johannesgerer.com/Lykah), which powers my personal website [http://johannesgerer.com](http://johannesgerer.com/johannesgerer.com). In Lykah, the HTML templates have access to the whole site structure (to -build things like menus) and automatically check, insert and keep -track of referenced pages and assets, which turns out to be very -useful for the task of static website generation. +build things like menus or blog post lists) and automatically check, +insert and keep track of referenced pages and assets, which turns out +to be very useful functionality of a static website generator. # How to use it? @@ -51,20 +51,73 @@ their [documentation](https://jaspervdj.be/blaze/). ## Unleash the monads +[Text.BlazeT](https://hackage.haskell.org/package/blazeT/docs/Text-BlazeT.html) exports +`runWith` and `execWith`, which work on any +`Text.Blaze.Renderer.*`. The rendered markup will be returned within +the base monad, whose actions can +be +[`lift`ed](https://hackage.haskell.org/package/transformers-0.5.2.0/docs/Control-Monad-Trans-Class.html) into +the Markup, as shown in the following example +(from [here](src/Readme.hs)): +```Haskell +{-# LANGUAGE OverloadedStrings #-} + +import Data.Time (getCurrentTime) +import Text.BlazeT.Html5 hiding (main) +import Text.BlazeT.Renderer.String +import Control.Monad.Trans.Class (lift) + +-- Backwords compatible Blaze HTML +old :: Markup +old = do + p $ "created with blaze-html" + +-- BlazeT HTML with lifted IO actions +new :: MarkupT IO () +new = do + time <- lift getCurrentTime + p $ string $ "created with blazeT at " ++ show time + +main :: IO () +main = do + putStrLn $ renderMarkup old + putStrLn =<< execWith renderMarkup new + +``` + +prints: + +```HTML +

created with blaze-html

+

created with blazeT at 2016-10-26 01:09:16.969147361 UTC

+``` + +# Installation + +1. To make it available on your system (or sandbox) use `cabal install blazeT`. + +2. To play around with the source, obtain by cloning this repo or use + `cabal get blazet`, enter the directory and run: + +```bash +cabal sandbox init #optional +cabal install +``` + +# Documentation on [Hackage](https://hackage.haskell.org/package/blazeT) # Implementation -... is located +... is contained in [Text.BlazeT.Internals](https://hackage.haskell.org/package/blazeT/docs/Text-BlazeT-Internals.html). -Everything build around the simple `newtype` definition of the -`MarkupT` transformer, which makes use of the fact that `Blaze.Markup` -is -a -[Monoid](https://hackage.haskell.org/package/base-4.7.0.2/docs/Data-Monoid.html) and -which is basically a `WriterT` transformer writing `Blaze.Markup`: +Everything is build around the simple `newtype` definition of the +`MarkupT` transformer, which makes use +the +[Monoid](https://hackage.haskell.org/package/base-4.7.0.2/docs/Data-Monoid.html) instance +of `Blaze.Markup` and is basically a `WriterT` writing `Blaze.Markup`: ```Haskell newtype MarkupT m a = MarkupT { fromMarkupT :: WriterT B.Markup m a } diff --git a/src/Readme.hs b/src/Readme.hs new file mode 100644 index 0000000..3ccabad --- /dev/null +++ b/src/Readme.hs @@ -0,0 +1,23 @@ +{-# LANGUAGE OverloadedStrings #-} + +import Data.Time (getCurrentTime) +import Text.BlazeT.Html5 hiding (main) +import Text.BlazeT.Renderer.String +import Control.Monad.Trans.Class (lift) + +-- Backwords compatible Blaze HTML +old :: Markup +old = do + p $ "created with blaze-html" + +-- BlazeT HTML with lifted IO actions +new :: MarkupT IO () +new = do + time <- lift getCurrentTime + p $ string $ "created with blazeT at " ++ show time + +main :: IO () +main = do + putStrLn $ renderMarkup old + putStrLn =<< execWith renderMarkup new + diff --git a/src/Text/BlazeT.hs b/src/Text/BlazeT.hs index 27228fa..b3e7c8d 100644 --- a/src/Text/BlazeT.hs +++ b/src/Text/BlazeT.hs @@ -62,6 +62,8 @@ module Text.BlazeT ,runMarkupT ,execMarkup ,execMarkupT + ,runWith + ,execWith ) where import qualified Text.Blaze as B diff --git a/src/Text/BlazeT/Internal.hs b/src/Text/BlazeT/Internal.hs index 24ef1fe..f0c3edb 100644 --- a/src/Text/BlazeT/Internal.hs +++ b/src/Text/BlazeT/Internal.hs @@ -83,8 +83,11 @@ module Text.BlazeT.Internal ,wrapMarkupT ,wrapMarkup2 ,wrapMarkupT2 + ,runWith + ,execWith ) where +import Control.Arrow import Control.Monad.Identity import Control.Monad.Trans.Class import Control.Monad.Writer.Strict @@ -121,10 +124,21 @@ runMarkupT :: MarkupT m a -> m (a,B.Markup) runMarkupT = runWriterT . fromMarkupT {-# INLINE runMarkupT #-} +-- | run the MarkupT and return a pair consisting of the result of the +-- computation and the blaze markup rendered with a blaze renderer +-- like 'Text.Blaze.Renderer.Text.renderHtml' +runWith :: Monad m => (MarkupM () -> c) -> MarkupT m a -> m (a, c) +runWith renderer = liftM (second $ renderer . wrapMarkup) . runMarkupT +{-# INLINE runWith #-} + execMarkupT :: Monad m => MarkupT m a -> m B.Markup execMarkupT = liftM snd . runMarkupT {-# INLINE execMarkupT #-} +execWith :: Monad m => (MarkupM () -> c) -> MarkupT m a -> m c +execWith renderer = liftM snd . runWith renderer +{-# INLINE execWith #-} + runMarkup :: MarkupM a -> (a,B.Markup) runMarkup = runIdentity . runMarkupT {-# INLINE runMarkup #-} diff --git a/src/Text/BlazeT/Renderer/Pretty.hs b/src/Text/BlazeT/Renderer/Pretty.hs index 8977c94..fa8cdad 100644 --- a/src/Text/BlazeT/Renderer/Pretty.hs +++ b/src/Text/BlazeT/Renderer/Pretty.hs @@ -1,22 +1,14 @@ module Text.BlazeT.Renderer.Pretty ( renderMarkup , renderHtml - , renderMarkupT - , renderHtmlT ) where -import Control.Monad -import Control.Monad.Identity import qualified Text.Blaze.Renderer.Pretty as BU import Text.BlazeT renderMarkup :: MarkupM a -> String -renderMarkup = runIdentity . renderMarkupT -renderMarkupT :: Monad m => MarkupT m a -> m String -renderMarkupT = liftM BU.renderMarkup . execMarkupT +renderMarkup = BU.renderMarkup . execMarkup renderHtml :: MarkupM a -> String renderHtml = renderMarkup -renderHtmlT :: Monad m => MarkupT m a -> m String -renderHtmlT = renderMarkupT diff --git a/src/Text/BlazeT/Renderer/String.hs b/src/Text/BlazeT/Renderer/String.hs index 0a2de8a..9f0e0a0 100644 --- a/src/Text/BlazeT/Renderer/String.hs +++ b/src/Text/BlazeT/Renderer/String.hs @@ -2,8 +2,6 @@ module Text.BlazeT.Renderer.String ( fromChoiceString , renderMarkup , renderHtml - , renderMarkupT - , renderHtmlT ) where import Control.Monad @@ -16,12 +14,8 @@ fromChoiceString :: ChoiceString -> String -> String fromChoiceString = BU.fromChoiceString renderMarkup :: MarkupM a -> String -renderMarkup = runIdentity . renderMarkupT -renderMarkupT :: Monad m => MarkupT m a -> m String -renderMarkupT = liftM BU.renderMarkup . execMarkupT +renderMarkup = BU.renderMarkup . execMarkup renderHtml :: MarkupM a -> String renderHtml = renderMarkup -renderHtmlT :: Monad m => MarkupT m a -> m String -renderHtmlT = renderMarkupT diff --git a/src/Text/BlazeT/Renderer/Text.hs b/src/Text/BlazeT/Renderer/Text.hs index 31181eb..991c81c 100644 --- a/src/Text/BlazeT/Renderer/Text.hs +++ b/src/Text/BlazeT/Renderer/Text.hs @@ -1,13 +1,5 @@ module Text.BlazeT.Renderer.Text - ( renderMarkupBuilderT - , renderMarkupBuilder - , renderMarkupBuilderWithT - , renderMarkupT - , renderMarkupWithT - , renderHtmlBuilderT - , renderHtmlBuilderWithT - , renderHtmlT - , renderHtmlWithT + ( renderMarkupBuilder , renderMarkupBuilderWith , renderMarkup , renderMarkupWith @@ -17,9 +9,7 @@ module Text.BlazeT.Renderer.Text , renderHtmlWith ) where -import Control.Monad import Data.ByteString (ByteString) -import Control.Monad.Identity import Data.Text (Text) import qualified Data.Text.Lazy as L import qualified Data.Text.Lazy.Builder as B @@ -28,48 +18,26 @@ import qualified Text.Blaze.Renderer.Text as BU import Text.BlazeT renderMarkupBuilder :: MarkupM a -> B.Builder -renderMarkupBuilder = runIdentity . renderMarkupBuilderT - -renderMarkupBuilderT :: Monad m => MarkupT m a -> m B.Builder -renderMarkupBuilderT = liftM BU.renderMarkupBuilder . execMarkupT +renderMarkupBuilder = BU.renderMarkupBuilder . execMarkup renderHtmlBuilder :: MarkupM a -> B.Builder renderHtmlBuilder = renderMarkupBuilder -renderHtmlBuilderT :: Monad m => MarkupT m a -> m B.Builder -renderHtmlBuilderT = renderMarkupBuilderT - renderMarkup :: MarkupM a -> L.Text -renderMarkup = runIdentity . renderMarkupT -renderMarkupT :: Monad m => MarkupT m a -> m L.Text -renderMarkupT = liftM BU.renderMarkup . execMarkupT +renderMarkup = BU.renderMarkup . execMarkup renderHtml :: MarkupM a -> L.Text renderHtml = renderMarkup -renderHtmlT :: Monad m => MarkupT m a -> m L.Text -renderHtmlT = renderMarkupT - -renderMarkupWithT :: Monad m => (ByteString -> Text) -> MarkupT m a -> m L.Text -renderMarkupWithT g = liftM (BU.renderMarkupWith g) . execMarkupT renderMarkupWith :: (ByteString -> Text) -> MarkupM a -> L.Text -renderMarkupWith g = runIdentity . renderMarkupWithT g - -renderHtmlWithT :: Monad m => (ByteString -> Text) -> MarkupT m a -> m L.Text -renderHtmlWithT g = liftM (BH.renderHtmlWith g) . execMarkupT +renderMarkupWith g = (BH.renderHtmlWith g) . execMarkup renderHtmlWith :: (ByteString -> Text) -> MarkupM a -> L.Text -renderHtmlWith g = runIdentity . renderHtmlWithT g - -renderHtmlBuilderWithT :: Monad m => (ByteString -> Text) -> MarkupT m a -> m B.Builder -renderHtmlBuilderWithT g = liftM (BH.renderHtmlBuilderWith g) . execMarkupT - -renderHtmlBuilderWith :: (ByteString -> Text) -> MarkupM a -> B.Builder -renderHtmlBuilderWith g = runIdentity . renderHtmlBuilderWithT g +renderHtmlWith = renderMarkupWith +renderMarkupBuilderWith :: (ByteString -> Text) -> MarkupM a -> B.Builder +renderMarkupBuilderWith g = (BU.renderMarkupBuilderWith g) . execMarkup -renderMarkupBuilderWithT :: Monad m => (ByteString -> Text) -> MarkupT m a -> m B.Builder -renderMarkupBuilderWithT g = liftM (BU.renderMarkupBuilderWith g) . execMarkupT +renderHtmlBuilderWith :: (ByteString -> Text) -> MarkupM a -> B.Builder +renderHtmlBuilderWith = renderHtmlBuilderWith -renderMarkupBuilderWith :: (ByteString -> Text) -> MarkupM a -> B.Builder -renderMarkupBuilderWith g = runIdentity . renderMarkupBuilderWithT g diff --git a/src/Text/BlazeT/Renderer/Utf8.hs b/src/Text/BlazeT/Renderer/Utf8.hs index 292f81f..b5fd656 100644 --- a/src/Text/BlazeT/Renderer/Utf8.hs +++ b/src/Text/BlazeT/Renderer/Utf8.hs @@ -13,54 +13,28 @@ module Text.BlazeT.Renderer.Utf8 , renderHtmlBuilder , renderHtml , renderHtmlToByteStringIO - - -- * new BlazeT stuff - , renderMarkupBuilderT - , renderMarkupT - , renderMarkupToByteStringIOT - , renderHtmlToByteStringIOT - , renderHtmlBuilderT - , renderHtmlT ) where import qualified Blaze.ByteString.Builder as B -import Control.Monad -import Control.Monad.Identity import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL import qualified Text.Blaze.Renderer.Utf8 as BU import Text.BlazeT renderMarkupBuilder :: MarkupM a -> B.Builder -renderMarkupBuilder = runIdentity . renderMarkupBuilderT - -renderMarkupBuilderT :: Monad m => MarkupT m a -> m B.Builder -renderMarkupBuilderT = liftM BU.renderMarkupBuilder . execMarkupT +renderMarkupBuilder = BU.renderMarkupBuilder . execMarkup renderHtmlBuilder :: MarkupM a -> B.Builder renderHtmlBuilder = renderMarkupBuilder -renderHtmlBuilderT :: Monad m => MarkupT m a -> m B.Builder -renderHtmlBuilderT = renderMarkupBuilderT - renderMarkup :: MarkupM a -> BL.ByteString -renderMarkup = runIdentity . renderMarkupT -renderMarkupT :: Monad m => MarkupT m a -> m BL.ByteString -renderMarkupT = liftM BU.renderMarkup . execMarkupT +renderMarkup = BU.renderMarkup . execMarkup renderHtml :: MarkupM a -> BL.ByteString renderHtml = renderMarkup -renderHtmlT :: Monad m => MarkupT m a -> m BL.ByteString -renderHtmlT = renderMarkupT renderMarkupToByteStringIO :: (BS.ByteString -> IO ()) -> MarkupM a -> IO () -renderMarkupToByteStringIO g = runIdentity . renderMarkupToByteStringIOT g -renderMarkupToByteStringIOT :: Monad m => (BS.ByteString -> IO ()) -> - MarkupT m a -> m (IO ()) -renderMarkupToByteStringIOT g = liftM (BU.renderMarkupToByteStringIO g) . execMarkupT +renderMarkupToByteStringIO g = BU.renderMarkupToByteStringIO g . execMarkup renderHtmlToByteStringIO :: (BS.ByteString -> IO ()) -> MarkupM a -> IO () -renderHtmlToByteStringIO g = runIdentity . renderMarkupToByteStringIOT g -renderHtmlToByteStringIOT :: Monad m => (BS.ByteString -> IO ()) -> - MarkupT m a -> m (IO ()) -renderHtmlToByteStringIOT g = liftM (BU.renderMarkupToByteStringIO g) . execMarkupT +renderHtmlToByteStringIO = renderMarkupToByteStringIO -- 2.41.0