HSmarty 0.4.0 → 0.4.1
raw patch · 10 files changed
+83/−14 lines, 10 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Text.HSmarty.Types: [c_assign] :: Capture -> Maybe Text
- Text.HSmarty.Types: Capture :: Text -> [SmartyStmt] -> Capture
+ Text.HSmarty.Types: Capture :: Text -> Maybe Text -> [SmartyStmt] -> Capture
Files
- HSmarty.cabal +7/−3
- data/testCapture.tpl +1/−0
- data/testCapture.txt +1/−0
- src/Text/HSmarty/Parser/Smarty.hs +5/−4
- src/Text/HSmarty/Parser/Util.hs +4/−4
- src/Text/HSmarty/Render/Engine.hs +27/−3
- src/Text/HSmarty/Types.hs +1/−0
- test/Tests.hs +1/−0
- test/Text/HSmarty/Parser/SmartyTest.hs +8/−0
- test/Text/HSmarty/Render/EngineTest.hs +28/−0
HSmarty.cabal view
@@ -1,5 +1,5 @@ name: HSmarty-version: 0.4.0+version: 0.4.1 synopsis: Small template engine description: Haskell implementation of a subset of the PHP-Smarty template language Homepage: https://github.com/agrafix/HSmarty@@ -13,7 +13,9 @@ build-type: Simple cabal-version: >=1.10 data-dir: data-data-files: test.tpl+data-files: test.tpl,+ testCapture.tpl,+ testCapture.txt tested-with: GHC==8.8.4 Library@@ -42,7 +44,9 @@ Test-Suite TestHSmarty hs-source-dirs: test- other-modules: Text.HSmarty.Parser.SmartyTest, Paths_HSmarty+ other-modules: Text.HSmarty.Parser.SmartyTest, + Text.HSmarty.Render.EngineTest, + Paths_HSmarty Type: exitcode-stdio-1.0 Main-Is: Tests.hs Ghc-Options: -Wall
+ data/testCapture.tpl view
@@ -0,0 +1,1 @@+{capture name='var' assign=var}Hello{/capture}{$var}/{$smarty.capture.var}
+ data/testCapture.txt view
@@ -0,0 +1,1 @@+Hello/Hello
src/Text/HSmarty/Parser/Smarty.hs view
@@ -22,7 +22,7 @@ pRoot :: Parser [SmartyStmt] pRoot =- (stripSpace $ many1 pStmt) <* endOfInput+ stripSpace (many1 pStmt) <* endOfInput pStmt :: Parser SmartyStmt pStmt =@@ -34,7 +34,7 @@ SmartyScope <$> pScope <|> SmartyFun <$> pFunDef <|> braced (char '{') (char '}') (SmartyPrint <$> pExpr <*> many pPrintDirective) <|>- SmartyText <$> (takeWhile1 (/='{'))+ SmartyText <$> takeWhile1 (/='{') pPrintDirective :: Parser PrintDirective pPrintDirective =@@ -113,8 +113,9 @@ pCapture :: Parser Capture pCapture = Capture- <$> ((string "{capture name=" *> space_) *> stringP <* char '}')- <*> (many pStmt <* pClose "capture")+ <$> ((string "{capture name=" *> optSpace_) *> stringP)+ <*> optional (optSpace_ *> string "assign=" *> pName)+ <*> (optSpace_ *> char '}' *> many pStmt <* pClose "capture") pFunDef :: Parser FunctionDef pFunDef =
src/Text/HSmarty/Parser/Util.hs view
@@ -16,8 +16,8 @@ boolP :: Parser Bool boolP =- const True <$> string "true" <|>- const False <$> string "false"+ True <$ string "true" <|>+ False <$ string "false" stringP :: Parser T.Text stringP = (quotedString '"' <|> quotedString '\'') <?> "stringP"@@ -51,11 +51,11 @@ where decode c r = r <$ char c unicodeSeq :: Parser Char-unicodeSeq = char 'u' *> (intToChar <$> decodeHexUnsafe <$> count 4 hexDigit)+unicodeSeq = char 'u' *> (intToChar . decodeHexUnsafe <$> count 4 hexDigit) where intToChar = toEnum . fromIntegral decodeHexUnsafe :: String -> Integer-decodeHexUnsafe hex = (head $ map fst $ readHex hex)+decodeHexUnsafe hex = head $ map fst $ readHex hex hexDigitUpper :: Parser Char hexDigitUpper = satisfy (inClass "0-9A-F")
src/Text/HSmarty/Render/Engine.hs view
@@ -66,10 +66,28 @@ = SmartyError { unSmartyError :: T.Text } deriving (Show, Eq) +wrapSmartyCapture :: A.Value -> PropMap -> TemplateVar+wrapSmartyCapture x = TemplateVar (A.Object $ HM.singleton "capture" x)++updateSmartyCapture :: T.Text -> A.Value -> HM.HashMap T.Text TemplateVar -> HM.HashMap T.Text TemplateVar+updateSmartyCapture key value hm =+ let updatedVal =+ case HM.lookup "smarty" hm of+ Nothing -> wrapSmartyCapture (A.Object $ HM.singleton key value) mempty+ Just (TemplateVar existingCtx oldProps) -> + case existingCtx of+ A.Object oldContext -> + wrapSmartyCapture (A.Object $ HM.insert key value oldContext) oldProps+ _ -> error "Smarty capture context is always a map!"+ in HM.insert "smarty" updatedVal hm++rootMap :: HM.HashMap T.Text TemplateVar+rootMap = HM.singleton "smarty" (wrapSmartyCapture (A.Object mempty) mempty)+ mkEnv :: ParamMap -> SmartyCtx -> Env mkEnv pm ctx = Env- { e_var = HM.map (\init' -> TemplateVar init' HM.empty) pm+ { e_var = rootMap <> HM.map (\init' -> TemplateVar init' HM.empty) pm , e_fun = HM.empty , e_ctx = ctx }@@ -167,8 +185,14 @@ pure (env { e_fun = fun }, T.empty) evalStmt env (SmartyCapture cap) = do (_, body) <- seqStmts env (c_stmts cap)- let eVars =- HM.insert (c_name cap) (TemplateVar (A.String body) mempty) (e_var env)+ let varBody = TemplateVar (A.String body) mempty+ capture =+ updateSmartyCapture (c_name cap) (A.String body)+ assignment = + case c_assign cap of+ Nothing -> mempty+ Just x -> HM.insert x varBody+ eVars = capture . assignment $ e_var env pure (env { e_var = eVars }, T.empty) evalStmt env (SmartyLet l) = do r <- evalExpr env (l_expr l)
src/Text/HSmarty/Types.hs view
@@ -78,6 +78,7 @@ data Capture = Capture { c_name :: T.Text+ , c_assign :: Maybe T.Text , c_stmts :: [SmartyStmt] } deriving (Show, Eq)
test/Tests.hs view
@@ -3,6 +3,7 @@ import Test.Framework import {-@ HTF_TESTS @-} Text.HSmarty.Parser.SmartyTest+import {-@ HTF_TESTS @-} Text.HSmarty.Render.EngineTest main :: IO () main = htfMain htf_importedTests
test/Text/HSmarty/Parser/SmartyTest.hs view
@@ -48,6 +48,14 @@ do parserTest pVar "$hallo.sub@prop" (Variable "hallo" ["sub"] Nothing (Just "prop")) parserTest pVar "$hallo.foo_bar" (Variable "hallo" ["foo_bar"] Nothing Nothing) +test_capture :: IO ()+test_capture =+ do parserTest pCapture "{capture name='foo'}Bye{/capture}" expect1+ parserTest pCapture "{capture name='foo' assign=bar}Bye{/capture}" expect2+ where+ expect1 = Capture "foo" Nothing [SmartyText "Bye"]+ expect2 = Capture "foo" (Just "bar") [SmartyText "Bye"]+ test_if :: IO () test_if = do parserTest pIf "{if $var@last}Bye{/if}" expect
+ test/Text/HSmarty/Render/EngineTest.hs view
@@ -0,0 +1,28 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+module Text.HSmarty.Render.EngineTest where++import Paths_HSmarty+import Test.Framework+import Text.HSmarty+import qualified Data.Text as T+import qualified Data.Text.IO as T++readDataFile :: String -> IO T.Text+readDataFile name =+ do fp <- getDataFileName name+ T.readFile fp++engineTest :: FilePath -> FilePath -> IO ()+engineTest inputFile outputFile =+ do testInputFile <- getDataFileName inputFile+ expectedOutput <- readDataFile outputFile+ ctx <- prepareTemplate testInputFile+ case applyTemplate testInputFile ctx mempty of+ Left errMsg -> fail (show errMsg)+ Right ok -> assertEqual ok expectedOutput++test_capture :: IO ()+test_capture =+ engineTest "testCapture.tpl" "testCapture.txt"