doctemplates 0.7.1 → 0.7.2
raw patch · 9 files changed
+123/−71 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Text.DocTemplates.Internal: NoWrap :: Filter
Files
- README.md +18/−19
- changelog.md +12/−0
- doctemplates.cabal +2/−1
- src/Text/DocTemplates.hs +19/−18
- src/Text/DocTemplates/Internal.hs +30/−32
- src/Text/DocTemplates/Parser.hs +1/−0
- test/filters.test +25/−1
- test/keyval.txt +1/−0
- test/test.hs +15/−0
README.md view
@@ -192,6 +192,8 @@ - If `variable` is an array, the material inside the loop will be evaluated repeatedly, with `variable` being set to each value of the array in turn, and concatenated.+- If `variable` is a map, the material inside will be set to+ the map. - If the value of the associated variable is not an array or a map, a single iteration will be performed on its value. @@ -207,6 +209,10 @@ ${ for(foo.bar) } - ${ foo.bar.last }, ${ foo.bar.first } ${ endfor }++$for(mymap)$+$it.name$: $it.office$+$endfor$ ``` You may optionally specify a separator between consecutive@@ -362,11 +368,7 @@ $for(metadata/pairs)$ - $it.key$: $it.value$ $endfor$-``` -Filters may also be applied to the results of partials:--``` $employee:name()/uppercase$ ``` @@ -395,11 +397,9 @@ value was an array, the `key` will be the array index, starting with 1. -- `uppercase`: Converts a textual value to uppercase,- and has no effect on other values.+- `uppercase`: Converts text to uppercase. -- `lowercase`: Converts a textual value to lowercase,- and has no effect on other values.+- `lowercase`: Converts text to lowercase. - `length`: Returns the length of the value: number of characters for a textual value, number of elements@@ -408,21 +408,20 @@ - `reverse`: Reverses a textual value or array, and has no effect on other values. -- `chomp`: Removes trailing newlines (and breakable space)- from a textual value, and has no effect on other values.+- `chomp`: Removes trailing newlines (and breakable space). -- `alpha`: Converts a textual value that can be- read as an integer into a lowercase alphabetic- character `a..z` (mod 26), and has no effect on- other values. This can be used to get lettered+- `nowrap`: Disables line wrapping on breakable spaces.++- `alpha`: Converts textual values that can be+ read as an integer into lowercase alphabetic+ characters `a..z` (mod 26). This can be used to get lettered enumeration from array indices. To get uppercase letters, chain with `uppercase`. -- `roman`: Converts a textual value that can be- read as an integer into a lowercase roman numerial,- and has no effect on other values. This can be used- to get lettered enumeration from array indices. To- get uppercase roman, chain with `uppercase`.+- `roman`: Converts textual values that can be+ read as an integer into lowercase roman numerials.+ This can be used to get lettered enumeration from array indices.+ To get uppercase roman, chain with `uppercase`. - `left n "leftborder" "rightborder"`: Renders a textual value in a block of width `n`, aligned to the left, with an optional
changelog.md view
@@ -1,5 +1,17 @@ # doctemplates +## 0.7.2++ * Add `nowrap` filter.++ * Improve `alpha`, `roman`, `uppercase`, `lowercase` filters so they+ apply recursively within a list or map.++ * Allow `for` loops to bind map value. In this case there is no+ iteration, but the anophoric variable 'it' is assigned, which may+ help in using filters that destructure a string into a map (if+ we add any).+ ## 0.7.1 * Add `chomp` filter.
doctemplates.cabal view
@@ -1,5 +1,5 @@ name: doctemplates-version: 0.7.1+version: 0.7.2 synopsis: Pandoc-style document templates description: This is the text templating system used by pandoc. It supports variable interpolation, iteration,@@ -54,6 +54,7 @@ build-depends: base, doctemplates, doclayout >= 0.2 && < 0.3,+ containers, aeson, Glob, tasty,
src/Text/DocTemplates.hs view
@@ -180,6 +180,7 @@ - If @variable@ is an array, the material inside the loop will be evaluated repeatedly, with @variable@ being set to each value of the array in turn, and concatenated.+- If @variable@ is a map, the material inside will be set to the map. - If the value of the associated variable is not an array or a map, a single iteration will be performed on its value. @@ -194,6 +195,10 @@ > ${ for(foo.bar) } > - ${ foo.bar.last }, ${ foo.bar.first } > ${ endfor }+>+> $for(mymap)$+> $it.name$: $it.office$+> $endfor$ You may optionally specify a separator between consecutive values using @sep@ (enclosed in matched delimiters). The material between @sep@ and@@ -317,9 +322,7 @@ > $for(metadata/pairs)$ > - $it.key$: $it.value$ > $endfor$--Filters may also be applied to the results of partials:-+> > $employee:name()/uppercase$ Filters may be chained:@@ -342,11 +345,9 @@ @key@ and @value@ fields. If the original value was an array, the @key@ will be the array index, starting with 1. -- @uppercase@: Converts a textual value to uppercase, and has no- effect on other values.+- @uppercase@: Converts text to uppercase. -- @lowercase@: Converts a textual value to lowercase, and has no- effect on other values.+- @lowercase@: Converts text to lowercase. - @length@: Returns the length of the value: number of characters for a textual value, number of elements for a map or array.@@ -354,19 +355,19 @@ - @reverse@: Reverses a textual value or array, and has no effect on other values. -- @chomp@: Removes trailing newlines (and breakable space) from a- textual value, and has no effect on other values.+- @chomp@: Removes trailing newlines (and breakable space). -- @alpha@: Converts a textual value that can be read as an integer- into a lowercase alphabetic character @a..z@ (mod 26), and has no- effect on other values. This can be used to get lettered enumeration- from array indices. To get uppercase letters, chain with- @uppercase@.+- @nowrap@: Disables line wrapping on breakable spaces. -- @roman@: Converts a textual value that can be read as an integer- into a lowercase roman numerial, and has no effect on other values.- This can be used to get lettered enumeration from array indices. To- get uppercase roman, chain with @uppercase@.+- @alpha@: Converts textual values that can be read as an integer into+ lowercase alphabetic characters @a..z@ (mod 26). This can be used to+ get lettered enumeration from array indices. To get uppercase+ letters, chain with @uppercase@.++- @roman@: Converts textual values that can be read as an integer into+ lowercase roman numerials. This can be used to get lettered+ enumeration from array indices. To get uppercase roman, chain with+ @uppercase@. - @left n \"leftborder\" \"rightborder\"@: Renders a textual value in a block of width @n@, aligned to the left, with an optional left and
src/Text/DocTemplates/Internal.hs view
@@ -95,6 +95,7 @@ | Chomp | ToAlpha | ToRoman+ | NoWrap | Block Alignment Int Border deriving (Show, Read, Data, Typeable, Generic, Eq, Ord) @@ -281,6 +282,18 @@ toYAML (ListVal xs) = toYAML xs toYAML (SimpleVal d) = toYAML $ toText $ DL.render Nothing d +mapDoc :: TemplateTarget a => (Doc a -> Doc a) -> Val a -> Val a+mapDoc f val =+ case val of+ SimpleVal d -> SimpleVal (f d)+ MapVal (Context m) -> MapVal (Context $ M.map (mapDoc f) m)+ ListVal xs -> ListVal $ map (mapDoc f) xs+ NullVal -> NullVal++mapText :: TemplateTarget a => (Text -> Text) -> Val a -> Val a+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 where@@ -289,16 +302,8 @@ MapVal (Context m) -> M.size m ListVal xs -> length xs NullVal -> 0-applyFilter ToUppercase val =- case val of- SimpleVal d -> SimpleVal . runIdentity $- traverse (pure . fromText . T.toUpper . toText) d- _ -> val-applyFilter ToLowercase val =- case val of- SimpleVal d -> SimpleVal . runIdentity $- traverse (pure . fromText . T.toLower . toText) d- _ -> val+applyFilter ToUppercase val = mapText T.toUpper val+applyFilter ToLowercase val = mapText T.toLower val applyFilter ToPairs val = case val of MapVal (Context m) ->@@ -312,30 +317,21 @@ , ("value", v) ] applyFilter Reverse val = case val of- SimpleVal d -> SimpleVal . runIdentity $- traverse (pure . fromText . T.reverse . toText) d ListVal xs -> ListVal (reverse xs)- _ -> val-applyFilter Chomp val =- case val of- SimpleVal d -> SimpleVal $ DL.chomp d- _ -> val-applyFilter ToAlpha val =- case val of- SimpleVal (DL.Text _ t) ->- case T.decimal (toText t) of- Right (y,"") -> SimpleVal $ fromString- [chr (ord 'a' + (y `mod` 26) - 1)]- _ -> val- _ -> val-applyFilter ToRoman val =- case val of- SimpleVal (DL.Text _ t) ->- case T.decimal (toText t) of- Right (y,"") -> maybe val (SimpleVal . DL.literal . fromText)- (toRoman y)- _ -> val+ SimpleVal{} -> mapText T.reverse val _ -> val+applyFilter Chomp val = mapDoc DL.chomp val+applyFilter 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+ 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 = let constructor = case align of LeftAligned -> DL.lblock@@ -413,6 +409,8 @@ NullVal -> return mempty ListVal xs -> mapM (\iterval -> f $ Context $ M.insert "it" iterval $ unContext ctx) xs+ MapVal ctx' -> (:[]) <$> f+ (Context $ M.insert "it" (MapVal ctx') $ unContext ctx) val' -> (:[]) <$> f (Context $ M.insert "it" val' $ unContext ctx) type RenderState = S.State Int
src/Text/DocTemplates/Parser.hs view
@@ -416,6 +416,7 @@ "roman" -> return ToRoman "reverse" -> return Reverse "chomp" -> return Chomp+ "nowrap" -> return NoWrap "left" -> Block LeftAligned <$> pBlockWidth <*> pBlockBorders "right" -> Block RightAligned <$> pBlockWidth <*> pBlockBorders "center" -> Block Centered <$> pBlockWidth <*> pBlockBorders
test/filters.test view
@@ -7,7 +7,10 @@ "items": [ "one with\na line break", "two", "three with\na line break" ],- "hasblanks": "hello\n\n"+ "hasblanks": "hello\n\n",+ "hasblanksmap": { "a": "hello\n\n",+ "b": "there\n\n" },+ "digits": [1, 5, 20] } . $bar/length$@@ -16,6 +19,8 @@ $bim/length$ $sup/length$ +$baz/uppercase[, ]$+ $for(baz)$ $it$ $it/uppercase$@@ -35,6 +40,16 @@ $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@@ -42,6 +57,8 @@ 1 2 +A, B+ a A a@@ -65,3 +82,10 @@ (hello)++A (HELLO)+B (THERE)++i v xx++SIM
+ test/keyval.txt view
@@ -0,0 +1,1 @@+
test/test.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE ScopedTypeVariables #-} import Text.DocLayout (render)+import qualified Text.DocLayout as DL+import qualified Data.Map as M import Text.DocTemplates import Test.Tasty.Golden import Test.Tasty@@ -65,6 +67,19 @@ (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+ (templ :: Either String (Template T.Text)) <-+ compileTemplate "foo" "$foo/nowrap$\n$foo$"+ let res :: T.Text+ res = case templ of+ Right t -> render (Just 10)+ (renderTemplate t (Context $ M.insert "foo"+ (SimpleVal $+ DL.hsep ["hello", "this", "is", "a",+ "test", "of", "the", "wrapping"]+ :: Val T.Text) mempty))+ Left e -> T.pack e+ res @?= "hello this is a test of the wrapping\nhello this\nis a test\nof the\nwrapping" ] {- The test "golden" files are structured as follows: