packages feed

lucid 2.10.0 → 2.11.0

raw patch · 4 files changed

+44/−15 lines, 4 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

- Lucid: runHtmlT :: HtmlT m a -> m (Map Text Text -> Builder, a)
+ Lucid: runHtmlT :: HtmlT m a -> m (Seq Attribute -> Builder, a)
- Lucid.Base: HtmlT :: m (Map Text Text -> Builder, a) -> HtmlT m a
+ Lucid.Base: HtmlT :: m (Seq Attribute -> Builder, a) -> HtmlT m a
- Lucid.Base: runHtmlT :: HtmlT m a -> m (Map Text Text -> Builder, a)
+ Lucid.Base: runHtmlT :: HtmlT m a -> m (Seq Attribute -> Builder, a)

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+## 2.11.0++* Change internal attributes to `Seq Attribute`. This preserves+  ordering. Attributes are merged in a left-biased way, preserving the+  key order as first encountered.+ ## 2.9.13  * Change internal attributes representation from HashMap to Map. This
lucid.cabal view
@@ -1,5 +1,5 @@ name:                lucid-version:             2.10.0+version:             2.11.0 synopsis:            Clear to write, read and edit DSL for HTML description:   Clear to write, read and edit DSL for HTML.
src/Lucid/Base.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -53,7 +54,6 @@ import qualified Data.ByteString.Lazy as L import qualified Data.ByteString as S import           Data.Functor.Identity-import           Data.Map.Strict (Map) import qualified Data.Map.Strict as M import           Data.Hashable (Hashable(..)) import           Data.Semigroup (Semigroup (..))@@ -65,11 +65,18 @@ import qualified Data.Text.Encoding as T import           Data.Typeable (Typeable) import           Prelude+import           Data.Maybe+import           Data.Sequence (Seq)+import qualified Data.Sequence as Seq+import           Data.Foldable (toList)+import qualified Data.Set as Set  -------------------------------------------------------------------------------- -- Types --- | A simple attribute. Don't use the constructor, use 'makeAttribute'.+-- | A simple attribute. Don't use the constructor, use+-- 'makeAttribute'.  Attributes are case sensitive, so if you want+-- attributes to be merged properly, use a single case representation. data Attribute = Attribute !Text !Text   deriving (Show,Eq,Typeable) @@ -85,8 +92,11 @@  -- | A monad transformer that generates HTML. Use the simpler 'Html' -- type if you don't want to transform over some other monad.+--+-- Don't rely on the internal representation of this type. Use the+-- monad and functor classes. newtype HtmlT m a =-  HtmlT {runHtmlT :: m (Map Text Text -> Builder,a)+  HtmlT {runHtmlT :: m (Seq Attribute -> Builder,a)          -- ^ This is the low-level way to run the HTML transformer,          -- finally returning an element builder and a value. You can          -- pass 'mempty' for this argument for a top-level call. See@@ -342,22 +352,16 @@ instance (Functor m) => With (HtmlT m a) where   with f = \attr -> HtmlT (mk attr <$> runHtmlT f)     where-      mk attr ~(f',a) = (\attr' -> f' (unionArgs (M.fromListWith (<>) (map toPair attr)) attr')+      mk attr ~(f',a) = (\attr' -> f' (attr' <> Seq.fromList attr)                         ,a)-      toPair (Attribute x y) = (x,y)  -- | For the contentful elements: 'Lucid.Html5.div_' instance (Functor m) => With (HtmlT m a -> HtmlT m a) where   with f = \attr inner -> HtmlT (mk attr <$> runHtmlT (f inner))     where-      mk attr ~(f',a) = (\attr' -> f' (unionArgs (M.fromListWith (<>) (map toPair attr)) attr')+      mk attr ~(f',a) = (\attr' -> f' (attr' <> Seq.fromList attr)                         ,a)-      toPair (Attribute x y) = (x,y) --- | Union two sets of arguments and append duplicate keys.-unionArgs :: Map Text Text -> Map Text Text -> Map Text Text-unionArgs = M.unionWith (<>)- -------------------------------------------------------------------------------- -- Running @@ -529,8 +533,27 @@      else s "=\"" <> Blaze.fromHtmlEscapedText val <> s "\""  -- | Folding and monoidally appending attributes.-foldlMapWithKey :: Monoid m => (k -> v -> m) -> Map k v -> m-foldlMapWithKey f = M.foldlWithKey' (\m k v -> m `mappend` f k v) mempty+foldlMapWithKey :: (Text -> Text -> Builder) -> Seq Attribute -> Builder+foldlMapWithKey f attributes =+  case nubOrdMaybe (map fst pairs) of+    Just keyList ->+      foldMap (\k -> fromMaybe mempty (fmap (f k) (M.lookup k values))) keyList+      where values = M.fromListWith (<>) pairs+    Nothing -> foldMap (\(Attribute k v) -> f k v) attributes+  where+    pairs = map (\(Attribute k v) -> (k,v)) (toList attributes)++-- | Do a nubOrd, but only return Maybe if it actually removes anything.+nubOrdMaybe :: Ord a => [a] -> Maybe [a]+nubOrdMaybe = go False Set.empty []+  where+    go (!removed) set acc (x:xs)+      | x `Set.member` set = go True set acc xs+      | otherwise = go removed (Set.insert x set) (x : acc) xs+    go removed _set acc [] =+      if removed+        then pure (reverse acc)+        else Nothing  -- | Convenience function for constructing builders. s :: String -> Builder
test/Main.hs view
@@ -193,7 +193,7 @@          "<div class=\" container \">Foo!</div>")      it "bootstrap-attributes-extended" $         renderText (container_ [class_ "bar",id_ "zot"] "Foo!") ==?*-        [ "<div id=\"zot\" class=\" container bar\">Foo!</div>"+        [ "<div class=\" container bar\" id=\"zot\">Foo!</div>"         , "<div class=\" container bar\" id=\"zot\">Foo!</div>"         ]