hastache 0.1.4 → 0.1.5
raw patch · 4 files changed
+140/−54 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Text.Hastache: MuNothing :: MuType m
Files
- Text/Hastache.hs +45/−33
- Text/Hastache/Context.hs +23/−17
- hastache.cabal +1/−1
- tests/test.hs +71/−3
Text/Hastache.hs view
@@ -29,23 +29,25 @@ , decodeStrLBS ) where -import Prelude hiding (putStrLn, readFile, length, drop, tail, dropWhile, - elem, head, last, reverse, take, span)-import Data.ByteString hiding (map, foldl1)-import qualified Data.ByteString.Lazy as LZ-import qualified Codec.Binary.UTF8.String as SU+import Control.Monad (guard, when)+import Control.Monad.Trans (lift) import Control.Monad.Writer.Lazy (tell, liftIO, MonadIO, execWriterT, MonadWriter)+import Data.ByteString hiding (map, foldl1) import Data.Char (ord)+import Data.Int+import Data.Maybe (isJust) import Data.Word-import Control.Monad (guard, when)-import System.FilePath (combine)+import Prelude hiding (putStrLn, readFile, length, drop, tail, dropWhile, elem,+ head, last, reverse, take, span) import System.Directory (doesFileExist)-import Control.Monad.Trans (lift)-import Data.Int+import System.FilePath (combine)++import qualified Codec.Binary.UTF8.String as SU+import qualified Data.ByteString.Lazy as LZ import qualified Data.Text as Text import qualified Data.Text.Lazy as LText-import Data.Maybe (isJust)+import qualified Data.List as List (~>) :: a -> (a -> b) -> b x ~> f = f $ x@@ -105,14 +107,16 @@ MuList [MuContext m] | MuBool Bool | MuLambda (ByteString -> ByteString) |- MuLambdaM (ByteString -> m ByteString)- + MuLambdaM (ByteString -> m ByteString) |+ MuNothing+ instance Show (MuType m) where show (MuVariable a) = "MuVariable " ++ show a show (MuList _) = "MuList [..]" show (MuBool v) = "MuBool " ++ show v show (MuLambda _) = "MuLambda <..>" show (MuLambdaM _) = "MuLambdaM <..>"+ show MuNothing = "MuNothing" data MuConfig = MuConfig { muEscapeFunc :: LZ.ByteString -> LZ.ByteString, @@ -142,6 +146,9 @@ ord8 :: Char -> Word8 ord8 = fromIntegral . ord +isMuNothing MuNothing = True+isMuNothing _ = False+ -- | Escape HTML symbols htmlEscape :: LZ.ByteString -> LZ.ByteString htmlEscape str = LZ.unpack str ~> proc ~> LZ.pack@@ -194,12 +201,14 @@ toLBS :: ByteString -> LZ.ByteString toLBS v = LZ.fromChunks [v] -readVar context name = do+readVar [] _ = LZ.empty+readVar (context:parentCtx) name = case context name of MuVariable a -> toLByteString a MuBool a -> show a ~> encodeStr ~> toLBS+ MuNothing -> readVar parentCtx name _ -> LZ.empty- + findCloseSection :: ByteString -> ByteString -> ByteString -> ByteString -> Maybe (ByteString, ByteString) findCloseSection str name otag ctag = do@@ -218,22 +227,22 @@ tellBS :: (MonadWriter LZ.ByteString m) => ByteString -> m () tellBS str = toLBS str ~> tell -processBlock str context otag ctag conf = do+processBlock str contexts otag ctag conf = do case findBlock str otag ctag of Just (pre, symb, inTag, afterClose) -> do tellBS pre- renderBlock context symb inTag afterClose + renderBlock contexts symb inTag afterClose otag ctag conf Nothing -> do tellBS str return () -renderBlock context symb inTag afterClose otag ctag conf+renderBlock contexts symb inTag afterClose otag ctag conf -- comment | symb == ord8 '!' = next afterClose -- unescape variable | symb == ord8 '&' || (symb == ord8 '{' && otag == defOTag) = do- readVar context (tail inTag ~> trimAll) ~> tell+ readVar contexts (tail inTag ~> trimAll) ~> tell next afterClose -- section. inverted section | symb == ord8 '#' || symb == ord8 '^' = @@ -251,38 +260,41 @@ if ord8 '\n' `elem` sectionContent then dropNL afterSection' else afterSection'+ tlInTag = tail inTag+ readContext = map ($ tlInTag) contexts + ~> List.find (not . isMuNothing) in do- case context (tail inTag) of- MuList [] -> + case readContext of+ Just (MuList []) -> if normalSection then do next afterSection else do processBlock sectionContent- context otag ctag conf+ contexts otag ctag conf next afterSection- MuList b -> + Just (MuList b) -> if normalSection then do mapM_ (\c -> processBlock sectionContent- c otag ctag conf) b+ (c:contexts) otag ctag conf) b next afterSection else do next afterSection- MuBool True -> + Just (MuBool True) -> if normalSection then do processBlock sectionContent- context otag ctag conf+ contexts otag ctag conf next afterSection else do next afterSection- MuBool False -> + Just (MuBool False) -> if normalSection then do next afterSection else do processBlock sectionContent- context otag ctag conf+ contexts otag ctag conf next afterSection- MuLambda func -> + Just (MuLambda func) -> if normalSection then do func sectionContent ~> tellBS next afterSection else do next afterSection- MuLambdaM func -> + Just (MuLambdaM func) -> if normalSection then do res <- lift (func sectionContent) tellBS res@@ -304,7 +316,7 @@ case getDelimiter of Nothing -> next afterClose Just (newOTag, newCTag) -> - processBlock (trim' afterClose) context + processBlock (trim' afterClose) contexts newOTag newCTag conf -- partials | symb == ord8 '>' =@@ -325,10 +337,10 @@ next (trim' afterClose) -- variable | otherwise = do- readVar context (trimAll inTag) ~> muEscapeFunc conf ~> tell+ readVar contexts (trimAll inTag) ~> muEscapeFunc conf ~> tell next afterClose where- next t = processBlock t context otag ctag conf+ next t = processBlock t contexts otag ctag conf trim' content = dropWhile trimCharsTest content ~> \t -> if (length t > 0 && head t == ord8 '\n')@@ -341,7 +353,7 @@ -> MuContext m -- ^ Context -> m LZ.ByteString hastacheStr conf str context = - execWriterT (processBlock str context defOTag defCTag conf)+ execWriterT (processBlock str [context] defOTag defCTag conf) -- | Render Hastache template from file hastacheFile :: (MonadIO m) =>
Text/Hastache/Context.hs view
@@ -56,18 +56,18 @@ example = hastacheStr defaultConfig (encodeStr template) (mkGenericContext context) where- template = concat [- \"string: {{stringField}} \\n\",- \"int: {{intField}} \\n\",- \"data: {{dataField.someField}}, {{dataField.anotherField}} \\n\",- \"data: {{#dataField}}{{someField}}, {{anotherField}}{{/dataField}} \\n\",- \"simple list: {{#simpleListField}}{{.}} {{/simpleListField}} \\n\",- \"data list: \\n\",- \"{{#dataListField}}\\n\",- \" * {{someField}}, {{anotherField}} \\n\",- \"{{/dataListField}}\\n\",- \"{{#stringFunc}}upper{{/stringFunc}} \\n\",- \"{{#byteStringFunc}}reverse{{/byteStringFunc}} \\n\"]+ template = concat $ map (++ \"\\n\") [+ \"string: {{stringField}}\",+ \"int: {{intField}}\",+ \"data: {{dataField.someField}}, {{dataField.anotherField}}\",+ \"data: {{#dataField}}{{someField}}, {{anotherField}}{{/dataField}}\",+ \"simple list: {{#simpleListField}}{{.}} {{/simpleListField}}\",+ \"data list:\",+ \"{{#dataListField}}\",+ \" * {{someField}}, {{anotherField}}. top level var: {{intField}}\",+ \"{{/dataListField}}\",+ \"{{#stringFunc}}upper{{/stringFunc}}\",+ \"{{#byteStringFunc}}reverse{{/byteStringFunc}}\"] context = Example { stringField = \"string value\", intField = 1, dataField = InternalData \"val\" 123, simpleListField = [\"a\",\"b\",\"c\"], dataListField = [InternalData \"aaa\" 1, InternalData \"bbb\" 2],@@ -84,8 +84,8 @@ data: val, 123 simple list: a b c data list: - * aaa, 1 - * bbb, 2 + * aaa, 1. top level var: 1 + * bbb, 2. top level var: 1 UPPER esrever @@@ -160,8 +160,14 @@ foldTObj name m (fn, fv) = mkMap (mkName name fn) m fv mkMapContext m a = case Map.lookup a m of- Nothing -> case Map.lookup BS.empty m of- Nothing -> MuVariable BS.empty- Just a -> a+ Nothing -> + case a == dotBS of+ True -> + case Map.lookup BS.empty m of+ Nothing -> MuNothing+ Just a -> a+ _ -> MuNothing Just a -> a++dotBS = encodeStr "."
hastache.cabal view
@@ -1,5 +1,5 @@ name: hastache-version: 0.1.4+version: 0.1.5 license: BSD3 license-file: LICENSE category: Text
tests/test.hs view
@@ -309,6 +309,71 @@ \text 2\n\ \" +-- Up-level context from nested block+nestedContextTest = do+ res <- hastacheStr defaultConfig (encodeStr template) + (mkStrContext context)+ assertEqualStr "result correctness" (decodeStrLBS res) testRes+ where+ template = "\+ \{{top}}\n\+ \{{#section}}\n\+ \ * {{val}}. {{top}}\n\+ \{{/section}}\n\+ \"+ context "section" = MuList $ map elemCtx ["elem 1", "elem 2"]+ context "top" = MuVariable "top"+ elemCtx vl = mkStrContext (\v -> case v of + "val" -> MuVariable vl+ _ -> MuNothing+ )++ testRes = "\+ \top\n\+ \ * elem 1. top\n\+ \ * elem 2. top\n\+ \"++data TopData = TopData {+ topDataTop :: String,+ topDataItems :: [NestedData]+ }+ deriving (Data, Typeable)++data NestedData = NestedData {+ nestedDataNested :: String+ }+ deriving (Data, Typeable)++-- Up-level context from nested block (Generic version)+nestedGenericContextTest = do+ res <- hastacheStr defaultConfig (encodeStr template) context+ assertEqualStr "result correctness" (decodeStrLBS res) testRes+ where+ template = "\+ \Top variable : {{topDataTop}}\n\+ \{{#topDataItems}}\n\+ \-- Nested section\n\+ \Top variable : {{topDataTop}}\n\+ \Nested variable : {{nestedDataNested}}\n\+ \{{/topDataItems}}\n\+ \"+ context = mkGenericContext $ TopData {+ topDataTop = "TOP",+ topDataItems = [+ NestedData "NESTED_ONE",+ NestedData "NESTED_TWO"]+ }+ testRes = "\+ \Top variable : TOP\n\+ \-- Nested section\n\+ \Top variable : TOP\n\+ \Nested variable : NESTED_ONE\n\+ \-- Nested section\n\+ \Top variable : TOP\n\+ \Nested variable : NESTED_TWO\n\+ \"+ tests = TestList [ TestLabel "Comments test" (TestCase commentsTest) ,TestLabel "Variables test" (TestCase variablesTest)@@ -320,13 +385,16 @@ ,TestLabel "Set delimiter test" (TestCase setDelimiterTest) ,TestLabel "Partials test" (TestCase partialsTest) ,TestLabel "Generic context test" (TestCase genericContextTest)+ ,TestLabel "Nested context test" (TestCase nestedContextTest)+ ,TestLabel "Nested generic context test" (TestCase nestedGenericContextTest) ] main = do runTestTT tests -assertEqualStr preface expected actual =+assertEqualStr preface actual expected = unless (actual == expected) (assertFailure msg)- where msg = (if null preface then "" else preface ++ "\n") ++- "expected: \n" ++ expected ++ "\nbut got: \n" ++ actual+ where + msg = (if null preface then "" else preface ++ "\n") +++ "expected: \n" ++ expected ++ "\nbut got: \n" ++ actual