@@ -114,23 +114,88 @@ writeDocx opts doc@(Pandoc (Meta tit auths date) _) = do
114 defaultWriterState
114 defaultWriterState
115 epochtime <- floor `fmap` getPOSIXTime
115 epochtime <- floor `fmap` getPOSIXTime
116 let imgs = M.elems $ stImages st
116 let imgs = M.elems $ stImages st
117− let toImgRel (ident,path,_,_,_) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",ident),("Target",path)] ()
117+
118+ -- we create [Content_Types].xml and word/_rels/document.xml.rels
119+ -- from scratch rather than reading from reference.docx,
120+ -- because Word sometimes changes these files when a reference.docx is modified,
121+ -- e.g. deleting the reference to footnotes.xml or removing default entries
122+ -- for image content types.
124+ -- [Content_Types].xml
125+ let mkOverrideNode (part', contentType') = mknode "Override"
126+ [("PartName",part'),("ContentType",contentType')] ()
127+ let mkImageOverride (_, imgpath, mbMimeType, _, _) =
128+ mkOverrideNode ("/word/" ++ imgpath, maybe "application/octet-stream" id mbMimeType)
129+ let overrides = map mkOverrideNode
130+ [("/word/webSettings.xml",
131+ "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")
132+ ,("/word/numbering.xml",
133+ "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml")
134+ ,("/word/settings.xml",
135+ "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml")
136+ ,("/word/theme/theme1.xml",
137+ "application/vnd.openxmlformats-officedocument.theme+xml")
138+ ,("/word/fontTable.xml",
139+ "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml")
140+ ,("/docProps/app.xml",
141+ "application/vnd.openxmlformats-officedocument.extended-properties+xml")
142+ ,("/docProps/core.xml",
143+ "application/vnd.openxmlformats-package.core-properties+xml")
144+ ,("/word/styles.xml",
145+ "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")
146+ ,("/word/document.xml",
147+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")
148+ ,("/word/footnotes.xml",
149+ "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")
150+ ] ++ map mkImageOverride imgs
151+ let defaultnodes = [mknode "Default"
152+ [("Extension","xml"),("ContentType","application/xml")] (),
154+ [("Extension","rels"),("ContentType","application/vnd.openxmlformats-package.relationships+xml")] ()]
155+ let contentTypesDoc = mknode "Types" [("xmlns","http://schemas.openxmlformats.org/package/2006/content-types")] $ defaultnodes ++ overrides
156+ let contentTypesEntry = toEntry "[Content_Types].xml" epochtime
157+ $ UTF8.fromStringLazy $ showTopElement' contentTypesDoc
119 -- word/_rels/document.xml.rels
159 -- word/_rels/document.xml.rels
160+ let toBaseRel (url', id', target') = mknode "Relationship"
163+ ,("Target",target')] ()
164+ let baserels = map toBaseRel
165+ [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
168+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
171+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
174+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
177+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
180+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
183+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
186+ let toImgRel (ident,path,_,_,_) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",ident),("Target",path)] ()
120− let newrels = map toImgRel imgs
187+ let imgrels = map toImgRel imgs
188+ let toLinkRel (src,ident) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"),("Id",ident),("Target",src),("TargetMode","External") ] ()
189+ let linkrels = map toLinkRel $ M.toList $ stExternalLinks st
190+ let reldoc = mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")] $ baserels ++ imgrels ++ linkrels
121− let relpath = "word/_rels/document.xml.rels"
191+ let relEntry = toEntry "word/_rels/document.xml.rels" epochtime
122− reldoc <- parseXml refArchive relpath
192+ $ UTF8.fromStringLazy $ showTopElement' reldoc
123− let reldoc' = reldoc{ elContent = elContent reldoc ++ map Elem newrels }
125− -- create entries for images
194+ -- create entries for images in word/media/...
126 let toImageEntry (_,path,_,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img
195 let toImageEntry (_,path,_,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img
127 let imageEntries = map toImageEntry imgs
196 let imageEntries = map toImageEntry imgs
129− -- NOW get list of external links and images from this, and do what's needed
198+ -- word/document.xml
130− let toLinkRel (src,ident) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"),("Id",ident),("Target",src),("TargetMode","External") ] ()
131− let newrels' = map toLinkRel $ M.toList $ stExternalLinks st
132− let reldoc'' = reldoc' { elContent = elContent reldoc' ++ map Elem newrels' }
133− let relEntry = toEntry relpath epochtime $ UTF8.fromStringLazy $ showTopElement' reldoc''
134 let contentEntry = toEntry "word/document.xml" epochtime $ UTF8.fromStringLazy $ showTopElement' contents
199 let contentEntry = toEntry "word/document.xml" epochtime $ UTF8.fromStringLazy $ showTopElement' contents
136 -- footnotes
201 -- footnotes
@@ -140,7 +205,7 @@ writeDocx opts doc@(Pandoc (Meta tit auths date) _) = do
140 -- footnote rels
205 -- footnote rels
141 let footnoteRelEntry = toEntry "word/_rels/footnotes.xml.rels" epochtime $ UTF8.fromStringLazy $
206 let footnoteRelEntry = toEntry "word/_rels/footnotes.xml.rels" epochtime $ UTF8.fromStringLazy $
142 showTopElement' $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]
207 showTopElement' $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]
143− $ newrels'
208+ $ linkrels
145 -- styles
210 -- styles
146 let newstyles = styleToOpenXml $ writerHighlightStyle opts
211 let newstyles = styleToOpenXml $ writerHighlightStyle opts
@@ -179,7 +244,7 @@ writeDocx opts doc@(Pandoc (Meta tit auths date) _) = do
180 -- Create archive
245 -- Create archive
181 let archive = foldr addEntryToArchive refArchive $
246 let archive = foldr addEntryToArchive refArchive $
182− relsEntry : contentEntry : relEntry : footnoteRelEntry : numEntry : styleEntry : footnotesEntry : docPropsEntry : imageEntries
247+ contentTypesEntry : relsEntry : contentEntry : relEntry : footnoteRelEntry : numEntry : styleEntry : footnotesEntry : docPropsEntry : imageEntries
183 return $ fromArchive archive
248 return $ fromArchive archive
185styleToOpenXml :: Style -> [Element]
250styleToOpenXml :: Style -> [Element]
@@ -689,8 +754,7 @@ inlineToOpenXML opts (Image alt (src, tit)) = do
690 let imgpath = "media/" ++ ident ++ imgext
755 let imgpath = "media/" ++ ident ++ imgext
691 let mbMimeType = getMimeType imgpath
756 let mbMimeType = getMimeType imgpath
692− -- TODO also insert mime type; later can use this
693− -- to construct [Content_Types].xml
757+ -- insert mime type to use in constructing [Content_Types].xml
694 modify $ \st -> st{ stImages =
758 modify $ \st -> st{ stImages =
695 M.insert src (ident, imgpath, mbMimeType, imgElt, img)
759 M.insert src (ident, imgpath, mbMimeType, imgElt, img)
696 $ stImages st }
760 $ stImages st }