1 {-# LANGUAGE DeriveFunctor #-}
2 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
3 {-# LANGUAGE FlexibleInstances #-}
4 {-# LANGUAGE RankNTypes #-}
6 #if MIN_VERSION_blaze_markup(0,7,1)
9 module Text.BlazeT.Internal
11 -- * Entities exported only by the @blazeT@ version of this module
15 -- ** Specializations for @blaze-markup@ backwards compatibility
34 -- * Entities exported also by "Text.Blaze.Internal"
37 -- ** Important types.
38 Text.Blaze.ChoiceString (..)
39 , Text.Blaze.StaticString (..)
43 , Text.Blaze.Attribute
44 , Text.Blaze.AttributeValue
46 -- ** Creating custom tags and attributes.
49 , Text.Blaze.attribute
50 , Text.Blaze.dataAttribute
51 , Text.Blaze.customAttribute
53 -- ** Converting values to Markup.
59 , preEscapedTextBuilder
63 , unsafeLazyByteString
69 , unsafeByteStringComment
70 , unsafeLazyByteStringComment
72 -- ** Converting values to tags.
74 , Text.Blaze.stringTag
76 -- ** Converting values to attribute values.
77 , Text.Blaze.textValue
78 , Text.Blaze.preEscapedTextValue
79 , Text.Blaze.lazyTextValue
80 , Text.Blaze.preEscapedLazyTextValue
81 , Text.Blaze.textBuilderValue
82 , Text.Blaze.preEscapedTextBuilderValue
83 , Text.Blaze.stringValue
84 , Text.Blaze.preEscapedStringValue
85 , Text.Blaze.unsafeByteStringValue
86 , Text.Blaze.unsafeLazyByteStringValue
88 -- ** Setting attributes
89 , Text.Blaze.Attributable
93 -- ** Modifying Markup elements
97 -- ** Querying Markup elements
103 import Control.Monad.Identity
104 import Control.Monad.Trans.Class
105 import Control.Monad.Writer.Strict
106 import qualified Data.ByteString as BS
107 import qualified Data.ByteString.Lazy as BL
109 import qualified Data.Text as T
110 import qualified Data.Text.Lazy as LT
111 import qualified Data.Text.Lazy.Builder as LTB
112 import qualified Text.Blaze
113 import qualified Text.Blaze.Internal as Text.Blaze
115 {- | Everything is build around the simple @newtype@ definition of the
116 'MarkupT' transformer, which makes use the 'Monoid' instance of Blaze
117 'Text.Blaze.Markup' and is simply a 'WriterT' writing Blaze
120 newtype MarkupT m a= MarkupT { fromMarkupT :: WriterT Text.Blaze.Markup m a }
122 #if MIN_VERSION_base(4,8,0)
126 ,MonadWriter Text.Blaze.Markup
130 type MarkupI a = MarkupT Identity a
132 -- | Map both the return value and markup of a computation using the
134 mapMarkupT :: (m (a,Text.Blaze.Markup) -> n (b,Text.Blaze.Markup)) -> MarkupT m a -> MarkupT n b
135 mapMarkupT f = MarkupT . mapWriterT f . fromMarkupT
136 {-# INLINE mapMarkupT #-}
138 type MarkupM a = forall m . Monad m => MarkupT m a
139 type Markup = MarkupM ()
140 type Markup2 = forall m . Monad m => MarkupT m () -> MarkupT m ()
142 runMarkupT :: MarkupT m a -> m (a,Text.Blaze.Markup)
143 runMarkupT = runWriterT . fromMarkupT
144 {-# INLINE runMarkupT #-}
146 -- | run the MarkupT and return a pair consisting of the result of the
147 -- computation and the blaze markup rendered with a blaze renderer
148 -- like 'Text.BlazeT.Renderer.Text.renderHtml'
149 runWith :: Monad m => (MarkupI () -> c) -> MarkupT m a -> m (a, c)
150 runWith renderer = liftM (second $ renderer . wrapMarkup) . runMarkupT
151 {-# INLINE runWith #-}
153 execMarkupT :: Monad m => MarkupT m a -> m Text.Blaze.Markup
154 execMarkupT = liftM snd . runMarkupT
155 {-# INLINE execMarkupT #-}
157 execWith :: Monad m => (MarkupI () -> c) -> MarkupT m a -> m c
158 execWith renderer = liftM snd . runWith renderer
159 {-# INLINE execWith #-}
161 runMarkup :: MarkupI a -> (a, Text.Blaze.Markup)
162 runMarkup = runIdentity . runMarkupT
163 {-# INLINE runMarkup #-}
165 execMarkup :: MarkupI a -> Text.Blaze.Markup
166 execMarkup = snd . runMarkup
167 {-# INLINE execMarkup #-}
169 -- | Wrapper for 'Text.Blaze.Markup' is simply
171 wrapMarkupT :: Monad m => Text.Blaze.Markup -> MarkupT m ()
173 {-# INLINE wrapMarkupT #-}
175 wrapMarkup :: Text.Blaze.Markup -> Markup
176 wrapMarkup = wrapMarkupT
177 {-# INLINE wrapMarkup #-}
180 -- | Wrapper for functions that modify 'Text.Blaze.Markup' is simply
182 wrapMarkupT2 :: Monad m => (Text.Blaze.Markup -> Text.Blaze.Markup)
183 -> MarkupT m a -> MarkupT m a
184 wrapMarkupT2 = censor
185 {-# INLINE wrapMarkupT2 #-}
187 wrapMarkup2 :: (Text.Blaze.Markup -> Text.Blaze.Markup) -> Markup2
188 wrapMarkup2 = wrapMarkupT2
189 {-# INLINE wrapMarkup2 #-}
192 instance (Monad m,Monoid a) => Monoid (MarkupT m a) where
193 mempty = return mempty
194 {-# INLINE mempty #-}
195 a `mappend` b = do {a' <- a; b >>= return . (mappend a')}
196 {-# INLINE mappend #-}
199 instance Monad m => Text.Blaze.Attributable (MarkupT m a) where
200 h ! a = wrapMarkupT2 (Text.Blaze.! a) h
203 instance Monad m => Text.Blaze.Attributable (a -> MarkupT m b) where
204 h ! a = \x -> wrapMarkupT2 (Text.Blaze.! a) $ h x
207 instance Monad m => IsString (MarkupT m ()) where
208 fromString = wrapMarkup . fromString
209 {-# INLINE fromString #-}
211 unsafeByteString :: BS.ByteString -> Markup
212 unsafeByteString = wrapMarkup . Text.Blaze.unsafeByteString
213 {-# INLINE unsafeByteString #-}
215 -- | Insert a lazy 'BL.ByteString'. See 'unsafeByteString' for reasons why this
216 -- is an unsafe operation.
218 unsafeLazyByteString :: BL.ByteString -- ^ Value to insert
219 -> Markup -- ^ Resulting HTML fragment
220 unsafeLazyByteString = wrapMarkup . Text.Blaze.unsafeLazyByteString
221 {-# INLINE unsafeLazyByteString #-}
223 external :: Monad m => MarkupT m a -> MarkupT m a
224 external = wrapMarkupT2 Text.Blaze.external
225 {-# INLINE external #-}
227 contents :: Monad m => MarkupT m a -> MarkupT m a
228 contents = wrapMarkupT2 Text.Blaze.contents
229 {-# INLINE contents #-}
231 customParent ::Text.Blaze.Tag -> Markup2
232 customParent = wrapMarkup2 . Text.Blaze.customParent
233 {-# INLINE customParent #-}
235 customLeaf :: Text.Blaze.Tag -> Bool -> Markup
236 customLeaf = fmap wrapMarkup . Text.Blaze.customLeaf
237 {-# INLINE customLeaf #-}
239 preEscapedText :: T.Text -> Markup
240 preEscapedText = wrapMarkup . Text.Blaze.preEscapedText
241 {-# INLINE preEscapedText #-}
243 preEscapedLazyText :: LT.Text -> Markup
244 preEscapedLazyText = wrapMarkup . Text.Blaze.preEscapedLazyText
245 {-# INLINE preEscapedLazyText #-}
247 preEscapedTextBuilder :: LTB.Builder -> Markup
248 textBuilder :: LTB.Builder -> Markup
251 preEscapedTextBuilder = wrapMarkup . Text.Blaze.preEscapedTextBuilder
252 textBuilder = wrapMarkup . Text.Blaze.textBuilder
253 {-# INLINE preEscapedTextBuilder #-}
254 {-# INLINE textBuilder #-}
256 preEscapedTextBuilder = error "This function needs blaze-markup 0.7.1.0"
257 textBuilder = error "This function needs blaze-markup 0.7.1.0"
260 preEscapedString :: String -> Markup
261 preEscapedString = wrapMarkup . Text.Blaze.preEscapedString
262 {-# INLINE preEscapedString #-}
264 string :: String -> Markup
265 string = wrapMarkup . Text.Blaze.string
266 {-# INLINE string #-}
268 text :: T.Text -> Markup
269 text = wrapMarkup . Text.Blaze.text
272 lazyText :: LT.Text -> Markup
273 lazyText = wrapMarkup . Text.Blaze.lazyText
274 {-# INLINE lazyText #-}
277 textComment :: T.Text -> Markup
278 textComment = wrapMarkup . Text.Blaze.textComment
280 lazyTextComment :: LT.Text -> Markup
281 lazyTextComment = wrapMarkup . Text.Blaze.lazyTextComment
283 stringComment :: String -> Markup
284 stringComment = wrapMarkup . Text.Blaze.stringComment
286 unsafeByteStringComment :: BS.ByteString -> Markup
287 unsafeByteStringComment = wrapMarkup . Text.Blaze.unsafeByteStringComment
289 unsafeLazyByteStringComment :: BL.ByteString -> Markup
290 unsafeLazyByteStringComment = wrapMarkup . Text.Blaze.unsafeLazyByteStringComment
293 -- The following is an adaptation of all "Text.Blaze.Internal" exports to
296 -- Entities that are reexported from "Text.Blaze.Internal" have the original
297 -- documentation attached to them.
299 -- Entities that had to be adapted are tagged with \"(Adapted)\". For
300 -- their documentation consult the "Text.Blaze.Internal" documentation.