hastache 0.2.4 → 0.3.2
raw patch · 3 files changed
+106/−89 lines, 3 filesdep +ieee754PVP ok
version bump matches the API change (PVP)
Dependencies added: ieee754
API changes (from Hackage documentation)
+ Text.Hastache: isEmpty :: MuVar a => a -> Bool
- Text.Hastache: class Show a => MuVar a
+ Text.Hastache: class Show a => MuVar a where isEmpty _ = False
Files
- Text/Hastache.hs +66/−67
- hastache.cabal +2/−1
- tests/test.hs +38/−21
Text/Hastache.hs view
@@ -83,6 +83,7 @@ import Control.Monad (guard, when) import Control.Monad.Reader (ask, runReaderT, MonadReader, ReaderT) import Control.Monad.Trans (lift, liftIO, MonadIO)+import Data.AEq ((~==)) import Data.ByteString hiding (map, foldl1) import Data.Char (ord) import Data.Int@@ -101,9 +102,10 @@ import qualified Data.List as List import qualified Data.Text as Text import qualified Data.Text.Lazy as LText+import qualified Prelude (~>) :: a -> (a -> b) -> b-x ~> f = f $ x+x ~> f = f x infixl 9 ~> -- | Data for Hastache variable@@ -112,49 +114,59 @@ -> MuType m -- ^ Value class Show a => MuVar a where- toLByteString :: a -> LZ.ByteString+ -- | Convert to Lazy ByteString+ toLByteString :: a -> LZ.ByteString + -- | Is empty variable (empty string, zero number etc.)+ isEmpty :: a -> Bool + isEmpty _ = False instance MuVar ByteString where toLByteString = toLBS+ isEmpty a = length a == 0 instance MuVar LZ.ByteString where toLByteString = id+ isEmpty a = LZ.length a == 0 withShowToLBS a = show a ~> encodeStr ~> toLBS+numEmpty a = a ~== 0 -instance MuVar Integer where toLByteString = withShowToLBS-instance MuVar Int where toLByteString = withShowToLBS-instance MuVar Float where toLByteString = withShowToLBS-instance MuVar Double where toLByteString = withShowToLBS-instance MuVar Int8 where toLByteString = withShowToLBS-instance MuVar Int16 where toLByteString = withShowToLBS-instance MuVar Int32 where toLByteString = withShowToLBS-instance MuVar Int64 where toLByteString = withShowToLBS-instance MuVar Word where toLByteString = withShowToLBS-instance MuVar Word8 where toLByteString = withShowToLBS-instance MuVar Word16 where toLByteString = withShowToLBS-instance MuVar Word32 where toLByteString = withShowToLBS-instance MuVar Word64 where toLByteString = withShowToLBS+instance MuVar Integer where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Int where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Float where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Double where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Int8 where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Int16 where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Int32 where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Int64 where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Word where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Word8 where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Word16 where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Word32 where {toLByteString = withShowToLBS; isEmpty = numEmpty}+instance MuVar Word64 where {toLByteString = withShowToLBS; isEmpty = numEmpty} instance MuVar Text.Text where toLByteString t = Text.unpack t ~> encodeStr ~> toLBS+ isEmpty a = Text.length a == 0 instance MuVar LText.Text where toLByteString t = LText.unpack t ~> encodeStr ~> toLBS+ isEmpty a = LText.length a == 0 instance MuVar Char where toLByteString a = (a : "") ~> encodeStr ~> toLBS instance MuVar a => MuVar [a] where- toLByteString a = (toLByteString '[') <+> cnvLst <+> (toLByteString ']')+ toLByteString a = toLByteString '[' <+> cnvLst <+> toLByteString ']' where- cnvLst = (map toLByteString a) ~> - (LZ.intercalate (toLByteString ','))+ cnvLst = map toLByteString a ~> + LZ.intercalate (toLByteString ',') (<+>) = LZ.append instance MuVar [Char] where toLByteString k = k ~> encodeStr ~> toLBS- + isEmpty a = Prelude.length a == 0+ data MuType m = forall a. MuVar a => MuVariable a | MuList [MuContext m] |@@ -214,9 +226,9 @@ | h == ord8 '\''= stp "'" t | h == ord8 '<' = stp "<" t | h == ord8 '>' = stp ">" t- | otherwise = h : (proc t)+ | otherwise = h : proc t proc [] = []- stp a t = (map ord8 a) ++ (proc t)+ stp a t = map ord8 a ++ proc t -- | No escape emptyEscape :: LZ.ByteString -> LZ.ByteString@@ -241,7 +253,7 @@ -> ByteString -> Maybe (ByteString, Word8, ByteString, ByteString) findBlock str otag ctag = do- guard (length fnd > (length otag))+ guard (length fnd > length otag) Just (pre, symb, inTag, afterClose) where (pre, fnd) = breakSubstring otag str@@ -279,7 +291,7 @@ (before, after) = breakSubstring close str trimCharsTest :: Word8 -> Bool-trimCharsTest = (`elem` (encodeStr " \t"))+trimCharsTest = (`elem` encodeStr " \t") trimAll :: ByteString -> ByteString trimAll str = span trimCharsTest str ~> snd ~> spanEnd trimCharsTest ~> fst@@ -305,12 +317,11 @@ -> ByteString -> MuConfig -> ReaderT (IORef BSB.Builder) m ()-processBlock str contexts otag ctag conf = do+processBlock str contexts otag ctag conf = case findBlock str otag ctag of Just (pre, symb, inTag, afterClose) -> do addResBS pre- renderBlock contexts symb inTag afterClose - otag ctag conf+ renderBlock contexts symb inTag afterClose otag ctag conf Nothing -> do addResBS str return ()@@ -331,15 +342,14 @@ | symb == ord8 '&' || (symb == ord8 '{' && otag == defOTag) = do readVar contexts (tail inTag ~> trimAll) ~> addResLZ next afterClose- -- section. inverted section+ -- section, inverted section | symb == ord8 '#' || symb == ord8 '^' = - let normalSection = symb == ord8 '#' in do case findCloseSection afterClose (tail inTag) otag ctag of Nothing -> next afterClose Just (sectionContent', afterSection') -> let dropNL str = - if (length str) > 0 && (head str) == ord8 '\n' + if length str > 0 && head str == ord8 '\n' then tail str else str sectionContent = dropNL sectionContent'@@ -350,57 +360,45 @@ tlInTag = tail inTag readContext = map ($ tlInTag) contexts ~> List.find (not . isMuNothing)- in do- case readContext of- Just (MuList []) -> - if normalSection then do next afterSection- else do- processBlock sectionContent- contexts otag ctag conf- next afterSection- Just (MuList b) -> - if normalSection then do+ processAndNext = do + processBlock sectionContent contexts otag ctag conf+ next afterSection+ in + if symb == ord8 '#'+ then case readContext of -- section+ Just (MuList []) -> next afterSection+ Just (MuList b) -> do mapM_ (\c -> processBlock sectionContent (c:contexts) otag ctag conf) b next afterSection- else do next afterSection- Just (MuBool True) -> - if normalSection then do- processBlock sectionContent- contexts otag ctag conf- next afterSection- else do next afterSection- Just (MuBool False) -> - if normalSection then do next afterSection- else do- processBlock sectionContent- contexts otag ctag conf- next afterSection- Just (MuLambda func) -> - if normalSection then do+ Just (MuBool True) -> processAndNext+ Just (MuLambda func) -> do func sectionContent ~> toLByteString ~> addResLZ next afterSection- else do next afterSection- Just (MuLambdaM func) -> - if normalSection then do+ Just (MuLambdaM func) -> do res <- lift (func sectionContent) toLByteString res ~> addResLZ next afterSection- else do next afterSection- _ -> next afterSection+ _ -> next afterSection+ else case readContext of -- inverted section+ Just (MuList []) -> processAndNext+ Just (MuBool False) -> processAndNext+ Just (MuVariable a) -> if isEmpty a + then processAndNext+ else next afterSection+ Nothing -> processAndNext+ _ -> next afterSection -- set delimiter | symb == ord8 '=' = let lenInTag = length inTag delimitersCommand = take (lenInTag - 1) inTag ~> drop 1 getDelimiter = do- guard (lenInTag > 4)- guard ((index inTag $ lenInTag - 1) == ord8 '=')- [newOTag,newCTag] <- Just $ split (ord8 ' ') - delimitersCommand+ guard $ lenInTag > 4+ guard $ index inTag (lenInTag - 1) == ord8 '='+ [newOTag,newCTag] <- Just $ split (ord8 ' ') delimitersCommand Just (newOTag, newCTag)- in do- case getDelimiter of+ in case getDelimiter of Nothing -> next afterClose Just (newOTag, newCTag) -> processBlock (trim' afterClose) contexts@@ -411,7 +409,7 @@ fileName' = tail inTag ~> trimAll fileName'' = case muTemplateFileExt conf of Nothing -> fileName'- Just ext -> fileName' `append` (encodeStr ext)+ Just ext -> fileName' `append` encodeStr ext fileName = decodeStr fileName'' fullFileName = case muTemplateFileDir conf of Nothing -> fileName@@ -430,8 +428,9 @@ next t = processBlock t contexts otag ctag conf trim' content = dropWhile trimCharsTest content- ~> \t -> if (length t > 0 && head t == ord8 '\n')+ ~> \t -> if length t > 0 && head t == ord8 '\n' then tail t else content+ processSection = undefined -- | Render Hastache template from ByteString hastacheStr :: (MonadIO m) =>
hastache.cabal view
@@ -1,5 +1,5 @@ name: hastache-version: 0.2.4+version: 0.3.2 license: BSD3 license-file: LICENSE category: Text@@ -40,6 +40,7 @@ ,containers ,syb ,blaze-builder+ ,ieee754 source-repository head type: git
tests/test.hs view
@@ -13,10 +13,12 @@ import qualified Data.ByteString.Lazy as LZ import qualified Data.Text as T +resCorrectness = "result correctness"+ -- Hastache comments commentsTest = do res <- hastacheStr defaultConfig (encodeStr template) undefined- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \hello {{! comment #1}} world! \n\@@ -33,7 +35,7 @@ variablesTest = do res <- hastacheStr defaultConfig (encodeStr template) (mkStrContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \ Char: [ {{Char}} ] \n\@@ -66,38 +68,53 @@ \ HtmlStringUnEsc2: [ <p>text (\\)</p> ] \n\ \" --- Show/hide block according to list state-emptyListSectionsTest = do+-- Inverted sections+invertedSections = do res <- hastacheStr defaultConfig (encodeStr template) (mkStrContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\+ \no context : {{^noCtx}}Should render{{/noCtx}}\n\ \text 1\n\- \{{#blankSection}}\n\+ \{{#emptyList}}\n\ \ some text\n\- \{{/blankSection}}\n\+ \{{/emptyList}}\n\ \text 2\n\- \{{^blankSection}}\n\+ \{{^emptyList}}\n\ \ empty list. {{someval}}\n\- \{{/blankSection}}\n\- \inline [{{#blankSection}}txt{{/blankSection}}]\n\+ \{{/emptyList}}\n\+ \inline [{{#emptyList}}txt{{/emptyList}}]\n\+ \{{#emptyString}}no {{someval}}{{/emptyString}}\+ \{{^emptyString}}yes {{someval}}{{/emptyString}}\n\+ \{{#emptyInt}}no {{emptyInt}}{{/emptyInt}}\+ \{{^emptyInt}}yes {{emptyInt}}{{/emptyInt}}\n\+ \{{#emptyDouble}}no {{emptyDouble}}{{/emptyDouble}}\+ \{{^emptyDouble}}yes {{emptyDouble}}{{/emptyDouble}}\n\ \"- context "blankSection" = MuList []+ context "noCtx" = MuNothing+ context "emptyList" = MuList [] context "someval" = MuVariable (5 :: Int)+ context "emptyString" = MuVariable ""+ context "emptyInt" = MuVariable (0 :: Int)+ context "emptyDouble" = MuVariable (0 :: Double) testRes = "\+ \no context : Should render\n\ \text 1\n\ \text 2\n\ \ empty list. 5\n\ \inline []\n\+ \yes 5\n\+ \yes 0\n\+ \yes 0.0\n\ \" -- Render list listSectionTest = do res <- hastacheStr defaultConfig (encodeStr template) (mkStrContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \text 1\n\@@ -123,7 +140,7 @@ boolSectionTest = do res <- hastacheStr defaultConfig (encodeStr template) (mkStrContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \text 1\n\@@ -156,7 +173,7 @@ lambdaSectionTest = do res <- hastacheStr defaultConfig (encodeStr template) (mkStrContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \text 1\n\@@ -174,7 +191,7 @@ -- Transform section with monadic function lambdaMSectionTest = do (res, writerState) <- runWriterT monadicFunction- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes assertEqualStr "monad state correctness" (decodeStr writerState) testMonad where@@ -199,7 +216,7 @@ setDelimiterTest = do res <- hastacheStr defaultConfig (encodeStr template) (mkStrContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \text 1\n\@@ -224,7 +241,7 @@ partialsTest = do res <- hastacheStr defaultConfig (encodeStr template) (mkStrContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \text 1\n\@@ -261,7 +278,7 @@ genericContextTest = do res <- hastacheStr defaultConfig (encodeStr template) (mkGenericContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \text 1\n\@@ -321,7 +338,7 @@ nestedContextTest = do res <- hastacheStr defaultConfig (encodeStr template) (mkStrContext context)- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \{{top}}\n\@@ -356,7 +373,7 @@ nestedGenericContextTest = do res <- hastacheStr defaultConfig (encodeStr template) context- assertEqualStr "result correctness" (decodeStrLBS res) testRes+ assertEqualStr resCorrectness (decodeStrLBS res) testRes where template = "\ \Top variable : {{topDataTop}}\n\@@ -385,7 +402,7 @@ tests = TestList [ TestLabel "Comments test" (TestCase commentsTest) ,TestLabel "Variables test" (TestCase variablesTest)- ,TestLabel "Empty list test" (TestCase emptyListSectionsTest)+ ,TestLabel "Inverted sections" (TestCase invertedSections) ,TestLabel "List test" (TestCase listSectionTest) ,TestLabel "Bool test" (TestCase boolSectionTest) ,TestLabel "Lambda test" (TestCase lambdaSectionTest)