@@ -114,23 +114,88 @@ writeDocx opts doc@(Pandoc (Meta tit auths date) _) = do
114114 defaultWriterState
115115 epochtime <- floor `fmap` getPOSIXTime
116116 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.
123+
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")] (),
153+ mknode "Default"
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
118158
119159 -- word/_rels/document.xml.rels
120− let newrels = map toImgRel imgs
121− let relpath = "word/_rels/document.xml.rels"
122− reldoc <- parseXml refArchive relpath
123− let reldoc' = reldoc{ elContent = elContent reldoc ++ map Elem newrels }
160+ let toBaseRel (url', id', target') = mknode "Relationship"
161+ [("Type",url')
162+ ,("Id",id')
163+ ,("Target",target')] ()
164+ let baserels = map toBaseRel
165+ [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
166+ "rId1",
167+ "numbering.xml")
168+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
169+ "rId2",
170+ "styles.xml")
171+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
172+ "rId3",
173+ "settings.xml")
174+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
175+ "rId4",
176+ "webSettings.xml")
177+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
178+ "rId5",
179+ "fontTable.xml")
180+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
181+ "rId6",
182+ "theme/theme1.xml")
183+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
184+ "rId7",
185+ "footnotes.xml")]
186+ let toImgRel (ident,path,_,_,_) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",ident),("Target",path)] ()
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
191+ let relEntry = toEntry "word/_rels/document.xml.rels" epochtime
192+ $ UTF8.fromStringLazy $ showTopElement' reldoc
124193
125− -- create entries for images
194+ -- create entries for images in word/media/...
126195 let toImageEntry (_,path,_,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img
127196 let imageEntries = map toImageEntry imgs
128197
129− -- NOW get list of external links and images from this, and do what's needed
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''
198+ -- word/document.xml
134199 let contentEntry = toEntry "word/document.xml" epochtime $ UTF8.fromStringLazy $ showTopElement' contents
135200
136201 -- footnotes
@@ -140,7 +205,7 @@ writeDocx opts doc@(Pandoc (Meta tit auths date) _) = do
140205 -- footnote rels
141206 let footnoteRelEntry = toEntry "word/_rels/footnotes.xml.rels" epochtime $ UTF8.fromStringLazy $
142207 showTopElement' $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]
143− $ newrels'
208+ $ linkrels
144209
145210 -- styles
146211 let newstyles = styleToOpenXml $ writerHighlightStyle opts
@@ -179,7 +244,7 @@ writeDocx opts doc@(Pandoc (Meta tit auths date) _) = do
179244
180245 -- Create archive
181246 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
183248 return $ fromArchive archive
184249
185250styleToOpenXml :: Style -> [Element]
@@ -689,8 +754,7 @@ inlineToOpenXML opts (Image alt (src, tit)) = do
689754 else do
690755 let imgpath = "media/" ++ ident ++ imgext
691756 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
694758 modify $ \st -> st{ stImages =
695759 M.insert src (ident, imgpath, mbMimeType, imgElt, img)
696760 $ stImages st }