microstache 1.0.1.1 → 1.0.1.2
raw patch · 7 files changed
+154/−139 lines, 7 filesdep ~basedep ~bytestringPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base, bytestring
API changes (from Hackage documentation)
- Text.Microstache.Type: instance Data.Semigroup.Semigroup Text.Microstache.Type.Key
- Text.Microstache.Type: instance Data.Semigroup.Semigroup Text.Microstache.Type.Template
- Text.Microstache.Type: instance GHC.Exception.Exception Text.Microstache.Type.MustacheException
- Text.Microstache.Type: instance GHC.Exception.Exception Text.Microstache.Type.MustacheWarning
+ Text.Microstache.Type: instance GHC.Base.Semigroup Text.Microstache.Type.Key
+ Text.Microstache.Type: instance GHC.Base.Semigroup Text.Microstache.Type.Template
+ Text.Microstache.Type: instance GHC.Exception.Type.Exception Text.Microstache.Type.MustacheException
+ Text.Microstache.Type: instance GHC.Exception.Type.Exception Text.Microstache.Type.MustacheWarning
- Text.Microstache: Partial :: PName -> (Maybe Word) -> Node
+ Text.Microstache: Partial :: PName -> Maybe Word -> Node
- Text.Microstache.Type: Partial :: PName -> (Maybe Word) -> Node
+ Text.Microstache.Type: Partial :: PName -> Maybe Word -> Node
Files
- CHANGELOG.md +4/−0
- microstache.cabal +80/−70
- src/Text/Microstache.hs +2/−6
- src/Text/Microstache/Compile.hs +13/−12
- src/Text/Microstache/Parser.hs +10/−9
- src/Text/Microstache/Render.hs +33/−31
- src/Text/Microstache/Type.hs +12/−11
CHANGELOG.md view
@@ -1,3 +1,7 @@+## microstache 1.0.1.2++- Drop `bytestring` dependency (there weren't direct one)+ ## microstache 1.0.1.1 - Fix build against `transformers-0.3`
microstache.cabal view
@@ -1,15 +1,17 @@-name: microstache-version: 1.0.1.1-cabal-version: >= 1.10-license: BSD3-license-file: LICENSE-author: Mark Karpov <markkarpov@openmailbox.org>, Oleg Grenrus <oleg.grenrus@iki.fi>-maintainer: Oleg Grenrus<oleg.grenrus@iki.fi>-homepage: https://github.com/phadej/microstache-bug-reports: https://github.com/phadej/microstache/issues-category: Text-synopsis: Mustache templates for Haskell-build-type: Simple+name: microstache+version: 1.0.1.2+cabal-version: >=1.10+license: BSD3+license-file: LICENSE+author:+ Mark Karpov <markkarpov@openmailbox.org>, Oleg Grenrus <oleg.grenrus@iki.fi>++maintainer: Oleg Grenrus<oleg.grenrus@iki.fi>+homepage: https://github.com/phadej/microstache+bug-reports: https://github.com/phadej/microstache/issues+category: Text+synopsis: Mustache templates for Haskell+build-type: Simple description: Mustache templates for Haskell. .@@ -18,7 +20,7 @@ extra-source-files: CHANGELOG.md- README.md+ README.md specification/comments.json specification/delimiters.json specification/interpolation.json@@ -27,79 +29,87 @@ specification/sections.json tested-with:- GHC==7.4.2,- GHC==7.6.3,- GHC==7.8.4,- GHC==7.10.3,- GHC==8.0.2,- GHC==8.2.1+ GHC ==7.4.2+ || ==7.6.3+ || ==7.8.4+ || ==7.10.3+ || ==8.0.2+ || ==8.2.2+ || ==8.4.4+ || ==8.6.5+ || ==8.8.3+ || ==8.10.1 source-repository head- type: git- location: https://github.com/phadej/microstache.git+ type: git+ location: https://github.com/phadej/microstache.git library build-depends:- aeson >=0.11 && < 1.3,- base >=4.5 && < 5.0,- bytestring >=0.9.2.1 && < 0.11,- containers >=0.4.2.1 && < 0.6,- deepseq >=1.3.0.0 && < 1.5,- directory >=1.1.0.2 && < 1.4,- filepath >=1.3.0.0 && < 1.5,- parsec >=3.1.11 && < 6.0,- transformers >=0.3.0.0 && < 0.6,- text >=1.2 && < 1.3,- unordered-containers >= 0.2.5 && < 0.3,- vector >= 0.11 && < 0.13- if impl(ghc <= 7.6)- build-depends:- ghc-prim- if !impl(ghc >= 8.0)- build-depends:- semigroups == 0.18.*+ aeson >=0.11 && <1.6+ , base >=4.5 && <4.15+ , containers >=0.4.2.1 && <0.7+ , deepseq >=1.3.0.0 && <1.5+ , directory >=1.1.0.2 && <1.4+ , filepath >=1.3.0.0 && <1.5+ , parsec >=3.1.11 && <6.0+ , text >=1.2 && <1.3+ , transformers >=0.3.0.0 && <0.6+ , unordered-containers >=0.2.5 && <0.3+ , vector >=0.11 && <0.13++ if impl(ghc <=7.6)+ build-depends: ghc-prim++ if !impl(ghc >=8.0)+ build-depends: semigroups >=0.18 && <0.20+ exposed-modules: Text.Microstache Text.Microstache.Compile Text.Microstache.Parser Text.Microstache.Render Text.Microstache.Type- hs-source-dirs: src- ghc-options: -Wall- default-language: Haskell2010 + hs-source-dirs: src+ ghc-options: -Wall+ default-language: Haskell2010+ test-suite tests- main-is: Spec.hs- hs-source-dirs: tests- type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs: tests+ type: exitcode-stdio-1.0 build-depends:- hspec >= 2.0 && < 3.0,- aeson,- base,- containers,- parsec,- microstache,- text- if !impl(ghc >= 8.0)- build-depends:- semigroups == 0.18.*- other-modules: + aeson+ , base+ , containers+ , hspec >=2.0 && <3.0+ , microstache+ , parsec+ , text++ if !impl(ghc >=8.0)+ build-depends: semigroups++ other-modules: Text.Microstache.ParserSpec Text.Microstache.RenderSpec Text.Microstache.TypeSpec- default-language: Haskell2010 + default-language: Haskell2010+ test-suite mustache-spec- main-is: Spec.hs- hs-source-dirs: mustache-spec- type: exitcode-stdio-1.0- build-depends: - hspec,- aeson,- base,- bytestring,- containers, - parsec,- microstache,- text- default-language: Haskell2010+ main-is: Spec.hs+ hs-source-dirs: mustache-spec+ type: exitcode-stdio-1.0+ build-depends:+ aeson+ , base+ , bytestring+ , containers+ , hspec+ , microstache+ , parsec+ , text++ default-language: Haskell2010
src/Text/Microstache.hs view
@@ -14,14 +14,11 @@ -- functions to compile templates (from directory, from file, and from lazy -- text) and one to render them. ----- The implementation uses the Megaparsec parsing library to parse the--- templates which results in superior quality of error messages.--- -- For rendering you only need to create Aeson's 'Data.Aeson.Value' where -- you put the data to interpolate. Since the library re-uses Aeson's -- instances and most data types in Haskell ecosystem are instances of -- classes like 'Data.Aeson.ToJSON', the whole process is very simple for--- end user.+-- the end user. -- -- Template Haskell helpers for compilation of templates at compile time are -- available in the "Text.Microstache.Compile.TH" module. The helpers are@@ -41,7 +38,6 @@ -- > -- > import Data.Aeson -- > import Data.Text--- > import Text.Megaparsec -- > import Text.Microstache -- > import qualified Data.Text.Lazy.IO as TIO -- >@@ -50,7 +46,7 @@ -- > let res = compileMustacheText "foo" -- > "Hi, {{name}}! You have:\n{{#things}}\n * {{.}}\n{{/things}}\n" -- > case res of--- > Left err -> putStrLn (parseErrorPretty err)+-- > Left err -> print err -- > Right template -> TIO.putStr $ renderMustache template $ object -- > [ "name" .= ("John" :: Text) -- > , "things" .= ["pen" :: Text, "candle", "egg"]
src/Text/Microstache/Compile.hs view
@@ -20,16 +20,17 @@ , compileMustacheText ) where -import Control.Exception (throwIO)-import Control.Monad (foldM, filterM)-import Data.Text.Lazy (Text)+import Control.Exception (throwIO)+import Control.Monad (filterM, foldM)+import Data.Text.Lazy (Text) import System.Directory-import Text.Parsec import Text.Microstache.Parser import Text.Microstache.Type-import qualified Data.Map as M+import Text.Parsec++import qualified Data.Map as Map import qualified Data.Text as T-import qualified Data.Text.Lazy.IO as TL+import qualified Data.Text.Lazy.IO as LT import qualified System.FilePath as F #if !MIN_VERSION_base(4,8,0)@@ -49,12 +50,12 @@ -> IO Template -- ^ The resulting template compileMustacheDir pname path = getMustacheFilesInDir path >>=- fmap selectKey . foldM f (Template undefined M.empty)+ fmap selectKey . foldM f (Template undefined Map.empty) where selectKey t = t { templateActual = pname } f (Template _ old) fp = do Template _ new <- compileMustacheFile fp- return (Template undefined (M.union new old))+ return (Template undefined (Map.union new old)) -- | Return a list of templates found in given directory. The returned paths -- are absolute.@@ -63,7 +64,7 @@ :: FilePath -- ^ Directory with templates -> IO [FilePath] getMustacheFilesInDir path =- (getDirectoryContents path) >>=+ getDirectoryContents path >>= filterM isMustacheFile . fmap (F.combine path) >>= mapM makeAbsolute' @@ -75,10 +76,10 @@ :: FilePath -- ^ Location of the file -> IO Template compileMustacheFile path =- (TL.readFile path) >>= withException . compile+ LT.readFile path >>= withException . compile where pname = pathToPName path- compile = fmap (Template pname . M.singleton pname) . parseMustache path+ compile = fmap (Template pname . Map.singleton pname) . parseMustache path -- | Compile Mustache template from a lazy 'Text' value. The cache will -- contain only this template named according to given 'PName'.@@ -88,7 +89,7 @@ -> Text -- ^ The template to compile -> Either ParseError Template -- ^ The result compileMustacheText pname txt =- Template pname . M.singleton pname <$> parseMustache "" txt+ Template pname . Map.singleton pname <$> parseMustache "" txt ---------------------------------------------------------------------------- -- Helpers
src/Text/Microstache/Parser.hs view
@@ -15,18 +15,19 @@ ( parseMustache ) where -import Control.Applicative hiding (many)+import Control.Applicative hiding (many) import Control.Monad-import Data.Char (isSpace, isAlphaNum)-import Data.List (intercalate)+import Data.Char (isAlphaNum, isSpace) import Data.Functor.Identity-import Data.Maybe (catMaybes)-import Data.Text.Lazy (Text)-import Text.Parsec hiding ((<|>))-import Text.Parsec.Char ()-import Data.Word (Word)+import Data.List (intercalate)+import Data.Maybe (catMaybes)+import Data.Text.Lazy (Text)+import Data.Word (Word) import Text.Microstache.Type-import qualified Data.Text as T+import Text.Parsec hiding ((<|>))+import Text.Parsec.Char ()++import qualified Data.Text as T ---------------------------------------------------------------------------- -- Parser
src/Text/Microstache/Render.hs view
@@ -11,37 +11,39 @@ -- import the module, because "Text.Microstache" re-exports everything you may -- need, import that module instead. -{-# LANGUAGE CPP #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} module Text.Microstache.Render ( renderMustache, renderMustacheW ) where -import Control.Monad (when, forM_, unless)+import Control.Monad (forM_, unless, when)+import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Reader (ReaderT (..), asks, local)+import Data.Aeson (Value (..), encode)+import Data.Foldable (asum)+import Data.List (tails)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Monoid (mempty)+import Data.Semigroup ((<>))+import Data.Text (Text)+import Data.Word (Word)+import Text.Microstache.Type++import qualified Data.HashMap.Strict as HM+import qualified Data.List.NonEmpty as NE+import qualified Data.Map as Map+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import qualified Data.Text.Lazy.Builder as B+import qualified Data.Text.Lazy.Encoding as LTE+import qualified Data.Vector as V+ #if MIN_VERSION_transformers(0,4,0)-import Control.Monad.Trans.State.Strict (State, modify', execState)+import Control.Monad.Trans.State.Strict (State, execState, modify') #else-import Control.Monad.Trans.State.Strict (State, get, put, execState)+import Control.Monad.Trans.State.Strict (State, execState, get, put) #endif-import Control.Monad.Trans.Class (lift)-import Data.Aeson (Value (..), encode)-import Data.Monoid (mempty)-import Data.Semigroup ((<>))-import Data.Foldable (asum)-import Data.List (tails)-import Data.List.NonEmpty (NonEmpty (..))-import Data.Text (Text)-import Data.Word (Word)-import Text.Microstache.Type-import qualified Data.HashMap.Strict as H-import qualified Data.List.NonEmpty as NE-import qualified Data.Map as M-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.Encoding as TL-import qualified Data.Text.Lazy.Builder as B-import qualified Data.Vector as V #if !MIN_VERSION_base(4,8,0) import Control.Applicative@@ -59,7 +61,7 @@ -- | Synonym for the monad we use for rendering. It allows to share context -- and accumulate the result as 'B.Builder' data which is then turned into--- lazy 'TL.Text'.+-- lazy 'LT.Text'. type Render a = ReaderT RenderContext (State S) a @@ -87,13 +89,13 @@ -- | Render a Mustache 'Template' using Aeson's 'Value' to get actual values -- for interpolation.-renderMustache :: Template -> Value -> TL.Text+renderMustache :: Template -> Value -> LT.Text renderMustache t = snd . renderMustacheW t -- | Like 'renderMustache' but also return a list of warnings. -- -- @since 1.0.1-renderMustacheW :: Template -> Value -> ([MustacheWarning], TL.Text)+renderMustacheW :: Template -> Value -> ([MustacheWarning], LT.Text) renderMustacheW t = runRender (renderPartial (templateActual t) Nothing renderNode) t @@ -128,7 +130,7 @@ -- | Run 'Render' monad given template to render and a 'Value' to take -- values from. -runRender :: Render a -> Template -> Value -> ([MustacheWarning], TL.Text)+runRender :: Render a -> Template -> Value -> ([MustacheWarning], LT.Text) runRender m t v = case execState (runReaderT m rc) (S id mempty) of S ws b -> (ws [], B.toLazyText b) where@@ -187,7 +189,7 @@ getNodes :: Render [Node] getNodes = do Template actual cache <- asks rcTemplate- return (M.findWithDefault [] actual cache)+ return (Map.findWithDefault [] actual cache) {-# INLINE getNodes #-} -- | Render many nodes.@@ -233,7 +235,7 @@ -> Maybe Value -- ^ Looked-up value simpleLookup _ (Key []) obj = return obj simpleLookup c (Key (k:ks)) (Object m) =- case H.lookup k m of+ case HM.lookup k m of Nothing -> if c then Just Null else Nothing Just v -> simpleLookup True (Key ks) v simpleLookup _ _ _ = Nothing@@ -278,7 +280,7 @@ isBlank :: Value -> Bool isBlank Null = True isBlank (Bool False) = True-isBlank (Object m) = H.null m+isBlank (Object m) = HM.null m isBlank (Array a) = V.null a isBlank (String s) = T.null s isBlank _ = False@@ -298,7 +300,7 @@ render v _ -> render v where- render = return . TL.toStrict . TL.decodeUtf8 . encode+ render = return . LT.toStrict . LTE.decodeUtf8 . encode {-# INLINE renderValue #-} -- | Escape HTML represented as strict 'Text'.
src/Text/Microstache/Type.hs view
@@ -30,18 +30,19 @@ ) where -import Data.Word (Word) import Control.DeepSeq-import Control.Exception (Exception(..))-import Data.Data (Data)-import Data.Map (Map)+import Control.Exception (Exception (..))+import Data.Data (Data)+import Data.Map (Map) import Data.Semigroup-import Data.String (IsString (..))-import Data.Text (Text)-import Data.Typeable (Typeable)+import Data.String (IsString (..))+import Data.Text (Text)+import Data.Typeable (Typeable)+import Data.Word (Word) import GHC.Generics import Text.Parsec-import qualified Data.Map as M++import qualified Data.Map as Map import qualified Data.Text as T -- | Mustache template as name of “top-level” template and a collection of@@ -62,7 +63,7 @@ } deriving (Eq, Ord, Show, Data, Typeable, Generic) instance Semigroup Template where- (Template pname x) <> (Template _ y) = Template pname (M.union x y)+ (Template pname x) <> (Template _ y) = Template pname (Map.union x y) -- | Structural element of template. @@ -143,9 +144,9 @@ -- | @since 1.0.1 displayMustacheWarning :: MustacheWarning -> String-displayMustacheWarning (MustacheVariableNotFound key) = +displayMustacheWarning (MustacheVariableNotFound key) = "Referenced value was not provided, key: " ++ T.unpack (showKey key)-displayMustacheWarning (MustacheDirectlyRenderedValue key) = +displayMustacheWarning (MustacheDirectlyRenderedValue key) = "Complex value rendered as such, key: " ++ T.unpack (showKey key) instance Exception MustacheWarning where