logfmt (empty) → 0.0.1
raw patch · 11 files changed
+6963/−0 lines, 11 filesdep +ansi-terminaldep +basedep +bytestringsetup-changed
Dependencies added: ansi-terminal, base, bytestring, fast-logger, profunctors, time
Files
- ChangeLog.md +5/−0
- LICENSE +29/−0
- README.md +1/−0
- Setup.hs +2/−0
- logfmt.cabal +45/−0
- src/Data/Fmt.hs +815/−0
- src/Data/Fmt/Ansi.hs +102/−0
- src/Data/Fmt/Attr.hs +3414/−0
- src/Data/Fmt/Code.hs +324/−0
- src/Data/Fmt/Html.hs +2120/−0
- src/Data/Fmt/Time.hs +106/−0
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for logfmt++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,29 @@+BSD 3-Clause License++Copyright (c) 2021, Chris McKinlay+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+ contributors may be used to endorse or promote products derived from+ this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+# logfmt
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ logfmt.cabal view
@@ -0,0 +1,45 @@+cabal-version: >=1.10++name: logfmt+version: 0.0.1+synopsis: Formatting+description: Please see the README on GitHub at https://github.com/cmk/logfmt#readme+category: Text, System+homepage: https://github.com/cmk/logfmt#readme+bug-reports: https://github.com/cmk/logfmt/issues+author: Chris McKinlay+maintainer: chris.mckinlay@gmail.com+copyright: 2020-2021 Chris McKinlay+license: BSD3+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md+ ChangeLog.md+tested-with:+ GHC == 8.10.1+source-repository head+ type: git+ location: https://github.com/cmk/logfmt++library+ exposed-modules:+ Data.Fmt+ Data.Fmt.Ansi+ Data.Fmt.Attr+ Data.Fmt.Code+ Data.Fmt.Html+ Data.Fmt.Time++ other-modules:+ Paths_logfmt+ hs-source-dirs:+ src+ build-depends:+ base >=4.14 && <5+ , bytestring+ , profunctors+ , fast-logger+ , ansi-terminal+ , time+ default-language: Haskell2010
+ src/Data/Fmt.hs view
@@ -0,0 +1,815 @@+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}++module Data.Fmt (+ Term,++ -- * Type+ LogFmt,+ Fmt (..),+ spr,+ printf,+ runFmt,+ runLogFmt,+ + -- * Fmt+ fmt,+ logFmt,+ (%),+ apply,+ bind,+ cat,+ refmt,+ replace1,+ splitWith,++ -- * Fmt1+ Fmt1,+ Fmt2,+ fmt1,+ fmt2,+ fmt1_,+ fmt2_,+ (.%),+ cat1,+ cat1With,+ split1With,++ -- * Html+ Html,+ toHtml,+ comment,+ Attr (..),+ Element (..),+ (!?),++ -- * Formatting+ hsep,+ vsep,+ hang,+ indent,+ prefix,+ suffix,+ enclose,+ tuple,+ quotes,+ quotes',+ parens,+ braces,+ brackets,+ backticks,++ -- * Collections+ left1,+ right1,+ either1,+ maybe1,+ list1,+ jsonList,+ yamlList,+ jsonMap,+ yamlMap,++ -- * Re-exports+ LogStr,+ fromLogStr,+ ToLogStr (..),+ IsString (..),+) where++import Control.Applicative (Const (..), getConst)+import Control.Arrow+import Control.Category (Category (), (<<<), (>>>))+import Data.ByteString (ByteString)+import Data.ByteString.Builder (Builder)+import Data.Foldable (toList)+import Data.Profunctor+import Data.String+import GHC.Exts (IsList, Item)+import System.Log.FastLogger (LogStr, ToLogStr (..), fromLogStr)+import qualified Control.Category as C+import qualified Data.ByteString.Builder as BL+import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy.Char8 as BL+import qualified GHC.Exts as IsList (toList)+import qualified Numeric as N++{- $setup+ >>> import Data.Printf+ >>> :load Data.Fmt+-}++type Term = IO ()++type LogFmt = Fmt LogStr++{- | A formatter, implemented as an indexed continuation++ When you construct formatters the first type+ parameter, @r@, will remain polymorphic. The second type+ parameter, @a@, will change to reflect the types of the data that+ will be formatted. For example, in++ @+ person :: Fmt2 ByteString Int+ person = \"Person's name is \" % t % \", age is \" % d+ @++ the first type parameter remains polymorphic, and the second type+ parameter is @ByteString -> Int -> r@, which indicates that it formats a+ 'ByteString' and an 'Int'.++ When you run the formatter, for example with 'format', you provide+ the arguments and they will be formatted into a string.++ >>> format ("This person's name is " % s % ", their age is " % d) "Anne" 22+ "This person's name is Anne, their age is 22"+-}+newtype Fmt m a b = Fmt {unFmt :: (m -> a) -> b}++deriving via (Costar ((->) m) a) instance Functor (Fmt m a)+deriving via (Costar ((->) m) a) instance Applicative (Fmt m a)+deriving via (Costar ((->) m) a) instance Monad (Fmt m a)+deriving via (Costar ((->) m)) instance Profunctor (Fmt m)+deriving via (Costar ((->) m)) instance Closed (Fmt m)+deriving via (Costar ((->) m)) instance Costrong (Fmt m)+deriving via (Costar ((->) m)) instance Cochoice (Fmt m)++instance (IsString s, Show a) => Show (Fmt LogStr s a) where+ show = show . runLogFmt++instance (IsString m, a ~ b) => IsString (Fmt m a b) where+ fromString = fmt . fromString++instance Semigroup m => Semigroup (Fmt1 m s a) where+ (<>) = (.%)++instance Monoid m => Monoid (Fmt1 m s a) where+ mempty = Fmt (\k _ -> k mempty)++instance Monoid m => Category (Fmt m) where+ id = fmt mempty+ (.) = (%)++instance Monoid m => Arrow (Fmt m) where+ arr f = Fmt $ \k -> f (k mempty)+ x *** y = dimap fst (,) x <*> lmap snd y++instance Monoid m => Strong (Fmt m) where+ first' x = x *** C.id+ second' x = C.id *** x++{- | Run a monadic formatting expression.++ Like the method of 'Text.Printf.PrintfType', 'spr' executes the formatting+ commands contained in the expression and returns the result as a monadic+ variable.++ For example, note that the 'Data.Fmt.Html.li' tag repeats, while the+ 'Data.Fmt.Html.ul' tag does not: ++ >>> :{+ let contact = p "You can reach me at" % ul . spr . li $ do+ c1 <- a ! href @String "https://example.com" $ "Website"+ c2 <- a ! href @String "mailto:cmk@example.com" $ "Email"+ pure $ c1 <> c2+ in runLogStr contact+ :}+ "<p>You can reach me at</p><ul><li><a href=\"https://foo.com\">Web</a></li><li><a href=\"mailto:cmk@foo.com\">Email</a></li></ul>"+-}+spr :: IsString s => Fmt LogStr s m -> Fmt m a a+spr = fmt . runLogFmt++-- | Run a formatter and print out the text to stdout.+{-# INLINE printf #-}+printf :: Fmt LogStr Term a -> a+printf = flip unFmt (B.putStrLn . fromLogStr)++-- | Run a 'Fmt'.+{-# INLINE runFmt #-}+runFmt :: Fmt m m a -> a+runFmt = flip unFmt id++-- | Run a 'LogFmt'.+{-# INLINE runLogFmt #-}+runLogFmt :: IsString s => Fmt LogStr s a -> a+runLogFmt = flip unFmt (fromString . B.unpack . fromLogStr)+{-# SPECIALIZE runLogFmt :: Fmt LogStr BL.ByteString a -> a #-}+{-# SPECIALIZE runLogFmt :: Fmt LogStr ByteString a -> a #-}+{-# SPECIALIZE runLogFmt :: Fmt LogStr String a -> a #-}+{-# SPECIALIZE runLogFmt :: Fmt LogStr LogStr a -> a #-}+{-# SPECIALIZE runLogFmt :: Fmt LogStr Builder a -> a #-}++-- | Format a constant value of type @m@.+{-# INLINE fmt #-}+fmt :: m -> Fmt m a a+fmt m = Fmt ($ m)++-- | Format a constant value of type @m@.+{-# INLINE logFmt #-}+logFmt :: ToLogStr m => m -> Fmt LogStr a a+logFmt = fmt . toLogStr++-- | Concatenate two formatters.+infixr 0 %++{-# INLINE (%) #-}+(%) :: Semigroup m => Fmt m b c -> Fmt m a b -> Fmt m a c+f % g =+ f+ `bind` \a ->+ g+ `bind` \b -> fmt (a <> b)++-- | Apply a 'Fmt1' to a 'Fmt'.+{-# INLINE apply #-}+apply :: Fmt1 m s m -> Fmt m s a -> Fmt m s a+apply (Fmt f) (Fmt a) = Fmt (a . f)++-- | Indexed bind.+{-# INLINE bind #-}+bind :: Fmt m a1 b -> (m -> Fmt m a2 a1) -> Fmt m a2 b+bind m f = Fmt $ \k -> unFmt m (\a -> unFmt (f a) k)++-- | Concatenate a collection of formatters.+{-# INLINE cat #-}+cat :: (Monoid m, Foldable f) => f (Fmt m a a) -> Fmt m a a+cat = foldr (%) C.id++-- | Map over the the formatting @Monoid@.+{-# INLINE refmt #-}+refmt :: (m1 -> m2) -> Fmt m1 a b -> Fmt m2 a b+refmt m12 (Fmt f) = Fmt $ \a -> f (a . m12)++{- | Replace one occurance of a search term.++ > replace1 "bar" "foo" "foobarbaz"+ "foofoobaz"+-}+{-# INLINE replace1 #-}+replace1 :: ByteString -> Fmt LogStr a a -> Fmt LogStr a b -> Fmt LogStr a b+replace1 x y =+ splitWith (B.breakSubstring x) $ \l r0 ->+ case B.stripPrefix x r0 of+ Nothing -> logFmt l+ Just r -> cat [logFmt l, y, logFmt r]++{-# INLINE splitWith #-}+splitWith ::+ (ByteString -> (ByteString, ByteString)) -> -- Splitter+ (ByteString -> ByteString -> Fmt LogStr a2 a1) -> -- Joiner+ Fmt LogStr a1 b ->+ Fmt LogStr a2 b+splitWith break join = flip bind $ uncurry join . break . fromLogStr++-- Fmt1++-------------------------++{- | A unary higher-order formatter.++ @ 'Fmt1' m s a ~ (m -> s) -> a -> s @+-}+type Fmt1 m s a = Fmt m s (a -> s)++{- | A binary higher-order formatter.++ @ 'Fmt2' m s a b ~ (m -> s) -> a -> b -> s @+-}+type Fmt2 m s a b = Fmt m s (a -> b -> s)++{- | A ternary higher-order formatter.++ @ 'Fmt3' m s a b c ~ (m -> s) -> a -> b -> c -> s @+-}+type Fmt3 m s a b c = Fmt m s (a -> b -> c -> s)++{- | Format a value of type @a@ using a function of type @a -> m@.++ @ 'runFmt' . 'fmt1' :: (a -> m) -> a -> m @+-}+{-# INLINE fmt1 #-}+fmt1 :: (a -> m) -> Fmt1 m s a+fmt1 f = Fmt $ \k -> k . f++{-# INLINE fmt2 #-}+fmt2 :: (a -> b -> m) -> Fmt2 m s a b+fmt2 f = Fmt $ \k -> fmap k . f++{-# INLINE fmt1_ #-}+fmt1_ :: Fmt m a a -> Fmt1 m a b+fmt1_ = lmap const . closed++{-# INLINE fmt2_ #-}+fmt2_ :: Fmt m a a -> Fmt2 m a b c+fmt2_ = lmap (const . const) . (closed . closed)++-- | Concatenate two formatters, applying both to the same input.+infixr 6 .%++{-# INLINE (.%) #-}+(.%) :: Semigroup m => Fmt1 m s a -> Fmt1 m s a -> Fmt1 m s a+f .% g =+ Fmt+ ( \k a ->+ unFmt f (\b1 -> unFmt g (\b2 -> k (b1 <> b2)) a) a+ )++{- | Format each value in a list and concatenate them all:++ >>> runFmt (cat1 (s % " ")) ["one", "two", "three"]+ "one two three "+-}+{-# INLINE cat1 #-}+cat1 :: (Monoid m, Foldable f) => Fmt1 m m a -> Fmt1 m s (f a)+cat1 f = fmt1 $ foldMap (runFmt f)++{- | Use the given text-joining function to join together the individually rendered items of a list.++ >>> runLogFmt (cat1With (mconcat . reverse) d) [123, 456, 789]+ "789456123"++ @+ 'cat1With' 'L.unlines' :: 'Foldable' f => 'Fmt1' 'LogStr' 'String' a -> 'Fmt1' 'LogStr' s (f a)+ 'cat1With' 'T.unlines' :: 'Foldable' f => 'Fmt1' 'LogStr' 'T.Text' a -> 'Fmt1' 'LogStr' s (f a)+ 'cat1With' 'B.unlines' :: 'Foldable' f => 'Fmt1' 'LogStr' 'B.ByteString' a -> 'Fmt1' 'LogStr' s (f a)+ 'cat1With' '$' 'L.intercalate' " " :: 'Foldable' f => 'Fmt1' 'LogStr' 'String' a -> 'Fmt1' 'LogStr' s (f a)+ 'cat1With' '$' 'T.intercalate' " " :: 'Foldable' f => 'Fmt1' 'LogStr' 'T.Text' a -> 'Fmt1' 'LogStr' s (f a)+ 'cat1With' '$' 'B.intercalate' " " :: 'Foldable' f => 'Fmt1' 'LogStr' 'B.ByteString' a -> 'Fmt1' 'LogStr' s (f a)+ @+-}+{-# INLINEABLE cat1With #-}+cat1With ::+ (Foldable f, ToLogStr str, IsString str) =>+ ([str] -> str) ->+ Fmt1 LogStr str a ->+ Fmt1 LogStr s (f a)+cat1With join f = fmt1 $ toLogStr . join . fmap (runLogFmt f) . toList+{-# SPECIALIZE cat1With :: Foldable f => ([LogStr] -> LogStr) -> Fmt1 LogStr LogStr a -> Fmt1 LogStr s (f a) #-}+{-# SPECIALIZE cat1With :: Foldable f => ([Builder] -> Builder) -> Fmt1 LogStr Builder a -> Fmt1 LogStr s (f a) #-}+{-# SPECIALIZE cat1With :: Foldable f => ([ByteString] -> ByteString) -> Fmt1 LogStr ByteString a -> Fmt1 LogStr s (f a) #-}+{-# SPECIALIZE cat1With :: Foldable f => ([BL.ByteString] -> BL.ByteString) -> Fmt1 LogStr BL.ByteString a -> Fmt1 LogStr s (f a) #-}++{- | Turn a text-splitting function into a formatting combinator.++ @+ 'split1With' 'hsep' :: ('Traversable' f, 'ToLogStr' msg) => ('ByteString' -> f msg) -> 'Fmt' 'LogStr' s a -> 'Fmt' 'LogStr' s a+ 'split1With' 'vsep' :: ('Traversable' f, 'ToLogStr' msg) => ('ByteString' -> f msg) -> 'Fmt' 'LogStr' s a -> 'Fmt' 'LogStr' s a+ 'split1With' 'list1' :: ('Traversable' f, 'ToLogStr' msg) => ('ByteString' -> f msg) -> 'Fmt' 'LogStr' s a -> 'Fmt' 'LogStr' s a+ @+ >>> commas = reverse . fmap BL.reverse . BL.chunksOf 3 . BL.reverse+ >>> dollars = prefix "$" . split1With commas (intercalate ",") . reversed+ >>> runLogFmt (dollars d) 1234567890+ "$1,234,567,890"+ >>> printf (split1With (BL.splitOn ",") vsep t) "one,two,three"+ one+ two+ three+ >>> printf (split1With (BL.splitOn ",") (indentEach 4) t) "one,two,three"+ one+ two+ three+-}+{-# INLINEABLE split1With #-}+split1With ::+ (Traversable f, ToLogStr str) =>+ (Fmt1 m s_ m -> Fmt1 m m (f LogStr)) ->+ (ByteString -> f str) ->+ Fmt LogStr s a ->+ Fmt m s a+split1With lf split (Fmt g) = Fmt (g . (. runFmt (lf $ fmt1 id) . fmap toLogStr . split . fromLogStr))++-- Html++-------------------------++{- | Format HTML++ For example:++ @+ contact :: 'Html' 'LogStr'+ contact = 'Data.Fmt.Html.p' "You can reach me at" '%' 'Data.Fmt.Html.ul' . 'spr' . 'Data.Fmt.Html.li' $ do+ c1 <- 'Data.Fmt.Html.a' '!' 'href' @String "https://example.com" $ "Website"+ c2 <- 'Data.Fmt.Html.a' '!' 'href' @String "mailto:cmk@example.com" $ "Email"+ 'pure' $ c1 '<>' c2+ @+ + generates the following output:++ > "<p>You can reach me at</p><ul><li><a href=\"https://foo.com\">Web</a></li><li><a href=\"mailto:cmk@foo.com\">Email</a></li></ul>"+-}+type Html a = Fmt LogStr a a++toHtml :: ToLogStr s => s -> Html a+toHtml = logFmt++comment :: ToLogStr s => s -> Html a+comment = enclose "<!-- " " -->" . toHtml++-- | Type for an attribute.+newtype Attr = Attr (forall a. Html a -> Html a)++instance Semigroup Attr where+ Attr f <> Attr g = Attr (g . f)++instance Monoid Attr where+ mempty = Attr id++{- | Apply an attribute to an HTML tag.++ The interface is similar to < https://hackage.haskell.org/package/blaze-builder >.++ You should not define your own instances of this class.+-}+class Element html where+ {- | Apply an attribute to an element.++ >>> printf $ img ! src "foo.png"+ <img src="foo.png" />++ This can be used on nested elements as well:++ >>> printf $ p ! style "float: right" $ "Hello!"+ <p style="float: right">Hello!</p>+ -}+ (!) :: html -> Attr -> html++instance Element (Html a) where+ h ! (Attr f) = f h+ {-# INLINE (!) #-}++instance Element (Html a -> Html b) where+ h ! f = (! f) . h+ {-# INLINE (!) #-}++{- | Shorthand for setting an attribute depending on a conditional.++ Example:++ > p !? (isBig, A.class "big") $ "Hello"++ Gives the same result as:++ > (if isBig then p ! A.class "big" else p) "Hello"+-}+(!?) :: Element html => html -> (Bool, Attr) -> html+(!?) h (c, a) = if c then h ! a else h++-- Formatting++-------------------------++{- | Format each value in a list with spaces in between:++ >>> runLogFmt (hsep d) [1, 2, 3]+ "1 2 3"+-}+hsep :: Foldable f => Fmt1 LogStr ByteString a -> Fmt1 LogStr s (f a)+hsep = cat1With $ B.intercalate " "+{-# INLINE hsep #-}++{- | Format each value in a list, placing each on its own line:++ >>> printf (vsep c) ['a'..'c']+ a+ b+ c+-}+vsep :: Foldable f => Fmt1 LogStr ByteString a -> Fmt1 LogStr s (f a)+vsep = cat1With B.unlines+{-# INLINE vsep #-}++{- | Format a list of items, placing one per line, indent by the given number of spaces.++ @ 'indentEach' n = 'Test.Contra.Type.Format.vsep' . 'indent' n @++ >>> printf (split1With BL.lines (indentList 2) t) "one\ntwo\nthree"+ one+ two+ three+ >>> printf ("The lucky numbers are:\n" % indentList 2 d) [7, 13, 1, 42]+ The lucky numbers are:+ 7+ 13+ 1+ 42+-}+hang :: Foldable f => Int -> Fmt1 LogStr ByteString a -> Fmt1 LogStr s (f a)+hang n = vsep . indent n+{-# INLINE hang #-}++{- | Insert the given number of spaces at the start of the rendered text:++ >>> runFmt (indent 4 d) 7+ " 7"++ Note that this only indents the first line of a multi-line string.+ To indent all lines see 'reindent'.+-}+indent :: (IsString m, Semigroup m) => Int -> Fmt m a b -> Fmt m a b+indent n = prefix $ fromString $ replicate n ' '+{-# INLINEABLE indent #-}++{- | Add the given prefix to the formatted item:++ >>> runLogFmt ("The answer is: " % prefix "wait for it... " d) 42+ "The answer is: wait for it... 42"++ >>> printf (vsep (indent 4 (prefix "- " d))) [1, 2, 3]+ - 1+ - 2+ - 3+-}+prefix :: Semigroup m => m -> Fmt m a b -> Fmt m a b+prefix s f = fmt s % f+{-# INLINE prefix #-}++-- | Add the given suffix to the formatted item.+suffix :: Semigroup m => m -> Fmt m a b -> Fmt m a b+suffix s f = f % fmt s+{-# INLINE suffix #-}++{- | Enclose the output string with the given strings:++ >>> runFmt (parens $ enclose v s ", ") 1 "two"+ "(1, two)"+ >>> runFmt (enclose (fmt "<!--") (fmt "-->") s) "an html comment"+ "<!--an html comment-->"+-}+enclose :: Semigroup m => Fmt m b2 c -> Fmt m a b1 -> Fmt m b1 b2 -> Fmt m a c+enclose pre suf f = pre % f % suf+{-# INLINE enclose #-}++-- @ 'tuple' 'd' 'd' :: 'LogFmt2' a 'Int' @+--+-- >>> runFmt (tuple d t) 1 "two"+-- "(1, two)"+tuple :: (Semigroup m, IsString m) => Fmt m b c -> Fmt m a b -> Fmt m a c+tuple f1 f2 = parens $ enclose f1 f2 ", "++{- | Add double quotes around the formatted item:++ Use this to escape a string:++ >>> runFmt ("He said it was based on " % quotes t' % ".") "science"+ He said it was based on "science".+-}+quotes :: (Semigroup m, IsString m) => Fmt m a b -> Fmt m a b+quotes = enclose "\"" "\""+{-# INLINE quotes #-}++{- | Add single quotes around the formatted item:++ >>> let obj = Just Nothing in format ("The object is: " % quotes' shown % ".") obj+ "The object is: 'Just Nothing'."+-}+quotes' :: (Semigroup m, IsString m) => Fmt m a b -> Fmt m a b+quotes' = enclose "'" "'"+{-# INLINE quotes' #-}++{- | Add parentheses around the formatted item:++ >>> runFmt ("We found " % parens d % " discrepancies.") 17+ "We found (17) discrepancies."++ >>> printf (get 5 (list1 (parens d))) [1..]+ [(1), (2), (3), (4), (5)]+-}+parens :: (Semigroup m, IsString m) => Fmt m a b -> Fmt m a b+parens = enclose "(" ")"+{-# INLINE parens #-}++{- | Add braces around the formatted item:++ >>> runFmt ("\\begin" % braces t) "section"+ "\\begin{section}"+-}+braces :: (Semigroup m, IsString m) => Fmt m a b -> Fmt m a b+braces = enclose "{" "}"+{-# INLINE braces #-}++{- | Add square brackets around the formatted item:++ >>> runFmt (brackets d) 7+ "[7]"+-}+brackets :: (Semigroup m, IsString m) => Fmt m a b -> Fmt m a b+brackets = enclose "[" "]"+{-# INLINE brackets #-}++{- | Add backticks around the formatted item:++ >>> runLogFmt ("Be sure to run " % backticks builder % " as root.") ":(){:|:&};:"+ "Be sure to run `:(){:|:&};:` as root."+-}+backticks :: (Semigroup m, IsString m) => Fmt m a b -> Fmt m a b+backticks = enclose "`" "`"+{-# INLINE backticks #-}++-- Collections++-------------------------++{- | Render the value in a Left with the given formatter, rendering a Right as an empty string:++ >>> runLogFmt (left1 text) (Left "bingo")+ "bingo"++ >>> runLogFmt (left1 text) (Right 16)+ ""+-}+left1 :: IsString m => Fmt1 m m a -> Fmt1 m s (Either a b)+left1 f = either1 f (fmt1 $ const "")+{-# INLINE left1 #-}++{- | Render the value in a Right with the given formatter, rendering a Left as an empty string:++ >>> runLogFmt (right1 text) (Left 16)+ ""++ >>> runLogFmt (right1 text) (Right "bingo")+ "bingo"+-}+right1 :: IsString m => Fmt1 m m b -> Fmt1 m s (Either a b)+right1 = either1 (fmt1 $ const "")+{-# INLINE right1 #-}++{- | Render the value in an Either:++ >>> runLogFmt (either1 text int) (Left "Error!"+ "Error!"++ >>> runLogFmt (either1 text int) (Right 69)+ "69"+-}+either1 :: Fmt1 m m a -> Fmt1 m m b -> Fmt1 m s (Either a b)+either1 l r = fmt1 $ either (runFmt l) (runFmt r)+{-# INLINE either1 #-}++{- | Render a Maybe value either as a default (if Nothing) or using the given formatter:++ >>> runLogFmt (maybe1 "Goodbye" text) Nothing+ "Goodbye"++ >>> runLogFmt (maybe1 "Goodbye" text) (Just "Hello")+ "Hello"+-}+maybe1 :: m -> Fmt1 m m a -> Fmt1 m s (Maybe a)+maybe1 def f = fmt1 $ maybe def (runFmt f)+{-# INLINE maybe1 #-}++{- | Add square brackets around the Foldable (e.g. a list), and separate each formatted item with a comma and space.++ >>> runLogFmt (list1 s) ["one", "two", "three"]+ "[one, two, three]"+ >>> printf (quotes $ list1 d) [1,2,3]+ ["1", "2", "3"]+ >>> printf (quotes $ list1 s) ["one", "two", "three"]+ ["one", "two", "three"]+-}+list1 :: Foldable f => Fmt1 LogStr ByteString a -> Fmt1 LogStr s (f a)+list1 = cat1With (B.intercalate ", ") . brackets+{-# INLINE list1 #-}++{- | A JSON-style formatter for lists.++ >>> printf jsonList [1,2,3]+ [+ 1+ , 2+ , 3+ ]++ Like 'yamlListF', it handles multiline elements well:++ >>> fmt $ jsonListF ["hello\nworld", "foo\nbar\nquix"]+ [+ hello+ world+ , foo+ bar+ quix+ ]+-}+{-# INLINE jsonList #-}+jsonList :: (Foldable f, ToLogStr a) => Fmt1 LogStr s (f a)+jsonList = fmt1 f+ where+ f xs+ | null items = "[]\n"+ | otherwise = "[\n" <> mconcat items <> "]\n"+ where+ items = zipWith buildItem (True : repeat False) (toList xs)+ -- Item builder+ --buildItem :: Bool -> a -> B++ buildItem isFirst x =+ case map toLogStr (B.lines (fromLogStr (toLogStr x))) of+ []+ | isFirst -> "\n"+ | otherwise -> ",\n"+ (h : t) ->+ mconcat . map (<> "\n") $+ if isFirst+ then " " <> h : fmap (" " <>) t+ else ", " <> h : fmap (" " <>) t++{- | A multiline formatter for lists.++ >>> printf (yamlList d) [1,2,3]+ - 1+ - 2+ - 3++ Multi-line elements are indented correctly:++ >>> printf (yamlList s) ["hello\nworld", "foo\nbar\nquix"]+ - hello+ world+ - foo+ bar+ quix+-}+{-# INLINE yamlList #-}+yamlList :: (Foldable f, ToLogStr a) => Fmt1 LogStr s (f a)+yamlList = fmt1 f+ where+ f xs = if null items then "[]\n" else mconcat items+ where+ bullet = "-"+ spaces = " "+ newline = "\n"+ items = map buildItem (toList xs)+ buildItem x = case B.lines (fromLogStr (toLogStr x)) of+ [] -> bullet <> newline+ (l : ls) ->+ bullet <> " " <> toLogStr l <> newline+ <> mconcat [spaces <> toLogStr s <> newline | s <- ls]++{- | A JSON-like map formatter; works for Map, HashMap, etc, and lists of pairs.++>>> fmt $ jsonMapF [("Odds", jsonListF [1,3]), ("Evens", jsonListF [2,4])]+{+ Odds:+ [+ 1+ , 3+ ]+, Evens:+ [+ 2+ , 4+ ]+}+-}+{-# INLINE jsonMap #-}+jsonMap :: (ToLogStr k, IsList map, Item map ~ (k, ByteString)) => Fmt1 LogStr s map+jsonMap = fmt1 f+ where+ f xs+ | null items = "{}\n"+ | otherwise = "{\n" <> mconcat items <> "}\n"+ where+ items = zipWith buildItem (True : repeat False) (IsList.toList xs)+ -- Item builder+ --buildItem :: Bool -> (k, v) -> B+ buildItem isFirst (k, v) = do+ let kb = (if isFirst then " " else ", ") <> toLogStr k+ case map toLogStr (B.lines v) of+ [] -> kb <> ":\n"+ [l] -> kb <> ": " <> l <> "\n"+ ls ->+ kb <> ":\n"+ <> mconcat [" " <> s <> "\n" | s <- ls]++-- | A YAML-like map formatter:+--+-- >>> BL.putStrLn $ BL.toLazyByteString $ yamlMapF id id [("Odds", yamlListF (BL.fromString . show) "-" [1,3]), ("Evens", yamlListF (BL.fromString . show) "-" [2,4])]+-- Odds:+-- - 1+-- - 3+-- Evens:+-- - 2+-- - 4+{-# INLINE yamlMap #-}+yamlMap :: (ToLogStr k, ToLogStr v, IsList map, Item map ~ (k, v)) => Fmt1 LogStr s map+yamlMap = fmt1 f+ where+ f xs+ | null items = "{}\n"+ | otherwise = mconcat items+ where+ items = map (\(k, v) -> nameF (toLogStr k) (toLogStr v)) (IsList.toList xs)++nameF :: LogStr -> LogStr -> LogStr+nameF k v = case B.lines (fromLogStr v) of+ [] -> k <> ":\n"+ [l] -> k <> ": " <> toLogStr l <> "\n"+ ls ->+ k <> ":\n"+ <> mconcat [" " <> toLogStr s <> "\n" | s <- ls]
+ src/Data/Fmt/Ansi.hs view
@@ -0,0 +1,102 @@+module Data.Fmt.Ansi (+ -- * Ansi terminal codes+ code,+ codes,+ erase,+ reset,+ shift,+ scroll,++ -- ** Emphasis+ blink,+ bold,+ faint,+ italic,+ underline,++ -- ** Color+ dull,+ vivid,+ layer,+ palette,+ Palette,+ XColor,+ Color (..),+ ConsoleLayer (..),+) where++import Data.Fmt+import Data.Word+import System.Console.ANSI.Codes+import System.Console.ANSI.Types++-- Ansi terminal formatters++-------------------------++code :: (Semigroup m, IsString m) => SGR -> Fmt m s a -> Fmt m s a+code = codes . pure++-- | Wrap content with escape sequence to set and reset color of normal intensity.+codes :: (Semigroup m, IsString m) => [SGR] -> Fmt m s a -> Fmt m s a+codes sgr x = enclose before after x+ where+ before = fromString $ setSGRCode sgr+ after = fromString $ setSGRCode [Reset]++erase :: (Semigroup m, IsString m) => Ordering -> Fmt m s a -> Fmt m s a+erase LT = suffix $ fromString clearFromCursorToLineBeginningCode+erase EQ = suffix $ fromString clearLineCode+erase GT = suffix $ fromString clearFromCursorToLineEndCode++reset :: (Semigroup m, IsString m) => Fmt m s a -> Fmt m s a+reset = prefix $ fromString $ setSGRCode [Reset]++shift :: (Semigroup m, IsString m) => Either Int Int -> Fmt m s a -> Fmt m s a+shift = prefix . fromString . either cursorBackwardCode cursorForwardCode++scroll :: (Semigroup m, IsString m) => Either Int Int -> Fmt m s a -> Fmt m s a+scroll = prefix . fromString . either scrollPageUpCode scrollPageDownCode++-- Emphasis++-------------------------++blink :: (Semigroup m, IsString m) => Fmt m s a -> Fmt m s a+blink = code $ SetBlinkSpeed SlowBlink++bold :: (Semigroup m, IsString m) => Fmt m s a -> Fmt m s a+bold = code $ SetConsoleIntensity BoldIntensity++italic :: (Semigroup m, IsString m) => Fmt m s a -> Fmt m s a+italic = code $ SetItalicized True++underline :: (Semigroup m, IsString m) => Fmt m s a -> Fmt m s a+underline = code $ SetUnderlining SingleUnderline++faint :: (Semigroup m, IsString m) => Fmt m s a -> Fmt m s a+faint = code $ SetConsoleIntensity FaintIntensity++-- Color++-------------------------++-- | The xterm < https://en.wikipedia.org/wiki/8-bit_color 8 bit > color encoding.+type XColor = Word8++-- | A simple palette consisting of a foreground and background color.+type Palette = (XColor, XColor)++dull :: (Semigroup m, IsString m) => Color -> ConsoleLayer -> Fmt m s a -> Fmt m s a+dull = layer . xtermSystem Dull++vivid :: (Semigroup m, IsString m) => Color -> ConsoleLayer -> Fmt m s a -> Fmt m s a+vivid = layer . xtermSystem Vivid++--vivid col lay = code $ SetColor lay Vivid col++layer :: (Semigroup m, IsString m) => XColor -> ConsoleLayer -> Fmt m s a -> Fmt m s a+layer pal lay = code $ SetPaletteColor lay pal++palette :: (Semigroup m, IsString m) => Palette -> Fmt m s a -> Fmt m s a+palette (fg, bg) = codes [SetPaletteColor Foreground fg, SetPaletteColor Background bg]
+ src/Data/Fmt/Attr.hs view
@@ -0,0 +1,3414 @@+{-# LANGUAGE OverloadedStrings #-}++{- | Html5 formatting.++ The API is similar to < https://hackage.haskell.org/package/blaze-html >.+-}+module Data.Fmt.Attr (+ -- * Html+ Html,+ Attr,+ toHtml,+ comment,+ Element (..),+ (!?),++ -- * Attributes+ accept,+ acceptCharset,+ accesskey,+ action,+ alt,+ async,+ autocomplete,+ autofocus,+ autoplay,+ challenge,+ charset,+ checked,+ cite,+ class_,+ cols,+ colspan,+ content,+ contenteditable,+ contextmenu,+ controls,+ coords,+ data_,+ datetime,+ defer,+ dir,+ disabled,+ draggable,+ enctype,+ for,+ form,+ formaction,+ formenctype,+ formmethod,+ formnovalidate,+ formtarget,+ headers,+ height,+ hidden,+ high,+ href,+ hreflang,+ httpEquiv,+ icon,+ id,+ ismap,+ item,+ itemprop,+ itemscope,+ itemtype,+ keytype,+ label,+ lang,+ list,+ loop,+ low,+ manifest,+ max,+ maxlength,+ media,+ method,+ min,+ multiple,+ name,+ novalidate,+ onbeforeonload,+ onbeforeprint,+ onblur,+ oncanplay,+ oncanplaythrough,+ onchange,+ onclick,+ oncontextmenu,+ ondblclick,+ ondrag,+ ondragend,+ ondragenter,+ ondragleave,+ ondragover,+ ondragstart,+ ondrop,+ ondurationchange,+ onemptied,+ onended,+ onerror,+ onfocus,+ onformchange,+ onforminput,+ onhaschange,+ oninput,+ oninvalid,+ onkeydown,+ onkeyup,+ onload,+ onloadeddata,+ onloadedmetadata,+ onloadstart,+ onmessage,+ onmousedown,+ onmousemove,+ onmouseout,+ onmouseover,+ onmouseup,+ onmousewheel,+ ononline,+ onpagehide,+ onpageshow,+ onpause,+ onplay,+ onplaying,+ onprogress,+ onpropstate,+ onratechange,+ onreadystatechange,+ onredo,+ onresize,+ onscroll,+ onseeked,+ onseeking,+ onselect,+ onstalled,+ onstorage,+ onsubmit,+ onsuspend,+ ontimeupdate,+ onundo,+ onunload,+ onvolumechange,+ onwaiting,+ open,+ optimum,+ pattern,+ ping,+ placeholder,+ preload,+ pubdate,+ radiogroup,+ readonly,+ rel,+ required,+ reversed,+ role,+ rows,+ rowspan,+ sandbox,+ scope,+ scoped,+ seamless,+ selected,+ shape,+ size,+ sizes,+ span,+ spellcheck,+ src,+ srcdoc,+ start,+ step,+ style,+ subject,+ summary,+ tabindex,+ target,+ title,+ type_,+ usemap,+ value,+ width,+ wrap,+ xmlns,+) where++import qualified Data.ByteString.Char8 as B+import Data.Fmt+import Prelude (Eq (..), Maybe (..), Monoid (..), ($), (||))++attr :: ToLogStr s => LogStr -> s -> Attr+attr k v = Attr $ splitWith f g+ where+ f = B.break $ \c -> c == '/' || c == '>'+ g l r0 = case B.uncons r0 of+ Just ('/', r) -> toHtml l % fmt k % "=" % quotes (toHtml v) % fmt " /" % toHtml r+ Just ('>', r) -> toHtml l % " " % fmt k % "=" % quotes (toHtml v) % fmt ">" % toHtml r+ _ -> fmt mempty++-- Attributes++-------------------------++{- | Combinator for the @accept@ attribute.++ Example:++ > div ! accept "bar" $ "Hello."++ Result:++ > <div accept="bar">Hello.</div>+-}+accept ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+accept = attr "accept"+{-# INLINE accept #-}++{- | Combinator for the @accept-charset@ attribute.++ Example:++ > div ! acceptCharset "bar" $ "Hello."++ Result:++ > <div accept-charset="bar">Hello.</div>+-}+acceptCharset ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+acceptCharset = attr "accept-charset"+{-# INLINE acceptCharset #-}++{- | Combinator for the @accesskey@ attribute.++ Example:++ > div ! accesskey "bar" $ "Hello."++ Result:++ > <div accesskey="bar">Hello.</div>+-}+accesskey ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+accesskey = attr "accesskey"+{-# INLINE accesskey #-}++{- | Combinator for the @action@ attribute.++ Example:++ > div ! action "bar" $ "Hello."++ Result:++ > <div action="bar">Hello.</div>+-}+action ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+action = attr "action"+{-# INLINE action #-}++{- | Combinator for the @alt@ attribute.++ Example:++ > div ! alt "bar" $ "Hello."++ Result:++ > <div alt="bar">Hello.</div>+-}+alt ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+alt = attr "alt"+{-# INLINE alt #-}++{- | Combinator for the @async@ attribute.++ Example:++ > div ! async "bar" $ "Hello."++ Result:++ > <div async="bar">Hello.</div>+-}+async ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+async = attr "async"+{-# INLINE async #-}++{- | Combinator for the @autocomplete@ attribute.++ Example:++ > div ! autocomplete "bar" $ "Hello."++ Result:++ > <div autocomplete="bar">Hello.</div>+-}+autocomplete ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+autocomplete = attr "autocomplete"+{-# INLINE autocomplete #-}++{- | Combinator for the @autofocus@ attribute.++ Example:++ > div ! autofocus "bar" $ "Hello."++ Result:++ > <div autofocus="bar">Hello.</div>+-}+autofocus ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+autofocus = attr "autofocus"+{-# INLINE autofocus #-}++{- | Combinator for the @autoplay@ attribute.++ Example:++ > div ! autoplay "bar" $ "Hello."++ Result:++ > <div autoplay="bar">Hello.</div>+-}+autoplay ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+autoplay = attr "autoplay"+{-# INLINE autoplay #-}++{- | Combinator for the @challenge@ attribute.++ Example:++ > div ! challenge "bar" $ "Hello."++ Result:++ > <div challenge="bar">Hello.</div>+-}+challenge ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+challenge = attr "challenge"+{-# INLINE challenge #-}++{- | Combinator for the @charset@ attribute.++ Example:++ > div ! charset "bar" $ "Hello."++ Result:++ > <div charset="bar">Hello.</div>+-}+charset ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+charset = attr "charset"+{-# INLINE charset #-}++{- | Combinator for the @checked@ attribute.++ Example:++ > div ! checked "bar" $ "Hello."++ Result:++ > <div checked="bar">Hello.</div>+-}+checked ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+checked = attr "checked"+{-# INLINE checked #-}++{- | Combinator for the @cite@ attribute.++ Example:++ > div ! cite "bar" $ "Hello."++ Result:++ > <div cite="bar">Hello.</div>+-}+cite ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+cite = attr "cite"+{-# INLINE cite #-}++{- | Combinator for the @class@ attribute.++ Example:++ > div ! class_ "bar" $ "Hello."++ Result:++ > <div class="bar">Hello.</div>+-}+class_ ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+class_ = attr "class"+{-# INLINE class_ #-}++{- | Combinator for the @cols@ attribute.++ Example:++ > div ! cols "bar" $ "Hello."++ Result:++ > <div cols="bar">Hello.</div>+-}+cols ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+cols = attr "cols"+{-# INLINE cols #-}++{- | Combinator for the @colspan@ attribute.++ Example:++ > div ! colspan "bar" $ "Hello."++ Result:++ > <div colspan="bar">Hello.</div>+-}+colspan ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+colspan = attr "colspan"+{-# INLINE colspan #-}++{- | Combinator for the @content@ attribute.++ Example:++ > div ! content "bar" $ "Hello."++ Result:++ > <div content="bar">Hello.</div>+-}+content ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+content = attr "content"+{-# INLINE content #-}++{- | Combinator for the @contenteditable@ attribute.++ Example:++ > div ! contenteditable "bar" $ "Hello."++ Result:++ > <div contenteditable="bar">Hello.</div>+-}+contenteditable ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+contenteditable = attr "contenteditable"+{-# INLINE contenteditable #-}++{- | Combinator for the @contextmenu@ attribute.++ Example:++ > div ! contextmenu "bar" $ "Hello."++ Result:++ > <div contextmenu="bar">Hello.</div>+-}+contextmenu ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+contextmenu = attr "contextmenu"+{-# INLINE contextmenu #-}++{- | Combinator for the @controls@ attribute.++ Example:++ > div ! controls "bar" $ "Hello."++ Result:++ > <div controls="bar">Hello.</div>+-}+controls ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+controls = attr "controls"+{-# INLINE controls #-}++{- | Combinator for the @coords@ attribute.++ Example:++ > div ! coords "bar" $ "Hello."++ Result:++ > <div coords="bar">Hello.</div>+-}+coords ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+coords = attr "coords"+{-# INLINE coords #-}++{- | Combinator for the @data@ attribute.++ Example:++ > div ! data_ "bar" $ "Hello."++ Result:++ > <div data="bar">Hello.</div>+-}+data_ ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+data_ = attr "data"+{-# INLINE data_ #-}++{- | Combinator for the @datetime@ attribute.++ Example:++ > div ! datetime "bar" $ "Hello."++ Result:++ > <div datetime="bar">Hello.</div>+-}+datetime ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+datetime = attr "datetime"+{-# INLINE datetime #-}++{- | Combinator for the @defer@ attribute.++ Example:++ > div ! defer "bar" $ "Hello."++ Result:++ > <div defer="bar">Hello.</div>+-}+defer ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+defer = attr "defer"+{-# INLINE defer #-}++{- | Combinator for the @dir@ attribute.++ Example:++ > div ! dir "bar" $ "Hello."++ Result:++ > <div dir="bar">Hello.</div>+-}+dir ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+dir = attr "dir"+{-# INLINE dir #-}++{- | Combinator for the @disabled@ attribute.++ Example:++ > div ! disabled "bar" $ "Hello."++ Result:++ > <div disabled="bar">Hello.</div>+-}+disabled ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+disabled = attr "disabled"+{-# INLINE disabled #-}++{- | Combinator for the @draggable@ attribute.++ Example:++ > div ! draggable "bar" $ "Hello."++ Result:++ > <div draggable="bar">Hello.</div>+-}+draggable ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+draggable = attr "draggable"+{-# INLINE draggable #-}++{- | Combinator for the @enctype@ attribute.++ Example:++ > div ! enctype "bar" $ "Hello."++ Result:++ > <div enctype="bar">Hello.</div>+-}+enctype ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+enctype = attr "enctype"+{-# INLINE enctype #-}++{- | Combinator for the @for@ attribute.++ Example:++ > div ! for "bar" $ "Hello."++ Result:++ > <div for="bar">Hello.</div>+-}+for ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+for = attr "for"+{-# INLINE for #-}++{- | Combinator for the @form@ attribute.++ Example:++ > div ! form "bar" $ "Hello."++ Result:++ > <div form="bar">Hello.</div>+-}+form ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+form = attr "form"+{-# INLINE form #-}++{- | Combinator for the @formaction@ attribute.++ Example:++ > div ! formaction "bar" $ "Hello."++ Result:++ > <div formaction="bar">Hello.</div>+-}+formaction ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+formaction = attr "formaction"+{-# INLINE formaction #-}++{- | Combinator for the @formenctype@ attribute.++ Example:++ > div ! formenctype "bar" $ "Hello."++ Result:++ > <div formenctype="bar">Hello.</div>+-}+formenctype ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+formenctype = attr "formenctype"+{-# INLINE formenctype #-}++{- | Combinator for the @formmethod@ attribute.++ Example:++ > div ! formmethod "bar" $ "Hello."++ Result:++ > <div formmethod="bar">Hello.</div>+-}+formmethod ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+formmethod = attr "formmethod"+{-# INLINE formmethod #-}++{- | Combinator for the @formnovalidate@ attribute.++ Example:++ > div ! formnovalidate "bar" $ "Hello."++ Result:++ > <div formnovalidate="bar">Hello.</div>+-}+formnovalidate ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+formnovalidate = attr "formnovalidate"+{-# INLINE formnovalidate #-}++{- | Combinator for the @formtarget@ attribute.++ Example:++ > div ! formtarget "bar" $ "Hello."++ Result:++ > <div formtarget="bar">Hello.</div>+-}+formtarget ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+formtarget = attr "formtarget"+{-# INLINE formtarget #-}++{- | Combinator for the @headers@ attribute.++ Example:++ > div ! headers "bar" $ "Hello."++ Result:++ > <div headers="bar">Hello.</div>+-}+headers ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+headers = attr "headers"+{-# INLINE headers #-}++{- | Combinator for the @height@ attribute.++ Example:++ > div ! height "bar" $ "Hello."++ Result:++ > <div height="bar">Hello.</div>+-}+height ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+height = attr "height"+{-# INLINE height #-}++{- | Combinator for the @hidden@ attribute.++ Example:++ > div ! hidden "bar" $ "Hello."++ Result:++ > <div hidden="bar">Hello.</div>+-}+hidden ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+hidden = attr "hidden"+{-# INLINE hidden #-}++{- | Combinator for the @high@ attribute.++ Example:++ > div ! high "bar" $ "Hello."++ Result:++ > <div high="bar">Hello.</div>+-}+high ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+high = attr "high"+{-# INLINE high #-}++{- | Combinator for the @href@ attribute.++ Example:++ > div ! href "bar" $ "Hello."++ Result:++ > <div href="bar">Hello.</div>+-}+href ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+href = attr "href"+{-# INLINE href #-}++{- | Combinator for the @hreflang@ attribute.++ Example:++ > div ! hreflang "bar" $ "Hello."++ Result:++ > <div hreflang="bar">Hello.</div>+-}+hreflang ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+hreflang = attr "hreflang"+{-# INLINE hreflang #-}++{- | Combinator for the @http-equiv@ attribute.++ Example:++ > div ! httpEquiv "bar" $ "Hello."++ Result:++ > <div http-equiv="bar">Hello.</div>+-}+httpEquiv ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+httpEquiv = attr "http-equiv"+{-# INLINE httpEquiv #-}++{- | Combinator for the @icon@ attribute.++ Example:++ > div ! icon "bar" $ "Hello."++ Result:++ > <div icon="bar">Hello.</div>+-}+icon ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+icon = attr "icon"+{-# INLINE icon #-}++{- | Combinator for the @id@ attribute.++ Example:++ > div ! id "bar" $ "Hello."++ Result:++ > <div id="bar">Hello.</div>+-}+id ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+id = attr "id"+{-# INLINE id #-}++{- | Combinator for the @ismap@ attribute.++ Example:++ > div ! ismap "bar" $ "Hello."++ Result:++ > <div ismap="bar">Hello.</div>+-}+ismap ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ismap = attr "ismap"+{-# INLINE ismap #-}++{- | Combinator for the @item@ attribute.++ Example:++ > div ! item "bar" $ "Hello."++ Result:++ > <div item="bar">Hello.</div>+-}+item ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+item = attr "item"+{-# INLINE item #-}++{- | Combinator for the @itemprop@ attribute.++ Example:++ > div ! itemprop "bar" $ "Hello."++ Result:++ > <div itemprop="bar">Hello.</div>+-}+itemprop ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+itemprop = attr "itemprop"+{-# INLINE itemprop #-}++{- | Combinator for the @itemscope@ attribute.++ Example:++ > div ! itemscope "bar" $ "Hello."++ Result:++ > <div itemscope="bar">Hello.</div>+-}+itemscope ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+itemscope = attr "itemscope"+{-# INLINE itemscope #-}++{- | Combinator for the @itemtype@ attribute.++ Example:++ > div ! itemtype "bar" $ "Hello."++ Result:++ > <div itemtype="bar">Hello.</div>+-}+itemtype ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+itemtype = attr "itemtype"+{-# INLINE itemtype #-}++{- | Combinator for the @keytype@ attribute.++ Example:++ > div ! keytype "bar" $ "Hello."++ Result:++ > <div keytype="bar">Hello.</div>+-}+keytype ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+keytype = attr "keytype"+{-# INLINE keytype #-}++{- | Combinator for the @label@ attribute.++ Example:++ > div ! label "bar" $ "Hello."++ Result:++ > <div label="bar">Hello.</div>+-}+label ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+label = attr "label"+{-# INLINE label #-}++{- | Combinator for the @lang@ attribute.++ Example:++ > div ! lang "bar" $ "Hello."++ Result:++ > <div lang="bar">Hello.</div>+-}+lang ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+lang = attr "lang"+{-# INLINE lang #-}++{- | Combinator for the @list@ attribute.++ Example:++ > div ! list "bar" $ "Hello."++ Result:++ > <div list="bar">Hello.</div>+-}+list ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+list = attr "list"+{-# INLINE list #-}++{- | Combinator for the @loop@ attribute.++ Example:++ > div ! loop "bar" $ "Hello."++ Result:++ > <div loop="bar">Hello.</div>+-}+loop ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+loop = attr "loop"+{-# INLINE loop #-}++{- | Combinator for the @low@ attribute.++ Example:++ > div ! low "bar" $ "Hello."++ Result:++ > <div low="bar">Hello.</div>+-}+low ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+low = attr "low"+{-# INLINE low #-}++{- | Combinator for the @manifest@ attribute.++ Example:++ > div ! manifest "bar" $ "Hello."++ Result:++ > <div manifest="bar">Hello.</div>+-}+manifest ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+manifest = attr "manifest"+{-# INLINE manifest #-}++{- | Combinator for the @max@ attribute.++ Example:++ > div ! max "bar" $ "Hello."++ Result:++ > <div max="bar">Hello.</div>+-}+max ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+max = attr "max"+{-# INLINE max #-}++{- | Combinator for the @maxlength@ attribute.++ Example:++ > div ! maxlength "bar" $ "Hello."++ Result:++ > <div maxlength="bar">Hello.</div>+-}+maxlength ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+maxlength = attr "maxlength"+{-# INLINE maxlength #-}++{- | Combinator for the @media@ attribute.++ Example:++ > div ! media "bar" $ "Hello."++ Result:++ > <div media="bar">Hello.</div>+-}+media ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+media = attr "media"+{-# INLINE media #-}++{- | Combinator for the @method@ attribute.++ Example:++ > div ! method "bar" $ "Hello."++ Result:++ > <div method="bar">Hello.</div>+-}+method ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+method = attr "method"+{-# INLINE method #-}++{- | Combinator for the @min@ attribute.++ Example:++ > div ! min "bar" $ "Hello."++ Result:++ > <div min="bar">Hello.</div>+-}+min ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+min = attr "min"+{-# INLINE min #-}++{- | Combinator for the @multiple@ attribute.++ Example:++ > div ! multiple "bar" $ "Hello."++ Result:++ > <div multiple="bar">Hello.</div>+-}+multiple ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+multiple = attr "multiple"+{-# INLINE multiple #-}++{- | Combinator for the @name@ attribute.++ Example:++ > div ! name "bar" $ "Hello."++ Result:++ > <div name="bar">Hello.</div>+-}+name ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+name = attr "name"+{-# INLINE name #-}++{- | Combinator for the @novalidate@ attribute.++ Example:++ > div ! novalidate "bar" $ "Hello."++ Result:++ > <div novalidate="bar">Hello.</div>+-}+novalidate ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+novalidate = attr "novalidate"+{-# INLINE novalidate #-}++{- | Combinator for the @onbeforeonload@ attribute.++ Example:++ > div ! onbeforeonload "bar" $ "Hello."++ Result:++ > <div onbeforeonload="bar">Hello.</div>+-}+onbeforeonload ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onbeforeonload = attr "onbeforeonload"+{-# INLINE onbeforeonload #-}++{- | Combinator for the @onbeforeprint@ attribute.++ Example:++ > div ! onbeforeprint "bar" $ "Hello."++ Result:++ > <div onbeforeprint="bar">Hello.</div>+-}+onbeforeprint ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onbeforeprint = attr "onbeforeprint"+{-# INLINE onbeforeprint #-}++{- | Combinator for the @onblur@ attribute.++ Example:++ > div ! onblur "bar" $ "Hello."++ Result:++ > <div onblur="bar">Hello.</div>+-}+onblur ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onblur = attr "onblur"+{-# INLINE onblur #-}++{- | Combinator for the @oncanplay@ attribute.++ Example:++ > div ! oncanplay "bar" $ "Hello."++ Result:++ > <div oncanplay="bar">Hello.</div>+-}+oncanplay ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+oncanplay = attr "oncanplay"+{-# INLINE oncanplay #-}++{- | Combinator for the @oncanplaythrough@ attribute.++ Example:++ > div ! oncanplaythrough "bar" $ "Hello."++ Result:++ > <div oncanplaythrough="bar">Hello.</div>+-}+oncanplaythrough ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+oncanplaythrough = attr "oncanplaythrough"+{-# INLINE oncanplaythrough #-}++{- | Combinator for the @onchange@ attribute.++ Example:++ > div ! onchange "bar" $ "Hello."++ Result:++ > <div onchange="bar">Hello.</div>+-}+onchange ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onchange = attr "onchange"+{-# INLINE onchange #-}++{- | Combinator for the @onclick@ attribute.++ Example:++ > div ! onclick "bar" $ "Hello."++ Result:++ > <div onclick="bar">Hello.</div>+-}+onclick ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onclick = attr "onclick"+{-# INLINE onclick #-}++{- | Combinator for the @oncontextmenu@ attribute.++ Example:++ > div ! oncontextmenu "bar" $ "Hello."++ Result:++ > <div oncontextmenu="bar">Hello.</div>+-}+oncontextmenu ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+oncontextmenu = attr "oncontextmenu"+{-# INLINE oncontextmenu #-}++{- | Combinator for the @ondblclick@ attribute.++ Example:++ > div ! ondblclick "bar" $ "Hello."++ Result:++ > <div ondblclick="bar">Hello.</div>+-}+ondblclick ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondblclick = attr "ondblclick"+{-# INLINE ondblclick #-}++{- | Combinator for the @ondrag@ attribute.++ Example:++ > div ! ondrag "bar" $ "Hello."++ Result:++ > <div ondrag="bar">Hello.</div>+-}+ondrag ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondrag = attr "ondrag"+{-# INLINE ondrag #-}++{- | Combinator for the @ondragend@ attribute.++ Example:++ > div ! ondragend "bar" $ "Hello."++ Result:++ > <div ondragend="bar">Hello.</div>+-}+ondragend ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondragend = attr "ondragend"+{-# INLINE ondragend #-}++{- | Combinator for the @ondragenter@ attribute.++ Example:++ > div ! ondragenter "bar" $ "Hello."++ Result:++ > <div ondragenter="bar">Hello.</div>+-}+ondragenter ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondragenter = attr "ondragenter"+{-# INLINE ondragenter #-}++{- | Combinator for the @ondragleave@ attribute.++ Example:++ > div ! ondragleave "bar" $ "Hello."++ Result:++ > <div ondragleave="bar">Hello.</div>+-}+ondragleave ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondragleave = attr "ondragleave"+{-# INLINE ondragleave #-}++{- | Combinator for the @ondragover@ attribute.++ Example:++ > div ! ondragover "bar" $ "Hello."++ Result:++ > <div ondragover="bar">Hello.</div>+-}+ondragover ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondragover = attr "ondragover"+{-# INLINE ondragover #-}++{- | Combinator for the @ondragstart@ attribute.++ Example:++ > div ! ondragstart "bar" $ "Hello."++ Result:++ > <div ondragstart="bar">Hello.</div>+-}+ondragstart ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondragstart = attr "ondragstart"+{-# INLINE ondragstart #-}++{- | Combinator for the @ondrop@ attribute.++ Example:++ > div ! ondrop "bar" $ "Hello."++ Result:++ > <div ondrop="bar">Hello.</div>+-}+ondrop ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondrop = attr "ondrop"+{-# INLINE ondrop #-}++{- | Combinator for the @ondurationchange@ attribute.++ Example:++ > div ! ondurationchange "bar" $ "Hello."++ Result:++ > <div ondurationchange="bar">Hello.</div>+-}+ondurationchange ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ondurationchange = attr "ondurationchange"+{-# INLINE ondurationchange #-}++{- | Combinator for the @onemptied@ attribute.++ Example:++ > div ! onemptied "bar" $ "Hello."++ Result:++ > <div onemptied="bar">Hello.</div>+-}+onemptied ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onemptied = attr "onemptied"+{-# INLINE onemptied #-}++{- | Combinator for the @onended@ attribute.++ Example:++ > div ! onended "bar" $ "Hello."++ Result:++ > <div onended="bar">Hello.</div>+-}+onended ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onended = attr "onended"+{-# INLINE onended #-}++{- | Combinator for the @onerror@ attribute.++ Example:++ > div ! onerror "bar" $ "Hello."++ Result:++ > <div onerror="bar">Hello.</div>+-}+onerror ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onerror = attr "onerror"+{-# INLINE onerror #-}++{- | Combinator for the @onfocus@ attribute.++ Example:++ > div ! onfocus "bar" $ "Hello."++ Result:++ > <div onfocus="bar">Hello.</div>+-}+onfocus ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onfocus = attr "onfocus"+{-# INLINE onfocus #-}++{- | Combinator for the @onformchange@ attribute.++ Example:++ > div ! onformchange "bar" $ "Hello."++ Result:++ > <div onformchange="bar">Hello.</div>+-}+onformchange ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onformchange = attr "onformchange"+{-# INLINE onformchange #-}++{- | Combinator for the @onforminput@ attribute.++ Example:++ > div ! onforminput "bar" $ "Hello."++ Result:++ > <div onforminput="bar">Hello.</div>+-}+onforminput ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onforminput = attr "onforminput"+{-# INLINE onforminput #-}++{- | Combinator for the @onhaschange@ attribute.++ Example:++ > div ! onhaschange "bar" $ "Hello."++ Result:++ > <div onhaschange="bar">Hello.</div>+-}+onhaschange ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onhaschange = attr "onhaschange"+{-# INLINE onhaschange #-}++{- | Combinator for the @oninput@ attribute.++ Example:++ > div ! oninput "bar" $ "Hello."++ Result:++ > <div oninput="bar">Hello.</div>+-}+oninput ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+oninput = attr "oninput"+{-# INLINE oninput #-}++{- | Combinator for the @oninvalid@ attribute.++ Example:++ > div ! oninvalid "bar" $ "Hello."++ Result:++ > <div oninvalid="bar">Hello.</div>+-}+oninvalid ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+oninvalid = attr "oninvalid"+{-# INLINE oninvalid #-}++{- | Combinator for the @onkeydown@ attribute.++ Example:++ > div ! onkeydown "bar" $ "Hello."++ Result:++ > <div onkeydown="bar">Hello.</div>+-}+onkeydown ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onkeydown = attr "onkeydown"+{-# INLINE onkeydown #-}++{- | Combinator for the @onkeyup@ attribute.++ Example:++ > div ! onkeyup "bar" $ "Hello."++ Result:++ > <div onkeyup="bar">Hello.</div>+-}+onkeyup ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onkeyup = attr "onkeyup"+{-# INLINE onkeyup #-}++{- | Combinator for the @onload@ attribute.++ Example:++ > div ! onload "bar" $ "Hello."++ Result:++ > <div onload="bar">Hello.</div>+-}+onload ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onload = attr "onload"+{-# INLINE onload #-}++{- | Combinator for the @onloadeddata@ attribute.++ Example:++ > div ! onloadeddata "bar" $ "Hello."++ Result:++ > <div onloadeddata="bar">Hello.</div>+-}+onloadeddata ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onloadeddata = attr "onloadeddata"+{-# INLINE onloadeddata #-}++{- | Combinator for the @onloadedmetadata@ attribute.++ Example:++ > div ! onloadedmetadata "bar" $ "Hello."++ Result:++ > <div onloadedmetadata="bar">Hello.</div>+-}+onloadedmetadata ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onloadedmetadata = attr "onloadedmetadata"+{-# INLINE onloadedmetadata #-}++{- | Combinator for the @onloadstart@ attribute.++ Example:++ > div ! onloadstart "bar" $ "Hello."++ Result:++ > <div onloadstart="bar">Hello.</div>+-}+onloadstart ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onloadstart = attr "onloadstart"+{-# INLINE onloadstart #-}++{- | Combinator for the @onmessage@ attribute.++ Example:++ > div ! onmessage "bar" $ "Hello."++ Result:++ > <div onmessage="bar">Hello.</div>+-}+onmessage ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onmessage = attr "onmessage"+{-# INLINE onmessage #-}++{- | Combinator for the @onmousedown@ attribute.++ Example:++ > div ! onmousedown "bar" $ "Hello."++ Result:++ > <div onmousedown="bar">Hello.</div>+-}+onmousedown ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onmousedown = attr "onmousedown"+{-# INLINE onmousedown #-}++{- | Combinator for the @onmousemove@ attribute.++ Example:++ > div ! onmousemove "bar" $ "Hello."++ Result:++ > <div onmousemove="bar">Hello.</div>+-}+onmousemove ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onmousemove = attr "onmousemove"+{-# INLINE onmousemove #-}++{- | Combinator for the @onmouseout@ attribute.++ Example:++ > div ! onmouseout "bar" $ "Hello."++ Result:++ > <div onmouseout="bar">Hello.</div>+-}+onmouseout ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onmouseout = attr "onmouseout"+{-# INLINE onmouseout #-}++{- | Combinator for the @onmouseover@ attribute.++ Example:++ > div ! onmouseover "bar" $ "Hello."++ Result:++ > <div onmouseover="bar">Hello.</div>+-}+onmouseover ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onmouseover = attr "onmouseover"+{-# INLINE onmouseover #-}++{- | Combinator for the @onmouseup@ attribute.++ Example:++ > div ! onmouseup "bar" $ "Hello."++ Result:++ > <div onmouseup="bar">Hello.</div>+-}+onmouseup ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onmouseup = attr "onmouseup"+{-# INLINE onmouseup #-}++{- | Combinator for the @onmousewheel@ attribute.++ Example:++ > div ! onmousewheel "bar" $ "Hello."++ Result:++ > <div onmousewheel="bar">Hello.</div>+-}+onmousewheel ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onmousewheel = attr "onmousewheel"+{-# INLINE onmousewheel #-}++{- | Combinator for the @ononline@ attribute.++ Example:++ > div ! ononline "bar" $ "Hello."++ Result:++ > <div ononline="bar">Hello.</div>+-}+ononline ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ononline = attr "ononline"+{-# INLINE ononline #-}++{- | Combinator for the @onpagehide@ attribute.++ Example:++ > div ! onpagehide "bar" $ "Hello."++ Result:++ > <div onpagehide="bar">Hello.</div>+-}+onpagehide ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onpagehide = attr "onpagehide"+{-# INLINE onpagehide #-}++{- | Combinator for the @onpageshow@ attribute.++ Example:++ > div ! onpageshow "bar" $ "Hello."++ Result:++ > <div onpageshow="bar">Hello.</div>+-}+onpageshow ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onpageshow = attr "onpageshow"+{-# INLINE onpageshow #-}++{- | Combinator for the @onpause@ attribute.++ Example:++ > div ! onpause "bar" $ "Hello."++ Result:++ > <div onpause="bar">Hello.</div>+-}+onpause ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onpause = attr "onpause"+{-# INLINE onpause #-}++{- | Combinator for the @onplay@ attribute.++ Example:++ > div ! onplay "bar" $ "Hello."++ Result:++ > <div onplay="bar">Hello.</div>+-}+onplay ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onplay = attr "onplay"+{-# INLINE onplay #-}++{- | Combinator for the @onplaying@ attribute.++ Example:++ > div ! onplaying "bar" $ "Hello."++ Result:++ > <div onplaying="bar">Hello.</div>+-}+onplaying ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onplaying = attr "onplaying"+{-# INLINE onplaying #-}++{- | Combinator for the @onprogress@ attribute.++ Example:++ > div ! onprogress "bar" $ "Hello."++ Result:++ > <div onprogress="bar">Hello.</div>+-}+onprogress ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onprogress = attr "onprogress"+{-# INLINE onprogress #-}++{- | Combinator for the @onpropstate@ attribute.++ Example:++ > div ! onpropstate "bar" $ "Hello."++ Result:++ > <div onpropstate="bar">Hello.</div>+-}+onpropstate ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onpropstate = attr "onpropstate"+{-# INLINE onpropstate #-}++{- | Combinator for the @onratechange@ attribute.++ Example:++ > div ! onratechange "bar" $ "Hello."++ Result:++ > <div onratechange="bar">Hello.</div>+-}+onratechange ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onratechange = attr "onratechange"+{-# INLINE onratechange #-}++{- | Combinator for the @onreadystatechange@ attribute.++ Example:++ > div ! onreadystatechange "bar" $ "Hello."++ Result:++ > <div onreadystatechange="bar">Hello.</div>+-}+onreadystatechange ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onreadystatechange = attr "onreadystatechange"+{-# INLINE onreadystatechange #-}++{- | Combinator for the @onredo@ attribute.++ Example:++ > div ! onredo "bar" $ "Hello."++ Result:++ > <div onredo="bar">Hello.</div>+-}+onredo ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onredo = attr "onredo"+{-# INLINE onredo #-}++{- | Combinator for the @onresize@ attribute.++ Example:++ > div ! onresize "bar" $ "Hello."++ Result:++ > <div onresize="bar">Hello.</div>+-}+onresize ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onresize = attr "onresize"+{-# INLINE onresize #-}++{- | Combinator for the @onscroll@ attribute.++ Example:++ > div ! onscroll "bar" $ "Hello."++ Result:++ > <div onscroll="bar">Hello.</div>+-}+onscroll ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onscroll = attr "onscroll"+{-# INLINE onscroll #-}++{- | Combinator for the @onseeked@ attribute.++ Example:++ > div ! onseeked "bar" $ "Hello."++ Result:++ > <div onseeked="bar">Hello.</div>+-}+onseeked ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onseeked = attr "onseeked"+{-# INLINE onseeked #-}++{- | Combinator for the @onseeking@ attribute.++ Example:++ > div ! onseeking "bar" $ "Hello."++ Result:++ > <div onseeking="bar">Hello.</div>+-}+onseeking ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onseeking = attr "onseeking"+{-# INLINE onseeking #-}++{- | Combinator for the @onselect@ attribute.++ Example:++ > div ! onselect "bar" $ "Hello."++ Result:++ > <div onselect="bar">Hello.</div>+-}+onselect ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onselect = attr "onselect"+{-# INLINE onselect #-}++{- | Combinator for the @onstalled@ attribute.++ Example:++ > div ! onstalled "bar" $ "Hello."++ Result:++ > <div onstalled="bar">Hello.</div>+-}+onstalled ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onstalled = attr "onstalled"+{-# INLINE onstalled #-}++{- | Combinator for the @onstorage@ attribute.++ Example:++ > div ! onstorage "bar" $ "Hello."++ Result:++ > <div onstorage="bar">Hello.</div>+-}+onstorage ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onstorage = attr "onstorage"+{-# INLINE onstorage #-}++{- | Combinator for the @onsubmit@ attribute.++ Example:++ > div ! onsubmit "bar" $ "Hello."++ Result:++ > <div onsubmit="bar">Hello.</div>+-}+onsubmit ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onsubmit = attr "onsubmit"+{-# INLINE onsubmit #-}++{- | Combinator for the @onsuspend@ attribute.++ Example:++ > div ! onsuspend "bar" $ "Hello."++ Result:++ > <div onsuspend="bar">Hello.</div>+-}+onsuspend ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onsuspend = attr "onsuspend"+{-# INLINE onsuspend #-}++{- | Combinator for the @ontimeupdate@ attribute.++ Example:++ > div ! ontimeupdate "bar" $ "Hello."++ Result:++ > <div ontimeupdate="bar">Hello.</div>+-}+ontimeupdate ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ontimeupdate = attr "ontimeupdate"+{-# INLINE ontimeupdate #-}++{- | Combinator for the @onundo@ attribute.++ Example:++ > div ! onundo "bar" $ "Hello."++ Result:++ > <div onundo="bar">Hello.</div>+-}+onundo ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onundo = attr "onundo"+{-# INLINE onundo #-}++{- | Combinator for the @onunload@ attribute.++ Example:++ > div ! onunload "bar" $ "Hello."++ Result:++ > <div onunload="bar">Hello.</div>+-}+onunload ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onunload = attr "onunload"+{-# INLINE onunload #-}++{- | Combinator for the @onvolumechange@ attribute.++ Example:++ > div ! onvolumechange "bar" $ "Hello."++ Result:++ > <div onvolumechange="bar">Hello.</div>+-}+onvolumechange ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onvolumechange = attr "onvolumechange"+{-# INLINE onvolumechange #-}++{- | Combinator for the @onwaiting@ attribute.++ Example:++ > div ! onwaiting "bar" $ "Hello."++ Result:++ > <div onwaiting="bar">Hello.</div>+-}+onwaiting ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+onwaiting = attr "onwaiting"+{-# INLINE onwaiting #-}++{- | Combinator for the @open@ attribute.++ Example:++ > div ! open "bar" $ "Hello."++ Result:++ > <div open="bar">Hello.</div>+-}+open ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+open = attr "open"+{-# INLINE open #-}++{- | Combinator for the @optimum@ attribute.++ Example:++ > div ! optimum "bar" $ "Hello."++ Result:++ > <div optimum="bar">Hello.</div>+-}+optimum ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+optimum = attr "optimum"+{-# INLINE optimum #-}++{- | Combinator for the @pattern@ attribute.++ Example:++ > div ! pattern "bar" $ "Hello."++ Result:++ > <div pattern="bar">Hello.</div>+-}+pattern ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+pattern = attr "pattern"+{-# INLINE pattern #-}++{- | Combinator for the @ping@ attribute.++ Example:++ > div ! ping "bar" $ "Hello."++ Result:++ > <div ping="bar">Hello.</div>+-}+ping ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+ping = attr "ping"+{-# INLINE ping #-}++{- | Combinator for the @placeholder@ attribute.++ Example:++ > div ! placeholder "bar" $ "Hello."++ Result:++ > <div placeholder="bar">Hello.</div>+-}+placeholder ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+placeholder = attr "placeholder"+{-# INLINE placeholder #-}++{- | Combinator for the @preload@ attribute.++ Example:++ > div ! preload "bar" $ "Hello."++ Result:++ > <div preload="bar">Hello.</div>+-}+preload ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+preload = attr "preload"+{-# INLINE preload #-}++{- | Combinator for the @pubdate@ attribute.++ Example:++ > div ! pubdate "bar" $ "Hello."++ Result:++ > <div pubdate="bar">Hello.</div>+-}+pubdate ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+pubdate = attr "pubdate"+{-# INLINE pubdate #-}++{- | Combinator for the @radiogroup@ attribute.++ Example:++ > div ! radiogroup "bar" $ "Hello."++ Result:++ > <div radiogroup="bar">Hello.</div>+-}+radiogroup ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+radiogroup = attr "radiogroup"+{-# INLINE radiogroup #-}++{- | Combinator for the @readonly@ attribute.++ Example:++ > div ! readonly "bar" $ "Hello."++ Result:++ > <div readonly="bar">Hello.</div>+-}+readonly ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+readonly = attr "readonly"+{-# INLINE readonly #-}++{- | Combinator for the @rel@ attribute.++ Example:++ > div ! rel "bar" $ "Hello."++ Result:++ > <div rel="bar">Hello.</div>+-}+rel ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+rel = attr "rel"+{-# INLINE rel #-}++{- | Combinator for the @required@ attribute.++ Example:++ > div ! required "bar" $ "Hello."++ Result:++ > <div required="bar">Hello.</div>+-}+required ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+required = attr "required"+{-# INLINE required #-}++{- | Combinator for the @reversed@ attribute.++ Example:++ > div ! reversed "bar" $ "Hello."++ Result:++ > <div reversed="bar">Hello.</div>+-}+reversed ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+reversed = attr "reversed"+{-# INLINE reversed #-}++{- | Combinator for the @role@ attribute.++ Example:++ > div ! role "bar" $ "Hello."++ Result:++ > <div role="bar">Hello.</div>+-}+role ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+role = attr "role"+{-# INLINE role #-}++{- | Combinator for the @rows@ attribute.++ Example:++ > div ! rows "bar" $ "Hello."++ Result:++ > <div rows="bar">Hello.</div>+-}+rows ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+rows = attr "rows"+{-# INLINE rows #-}++{- | Combinator for the @rowspan@ attribute.++ Example:++ > div ! rowspan "bar" $ "Hello."++ Result:++ > <div rowspan="bar">Hello.</div>+-}+rowspan ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+rowspan = attr "rowspan"+{-# INLINE rowspan #-}++{- | Combinator for the @sandbox@ attribute.++ Example:++ > div ! sandbox "bar" $ "Hello."++ Result:++ > <div sandbox="bar">Hello.</div>+-}+sandbox ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+sandbox = attr "sandbox"+{-# INLINE sandbox #-}++{- | Combinator for the @scope@ attribute.++ Example:++ > div ! scope "bar" $ "Hello."++ Result:++ > <div scope="bar">Hello.</div>+-}+scope ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+scope = attr "scope"+{-# INLINE scope #-}++{- | Combinator for the @scoped@ attribute.++ Example:++ > div ! scoped "bar" $ "Hello."++ Result:++ > <div scoped="bar">Hello.</div>+-}+scoped ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+scoped = attr "scoped"+{-# INLINE scoped #-}++{- | Combinator for the @seamless@ attribute.++ Example:++ > div ! seamless "bar" $ "Hello."++ Result:++ > <div seamless="bar">Hello.</div>+-}+seamless ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+seamless = attr "seamless"+{-# INLINE seamless #-}++{- | Combinator for the @selected@ attribute.++ Example:++ > div ! selected "bar" $ "Hello."++ Result:++ > <div selected="bar">Hello.</div>+-}+selected ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+selected = attr "selected"+{-# INLINE selected #-}++{- | Combinator for the @shape@ attribute.++ Example:++ > div ! shape "bar" $ "Hello."++ Result:++ > <div shape="bar">Hello.</div>+-}+shape ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+shape = attr "shape"+{-# INLINE shape #-}++{- | Combinator for the @size@ attribute.++ Example:++ > div ! size "bar" $ "Hello."++ Result:++ > <div size="bar">Hello.</div>+-}+size ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+size = attr "size"+{-# INLINE size #-}++{- | Combinator for the @sizes@ attribute.++ Example:++ > div ! sizes "bar" $ "Hello."++ Result:++ > <div sizes="bar">Hello.</div>+-}+sizes ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+sizes = attr "sizes"+{-# INLINE sizes #-}++{- | Combinator for the @span@ attribute.++ Example:++ > div ! span "bar" $ "Hello."++ Result:++ > <div span="bar">Hello.</div>+-}+span ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+span = attr "span"+{-# INLINE span #-}++{- | Combinator for the @spellcheck@ attribute.++ Example:++ > div ! spellcheck "bar" $ "Hello."++ Result:++ > <div spellcheck="bar">Hello.</div>+-}+spellcheck ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+spellcheck = attr "spellcheck"+{-# INLINE spellcheck #-}++{- | Combinator for the @src@ attribute.++ Example:++ > div ! src "bar" $ "Hello."++ Result:++ > <div src="bar">Hello.</div>+-}+src ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+src = attr "src"+{-# INLINE src #-}++{- | Combinator for the @srcdoc@ attribute.++ Example:++ > div ! srcdoc "bar" $ "Hello."++ Result:++ > <div srcdoc="bar">Hello.</div>+-}+srcdoc ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+srcdoc = attr "srcdoc"+{-# INLINE srcdoc #-}++{- | Combinator for the @start@ attribute.++ Example:++ > div ! start "bar" $ "Hello."++ Result:++ > <div start="bar">Hello.</div>+-}+start ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+start = attr "start"+{-# INLINE start #-}++{- | Combinator for the @step@ attribute.++ Example:++ > div ! step "bar" $ "Hello."++ Result:++ > <div step="bar">Hello.</div>+-}+step ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+step = attr "step"+{-# INLINE step #-}++{- | Combinator for the @style@ attribute.++ Example:++ > div ! style "bar" $ "Hello."++ Result:++ > <div style="bar">Hello.</div>+-}+style ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+style = attr "style"+{-# INLINE style #-}++{- | Combinator for the @subject@ attribute.++ Example:++ > div ! subject "bar" $ "Hello."++ Result:++ > <div subject="bar">Hello.</div>+-}+subject ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+subject = attr "subject"+{-# INLINE subject #-}++{- | Combinator for the @summary@ attribute.++ Example:++ > div ! summary "bar" $ "Hello."++ Result:++ > <div summary="bar">Hello.</div>+-}+summary ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+summary = attr "summary"+{-# INLINE summary #-}++{- | Combinator for the @tabindex@ attribute.++ Example:++ > div ! tabindex "bar" $ "Hello."++ Result:++ > <div tabindex="bar">Hello.</div>+-}+tabindex ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+tabindex = attr "tabindex"+{-# INLINE tabindex #-}++{- | Combinator for the @target@ attribute.++ Example:++ > div ! target "bar" $ "Hello."++ Result:++ > <div target="bar">Hello.</div>+-}+target ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+target = attr "target"+{-# INLINE target #-}++{- | Combinator for the @title@ attribute.++ Example:++ > div ! title "bar" $ "Hello."++ Result:++ > <div title="bar">Hello.</div>+-}+title ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+title = attr "title"+{-# INLINE title #-}++{- | Combinator for the @type@ attribute.++ Example:++ > div ! type_ "bar" $ "Hello."++ Result:++ > <div type="bar">Hello.</div>+-}+type_ ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+type_ = attr "type"+{-# INLINE type_ #-}++{- | Combinator for the @usemap@ attribute.++ Example:++ > div ! usemap "bar" $ "Hello."++ Result:++ > <div usemap="bar">Hello.</div>+-}+usemap ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+usemap = attr "usemap"+{-# INLINE usemap #-}++{- | Combinator for the @value@ attribute.++ Example:++ > div ! value "bar" $ "Hello."++ Result:++ > <div value="bar">Hello.</div>+-}+value ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+value = attr "value"+{-# INLINE value #-}++{- | Combinator for the @width@ attribute.++ Example:++ > div ! width "bar" $ "Hello."++ Result:++ > <div width="bar">Hello.</div>+-}+width ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+width = attr "width"+{-# INLINE width #-}++{- | Combinator for the @wrap@ attribute.++ Example:++ > div ! wrap "bar" $ "Hello."++ Result:++ > <div wrap="bar">Hello.</div>+-}+wrap ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+wrap = attr "wrap"+{-# INLINE wrap #-}++{- | Combinator for the @xmlns@ attribute.++ Example:++ > div ! xmlns "bar" $ "Hello."++ Result:++ > <div xmlns="bar">Hello.</div>+-}+xmlns ::+ ToLogStr s =>+ -- | Attribute value.+ s ->+ -- | Resulting attribute.+ Attr+xmlns = attr "xmlns"+{-# INLINE xmlns #-}
+ src/Data/Fmt/Code.hs view
@@ -0,0 +1,324 @@+module Data.Fmt.Code (+ v,++ -- * Character encodings+ c,+ c7,+ c8,+ s,+ s7,+ s8,++ -- * Ascii float encodings+ e,+ f,+ g,++ -- * Decimal encodings+ d,+ hhd,+ hd,+ ld,+ lld,+ u,+ hhu,+ hu,+ lu,+ llu,++ -- * Hexadecimal encodings+ x,+ hhx,+ hx,+ hx',+ lx,+ lx',+ llx,+ llx',++ -- * Binary encodings+ b,+ b',+ hhb,+ hb,+ hb',+ lb,+ lb',+ llb,+ llb',+) where++import Data.ByteString (ByteString)+import qualified Data.ByteString.Builder as BL+import qualified Data.ByteString.Lazy.Char8 as BL+import Data.Fmt+import Data.Int+import Data.Word+import qualified Numeric as N++{- $setup+ >>> import Text.Printf+ >>> :load Data.Fmt+-}++{- | Encode a loggable value.++ Semantics are similar to 'ByteString.Printf.printf':++ >>> Text.Printf.printf "%v" 42 :: String+ "42"+ >>> runLogFmt v 42+ "42"+-}+{-# INLINE v #-}+v :: ToLogStr a => Fmt1 LogStr s a+v = fmt1 toLogStr++-- Character encodings++-------------------------++-- | Format a character.+{-# INLINE c #-}+c :: IsString m => Fmt1 m s Char+c = fmt1 (fromString . pure)++-- | ASCII encode a 'Char'.+{-# INLINE c7 #-}+c7 :: Fmt1 LogStr s Char+c7 = fmt1 $ toLogStr . BL.char7++-- | Latin-1 (ISO/IEC 8859-1) encode a 'Char'.+{-# INLINE c8 #-}+c8 :: Fmt1 LogStr s Char+c8 = fmt1 $ toLogStr . BL.char8++-- | Format a showable value.+{-# INLINE s #-}+s :: (IsString m, Show a) => Fmt1 m s a+s = fmt1 (fromString . show)++-- | ASCII encode a 'String'.+{-# INLINE s7 #-}+s7 :: Fmt1 LogStr s String+s7 = fmt1 $ toLogStr . BL.string7++-- | Latin-1 (ISO/IEC 8859-1) encode a 'String'.+{-# INLINE s8 #-}+s8 :: Fmt1 LogStr s String+s8 = fmt1 $ toLogStr . BL.string8++-- Floating point++-------------------------++{- | Format a floating point number to a given number of digits of precision.++ Semantics are similar to 'ByteString.Printf.printf':++ >>> Text.Printf.printf "%.5e" pi :: String+ "3.14159e0"+ >>> runLogFmt (e 5) pi+ "3.14159e0"+-}+e :: (IsString m, RealFloat a) => Int -> Fmt1 m s a+e prec = fmt1 $ fromString . flip (N.showEFloat $ Just prec) []++{- | Format a floating point number to a given number of digits of precision.++ Semantics are similar to 'ByteString.Printf.printf':++ >>> Text.Printf.printf "%.5f" maximal32 :: String+ "340282330000000000000000000000000000000.00000"+ >>> runLogFmt (f 5) maximal32+ "340282330000000000000000000000000000000.00000"+-}+f :: (IsString m, RealFloat a) => Int -> Fmt1 m s a+f prec = fmt1 $ fromString . flip (N.showFFloat $ Just prec) []++{- | Format a floating point number to a given number of digits of precision.++ Semantics are similar to 'ByteString.Printf.printf':++ >>> Text.Printf.printf "%.5g" maximal32 :: String+ "3.40282e38"+ >>> runLogFmt (g 5) maximal32+ "3.40282e38"+-}+g :: (IsString m, RealFloat a) => Int -> Fmt1 m s a+g prec = fmt1 $ fromString . flip (N.showGFloat $ Just prec) []++-- Decimal encodings++-------------------------++-- | Decimal encoding of an 'Int' using the ASCII digits.+{-# INLINE d #-}+d :: Fmt1 LogStr s Int+d = fmt1 $ toLogStr . BL.intDec++{- | Decimal encoding of an 'Int8' using the ASCII digits.++ e.g.++ > toLazyByteString (int8Dec 42) = "42"+ > toLazyByteString (int8Dec (-1)) = "-1"+-}+{-# INLINE hhd #-}+hhd :: Fmt1 LogStr s Int8+hhd = fmt1 $ toLogStr . BL.int8Dec++-- | Decimal encoding of an 'Int16' using the ASCII digits.+{-# INLINE hd #-}+hd :: Fmt1 LogStr s Int16+hd = fmt1 $ toLogStr . BL.int16Dec++-- | Decimal encoding of an 'Int32' using the ASCII digits.+{-# INLINE ld #-}+ld :: Fmt1 LogStr s Int32+ld = fmt1 $ toLogStr . BL.int32Dec++-- | Decimal encoding of an 'Int64' using the ASCII digits.+{-# INLINE lld #-}+lld :: Fmt1 LogStr s Int64+lld = fmt1 $ toLogStr . BL.int64Dec++-- | Decimal encoding of a 'Word' using the ASCII digits.+{-# INLINE u #-}+u :: Fmt1 LogStr s Word+u = fmt1 $ toLogStr . BL.wordDec++-- | Decimal encoding of a 'Word8' using the ASCII digits.+{-# INLINE hhu #-}+hhu :: Fmt1 LogStr s Word8+hhu = fmt1 $ toLogStr . BL.word8Dec++-- | Decimal encoding of a 'Word16' using the ASCII digits.+{-# INLINE hu #-}+hu :: Fmt1 LogStr s Word16+hu = fmt1 $ toLogStr . BL.word16Dec++-- | Decimal encoding of a 'Word32' using the ASCII digits.+{-# INLINE lu #-}+lu :: Fmt1 LogStr s Word32+lu = fmt1 $ toLogStr . BL.word32Dec++-- | Decimal encoding of a 'Word64' using the ASCII digits.+{-# INLINE llu #-}+llu :: Fmt1 LogStr s Word64+llu = fmt1 $ toLogStr . BL.word64Dec++-- Hexadecimal encodings+--------------------++-- | Shortest hexadecimal encoding of a 'Word' using lower-case characters.+{-# INLINE x #-}+x :: Fmt1 LogStr s Word+x = fmt1 $ toLogStr . BL.wordHex++-- | Shortest hexadecimal encoding of a 'Word8' using lower-case characters.+{-# INLINE hhx #-}+hhx :: Fmt1 LogStr s Word8+hhx = fmt1 $ toLogStr . BL.word8Hex++-- | Encode a 'Word8' using 2 nibbles (hexadecimal digits).+{-# INLINE hhx' #-}+hhx' :: Fmt1 LogStr s Word8+hhx' = fmt1 $ toLogStr . BL.word8HexFixed++-- | Shortest hexadecimal encoding of a 'Word16' using lower-case characters.+{-# INLINE hx #-}+hx :: Fmt1 LogStr s Word16+hx = fmt1 $ toLogStr . BL.word16Hex++-- | Encode a 'Word16' using 4 nibbles.+{-# INLINE hx' #-}+hx' :: Fmt1 LogStr s Word16+hx' = fmt1 $ toLogStr . BL.word16HexFixed++-- | Shortest hexadecimal encoding of a 'Word32' using lower-case characters.+{-# INLINE lx #-}+lx :: Fmt1 LogStr s Word32+lx = fmt1 $ toLogStr . BL.word32Hex++-- | Encode a 'Word32' using 8 nibbles.+{-# INLINE lx' #-}+lx' :: Fmt1 LogStr s Word32+lx' = fmt1 $ toLogStr . BL.word32HexFixed++{- | Shortest hexadecimal encoding of a 'Word64' using lower-case characters.++ Semantics are similar to 'Text.Printf.printf':++ >>> Text.printf "%s: %llx" "Val" (-7) :: String+ "Val: fffffffffffffff9"+ >>> printf (s % ": " % llx) "Val" (-7)+ "Val: fffffffffffffff9"+-}+{-# INLINE llx #-}+llx :: Fmt1 LogStr s Word64+llx = fmt1 $ toLogStr . BL.word64Hex++-- | Encode a 'Word64' using 16 nibbles.+{-# INLINE llx' #-}+llx' :: Fmt1 LogStr s Word64+llx' = fmt1 $ toLogStr . BL.word64HexFixed++-- Binary encodings+--------------------++-- | Format a lazy byte string.+b :: Fmt1 LogStr s BL.ByteString+b = fmt1 toLogStr+{-# INLINE b #-}++{- | Format a strict byte string.++ @ 'fmap' (. 'Data.ByteString.pack') 't'' :: 'Fmt1' 'Data.ByteString.Builder.Builder' s 'String' @+-}+b' :: Fmt1 LogStr s ByteString+b' = fmt1 toLogStr+{-# INLINE b' #-}++-- | Encode a 'Word8' as-is+{-# INLINE hhb #-}+hhb :: Fmt1 LogStr s Word8+hhb = fmt1 $ toLogStr . BL.word8++-- | Encode a 'Word16' using little-endian format.+{-# INLINE hb #-}+hb :: Fmt1 LogStr s Word16+hb = fmt1 $ toLogStr . BL.word16LE++-- | Encode a 'Word16' using big-endian format.+{-# INLINE hb' #-}+hb' :: Fmt1 LogStr s Word16+hb' = fmt1 $ toLogStr . BL.word16BE++-- | Encode a 'Word32' using little-endian format.+{-# INLINE lb #-}+lb :: Fmt1 LogStr s Word32+lb = fmt1 $ toLogStr . BL.word32LE++-- | Encode a 'Word32' using big-endian format.+{-# INLINE lb' #-}+lb' :: Fmt1 LogStr s Word32+lb' = fmt1 $ toLogStr . BL.word32BE++{- | Encode a 'Word64' using little-endian format.++ Semantics are similar to 'Tebt.Printf.printf':++ >>> Text.printf "%s: %llb" "Val" (-7) :: String+ "Val: fffffffffffffff9"+ >>> printf (s % ": " % llb) "Val" (-7)+ "Val: fffffffffffffff9"+-}+{-# INLINE llb #-}+llb :: Fmt1 LogStr s Word64+llb = fmt1 $ toLogStr . BL.word64LE++-- | Encode a 'Word64' using big-endian format.+{-# INLINE llb' #-}+llb' :: Fmt1 LogStr s Word64+llb' = fmt1 $ toLogStr . BL.word64BE
+ src/Data/Fmt/Html.hs view
@@ -0,0 +1,2120 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}++{- | Html5 formatting.++ The API is similar to < https://hackage.haskell.org/package/blaze-html >.+-}+module Data.Fmt.Html (+ -- * Html+ Html,+ Attr,+ toHtml,+ comment,+ Element (..),+ (!?),+ + numbers,+ -- * Elements+ docType,+ docTypeHtml,+ a,+ abbr,+ address,+ area,+ article,+ aside,+ audio,+ b,+ base,+ bdo,+ blockquote,+ body,+ br,+ button,+ canvas,+ caption,+ cite,+ code,+ col,+ colgroup,+ command,+ datalist,+ dd,+ del,+ details,+ dfn,+ div,+ dl,+ dt,+ em,+ embed,+ fieldset,+ figcaption,+ figure,+ footer,+ form,+ h1,+ h2,+ h3,+ h4,+ h5,+ h6,+ head,+ header,+ hgroup,+ hr,+ html,+ i,+ iframe,+ img,+ input,+ ins,+ kbd,+ keygen,+ label,+ legend,+ li,+ link,+ main,+ map,+ mark,+ menu,+ menuitem,+ meta,+ meter,+ nav,+ noscript,+ object,+ ol,+ optgroup,+ option,+ output,+ p,+ param,+ pre,+ progress,+ q,+ rp,+ rt,+ ruby,+ samp,+ script,+ section,+ select,+ small,+ source,+ span,+ strong,+ style,+ sub,+ summary,+ sup,+ table,+ tbody,+ td,+ textarea,+ tfoot,+ th,+ thead,+ time,+ title,+ tr,+ track,+ u,+ ul,+ var,+ video,+ wbr,+ contact+) where++import Data.Fmt+import Prelude hiding (div, head, map, span)++import Data.Fmt.Attr (href)+++contact :: Html LogStr+contact = p "You can reach me at" % ul . spr . li $ do+ c1 <- a ! href @String "https://example.com" $ "Website"+ c2 <- a ! href @String "mailto:cmk@example.com" $ "Email"+ pure $ c1 <> c2++-- "<p>You can reach me at</p><ul><li><a href=\"https://example.com\">Website</a></li><li><a href=\"mailto:cmk@example.com\">Email</a></li></ul>"++-- | Run a monadic expression.+--+-- This executes the formatting commands contained in the expression and +-- returns the result as a variable.+run :: Fmt m m n -> Fmt n a a+run = fmt . runFmt++-- > runLogFmt $ numbers 2+-- "<html><p>A list of numbers:</p><html><ul><li>1</li><li>2</li></ul></html><p>The end.</p></html>"+numbers :: Int -> Html LogStr+numbers n = html $ do+ l <- ul . cat $ li . toHtml <$> [1 .. n]+ cat+ [ p "A list of numbers:"+ , fmt l+ , p "The end."+ ]++-- | Create a < https://en.wikipedia.org/wiki/HTML_element#Syntax tag > for an element.+element :: String -> Html a -> Html a+element = enclose <$> (enclose "<" ">" . toHtml) <*> (enclose "</" ">" . toHtml)++element_ :: String -> Html a+element_ = enclose "<" " />" . toHtml++-- Elements++-------------------------++{- | Combinator for the document type. This should be placed at the top+ of every HTML page.++ Example:++ > docType++ Result:++ > <!DOCTYPE HTML>+-}+docType ::+ -- | The document type HTML.+ Html a+docType = "<!DOCTYPE HTML>\n"+{-# INLINE docType #-}++{- | Combinator for the @\<html>@ element. This combinator will also+ insert the correct doctype.++ Example:++ > docTypeHtml $ span $ fmt "foo"++ Result:++ > <!DOCTYPE HTML>+ > <html><span>foo</span></html>+-}+docTypeHtml ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+docTypeHtml inner = docType % html inner+{-# INLINE docTypeHtml #-}++{- | Combinator for the @\<a>@ element.++ Example:++ > a $ span $ fmt "foo"++ Result:++ > <a><span>foo</span></a>+-}+a ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+a = element "a"+{-# INLINE a #-}++{- | Combinator for the @\<abbr>@ element.++ Example:++ > abbr $ span $ fmt "foo"++ Result:++ > <abbr><span>foo</span></abbr>+-}+abbr ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+abbr = element "abbr"+{-# INLINE abbr #-}++{- | Combinator for the @\<address>@ element.++ Example:++ > address $ span $ fmt "foo"++ Result:++ > <address><span>foo</span></address>+-}+address ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+address = element "address"+{-# INLINE address #-}++{- | Combinator for the @\<area />@ element.++ Example:++ > area++ Result:++ > <area />+-}+area ::+ -- | Resulting HTML.+ Html a+area = element_ "area"+{-# INLINE area #-}++{- | Combinator for the @\<article>@ element.++ Example:++ > article $ span $ fmt "foo"++ Result:++ > <article><span>foo</span></article>+-}+article ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+article = element "article"+{-# INLINE article #-}++{- | Combinator for the @\<aside>@ element.++ Example:++ > aside $ span $ fmt "foo"++ Result:++ > <aside><span>foo</span></aside>+-}+aside ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+aside = element "aside"+{-# INLINE aside #-}++{- | Combinator for the @\<audio>@ element.++ Example:++ > audio $ span $ fmt "foo"++ Result:++ > <audio><span>foo</span></audio>+-}+audio ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+audio = element "audio"+{-# INLINE audio #-}++{- | Combinator for the @\<b>@ element.++ Example:++ > b $ span $ fmt "foo"++ Result:++ > <b><span>foo</span></b>+-}+b ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+b = element "b"+{-# INLINE b #-}++{- | Combinator for the @\<base />@ element.++ Example:++ > base++ Result:++ > <base />+-}+base ::+ -- | Resulting HTML.+ Html a+base = element_ "base"+{-# INLINE base #-}++{- | Combinator for the @\<bdo>@ element.++ Example:++ > bdo $ span $ fmt "foo"++ Result:++ > <bdo><span>foo</span></bdo>+-}+bdo ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+bdo = element "bdo"+{-# INLINE bdo #-}++{- | Combinator for the @\<blockquote>@ element.++ Example:++ > blockquote $ span $ fmt "foo"++ Result:++ > <blockquote><span>foo</span></blockquote>+-}+blockquote ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+blockquote = element "blockquote"+{-# INLINE blockquote #-}++{- | Combinator for the @\<body>@ element.++ Example:++ > body $ span $ fmt "foo"++ Result:++ > <body><span>foo</span></body>+-}+body ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+body = element "body"+{-# INLINE body #-}++{- | Combinator for the @\<br />@ element.++ Example:++ > br++ Result:++ > <br />+-}+br ::+ -- | Resulting HTML.+ Html a+br = element_ "br"+{-# INLINE br #-}++{- | Combinator for the @\<button>@ element.++ Example:++ > button $ span $ fmt "foo"++ Result:++ > <button><span>foo</span></button>+-}+button ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+button = element "button"+{-# INLINE button #-}++{- | Combinator for the @\<canvas>@ element.++ Example:++ > canvas $ span $ fmt "foo"++ Result:++ > <canvas><span>foo</span></canvas>+-}+canvas ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+canvas = element "canvas"+{-# INLINE canvas #-}++{- | Combinator for the @\<caption>@ element.++ Example:++ > caption $ span $ fmt "foo"++ Result:++ > <caption><span>foo</span></caption>+-}+caption ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+caption = element "caption"+{-# INLINE caption #-}++{- | Combinator for the @\<cite>@ element.++ Example:++ > cite $ span $ fmt "foo"++ Result:++ > <cite><span>foo</span></cite>+-}+cite ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+cite = element "cite"+{-# INLINE cite #-}++{- | Combinator for the @\<code>@ element.++ Example:++ > code $ span $ fmt "foo"++ Result:++ > <code><span>foo</span></code>+-}+code ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+code = element "code"+{-# INLINE code #-}++{- | Combinator for the @\<col />@ element.++ Example:++ > col++ Result:++ > <col />+-}+col ::+ -- | Resulting HTML.+ Html a+col = element_ "col"+{-# INLINE col #-}++{- | Combinator for the @\<colgroup>@ element.++ Example:++ > colgroup $ span $ fmt "foo"++ Result:++ > <colgroup><span>foo</span></colgroup>+-}+colgroup ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+colgroup = element "colgroup"+{-# INLINE colgroup #-}++{- | Combinator for the @\<command>@ element.++ Example:++ > command $ span $ fmt "foo"++ Result:++ > <command><span>foo</span></command>+-}+command ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+command = element "command"+{-# INLINE command #-}++{- | Combinator for the @\<datalist>@ element.++ Example:++ > datalist $ span $ fmt "foo"++ Result:++ > <datalist><span>foo</span></datalist>+-}+datalist ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+datalist = element "datalist"+{-# INLINE datalist #-}++{- | Combinator for the @\<dd>@ element.++ Example:++ > dd $ span $ fmt "foo"++ Result:++ > <dd><span>foo</span></dd>+-}+dd ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+dd = element "dd"+{-# INLINE dd #-}++{- | Combinator for the @\<del>@ element.++ Example:++ > del $ span $ fmt "foo"++ Result:++ > <del><span>foo</span></del>+-}+del ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+del = element "del"+{-# INLINE del #-}++{- | Combinator for the @\<details>@ element.++ Example:++ > details $ span $ fmt "foo"++ Result:++ > <details><span>foo</span></details>+-}+details ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+details = element "details"+{-# INLINE details #-}++{- | Combinator for the @\<dfn>@ element.++ Example:++ > dfn $ span $ fmt "foo"++ Result:++ > <dfn><span>foo</span></dfn>+-}+dfn ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+dfn = element "dfn"+{-# INLINE dfn #-}++{- | Combinator for the @\<div>@ element.++ Example:++ > div $ span $ fmt "foo"++ Result:++ > <div><span>foo</span></div>+-}+div ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+div = element "div"+{-# INLINE div #-}++{- | Combinator for the @\<dl>@ element.++ Example:++ > dl $ span $ fmt "foo"++ Result:++ > <dl><span>foo</span></dl>+-}+dl ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+dl = element "dl"+{-# INLINE dl #-}++{- | Combinator for the @\<dt>@ element.++ Example:++ > dt $ span $ fmt "foo"++ Result:++ > <dt><span>foo</span></dt>+-}+dt ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+dt = element "dt"+{-# INLINE dt #-}++{- | Combinator for the @\<em>@ element.++ Example:++ > em $ span $ fmt "foo"++ Result:++ > <em><span>foo</span></em>+-}+em ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+em = element "em"+{-# INLINE em #-}++{- | Combinator for the @\<embed />@ element.++ Example:++ > embed++ Result:++ > <embed />+-}+embed ::+ -- | Resulting HTML.+ Html a+embed = element_ "embed"+{-# INLINE embed #-}++{- | Combinator for the @\<fieldset>@ element.++ Example:++ > fieldset $ span $ fmt "foo"++ Result:++ > <fieldset><span>foo</span></fieldset>+-}+fieldset ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+fieldset = element "fieldset"+{-# INLINE fieldset #-}++{- | Combinator for the @\<figcaption>@ element.++ Example:++ > figcaption $ span $ fmt "foo"++ Result:++ > <figcaption><span>foo</span></figcaption>+-}+figcaption ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+figcaption = element "figcaption"+{-# INLINE figcaption #-}++{- | Combinator for the @\<figure>@ element.++ Example:++ > figure $ span $ fmt "foo"++ Result:++ > <figure><span>foo</span></figure>+-}+figure ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+figure = element "figure"+{-# INLINE figure #-}++{- | Combinator for the @\<footer>@ element.++ Example:++ > footer $ span $ fmt "foo"++ Result:++ > <footer><span>foo</span></footer>+-}+footer ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+footer = element "footer"+{-# INLINE footer #-}++{- | Combinator for the @\<form>@ element.++ Example:++ > form $ span $ fmt "foo"++ Result:++ > <form><span>foo</span></form>+-}+form ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+form = element "form"+{-# INLINE form #-}++{- | Combinator for the @\<h1>@ element.++ Example:++ > h1 $ span $ fmt "foo"++ Result:++ > <h1><span>foo</span></h1>+-}+h1 ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+h1 = element "h1"+{-# INLINE h1 #-}++{- | Combinator for the @\<h2>@ element.++ Example:++ > h2 $ span $ fmt "foo"++ Result:++ > <h2><span>foo</span></h2>+-}+h2 ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+h2 = element "h2"+{-# INLINE h2 #-}++{- | Combinator for the @\<h3>@ element.++ Example:++ > h3 $ span $ fmt "foo"++ Result:++ > <h3><span>foo</span></h3>+-}+h3 ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+h3 = element "h3"+{-# INLINE h3 #-}++{- | Combinator for the @\<h4>@ element.++ Example:++ > h4 $ span $ fmt "foo"++ Result:++ > <h4><span>foo</span></h4>+-}+h4 ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+h4 = element "h4"+{-# INLINE h4 #-}++{- | Combinator for the @\<h5>@ element.++ Example:++ > h5 $ span $ fmt "foo"++ Result:++ > <h5><span>foo</span></h5>+-}+h5 ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+h5 = element "h5"+{-# INLINE h5 #-}++{- | Combinator for the @\<h6>@ element.++ Example:++ > h6 $ span $ fmt "foo"++ Result:++ > <h6><span>foo</span></h6>+-}+h6 ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+h6 = element "h6"+{-# INLINE h6 #-}++{- | Combinator for the @\<head>@ element.++ Example:++ > head $ span $ fmt "foo"++ Result:++ > <head><span>foo</span></head>+-}+head ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+head = element "head"+{-# INLINE head #-}++{- | Combinator for the @\<header>@ element.++ Example:++ > header $ span $ fmt "foo"++ Result:++ > <header><span>foo</span></header>+-}+header ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+header = element "header"+{-# INLINE header #-}++{- | Combinator for the @\<hgroup>@ element.++ Example:++ > hgroup $ span $ fmt "foo"++ Result:++ > <hgroup><span>foo</span></hgroup>+-}+hgroup ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+hgroup = element "hgroup"+{-# INLINE hgroup #-}++{- | Combinator for the @\<hr />@ element.++ Example:++ > hr++ Result:++ > <hr />+-}+hr ::+ -- | Resulting HTML.+ Html a+hr = element_ "hr"+{-# INLINE hr #-}++{- | Combinator for the @\<html>@ element.++ Example:++ > html $ span $ fmt "foo"++ Result:++ > <html><span>foo</span></html>+-}+html ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+html = element "html"+{-# INLINE html #-}++{- | Combinator for the @\<i>@ element.++ Example:++ > i $ span $ fmt "foo"++ Result:++ > <i><span>foo</span></i>+-}+i ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+i = element "i"+{-# INLINE i #-}++{- | Combinator for the @\<iframe>@ element.++ Example:++ > iframe $ span $ fmt "foo"++ Result:++ > <iframe><span>foo</span></iframe>+-}+iframe ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+iframe = element "iframe"+{-# INLINE iframe #-}++{- | Combinator for the @\<img />@ element.++ Example:++ > img++ Result:++ > <img />+-}+img ::+ -- | Resulting HTML.+ Html a+img = element_ "img"+{-# INLINE img #-}++{- | Combinator for the @\<input />@ element.++ Example:++ > input++ Result:++ > <input />+-}+input ::+ -- | Resulting HTML.+ Html a+input = element_ "input"+{-# INLINE input #-}++{- | Combinator for the @\<ins>@ element.++ Example:++ > ins $ span $ fmt "foo"++ Result:++ > <ins><span>foo</span></ins>+-}+ins ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+ins = element "ins"+{-# INLINE ins #-}++{- | Combinator for the @\<kbd>@ element.++ Example:++ > kbd $ span $ fmt "foo"++ Result:++ > <kbd><span>foo</span></kbd>+-}+kbd ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+kbd = element "kbd"+{-# INLINE kbd #-}++{- | Combinator for the @\<keygen />@ element.++ Example:++ > keygen++ Result:++ > <keygen />+-}+keygen ::+ -- | Resulting HTML.+ Html a+keygen = element_ "keygen"+{-# INLINE keygen #-}++{- | Combinator for the @\<label>@ element.++ Example:++ > label $ span $ fmt "foo"++ Result:++ > <label><span>foo</span></label>+-}+label ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+label = element "label"+{-# INLINE label #-}++{- | Combinator for the @\<legend>@ element.++ Example:++ > legend $ span $ fmt "foo"++ Result:++ > <legend><span>foo</span></legend>+-}+legend ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+legend = element "legend"+{-# INLINE legend #-}++{- | Combinator for the @\<li>@ element.++ Example:++ > li $ span $ fmt "foo"++ Result:++ > <li><span>foo</span></li>+-}+li ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+li = element "li"+{-# INLINE li #-}++{- | Combinator for the @\<link />@ element.++ Example:++ > link++ Result:++ > <link />+-}+link ::+ -- | Resulting HTML.+ Html a+link = element_ "link"+{-# INLINE link #-}++{- | Combinator for the @\<main>@ element.++ Example:++ > main $ span $ fmt "foo"++ Result:++ > <main><span>foo</span></main>+-}+main ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+main = element "main"+{-# INLINE main #-}++{- | Combinator for the @\<map>@ element.++ Example:++ > map $ span $ fmt "foo"++ Result:++ > <map><span>foo</span></map>+-}+map ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+map = element "map"+{-# INLINE map #-}++{- | Combinator for the @\<mark>@ element.++ Example:++ > mark $ span $ fmt "foo"++ Result:++ > <mark><span>foo</span></mark>+-}+mark ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+mark = element "mark"+{-# INLINE mark #-}++{- | Combinator for the @\<menu>@ element.++ Example:++ > menu $ span $ fmt "foo"++ Result:++ > <menu><span>foo</span></menu>+-}+menu ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+menu = element "menu"+{-# INLINE menu #-}++{- | Combinator for the @\<menuitem />@ element.++ Example:++ > menuitem++ Result:++ > <menuitem />+-}+menuitem ::+ -- | Resulting HTML.+ Html a+menuitem = element_ "menuitem"+{-# INLINE menuitem #-}++{- | Combinator for the @\<meta />@ element.++ Example:++ > meta++ Result:++ > <meta />+-}+meta ::+ -- | Resulting HTML.+ Html a+meta = element_ "meta"+{-# INLINE meta #-}++{- | Combinator for the @\<meter>@ element.++ Example:++ > meter $ span $ fmt "foo"++ Result:++ > <meter><span>foo</span></meter>+-}+meter ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+meter = element "meter"+{-# INLINE meter #-}++{- | Combinator for the @\<nav>@ element.++ Example:++ > nav $ span $ fmt "foo"++ Result:++ > <nav><span>foo</span></nav>+-}+nav ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+nav = element "nav"+{-# INLINE nav #-}++{- | Combinator for the @\<noscript>@ element.++ Example:++ > noscript $ span $ fmt "foo"++ Result:++ > <noscript><span>foo</span></noscript>+-}+noscript ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+noscript = element "noscript"+{-# INLINE noscript #-}++{- | Combinator for the @\<object>@ element.++ Example:++ > object $ span $ fmt "foo"++ Result:++ > <object><span>foo</span></object>+-}+object ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+object = element "object"+{-# INLINE object #-}++{- | Combinator for the @\<ol>@ element.++ Example:++ > ol $ span $ fmt "foo"++ Result:++ > <ol><span>foo</span></ol>+-}+ol ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+ol = element "ol"+{-# INLINE ol #-}++{- | Combinator for the @\<optgroup>@ element.++ Example:++ > optgroup $ span $ fmt "foo"++ Result:++ > <optgroup><span>foo</span></optgroup>+-}+optgroup ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+optgroup = element "optgroup"+{-# INLINE optgroup #-}++{- | Combinator for the @\<option>@ element.++ Example:++ > option $ span $ fmt "foo"++ Result:++ > <option><span>foo</span></option>+-}+option ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+option = element "option"+{-# INLINE option #-}++{- | Combinator for the @\<output>@ element.++ Example:++ > output $ span $ fmt "foo"++ Result:++ > <output><span>foo</span></output>+-}+output ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+output = element "output"+{-# INLINE output #-}++{- | Combinator for the @\<p>@ element.++ Example:++ > p $ span $ fmt "foo"++ Result:++ > <p><span>foo</span></p>+-}+p ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+p = element "p"+{-# INLINE p #-}++{- | Combinator for the @\<param />@ element.++ Example:++ > param++ Result:++ > <param />+-}+param ::+ -- | Resulting HTML.+ Html a+param = element_ "param"+{-# INLINE param #-}++{- | Combinator for the @\<pre>@ element.++ Example:++ > pre $ span $ fmt "foo"++ Result:++ > <pre><span>foo</span></pre>+-}+pre ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+pre = element "pre"+{-# INLINE pre #-}++{- | Combinator for the @\<progress>@ element.++ Example:++ > progress $ span $ fmt "foo"++ Result:++ > <progress><span>foo</span></progress>+-}+progress ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+progress = element "progress"+{-# INLINE progress #-}++{- | Combinator for the @\<q>@ element.++ Example:++ > q $ span $ fmt "foo"++ Result:++ > <q><span>foo</span></q>+-}+q ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+q = element "q"+{-# INLINE q #-}++{- | Combinator for the @\<rp>@ element.++ Example:++ > rp $ span $ fmt "foo"++ Result:++ > <rp><span>foo</span></rp>+-}+rp ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+rp = element "rp"+{-# INLINE rp #-}++{- | Combinator for the @\<rt>@ element.++ Example:++ > rt $ span $ fmt "foo"++ Result:++ > <rt><span>foo</span></rt>+-}+rt ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+rt = element "rt"+{-# INLINE rt #-}++{- | Combinator for the @\<ruby>@ element.++ Example:++ > ruby $ span $ fmt "foo"++ Result:++ > <ruby><span>foo</span></ruby>+-}+ruby ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+ruby = element "ruby"+{-# INLINE ruby #-}++{- | Combinator for the @\<samp>@ element.++ Example:++ > samp $ span $ fmt "foo"++ Result:++ > <samp><span>foo</span></samp>+-}+samp ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+samp = element "samp"+{-# INLINE samp #-}++{- | Combinator for the @\<script>@ element.++ Example:++ > script $ span $ fmt "foo"++ Result:++ > <script><span>foo</span></script>+-}+script ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+script = element "script"+{-# INLINE script #-}++{- | Combinator for the @\<section>@ element.++ Example:++ > section $ span $ fmt "foo"++ Result:++ > <section><span>foo</span></section>+-}+section ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+section = element "section"+{-# INLINE section #-}++{- | Combinator for the @\<select>@ element.++ Example:++ > select $ span $ fmt "foo"++ Result:++ > <select><span>foo</span></select>+-}+select ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+select = element "select"+{-# INLINE select #-}++{- | Combinator for the @\<small>@ element.++ Example:++ > small $ span $ fmt "foo"++ Result:++ > <small><span>foo</span></small>+-}+small ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+small = element "small"+{-# INLINE small #-}++{- | Combinator for the @\<source />@ element.++ Example:++ > source++ Result:++ > <source />+-}+source ::+ -- | Resulting HTML.+ Html a+source = element_ "source"+{-# INLINE source #-}++{- | Combinator for the @\<span>@ element.++ Example:++ > span $ span $ fmt "foo"++ Result:++ > <span><span>foo</span></span>+-}+span ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+span = element "span"+{-# INLINE span #-}++{- | Combinator for the @\<strong>@ element.++ Example:++ > strong $ span $ fmt "foo"++ Result:++ > <strong><span>foo</span></strong>+-}+strong ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+strong = element "strong"+{-# INLINE strong #-}++{- | Combinator for the @\<style>@ element.++ Example:++ > style $ span $ fmt "foo"++ Result:++ > <style><span>foo</span></style>+-}+style ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+style = element "style"+{-# INLINE style #-}++{- | Combinator for the @\<sub>@ element.++ Example:++ > sub $ span $ fmt "foo"++ Result:++ > <sub><span>foo</span></sub>+-}+sub ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+sub = element "sub"+{-# INLINE sub #-}++{- | Combinator for the @\<summary>@ element.++ Example:++ > summary $ span $ fmt "foo"++ Result:++ > <summary><span>foo</span></summary>+-}+summary ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+summary = element "summary"+{-# INLINE summary #-}++{- | Combinator for the @\<sup>@ element.++ Example:++ > sup $ span $ fmt "foo"++ Result:++ > <sup><span>foo</span></sup>+-}+sup ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+sup = element "sup"+{-# INLINE sup #-}++{- | Combinator for the @\<table>@ element.++ Example:++ > table $ span $ fmt "foo"++ Result:++ > <table><span>foo</span></table>+-}+table ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+table = element "table"+{-# INLINE table #-}++{- | Combinator for the @\<tbody>@ element.++ Example:++ > tbody $ span $ fmt "foo"++ Result:++ > <tbody><span>foo</span></tbody>+-}+tbody ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+tbody = element "tbody"+{-# INLINE tbody #-}++{- | Combinator for the @\<td>@ element.++ Example:++ > td $ span $ fmt "foo"++ Result:++ > <td><span>foo</span></td>+-}+td ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+td = element "td"+{-# INLINE td #-}++{- | Combinator for the @\<textarea>@ element.++ Example:++ > textarea $ span $ fmt "foo"++ Result:++ > <textarea><span>foo</span></textarea>+-}+textarea ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+textarea = element "textarea"+{-# INLINE textarea #-}++{- | Combinator for the @\<tfoot>@ element.++ Example:++ > tfoot $ span $ fmt "foo"++ Result:++ > <tfoot><span>foo</span></tfoot>+-}+tfoot ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+tfoot = element "tfoot"+{-# INLINE tfoot #-}++{- | Combinator for the @\<th>@ element.++ Example:++ > th $ span $ fmt "foo"++ Result:++ > <th><span>foo</span></th>+-}+th ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+th = element "th"+{-# INLINE th #-}++{- | Combinator for the @\<thead>@ element.++ Example:++ > thead $ span $ fmt "foo"++ Result:++ > <thead><span>foo</span></thead>+-}+thead ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+thead = element "thead"+{-# INLINE thead #-}++{- | Combinator for the @\<time>@ element.++ Example:++ > time $ span $ fmt "foo"++ Result:++ > <time><span>foo</span></time>+-}+time ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+time = element "time"+{-# INLINE time #-}++{- | Combinator for the @\<title>@ element.++ Example:++ > title $ span $ fmt "foo"++ Result:++ > <title><span>foo</span></title>+-}+title ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+title = element "title"+{-# INLINE title #-}++{- | Combinator for the @\<tr>@ element.++ Example:++ > tr $ span $ fmt "foo"++ Result:++ > <tr><span>foo</span></tr>+-}+tr ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+tr = element "tr"+{-# INLINE tr #-}++{- | Combinator for the @\<track />@ element.++ Example:++ > track++ Result:++ > <track />+-}+track ::+ -- | Resulting HTML.+ Html a+track = element_ "track"+{-# INLINE track #-}++{- | Combinator for the @\<u>@ element.++ Example:++ > u $ span $ fmt "foo"++ Result:++ > <u><span>foo</span></u>+-}+u ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+u = element "u"+{-# INLINE u #-}++{- | Combinator for the @\<ul>@ element.++ Example:++ > ul $ span $ fmt "foo"++ Result:++ > <ul><span>foo</span></ul>+-}+ul ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+ul = element "ul"+{-# INLINE ul #-}++{- | Combinator for the @\<var>@ element.++ Example:++ > var $ span $ fmt "foo"++ Result:++ > <var><span>foo</span></var>+-}+var ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+var = element "var"+{-# INLINE var #-}++{- | Combinator for the @\<video>@ element.++ Example:++ > video $ span $ fmt "foo"++ Result:++ > <video><span>foo</span></video>+-}+video ::+ -- | Inner HTML.+ Html a ->+ -- | Resulting HTML.+ Html a+video = element "video"+{-# INLINE video #-}++{- | Combinator for the @\<wbr />@ element.++ Example:++ > wbr++ Result:++ > <wbr />+-}+wbr :: Html a+wbr = element_ "wbr"+{-# INLINE wbr #-}
+ src/Data/Fmt/Time.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE OverloadedStrings #-}++module Data.Fmt.Time (+ time,++ -- * Time+ t,+ hm,+ hms,+ day,+ day',+ month,+ month',+ year,+ unix,+ zone,++ -- * Duration+ secs,+ mins,+ hours,+ days,+ years,+) where++import Data.Fmt+import Data.String+import Data.Time (FormatTime, defaultTimeLocale, formatTime)+import Data.Time.Format.ISO8601 (ISO8601, iso8601Show)+import Prelude hiding (min)+import qualified Data.Fmt.Code as Fmt++{- | A custom time formatter.++ For example, the E.U. formatting convention is /time "%Y-%m-%d %T %z"/+-}+time :: (IsString m, FormatTime a) => String -> Fmt1 m s a+time s = fmt1 $ fromString . formatTime defaultTimeLocale s++-- Time++-------------------------++-- | < https://en.wikipedia.org/wiki/ISO_8601 ISO-8601> time: /2021-06-05T01:46:46.173677-07:00/+t :: (IsString m, ISO8601 a) => Fmt1 m s a+t = fmt1 $ fromString . iso8601Show++-- | Hour-minute of day: @%H:%M@.+hm :: (IsString m, FormatTime a) => Fmt1 m s a+hm = time "%R"++-- | Hour-minute-second of day: @%H:%M:%S@.+hms :: (IsString m, FormatTime a) => Fmt1 m s a+hms = time "%T"++-- | Day of month: @01@ - @31@.+day :: (IsString m, FormatTime a) => Fmt1 m s a+day = time "%d"++-- | Day of week: @Sun@ - @Sat@.+day' :: (IsString m, FormatTime a) => Fmt1 m s a+day' = time "%a"++-- | Month of year: @01@ - @12@.+month :: (IsString m, FormatTime a) => Fmt1 m s a+month = time "%m"++-- | Month of year: @Jan@ - @Dec@.+month' :: (IsString m, FormatTime a) => Fmt1 m s a+month' = time "%b"++-- | Year.+year :: (IsString m, FormatTime a) => Fmt1 m s a+year = time "%Y"++-- | Seconds from Unix epoch.+unix :: (IsString m, FormatTime a) => Fmt1 m s a+unix = time "%s"++-- | Timezone offset: @-HHMM@.+zone :: (IsString m, FormatTime a) => Fmt1 m s a+zone = time "%z"++-- Duration++-------------------------++-- | Display to a given precision the absolute value time span in seconds.+secs :: IsString m => Int -> Fmt1 m s Double+secs n = fmt1 (runFmt (Fmt.f n) . abs . count) where count n' = n'++-- | Display to a given precision the absolute value time span in minutes.+mins :: IsString m => Int -> Fmt1 m s Double+mins n = fmt1 (runFmt (Fmt.f n) . abs . count) where count n' = n' / 60++-- | Display to a given precision the absolute value time span in hours.+hours :: IsString m => Int -> Fmt1 m s Double+hours n = fmt1 (runFmt (Fmt.f n) . abs . count) where count n' = n' / 60 / 60++-- | Display to a given precision the absolute value time span in days.+days :: (IsString m) => Int -> Fmt1 m s Double+days n = fmt1 (runFmt (Fmt.f n) . abs . count) where count n' = n' / 24 / 60 / 60++-- | Display to a given precision the absolute value time span in years.+years :: IsString m => Int -> Fmt1 m s Double+years n = fmt1 (runFmt (Fmt.f n) . abs . count) where count n' = n' / 365 / 24 / 60 / 60