@@ -73,6 +73,7 @@ import Text.Pandoc.Readers.Docx.Util
73import Data.Char (readLitChar, ord, chr, isDigit)
73import Data.Char (readLitChar, ord, chr, isDigit)
75data ReaderEnv = ReaderEnv { envNotes :: Notes
75data ReaderEnv = ReaderEnv { envNotes :: Notes
76+ , envComments :: Comments
76 , envNumbering :: Numbering
77 , envNumbering :: Numbering
77 , envRelationships :: [Relationship]
78 , envRelationships :: [Relationship]
78 , envMedia :: Media
79 , envMedia :: Media
@@ -160,6 +161,9 @@ data Notes = Notes NameSpaces
160 (Maybe (M.Map String Element))
161 (Maybe (M.Map String Element))
161 deriving Show
162 deriving Show
164+data Comments = Comments NameSpaces (M.Map String Element)
163data ParIndentation = ParIndentation { leftParIndent :: Maybe Integer
167data ParIndentation = ParIndentation { leftParIndent :: Maybe Integer
164 , rightParIndent :: Maybe Integer
168 , rightParIndent :: Maybe Integer
165 , hangingParIndent :: Maybe Integer}
169 , hangingParIndent :: Maybe Integer}
@@ -210,6 +214,8 @@ type Extent = Maybe (Double, Double)
210data ParPart = PlainRun Run
214data ParPart = PlainRun Run
211 | Insertion ChangeId Author ChangeDate [Run]
215 | Insertion ChangeId Author ChangeDate [Run]
212 | Deletion ChangeId Author ChangeDate [Run]
216 | Deletion ChangeId Author ChangeDate [Run]
217+ | CommentStart CommentId Author CommentDate [BodyPart]
218+ | CommentEnd CommentId
213 | BookMark BookMarkId Anchor
219 | BookMark BookMarkId Anchor
214 | InternalHyperLink Anchor [Run]
220 | InternalHyperLink Anchor [Run]
215 | ExternalHyperLink URL [Run]
221 | ExternalHyperLink URL [Run]
@@ -259,8 +265,10 @@ type URL = String
259type BookMarkId = String
265type BookMarkId = String
260type RelId = String
266type RelId = String
261type ChangeId = String
267type ChangeId = String
268+type CommentId = String
262type Author = String
269type Author = String
263type ChangeDate = String
270type ChangeDate = String
271+type CommentDate = String
265archiveToDocx :: Archive -> Either DocxError Docx
273archiveToDocx :: Archive -> Either DocxError Docx
266archiveToDocx archive = fst <$> archiveToDocxWithWarnings archive
274archiveToDocx archive = fst <$> archiveToDocxWithWarnings archive
@@ -268,12 +276,13 @@ archiveToDocx archive = fst <$> archiveToDocxWithWarnings archive
268archiveToDocxWithWarnings :: Archive -> Either DocxError (Docx, [String])
276archiveToDocxWithWarnings :: Archive -> Either DocxError (Docx, [String])
269archiveToDocxWithWarnings archive = do
277archiveToDocxWithWarnings archive = do
270 let notes = archiveToNotes archive
278 let notes = archiveToNotes archive
279+ comments = archiveToComments archive
271 numbering = archiveToNumbering archive
280 numbering = archiveToNumbering archive
272 rels = archiveToRelationships archive
281 rels = archiveToRelationships archive
273 media = archiveToMedia archive
282 media = archiveToMedia archive
274 (styles, parstyles) = archiveToStyles archive
283 (styles, parstyles) = archiveToStyles archive
276− ReaderEnv notes numbering rels media Nothing styles parstyles InDocument
285+ ReaderEnv notes comments numbering rels media Nothing styles parstyles InDocument
277 rState = ReaderState { stateWarnings = [] }
286 rState = ReaderState { stateWarnings = [] }
278 (eitherDoc, st) = runD (archiveToDocument archive) rEnv rState
287 (eitherDoc, st) = runD (archiveToDocument archive) rEnv rState
279 case eitherDoc of
288 case eitherDoc of
@@ -384,6 +393,20 @@ archiveToNotes zf =
385 Notes ns fn en
394 Notes ns fn en
396+archiveToComments :: Archive -> Comments
397+archiveToComments zf =
398+ let cmtsElem = findEntryByPath "word/comments.xml" zf
399+ >>= (parseXMLDoc . UTF8.toStringLazy . fromEntry)
400+ cmts_namespaces = case cmtsElem of
401+ Just e -> elemToNameSpaces e
403+ cmts = (elemToComments cmts_namespaces) <$> cmtsElem
406+ Just c -> Comments cmts_namespaces c
407+ Nothing -> Comments cmts_namespaces M.empty
387filePathToRelType :: FilePath -> Maybe DocumentLocation
410filePathToRelType :: FilePath -> Maybe DocumentLocation
388filePathToRelType "word/_rels/document.xml.rels" = Just InDocument
411filePathToRelType "word/_rels/document.xml.rels" = Just InDocument
389filePathToRelType "word/_rels/footnotes.xml.rels" = Just InFootnote
412filePathToRelType "word/_rels/footnotes.xml.rels" = Just InFootnote
@@ -504,6 +527,18 @@ elemToNotes ns notetype element
504 Just $ M.fromList $ pairs
527 Just $ M.fromList $ pairs
505elemToNotes _ _ _ = Nothing
528elemToNotes _ _ _ = Nothing
530+elemToComments :: NameSpaces -> Element -> M.Map String Element
531+elemToComments ns element
532+ | isElem ns "w" "comments" element =
533+ let pairs = mapMaybe
534+ (\e -> findAttr (elemName ns "w" "id") e >>=
535+ (\a -> Just (a, e)))
536+ (findChildren (elemName ns "w" "comment") element)
539+elemToComments _ _ = M.empty
507---------------------------------------------
542---------------------------------------------
508---------------------------------------------
543---------------------------------------------
@@ -696,11 +731,32 @@ elemToParPart ns element
696 , Just anchor <- findAttr (elemName ns "w" "anchor") element = do
731 , Just anchor <- findAttr (elemName ns "w" "anchor") element = do
697 runs <- mapD (elemToRun ns) (elChildren element)
732 runs <- mapD (elemToRun ns) (elChildren element)
698 return $ InternalHyperLink anchor runs
733 return $ InternalHyperLink anchor runs
734+elemToParPart ns element
735+ | isElem ns "w" "commentRangeStart" element
736+ , Just cmtId <- findAttr (elemName ns "w" "id") element = do
737+ (Comments _ commentMap) <- asks envComments
738+ case M.lookup cmtId commentMap of
739+ Just cmtElem -> elemToCommentStart ns cmtElem
740+ Nothing -> throwError WrongElem
741+elemToParPart ns element
742+ | isElem ns "w" "commentRangeEnd" element
743+ , Just cmtId <- findAttr (elemName ns "w" "id") element =
744+ return $ CommentEnd cmtId
699elemToParPart ns element
745elemToParPart ns element
700 | isElem ns "m" "oMath" element =
746 | isElem ns "m" "oMath" element =
701 (eitherToD $ readOMML $ showElement element) >>= (return . PlainOMath)
747 (eitherToD $ readOMML $ showElement element) >>= (return . PlainOMath)
702elemToParPart _ _ = throwError WrongElem
748elemToParPart _ _ = throwError WrongElem
750+elemToCommentStart :: NameSpaces -> Element -> D ParPart
751+elemToCommentStart ns element
752+ | isElem ns "w" "comment" element
753+ , Just cmtId <- findAttr (elemName ns "w" "id") element
754+ , Just cmtAuthor <- findAttr (elemName ns "w" "author") element
755+ , Just cmtDate <- findAttr (elemName ns "w" "date") element = do
756+ bps <- mapD (elemToBodyPart ns) (elChildren element)
757+ return $ CommentStart cmtId cmtAuthor cmtDate bps
758+elemToCommentStart _ _ = throwError WrongElem
704lookupFootnote :: String -> Notes -> Maybe Element
760lookupFootnote :: String -> Notes -> Maybe Element
705lookupFootnote s (Notes _ fns _) = fns >>= (M.lookup s)
761lookupFootnote s (Notes _ fns _) = fns >>= (M.lookup s)