glabrous 0.4.0 → 1.0.0
raw patch · 5 files changed
+58/−35 lines, 5 filesdep ~hspecPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hspec
API changes (from Hackage documentation)
- Text.Glabrous: data Context
- Text.Glabrous: data Template
- Text.Glabrous: type Tag = Text
- Text.Glabrous.Types: data Context
- Text.Glabrous.Types: data Template
- Text.Glabrous.Types: type Tag = Text
+ Text.Glabrous: insertMany :: Template -> [(Token, Template)] -> Maybe Template
+ Text.Glabrous: newtype Context
+ Text.Glabrous: newtype Template
+ Text.Glabrous.Types: newtype Context
+ Text.Glabrous.Types: newtype Template
- Text.Glabrous: Context :: !(HashMap Text Text) -> Context
+ Text.Glabrous: Context :: HashMap Text Text -> Context
- Text.Glabrous: Template :: ![Token] -> Template
+ Text.Glabrous: Template :: [Token] -> Template
- Text.Glabrous: [content] :: Template -> ![Token]
+ Text.Glabrous: [content] :: Template -> [Token]
- Text.Glabrous: [variables] :: Context -> !(HashMap Text Text)
+ Text.Glabrous: [variables] :: Context -> HashMap Text Text
- Text.Glabrous: insert :: Template -> Text -> Template -> Maybe Template
+ Text.Glabrous: insert :: Template -> Token -> Template -> Maybe Template
- Text.Glabrous: tagsOf :: Template -> [Tag]
+ Text.Glabrous: tagsOf :: Template -> [Token]
- Text.Glabrous.Types: Context :: !(HashMap Text Text) -> Context
+ Text.Glabrous.Types: Context :: HashMap Text Text -> Context
- Text.Glabrous.Types: Template :: ![Token] -> Template
+ Text.Glabrous.Types: Template :: [Token] -> Template
- Text.Glabrous.Types: [content] :: Template -> ![Token]
+ Text.Glabrous.Types: [content] :: Template -> [Token]
- Text.Glabrous.Types: [variables] :: Context -> !(HashMap Text Text)
+ Text.Glabrous.Types: [variables] :: Context -> HashMap Text Text
Files
- glabrous.cabal +2/−2
- src/Text/Glabrous.hs +44/−23
- src/Text/Glabrous/Internal.hs +7/−3
- src/Text/Glabrous/Types.hs +4/−6
- tests/hspec.hs +1/−1
glabrous.cabal view
@@ -1,5 +1,5 @@ name: glabrous-version: 0.4.0+version: 1.0.0 synopsis: A template DSL library description: A minimalistic, Mustache-like syntax, truly logic-less, pure Text template DSL library@@ -45,7 +45,7 @@ , directory > 1.2 && < 1.4 , either >= 4.4.1 && < 5.1 , glabrous- , hspec >= 2.1.10 && < 2.6+ , hspec >= 2.1.10 && < 2.7 , text >= 1.2.1 && < 1.3 , unordered-containers == 0.2.* default-language: Haskell2010
src/Text/Glabrous.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} -- | A minimalistic Mustache-like syntax, truly logic-less, -- pure 'T.Text' template library@@ -14,7 +15,6 @@ -- * 'Template' Template (..)- , Tag -- ** Get a 'Template' , fromText@@ -29,6 +29,7 @@ , compress , writeTemplateFile , insert+ , insertMany -- * 'Context' , Context (..)@@ -56,22 +57,22 @@ , process , processWithDefault , partialProcess- , G.Result (..)+ , Result (..) , partialProcess' ) where import Control.Monad (guard)-import Data.Aeson+import Data.Aeson hiding (Result) import Data.Aeson.Encode.Pretty (encodePretty) import qualified Data.ByteString.Lazy as L import qualified Data.HashMap.Strict as H-import Data.List (uncons)+import Data.List (intersect,uncons) import qualified Data.Text as T import qualified Data.Text.IO as I import Text.Glabrous.Internal-import Text.Glabrous.Types as G+import Text.Glabrous.Types -- | Optimize a 'Template' content after (many) 'partialProcess'(') rewriting(s). compress :: Template -> Template@@ -138,11 +139,11 @@ -- >λ>fromTagsList ["tag","etc."] -- >Context {variables = fromList [("etc.",""),("tag","")]} fromTagsList :: [T.Text] -> Context-fromTagsList ts = fromList $ (\t -> (t,T.empty)) <$> ts+fromTagsList ts = fromList $ (,T.empty) <$> ts -- | Build an unset ad hoc 'Context' from the given 'Template'. fromTemplate :: Template -> Context-fromTemplate t = setVariables ((\e -> (e,T.empty)) <$> tagsOf t) initContext+fromTemplate t = setVariables ((\(Tag e) -> (e,T.empty)) <$> tagsOf t) initContext -- | Get a 'Context' from a JSON file. readContextFile :: FilePath -> IO (Maybe Context)@@ -216,21 +217,45 @@ writeTemplateFile f t = I.writeFile f (toText t) -- | get 'Just' a new 'Template' by inserting a 'Template'--- into another one by replacing the 'Tag' named, or 'Nothing'.+-- into another one by replacing the 'Tag', or 'Nothing'.+--+-- >λ>insert t0 (Tag "template1") t1 insert :: Template -- ^ The Template to insert in- -> T.Text -- ^ The Tag name to be replaced+ -> Token -- ^ The Tag to be replaced -> Template -- ^ The Template to be inserted -> Maybe Template -- ^ Just the new Template, or Nothing-insert te tn te' = do- guard (Tag tn `elem` content te)+insert _ (Literal _) _ = Nothing+insert te t te' = do+ guard (t `elem` content te) return Template { content = foldl trans [] (content te) } where- trans o t@(Tag tn') =- if tn' == tn+ trans o t'@(Tag _) =+ if t' == t then o ++ content te'- else o ++ [t]+ else o ++ [t'] trans o l = o ++ [l] +-- | get 'Just' a new 'Template' by inserting many 'Template's,+-- if there is at least one tag correspondence, or 'Nothing'.+--+-- >λ>insertMany t0 [(Tag "template1",t1),(Tag "template2",t2)]+insertMany :: Template -> [(Token,Template)] -> Maybe Template+insertMany te ttps = do+ guard (tagsOf te `intersect` (fst <$> ttps) /= mempty)+ return Template { content = foldl trans [] (content te) }+ where+ trans o li@(Literal _) = o ++ [li]+ trans o ta@(Tag _) =+ case lookupTemplate ta ttps of+ Nothing -> o ++ [ta]+ Just te' -> o ++ content te'+ lookupTemplate (Literal _) _ = Nothing+ lookupTemplate _ [] = Nothing+ lookupTemplate t (p:ps) =+ if fst p == t+ then Just (snd p)+ else lookupTemplate t ps+ -- | Output the content of the given 'Template' -- as it is, with its 'Tag's, if they exist. toText :: Template -> T.Text@@ -250,12 +275,8 @@ trans o (Tag _) = o -- | Get the list of 'Tag's in the given 'Template'.-tagsOf :: Template -> [Tag]-tagsOf Template{..} =- (\(Tag k) -> k) <$> filter isTag content- where- isTag (Tag _) = True- isTag _ = False+tagsOf :: Template -> [Token]+tagsOf Template{..} = filter isTag content tagsRename :: [(T.Text,T.Text)] -> Template -> Template tagsRename ts Template{..} =@@ -307,11 +328,11 @@ -- -- >λ>partialProcess' template context -- >Partial {template = Template {content = [Literal "Some ",Tag "tags",Literal " are unused in this ",Tag "text",Literal "."]}, context = Context {variables = fromList [("text",""),("tags","")]}}-partialProcess' :: Template -> Context -> G.Result+partialProcess' :: Template -> Context -> Result partialProcess' t c@Context{..} =- case foldl trans ([],[]) (content t) of+ case foldl trans (mempty,mempty) (content t) of (f,[]) -> Final (toTextWithContext (const T.empty) c f)- (p,p') -> G.Partial Template { content = p } (fromTagsList p')+ (p,p') -> Partial Template { content = p } (fromTagsList p') where trans (!c',!ts) t' = case t' of
src/Text/Glabrous/Internal.hs view
@@ -9,11 +9,11 @@ import Data.Maybe (fromMaybe) import qualified Data.Text as T -import Text.Glabrous.Types as G+import Text.Glabrous.Types toTextWithContext :: (T.Text -> T.Text) -> Context -> [Token] -> T.Text toTextWithContext tagDefault Context{..} ts =- T.concat $ trans <$> ts+ T.concat (trans <$> ts) where trans (Tag k) = fromMaybe (tagDefault k) (H.lookup k variables) trans (Literal c) = c@@ -33,13 +33,17 @@ isLiteral (Literal _) = True isLiteral _ = False +isTag :: Token -> Bool+isTag (Tag _) = True+isTag _ = False+ tokens :: Parser [Token] tokens = many' token where token = literal <|> tag <|> leftover leftover = do- c <- takeWhile1 $ not . content+ c <- takeWhile1 (not . content) return (Literal c) literal = do c <- takeWhile1 content
src/Text/Glabrous/Types.hs view
@@ -18,16 +18,16 @@ instance Serialize Token -data Template =+newtype Template = Template- { content :: ![Token] }+ { content :: [Token] } deriving (Eq, Show, Generic) instance Serialize Template -data Context =+newtype Context = Context- { variables :: !(H.HashMap T.Text T.Text) }+ { variables :: H.HashMap T.Text T.Text } deriving (Eq, Show) instance ToJSON Context where@@ -38,8 +38,6 @@ parseJSON (Object o) = return Context { variables = H.fromList ((\(k,String v) -> (k,v)) <$> H.toList o) } parseJSON _ = fail "expected an object"--type Tag = T.Text data Result = Final !T.Text
tests/hspec.hs view
@@ -49,7 +49,7 @@ describe "tagsOf" $ it "returns the list of tags in a template" $- tagsOf <$> fromRight' <$> readTemplateFile templateFile `shouldReturn` ["ipsum","tortor","lectus","vehicula","bibendum","condimentum","tellus","faucibus","cursus","commodo","vestibulum","lobortis","fermentum","maximus","venenatis","sagittis","vitae","rhoncus"]+ tagsOf <$> fromRight' <$> readTemplateFile templateFile `shouldReturn` [Tag "ipsum",Tag "tortor",Tag "lectus",Tag "vehicula",Tag "bibendum",Tag "condimentum",Tag "tellus",Tag "faucibus",Tag "cursus",Tag "commodo",Tag "vestibulum",Tag "lobortis",Tag "fermentum",Tag "maximus",Tag "venenatis",Tag "sagittis",Tag "vitae",Tag "rhoncus"] describe "toText" $ it "returns the template as it is" $