diff options
-rw-r--r-- | README | 7 | ||||
-rw-r--r-- | data/docx/word/styles.xml | 19 | ||||
-rw-r--r-- | src/Text/Pandoc/Readers/Org.hs | 2 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/Docx.hs | 51 | ||||
-rw-r--r-- | tests/Tests/Readers/Org.hs | 4 |
5 files changed, 78 insertions, 5 deletions
@@ -319,7 +319,12 @@ Reader options Those who would prefer to write filters in python can use the module `pandocfilters`, installable from PyPI. See <http://github.com/jgm/pandocfilters> for the module and several - examples. Note that the *EXECUTABLE* will be sought in the user's + examples. There are also pandoc filter libraries in + [PHP](https://github.com/vinai/pandocfilters-php), + [perl](https://metacpan.org/pod/Pandoc::Filter), and + [javascript/node.js](https://github.com/mvhenderson/pandoc-filter-node). + + Note that the *EXECUTABLE* will be sought in the user's `PATH`, and not in the working directory, if no directory is provided. If you want to run a script in the working directory, preface the filename with `./`. diff --git a/data/docx/word/styles.xml b/data/docx/word/styles.xml index 0de21bd4c..01190ef5a 100644 --- a/data/docx/word/styles.xml +++ b/data/docx/word/styles.xml @@ -340,4 +340,23 @@ <w:color w:val="4F81BD" w:themeColor="accent1" /> </w:rPr> </w:style> + <w:style w:type="paragraph" w:styleId="TOCHeading"> + <w:name w:val="TOC Heading" /> + <w:basedOn w:val="Heading1" /> + <w:next w:val="BodyText" /> + <w:uiPriority w:val="39" /> + <w:unhideWhenUsed /> + <w:qFormat /> + <w:pPr> + <w:spacing w:before="240" w:line="259" w:lineRule="auto" /> + <w:outlineLvl w:val="9" /> + </w:pPr> + <w:rPr> + <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" /> + <w:b w:val="0" /> + <w:bCs w:val="0" /> + <w:color w:val="365F91" w:themeColor="accent1" + w:themeShade="BF" /> + </w:rPr> + </w:style> </w:styles> diff --git a/src/Text/Pandoc/Readers/Org.hs b/src/Text/Pandoc/Readers/Org.hs index 1dfbdd700..fc63cc11e 100644 --- a/src/Text/Pandoc/Readers/Org.hs +++ b/src/Text/Pandoc/Readers/Org.hs @@ -1093,7 +1093,7 @@ explicitOrImageLink = try $ do char ']' alt <- internalLink src title' return $ - (if isImageFilename src && isImageFilename title + (if isImageFilename title then B.link src "" $ B.image title mempty mempty else fromMaybe alt (linkToInlines src title')) diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs index 5903e7689..8bb1d0ced 100644 --- a/src/Text/Pandoc/Writers/Docx.hs +++ b/src/Text/Pandoc/Writers/Docx.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE ScopedTypeVariables, PatternGuards #-} +{-# LANGUAGE ScopedTypeVariables, PatternGuards, ViewPatterns #-} {- Copyright (C) 2012-2014 John MacFarlane <jgm@berkeley.edu> @@ -66,6 +66,7 @@ import Text.Pandoc.MIME (MimeType, getMimeType, getMimeTypeDef, extensionFromMimeType) import Control.Applicative ((<$>), (<|>), (<*>)) import Data.Maybe (fromMaybe, mapMaybe, maybeToList) +import Data.Char (ord) data ListMarker = NoMarker | BulletMarker @@ -176,13 +177,29 @@ renumId f renumMap e renumIds :: (QName -> Bool) -> (M.Map String String) -> [Element] -> [Element] renumIds f renumMap = map (renumId f renumMap) +-- | Certain characters are invalid in XML even if escaped. +-- See #1992 +stripInvalidChars :: Pandoc -> Pandoc +stripInvalidChars = bottomUp (filter isValidChar) + +-- | See XML reference +isValidChar :: Char -> Bool +isValidChar (ord -> c) + | c == 0x9 = True + | c == 0xA = True + | c == 0xD = True + | 0x20 <= c && c <= 0xD7FF = True + | 0xE000 <= c && c <= 0xFFFD = True + | 0x10000 <= c && c <= 0x10FFFF = True + | otherwise = False + -- | Produce an Docx file from a Pandoc document. writeDocx :: WriterOptions -- ^ Writer options -> Pandoc -- ^ Document to convert -> IO BL.ByteString writeDocx opts doc@(Pandoc meta _) = do let datadir = writerUserDataDir opts - let doc' = walk fixDisplayMath doc + let doc' = stripInvalidChars . walk fixDisplayMath $ doc username <- lookup "USERNAME" <$> getEnvironment utctime <- getCurrentTime refArchive <- liftM (toArchive . toLazy) $ @@ -604,6 +621,33 @@ mkLvl marker lvl = getNumId :: WS Int getNumId = (((baseListId - 1) +) . length) `fmap` gets stLists +makeTOC :: WriterOptions -> WS [Element] +makeTOC opts | writerTableOfContents opts = do + let depth = "1-"++(show (writerTOCDepth opts)) + let tocCmd = "TOC \\o \""++depth++"\" \\h \\z \\u" + title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para [Str "Table of Contents"]]) + return $ + [mknode "w:sdt" [] ([ + mknode "w:sdtPr" [] ( + mknode "w:docPartObj" [] ( + [mknode "w:docPartGallery" [("w:val","Table of Contents")] (), + mknode "w:docPartUnique" [] ()] + ) -- w:docPartObj + ), -- w:sdtPr + mknode "w:sdtContent" [] (title++[ + mknode "w:p" [] ( + mknode "w:r" [] ([ + mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (), + mknode "w:instrText" [("xml:space","preserve")] tocCmd, + mknode "w:fldChar" [("w:fldCharType","separate")] (), + mknode "w:fldChar" [("w:fldCharType","end")] () + ]) -- w:r + ) -- w:p + ]) + ])] -- w:sdt +makeTOC _ = return [] + + -- | Convert Pandoc document to two lists of -- OpenXML elements (the main document and footnotes). writeOpenXML :: WriterOptions -> Pandoc -> WS ([Element], [Element]) @@ -636,7 +680,8 @@ writeOpenXML opts (Pandoc meta blocks) = do let blocks' = bottomUp convertSpace blocks doc' <- (setFirstPara >> blocksToOpenXML opts blocks') notes' <- reverse `fmap` gets stFootnotes - let meta' = title ++ subtitle ++ authors ++ date ++ abstract + toc <- makeTOC opts + let meta' = title ++ subtitle ++ authors ++ date ++ abstract ++ toc return (meta' ++ doc', notes') -- | Convert a list of Pandoc blocks to OpenXML. diff --git a/tests/Tests/Readers/Org.hs b/tests/Tests/Readers/Org.hs index f555447c7..4cec54a68 100644 --- a/tests/Tests/Readers/Org.hs +++ b/tests/Tests/Readers/Org.hs @@ -216,6 +216,10 @@ tests = "[[sunset.png][dusk.svg]]" =?> (para $ link "sunset.png" "" (image "dusk.svg" "" "")) + , "Image link with non-image target" =: + "[[http://example.com][logo.png]]" =?> + (para $ link "http://example.com" "" (image "logo.png" "" "")) + , "Plain link" =: "Posts on http://zeitlens.com/ can be funny at times." =?> (para $ spcSep [ "Posts", "on" |