packages feed

mustache 0.3.1.0 → 0.4.0.0

raw patch · 8 files changed

+144/−158 lines, 8 filesdep −conversiondep −conversion-text

Dependencies removed: conversion, conversion-text

Files

+ CHANGELOG.md view
@@ -0,0 +1,24 @@+# Mustache library changelog++## v0.4.0.0rc-4 (current stable version)++- Removed `conversion` and `conversion-text` dependency.+- Subsequently removed any dependency on overlapping instances+- Readded support for ghc version 7.8+- Removed `Char -> Value` instance of `ToMustache` (because of overlap)+- Renamed `AST`++## v0.3.1.0rc-3++- Added infix precedence to conversion operators+- Added `INLINEABLE` pragma to conversion functions++## v0.3.0.1rc-2++Dropped GHC 7.8 support in favor of efficient and easy data conversion.++## v0.3.0.0rc-1++- improved documentation+- fixed a bug with scope+- small interface changes
mustache.cabal view
@@ -1,27 +1,25 @@ name:                mustache-version:             0.3.1.0+version:             0.4.0.0 synopsis:            A mustache template parser library. description:   Allows parsing and rendering template files with mustache markup. See the   mustache <http://mustache.github.io/mustache.5.html language reference>.--  Implements the mustache spec version 1.1.3--  This library requires GHC >= 7.10 because it uses the new overlapping instances-  to provide efficient and versatile conversion of custom data types into mustache-  Values.+  .+  Implements the mustache spec version 1.1.3.+  .+  /Note/: Versions including and beyond 0.4 are compatible with ghc 7.8 again. license:             BSD3 license-file:        LICENSE author:              Justus Adam maintainer:          dev@justus.science homepage:            https://github.com/JustusAdam/mustache bug-reports:         https://github.com/JustusAdam/mustache/issues--- copyright:+copyright:           (c) 2015 Justus Adam category:            Development build-type:          Simple-extra-source-files:  README.md+extra-source-files:  README.md CHANGELOG.md cabal-version:       >=1.10-tested-with:         GHC >=7.10 && <= 7.10.2+tested-with:         GHC >=7.8 && <= 7.10.2   source-repository head@@ -32,7 +30,7 @@   type:     git   branch:   master   location: git://github.com/JustusAdam/mustache.git-  tag:      v0.3.1.0rc-3+  tag:      v0.4.0.0rc-4   @@ -57,8 +55,6 @@                        directory,                        filepath,                        scientific,-                       conversion >= 1.2,-                       conversion-text,                        base-unicode-symbols,                        ja-base-extra >= 0.2.1,                        containers
src/lib/Text/Mustache.hs view
@@ -71,8 +71,7 @@ @  The values to the left of the '~>' operator has to be of type 'Text', hence the-@OverloadedStrings@ can becomes very handy here. Alternatively the '~~>' operator-can be used, which accepts an arbitrary string-like, converting it to text.+@OverloadedStrings@ can becomes very handy here.  Values to the right of the '~>' operator must be an instance of the 'ToMustache' typeclass. Alternatively, if your value to the right of the '~>' operator is@@ -121,7 +120,7 @@ ['ToMustache'] A typeclass for converting arbitrary types to 'Value', similar to Data.Aeson.ToJSON but with support for lambdas. -['Template'] Contains the 'AST', the abstract syntax tree, which is basically a+['Template'] Contains the 'STree', the syntax tree, which is basically a list of text blocks and mustache tags. The 'name' of the template and its 'partials' cache. @@ -130,7 +129,7 @@ During the compilation step the template file is located, read, then parsed in a single pass ('compileTemplate'), resulting in a 'Template' with an empty 'partials' section. -Subsequenty the 'AST' of the template is scanned for included partials, any+Subsequenty the 'STree' of the template is scanned for included partials, any present 'TemplateCache' is queried for the partial ('compileTemplateWithCache'), if not found it will be searched for in the @searchSpache@, compiled and inserted into the template's own cache as well as the global cache for the@@ -173,7 +172,7 @@   , substituteValue    -- ** Data Conversion-  , ToMustache, toMustache, object, (~>), (~=), (~~>), (~~=)+  , ToMustache, toMustache, object, (~>), (~=)   ) where  
src/lib/Text/Mustache/Compile.hs view
@@ -78,7 +78,7 @@         Just template → return template         Nothing → do           rawSource ← lift $ getFile searchSpace name'-          compiled@(Template { ast = mAST }) ←+          compiled@(Template { ast = mSTree }) ←             lift $ hoistEither $ compileTemplate name' rawSource            foldM@@ -88,7 +88,7 @@               return (st { partials = HM.insert partialName nt p })             )             compiled-            (getPartials mAST)+            (getPartials mSTree)   -- | Flatten a list of Templates into a single 'TemplateChache'@@ -103,11 +103,11 @@   {-|-  Find the names of all included partials in a mustache AST.+  Find the names of all included partials in a mustache STree.    Same as @join . fmap getPartials'@ -}-getPartials ∷ AST → [FilePath]+getPartials ∷ STree → [FilePath] getPartials = join ∘ fmap getPartials'  
src/lib/Text/Mustache/Parser.hs view
@@ -38,17 +38,15 @@  import           Control.Monad import           Control.Monad.Unicode-import           Conversion                  (Conversion, convert)-import           Conversion.Text             ()-import           Data.Char                   (isAlphaNum, isSpace)-import           Data.Functor                ((<$>))-import           Data.List                   (nub)-import           Data.Monoid.Unicode         ((∅), (⊕))-import           Data.Text                   as T (Text, null, pack)-import           Prelude                     as Prel+import           Data.Char              (isAlphaNum, isSpace)+import           Data.Functor           ((<$>))+import           Data.List              (nub)+import           Data.Monoid.Unicode    ((∅), (⊕))+import           Data.Text              as T (Text, null, pack)+import           Prelude                as Prel import           Prelude.Unicode import           Text.Mustache.Types-import           Text.Parsec                 as P hiding (endOfLine, parse)+import           Text.Parsec            as P hiding (endOfLine, parse)   -- | Initial configuration for the parser@@ -149,16 +147,16 @@ {-|   Runs the parser for a mustache template, returning the syntax tree. -}-parse ∷ FilePath → Text → Either ParseError AST+parse ∷ FilePath → Text → Either ParseError STree parse = parseWithConf defaultConf   -- | Parse using a custom initial configuration-parseWithConf ∷ MustacheConf → FilePath → Text → Either ParseError AST+parseWithConf ∷ MustacheConf → FilePath → Text → Either ParseError STree parseWithConf = P.runParser parseText ∘ initState  -parseText ∷ Parser AST+parseText ∷ Parser STree parseText = do   (MustacheState { isBeginngingOfLine }) ← getState   if isBeginngingOfLine@@ -166,24 +164,24 @@     else continueLine  -appendTextStack ∷ Conversion t Text ⇒ t → Parser ()-appendTextStack t = modifyState (\s → s { textStack = textStack s ⊕ convert t})+appendStringStack ∷ String → Parser ()+appendStringStack t = modifyState (\s → s { textStack = textStack s ⊕ pack t})  -continueLine ∷ Parser AST+continueLine ∷ Parser STree continueLine = do   (MustacheState { sDelimiters = ( start@(x:_), _ )}) ← getState   let forbidden = x : "\n\r" -  many (noneOf forbidden) ≫= appendTextStack+  many (noneOf forbidden) ≫= appendStringStack -  (try endOfLine ≫= appendTextStack ≫ setIsBeginning True ≫ parseLine)+  (try endOfLine ≫= appendStringStack ≫ setIsBeginning True ≫ parseLine)     <|> (try (string start) ≫ switchOnTag ≫= continueFromTag)     <|> (try eof ≫ finishFile)-    <|> (anyChar ≫= appendTextStack ≫ continueLine)+    <|> (anyChar ≫= appendStringStack . (:[]) ≫ continueLine)  -flushText ∷ Parser AST+flushText ∷ Parser STree flushText = do   s@(MustacheState { textStack = text }) ← getState   putState $ s { textStack = (∅) }@@ -192,7 +190,7 @@               else [TextBlock text]  -finishFile ∷ Parser AST+finishFile ∷ Parser STree finishFile =   getState ≫= \case     (MustacheState {currentSectionName = Nothing}) → flushText@@ -200,14 +198,14 @@       parserFail $ "Unclosed section " ⊕ show name  -parseLine ∷ Parser AST+parseLine ∷ Parser STree parseLine = do   (MustacheState { sDelimiters = ( start, _ ) }) ← getState   initialWhitespace ← many (oneOf " \t")   let handleStandalone = do         tag ← switchOnTag         let continueNoStandalone = do-              appendTextStack initialWhitespace+              appendStringStack initialWhitespace               setIsBeginning False               continueFromTag tag             standaloneEnding = do@@ -224,11 +222,11 @@               continueFromTag tag             ) <|> continueNoStandalone   (try (string start) ≫ handleStandalone)-    <|> (try eof ≫ appendTextStack initialWhitespace ≫ finishFile)-    <|> (appendTextStack initialWhitespace ≫ setIsBeginning False ≫ continueLine)+    <|> (try eof ≫ appendStringStack initialWhitespace ≫ finishFile)+    <|> (appendStringStack initialWhitespace ≫ setIsBeginning False ≫ continueLine)  -continueFromTag ∷ ParseTagRes → Parser AST+continueFromTag ∷ ParseTagRes → Parser STree continueFromTag (SectionBegin inverted name) = do   textNodes ← flushText   state@(MustacheState
src/lib/Text/Mustache/Render.hs view
@@ -66,17 +66,17 @@     substitute' _ (TextBlock t) = t      -- substituting a whole section (entails a focus shift)-    substitute' (Context parents focus@(Array a)) (Section Implicit secAST)+    substitute' (Context parents focus@(Array a)) (Section Implicit secSTree)       | V.null a  = (∅)       | otherwise = flip joinSubstituted a $ \focus' →         let           newContext = Context (focus:parents) focus'         in-          joinSubstituted (substitute' newContext) secAST-    substitute' context@(Context _ (Object _)) (Section Implicit secAST) =-      joinSubstituted (substitute' context) secAST+          joinSubstituted (substitute' newContext) secSTree+    substitute' context@(Context _ (Object _)) (Section Implicit secSTree) =+      joinSubstituted (substitute' context) secSTree     substitute' _ (Section Implicit _) = (∅)-    substitute' context@(Context parents focus) (Section (NamedData secName) secAST) =+    substitute' context@(Context parents focus) (Section (NamedData secName) secSTree) =       case search context secName of         Just arr@(Array arrCont) →           if V.null arrCont@@ -85,26 +85,26 @@               let                 newContext = Context (arr:focus:parents) focus'               in-                joinSubstituted (substitute' newContext) secAST+                joinSubstituted (substitute' newContext) secSTree         Just (Bool False) → (∅)-        Just (Lambda l)   → joinSubstituted (substitute' context) (l context secAST)+        Just (Lambda l)   → joinSubstituted (substitute' context) (l context secSTree)         Just focus'       →           let             newContext = Context (focus:parents) focus'           in-            joinSubstituted (substitute' newContext) secAST+            joinSubstituted (substitute' newContext) secSTree         Nothing → (∅)      -- substituting an inverted section     substitute' _       (InvertedSection  Implicit           _        ) = (∅)-    substitute' context (InvertedSection (NamedData secName) invSecAST) =+    substitute' context (InvertedSection (NamedData secName) invSecSTree) =       case search context secName of         Just (Bool False)         → contents         Just (Array a) | V.null a → contents         Nothing                   → contents         _                         → (∅)       where-        contents = joinSubstituted (substitute' context) invSecAST+        contents = joinSubstituted (substitute' context) invSecSTree      -- substituting a variable     substitute' (Context _ current) (Variable _ Implicit) = toString current@@ -122,7 +122,7 @@         $ HM.lookup pName cPartials  -handleIndent ∷ Maybe Text → AST → AST+handleIndent ∷ Maybe Text → STree → STree handleIndent Nothing ast' = ast' handleIndent (Just indentation) ast' = preface ⊕ content   where
src/lib/Text/Mustache/Types.hs view
@@ -15,7 +15,7 @@ module Text.Mustache.Types   (   -- * Types for the Parser / Template-    AST+    STree   , Template(..)   , Node(..)   , DataIdentifier(..)@@ -24,8 +24,8 @@   , Key   -- ** Converting   , object-  , (~>), (↝), (~=), (⥱), (~~>), (~↝), (~~=), (~⥱)-  , ToMustache, toMustache, toTextBlock, mFromJSON+  , (~>), (↝), (~=), (⥱)+  , ToMustache, toMustache, mFromJSON   -- ** Representation   , Array, Object, Pair   , Context(..)@@ -33,8 +33,6 @@   ) where  -import           Conversion-import           Conversion.Text     () import qualified Data.Aeson          as Aeson import           Data.HashMap.Strict as HM import qualified Data.HashSet        as HS@@ -45,15 +43,15 @@ import qualified Data.Vector         as V import           Prelude.Unicode --- | Abstract syntax tree for a mustache template-type AST = [Node Text]+-- | Syntax tree for a mustache template+type STree = [Node Text]  --- | Basic values composing the AST+-- | Basic values composing the STree data Node α   = TextBlock α-  | Section DataIdentifier AST-  | InvertedSection DataIdentifier AST+  | Section DataIdentifier STree+  | InvertedSection DataIdentifier STree   | Variable Bool DataIdentifier   | Partial (Maybe α) FilePath   deriving (Show, Eq)@@ -78,13 +76,13 @@ data Context α = Context [α] α   deriving (Eq, Show, Ord) --- | Internal value AST+-- | Internal value STree data Value   = Object Object   | Array  Array   | Number Scientific   | String Text-  | Lambda (Context Value → AST → AST)+  | Lambda (Context Value → STree → STree)   | Bool   Bool   | Null @@ -109,15 +107,12 @@ instance ToMustache Value where   toMustache = id -instance {-# OVERLAPPING #-} ToMustache [Char] where+instance ToMustache [Char] where   toMustache = toMustache ∘ pack  instance ToMustache Bool where   toMustache = Bool -instance ToMustache Char where-  toMustache = String ∘ pack ∘ return- instance ToMustache () where   toMustache = const Null @@ -130,65 +125,71 @@ instance ToMustache Scientific where   toMustache = Number -instance {-# OVERLAPPABLE #-} ToMustache ω ⇒ ToMustache [ω] where+instance ToMustache ω ⇒ ToMustache [ω] where   toMustache = Array ∘ V.fromList ∘ fmap toMustache -instance {-# OVERLAPPING #-} ToMustache (V.Vector Value) where-  toMustache = Array- instance ToMustache ω ⇒ ToMustache (V.Vector ω) where   toMustache = toMustache ∘ fmap toMustache -instance {-# OVERLAPPING #-} ToMustache (HM.HashMap Text Value) where-  toMustache = Object+instance (ToMustache ω) ⇒ ToMustache (Map.Map Text ω) where+  toMustache = mapInstanceHelper id -instance (Conversion θ Text, ToMustache ω) ⇒ ToMustache (Map.Map θ ω) where-  toMustache =-    toMustache-    ∘ Map.foldrWithKey-      (\k → HM.insert (convert k ∷ Text) ∘ toMustache)-      HM.empty+instance (ToMustache ω) ⇒ ToMustache (Map.Map LT.Text ω) where+  toMustache = mapInstanceHelper LT.toStrict +instance (ToMustache ω) ⇒ ToMustache (Map.Map String ω) where+  toMustache = mapInstanceHelper pack++mapInstanceHelper :: ToMustache v => (a -> Text) -> Map.Map a v -> Value+mapInstanceHelper conv =+  toMustache+  ∘ Map.foldrWithKey+    (\k → HM.insert (conv k) ∘ toMustache)+    HM.empty+ instance ToMustache ω ⇒ ToMustache (HM.HashMap Text ω) where   toMustache = toMustache ∘ fmap toMustache -instance {-# OVERLAPPABLE #-} (Conversion θ Text, ToMustache ω) ⇒ ToMustache (HM.HashMap θ ω) where-  toMustache =-    toMustache-    ∘ HM.foldrWithKey-      (\k → HM.insert (convert k ∷ Text) ∘ toMustache)-      HM.empty+instance ToMustache ω ⇒ ToMustache (HM.HashMap LT.Text ω) where+  toMustache = hashMapInstanceHelper LT.toStrict -instance ToMustache (Context Value → AST → AST) where+instance ToMustache ω ⇒ ToMustache (HM.HashMap String ω) where+  toMustache = hashMapInstanceHelper pack++hashMapInstanceHelper :: ToMustache v => (a -> Text) -> HM.HashMap a v -> Value+hashMapInstanceHelper conv =+  toMustache+  ∘ HM.foldrWithKey+    (\k → HM.insert (conv k) ∘ toMustache)+    HM.empty++instance ToMustache (Context Value → STree → STree) where   toMustache = Lambda -instance ToMustache (Context Value → AST → Text) where-  toMustache f = toMustache wrapper-    where-      wrapper ∷ Context Value → AST → AST-      wrapper c lAST = return ∘ TextBlock $ f c lAST+instance ToMustache (Context Value → STree → Text) where+  toMustache = lambdaInstanceHelper id -instance {-# OVERLAPPABLE #-} Conversion θ Text-  ⇒ ToMustache (Context Value → AST → θ) where-  toMustache f = toMustache wrapper-    where-      wrapper :: Context Value → AST → Text-      wrapper c = convert ∘ f c+instance ToMustache (Context Value → STree → LT.Text) where+  toMustache = lambdaInstanceHelper LT.toStrict -instance ToMustache (AST → AST) where-  toMustache f = toMustache (const f ∷ Context Value → AST → AST)+instance ToMustache (Context Value → STree → String) where+  toMustache = lambdaInstanceHelper pack -instance ToMustache (AST → Text) where+lambdaInstanceHelper :: (a -> Text) -> (Context Value -> STree -> a) -> Value+lambdaInstanceHelper conv f = Lambda wrapper+  where+    wrapper ∷ Context Value → STree → STree+    wrapper c lSTree = return ∘ TextBlock $ conv $ f c lSTree++instance ToMustache (STree → STree) where+  toMustache f = toMustache (const f ∷ Context Value → STree → STree)++instance ToMustache (STree → Text) where   toMustache f = toMustache wrapper     where-      wrapper ∷ Context Value → AST → AST+      wrapper ∷ Context Value → STree → STree       wrapper _ = (return ∘ TextBlock) ∘ f --- TODO Add these back in when you find a way to do so on earlier GHC versions--- or you drop support for GHC < 7.10--- instance {-# OVERLAPPABLE #-} Conversion θ Text ⇒ ToMustache (AST → θ) where---   toMustache f = toMustache (convert ∘ f ∷ AST → Text)- instance ToMustache Aeson.Value where   toMustache (Aeson.Object o) = Object $ fmap toMustache o   toMustache (Aeson.Array  a) = Array $ fmap toMustache a@@ -344,39 +345,6 @@ infixr 8 ⥱  --- | Conceptually similar to '~>' but uses arbitrary String-likes as keys.-(~~>) ∷ (Conversion ζ Text, ToMustache ω) ⇒ ζ → ω → Pair-(~~>) = (~>) ∘ convert-{-# INLINEABLE (~~>) #-}-infixr 8 ~~>----- | Unicde version of '~~>'-(~↝) ∷ (Conversion ζ Text, ToMustache ω) ⇒ ζ → ω → Pair-(~↝) = (~~>)-{-# INLINEABLE (~↝) #-}-infixr 8 ~↝----- | Conceptually similar to '~=' but uses arbitrary String-likes as keys.-(~~=) ∷ (Conversion ζ Text, Aeson.ToJSON ι) ⇒ ζ → ι → Pair-(~~=) = (~=) ∘ convert-{-# INLINEABLE (~~=) #-}-infixr 8 ~~=----- | Unicode version of '~~='-(~⥱) ∷ (Conversion ζ Text, Aeson.ToJSON ι) ⇒ ζ → ι → Pair-(~⥱) = (~~=)-{-# INLINEABLE (~⥱) #-}-infixr 8 ~⥱----- | Converts arbitrary String-likes to Values-toTextBlock ∷ Conversion ζ Text ⇒ ζ → Value-toTextBlock = String ∘ convert-- -- | Converts a value that can be represented as JSON to a Value. mFromJSON ∷ Aeson.ToJSON ι ⇒ ι → Value mFromJSON = toMustache ∘ Aeson.toJSON@@ -393,6 +361,6 @@ -} data Template = Template   { name     ∷ String-  , ast      ∷ AST+  , ast      ∷ STree   , partials ∷ TemplateCache   } deriving (Show)
test/integration/Language.hs view
@@ -26,14 +26,14 @@ import           Text.Mustache.Parser import           Text.Mustache.Types --- langspecDir = "spec-1.1.3"-langspecDir = "andrewthad-spec-786e4ac"-specDir = "specs"-releaseFile = "langspec.tar.gz"--- releaseURL = "https://codeload.github.com/mustache/spec/tar.gz/v1.1.3"-releaseURL = "https://codeload.github.com/andrewthad/spec/legacy.tar.gz/add_list_context_check" +-- (langspecDir, specDir, releaseFile, releaseURL)+langspecs =+  [ ("andrewthad-spec-786e4ac", "specs", "langspec-pull.tar.gz", "https://codeload.github.com/andrewthad/spec/legacy.tar.gz/add_list_context_check")+  , ("spec-1.1.3", "specs", "langspec-off.tar.gz", "https://codeload.github.com/mustache/spec/tar.gz/v1.1.3")+  ] + data LangSpecFile = LangSpecFile   { overview :: String   , tests    :: [LangSpecTest]@@ -72,14 +72,13 @@ (&) = flip ($)  -getOfficialSpecRelease ∷ FilePath → IO ()-getOfficialSpecRelease tempdir = do+getOfficialSpecRelease ∷ FilePath -> FilePath -> FilePath -> FilePath → IO ()+getOfficialSpecRelease tempdir langspecDir releaseFile releaseURL  = do   currentDirectory ← getCurrentDirectory   setCurrentDirectory tempdir   createDirectory langspecDir   callProcess "curl" [releaseURL, "-o", releaseFile]   callProcess "tar" ["-xf", releaseFile]-  getDirectoryContents "." >>= print   setCurrentDirectory currentDirectory  @@ -117,6 +116,8 @@     withSystemTempDirectory       "mustache-test-resources"       $ \tempdir → do-        getOfficialSpecRelease tempdir+        for_ langspecs $ \(langspecDir, _, releaseFile, releaseURL) ->+          getOfficialSpecRelease tempdir langspecDir releaseFile releaseURL         hspec $-          testOfficialLangSpec (tempdir </> langspecDir </> specDir)+          for_ langspecs $ \(langspecDir, specDir, _, _) ->+            testOfficialLangSpec (tempdir </> langspecDir </> specDir)