simple-templates 0.8.0.0 → 0.8.0.1
raw patch · 3 files changed
+201/−1 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Web.Simple.Templates.Types: call :: Function -> [Value] -> Value
- Web.Simple.Templates.Types: instance (FromJSON a1, FromJSON a2) => ToFunction (a1 -> a2 -> Value)
- Web.Simple.Templates.Types: instance (FromJSON a1, FromJSON a2, FromJSON a3) => ToFunction (a1 -> a2 -> a3 -> Value)
- Web.Simple.Templates.Types: instance (FromJSON a1, FromJSON a2, FromJSON a3, FromJSON a4) => ToFunction (a1 -> a2 -> a3 -> a4 -> Value)
- Web.Simple.Templates.Types: instance (FromJSON a1, FromJSON a2, FromJSON a3, FromJSON a4, FromJSON a5) => ToFunction (a1 -> a2 -> a3 -> a4 -> a5 -> Value)
- Web.Simple.Templates.Types: instance (FromJSON a1, FromJSON a2, FromJSON a3, FromJSON a4, FromJSON a5, FromJSON a6) => ToFunction (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> Value)
- Web.Simple.Templates.Types: instance (FromJSON a1, FromJSON a2, FromJSON a3, FromJSON a4, FromJSON a5, FromJSON a6, FromJSON a7) => ToFunction (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> Value)
- Web.Simple.Templates.Types: instance (FromJSON a1, FromJSON a2, FromJSON a3, FromJSON a4, FromJSON a5, FromJSON a6, FromJSON a7, FromJSON a8) => ToFunction (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> Value)
- Web.Simple.Templates.Types: instance Eq AST
- Web.Simple.Templates.Types: instance FromJSON a => ToFunction (a -> Value)
- Web.Simple.Templates.Types: instance Monoid Template
- Web.Simple.Templates.Types: instance Show AST
- Web.Simple.Templates.Types: renderTemplate :: Template -> FunctionMap -> Value -> Text
+ Web.Simple.Templates.Types: [call] :: Function -> [Value] -> Value
+ Web.Simple.Templates.Types: [renderTemplate] :: Template -> FunctionMap -> Value -> Text
+ Web.Simple.Templates.Types: instance (Data.Aeson.Types.FromJSON.FromJSON a1, Data.Aeson.Types.FromJSON.FromJSON a2) => Web.Simple.Templates.Types.ToFunction (a1 -> a2 -> Data.Aeson.Types.Internal.Value)
+ Web.Simple.Templates.Types: instance (Data.Aeson.Types.FromJSON.FromJSON a1, Data.Aeson.Types.FromJSON.FromJSON a2, Data.Aeson.Types.FromJSON.FromJSON a3) => Web.Simple.Templates.Types.ToFunction (a1 -> a2 -> a3 -> Data.Aeson.Types.Internal.Value)
+ Web.Simple.Templates.Types: instance (Data.Aeson.Types.FromJSON.FromJSON a1, Data.Aeson.Types.FromJSON.FromJSON a2, Data.Aeson.Types.FromJSON.FromJSON a3, Data.Aeson.Types.FromJSON.FromJSON a4) => Web.Simple.Templates.Types.ToFunction (a1 -> a2 -> a3 -> a4 -> Data.Aeson.Types.Internal.Value)
+ Web.Simple.Templates.Types: instance (Data.Aeson.Types.FromJSON.FromJSON a1, Data.Aeson.Types.FromJSON.FromJSON a2, Data.Aeson.Types.FromJSON.FromJSON a3, Data.Aeson.Types.FromJSON.FromJSON a4, Data.Aeson.Types.FromJSON.FromJSON a5) => Web.Simple.Templates.Types.ToFunction (a1 -> a2 -> a3 -> a4 -> a5 -> Data.Aeson.Types.Internal.Value)
+ Web.Simple.Templates.Types: instance (Data.Aeson.Types.FromJSON.FromJSON a1, Data.Aeson.Types.FromJSON.FromJSON a2, Data.Aeson.Types.FromJSON.FromJSON a3, Data.Aeson.Types.FromJSON.FromJSON a4, Data.Aeson.Types.FromJSON.FromJSON a5, Data.Aeson.Types.FromJSON.FromJSON a6) => Web.Simple.Templates.Types.ToFunction (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> Data.Aeson.Types.Internal.Value)
+ Web.Simple.Templates.Types: instance (Data.Aeson.Types.FromJSON.FromJSON a1, Data.Aeson.Types.FromJSON.FromJSON a2, Data.Aeson.Types.FromJSON.FromJSON a3, Data.Aeson.Types.FromJSON.FromJSON a4, Data.Aeson.Types.FromJSON.FromJSON a5, Data.Aeson.Types.FromJSON.FromJSON a6, Data.Aeson.Types.FromJSON.FromJSON a7) => Web.Simple.Templates.Types.ToFunction (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> Data.Aeson.Types.Internal.Value)
+ Web.Simple.Templates.Types: instance (Data.Aeson.Types.FromJSON.FromJSON a1, Data.Aeson.Types.FromJSON.FromJSON a2, Data.Aeson.Types.FromJSON.FromJSON a3, Data.Aeson.Types.FromJSON.FromJSON a4, Data.Aeson.Types.FromJSON.FromJSON a5, Data.Aeson.Types.FromJSON.FromJSON a6, Data.Aeson.Types.FromJSON.FromJSON a7, Data.Aeson.Types.FromJSON.FromJSON a8) => Web.Simple.Templates.Types.ToFunction (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> Data.Aeson.Types.Internal.Value)
+ Web.Simple.Templates.Types: instance Data.Aeson.Types.FromJSON.FromJSON a => Web.Simple.Templates.Types.ToFunction (a -> Data.Aeson.Types.Internal.Value)
+ Web.Simple.Templates.Types: instance GHC.Base.Monoid Web.Simple.Templates.Types.Template
+ Web.Simple.Templates.Types: instance GHC.Classes.Eq Web.Simple.Templates.Types.AST
+ Web.Simple.Templates.Types: instance GHC.Show.Show Web.Simple.Templates.Types.AST
Files
- simple-templates.cabal +4/−1
- test/Web/Simple/Templates/LanguageSpec.hs +18/−0
- test/Web/Simple/Templates/ParserSpec.hs +179/−0
simple-templates.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: simple-templates-version: 0.8.0.0+version: 0.8.0.1 synopsis: A basic template language for the Simple web framework description: A basic template language for the Simple web framework. The language supports@@ -51,6 +51,9 @@ , scientific , simple-templates , vector+ other-modules:+ Web.Simple.Templates.LanguageSpec+ , Web.Simple.Templates.ParserSpec default-language: Haskell2010 source-repository head
+ test/Web/Simple/Templates/LanguageSpec.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE OverloadedStrings #-}+module Web.Simple.Templates.LanguageSpec where++import Data.Aeson+import Test.HUnit+import Test.Hspec+import Web.Simple.Templates.Language++spec :: Spec+spec = describe "Web.Simple.Templates.Language" $ do+ describe "valueToText" $ do+ it "renders whole number as decimal" $ do+ let val = Number 4563+ assertEqual "" "4563" (valueToText val)+ it "renders rational number with decimal point" $ do+ let val = Number 3432.5+ assertEqual "" "3432.5" (valueToText val)+
+ test/Web/Simple/Templates/ParserSpec.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE OverloadedStrings #-}+module Web.Simple.Templates.ParserSpec where++import Data.Aeson+import qualified Data.Attoparsec.Text as A+import Data.Maybe+import Data.Scientific+import qualified Data.Vector as V+import Test.HUnit+import Test.Hspec+import Web.Simple.Templates.Parser+import Web.Simple.Templates.Types++spec :: Spec+spec = describe "Web.Simple.Templates.Parser" $ do+ describe "pEscapedDollar" $ do+ it "reads $$ as escaped dollar" $ do+ let parsedStr = A.parseOnly pEscapedDollar "$$"+ assertEqual "" (Right "$") parsedStr+ it "fails on single $" $ do+ let parsedStr = A.maybeResult $ A.parse pEscapedDollar "$ "+ assert $ isNothing parsedStr+ describe "pRaw" $ do+ it "fails on dollar-sign" $ do+ let parsedStr = A.maybeResult $ A.parse pRaw "$blor doop"+ assert $ isNothing parsedStr+ it "reads non-dollar-sign text" $ do+ let parsedStr = A.parseOnly pRaw "blor doop"+ assertEqual "" (Right $ ASTLiteral (String "blor doop")) parsedStr+ it "reads text until dollar sign" $ do+ let parsedStr = A.parseOnly pRaw "blor doop$"+ assertEqual "" (Right $ ASTLiteral (String "blor doop")) parsedStr+ it "reads text with escaped dollar sing" $ do+ let parsedStr = A.parseOnly pRaw "you owe me $$4"+ assertEqual "" (Right $ ASTLiteral (String "you owe me $4")) parsedStr++ describe "pLiteral" $ do+ it "reads a number" $ do+ let parsedStr = A.parseOnly pLiteral "12345.66"+ assertEqual "" (Right $ fromLiteral (12345.66 :: Scientific)) parsedStr+ it "reads a string" $ do+ let parsedStr = A.parseOnly pLiteral "\"hello\""+ assertEqual "" (Right $ fromLiteral ("hello" :: String)) parsedStr+ it "reads a string with escaped quote" $ do+ let parsedStr = A.parseOnly pLiteral "\"hello \\ \\\"world\""+ assertEqual "" (Right $ fromLiteral ("hello \\ \"world" :: String))+ parsedStr+ it "reads array" $ do+ let parsedStr = A.parseOnly pLiteral "[1]"+ let expected = ASTArray $ V.fromList [fromLiteral (1 :: Int)]+ assertEqual "" (Right expected) parsedStr+ it "reads 'true' as boolean" $ do+ let parsedStr = A.parseOnly pLiteral "true"+ assertEqual "" (Right $ fromLiteral True) parsedStr+ it "reads 'false' as boolean" $ do+ let parsedStr = A.parseOnly pLiteral "false"+ assertEqual "" (Right $ fromLiteral False) parsedStr+ it "reads null as null value" $ do+ let parsedStr = A.parseOnly pLiteral "null"+ assertEqual "" (Right $ ASTLiteral Null) parsedStr++ describe "pArray" $ do+ it "matches array with literals" $ do+ let parsedStr = A.parseOnly pArray "[1 ,2 ,3 , 4]"+ let expected = ASTArray $ V.fromList $ map fromLiteral+ [ 1 :: Int+ , 2+ , 3+ , 4 ]+ assertEqual "" (Right expected) parsedStr+ it "matches array with mixed literals" $ do+ let parsedStr = A.parseOnly pArray "[1,\"hello\"]"+ let expected = ASTArray $ V.fromList+ [ fromLiteral (1 :: Int)+ , fromLiteral ("hello" :: String)]+ assertEqual "" (Right expected) parsedStr++ describe "pIdentifier" $ do+ it "matches alphunumeric string starting with a letter" $ do+ let parsedStr = A.parseOnly pIdentifier "l33Th8x0r"+ assertEqual "" (Right "l33Th8x0r") parsedStr+ it "must start with a letter" $ do+ let parsedStr = A.maybeResult $ A.parse pIdentifier "3rd"+ assert $ isNothing parsedStr+ it "allows underscores and dashes" $ do+ let parsedStr = A.parseOnly pIdentifier "l33Th-8x_r"+ assertEqual "" (Right "l33Th-8x_r") parsedStr++ describe "pIndex" $ do+ it "matches an variable name on the left and an identifier on the right" $+ do+ let parsedStr = A.parseOnly pIndex "foo.bar.baz"+ assertEqual "" (Right $ ASTIndex (ASTVar "foo") ["bar", "baz"])+ parsedStr++ describe "pVar" $ do+ it "matches an identifier" $ do+ let parsedStr = A.parseOnly pVar "foo"+ assertEqual "" (Right $ ASTVar "foo") parsedStr++ describe "pFunc" $ do+ it "matches no argument function call" $ do+ let parsedStr = A.parseOnly pFunc "foo()"+ assertEqual "" (Right $ ASTFunc "foo" []) parsedStr+ it "matches function call with one argument" $ do+ let parsedStr = A.parseOnly pFunc "foo(1234)"+ assertEqual "" (Right $ ASTFunc "foo" [ASTLiteral $ Number 1234])+ parsedStr+ it "matches function call with many arguments" $ do+ let parsedStr = A.parseOnly pFunc "foo(1234, \"hello\", 5432)"+ assertEqual "" (Right $ ASTFunc "foo" [ ASTLiteral $ Number 1234+ , ASTLiteral $ String "hello"+ , ASTLiteral $ Number 5432])+ parsedStr+ it "matches nested function calls" $ do+ let parsedStr = A.parseOnly pFunc "foo(bar())"+ assertEqual "" (Right $ ASTFunc "foo" [ASTFunc "bar" []]) parsedStr+ it "matches function calls with index" $ do+ let parsedStr = A.parseOnly pFunc "foo(bar.baz)"+ assertEqual ""+ (Right $ ASTFunc "foo" [ASTIndex (ASTVar "bar") ["baz"]])+ parsedStr++ describe "pIf" $ do+ it "matches if with no false branch" $ do+ let parsedStr = A.parseOnly pIf "if(1234)$hello world$endif"+ assertEqual "" (Right $+ ASTIf (ASTLiteral $ Number 1234)+ (ASTRoot [ASTLiteral $ String "hello world"])+ Nothing)+ parsedStr+ it "matches if with nested statement in true branch" $ do+ let parsedStr = A.parseOnly pIf "if(1234)$hello $123$ world$endif"+ assertEqual "" (Right $+ ASTIf (ASTLiteral $ Number 1234)+ (ASTRoot [ ASTLiteral $ String "hello "+ , ASTLiteral $ Number 123+ , ASTLiteral $ String " world"])+ Nothing)+ parsedStr+ it "matches with a space after" $ do+ let parsedStr = A.parseOnly pIf "if 1234$hello world$endif"+ assertEqual "" (Right $+ ASTIf (ASTLiteral $ Number 1234)+ (ASTRoot [ASTLiteral $ String "hello world"])+ Nothing)+ parsedStr+ it "matches with if/else" $ do+ let parsedStr = A.parseOnly pIf "if(true)$$else$$endif"+ assertEqual "" (Right $+ ASTIf (ASTLiteral $ Bool True)+ (ASTRoot [])+ (Just $ ASTRoot []))+ parsedStr++ describe "pFor" $ do+ it "matches basic for loop" $ do+ let parsedStr = A.parseOnly pFor "for(i in [])$$i$$endfor"+ assertEqual "" (Right $+ ASTFor Nothing "i" (ASTArray (V.fromList []))+ (ASTRoot [ASTVar "i"]) Nothing) parsedStr+ it "matches with space after for" $ do+ let parsedStr = A.parseOnly pFor "for i in []$$i$$endfor"+ assertEqual "" (Right $+ ASTFor Nothing "i" (ASTArray (V.fromList []))+ (ASTRoot [ASTVar "i"]) Nothing) parsedStr+ it "matches with separator" $ do+ let parsedStr = A.parseOnly pFor "for(i in [])$$i$$sep$hello$endfor"+ assertEqual "" (Right $+ ASTFor Nothing "i" (ASTArray (V.fromList []))+ (ASTRoot [ASTVar "i"])+ (Just $ ASTRoot [ASTLiteral $ String "hello"]))+ parsedStr+ it "matches for loop with index" $ do+ let parsedStr = A.parseOnly pFor "for(i,v in [])$$i$$endfor"+ assertEqual "" (Right $+ ASTFor (Just "i") "v" (ASTArray (V.fromList []))+ (ASTRoot [ASTVar "i"]) Nothing) parsedStr+