From b1eba3c65ca2981c78b66d1ee9218f3dfeda89c7 Mon Sep 17 00:00:00 2001
From: Jesse Rosenthal <jrosenthal@jhu.edu>
Date: Sun, 29 Jun 2014 08:14:36 -0400
Subject: [PATCH 1/8] Docx Reader: Update state properly

Previously, a fresh state was created for the purpose of updating. In
the future, when there is more than one field in the state, this
obviously won't work.
---
 src/Text/Pandoc/Readers/Docx.hs | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs
index 71baa5dde..2e10ae3a4 100644
--- a/src/Text/Pandoc/Readers/Docx.hs
+++ b/src/Text/Pandoc/Readers/Docx.hs
@@ -110,6 +110,11 @@ data DEnv = DEnv { docxOptions  :: ReaderOptions
 
 type DocxContext = ReaderT DEnv (State DState)
 
+updateDState :: (DState -> DState) -> DocxContext ()
+updateDState f = do
+  st <- get
+  put $ f st
+
 evalDocxContext :: DocxContext a -> DEnv -> DState -> a
 evalDocxContext ctx env st = evalState (runReaderT ctx env) st
 
@@ -289,7 +294,7 @@ parPartToInlines (BookMark _ anchor) =
     let newAnchor = case anchor `elem` (M.elems anchorMap) of
           True -> uniqueIdent [Str anchor] (M.elems anchorMap)
           False -> anchor
-    put DState{ docxAnchorMap = M.insert anchor newAnchor anchorMap}
+    updateDState $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap}
     return [Span (anchor, ["anchor"], []) []]
 parPartToInlines (Drawing relid) = do
   (Docx _ _ _ rels _) <- asks docxDocument
@@ -329,7 +334,7 @@ makeHeaderAnchor (Header n (_, classes, kvs) ils)
     do
       hdrIDMap <- gets docxAnchorMap
       let newIdent = uniqueIdent ils (M.elems hdrIDMap)
-      put DState{docxAnchorMap = M.insert ident newIdent hdrIDMap}
+      updateDState $ \s -> s {docxAnchorMap = M.insert ident newIdent hdrIDMap}
       return $ Header n (newIdent, classes, kvs) (ils \\ (x:xs))
 -- Otherwise we just give it a name, and register that name (associate
 -- it with itself.)
@@ -337,7 +342,7 @@ makeHeaderAnchor (Header n (_, classes, kvs) ils) =
   do
     hdrIDMap <- gets docxAnchorMap
     let newIdent = uniqueIdent ils (M.elems hdrIDMap)
-    put DState{docxAnchorMap = M.insert newIdent newIdent hdrIDMap}
+    updateDState $ \s -> s {docxAnchorMap = M.insert newIdent newIdent hdrIDMap}
     return $ Header n (newIdent, classes, kvs) ils
 makeHeaderAnchor blk = return blk
 

From 0587334bc0c87ae62f37cf14543b7727d408aeca Mon Sep 17 00:00:00 2001
From: Jesse Rosenthal <jrosenthal@jhu.edu>
Date: Sun, 29 Jun 2014 16:38:51 -0400
Subject: [PATCH 2/8] Docx writer: insert bookmark tags inside <w:p> tag.

This makes the header anchors in pandoc-generated ooxml match those
generated by word.
---
 src/Text/Pandoc/Writers/Docx.hs | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
index 31e64f14e..4b787b023 100644
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -514,8 +514,11 @@ blockToOpenXML :: WriterOptions -> Block -> WS [Element]
 blockToOpenXML _ Null = return []
 blockToOpenXML opts (Div _ bs) = blocksToOpenXML opts bs
 blockToOpenXML opts (Header lev (ident,_,_) lst) = do
-  contents <- withParaProp (pStyle $ "Heading" ++ show lev) $
-               blockToOpenXML opts (Para lst)
+
+  paraProps <- withParaProp (pStyle $ "Heading" ++ show lev) $
+               getParaProps False
+  contents <- inlinesToOpenXML opts lst
+
   usedIdents <- gets stSectionIds
   let bookmarkName = if null ident
                         then uniqueIdent lst usedIdents
@@ -525,7 +528,7 @@ blockToOpenXML opts (Header lev (ident,_,_) lst) = do
   let bookmarkStart = mknode "w:bookmarkStart" [("w:id", id')
                                                ,("w:name",bookmarkName)] ()
   let bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()
-  return $ [bookmarkStart] ++ contents ++ [bookmarkEnd]
+  return [mknode "w:p" [] (paraProps ++ [bookmarkStart, bookmarkEnd] ++ contents)]
 blockToOpenXML opts (Plain lst) = withParaProp (pStyle "Compact")
   $ blockToOpenXML opts (Para lst)
 -- title beginning with fig: indicates that the image is a figure

From c0fcc8a7891892357854cf498ce262b256fac1ca Mon Sep 17 00:00:00 2001
From: Jesse Rosenthal <jrosenthal@jhu.edu>
Date: Sun, 29 Jun 2014 18:44:22 -0400
Subject: [PATCH 3/8] Docx reader: Add ParIndentation type to parser.

This lets us keep more information about the indentation, and act
accordingly in the reader.
---
 src/Text/Pandoc/Readers/Docx/Parse.hs | 31 ++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/src/Text/Pandoc/Readers/Docx/Parse.hs b/src/Text/Pandoc/Readers/Docx/Parse.hs
index 07f34450d..537c5c272 100644
--- a/src/Text/Pandoc/Readers/Docx/Parse.hs
+++ b/src/Text/Pandoc/Readers/Docx/Parse.hs
@@ -42,6 +42,7 @@ module Text.Pandoc.Readers.Docx.Parse (  Docx(..)
                                        , Relationship
                                        , Media
                                        , RunStyle(..)
+                                       , ParIndentation(..)
                                        , ParagraphStyle(..)
                                        , Row(..)
                                        , Cell(..)
@@ -341,16 +342,37 @@ testBitMask bitMaskS n =
     []            -> False
     ((n', _) : _) -> ((n' .|. n) /= 0)
 
+data ParIndentation = ParIndentation { leftParIndent :: Maybe Integer
+                                     , rightParIndent :: Maybe Integer
+                                     , hangingParIndent :: Maybe Integer}
+                      deriving Show
+
 data ParagraphStyle = ParagraphStyle { pStyle :: [String]
-                                     , indent :: Maybe Integer
+                                     , indentation :: Maybe ParIndentation
                                      }
                       deriving Show
 
 defaultParagraphStyle :: ParagraphStyle
 defaultParagraphStyle = ParagraphStyle { pStyle = []
-                                       , indent = Nothing
+                                       , indentation = Nothing
                                        }
 
+elemToParIndentation :: NameSpaces -> Element -> Maybe ParIndentation
+elemToParIndentation ns element
+  | qName (elName element) == "ind" &&
+    qURI (elName element) == (lookup "w" ns) =
+      Just $ ParIndentation {
+        leftParIndent =
+           findAttr (QName "left" (lookup "w" ns) (Just "w")) element >>=
+           stringToInteger
+        , rightParIndent = 
+          findAttr (QName "right" (lookup "w" ns) (Just "w")) element >>=
+          stringToInteger
+        , hangingParIndent = 
+          findAttr (QName "hanging" (lookup "w" ns) (Just "w")) element >>=
+          stringToInteger}
+elemToParIndentation _ _ = Nothing
+
 elemToParagraphStyle :: NameSpaces -> Element -> ParagraphStyle
 elemToParagraphStyle ns element =
   case findChild (QName "pPr" (lookup "w" ns) (Just "w")) element of
@@ -360,10 +382,9 @@ elemToParagraphStyle ns element =
           mapMaybe
           (findAttr (QName "val" (lookup "w" ns) (Just "w")))
           (findChildren (QName "pStyle" (lookup "w" ns) (Just "w")) pPr)
-      , indent =
+      , indentation =
         findChild (QName "ind" (lookup "w" ns) (Just "w")) pPr >>=
-        findAttr (QName "left" (lookup "w" ns) (Just "w")) >>=
-        stringToInteger
+        elemToParIndentation ns
         }
     Nothing -> defaultParagraphStyle
 

From 0f59196e0ef2f0977d404699ae16a48009fa7632 Mon Sep 17 00:00:00 2001
From: Jesse Rosenthal <jrosenthal@jhu.edu>
Date: Sun, 29 Jun 2014 22:50:29 -0400
Subject: [PATCH 4/8] Docx reader: Make use of new ParIndentation info.

Here, when hanging indents are greater than or equal to left indents, we
don't set it to block quote. Such indents are frequently used in
academic bibliographies. (Thanks to Caleb McDaniel.)
---
 src/Text/Pandoc/Readers/Docx.hs | 35 +++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs
index 71baa5dde..8357b4cca 100644
--- a/src/Text/Pandoc/Readers/Docx.hs
+++ b/src/Text/Pandoc/Readers/Docx.hs
@@ -94,6 +94,7 @@ import System.FilePath (combine)
 import qualified Data.Map as M
 import Control.Monad.Reader
 import Control.Monad.State
+import Control.Applicative (liftA2)
 
 readDocx :: ReaderOptions
          -> B.ByteString
@@ -148,7 +149,6 @@ runStyleToContainers rPr =
   in
    classContainers ++ formatters
 
-
 divAttrToContainers :: [String] -> [(String, String)] -> [Container Block]
 divAttrToContainers (c:cs) _ | Just n <- isHeaderClass c =
   [Container $ \_ ->
@@ -166,22 +166,37 @@ divAttrToContainers (c:cs) kvs | c `elem` listParagraphDivs =
 divAttrToContainers (c:cs) kvs | c `elem` blockQuoteDivs =
   (Container BlockQuote) : (divAttrToContainers (cs \\ blockQuoteDivs) kvs)
 divAttrToContainers (_:cs) kvs = divAttrToContainers cs kvs
-divAttrToContainers [] kvs | Just numString <- lookup "indent" kvs =
-  let kvs' = filter (\(k,_) -> k /= "indent") kvs
+divAttrToContainers [] kvs | Just _ <- lookup "indent" kvs
+                           , Just flInd <- lookup "first-line-indent" kvs =
+  let
+    kvs' = filter (\(k,_) -> notElem k ["indent", "first-line-indent"]) kvs
   in
-   case numString of
-     "0"       -> divAttrToContainers [] kvs'
-     ('-' : _) -> divAttrToContainers [] kvs'
-     _         -> (Container BlockQuote) : divAttrToContainers [] kvs'
+   case flInd of
+     "0" -> divAttrToContainers [] kvs'
+     ('-':_) -> divAttrToContainers [] kvs'
+     _       -> (Container BlockQuote) : divAttrToContainers [] kvs'
+divAttrToContainers [] kvs | Just ind <- lookup "indent" kvs =
+  let
+    kvs' = filter (\(k,_) -> notElem k ["indent"]) kvs
+  in
+   case ind of
+     "0" -> divAttrToContainers [] kvs'
+     ('-':_) -> divAttrToContainers [] kvs'
+     _       -> (Container BlockQuote) : divAttrToContainers [] kvs'
+
 divAttrToContainers _ _ = []
 
 
 parStyleToContainers :: ParagraphStyle -> [Container Block]
 parStyleToContainers pPr =
   let classes = pStyle pPr
-      kvs = case indent pPr of
-        Just n -> [("indent", show n)]
-        Nothing -> []
+      indent = indentation pPr >>= leftParIndent
+      hanging = indentation pPr >>= hangingParIndent
+      firstLineIndent = liftA2 (-) indent hanging
+      kvs = mapMaybe id
+            [ indent >>= (\n -> Just ("indent", show n)),
+              firstLineIndent >>= (\n -> Just ("first-line-indent", show n))
+              ]
   in
    divAttrToContainers classes kvs
   

From 1405e7b7091dedb50578c9e0cafd62f2c77ca689 Mon Sep 17 00:00:00 2001
From: Jesse Rosenthal <jrosenthal@jhu.edu>
Date: Sun, 29 Jun 2014 23:37:00 -0400
Subject: [PATCH 5/8] Docx reader: Add tests for hanging indent handline.

We want to treat it as a plain paragraph if the hanging amount is
greater to or equal to the left indent---i.e., if the first line has
zero indentation. But we still want it to be a block quote if it starts
to the right of the margin. Someone might format verse with wrapping
lines with a hanging indent, for example.
---
 tests/Tests/Readers/Docx.hs      |   4 ++++
 tests/docx.hanging_indent.docx   | Bin 0 -> 29924 bytes
 tests/docx.hanging_indent.native |   3 +++
 3 files changed, 7 insertions(+)
 create mode 100644 tests/docx.hanging_indent.docx
 create mode 100644 tests/docx.hanging_indent.native

diff --git a/tests/Tests/Readers/Docx.hs b/tests/Tests/Readers/Docx.hs
index 8c51217cf..a379bbf23 100644
--- a/tests/Tests/Readers/Docx.hs
+++ b/tests/Tests/Readers/Docx.hs
@@ -112,6 +112,10 @@ tests = [ testGroup "inlines"
             "blockquotes (parsing indent as blockquote)"
             "docx.block_quotes.docx"
             "docx.block_quotes_parse_indent.native"
+          , testCompare
+            "hanging indents"
+            "docx.hanging_indent.docx"
+            "docx.hanging_indent.native"
           , testCompare
             "tables"
             "docx.tables.docx"
diff --git a/tests/docx.hanging_indent.docx b/tests/docx.hanging_indent.docx
new file mode 100644
index 0000000000000000000000000000000000000000..6f62dc7315e7befbc4ab8ccacd4c4cb61d8891f1
GIT binary patch
literal 29924
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
QH30rmgJSyn=E2?n0f&Po;s5{u

literal 0
HcmV?d00001

diff --git a/tests/docx.hanging_indent.native b/tests/docx.hanging_indent.native
new file mode 100644
index 000000000..138a6967f
--- /dev/null
+++ b/tests/docx.hanging_indent.native
@@ -0,0 +1,3 @@
+[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."]
+,BlockQuote
+ [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"]]]

From 3fbbafd391334429df49255160ace17245409e41 Mon Sep 17 00:00:00 2001
From: John MacFarlane <jgm@berkeley.edu>
Date: Sun, 29 Jun 2014 23:03:12 -0700
Subject: [PATCH 6/8] Rewrote normalize for efficiency. (Closes #1385.)

* Added normalizeInlines, normalizeBlocks.
* Type signature is now more narrow, `Pandoc -> Pandoc` instead of
  `Data a :: a -> a`.  Some users may need to change their uses of
  `normalize` to the newly exported `normalizeInlines` or
  `normalizeBlocks`.
---
 man/make-pandoc-man-pages.hs |   6 +-
 src/Text/Pandoc/Shared.hs    | 187 ++++++++++++++++++++++++-----------
 tests/Tests/Shared.hs        |   8 +-
 3 files changed, 137 insertions(+), 64 deletions(-)

diff --git a/man/make-pandoc-man-pages.hs b/man/make-pandoc-man-pages.hs
index 008294433..afba9135a 100644
--- a/man/make-pandoc-man-pages.hs
+++ b/man/make-pandoc-man-pages.hs
@@ -27,7 +27,7 @@ main = do
 
   unless (null ds1 && null ds2) $ do
     rmContents <- UTF8.readFile "README"
-    let (Pandoc meta blocks) = readMarkdown def rmContents
+    let (Pandoc meta blocks) = normalize $ readMarkdown def rmContents
     let manBlocks = removeSect [Str "Wrappers"]
                   $ removeSect [Str "Pandoc's",Space,Str "markdown"] blocks
     let syntaxBlocks = extractSect [Str "Pandoc's",Space,Str "markdown"] blocks
@@ -67,13 +67,13 @@ capitalize (Str xs) = Str $ map toUpper xs
 capitalize x = x
 
 removeSect :: [Inline] -> [Block] -> [Block]
-removeSect ils (Header 1 _ x:xs) | normalize x == normalize ils =
+removeSect ils (Header 1 _ x:xs) | x == ils =
   dropWhile (not . isHeader1) xs
 removeSect ils (x:xs) = x : removeSect ils xs
 removeSect _ [] = []
 
 extractSect :: [Inline] -> [Block] -> [Block]
-extractSect ils (Header 1 _ z:xs) | normalize z == normalize ils =
+extractSect ils (Header 1 _ z:xs) | z == ils =
   bottomUp promoteHeader $ takeWhile (not . isHeader1) xs
     where promoteHeader (Header n attr x) = Header (n-1) attr x
           promoteHeader x            = x
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
index 5b0d9b6b4..4a536330d 100644
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -55,6 +55,8 @@ module Text.Pandoc.Shared (
                      normalizeSpaces,
                      extractSpaces,
                      normalize,
+                     normalizeInlines,
+                     normalizeBlocks,
                      stringify,
                      compactify,
                      compactify',
@@ -84,7 +86,6 @@ module Text.Pandoc.Shared (
 
 import Text.Pandoc.Definition
 import Text.Pandoc.Walk
-import Text.Pandoc.Generic
 import Text.Pandoc.Builder (Inlines, Blocks, ToMetaValue(..))
 import qualified Text.Pandoc.Builder as B
 import qualified Text.Pandoc.UTF8 as UTF8
@@ -350,72 +351,142 @@ extractSpaces f is =
 -- | Normalize @Pandoc@ document, consolidating doubled 'Space's,
 -- combining adjacent 'Str's and 'Emph's, remove 'Null's and
 -- empty elements, etc.
-normalize :: (Eq a, Data a) => a -> a
-normalize = topDown removeEmptyBlocks .
-            topDown consolidateInlines .
-            bottomUp (removeEmptyInlines . removeTrailingInlineSpaces)
+normalize :: Pandoc -> Pandoc
+normalize (Pandoc (Meta meta) blocks) =
+  Pandoc (Meta $ M.map go meta) (normalizeBlocks blocks)
+  where go (MetaInlines xs) = MetaInlines $ normalizeInlines xs
+        go (MetaBlocks xs)  = MetaBlocks  $ normalizeBlocks xs
+        go (MetaList ms)    = MetaList $ map go ms
+        go (MetaMap m)      = MetaMap $ M.map go m
+        go x                = x
 
-removeEmptyBlocks :: [Block] -> [Block]
-removeEmptyBlocks (Null : xs) = removeEmptyBlocks xs
-removeEmptyBlocks (BulletList [] : xs) = removeEmptyBlocks xs
-removeEmptyBlocks (OrderedList _ [] : xs) = removeEmptyBlocks xs
-removeEmptyBlocks (DefinitionList [] : xs) = removeEmptyBlocks xs
-removeEmptyBlocks (RawBlock _ [] : xs) = removeEmptyBlocks xs
-removeEmptyBlocks (x:xs) = x : removeEmptyBlocks xs
-removeEmptyBlocks [] = []
+normalizeBlocks :: [Block] -> [Block]
+normalizeBlocks (Null : xs) = normalizeBlocks xs
+normalizeBlocks (Div attr bs : xs) =
+  Div attr (normalizeBlocks bs) : normalizeBlocks xs
+normalizeBlocks (BlockQuote bs : xs) =
+  case normalizeBlocks bs of
+       []    -> normalizeBlocks xs
+       bs'   -> BlockQuote bs' : normalizeBlocks xs
+normalizeBlocks (BulletList [] : xs) = normalizeBlocks xs
+normalizeBlocks (BulletList items : xs) =
+  BulletList (map normalizeBlocks items) : normalizeBlocks xs
+normalizeBlocks (OrderedList _ [] : xs) = normalizeBlocks xs
+normalizeBlocks (OrderedList attr items : xs) =
+  OrderedList attr (map normalizeBlocks items) : normalizeBlocks xs
+normalizeBlocks (DefinitionList [] : xs) = normalizeBlocks xs
+normalizeBlocks (DefinitionList items : xs) =
+  DefinitionList (map go items) : normalizeBlocks xs
+  where go (ils, bs) = (normalizeInlines ils, map normalizeBlocks bs)
+normalizeBlocks (RawBlock _ "" : xs) = normalizeBlocks xs
+normalizeBlocks (Para ils : xs) =
+  case normalizeInlines ils of
+       []   -> normalizeBlocks xs
+       ils' -> Para ils' : normalizeBlocks xs
+normalizeBlocks (Plain ils : xs) =
+  case normalizeInlines ils of
+       []   -> normalizeBlocks xs
+       ils' -> Plain ils' : normalizeBlocks xs
+normalizeBlocks (Header lev attr ils : xs) =
+  Header lev attr (normalizeInlines ils) : normalizeBlocks xs
+normalizeBlocks (Table capt aligns widths hdrs rows : xs) =
+  Table (normalizeInlines capt) aligns widths
+    (map normalizeBlocks hdrs) (map (map normalizeBlocks) rows)
+  : normalizeBlocks xs
+normalizeBlocks (x:xs) = x : normalizeBlocks xs
+normalizeBlocks [] = []
 
-removeEmptyInlines :: [Inline] -> [Inline]
-removeEmptyInlines (Emph [] : zs) = removeEmptyInlines zs
-removeEmptyInlines (Strong [] : zs) = removeEmptyInlines zs
-removeEmptyInlines (Subscript [] : zs) = removeEmptyInlines zs
-removeEmptyInlines (Superscript [] : zs) = removeEmptyInlines zs
-removeEmptyInlines (SmallCaps [] : zs) = removeEmptyInlines zs
-removeEmptyInlines (Strikeout [] : zs) = removeEmptyInlines zs
-removeEmptyInlines (RawInline _ [] : zs) = removeEmptyInlines zs
-removeEmptyInlines (Code _ [] : zs) = removeEmptyInlines zs
-removeEmptyInlines (Str "" : zs) = removeEmptyInlines zs
-removeEmptyInlines (x : xs) = x : removeEmptyInlines xs
-removeEmptyInlines [] = []
-
-removeTrailingInlineSpaces :: [Inline] -> [Inline]
-removeTrailingInlineSpaces = reverse . removeLeadingInlineSpaces . reverse
-
-removeLeadingInlineSpaces :: [Inline] -> [Inline]
-removeLeadingInlineSpaces = dropWhile isSpaceOrEmpty
-
-consolidateInlines :: [Inline] -> [Inline]
-consolidateInlines (Str x : ys) =
+normalizeInlines :: [Inline] -> [Inline]
+normalizeInlines (Str x : ys) =
   case concat (x : map fromStr strs) of
-        ""     -> consolidateInlines rest
-        n      -> Str n : consolidateInlines rest
+        ""     -> rest
+        n      -> Str n : rest
    where
-     (strs, rest)  = span isStr ys
+     (strs, rest)  = span isStr $ normalizeInlines ys
      isStr (Str _) = True
      isStr _       = False
      fromStr (Str z) = z
-     fromStr _       = error "consolidateInlines - fromStr - not a Str"
-consolidateInlines (Space : ys) = Space : rest
+     fromStr _       = error "normalizeInlines - fromStr - not a Str"
+normalizeInlines (Space : ys) =
+  if null rest
+     then []
+     else Space : rest
    where isSp Space = True
          isSp _     = False
-         rest       = consolidateInlines $ dropWhile isSp ys
-consolidateInlines (Emph xs : Emph ys : zs) = consolidateInlines $
-  Emph (xs ++ ys) : zs
-consolidateInlines (Strong xs : Strong ys : zs) = consolidateInlines $
-  Strong (xs ++ ys) : zs
-consolidateInlines (Subscript xs : Subscript ys : zs) = consolidateInlines $
-  Subscript (xs ++ ys) : zs
-consolidateInlines (Superscript xs : Superscript ys : zs) = consolidateInlines $
-  Superscript (xs ++ ys) : zs
-consolidateInlines (SmallCaps xs : SmallCaps ys : zs) = consolidateInlines $
-  SmallCaps (xs ++ ys) : zs
-consolidateInlines (Strikeout xs : Strikeout ys : zs) = consolidateInlines $
-  Strikeout (xs ++ ys) : zs
-consolidateInlines (RawInline f x : RawInline f' y : zs) | f == f' =
-  consolidateInlines $ RawInline f (x ++ y) : zs
-consolidateInlines (Code a1 x : Code a2 y : zs) | a1 == a2 =
-  consolidateInlines $ Code a1 (x ++ y) : zs
-consolidateInlines (x : xs) = x : consolidateInlines xs
-consolidateInlines [] = []
+         rest       = dropWhile isSp $ normalizeInlines ys
+normalizeInlines (Emph xs : zs) =
+  case normalizeInlines zs of
+       (Emph ys : rest) -> normalizeInlines $
+         Emph (normalizeInlines $ xs ++ ys) : rest
+       rest -> case normalizeInlines xs of
+                    []  -> rest
+                    xs' -> Emph xs' : rest
+normalizeInlines (Strong xs : zs) =
+  case normalizeInlines zs of
+       (Strong ys : rest) -> normalizeInlines $
+         Strong (normalizeInlines $ xs ++ ys) : rest
+       rest -> case normalizeInlines xs of
+                    []  -> rest
+                    xs' -> Strong xs' : rest
+normalizeInlines (Subscript xs : zs) =
+  case normalizeInlines zs of
+       (Subscript ys : rest) -> normalizeInlines $
+         Subscript (normalizeInlines $ xs ++ ys) : rest
+       rest -> case normalizeInlines xs of
+                    []  -> rest
+                    xs' -> Subscript xs' : rest
+normalizeInlines (Superscript xs : zs) =
+  case normalizeInlines zs of
+       (Superscript ys : rest) -> normalizeInlines $
+         Superscript (normalizeInlines $ xs ++ ys) : rest
+       rest -> case normalizeInlines xs of
+                    []  -> rest
+                    xs' -> Superscript xs' : rest
+normalizeInlines (SmallCaps xs : zs) =
+  case normalizeInlines zs of
+       (SmallCaps ys : rest) -> normalizeInlines $
+         SmallCaps (normalizeInlines $ xs ++ ys) : rest
+       rest -> case normalizeInlines xs of
+                    []  -> rest
+                    xs' -> SmallCaps xs' : rest
+normalizeInlines (Strikeout xs : zs) =
+  case normalizeInlines zs of
+       (Strikeout ys : rest) -> normalizeInlines $
+         Strikeout (normalizeInlines $ xs ++ ys) : rest
+       rest -> case normalizeInlines xs of
+                    []  -> rest
+                    xs' -> Strikeout xs' : rest
+normalizeInlines (RawInline _ [] : ys) = normalizeInlines ys
+normalizeInlines (RawInline f xs : zs) =
+  case normalizeInlines zs of
+       (RawInline f' ys : rest) | f == f' -> normalizeInlines $
+         RawInline f (xs ++ ys) : rest
+       rest -> RawInline f xs : rest
+normalizeInlines (Code _ "" : ys) = normalizeInlines ys
+normalizeInlines (Code attr xs : zs) =
+  case normalizeInlines zs of
+       (Code attr' ys : rest) | attr == attr' -> normalizeInlines $
+         Code attr (xs ++ ys) : rest
+       rest -> Code attr xs : rest
+-- allow empty spans, they may carry identifiers etc.
+-- normalizeInlines (Span _ [] : ys) = normalizeInlines ys
+normalizeInlines (Span attr xs : zs) =
+  case normalizeInlines zs of
+       (Span attr' ys : rest) | attr == attr' -> normalizeInlines $
+         Span attr (normalizeInlines $ xs ++ ys) : rest
+       rest -> Span attr (normalizeInlines xs) : rest
+normalizeInlines (Note bs : ys) = Note (normalizeBlocks bs) :
+  normalizeInlines ys
+normalizeInlines (Quoted qt ils : ys) =
+  Quoted qt (normalizeInlines ils) : normalizeInlines ys
+normalizeInlines (Link ils t : ys) =
+  Link (normalizeInlines ils) t : normalizeInlines ys
+normalizeInlines (Image ils t : ys) =
+  Image (normalizeInlines ils) t : normalizeInlines ys
+normalizeInlines (Cite cs ils : ys) =
+  Cite cs (normalizeInlines ils) : normalizeInlines ys
+normalizeInlines (x : xs) = x : normalizeInlines xs
+normalizeInlines [] = []
 
 -- | Convert pandoc structure to a string with formatting removed.
 -- Footnotes are skipped (since we don't want their contents in link
diff --git a/tests/Tests/Shared.hs b/tests/Tests/Shared.hs
index f4bf13da4..8c7c31674 100644
--- a/tests/Tests/Shared.hs
+++ b/tests/Tests/Shared.hs
@@ -16,11 +16,13 @@ tests = [ testGroup "normalize"
         ]
 
 p_normalize_blocks_rt :: [Block] -> Bool
-p_normalize_blocks_rt bs = normalize bs == normalize (normalize bs)
+p_normalize_blocks_rt bs =
+  normalizeBlocks bs == normalizeBlocks (normalizeBlocks bs)
 
 p_normalize_inlines_rt :: [Inline] -> Bool
-p_normalize_inlines_rt ils = normalize ils == normalize (normalize ils)
+p_normalize_inlines_rt ils =
+  normalizeInlines ils == normalizeInlines (normalizeInlines ils)
 
 p_normalize_no_trailing_spaces :: [Inline] -> Bool
 p_normalize_no_trailing_spaces ils = null ils' || last ils' /= Space
-  where ils' = normalize $ ils ++ [Space]
+  where ils' = normalizeInlines $ ils ++ [Space]

From 0abfd386a4697bab78ca098fe439623aad5f4069 Mon Sep 17 00:00:00 2001
From: Jesse Rosenthal <jrosenthal@jhu.edu>
Date: Mon, 30 Jun 2014 11:19:06 -0400
Subject: [PATCH 7/8] Docx reader: clean up parStyle processing.

This gets rid of `divAttrToContainers`: an internal convenience function
which had become pretty inconvenient. Rather than converting classes and
indentations to string lists and back, we deal with the `pPr` attribute
directly.
---
 src/Text/Pandoc/Readers/Docx.hs | 81 +++++++++++++++------------------
 1 file changed, 36 insertions(+), 45 deletions(-)

diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs
index 6e9cf44b5..61c17156e 100644
--- a/src/Text/Pandoc/Readers/Docx.hs
+++ b/src/Text/Pandoc/Readers/Docx.hs
@@ -94,7 +94,6 @@ import System.FilePath (combine)
 import qualified Data.Map as M
 import Control.Monad.Reader
 import Control.Monad.State
-import Control.Applicative (liftA2)
 
 readDocx :: ReaderOptions
          -> B.ByteString
@@ -154,56 +153,48 @@ runStyleToContainers rPr =
   in
    classContainers ++ formatters
 
-divAttrToContainers :: [String] -> [(String, String)] -> [Container Block]
-divAttrToContainers (c:cs) _ | Just n <- isHeaderClass c =
-  [Container $ \_ ->
-     Header n ("", delete ("Heading" ++ show n) cs, []) []]
-divAttrToContainers (c:cs) kvs | c `elem` divsToKeep =
-  (Container $ Div ("", [c], [])) : (divAttrToContainers cs kvs)
-divAttrToContainers (c:cs) kvs | c `elem` codeDivs =
+parStyleToContainers :: ParagraphStyle -> [Container Block]
+parStyleToContainers pPr | (c:cs) <- pStyle pPr, Just n <- isHeaderClass c =
+  [Container $ \_ -> Header n ("", delete ("Heading" ++ show n) cs, []) []]
+parStyleToContainers pPr | (c:cs) <- pStyle pPr, c `elem` divsToKeep =
+  let pPr' = pPr { pStyle = cs }
+  in
+   (Container $ Div ("", [c], [])) : (parStyleToContainers pPr')
+parStyleToContainers pPr | (c:cs) <- pStyle pPr, c `elem` codeDivs =
   -- This is a bit of a cludge. We make the codeblock from the raw
   -- parparts in bodyPartToBlocks. But we need something to match against.
-  (Container $ \_ -> CodeBlock ("", [], []) "") : (divAttrToContainers cs kvs)
-divAttrToContainers (c:cs) kvs | c `elem` listParagraphDivs =
-  let kvs' = filter (\(k,_) -> k /= "indent") kvs
+  let pPr' = pPr { pStyle = cs }
   in
-   (Container $ Div ("", [c], [])) : (divAttrToContainers cs kvs')
-divAttrToContainers (c:cs) kvs | c `elem` blockQuoteDivs =
-  (Container BlockQuote) : (divAttrToContainers (cs \\ blockQuoteDivs) kvs)
-divAttrToContainers (_:cs) kvs = divAttrToContainers cs kvs
-divAttrToContainers [] kvs | Just _ <- lookup "indent" kvs
-                           , Just flInd <- lookup "first-line-indent" kvs =
-  let
-    kvs' = filter (\(k,_) -> notElem k ["indent", "first-line-indent"]) kvs
+   (Container $ \_ -> CodeBlock ("", [], []) "") : (parStyleToContainers pPr')
+parStyleToContainers pPr | (c:cs) <- pStyle pPr,  c `elem` listParagraphDivs =
+  let pPr' = pPr { pStyle = cs, indentation = Nothing}
   in
-   case flInd of
-     "0" -> divAttrToContainers [] kvs'
-     ('-':_) -> divAttrToContainers [] kvs'
-     _       -> (Container BlockQuote) : divAttrToContainers [] kvs'
-divAttrToContainers [] kvs | Just ind <- lookup "indent" kvs =
-  let
-    kvs' = filter (\(k,_) -> notElem k ["indent"]) kvs
-  in
-   case ind of
-     "0" -> divAttrToContainers [] kvs'
-     ('-':_) -> divAttrToContainers [] kvs'
-     _       -> (Container BlockQuote) : divAttrToContainers [] kvs'
+   (Container $ Div ("", [c], [])) : (parStyleToContainers pPr')
 
-divAttrToContainers _ _ = []
-
-
-parStyleToContainers :: ParagraphStyle -> [Container Block]
-parStyleToContainers pPr =
-  let classes = pStyle pPr
-      indent = indentation pPr >>= leftParIndent
-      hanging = indentation pPr >>= hangingParIndent
-      firstLineIndent = liftA2 (-) indent hanging
-      kvs = mapMaybe id
-            [ indent >>= (\n -> Just ("indent", show n)),
-              firstLineIndent >>= (\n -> Just ("first-line-indent", show n))
-              ]
+parStyleToContainers pPr | (c:cs) <- pStyle pPr, c `elem` blockQuoteDivs =
+  let pPr' = pPr { pStyle = cs \\ blockQuoteDivs }
   in
-   divAttrToContainers classes kvs
+   (Container BlockQuote) : (parStyleToContainers pPr')
+parStyleToContainers pPr | (_:cs) <- pStyle pPr =
+  let pPr' = pPr { pStyle = cs}
+  in
+    parStyleToContainers pPr'                                 
+parStyleToContainers pPr | null (pStyle pPr),
+                          Just left <- indentation pPr >>= leftParIndent,
+                          Just hang <- indentation pPr >>= hangingParIndent =
+  let pPr' = pPr { indentation = Nothing }
+  in
+   case (left - hang) > 0 of
+     True -> (Container BlockQuote) : (parStyleToContainers pPr')
+     False -> parStyleToContainers pPr'
+parStyleToContainers pPr | null (pStyle pPr),
+                          Just left <- indentation pPr >>= leftParIndent =
+  let pPr' = pPr { indentation = Nothing }
+  in
+   case left > 0 of
+     True -> (Container BlockQuote) : (parStyleToContainers pPr')
+     False -> parStyleToContainers pPr'
+parStyleToContainers _ = []
   
 
 strToInlines :: String -> [Inline]

From 264e366f1a973efa56fc32079927fc51cc1936ca Mon Sep 17 00:00:00 2001
From: John MacFarlane <jgm@berkeley.edu>
Date: Mon, 30 Jun 2014 14:03:47 -0700
Subject: [PATCH 8/8] Filters: respect shebang if filter is executable.

Closes #1389.
---
 pandoc.hs | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/pandoc.hs b/pandoc.hs
index 6281113cb..bf5f387dd 100644
--- a/pandoc.hs
+++ b/pandoc.hs
@@ -49,7 +49,7 @@ import System.Console.GetOpt
 import Data.Char ( toLower )
 import Data.List ( intercalate, isPrefixOf, isSuffixOf, sort )
 import System.Directory ( getAppUserDataDirectory, findExecutable,
-                          doesFileExist )
+                          doesFileExist, Permissions(..), getPermissions )
 import System.IO ( stdout, stderr )
 import System.IO.Error ( isDoesNotExistError )
 import qualified Control.Exception as E
@@ -104,8 +104,12 @@ externalFilter f args' d = do
                            Nothing -> do
                              exists <- doesFileExist f
                              if exists
-                                then return $
+                                then do
+                                  isExecutable <- executable `fmap`
+                                                    getPermissions f
+                                  return $
                                     case map toLower $ takeExtension f of
+                                         _ | isExecutable -> (f, args')
                                          ".py"  -> ("python", f:args')
                                          ".hs"  -> ("runhaskell", f:args')
                                          ".pl"  -> ("perl", f:args')