diff options
Diffstat (limited to 'src/Text/Pandoc/Writers')
-rw-r--r-- | src/Text/Pandoc/Writers/Docbook.hs | 78 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/HTML.hs | 266 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/LaTeX.hs | 43 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/Markdown.hs | 23 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/RST.hs | 8 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/RTF.hs | 8 |
6 files changed, 226 insertions, 200 deletions
diff --git a/src/Text/Pandoc/Writers/Docbook.hs b/src/Text/Pandoc/Writers/Docbook.hs index 0fa4a1d98..29fdf965f 100644 --- a/src/Text/Pandoc/Writers/Docbook.hs +++ b/src/Text/Pandoc/Writers/Docbook.hs @@ -59,14 +59,14 @@ hierarchicalize (block:rest) = x -> (Blk x):(hierarchicalize rest) -- | Convert list of authors to a docbook <author> section -authorToDocbook :: WriterOptions -> [Char] -> Doc -authorToDocbook opts name = inTagsIndented opts "author" $ +authorToDocbook :: [Char] -> Doc +authorToDocbook name = inTagsIndented "author" $ if ',' `elem` name then -- last name first let (lastname, rest) = break (==',') name firstname = removeLeadingSpace rest in - inTagsSimple opts "firstname" (text $ stringToSGML opts firstname) <> - inTagsSimple opts "surname" (text $ stringToSGML opts lastname) + inTagsSimple "firstname" (text $ stringToSGML firstname) <> + inTagsSimple "surname" (text $ stringToSGML lastname) else -- last name last let namewords = words name lengthname = length namewords @@ -74,8 +74,8 @@ authorToDocbook opts name = inTagsIndented opts "author" $ 0 -> ("","") 1 -> ("", name) n -> (joinWithSep " " (take (n-1) namewords), last namewords) in - inTagsSimple opts "firstname" (text $ stringToSGML opts firstname) $$ - inTagsSimple opts "surname" (text $ stringToSGML opts lastname) + inTagsSimple "firstname" (text $ stringToSGML firstname) $$ + inTagsSimple "surname" (text $ stringToSGML lastname) -- | Convert Pandoc document to string in Docbook format. writeDocbook :: WriterOptions -> Pandoc -> String @@ -84,22 +84,24 @@ writeDocbook opts (Pandoc (Meta title authors date) blocks) = then text (writerHeader opts) else empty meta = if (writerStandalone opts) - then inTagsIndented opts "articleinfo" $ - (inTagsSimple opts "title" (inlinesToDocbook opts title)) $$ - (vcat (map (authorToDocbook opts) authors)) $$ - (inTagsSimple opts "date" (text $ stringToSGML opts date)) + then inTagsIndented "articleinfo" $ + (inTagsSimple "title" (wrap opts title)) $$ + (vcat (map authorToDocbook authors)) $$ + (inTagsSimple "date" (text $ stringToSGML date)) else empty blocks' = replaceReferenceLinks blocks (noteBlocks, blocks'') = partition isNoteBlock blocks' opts' = opts {writerNotes = noteBlocks} elements = hierarchicalize blocks'' - body = text (writerIncludeBefore opts') <> + before = writerIncludeBefore opts' + after = writerIncludeAfter opts' + body = (if null before then empty else text before) $$ vcat (map (elementToDocbook opts') elements) $$ - text (writerIncludeAfter opts') + (if null after then empty else text after) body' = if writerStandalone opts' - then inTagsIndented opts "article" (meta $$ body) + then inTagsIndented "article" (meta $$ body) else body in - render $ head $$ body' <> text "\n" + render $ head $$ body' $$ text "" -- | Convert an Element to Docbook. elementToDocbook :: WriterOptions -> Element -> Doc @@ -109,8 +111,8 @@ elementToDocbook opts (Sec title elements) = let elements' = if null elements then [Blk (Para [])] else elements in - inTagsIndented opts "section" $ - inTagsSimple opts "title" (wrap opts title) $$ + inTagsIndented "section" $ + inTagsSimple "title" (wrap opts title) $$ vcat (map (elementToDocbook opts) elements') -- | Convert a list of Pandoc blocks to Docbook. @@ -128,7 +130,7 @@ listItemToDocbook opts item = let plainToPara (Plain x) = Para x plainToPara y = y in let item' = map plainToPara item in - inTagsIndented opts "listitem" (blocksToDocbook opts item') + inTagsIndented "listitem" (blocksToDocbook opts item') -- | Convert a Pandoc block element to Docbook. blockToDocbook :: WriterOptions -> Block -> Doc @@ -136,20 +138,20 @@ blockToDocbook opts Blank = text "" blockToDocbook opts Null = empty blockToDocbook opts (Plain lst) = wrap opts lst blockToDocbook opts (Para lst) = - inTagsIndented opts "para" (wrap opts lst) + inTagsIndented "para" (wrap opts lst) blockToDocbook opts (BlockQuote blocks) = - inTagsIndented opts "blockquote" (blocksToDocbook opts blocks) + inTagsIndented "blockquote" (blocksToDocbook opts blocks) blockToDocbook opts (CodeBlock str) = text "<screen>\n" <> text (escapeSGML str) <> text "\n</screen>" blockToDocbook opts (BulletList lst) = - inTagsIndented opts "itemizedlist" $ listItemsToDocbook opts lst + inTagsIndented "itemizedlist" $ listItemsToDocbook opts lst blockToDocbook opts (OrderedList lst) = - inTagsIndented opts "orderedlist" $ listItemsToDocbook opts lst + inTagsIndented "orderedlist" $ listItemsToDocbook opts lst blockToDocbook opts (RawHtml str) = text str -- raw XML block blockToDocbook opts HorizontalRule = empty -- not semantic blockToDocbook opts (Note _ _) = empty -- shouldn't occur blockToDocbook opts (Key _ _) = empty -- shouldn't occur -blockToDocbook opts _ = inTagsIndented opts "para" (text "Unknown block type") +blockToDocbook opts _ = inTagsIndented "para" (text "Unknown block type") -- | Put string in CDATA section cdata :: String -> Doc @@ -165,14 +167,20 @@ inlinesToDocbook opts lst = hcat (map (inlineToDocbook opts) lst) -- | Convert an inline element to Docbook. inlineToDocbook :: WriterOptions -> Inline -> Doc -inlineToDocbook opts (Str str) = text $ stringToSGML opts str +inlineToDocbook opts (Str str) = text $ stringToSGML str inlineToDocbook opts (Emph lst) = - inTagsSimple opts "emphasis" (inlinesToDocbook opts lst) + inTagsSimple "emphasis" (inlinesToDocbook opts lst) inlineToDocbook opts (Strong lst) = - inTags False opts "emphasis" [("role", "strong")] + inTags False "emphasis" [("role", "strong")] (inlinesToDocbook opts lst) +inlineToDocbook opts (Quoted _ lst) = + inTagsSimple "quote" (inlinesToDocbook opts lst) +inlineToDocbook opts Apostrophe = text "'" +inlineToDocbook opts Ellipses = text "…" +inlineToDocbook opts EmDash = text "—" +inlineToDocbook opts EnDash = text "–" inlineToDocbook opts (Code str) = - inTagsSimple opts "literal" $ text (escapeSGML str) + inTagsSimple "literal" $ text (escapeSGML str) inlineToDocbook opts (TeX str) = inlineToDocbook opts (Code str) inlineToDocbook opts (HtmlInline str) = empty inlineToDocbook opts LineBreak = @@ -180,19 +188,19 @@ inlineToDocbook opts LineBreak = inlineToDocbook opts Space = char ' ' inlineToDocbook opts (Link txt (Src src tit)) = case (matchRegex (mkRegex "mailto:(.*)") src) of - Just [addr] -> inTagsSimple opts "email" $ text (escapeSGML addr) - Nothing -> inTags False opts "ulink" [("url", src)] $ + Just [addr] -> inTagsSimple "email" $ text (escapeSGML addr) + Nothing -> inTags False "ulink" [("url", src)] $ inlinesToDocbook opts txt inlineToDocbook opts (Link text (Ref ref)) = empty -- shouldn't occur inlineToDocbook opts (Image alt (Src src tit)) = let titleDoc = if null tit then empty - else inTagsIndented opts "objectinfo" $ - inTagsIndented opts "title" - (text $ stringToSGML opts tit) in - inTagsIndented opts "inlinemediaobject" $ - inTagsIndented opts "imageobject" $ - titleDoc $$ selfClosingTag opts "imagedata" [("fileref", src)] + else inTagsIndented "objectinfo" $ + inTagsIndented "title" + (text $ stringToSGML tit) in + inTagsIndented "inlinemediaobject" $ + inTagsIndented "imageobject" $ + titleDoc $$ selfClosingTag "imagedata" [("fileref", src)] inlineToDocbook opts (Image alternate (Ref ref)) = empty --shouldn't occur inlineToDocbook opts (NoteRef ref) = let notes = writerNotes opts @@ -200,4 +208,4 @@ inlineToDocbook opts (NoteRef ref) = if null hits then empty else let (Note _ contents) = head hits in - inTagsIndented opts "footnote" $ blocksToDocbook opts contents + inTagsIndented "footnote" $ blocksToDocbook opts contents diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs index b42d78eb0..4c869ac21 100644 --- a/src/Text/Pandoc/Writers/HTML.hs +++ b/src/Text/Pandoc/Writers/HTML.hs @@ -37,48 +37,53 @@ import Text.Regex ( mkRegex, matchRegex ) import Numeric ( showHex ) import Data.Char ( ord, toLower ) import Data.List ( isPrefixOf, partition ) +import Text.PrettyPrint.HughesPJ hiding ( Str ) -- | Convert Pandoc document to string in HTML format. writeHtml :: WriterOptions -> Pandoc -> String -writeHtml options (Pandoc (Meta title authors date) blocks) = - let titlePrefix = writerTitlePrefix options in +writeHtml opts (Pandoc (Meta title authors date) blocks) = + let titlePrefix = writerTitlePrefix opts in let topTitle = if not (null titlePrefix) then [Str titlePrefix] ++ (if not (null title) then [Str " - "] ++ title else []) else title in - let head = if (writerStandalone options) - then htmlHeader options (Meta topTitle authors date) - else "" - titleBlocks = if (writerStandalone options) && (not (null title)) && - (not (writerS5 options)) + let head = if (writerStandalone opts) + then htmlHeader opts (Meta topTitle authors date) + else empty + titleBlocks = if (writerStandalone opts) && (not (null title)) && + (not (writerS5 opts)) then [RawHtml "<h1 class=\"title\">", Plain title, - RawHtml "</h1>\n"] + RawHtml "</h1>"] else [] - foot = if (writerStandalone options) then "</body>\n</html>\n" else "" + foot = if (writerStandalone opts) + then text "</body>\n</html>" + else empty blocks' = replaceReferenceLinks (titleBlocks ++ blocks) (noteBlocks, blocks'') = partition isNoteBlock blocks' - body = (writerIncludeBefore options) ++ - concatMap (blockToHtml options) blocks'' ++ - footnoteSection options noteBlocks ++ - (writerIncludeAfter options) in - head ++ body ++ foot + before = writerIncludeBefore opts + after = writerIncludeAfter opts + body = (if null before then empty else text before) $$ + vcat (map (blockToHtml opts) blocks'') $$ + footnoteSection opts noteBlocks $$ + (if null after then empty else text after) in + render $ head $$ body $$ foot $$ text "" -- | Convert list of Note blocks to a footnote <div>. -- Assumes notes are sorted. -footnoteSection :: WriterOptions -> [Block] -> String -footnoteSection options notes = +footnoteSection :: WriterOptions -> [Block] -> Doc +footnoteSection opts notes = if null notes - then "" - else "<div class=\"footnotes\">\n<hr />\n<ol>\n" ++ - concatMap (blockToHtml options) notes ++ - "</ol>\n</div>\n" + then empty + else inTags True "div" [("class","footnotes")] $ + selfClosingTag "hr" [] $$ (inTagsIndented "ol" + (vcat $ map (blockToHtml opts) notes)) -- | Obfuscate a "mailto:" link using Javascript. -obfuscateLink :: WriterOptions -> [Inline] -> String -> String -obfuscateLink options text src = +obfuscateLink :: WriterOptions -> [Inline] -> String -> Doc +obfuscateLink opts txt src = let emailRegex = mkRegex "mailto:*([^@]*)@(.*)" - text' = inlineListToHtml options text + text' = render $ inlineListToHtml opts txt src' = map toLower src in case (matchRegex emailRegex src') of (Just [name, domain]) -> @@ -91,16 +96,17 @@ obfuscateLink options text src = then name ++ " at " ++ domain' else text' ++ " (" ++ name ++ " at " ++ domain' ++ ")" in - if writerStrictMarkdown options - then "<a href=\"" ++ obfuscateString src' ++ "\">" ++ - obfuscateString text' ++ "</a>" - else "<script type=\"text/javascript\">\n<!--\nh='" ++ + if writerStrictMarkdown opts + then inTags False "a" [("href", obfuscateString src')] $ + text $ obfuscateString text' + else inTags False "script" [("type", "text/javascript")] + (text ("\n<!--\nh='" ++ obfuscateString domain ++ "';a='" ++ at' ++ "';n='" ++ obfuscateString name ++ "';e=n+a+h;\n" ++ "document.write('<a h'+'ref'+'=\"ma'+'ilto'+':'+e+'\">'+" ++ - linkText ++ "+'<\\/'+'a'+'>');\n// -->\n</script><noscript>" ++ - obfuscateString altText ++ "</noscript>" - _ -> "<a href=\"" ++ src ++ "\">" ++ text' ++ "</a>" -- malformed email + linkText ++ "+'<\\/'+'a'+'>');\n// -->\n")) <> + inTagsSimple "noscript" (text (obfuscateString altText)) + _ -> inTags False "a" [("href", src)] (text text') -- malformed email -- | Obfuscate character as entity. obfuscateChar :: Char -> String @@ -113,117 +119,123 @@ obfuscateChar char = obfuscateString :: String -> String obfuscateString = concatMap obfuscateChar --- | Returns an HTML header with appropriate bibliographic information. -htmlHeader :: WriterOptions -> Meta -> String -htmlHeader options (Meta title authors date) = - let titletext = "<title>" ++ (inlineListToHtml options title) ++ - "</title>\n" +-- | Return an HTML header with appropriate bibliographic information. +htmlHeader :: WriterOptions -> Meta -> Doc +htmlHeader opts (Meta title authors date) = + let titletext = inTagsSimple "title" (wrap opts title) authortext = if (null authors) - then "" - else "<meta name=\"author\" content=\"" ++ - (joinWithSep ", " (map (stringToSGML options) authors)) ++ - "\" />\n" + then empty + else selfClosingTag "meta" [("name", "author"), + ("content", + joinWithSep ", " (map stringToSGML authors))] datetext = if (date == "") - then "" - else "<meta name=\"date\" content=\"" ++ - (stringToSGML options date) ++ "\" />\n" in - (writerHeader options) ++ authortext ++ datetext ++ titletext ++ - "</head>\n<body>\n" + then empty + else selfClosingTag "meta" [("name", "date"), + ("content", stringToSGML date)] in + text (writerHeader opts) $$ authortext $$ datetext $$ titletext $$ + text "</head>\n<body>" + +-- | Take list of inline elements and return wrapped doc. +wrap :: WriterOptions -> [Inline] -> Doc +wrap opts lst = fsep $ map (inlineListToHtml opts) (splitBy Space lst) -- | Convert Pandoc block element to HTML. -blockToHtml :: WriterOptions -> Block -> String -blockToHtml options Blank = "\n" -blockToHtml options Null = "" -blockToHtml options (Plain lst) = inlineListToHtml options lst -blockToHtml options (Para lst) = "<p>" ++ (inlineListToHtml options lst) ++ "</p>\n" -blockToHtml options (BlockQuote blocks) = - if (writerS5 options) +blockToHtml :: WriterOptions -> Block -> Doc +blockToHtml opts Blank = text "" +blockToHtml opts Null = empty +blockToHtml opts (Plain lst) = wrap opts lst +blockToHtml opts (Para lst) = inTagsIndented "p" $ wrap opts lst +blockToHtml opts (BlockQuote blocks) = + if (writerS5 opts) then -- in S5, treat list in blockquote specially -- if default is incremental, make it nonincremental; -- otherwise incremental - let inc = not (writerIncremental options) in + let inc = not (writerIncremental opts) in case blocks of - [BulletList lst] -> blockToHtml (options {writerIncremental = + [BulletList lst] -> blockToHtml (opts {writerIncremental = inc}) (BulletList lst) - [OrderedList lst] -> blockToHtml (options {writerIncremental = + [OrderedList lst] -> blockToHtml (opts {writerIncremental = inc}) (OrderedList lst) - otherwise -> "<blockquote>\n" ++ - (concatMap (blockToHtml options) blocks) ++ - "</blockquote>\n" - else "<blockquote>\n" ++ (concatMap (blockToHtml options) blocks) ++ - "</blockquote>\n" -blockToHtml options (Note ref lst) = - let contents = (concatMap (blockToHtml options) lst) in - "<li id=\"fn" ++ ref ++ "\">" ++ contents ++ " <a href=\"#fnref" ++ ref ++ - "\" class=\"footnoteBacklink\" title=\"Jump back to footnote " ++ ref ++ - "\">↩</a></li>\n" -blockToHtml options (Key _ _) = "" -blockToHtml options (CodeBlock str) = - "<pre><code>" ++ (escapeSGML str) ++ "\n</code></pre>\n" -blockToHtml options (RawHtml str) = str -blockToHtml options (BulletList lst) = - let attribs = if (writerIncremental options) - then " class=\"incremental\"" - else "" in - "<ul" ++ attribs ++ ">\n" ++ (concatMap (listItemToHtml options) lst) ++ - "</ul>\n" -blockToHtml options (OrderedList lst) = - let attribs = if (writerIncremental options) - then " class=\"incremental\"" - else "" in - "<ol" ++ attribs ++ ">\n" ++ (concatMap (listItemToHtml options) lst) ++ - "</ol>\n" -blockToHtml options HorizontalRule = "<hr />\n" -blockToHtml options (Header level lst) = - let contents = inlineListToHtml options lst in + otherwise -> inTagsIndented "blockquote" $ + vcat $ map (blockToHtml opts) blocks + else inTagsIndented "blockquote" $ vcat $ map (blockToHtml opts) blocks +blockToHtml opts (Note ref lst) = + let contents = (vcat $ map (blockToHtml opts) lst) in + inTags True "li" [("id", "fn" ++ ref)] $ + contents <> inTags False "a" [("href", "#fnref" ++ ref), + ("class", "footnoteBacklink"), + ("title", "Jump back to footnote " ++ ref)] + (text "↩") +blockToHtml opts (Key _ _) = empty +blockToHtml opts (CodeBlock str) = + text "<pre><code>" <> text (escapeSGML str) <> text "\n</code></pre>" +blockToHtml opts (RawHtml str) = text str +blockToHtml opts (BulletList lst) = + let attribs = if (writerIncremental opts) + then [("class","incremental")] + else [] in + inTags True "ul" attribs $ vcat $ map (listItemToHtml opts) lst +blockToHtml opts (OrderedList lst) = + let attribs = if (writerIncremental opts) + then [("class","incremental")] + else [] in + inTags True "ol" attribs $ vcat $ map (listItemToHtml opts) lst +blockToHtml opts HorizontalRule = selfClosingTag "hr" [] +blockToHtml opts (Header level lst) = + let contents = wrap opts lst in if ((level > 0) && (level <= 6)) - then "<h" ++ (show level) ++ ">" ++ contents ++ - "</h" ++ (show level) ++ ">\n" - else "<p>" ++ contents ++ "</p>\n" -listItemToHtml options list = - "<li>" ++ (concatMap (blockToHtml options) list) ++ "</li>\n" + then inTagsSimple ("h" ++ show level) contents + else inTagsSimple "p" contents + +listItemToHtml :: WriterOptions -> [Block] -> Doc +listItemToHtml opts list = + inTagsSimple "li" $ vcat $ map (blockToHtml opts) list -- | Convert list of Pandoc inline elements to HTML. -inlineListToHtml :: WriterOptions -> [Inline] -> String -inlineListToHtml options lst = - -- consolidate adjacent Str and Space elements for more intelligent - -- smart typography filtering - let lst' = consolidateList lst in - concatMap (inlineToHtml options) lst' +inlineListToHtml :: WriterOptions -> [Inline] -> Doc +inlineListToHtml opts lst = hcat (map (inlineToHtml opts) lst) -- | Convert Pandoc inline element to HTML. -inlineToHtml :: WriterOptions -> Inline -> String -inlineToHtml options (Emph lst) = - "<em>" ++ (inlineListToHtml options lst) ++ "</em>" -inlineToHtml options (Strong lst) = - "<strong>" ++ (inlineListToHtml options lst) ++ "</strong>" -inlineToHtml options (Code str) = - "<code>" ++ (escapeSGML str) ++ "</code>" -inlineToHtml options (Str str) = stringToSGML options str -inlineToHtml options (TeX str) = (escapeSGML str) -inlineToHtml options (HtmlInline str) = str -inlineToHtml options (LineBreak) = "<br />\n" -inlineToHtml options Space = " " -inlineToHtml options (Link text (Src src tit)) = - let title = stringToSGML options tit in +inlineToHtml :: WriterOptions -> Inline -> Doc +inlineToHtml opts (Emph lst) = + inTagsSimple "em" (inlineListToHtml opts lst) +inlineToHtml opts (Strong lst) = + inTagsSimple "strong" (inlineListToHtml opts lst) +inlineToHtml opts (Code str) = + inTagsSimple "code" $ text (escapeSGML str) +inlineToHtml opts (Quoted SingleQuote lst) = + text "‘" <> (inlineListToHtml opts lst) <> text "’" +inlineToHtml opts (Quoted DoubleQuote lst) = + text "“" <> (inlineListToHtml opts lst) <> text "”" +inlineToHtml opts EmDash = text "—" +inlineToHtml opts EnDash = text "–" +inlineToHtml opts Ellipses = text "…" +inlineToHtml opts Apostrophe = text "’" +inlineToHtml opts (Str str) = text $ stringToSGML str +inlineToHtml opts (TeX str) = text $ escapeSGML str +inlineToHtml opts (HtmlInline str) = text str +inlineToHtml opts (LineBreak) = selfClosingTag "br" [] +inlineToHtml opts Space = space +inlineToHtml opts (Link txt (Src src tit)) = + let title = stringToSGML tit in if (isPrefixOf "mailto:" src) - then obfuscateLink options text src - else "<a href=\"" ++ (escapeSGML src) ++ "\"" ++ - (if tit /= "" then " title=\"" ++ title ++ "\">" else ">") ++ - (inlineListToHtml options text) ++ "</a>" -inlineToHtml options (Link text (Ref ref)) = - "[" ++ (inlineListToHtml options text) ++ "][" ++ - (inlineListToHtml options ref) ++ "]" + then obfuscateLink opts txt src + else inTags False "a" ([("href", escapeSGML src)] ++ + if null tit then [] else [("title", title)]) + (inlineListToHtml opts txt) +inlineToHtml opts (Link txt (Ref ref)) = + char '[' <> (inlineListToHtml opts txt) <> text "][" <> + (inlineListToHtml opts ref) <> char ']' -- this is what markdown does, for better or worse -inlineToHtml options (Image alt (Src source tit)) = - let title = stringToSGML options tit - alternate = inlineListToHtml options alt in - "<img src=\"" ++ source ++ "\"" ++ - (if tit /= "" then " title=\"" ++ title ++ "\"" else "") ++ - (if alternate /= "" then " alt=\"" ++ alternate ++ "\"" else "") ++ ">" -inlineToHtml options (Image alternate (Ref ref)) = - "![" ++ (inlineListToHtml options alternate) ++ "][" ++ - (inlineListToHtml options ref) ++ "]" -inlineToHtml options (NoteRef ref) = - "<sup class=\"footnoteRef\" id=\"fnref" ++ ref ++ "\"><a href=\"#fn" ++ - ref ++ "\">" ++ ref ++ "</a></sup>" +inlineToHtml opts (Image alt (Src source tit)) = + let title = stringToSGML tit + alternate = render $ inlineListToHtml opts alt in + selfClosingTag "img" $ [("src", source)] ++ + (if null tit then [] else [("title", title)]) ++ + (if null alternate then [] else [("alt", alternate)]) +inlineToHtml opts (Image alternate (Ref ref)) = + text "![" <> (inlineListToHtml opts alternate) <> text "][" <> + (inlineListToHtml opts ref) <> char ']' +inlineToHtml opts (NoteRef ref) = + inTags False "sup" [("class", "footnoteRef"), ("id", "fnref" ++ ref)] + (inTags False "a" [("href", "#fn" ++ ref)] $ text ref) diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index e34b7b61e..aca72535d 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -84,36 +84,9 @@ escapeBar = gsub "\\|" "\\\\textbar{}" escapeLt = gsub "<" "\\\\textless{}" escapeGt = gsub ">" "\\\\textgreater{}" -escapeDoubleQuotes = - gsub "\"" "''" . -- rest are right quotes . - gsub "``\\\\footnote" "''\\\\footnote" . -- except \footnote - gsub "\"\\\\" "``\\\\" . -- left quote before latex command - gsub "([[:space:]])\"" "\\1``" . -- never right quote after space - gsub "\"('|`)([^[:punct:][:space:]])" "``{}`\\2" . -- "'word left - gsub "\"([^[:punct:][:space:]])" "``\\1" -- "word left - -escapeSingleQuotes = - gsub "`\\\\footnote" "'\\\\footnote" . -- except \footnote - gsub "'\\\\" "`\\\\" . -- left quote before latex command - gsub "('|`)(\"|``)" "`{}``" . -- '"word left - gsub "([^[:punct:][:space:]])`(s|S)" "\\1'\\2" . -- catch possessives - gsub "^'([^[:punct:][:space:]])" "`\\1" . -- 'word left - gsub "([[:space:]])'" "\\1`" . -- never right quote after space - gsub "([[:space:]])'([^[:punct:][:space:]])" "\\1`\\2" - -- 'word left (leave possessives) - -escapeEllipses = gsub "\\.\\.\\.|\\. \\. \\." "\\ldots{}" - -escapeDashes = gsub "([0-9])-([0-9])" "\\1--\\2" . - gsub " *--- *" "---" . - gsub "([^-])--([^-])" "\\1---\\2" - -escapeSmart = escapeDashes . escapeSingleQuotes . escapeDoubleQuotes . - escapeEllipses - --- | Escape string for LaTeX (including smart quotes, dashes, ellipses) +-- | Escape string for LaTeX stringToLaTeX :: String -> String -stringToLaTeX = escapeSmart . escapeGt . escapeLt . escapeBar . escapeHat . +stringToLaTeX = escapeGt . escapeLt . escapeBar . escapeHat . escapeSpecial . fixBackslash . escapeBrackets . escapeBackslash @@ -158,9 +131,7 @@ inlineListToLaTeX :: [Block] -- ^ List of note blocks to use in resolving note -> [Inline] -- ^ Inlines to convert -> String inlineListToLaTeX notes lst = - -- first, consolidate Str and Space for more effective smartquotes: - let lst' = consolidateList lst in - concatMap (inlineToLaTeX notes) lst' + concatMap (inlineToLaTeX notes) lst -- | Convert inline element to LaTeX inlineToLaTeX :: [Block] -- ^ List of note blocks to use in resolving note refs @@ -173,6 +144,14 @@ inlineToLaTeX notes (Strong lst) = "\\textbf{" ++ inlineToLaTeX notes (Code str) = "\\verb" ++ [chr] ++ stuffing ++ [chr] where stuffing = str chr = ((enumFromTo '!' '~') \\ stuffing) !! 0 +inlineToLaTeX notes (Quoted SingleQuote lst) = + "`" ++ inlineListToLaTeX notes lst ++ "'" +inlineToLaTeX notes (Quoted DoubleQuote lst) = + "``" ++ inlineListToLaTeX notes lst ++ "''" +inlineToLaTeX notes Apostrophe = "'" +inlineToLaTeX notes EmDash = "---" +inlineToLaTeX notes EnDash = "--" +inlineToLaTeX notes Ellipses = "\\ldots{}" inlineToLaTeX notes (Str str) = stringToLaTeX str inlineToLaTeX notes (TeX str) = str inlineToLaTeX notes (HtmlInline str) = "" diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs index d5ec137cd..343942421 100644 --- a/src/Text/Pandoc/Writers/Markdown.hs +++ b/src/Text/Pandoc/Writers/Markdown.hs @@ -35,6 +35,7 @@ module Text.Pandoc.Writers.Markdown ( import Text.Regex ( matchRegex, mkRegex ) import Text.Pandoc.Definition import Text.Pandoc.Shared +import Data.List ( group ) import Text.PrettyPrint.HughesPJ hiding ( Str ) -- | Convert Pandoc to Markdown. @@ -154,12 +155,22 @@ inlineToMarkdown (Emph lst) = text "*" <> (inlineListToMarkdown lst) <> text "*" inlineToMarkdown (Strong lst) = text "**" <> (inlineListToMarkdown lst) <> text "**" -inlineToMarkdown (Code str) = - case (matchRegex (mkRegex "``") str) of - Just match -> text ("` " ++ str ++ " `") - Nothing -> case (matchRegex (mkRegex "`") str) of - Just match -> text ("`` " ++ str ++ " ``") - Nothing -> text ("`" ++ str ++ "`") +inlineToMarkdown (Quoted SingleQuote lst) = char '\'' <> + (inlineListToMarkdown lst) <> char '\'' +inlineToMarkdown (Quoted DoubleQuote lst) = char '"' <> + (inlineListToMarkdown lst) <> char '"' +inlineToMarkdown EmDash = text "--" +inlineToMarkdown EnDash = char '-' +inlineToMarkdown Apostrophe = char '\'' +inlineToMarkdown Ellipses = text "..." +inlineToMarkdown (Code str) = + let tickGroups = filter (\s -> '`' `elem` s) $ group str + longest = if null tickGroups + then 0 + else maximum $ map length tickGroups + marker = replicate (longest + 1) '`' + spacer = if (longest == 0) then "" else " " in + text (marker ++ spacer ++ str ++ spacer ++ marker) inlineToMarkdown (Str str) = text $ escapeString str inlineToMarkdown (TeX str) = text str inlineToMarkdown (HtmlInline str) = text str diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs index 9184e0200..7e1581908 100644 --- a/src/Text/Pandoc/Writers/RST.hs +++ b/src/Text/Pandoc/Writers/RST.hs @@ -182,6 +182,14 @@ inlineToRST (Emph lst) = let (main, refs) = inlineListToRST lst in (text "*" <> main <> text "*", refs) inlineToRST (Strong lst) = let (main, refs) = inlineListToRST lst in (text "**" <> main <> text "**", refs) +inlineToRST (Quoted SingleQuote lst) = let (main, refs) = inlineListToRST lst in + (char '\'' <> main <> char '\'', refs) +inlineToRST (Quoted DoubleQuote lst) = let (main, refs) = inlineListToRST lst in + (char '"' <> main <> char '"', refs) +inlineToRST EmDash = (text "--", empty) +inlineToRST EnDash = (char '-', empty) +inlineToRST Apostrophe = (char '\'', empty) +inlineToRST Ellipses = (text "...", empty) inlineToRST (Code str) = (text $ "``" ++ str ++ "``", empty) inlineToRST (Str str) = (text $ escapeString str, empty) inlineToRST (TeX str) = (text str, empty) diff --git a/src/Text/Pandoc/Writers/RTF.hs b/src/Text/Pandoc/Writers/RTF.hs index 28cbe2ee8..20f06d21b 100644 --- a/src/Text/Pandoc/Writers/RTF.hs +++ b/src/Text/Pandoc/Writers/RTF.hs @@ -211,6 +211,14 @@ inlineToRTF :: [Block] -- ^ list of note blocks inlineToRTF notes (Emph lst) = "{\\i " ++ (inlineListToRTF notes lst) ++ "} " inlineToRTF notes (Strong lst) = "{\\b " ++ (inlineListToRTF notes lst) ++ "} " +inlineToRTF notes (Quoted SingleQuote lst) = + "\\u8216'" ++ (inlineListToRTF notes lst) ++ "\\u8217'" +inlineToRTF notes (Quoted DoubleQuote lst) = + "\\u8220\"" ++ (inlineListToRTF notes lst) ++ "\\u8221\"" +inlineToRTF notes Apostrophe = "\\u8217'" +inlineToRTF notes Ellipses = "\\u8230?" +inlineToRTF notes EmDash = "\\u8212-" +inlineToRTF notes EnDash = "\\u8211-" inlineToRTF notes (Code str) = "{\\f1 " ++ (codeStringToRTF str) ++ "} " inlineToRTF notes (Str str) = stringToRTF str inlineToRTF notes (TeX str) = latexToRTF str |