git.iko.soy/typeable/pandoc
on master help sign in
Merge pull request #1386 from jkr/hanging_indent

Fix hanging indent behavior

commitaad618d9dbd68d5ea625945d23674befddf3a072 authorJohn MacFarlane <jgm@berkeley.edu> dateSun 29 Jun 2014, 21:31 (12 years ago) parent45d26fd1405e7b
5 files changed+58−15
src/Text/Pandoc/Readers/Docx.hs+25−10 src/Text/Pandoc/Readers/Docx/Parse.hs+26−5 tests/Tests/Readers/Docx.hs+4 tests/docx.hanging_indent.docx tests/docx.hanging_indent.native+3
src/Text/Pandoc/Readers/Docx.hs+25−10
@@ -94,6 +94,7 @@ import System.FilePath (combine)
9494import qualified Data.Map as M
9595import Control.Monad.Reader
9696import Control.Monad.State
97+import Control.Applicative (liftA2)
9798
9899readDocx :: ReaderOptions
99100 -> B.ByteString
@@ -153,7 +154,6 @@ runStyleToContainers rPr =
153154 in
154155 classContainers ++ formatters
155156
156−
157157divAttrToContainers :: [String] -> [(String, String)] -> [Container Block]
158158divAttrToContainers (c:cs) _ | Just n <- isHeaderClass c =
159159 [Container $ \_ ->
@@ -171,22 +171,37 @@ divAttrToContainers (c:cs) kvs | c `elem` listParagraphDivs =
171171divAttrToContainers (c:cs) kvs | c `elem` blockQuoteDivs =
172172 (Container BlockQuote) : (divAttrToContainers (cs \\ blockQuoteDivs) kvs)
173173divAttrToContainers (_:cs) kvs = divAttrToContainers cs kvs
174−divAttrToContainers [] kvs | Just numString <- lookup "indent" kvs =
175− let kvs' = filter (\(k,_) -> k /= "indent") kvs
174+divAttrToContainers [] kvs | Just _ <- lookup "indent" kvs
175+ , Just flInd <- lookup "first-line-indent" kvs =
176+ let
177+ kvs' = filter (\(k,_) -> notElem k ["indent", "first-line-indent"]) kvs
176178 in
177− case numString of
178− "0" -> divAttrToContainers [] kvs'
179− ('-' : _) -> divAttrToContainers [] kvs'
180− _ -> (Container BlockQuote) : divAttrToContainers [] kvs'
179+ case flInd of
180+ "0" -> divAttrToContainers [] kvs'
181+ ('-':_) -> divAttrToContainers [] kvs'
182+ _ -> (Container BlockQuote) : divAttrToContainers [] kvs'
183+divAttrToContainers [] kvs | Just ind <- lookup "indent" kvs =
184+ let
185+ kvs' = filter (\(k,_) -> notElem k ["indent"]) kvs
186+ in
187+ case ind of
188+ "0" -> divAttrToContainers [] kvs'
189+ ('-':_) -> divAttrToContainers [] kvs'
190+ _ -> (Container BlockQuote) : divAttrToContainers [] kvs'
191+
181192divAttrToContainers _ _ = []
182193
183194
184195parStyleToContainers :: ParagraphStyle -> [Container Block]
185196parStyleToContainers pPr =
186197 let classes = pStyle pPr
187− kvs = case indent pPr of
188− Just n -> [("indent", show n)]
189− Nothing -> []
198+ indent = indentation pPr >>= leftParIndent
199+ hanging = indentation pPr >>= hangingParIndent
200+ firstLineIndent = liftA2 (-) indent hanging
201+ kvs = mapMaybe id
202+ [ indent >>= (\n -> Just ("indent", show n)),
203+ firstLineIndent >>= (\n -> Just ("first-line-indent", show n))
204+ ]
190205 in
191206 divAttrToContainers classes kvs
192207
src/Text/Pandoc/Readers/Docx/Parse.hs+26−5
@@ -42,6 +42,7 @@ module Text.Pandoc.Readers.Docx.Parse ( Docx(..)
4242 , Relationship
4343 , Media
4444 , RunStyle(..)
45+ , ParIndentation(..)
4546 , ParagraphStyle(..)
4647 , Row(..)
4748 , Cell(..)
@@ -341,16 +342,37 @@ testBitMask bitMaskS n =
341342 [] -> False
342343 ((n', _) : _) -> ((n' .|. n) /= 0)
343344
345+data ParIndentation = ParIndentation { leftParIndent :: Maybe Integer
346+ , rightParIndent :: Maybe Integer
347+ , hangingParIndent :: Maybe Integer}
348+ deriving Show
349+
344350data ParagraphStyle = ParagraphStyle { pStyle :: [String]
345− , indent :: Maybe Integer
351+ , indentation :: Maybe ParIndentation
346352 }
347353 deriving Show
348354
349355defaultParagraphStyle :: ParagraphStyle
350356defaultParagraphStyle = ParagraphStyle { pStyle = []
351− , indent = Nothing
357+ , indentation = Nothing
352358 }
353359
360+elemToParIndentation :: NameSpaces -> Element -> Maybe ParIndentation
361+elemToParIndentation ns element
362+ | qName (elName element) == "ind" &&
363+ qURI (elName element) == (lookup "w" ns) =
364+ Just $ ParIndentation {
365+ leftParIndent =
366+ findAttr (QName "left" (lookup "w" ns) (Just "w")) element >>=
367+ stringToInteger
368+ , rightParIndent =
369+ findAttr (QName "right" (lookup "w" ns) (Just "w")) element >>=
370+ stringToInteger
371+ , hangingParIndent =
372+ findAttr (QName "hanging" (lookup "w" ns) (Just "w")) element >>=
373+ stringToInteger}
374+elemToParIndentation _ _ = Nothing
375+
354376elemToParagraphStyle :: NameSpaces -> Element -> ParagraphStyle
355377elemToParagraphStyle ns element =
356378 case findChild (QName "pPr" (lookup "w" ns) (Just "w")) element of
@@ -360,10 +382,9 @@ elemToParagraphStyle ns element =
360382 mapMaybe
361383 (findAttr (QName "val" (lookup "w" ns) (Just "w")))
362384 (findChildren (QName "pStyle" (lookup "w" ns) (Just "w")) pPr)
363− , indent =
385+ , indentation =
364386 findChild (QName "ind" (lookup "w" ns) (Just "w")) pPr >>=
365− findAttr (QName "left" (lookup "w" ns) (Just "w")) >>=
366− stringToInteger
387+ elemToParIndentation ns
367388 }
368389 Nothing -> defaultParagraphStyle
369390
tests/Tests/Readers/Docx.hs+4
@@ -112,6 +112,10 @@ tests = [ testGroup "inlines"
112112 "blockquotes (parsing indent as blockquote)"
113113 "docx.block_quotes.docx"
114114 "docx.block_quotes_parse_indent.native"
115+ , testCompare
116+ "hanging indents"
117+ "docx.hanging_indent.docx"
118+ "docx.hanging_indent.native"
115119 , testCompare
116120 "tables"
117121 "docx.tables.docx"
tests/docx.hanging_indent.docxnew file

Binary file not shown.

tests/docx.hanging_indent.nativenew file+3
@@ -0,0 +1,3 @@
1+[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "hanging",Space,Str "indent,",Space,Str "with",Space,Str "the",Space,Str "left",Space,Str "side",Space,Str "set",Space,Str "to",Space,Str "the",Space,Str "left",Space,Str "margin,",Space,Str "and",Space,Str "it",Space,Str "wraps",Space,Str "around",Space,Str "the",Space,Str "line."]
2+,BlockQuote
3+ [Para [Str "Five",Space,Str "years",Space,Str "have",Space,Str "passed,",Space,Str "five",Space,Str "summers",Space,Str "with",Space,Str "the",Space,Str "length"]]]