glabrous 0.1.1.0 → 0.1.2.0
raw patch · 4 files changed
+89/−61 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Text.Glabrous.Types: instance Data.Aeson.Types.Class.FromJSON Text.Glabrous.Types.Context
- Text.Glabrous.Types: instance Data.Aeson.Types.Class.ToJSON Text.Glabrous.Types.Context
+ Text.Glabrous: isSet :: Context -> Bool
+ Text.Glabrous: variablesOf :: Context -> [Text]
+ Text.Glabrous.Types: instance Data.Aeson.Types.FromJSON.FromJSON Text.Glabrous.Types.Context
+ Text.Glabrous.Types: instance Data.Aeson.Types.ToJSON.ToJSON Text.Glabrous.Types.Context
Files
- README.md +2/−7
- glabrous.cabal +1/−1
- src/Text/Glabrous.hs +82/−53
- tests/hspec.hs +4/−0
README.md view
@@ -1,10 +1,5 @@ # Glabrous [](https://travis-ci.org/MichelBoucey/glabrous) ---Glabrous is a minimalistic Mustache-like syntax, truly logic-less, pure Text template library.--* Use only the simplest Mustache tag {{name}}-* HTML agnostic+Glabrous is a minimalistic Mustache-like syntax - using only the simplest Mustache tag: {{name}} -, truly logic-less, HTML agnostic pure Text template library. -Bug fixes & improvements are welcome.+Any improvement is welcome.
glabrous.cabal view
@@ -1,5 +1,5 @@ name: glabrous-version: 0.1.1.0+version: 0.1.2.0 synopsis: A template library description: A minimalistic, Mustache-like syntax, truly logic-less, pure Text template library
src/Text/Glabrous.hs view
@@ -11,41 +11,61 @@ module Text.Glabrous (- -- * Template++ -- * 'Template'+ Template (..) , Tag+ -- ** Get a 'Template'+ , fromText , readTemplateFile+ -- ** 'Template' operations+ , toText , isFinal , tagsOf , tagsRename , compress , writeTemplateFile- -- * Context++ -- * 'Context'+ , Context (..)+ -- ** Get a 'Context'+ , initContext , fromList , fromTemplate+ -- ** 'Context' operations+ , setVariables , deleteVariables+ , variablesOf+ , isSet , unsetContext+ -- ** JSON 'Context' file+ , readContextFile , writeContextFile , initContextFile+ -- * Processing+ , process , processWithDefault , partialProcess , G.Result (..) , partialProcess'+ ) where +import Control.Monad import Data.Aeson import Data.Aeson.Encode.Pretty (encodePretty) import qualified Data.ByteString.Lazy as L@@ -57,28 +77,26 @@ import Text.Glabrous.Internal import Text.Glabrous.Types as G --- | Optimize a 'Template' content after (many) partialProcess(') rewriting(s).+-- | Optimize a 'Template' content after (many) 'partialProcess'(') rewriting(s). compress :: Template -> Template-compress t =- Template { content = packC (content t) [] }+compress Template {..} =+ Template { content = go content [] } where- packC ts !o = do- let (a,b) = span isL ts+ go ts !ac = do+ let (a,b) = span isLiteral ts+ u = uncons b if not (null a)- then packC b (o ++ [concatL a])- else if not (null b)- then do let (a',b') = span (not.isL) b- if not (null a')- then packC b' (o ++ a')- else if not (null b')- then packC b' o- else o- else o+ then case u of+ Just (c,d) -> go d (ac ++ [concatLiterals a] ++ [c])+ Nothing -> ac ++ [concatLiterals a]+ else case u of+ Just (e,f) -> go f (ac ++ [e])+ Nothing -> ac where- isL (Literal _) = True- isL (Tag _) = False- concatL _ts =- foldr trans (Literal "") _ts+ isLiteral (Literal _) = True+ isLiteral (Tag _) = False+ concatLiterals =+ foldr trans (Literal "") where trans (Literal a) (Literal b) = Literal (a `T.append` b) trans _ _ = undefined@@ -92,22 +110,26 @@ -- >λ>setVariables [("something","something new"), ("about","Haskell")] context -- >Context {variables = fromList [("etc.","..."),("about","Haskell"),("something","something new"),("name","")]} setVariables :: [(T.Text,T.Text)] -> Context -> Context-setVariables ts c@Context{..} =- case uncons ts of- Just ((k,v),ts') ->- setVariables ts' Context { variables = H.insert k v variables }- Nothing -> c+setVariables ts Context {..} =+ go ts variables+ where+ go _ts vs =+ case uncons _ts of+ Just ((k,v),ts') -> go ts' $ H.insert k v vs+ Nothing -> Context { variables = vs } -- | Delete variables from a 'Context' by these names. -- -- >λ>deleteVariables ["something"] context -- >Context {variables = fromList [("etc.","..."),("about","Haskell"),("name","")]} deleteVariables :: [T.Text] -> Context -> Context-deleteVariables ts c@Context{..} =- case uncons ts of- Just (k,ts') ->- deleteVariables ts' Context { variables = H.delete k variables }- Nothing -> c+deleteVariables ts Context {..} =+ go ts variables+ where+ go _ts vs =+ case uncons _ts of+ Just (k,ts') -> go ts' $ H.delete k vs+ Nothing -> Context { variables = vs } -- | Build a 'Context' from a list of 'Tag's and replacement 'T.Text's. --@@ -117,8 +139,8 @@ fromList :: [(T.Text, T.Text)] -> Context fromList ts = Context { variables = H.fromList ts } --- | Extract 'Tag's from a 'Template' and build--- a 'Context' with all its variables empty.+-- | Build an adhoc 'Context' for the given+-- 'Template' with all its variables empty. fromTemplate :: Template -> Context fromTemplate t = setVariables ((\e -> (e,T.empty)) <$> tagsOf t) initContext @@ -149,7 +171,7 @@ -- @ -- initContextFile :: FilePath -> Context -> IO ()-initContextFile f Context{..} = L.writeFile f $+initContextFile f Context {..} = L.writeFile f $ encodePretty Context { variables = H.map (const T.empty) variables } -- | Build 'Just' a (sub)'Context' made of unset variables@@ -159,12 +181,21 @@ -- >Just (Context {variables = fromList [("name","")]}) -- unsetContext :: Context -> Maybe Context-unsetContext Context{..} = do+unsetContext Context {..} = do let vs = H.filter (== T.empty) variables- if vs /= H.empty- then Just Context { variables = vs }- else Nothing+ guard (vs /= H.empty)+ return Context { variables = vs } +-- | 'True' if the all variables of+-- the given 'Context' are not empty+isSet :: Context -> Bool+isSet Context {..} =+ H.foldr (\v b -> b && v /= T.empty) True variables++-- | Get the list of the given 'Context' variables+variablesOf :: Context -> [T.Text]+variablesOf Context {..} = H.keys variables+ -- | Get a 'Template' from a file. readTemplateFile :: FilePath -> IO (Either String Template) readTemplateFile f = fromText <$> I.readFile f@@ -177,7 +208,7 @@ -- as it is, with its 'Tag's, if they exist (no -- 'Context' is processed). toText :: Template -> T.Text-toText Template{..} =+toText Template {..} = T.concat $ trans <$> content where trans (Literal c) = c@@ -185,14 +216,14 @@ -- | Get the list of 'Tag's in the given 'Template'. tagsOf :: Template -> [Tag]-tagsOf Template{..} =+tagsOf Template {..} = (\(Tag k) -> k) <$> filter isTag content where isTag (Tag _) = True isTag _ = False tagsRename :: [(T.Text,T.Text)] -> Template -> Template-tagsRename ts Template{..} =+tagsRename ts Template {..} = Template { content = rename <$> content } where rename t@(Tag n) =@@ -204,7 +235,7 @@ -- | 'True' if a 'Template' has no more 'Tag' -- inside and can be used as a final 'T.Text'. isFinal :: Template -> Bool-isFinal Template{..} =+isFinal Template {..} = allLiteral content where allLiteral t =@@ -226,12 +257,12 @@ -> Template -> Context -> T.Text-processWithDefault d Template{..} c = toTextWithContext (const d) c content+processWithDefault d Template {..} c = toTextWithContext (const d) c content -- | Process a (sub)'Context' present in the given template, leaving -- untouched, if they exist, other 'Tag's, to obtain a new template. partialProcess :: Template -> Context -> Template-partialProcess Template{..} c =+partialProcess Template {..} c = Template { content = transTags content c } where transTags ts Context{..} =@@ -250,18 +281,16 @@ -- >λ>partialProcess' template context -- >Partial {template = Template {content = [Literal "Some ",Tag "tags",Literal " are unused in this ",Tag "text",Literal "."]}, tags = ["tags","text"]} partialProcess' :: Template -> Context -> G.Result-partialProcess' t c@Context{..} =- case foldl trans (Template { content = [] },[]) (content t) of- (f,[]) -> Final $ toTextWithContext (const T.empty) c (content f)- (p,p') -> G.Partial p p'+partialProcess' t c@Context {..} =+ case foldl trans ([],[]) (content t) of+ (f,[]) -> Final $ toTextWithContext (const T.empty) c f+ (p,p') -> G.Partial Template { content = p } p' where- trans (!c',ts) t' =+ trans (!c',!ts) t' = case t' of Tag k -> case H.lookup k variables of- Just v -> (addToken (Literal v) c',ts)- Nothing -> (addToken t' c',ts ++ [k])- Literal _ -> (addToken t' c',ts)- where- addToken a b = Template { content = content b ++ [a] }+ Just v -> (c' ++ [Literal v],ts)+ Nothing -> (c' ++ [t'],ts ++ [k])+ Literal _ -> (c' ++ [t'],ts)
tests/hspec.hs view
@@ -71,6 +71,10 @@ it "gets a Context made of unset variables of the given context" $ fromJust <$> unsetContext <$> setVariables variablesList <$> fromTemplate <$> fromRight' <$> readTemplateFile templateFile `shouldReturn` Context {variables = H.fromList [("tortor",""),("commodo",""),("fermentum",""),("rhoncus",""),("bibendum",""),("venenatis","")]} + describe "isSet" $+ it "true if all variables are not empty" $+ (return $ isSet context') `shouldReturn` True+ describe "writeContextFile" $ it "writes a context to a file" $ do !acontext <- fromJust <$> readContextFile contextFile