diff options
Diffstat (limited to 'src/Text/Pandoc')
| -rw-r--r-- | src/Text/Pandoc/Highlighting.hs | 71 | ||||
| -rw-r--r-- | src/Text/Pandoc/Parsing.hs | 14 | ||||
| -rw-r--r-- | src/Text/Pandoc/Readers/LaTeX.hs | 8 | ||||
| -rw-r--r-- | src/Text/Pandoc/Readers/Markdown.hs | 14 | ||||
| -rw-r--r-- | src/Text/Pandoc/Shared.hs | 9 | ||||
| -rw-r--r-- | src/Text/Pandoc/Templates.hs | 1 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/AsciiDoc.hs | 4 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/ConTeXt.hs | 8 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/Docbook.hs | 6 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/EPUB.hs | 59 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/HTML.hs | 37 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/LaTeX.hs | 112 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/Man.hs | 12 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/Markdown.hs | 4 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/MediaWiki.hs | 12 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/OpenDocument.hs | 8 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/Org.hs | 11 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/RST.hs | 4 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/RTF.hs | 14 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/Texinfo.hs | 8 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/Textile.hs | 30 |
21 files changed, 268 insertions, 178 deletions
diff --git a/src/Text/Pandoc/Highlighting.hs b/src/Text/Pandoc/Highlighting.hs index c65d23f93..a40bab66a 100644 --- a/src/Text/Pandoc/Highlighting.hs +++ b/src/Text/Pandoc/Highlighting.hs @@ -29,57 +29,48 @@ Exports functions for syntax highlighting. -} module Text.Pandoc.Highlighting ( languages - , highlightHtml - , highlightLaTeX - , defaultHighlightingCss - , defaultLaTeXMacros , languagesByExtension + , highlight + , formatLaTeXInline + , formatLaTeXBlock + , styleToLaTeX + , formatHtmlInline + , formatHtmlBlock + , styleToHtml + , pygments + , espresso + , tango + , kate + , monochrome + , haddock + , Style ) where -import Text.Blaze import Text.Pandoc.Definition -import Text.Highlighting.Kate ( SourceLine, languages, highlightAs, formatAsHtml, - TokenType(..), formatAsLaTeX, FormatOption (..), defaultHighlightingCss, - defaultLaTeXMacros, languagesByExtension ) +import Text.Highlighting.Kate import Data.List (find) import Data.Maybe (fromMaybe) import Data.Char (toLower) -import qualified Text.Blaze.Html5.Attributes as A -highlight :: ([FormatOption] -> String -> [SourceLine] -> a) -- ^ Formatter - -> Bool -- ^ True if inline - -> Attr -- ^ Attributes of the Code or CodeBlock - -> String -- ^ Raw contents of the Code or CodeBlock - -> Maybe a -- ^ Maybe the formatted result -highlight formatter inline (_, classes, keyvals) rawCode = +lcLanguages :: [String] +lcLanguages = map (map toLower) languages + +highlight :: (FormatOptions -> [SourceLine] -> a) -- ^ Formatter + -> Attr -- ^ Attributes of the CodeBlock + -> String -- ^ Raw contents of the CodeBlock + -> Maybe a -- ^ Maybe the formatted result +highlight formatter (_, classes, keyvals) rawCode = let firstNum = case reads (fromMaybe "1" $ lookup "startFrom" keyvals) of ((n,_):_) -> n [] -> 1 - fmtOpts = [OptNumberFrom firstNum] ++ - [OptInline | inline] ++ - case find (`elem` ["number","numberLines","number-lines"]) classes of - Nothing -> [] - Just _ -> [OptNumberLines] - addBirdTracks = "literate" `elem` classes - lcLanguages = map (map toLower) languages - in case find (\c -> (map toLower c) `elem` lcLanguages) classes of + fmtOpts = defaultFormatOpts{ + startNumber = firstNum, + numberLines = any (`elem` + ["number","numberLines", "number-lines"]) classes } + lcclasses = map (map toLower) classes + in case find (`elem` lcLanguages) lcclasses of Nothing -> Nothing Just language -> Just - $ formatter fmtOpts language . - (if addBirdTracks - then map ((OtherTok,"> "):) - else id) + $ formatter fmtOpts{ codeClasses = [language], + containerClasses = classes } $ highlightAs language rawCode -highlightHtml :: Bool -- ^ True if inline HTML - -> Attr -- ^ Attributes of the Code or CodeBlock - -> String -- ^ Raw contents of the Code or CodeBlock - -> Maybe Html -- ^ Maybe formatted Html -highlightHtml inline attr@(id',_,_) = fmap addId . highlight formatAsHtml inline attr - where addId = if null id' then id else (! A.id (toValue id')) - -highlightLaTeX :: Bool -- ^ True if inline - -> Attr -- ^ Attributes of the Code or CodeBlock - -> String -- ^ Raw contents of the Code or CodeBlock - -> Maybe String -- ^ Maybe formatted LaTeX -highlightLaTeX = highlight formatAsLaTeX - diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs index 937deb484..5fa375ca6 100644 --- a/src/Text/Pandoc/Parsing.hs +++ b/src/Text/Pandoc/Parsing.hs @@ -704,7 +704,7 @@ smartPunctuation inlineParser = do choice [ quoted inlineParser, apostrophe, dash, ellipses ] apostrophe :: GenParser Char ParserState Inline -apostrophe = (char '\'' <|> char '\8217') >> return Apostrophe +apostrophe = (char '\'' <|> char '\8217') >> return (Str "\x2019") quoted :: GenParser Char ParserState Inline -> GenParser Char ParserState Inline @@ -779,22 +779,22 @@ doubleQuoteEnd = do ellipses :: GenParser Char st Inline ellipses = do - try (charOrRef "…\133") <|> try (string "..." >> return '…') - return Ellipses + try (charOrRef "\8230\133") <|> try (string "..." >> return '…') + return (Str "\8230") dash :: GenParser Char st Inline dash = enDash <|> emDash enDash :: GenParser Char st Inline enDash = do - try (charOrRef "–\150") <|> + try (charOrRef "\8211\150") <|> try (char '-' >> lookAhead (satisfy isDigit) >> return '–') - return EnDash + return (Str "\8211") emDash :: GenParser Char st Inline emDash = do - try (charOrRef "—\151") <|> (try $ string "--" >> optional (char '-') >> return '—') - return EmDash + try (charOrRef "\8212\151") <|> (try $ string "--" >> optional (char '-') >> return '-') + return (Str "\8212") -- -- Macros diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs index 9ad31cba5..708aa58c1 100644 --- a/src/Text/Pandoc/Readers/LaTeX.hs +++ b/src/Text/Pandoc/Readers/LaTeX.hs @@ -771,7 +771,7 @@ subscript = try $ string "\\textsubscript{" >> manyTill inline (char '}') >>= return . Subscript apostrophe :: GenParser Char ParserState Inline -apostrophe = char '\'' >> return Apostrophe +apostrophe = char '\'' >> return (Str "\x2019") quoted :: GenParser Char ParserState Inline quoted = doubleQuoted <|> singleQuoted @@ -802,13 +802,13 @@ ellipses = try $ do optional $ char 'l' string "dots" optional $ try $ string "{}" - return Ellipses + return (Str "…") enDash :: GenParser Char st Inline -enDash = try (string "--") >> return EnDash +enDash = try (string "--") >> return (Str "-") emDash :: GenParser Char st Inline -emDash = try (string "---") >> return EmDash +emDash = try (string "---") >> return (Str "—") hyphen :: GenParser Char st Inline hyphen = char '-' >> return (Str "-") diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs index cc9b8a23d..db68df629 100644 --- a/src/Text/Pandoc/Readers/Markdown.hs +++ b/src/Text/Pandoc/Readers/Markdown.hs @@ -44,7 +44,7 @@ import Text.Pandoc.Readers.HTML ( htmlTag, htmlInBalanced, isInlineTag, isBlockT isTextTag, isCommentTag ) import Text.Pandoc.CharacterReferences ( decodeCharacterReferences ) import Text.ParserCombinators.Parsec -import Control.Monad (when, liftM, guard) +import Control.Monad (when, liftM, guard, mzero) import Text.HTML.TagSoup import Text.HTML.TagSoup.Match (tagOpen) @@ -1087,12 +1087,18 @@ nonEndline = satisfy (/='\n') str :: GenParser Char ParserState Inline str = do + smart <- stateSmart `fmap` getState a <- alphaNum - as <- many $ alphaNum <|> (try $ char '_' >>~ lookAhead alphaNum) + as <- many $ alphaNum + <|> (try $ char '_' >>~ lookAhead alphaNum) + <|> if smart + then (try $ satisfy (\c -> c == '\'' || c == '\x2019') >> + lookAhead alphaNum >> return '\x2019') + -- for things like l'aide + else mzero let result = a:as - state <- getState let spacesToNbr = map (\c -> if c == ' ' then '\160' else c) - if stateSmart state + if smart then case likelyAbbrev result of [] -> return $ Str result xs -> choice (map (\x -> diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs index fac965b89..ba007f5e4 100644 --- a/src/Text/Pandoc/Shared.hs +++ b/src/Text/Pandoc/Shared.hs @@ -81,6 +81,7 @@ import System.FilePath ( (</>) ) import Data.Generics (Typeable, Data) import qualified Control.Monad.State as S import Paths_pandoc (getDataFileName) +import Text.Pandoc.Highlighting (Style, pygments) -- -- List processing @@ -325,10 +326,6 @@ stringify = queryWith go go (Str x) = x go (Code _ x) = x go (Math _ x) = x - go EmDash = "--" - go EnDash = "-" - go Apostrophe = "'" - go Ellipses = "..." go LineBreak = " " go _ = "" @@ -480,9 +477,11 @@ data WriterOptions = WriterOptions , writerCiteMethod :: CiteMethod -- ^ How to print cites , writerBiblioFiles :: [FilePath] -- ^ Biblio files to use for citations , writerHtml5 :: Bool -- ^ Produce HTML5 + , writerBeamer :: Bool -- ^ Produce beamer LaTeX slide show , writerChapters :: Bool -- ^ Use "chapter" for top-level sects , writerListings :: Bool -- ^ Use listings package for code , writerHighlight :: Bool -- ^ Highlight source code + , writerHighlightStyle :: Style -- ^ Style to use for highlighting } deriving Show {-# DEPRECATED writerXeTeX "writerXeTeX no longer does anything" #-} @@ -514,9 +513,11 @@ defaultWriterOptions = , writerCiteMethod = Citeproc , writerBiblioFiles = [] , writerHtml5 = False + , writerBeamer = False , writerChapters = False , writerListings = False , writerHighlight = False + , writerHighlightStyle = pygments } -- diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs index a7e836126..0d627e447 100644 --- a/src/Text/Pandoc/Templates.hs +++ b/src/Text/Pandoc/Templates.hs @@ -85,6 +85,7 @@ getDefaultTemplate _ "native" = return $ Right "" getDefaultTemplate _ "json" = return $ Right "" getDefaultTemplate user "odt" = getDefaultTemplate user "opendocument" getDefaultTemplate user "epub" = getDefaultTemplate user "html" +getDefaultTemplate user "beamer" = getDefaultTemplate user "latex" getDefaultTemplate user writer = do let format = takeWhile (/='+') writer -- strip off "+lhs" if present let fname = "templates" </> "default" <.> format diff --git a/src/Text/Pandoc/Writers/AsciiDoc.hs b/src/Text/Pandoc/Writers/AsciiDoc.hs index f45c20e9e..1913eb92b 100644 --- a/src/Text/Pandoc/Writers/AsciiDoc.hs +++ b/src/Text/Pandoc/Writers/AsciiDoc.hs @@ -321,10 +321,6 @@ inlineToAsciiDoc opts (Quoted SingleQuote lst) = do inlineToAsciiDoc opts (Quoted DoubleQuote lst) = do contents <- inlineListToAsciiDoc opts lst return $ "``" <> contents <> "''" -inlineToAsciiDoc _ EmDash = return "\8212" -inlineToAsciiDoc _ EnDash = return "\8211" -inlineToAsciiDoc _ Apostrophe = return "\8217" -inlineToAsciiDoc _ Ellipses = return "\8230" inlineToAsciiDoc _ (Code _ str) = return $ text "`" <> text (escapeStringUsing (backslashEscapes "`") str) <> "`" inlineToAsciiDoc _ (Str str) = return $ text $ escapeString str diff --git a/src/Text/Pandoc/Writers/ConTeXt.hs b/src/Text/Pandoc/Writers/ConTeXt.hs index b59b71cf0..a6771437d 100644 --- a/src/Text/Pandoc/Writers/ConTeXt.hs +++ b/src/Text/Pandoc/Writers/ConTeXt.hs @@ -102,6 +102,10 @@ escapeCharForConTeXt ch = ']' -> "{]}" '_' -> "\\letterunderscore{}" '\160' -> "~" + '\x2014' -> "---" + '\x2013' -> "--" + '\x2019' -> "'" + '\x2026' -> "\\ldots{}" x -> [x] -- | Escape string for ConTeXt @@ -258,10 +262,6 @@ inlineToConTeXt (Quoted DoubleQuote lst) = do contents <- inlineListToConTeXt lst return $ "\\quotation" <> braces contents inlineToConTeXt (Cite _ lst) = inlineListToConTeXt lst -inlineToConTeXt Apostrophe = return $ char '\'' -inlineToConTeXt EmDash = return "---" -inlineToConTeXt EnDash = return "--" -inlineToConTeXt Ellipses = return "\\ldots{}" inlineToConTeXt (Str str) = return $ text $ stringToConTeXt str inlineToConTeXt (Math InlineMath str) = return $ char '$' <> text str <> char '$' diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs index 9f8b921e7..f3ac726a9 100644 --- a/src/Text/Pandoc/Writers/Docbook.hs +++ b/src/Text/Pandoc/Writers/Docbook.hs @@ -35,7 +35,7 @@ import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Readers.TeXMath import Data.List ( isPrefixOf, intercalate, isSuffixOf ) import Data.Char ( toLower ) -import Text.Pandoc.Highlighting (languages, languagesByExtension) +import Text.Pandoc.Highlighting ( languages, languagesByExtension ) import Text.Pandoc.Pretty -- | Convert list of authors to a docbook <author> section @@ -248,10 +248,6 @@ inlineToDocbook opts (Quoted _ lst) = inTagsSimple "quote" $ inlinesToDocbook opts lst inlineToDocbook opts (Cite _ lst) = inlinesToDocbook opts lst -inlineToDocbook _ Apostrophe = char '\'' -inlineToDocbook _ Ellipses = text "…" -inlineToDocbook _ EmDash = text "—" -inlineToDocbook _ EnDash = text "–" inlineToDocbook _ (Code _ str) = inTagsSimple "literal" $ text (escapeStringForXML str) inlineToDocbook opts (Math _ str) = inlinesToDocbook opts $ readTeXMath str diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs index 55da4554d..d139c010c 100644 --- a/src/Text/Pandoc/Writers/EPUB.hs +++ b/src/Text/Pandoc/Writers/EPUB.hs @@ -40,7 +40,7 @@ import System.Time import Text.Pandoc.Shared hiding ( Element ) import Text.Pandoc.Definition import Text.Pandoc.Generic -import Control.Monad (liftM) +import Control.Monad.State import Text.XML.Light hiding (ppTopElement) import Text.Pandoc.UUID import Text.Pandoc.Writers.HTML @@ -104,12 +104,16 @@ writeEPUB mbStylesheet opts doc@(Pandoc meta _) = do -- body pages let isH1 (Header 1 _) = True isH1 _ = False - let h1Indices = dropWhile (== 0) $ findIndices isH1 blocks - let chunks = splitByIndices h1Indices blocks + -- internal reference IDs change when we chunk the file, + -- so the next two lines fix that: + let reftable = correlateRefs blocks + let blocks' = replaceRefs reftable blocks + let h1Indices = dropWhile (== 0) $ findIndices isH1 blocks' + let chunks = splitByIndices h1Indices blocks' let titleize (Header 1 xs : ys) = Pandoc meta{docTitle = xs} ys titleize xs = Pandoc meta xs - let chapToHtml = writeHtmlString opts'{ writerTemplate = pageTemplate } let chapters = map titleize chunks + let chapToHtml = writeHtmlString opts'{ writerTemplate = pageTemplate } let chapterToEntry :: Int -> Pandoc -> Entry chapterToEntry num chap = mkEntry ("ch" ++ show num ++ ".xhtml") $ fromString $ chapToHtml chap @@ -271,7 +275,6 @@ transformInlines (MathML _) _ _ (x@(Math _ _) : xs) = do result = if "<math" `isPrefixOf` mathml then inOps else mathml return $ RawInline "html" result : xs transformInlines _ _ _ (RawInline _ _ : xs) = return $ Str "" : xs -transformInlines _ _ _ (Link lab (_,_) : xs) = return $ lab ++ xs transformInlines _ _ _ xs = return xs transformBlock :: Block -> Block @@ -305,3 +308,49 @@ imageTypeOf x = case drop 1 (map toLower (takeExtension x)) of "svg" -> Just "image/svg+xml" _ -> Nothing + +data IdentState = IdentState{ + chapterNumber :: Int, + runningIdents :: [String], + chapterIdents :: [String], + identTable :: [(String,String)] + } deriving (Read, Show) + +-- Go through a block list and construct a table +-- correlating the automatically constructed references +-- that would be used in a normal pandoc document with +-- new URLs to be used in the EPUB. For example, what +-- was "header-1" might turn into "ch6.xhtml#header". +correlateRefs :: [Block] -> [(String,String)] +correlateRefs bs = identTable $ execState (mapM_ go bs) + IdentState{ chapterNumber = 0 + , runningIdents = [] + , chapterIdents = [] + , identTable = [] } + where go :: Block -> State IdentState () + go (Header n ils) = do + when (n == 1) $ + modify $ \s -> s{ chapterNumber = chapterNumber s + 1 + , chapterIdents = [] } + st <- get + let runningid = uniqueIdent ils (runningIdents st) + let chapid = if n == 1 + then Nothing + else Just $ uniqueIdent ils (chapterIdents st) + modify $ \s -> s{ runningIdents = runningid : runningIdents st + , chapterIdents = maybe (chapterIdents st) + (: chapterIdents st) chapid + , identTable = (runningid, "ch" ++ show (chapterNumber st) ++ + ".xhtml" ++ maybe "" ('#':) chapid) : identTable st + } + go _ = return () + +-- Replace internal link references using the table produced +-- by correlateRefs. +replaceRefs :: [(String,String)] -> [Block] -> [Block] +replaceRefs refTable = bottomUp replaceOneRef + where replaceOneRef x@(Link lab ('#':xs,tit)) = + case lookup xs refTable of + Just url -> Link lab (url,tit) + Nothing -> x + replaceOneRef x = x diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs index f2208ff4a..8eb5092f9 100644 --- a/src/Text/Pandoc/Writers/HTML.hs +++ b/src/Text/Pandoc/Writers/HTML.hs @@ -35,7 +35,8 @@ import Text.Pandoc.CharacterReferences ( decodeCharacterReferences ) import Text.Pandoc.Shared import Text.Pandoc.Templates import Text.Pandoc.Readers.TeXMath -import Text.Pandoc.Highlighting ( highlightHtml, defaultHighlightingCss ) +import Text.Pandoc.Highlighting ( highlight, styleToHtml, + formatHtmlInline, formatHtmlBlock ) import Text.Pandoc.XML (stripTags, escapeStringForXML) import Network.HTTP ( urlEncode ) import Numeric ( showHex ) @@ -153,7 +154,8 @@ pandocToHtml opts (Pandoc (Meta title' authors' date') blocks) = do ("/*<![CDATA[*/\n" ++ s ++ "/*]]>*/\n") Nothing -> mempty else mempty - let newvars = [("highlighting-css", defaultHighlightingCss) | + let newvars = [("highlighting-css", renderHtml $ styleToHtml + $ writerHighlightStyle opts) | stHighlighting st] ++ [("math", renderHtml math) | stMath st] return (tit, auths, date, toc, thebody, newvars) @@ -361,18 +363,23 @@ blockToHtml _ (RawBlock "html" str) = return $ preEscapedString str blockToHtml _ (RawBlock _ _) = return mempty blockToHtml _ (HorizontalRule) = return H.hr blockToHtml opts (CodeBlock (id',classes,keyvals) rawCode) = do - let classes' = if writerLiterateHaskell opts - then classes + let tolhs = writerLiterateHaskell opts && + any (\c -> map toLower c == "haskell") classes && + any (\c -> map toLower c == "literate") classes + classes' = if tolhs + then map (\c -> if map toLower c == "haskell" + then "literatehaskell" + else c) classes else filter (/= "literate") classes - case highlightHtml False (id',classes',keyvals) rawCode of + adjCode = if tolhs + then unlines . map ("> " ++) . lines $ rawCode + else rawCode + case highlight formatHtmlBlock (id',classes,keyvals) adjCode of Nothing -> let attrs = attrsToHtml opts (id', classes', keyvals) - addBird = if "literate" `elem` classes' - then unlines . map ("> " ++) . lines - else unlines . lines in return $ foldl (!) H.pre attrs $ H.code - $ toHtml $ addBird rawCode + $ toHtml adjCode Just h -> modify (\st -> st{ stHighlighting = True }) >> - return h + return (foldl (!) h (attrsToHtml opts (id',[],keyvals))) blockToHtml opts (BlockQuote blocks) = -- in S5, treat list in blockquote specially -- if default is incremental, make it nonincremental; @@ -534,17 +541,15 @@ inlineToHtml opts inline = (Str str) -> return $ strToHtml str (Space) -> return $ strToHtml " " (LineBreak) -> return H.br - (EmDash) -> return $ strToHtml "—" - (EnDash) -> return $ strToHtml "–" - (Ellipses) -> return $ strToHtml "…" - (Apostrophe) -> return $ strToHtml "’" (Emph lst) -> inlineListToHtml opts lst >>= return . H.em (Strong lst) -> inlineListToHtml opts lst >>= return . H.strong - (Code attr str) -> case highlightHtml True attr str of + (Code attr str) -> case highlight formatHtmlInline attr str of Nothing -> return $ foldl (!) H.code (attrsToHtml opts attr) $ strToHtml str - Just h -> return h + Just h -> return $ foldl (!) h $ + attrsToHtml opts (id',[],keyvals) + where (id',_,keyvals) = attr (Strikeout lst) -> inlineListToHtml opts lst >>= return . H.del (SmallCaps lst) -> inlineListToHtml opts lst >>= diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index cb7df6b8a..4575c6b14 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -41,7 +41,8 @@ import Data.Char ( toLower, isPunctuation ) import Control.Monad.State import Text.Pandoc.Pretty import System.FilePath (dropExtension) -import Text.Pandoc.Highlighting (highlightLaTeX, defaultLaTeXMacros) +import Text.Pandoc.Highlighting (highlight, styleToLaTeX, + formatLaTeXInline, formatLaTeXBlock) data WriterState = WriterState { stInNote :: Bool -- true if we're in a note @@ -60,7 +61,9 @@ data WriterState = , stLHS :: Bool -- true if document has literate haskell code , stBook :: Bool -- true if document uses book or memoir class , stCsquotes :: Bool -- true if document uses csquotes - , stHighlighting :: Bool -- true if document has highlighted code + , stHighlighting :: Bool -- true if document has highlighted code + , stFirstFrame :: Bool -- true til we've written first beamer frame + , stIncremental :: Bool -- true if beamer lists should be displayed bit by bit } -- | Convert Pandoc to LaTeX. @@ -73,23 +76,24 @@ writeLaTeX options document = stTable = False, stStrikeout = False, stSubscript = False, stUrl = False, stGraphics = False, stLHS = False, stBook = writerChapters options, - stCsquotes = False, stHighlighting = False } + stCsquotes = False, stHighlighting = False, + stFirstFrame = True, stIncremental = writerIncremental options } pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do let template = writerTemplate options + let templateLines = lines template let usesBookClass x = "\\documentclass" `isPrefixOf` x && ("{memoir}" `isSuffixOf` x || "{book}" `isSuffixOf` x || "{report}" `isSuffixOf` x) - when (any usesBookClass (lines template)) $ + when (any usesBookClass templateLines) $ modify $ \s -> s{stBook = True} -- check for \usepackage...{csquotes}; if present, we'll use -- \enquote{...} for smart quotes: when ("{csquotes}" `isInfixOf` template) $ modify $ \s -> s{stCsquotes = True} - opts <- liftM stOptions get - let colwidth = if writerWrapText opts - then Just $ writerColumns opts + let colwidth = if writerWrapText options + then Just $ writerColumns options else Nothing titletext <- liftM (render colwidth) $ inlineListToLaTeX title authorsText <- mapM (liftM (render colwidth) . inlineListToLaTeX) authors @@ -99,7 +103,10 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do else case last blocks of Header 1 il -> (init blocks, il) _ -> (blocks, []) - body <- blockListToLaTeX blocks' + blocks'' <- if writerBeamer options + then toSlides blocks' + else return blocks' + body <- blockListToLaTeX blocks'' biblioTitle <- liftM (render colwidth) $ inlineListToLaTeX lastHeader let main = render colwidth body st <- get @@ -118,7 +125,12 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do [ ("toc", if writerTableOfContents options then "yes" else "") , ("body", main) , ("title", titletext) - , ("date", dateText) ] ++ + , ("date", dateText) + , ("documentclass", if writerBeamer options + then "beamer" + else if writerChapters options + then "book" + else "article") ] ++ [ ("author", a) | a <- authorsText ] ++ [ ("verbatim-in-note", "yes") | stVerbInNote st ] ++ [ ("fancy-enums", "yes") | stEnumerate st ] ++ @@ -131,7 +143,9 @@ pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do [ ("graphics", "yes") | stGraphics st ] ++ [ ("book-class", "yes") | stBook st] ++ [ ("listings", "yes") | writerListings options || stLHS st ] ++ - [ ("highlighting-macros", defaultLaTeXMacros) | stHighlighting st ] ++ + [ ("beamer", "yes") | writerBeamer options ] ++ + [ ("highlighting-macros", styleToLaTeX + $ writerHighlightStyle options ) | stHighlighting st ] ++ citecontext return $ if writerStandalone options then renderTemplate context template @@ -160,12 +174,51 @@ stringToLaTeX isUrl = escapeStringUsing latexEscapes , ('\x2019', "'") , ('\x201C', "``") , ('\x201D', "''") + , ('\x2026', "\\ldots{}") + , ('\x2014', "---") + , ('\x2013', "--") ] -- | Puts contents into LaTeX command. inCmd :: String -> Doc -> Doc inCmd cmd contents = char '\\' <> text cmd <> braces contents +toSlides :: [Block] -> State WriterState [Block] +toSlides (Header n ils : bs) = do + tit <- inlineListToLaTeX ils + firstFrame <- gets stFirstFrame + modify $ \s -> s{ stFirstFrame = False } + -- note: [fragile] is required or verbatim breaks + result <- ((Header n ils :) . + (RawBlock "latex" ("\\begin{frame}[fragile]\n" ++ + "\\frametitle{" ++ render Nothing tit ++ "}") :)) + `fmap` toSlides bs + if firstFrame + then return result + else return $ RawBlock "latex" "\\end{frame}" : result +toSlides (HorizontalRule : Header n ils : bs) = + toSlides (Header n ils : bs) +toSlides (HorizontalRule : bs) = do + firstFrame <- gets stFirstFrame + modify $ \s -> s{ stFirstFrame = False } + result <- (RawBlock "latex" "\\begin{frame}[fragile]" :) + `fmap` toSlides bs + if firstFrame + then return result + else return $ RawBlock "latex" "\\end{frame}" : result +toSlides (b:bs) = (b:) `fmap` toSlides bs +toSlides [] = do + firstFrame <- gets stFirstFrame + if firstFrame + then return [] + else return [RawBlock "latex" "\\end{frame}"] + +isListBlock :: Block -> Bool +isListBlock (BulletList _) = True +isListBlock (OrderedList _ _) = True +isListBlock (DefinitionList _) = True +isListBlock _ = False + -- | Convert Pandoc block element to LaTeX. blockToLaTeX :: Block -- ^ Block to convert -> State WriterState Doc @@ -180,8 +233,17 @@ blockToLaTeX (Para lst) = do result <- inlineListToLaTeX lst return $ result <> blankline blockToLaTeX (BlockQuote lst) = do - contents <- blockListToLaTeX lst - return $ "\\begin{quote}" $$ contents $$ "\\end{quote}" + beamer <- writerBeamer `fmap` gets stOptions + case lst of + [b] | beamer && isListBlock b -> do + oldIncremental <- gets stIncremental + modify $ \s -> s{ stIncremental = True } + result <- blockToLaTeX b + modify $ \s -> s{ stIncremental = oldIncremental } + return result + _ -> do + contents <- blockListToLaTeX lst + return $ "\\begin{quote}" $$ contents $$ "\\end{quote}" blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do opts <- gets stOptions case () of @@ -199,8 +261,8 @@ blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do then modify (\s -> s{ stVerbInNote = True }) >> return "Verbatim" else return "verbatim" - return $ flush (text $ "\\begin{" ++ env ++ "}") $$ text str $$ - text ("\\end{" ++ env ++ "}") $$ cr -- final cr because of notes + return $ flush (text ("\\begin{" ++ env ++ "}") $$ text str $$ + text ("\\end{" ++ env ++ "}")) $$ cr -- final cr because of notes listingsCodeBlock = do st <- get let params = if writerListings (stOptions st) @@ -231,17 +293,20 @@ blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do return $ flush ("\\begin{lstlisting}" <> printParams $$ text str $$ "\\end{lstlisting}") $$ cr highlightedCodeBlock = - case highlightLaTeX False ("",classes,keyvalAttr) str of + case highlight formatLaTeXBlock ("",classes,keyvalAttr) str of Nothing -> rawCodeBlock Just h -> modify (\st -> st{ stHighlighting = True }) >> - return (text h) + return (flush $ text h) blockToLaTeX (RawBlock "latex" x) = return $ text x <> blankline blockToLaTeX (RawBlock _ _) = return empty blockToLaTeX (BulletList lst) = do + incremental <- gets stIncremental + let inc = if incremental then "[<+->]" else "" items <- mapM listItemToLaTeX lst - return $ "\\begin{itemize}" $$ vcat items $$ "\\end{itemize}" + return $ text ("\\begin{itemize}" ++ inc) $$ vcat items $$ "\\end{itemize}" blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do st <- get + let inc = if stIncremental st then "[<+->]" else "" let oldlevel = stOLLevel st put $ st {stOLLevel = oldlevel + 1} items <- mapM listItemToLaTeX lst @@ -258,11 +323,13 @@ blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do map toLower (toRomanNumeral oldlevel) ++ "}{" ++ show (start - 1) ++ "}" else empty - return $ "\\begin{enumerate}" <> exemplar $$ resetcounter $$ + return $ text ("\\begin{enumerate}" ++ inc) <> exemplar $$ resetcounter $$ vcat items $$ "\\end{enumerate}" blockToLaTeX (DefinitionList lst) = do + incremental <- gets stIncremental + let inc = if incremental then "[<+->]" else "" items <- mapM defListItemToLaTeX lst - return $ "\\begin{description}" $$ vcat items $$ "\\end{description}" + return $ text ("\\begin{description}" ++ inc) $$ vcat items $$ "\\end{description}" blockToLaTeX HorizontalRule = return $ "\\begin{center}\\rule{3in}{0.4pt}\\end{center}" $$ blankline blockToLaTeX (Header level lst) = do @@ -363,7 +430,6 @@ inlineListToLaTeX lst = mapM inlineToLaTeX lst >>= return . hcat isQuoted :: Inline -> Bool isQuoted (Quoted _ _) = True -isQuoted Apostrophe = True isQuoted _ = False -- | Convert inline element to LaTeX @@ -407,7 +473,7 @@ inlineToLaTeX (Code (_,classes,_) str) = do let chr = ((enumFromTo '!' '~') \\ str) !! 0 return $ text $ "\\lstinline" ++ [chr] ++ str ++ [chr] highlightCode = do - case highlightLaTeX True ("",classes,[]) str of + case highlight formatLaTeXInline ("",classes,[]) str of Nothing -> rawCode Just h -> modify (\st -> st{ stHighlighting = True }) >> return (text h) @@ -439,10 +505,6 @@ inlineToLaTeX (Quoted DoubleQuote lst) = do then "\\," else empty return $ "``" <> s1 <> contents <> s2 <> "''" -inlineToLaTeX Apostrophe = return $ char '\'' -inlineToLaTeX EmDash = return "---" -inlineToLaTeX EnDash = return "--" -inlineToLaTeX Ellipses = return "\\ldots{}" inlineToLaTeX (Str str) = return $ text $ stringToLaTeX False str inlineToLaTeX (Math InlineMath str) = return $ char '$' <> text str <> char '$' inlineToLaTeX (Math DisplayMath str) = return $ "\\[" <> text str <> "\\]" diff --git a/src/Text/Pandoc/Writers/Man.hs b/src/Text/Pandoc/Writers/Man.hs index 78b9274d6..d3735efa7 100644 --- a/src/Text/Pandoc/Writers/Man.hs +++ b/src/Text/Pandoc/Writers/Man.hs @@ -98,7 +98,13 @@ noteToMan opts num note = do -- | Association list of characters to escape. manEscapes :: [(Char, String)] -manEscapes = [('\160', "\\ "), ('\'', "\\[aq]")] ++ backslashEscapes "@\\" +manEscapes = [ ('\160', "\\ ") + , ('\'', "\\[aq]") + , ('’', "'") + , ('\x2014', "\\[em]") + , ('\x2013', "\\[en]") + , ('\x2026', "\\&...") + ] ++ backslashEscapes "@\\" -- | Escape special characters for Man. escapeString :: String -> String @@ -303,10 +309,6 @@ inlineToMan opts (Quoted DoubleQuote lst) = do return $ text "\\[lq]" <> contents <> text "\\[rq]" inlineToMan opts (Cite _ lst) = inlineListToMan opts lst -inlineToMan _ EmDash = return $ text "\\[em]" -inlineToMan _ EnDash = return $ text "\\[en]" -inlineToMan _ Apostrophe = return $ char '\'' -inlineToMan _ Ellipses = return $ text "\\&..." inlineToMan _ (Code _ str) = return $ text $ "\\f[C]" ++ escapeCode str ++ "\\f[]" inlineToMan _ (Str str) = return $ text $ escapeString str diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs index 70202294f..f0f608432 100644 --- a/src/Text/Pandoc/Writers/Markdown.hs +++ b/src/Text/Pandoc/Writers/Markdown.hs @@ -432,10 +432,6 @@ inlineToMarkdown opts (Quoted SingleQuote lst) = do inlineToMarkdown opts (Quoted DoubleQuote lst) = do contents <- inlineListToMarkdown opts lst return $ "“" <> contents <> "”" -inlineToMarkdown _ EmDash = return "\8212" -inlineToMarkdown _ EnDash = return "\8211" -inlineToMarkdown _ Apostrophe = return "\8217" -inlineToMarkdown _ Ellipses = return "\8230" inlineToMarkdown opts (Code attr str) = let tickGroups = filter (\s -> '`' `elem` s) $ group str longest = if null tickGroups diff --git a/src/Text/Pandoc/Writers/MediaWiki.hs b/src/Text/Pandoc/Writers/MediaWiki.hs index a7c7fc482..f31a2c2d1 100644 --- a/src/Text/Pandoc/Writers/MediaWiki.hs +++ b/src/Text/Pandoc/Writers/MediaWiki.hs @@ -346,22 +346,14 @@ inlineToMediaWiki opts (SmallCaps lst) = inlineListToMediaWiki opts lst inlineToMediaWiki opts (Quoted SingleQuote lst) = do contents <- inlineListToMediaWiki opts lst - return $ "‘" ++ contents ++ "’" + return $ "\8216" ++ contents ++ "\8217" inlineToMediaWiki opts (Quoted DoubleQuote lst) = do contents <- inlineListToMediaWiki opts lst - return $ "“" ++ contents ++ "”" + return $ "\8220" ++ contents ++ "\8221" inlineToMediaWiki opts (Cite _ lst) = inlineListToMediaWiki opts lst -inlineToMediaWiki _ EmDash = return "—" - -inlineToMediaWiki _ EnDash = return "–" - -inlineToMediaWiki _ Apostrophe = return "’" - -inlineToMediaWiki _ Ellipses = return "…" - inlineToMediaWiki _ (Code _ str) = return $ "<tt>" ++ (escapeString str) ++ "</tt>" diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs index e675f4e65..23ef2e31d 100644 --- a/src/Text/Pandoc/Writers/OpenDocument.hs +++ b/src/Text/Pandoc/Writers/OpenDocument.hs @@ -154,8 +154,8 @@ inHeaderTags i d = , ("text:outline-level", show i)] d inQuotes :: QuoteType -> Doc -> Doc -inQuotes SingleQuote s = text "‘" <> s <> text "’" -inQuotes DoubleQuote s = text "“" <> s <> text "”" +inQuotes SingleQuote s = char '\8216' <> s <> char '\8217' +inQuotes DoubleQuote s = char '\8220' <> s <> char '\8221' handleSpaces :: String -> Doc handleSpaces s @@ -361,10 +361,6 @@ inlinesToOpenDocument o l = hcat <$> mapM (inlineToOpenDocument o) l -- | Convert an inline element to OpenDocument. inlineToOpenDocument :: WriterOptions -> Inline -> State WriterState Doc inlineToOpenDocument o ils - | Ellipses <- ils = inTextStyle $ text "…" - | EmDash <- ils = inTextStyle $ text "—" - | EnDash <- ils = inTextStyle $ text "–" - | Apostrophe <- ils = inTextStyle $ text "’" | Space <- ils = inTextStyle space | LineBreak <- ils = return $ selfClosingTag "text:line-break" [] | Str s <- ils = inTextStyle $ handleSpaces $ escapeStringForXML s diff --git a/src/Text/Pandoc/Writers/Org.hs b/src/Text/Pandoc/Writers/Org.hs index 6e0fb98e1..4c77ba7c6 100644 --- a/src/Text/Pandoc/Writers/Org.hs +++ b/src/Text/Pandoc/Writers/Org.hs @@ -95,7 +95,12 @@ noteToOrg num note = do -- | Escape special characters for Org. escapeString :: String -> String -escapeString = escapeStringUsing (backslashEscapes "^_") +escapeString = escapeStringUsing $ + [ ('\x2014',"---") + , ('\x2013',"--") + , ('\x2019',"'") + , ('\x2026',"...") + ] ++ backslashEscapes "^_" titleToOrg :: [Inline] -> State WriterState Doc titleToOrg [] = return empty @@ -249,10 +254,6 @@ inlineToOrg (Quoted DoubleQuote lst) = do contents <- inlineListToOrg lst return $ "\"" <> contents <> "\"" inlineToOrg (Cite _ lst) = inlineListToOrg lst -inlineToOrg EmDash = return "---" -inlineToOrg EnDash = return "--" -inlineToOrg Apostrophe = return "'" -inlineToOrg Ellipses = return "..." inlineToOrg (Code _ str) = return $ "=" <> text str <> "=" inlineToOrg (Str str) = return $ text $ escapeString str inlineToOrg (Math t str) = do diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs index 0f0479e16..125ed4f13 100644 --- a/src/Text/Pandoc/Writers/RST.hs +++ b/src/Text/Pandoc/Writers/RST.hs @@ -281,10 +281,6 @@ inlineToRST (Quoted DoubleQuote lst) = do return $ "“" <> contents <> "”" inlineToRST (Cite _ lst) = inlineListToRST lst -inlineToRST EmDash = return $ char '\8212' -inlineToRST EnDash = return $ char '\8211' -inlineToRST Apostrophe = return $ char '\8217' -inlineToRST Ellipses = return $ char '\8230' inlineToRST (Code _ str) = return $ "``" <> text str <> "``" inlineToRST (Str str) = return $ text $ escapeString str inlineToRST (Math t str) = do diff --git a/src/Text/Pandoc/Writers/RTF.hs b/src/Text/Pandoc/Writers/RTF.hs index eb36c1ca6..4e7c2a7cd 100644 --- a/src/Text/Pandoc/Writers/RTF.hs +++ b/src/Text/Pandoc/Writers/RTF.hs @@ -106,7 +106,15 @@ handleUnicode (c:cs) = -- | Escape special characters. escapeSpecial :: String -> String -escapeSpecial = escapeStringUsing (('\t',"\\tab "):(backslashEscapes "{\\}")) +escapeSpecial = escapeStringUsing $ + [ ('\t',"\\tab ") + , ('\8216',"\\u8216'") + , ('\8217',"\\u8217'") + , ('\8220',"\\u8220\"") + , ('\8221',"\\u8221\"") + , ('\8211',"\\u8211-") + , ('\8212',"\\u8212-") + ] ++ backslashEscapes "{\\}" -- | Escape strings as needed for rich text format. stringToRTF :: String -> String @@ -287,10 +295,6 @@ inlineToRTF (Quoted SingleQuote lst) = "\\u8216'" ++ (inlineListToRTF lst) ++ "\\u8217'" inlineToRTF (Quoted DoubleQuote lst) = "\\u8220\"" ++ (inlineListToRTF lst) ++ "\\u8221\"" -inlineToRTF Apostrophe = "\\u8217'" -inlineToRTF Ellipses = "\\u8230?" -inlineToRTF EmDash = "\\u8212-" -inlineToRTF EnDash = "\\u8211-" inlineToRTF (Code _ str) = "{\\f1 " ++ (codeStringToRTF str) ++ "}" inlineToRTF (Str str) = stringToRTF str inlineToRTF (Math _ str) = inlineListToRTF $ readTeXMath str diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs index 4f6645cd5..563ad7044 100644 --- a/src/Text/Pandoc/Writers/Texinfo.hs +++ b/src/Text/Pandoc/Writers/Texinfo.hs @@ -96,6 +96,10 @@ stringToTexinfo = escapeStringUsing texinfoEscapes , ('@', "@@") , (',', "@comma{}") -- only needed in argument lists , ('\160', "@ ") + , ('\x2014', "---") + , ('\x2013', "--") + , ('\x2026', "@dots{}") + , ('\x2019', "'") ] -- | Puts contents into Texinfo command. @@ -387,10 +391,6 @@ inlineToTexinfo (Quoted DoubleQuote lst) = do inlineToTexinfo (Cite _ lst) = inlineListToTexinfo lst -inlineToTexinfo Apostrophe = return $ char '\'' -inlineToTexinfo EmDash = return $ text "---" -inlineToTexinfo EnDash = return $ text "--" -inlineToTexinfo Ellipses = return $ text "@dots{}" inlineToTexinfo (Str str) = return $ text (stringToTexinfo str) inlineToTexinfo (Math _ str) = return $ inCmd "math" $ text str inlineToTexinfo (RawInline f str) | f == "latex" || f == "tex" = diff --git a/src/Text/Pandoc/Writers/Textile.hs b/src/Text/Pandoc/Writers/Textile.hs index 6614ec28e..26d5ec6d7 100644 --- a/src/Text/Pandoc/Writers/Textile.hs +++ b/src/Text/Pandoc/Writers/Textile.hs @@ -72,15 +72,19 @@ withUseTags action = do -- | Escape one character as needed for Textile. escapeCharForTextile :: Char -> String escapeCharForTextile x = case x of - '&' -> "&" - '<' -> "<" - '>' -> ">" - '"' -> """ - '*' -> "*" - '_' -> "_" - '@' -> "@" - '|' -> "|" - c -> [c] + '&' -> "&" + '<' -> "<" + '>' -> ">" + '"' -> """ + '*' -> "*" + '_' -> "_" + '@' -> "@" + '|' -> "|" + '\x2014' -> " -- " + '\x2013' -> " - " + '\x2019' -> "'" + '\x2026' -> "..." + c -> [c] -- | Escape string as needed for Textile. escapeStringForTextile :: String -> String @@ -370,14 +374,6 @@ inlineToTextile opts (Quoted DoubleQuote lst) = do inlineToTextile opts (Cite _ lst) = inlineListToTextile opts lst -inlineToTextile _ EmDash = return " -- " - -inlineToTextile _ EnDash = return " - " - -inlineToTextile _ Apostrophe = return "'" - -inlineToTextile _ Ellipses = return "..." - inlineToTextile _ (Code _ str) = return $ if '@' `elem` str then "<tt>" ++ escapeStringForXML str ++ "</tt>" |
