diff options
| author | fiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b> | 2007-01-06 09:54:58 +0000 |
|---|---|---|
| committer | fiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b> | 2007-01-06 09:54:58 +0000 |
| commit | bb8478e4e24b431ca81ee7f669d517eb11a47500 (patch) | |
| tree | 3dedfbceaf88404e531b81e37f07b8f026f07ebb /src/Text/Pandoc/Writers | |
| parent | 06e6107f535ae921f4b1fec2e7de7dd98b793435 (diff) | |
| download | pandoc-bb8478e4e24b431ca81ee7f669d517eb11a47500.tar.gz | |
Merged changes from 'quotes' branch since r431. Smart typography
is now handled in the Markdown and LaTeX readers, rather than in
the writers. The HTML writer has been rewritten to use the
prettyprinting library.
git-svn-id: https://pandoc.googlecode.com/svn/trunk@436 788f1e2b-df1e-0410-8736-df70ead52e1b
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 |
