packages feed

doctemplates 0.7.2 → 0.8

raw patch · 10 files changed

+160/−154 lines, 10 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Text.DocTemplates.Internal: [varFilters] :: Variable -> [Filter]
- Text.DocTemplates.Internal: data Filter
- Text.DocTemplates.Internal: instance Data.Data.Data Text.DocTemplates.Internal.Filter
- Text.DocTemplates.Internal: instance GHC.Classes.Eq Text.DocTemplates.Internal.Filter
- Text.DocTemplates.Internal: instance GHC.Classes.Ord Text.DocTemplates.Internal.Filter
- Text.DocTemplates.Internal: instance GHC.Generics.Generic Text.DocTemplates.Internal.Filter
- Text.DocTemplates.Internal: instance GHC.Read.Read Text.DocTemplates.Internal.Filter
- Text.DocTemplates.Internal: instance GHC.Show.Show Text.DocTemplates.Internal.Filter
+ Text.DocTemplates.Internal: [varPipes] :: Variable -> [Pipe]
+ Text.DocTemplates.Internal: data Pipe
+ Text.DocTemplates.Internal: instance Data.Data.Data Text.DocTemplates.Internal.Pipe
+ Text.DocTemplates.Internal: instance GHC.Classes.Eq Text.DocTemplates.Internal.Pipe
+ Text.DocTemplates.Internal: instance GHC.Classes.Ord Text.DocTemplates.Internal.Pipe
+ Text.DocTemplates.Internal: instance GHC.Generics.Generic Text.DocTemplates.Internal.Pipe
+ Text.DocTemplates.Internal: instance GHC.Read.Read Text.DocTemplates.Internal.Pipe
+ Text.DocTemplates.Internal: instance GHC.Show.Show Text.DocTemplates.Internal.Pipe
- Text.DocTemplates.Internal: Block :: Alignment -> Int -> Border -> Filter
+ Text.DocTemplates.Internal: Block :: Alignment -> Int -> Border -> Pipe
- Text.DocTemplates.Internal: Chomp :: Filter
+ Text.DocTemplates.Internal: Chomp :: Pipe
- Text.DocTemplates.Internal: NoWrap :: Filter
+ Text.DocTemplates.Internal: NoWrap :: Pipe
- Text.DocTemplates.Internal: Partial :: [Filter] -> Template a -> Template a
+ Text.DocTemplates.Internal: Partial :: [Pipe] -> Template a -> Template a
- Text.DocTemplates.Internal: Reverse :: Filter
+ Text.DocTemplates.Internal: Reverse :: Pipe
- Text.DocTemplates.Internal: ToAlpha :: Filter
+ Text.DocTemplates.Internal: ToAlpha :: Pipe
- Text.DocTemplates.Internal: ToLength :: Filter
+ Text.DocTemplates.Internal: ToLength :: Pipe
- Text.DocTemplates.Internal: ToLowercase :: Filter
+ Text.DocTemplates.Internal: ToLowercase :: Pipe
- Text.DocTemplates.Internal: ToPairs :: Filter
+ Text.DocTemplates.Internal: ToPairs :: Pipe
- Text.DocTemplates.Internal: ToRoman :: Filter
+ Text.DocTemplates.Internal: ToRoman :: Pipe
- Text.DocTemplates.Internal: ToUppercase :: Filter
+ Text.DocTemplates.Internal: ToUppercase :: Pipe
- Text.DocTemplates.Internal: Variable :: [Text] -> [Filter] -> Variable
+ Text.DocTemplates.Internal: Variable :: [Text] -> [Pipe] -> Variable

Files

README.md view
@@ -11,9 +11,9 @@  Control structures are provided to test whether a variable has a non-blank value and to iterate over the items of a list.  Partials---that is,-subtemplates defined in different files---are supported.  Filters+subtemplates defined in different files---are supported.  Pipes can be used to transform the values of variables or partials.-The provided filters make it possible to do list enumeration and+The provided pipes make it possible to do list enumeration and tabular layout in templates.  Templates are rendered to a doclayout `Doc` (which is polymorphic@@ -354,11 +354,11 @@ The `~` keyword has no effect when rendering to `Text` or `String`. -## Filters+## Pipes -A filter transforms the value of a variable or partial.  Filters+A pipe transforms the value of a variable or partial.  Pipes are specified using a slash (`/`) between the variable name (or-partial) and the filter name.  Example:+partial) and the pipe name.  Example:  ``` $for(name)$@@ -372,7 +372,7 @@ $employee:name()/uppercase$ ``` -Filters may be chained:+Pipes may be chained:  ``` $for(employees/pairs)$@@ -380,7 +380,7 @@ $endfor$ ``` -Some filters take parameters:+Some pipes take parameters:  ``` |----------------------|------------|@@ -390,7 +390,7 @@ |----------------------|------------| ``` -Currently the following filters are predefined:+Currently the following pipes are predefined:  - `pairs`:  Converts a map or array to an array of maps,   each with `key` and `value` fields.  If the original
changelog.md view
@@ -1,5 +1,11 @@ # doctemplates +## 0.8++  * Change `Filter` data type to `Pipe`.  Use the nomenclature of+    "pipe" instead of "filter" to avoid confusion in pandoc between+    two notions of filter.  Otherwise everything works the same.+ ## 0.7.2    * Add `nowrap` filter.
doctemplates.cabal view
@@ -1,9 +1,9 @@ name:                doctemplates-version:             0.7.2+version:             0.8 synopsis:            Pandoc-style document templates description:         This is the text templating system used by pandoc.                      It supports variable interpolation, iteration,-                     tests for non-blank values, filters, and partials.+                     tests for non-blank values, pipes, and partials.                      Templates are rendered to doclayout Docs,                      and variable values may come from a variety of                      different sources, including aeson Values.
src/Text/DocTemplates/Internal.hs view
@@ -33,7 +33,7 @@       , TemplateTarget       , Template(..)       , Variable(..)-      , Filter(..)+      , Pipe(..)       , Alignment(..)       , Border(..)       ) where@@ -70,7 +70,7 @@      | Conditional Variable (Template a) (Template a)      | Iterate Variable (Template a) (Template a)      | Nested (Template a)-     | Partial [Filter] (Template a)+     | Partial [Pipe] (Template a)      | Literal (Doc a)      | Concat (Template a) (Template a)      | Empty@@ -86,7 +86,7 @@   mappend = (<>)   mempty = Empty -data Filter =+data Pipe =       ToPairs     | ToUppercase     | ToLowercase@@ -115,7 +115,7 @@ data Variable =   Variable     { varParts   :: [Text]-    , varFilters :: [Filter]+    , varPipes   :: [Pipe]     }   deriving (Show, Read, Data, Typeable, Generic, Eq, Ord) @@ -294,17 +294,17 @@ mapText f val =   runIdentity (traverse (return . fromText . f . toText) val) -applyFilter :: TemplateTarget a => Filter -> Val a -> Val a-applyFilter ToLength val = SimpleVal $ fromString . show $ len+applyPipe :: TemplateTarget a => Pipe -> Val a -> Val a+applyPipe ToLength val = SimpleVal $ fromString . show $ len   where    len = case val of            SimpleVal d        -> T.length . toText $ DL.render Nothing d            MapVal (Context m) -> M.size m            ListVal xs         -> length xs            NullVal            -> 0-applyFilter ToUppercase val = mapText T.toUpper val-applyFilter ToLowercase val = mapText T.toLower val-applyFilter ToPairs val =+applyPipe ToUppercase val = mapText T.toUpper val+applyPipe ToLowercase val = mapText T.toLower val+applyPipe ToPairs val =   case val of     MapVal (Context m) ->       ListVal $ map toPair $ M.toList m@@ -315,24 +315,24 @@   toPair (k, v) = MapVal $ Context $ M.fromList                     [ ("key", SimpleVal $ fromString . T.unpack $ k)                     , ("value", v) ]-applyFilter Reverse val =+applyPipe Reverse val =   case val of     ListVal xs  -> ListVal (reverse xs)     SimpleVal{} -> mapText T.reverse val     _           -> val-applyFilter Chomp val = mapDoc DL.chomp val-applyFilter ToAlpha val = mapText toAlpha val+applyPipe Chomp val = mapDoc DL.chomp val+applyPipe ToAlpha val = mapText toAlpha val   where toAlpha t =           case T.decimal t of             Right (y,"") -> fromString [chr (ord 'a' + (y `mod` 26) - 1)]             _            -> t-applyFilter ToRoman val = mapText toRoman' val+applyPipe ToRoman val = mapText toRoman' val   where toRoman' t =          case T.decimal t of            Right (y,"") -> maybe t id (toRoman y)            _            -> t-applyFilter NoWrap val = mapDoc DL.nowrap val-applyFilter (Block align n border) val =+applyPipe NoWrap val = mapDoc DL.nowrap val+applyPipe (Block align n border) val =   let constructor = case align of                       LeftAligned  -> DL.lblock                       Centered     -> DL.cblock@@ -371,8 +371,8 @@   | x == 0    = return ""   | otherwise = Nothing -applyFilters :: TemplateTarget a => [Filter] -> Val a -> Val a-applyFilters fs x = foldr applyFilter x $ reverse fs+applyPipes :: TemplateTarget a => [Pipe] -> Val a -> Val a+applyPipes fs x = foldr applyPipe x $ reverse fs  multiLookup :: TemplateTarget a => [Text] -> Val a -> Val a multiLookup [] x = x@@ -387,7 +387,7 @@  resolveVariable' :: TemplateTarget a => Variable -> Val a -> [Doc a] resolveVariable' v val =-  case applyFilters (varFilters v) $ multiLookup (varParts v) val of+  case applyPipes (varPipes v) $ multiLookup (varParts v) val of     ListVal xs    -> concatMap (resolveVariable' mempty) xs     SimpleVal d       | DL.isEmpty d -> []@@ -405,7 +405,7 @@              => Variable -> Context a -> (Context a -> m (Doc a))              -> m [Doc a] withVariable  v ctx f =-  case applyFilters (varFilters v) $ multiLookup (varParts v) (MapVal ctx) of+  case applyPipes (varPipes v) $ multiLookup (varParts v) (MapVal ctx) of     NullVal     -> return mempty     ListVal xs  -> mapM (\iterval -> f $                     Context $ M.insert "it" iterval $ unContext ctx) xs@@ -444,7 +444,7 @@   DL.nest n <$> renderTemp t ctx renderTemp (Partial fs t) ctx = do     val' <- renderTemp t ctx-    return $ case applyFilters fs (SimpleVal val') of+    return $ case applyPipes fs (SimpleVal val') of       SimpleVal x -> x       _           -> mempty renderTemp (Concat t1 t2) ctx =
src/Text/DocTemplates/Parser.hs view
@@ -349,7 +349,7 @@             P.setPosition oldPos             return res'   P.putState oldst-  fs <- many pFilter+  fs <- many pPipe   case mbvar of     Just var -> return $ Iterate var (Partial fs t) separ     Nothing  -> return $ Partial fs t@@ -399,15 +399,15 @@ pVar = do   first <- pIdentPart <|> pIt   rest <- P.many (P.char '.' *> pIdentPart)-  filters <- P.many pFilter-  return $ Variable (first:rest) filters+  pipes <- P.many pPipe+  return $ Variable (first:rest) pipes -pFilter :: Monad m => Parser m Filter-pFilter = do+pPipe :: Monad m => Parser m Pipe+pPipe = do   P.char '/'-  filterName <- P.many1 P.letter+  pipeName <- P.many1 P.letter   P.notFollowedBy P.letter-  case filterName of+  case pipeName of     "uppercase" -> return ToUppercase     "lowercase" -> return ToLowercase     "pairs"     -> return ToPairs@@ -420,7 +420,7 @@     "left"      -> Block LeftAligned <$> pBlockWidth <*> pBlockBorders     "right"     -> Block RightAligned <$> pBlockWidth <*> pBlockBorders     "center"    -> Block Centered <$> pBlockWidth <*> pBlockBorders-    _           -> fail $ "Unknown filter " ++ filterName+    _           -> fail $ "Unknown pipe " ++ pipeName  pBlockWidth :: Monad m => Parser m Int pBlockWidth = P.try (do@@ -428,8 +428,8 @@   ds <- P.many1 P.digit   case T.decimal (T.pack ds) of         Right (n,"") -> return n-        _            -> fail "Expected integer parameter for filter") P.<?>-          "integer parameter for filter"+        _            -> fail "Expected integer parameter for pipe") P.<?>+          "integer parameter for pipe"  pBlockBorders :: Monad m => Parser m Border pBlockBorders = do
− test/filter-and-partial.test
@@ -1,16 +0,0 @@-{ "employee":-  [ { "name": { "first": "John", "last": "Doe" } }-  , { "name": { "first": "Omar", "last": "Smith" }-    , "salary": "30000" }-  , { "name": { "first": "Sara", "last": "Chen" }-    , "salary": "60000" }-  ]-}-.-$for(employee)$-$it:name()/uppercase$-$endfor$-.-(JOHN) DOE-(OMAR) SMITH-(SARA) CHEN
− test/filters.test
@@ -1,91 +0,0 @@-{ "foo": 1,-  "bar": null,-  "baz": ["a", "b"],-  "bim": { "Zub": "Sim" },-  "sup": [ { "biz": "qux" },-           { "sax": 2 } ],-  "items": [ "one with\na line break",-            "two",-            "three with\na line break" ],-  "hasblanks": "hello\n\n",-  "hasblanksmap": { "a": "hello\n\n",-                    "b": "there\n\n" },-  "digits": [1, 5, 20]-}-.-$bar/length$-$baz/length$-$bim.Zub/length$-$bim/length$-$sup/length$--$baz/uppercase[, ]$--$for(baz)$-$it$-$it/uppercase$-$baz$-$baz/uppercase$-$endfor$--$for(bim/pairs)$-$it.key$: $it.value$-$bim.key$: $bim.value/lowercase$-$endfor$--$for(baz/pairs)$-$it.key/roman/uppercase/right 4$. $it.value$-$endfor$--$items/pairs/reverse:enum()$--($hasblanks/chomp$)--$for(hasblanksmap/chomp/pairs/uppercase)$-$it.key$ ($it.value$)-$endfor$--$digits/roman[ ]$--$for(bim/uppercase)$-$it.Zub$-$endfor$-.-0-2-3-1-2--A, B--a-A-a-A-b-B-b-B--Zub: Sim-Zub: sim--   I. a-  II. b--C.  three with-    a line break-B.  two-A.  one with-    a line break---(hello)--A (HELLO)-B (THERE)--i v xx--SIM
+ test/pipe-and-partial.test view
@@ -0,0 +1,16 @@+{ "employee":+  [ { "name": { "first": "John", "last": "Doe" } }+  , { "name": { "first": "Omar", "last": "Smith" }+    , "salary": "30000" }+  , { "name": { "first": "Sara", "last": "Chen" }+    , "salary": "60000" }+  ]+}+.+$for(employee)$+$it:name()/uppercase$+$endfor$+.+(JOHN) DOE+(OMAR) SMITH+(SARA) CHEN
+ test/pipes.test view
@@ -0,0 +1,91 @@+{ "foo": 1,+  "bar": null,+  "baz": ["a", "b"],+  "bim": { "Zub": "Sim" },+  "sup": [ { "biz": "qux" },+           { "sax": 2 } ],+  "items": [ "one with\na line break",+            "two",+            "three with\na line break" ],+  "hasblanks": "hello\n\n",+  "hasblanksmap": { "a": "hello\n\n",+                    "b": "there\n\n" },+  "digits": [1, 5, 20]+}+.+$bar/length$+$baz/length$+$bim.Zub/length$+$bim/length$+$sup/length$++$baz/uppercase[, ]$++$for(baz)$+$it$+$it/uppercase$+$baz$+$baz/uppercase$+$endfor$++$for(bim/pairs)$+$it.key$: $it.value$+$bim.key$: $bim.value/lowercase$+$endfor$++$for(baz/pairs)$+$it.key/roman/uppercase/right 4$. $it.value$+$endfor$++$items/pairs/reverse:enum()$++($hasblanks/chomp$)++$for(hasblanksmap/chomp/pairs/uppercase)$+$it.key$ ($it.value$)+$endfor$++$digits/roman[ ]$++$for(bim/uppercase)$+$it.Zub$+$endfor$+.+0+2+3+1+2++A, B++a+A+a+A+b+B+b+B++Zub: Sim+Zub: sim++   I. a+  II. b++C.  three with+    a line break+B.  two+A.  one with+    a line break+++(hello)++A (HELLO)+B (THERE)++i v xx++SIM
test/test.hs view
@@ -38,18 +38,18 @@     (res :: Either String (Template T.Text)) <-         compileTemplate "foobar.txt" "$sep$"     res @?= Left "\"foobar.txt\" (line 1, column 5):\nunexpected \"$\"\nexpecting letter or digit or \"()\""-  , testCase "compile failure (unknown filter)" $ do+  , testCase "compile failure (unknown pipe)" $ do     (res :: Either String (Template T.Text)) <-         compileTemplate "foobar.txt" "$foo/nope$"-    res @?= Left "\"foobar.txt\" (line 1, column 10):\nunexpected \"$\"\nexpecting letter, letter or digit or \"()\"\nUnknown filter nope"-  , testCase "compile failure (missing parameter for filter)" $ do+    res @?= Left "\"foobar.txt\" (line 1, column 10):\nunexpected \"$\"\nexpecting letter, letter or digit or \"()\"\nUnknown pipe nope"+  , testCase "compile failure (missing parameter for pipe)" $ do     (res :: Either String (Template T.Text)) <-         compileTemplate "foobar.txt" "$foo/left$"-    res @?=  Left "\"foobar.txt\" (line 1, column 10):\nunexpected \"$\"\nexpecting letter, integer parameter for filter, letter or digit or \"()\""-  , testCase "compile failure (unexpected parameter for filter)" $ do+    res @?=  Left "\"foobar.txt\" (line 1, column 10):\nunexpected \"$\"\nexpecting letter, integer parameter for pipe, letter or digit or \"()\""+  , testCase "compile failure (unexpected parameter for pipe)" $ do     (res :: Either String (Template T.Text)) <-         compileTemplate "foobar.txt" "$foo/left a$"-    res @?= Left "\"foobar.txt\" (line 1, column 11):\nunexpected \"a\"\nexpecting integer parameter for filter"+    res @?= Left "\"foobar.txt\" (line 1, column 11):\nunexpected \"a\"\nexpecting integer parameter for pipe"   , testCase "compile failure (error in partial)" $ do       (res :: Either String (Template T.Text)) <-          compileTemplate "test/foobar.txt" "$bad()$"@@ -67,7 +67,7 @@                    (renderTemplate t (object ["foo" .= ("42" :: T.Text)]))                   Left e  -> T.pack e       res @?= "not breakable and\nthis is\nbreakable\nok? 42"-  , testCase "nowrap filter" $ do+  , testCase "nowrap pipe" $ do       (templ :: Either String (Template T.Text)) <-         compileTemplate "foo" "$foo/nowrap$\n$foo$"       let res :: T.Text