packages feed

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 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+