git.iko.soy/typeable/pandoc
on master help sign in
Support bidirectional text output with XeLaTeX, ConTeXt and HTML
7b0c1e0mb21
@@ -959,6 +959,25 @@ as `title`, `author`, and `date`) as well as the following:
959 Currently only used by XeTeX through the generated
959 Currently only used by XeTeX through the generated
960 `polyglossia-otherlangs` variable.
960 `polyglossia-otherlangs` variable.
961
961
962+`dir`
963+: the base direction of the document, either `rtl` (right-to-left)
964+ or `ltr` (left-to-right).
965+
966+ For bidirectional documents, native pandoc `span`s and `div`s
967+ with the `dir` attribute (value `rtl` or `ltr`) can be used to
968+ override the base direction in some output formats.
969+ This may not always be necessary if the final renderer
970+ (e.g. the browser, when generating HTML) supports the
971+ [Unicode Bidirectional Algorithm][uba-basics].
972+
973+ When using LaTeX for bidi documents, only the XeLaTeX engine
974+ is fully supported (see `--latex-engine`).
975+ Setting the `dir` variable enables bidirectional text
976+ handling in LaTeX and ConTeXt, thus even if the base direction
977+ is the default left-to-right, you should set `dir: ltr` for
978+ documents that also contain some right-to-left script.
979+
980+
962`slidy-url`
981`slidy-url`
963: base URL for Slidy documents (defaults to
982: base URL for Slidy documents (defaults to
964 `http://www.w3.org/Talks/Tools/Slidy2`)
983 `http://www.w3.org/Talks/Tools/Slidy2`)
src/Text/Pandoc/Writers/ConTeXt.hs+24−9
@@ -83,13 +83,18 @@ pandocToConTeXt options (Pandoc meta blocks) = do
83 $ metadata
83 $ metadata
84 let context' = defField "context-lang" (maybe "" (fromBcp47 . splitBy (=='-')) $
84 let context' = defField "context-lang" (maybe "" (fromBcp47 . splitBy (=='-')) $
85 getField "lang" context)
85 getField "lang" context)
86+ $ defField "context-dir" (toContextDir $ getField "dir" context)
86− context
87+ $ context
87 return $ if writerStandalone options
88 return $ if writerStandalone options
88 then renderTemplate' (writerTemplate options) context'
89 then renderTemplate' (writerTemplate options) context'
89 else main
90 else main
90
91
91−-- escape things as needed for ConTeXt
92+toContextDir :: Maybe String -> String
93+toContextDir (Just "rtl") = "r2l"
94+toContextDir (Just "ltr") = "l2r"
95+toContextDir _ = ""
92
96
97+-- | escape things as needed for ConTeXt
93escapeCharForConTeXt :: WriterOptions -> Char -> String
98escapeCharForConTeXt :: WriterOptions -> Char -> String
94escapeCharForConTeXt opts ch =
99escapeCharForConTeXt opts ch =
95 let ligatures = writerTeXLigatures opts in
100 let ligatures = writerTeXLigatures opts in
@@ -151,13 +156,18 @@ blockToConTeXt (CodeBlock _ str) =
151 -- blankline because \stoptyping can't have anything after it, inc. '}'
156 -- blankline because \stoptyping can't have anything after it, inc. '}'
152blockToConTeXt (RawBlock "context" str) = return $ text str <> blankline
157blockToConTeXt (RawBlock "context" str) = return $ text str <> blankline
153blockToConTeXt (RawBlock _ _ ) = return empty
158blockToConTeXt (RawBlock _ _ ) = return empty
154−blockToConTeXt (Div (ident,_,_) bs) = do
159+blockToConTeXt (Div (ident,_,kvs) bs) = do
155 contents <- blockListToConTeXt bs
160 contents <- blockListToConTeXt bs
156− if null ident
161+ let contents' = if null ident
157− then return contents
162+ then contents
158− else return $
159− ("\\reference" <> brackets (text $ toLabel ident) <> braces empty <>
163+ else ("\\reference" <> brackets (text $ toLabel ident) <>
160− "%") $$ contents
164+ braces empty <> "%") $$ contents
165+ let align dir = blankline <> "\\startalignment[" <> dir <> "]"
166+ $$ contents' $$ "\\stopalignment" <> blankline
167+ return $ case lookup "dir" kvs of
168+ Just "rtl" -> align "righttoleft"
169+ Just "ltr" -> align "lefttoright"
170+ _ -> contents'
161blockToConTeXt (BulletList lst) = do
171blockToConTeXt (BulletList lst) = do
162 contents <- mapM listItemToConTeXt lst
172 contents <- mapM listItemToConTeXt lst
163 return $ ("\\startitemize" <> if isTightList lst
173 return $ ("\\startitemize" <> if isTightList lst
@@ -335,7 +345,12 @@ inlineToConTeXt (Note contents) = do
335 then text "\\footnote{" <> nest 2 contents' <> char '}'
345 then text "\\footnote{" <> nest 2 contents' <> char '}'
336 else text "\\startbuffer " <> nest 2 contents' <>
346 else text "\\startbuffer " <> nest 2 contents' <>
337 text "\\stopbuffer\\footnote{\\getbuffer}"
347 text "\\stopbuffer\\footnote{\\getbuffer}"
338−inlineToConTeXt (Span _ ils) = inlineListToConTeXt ils
348+inlineToConTeXt (Span (_,_,kvs) ils) = do
349+ contents <- inlineListToConTeXt ils
350+ return $ case lookup "dir" kvs of
351+ Just "rtl" -> braces $ "\\righttoleft " <> contents
352+ Just "ltr" -> braces $ "\\lefttoright " <> contents
353+ _ -> contents
339
354
340-- | Craft the section header, inserting the secton reference, if supplied.
355-- | Craft the section header, inserting the secton reference, if supplied.
341sectionHeader :: Attr
356sectionHeader :: Attr
src/Text/Pandoc/Writers/LaTeX.hs+16−4
@@ -188,6 +188,9 @@ pandocToLaTeX options (Pandoc meta blocks) = do
188 $ defField "polyglossia-otherlangs"
188 $ defField "polyglossia-otherlangs"
189 (maybe [] (map $ fst . toPolyglossia . splitBy (=='-')) $
189 (maybe [] (map $ fst . toPolyglossia . splitBy (=='-')) $
190 getField "otherlangs" context)
190 getField "otherlangs" context)
191+ $ defField "latex-dir-rtl" (case (getField "dir" context)::Maybe String of
192+ Just "rtl" -> True
193+ _ -> False)
191 $ context
194 $ context
192 return $ if writerStandalone options
195 return $ if writerStandalone options
193 then renderTemplate' template context'
196 then renderTemplate' template context'
@@ -324,14 +327,19 @@ isLineBreakOrSpace _ = False
324blockToLaTeX :: Block -- ^ Block to convert
327blockToLaTeX :: Block -- ^ Block to convert
325 -> State WriterState Doc
328 -> State WriterState Doc
326blockToLaTeX Null = return empty
329blockToLaTeX Null = return empty
327−blockToLaTeX (Div (identifier,classes,_) bs) = do
330+blockToLaTeX (Div (identifier,classes,kvs) bs) = do
328 beamer <- writerBeamer `fmap` gets stOptions
331 beamer <- writerBeamer `fmap` gets stOptions
329 ref <- toLabel identifier
332 ref <- toLabel identifier
330 let linkAnchor = if null identifier
333 let linkAnchor = if null identifier
331 then empty
334 then empty
332 else "\\hyperdef{}" <> braces (text ref) <>
335 else "\\hyperdef{}" <> braces (text ref) <>
333 braces ("\\label" <> braces (text ref))
336 braces ("\\label" <> braces (text ref))
334− contents <- blockListToLaTeX bs
337+ contents' <- blockListToLaTeX bs
338+ let align dir = inCmd "begin" dir $$ contents' $$ inCmd "end" dir
339+ let contents = case lookup "dir" kvs of
340+ Just "rtl" -> align "RTL"
341+ Just "ltr" -> align "LTR"
342+ _ -> contents'
335 if beamer && "notes" `elem` classes -- speaker notes
343 if beamer && "notes" `elem` classes -- speaker notes
336 then return $ "\\note" <> braces contents
344 then return $ "\\note" <> braces contents
337 else return (linkAnchor $$ contents)
345 else return (linkAnchor $$ contents)
@@ -728,10 +736,12 @@ isQuoted _ = False
728-- | Convert inline element to LaTeX
736-- | Convert inline element to LaTeX
729inlineToLaTeX :: Inline -- ^ Inline to convert
737inlineToLaTeX :: Inline -- ^ Inline to convert
730 -> State WriterState Doc
738 -> State WriterState Doc
731−inlineToLaTeX (Span (id',classes,_) ils) = do
739+inlineToLaTeX (Span (id',classes,kvs) ils) = do
732 let noEmph = "csl-no-emph" `elem` classes
740 let noEmph = "csl-no-emph" `elem` classes
733 let noStrong = "csl-no-strong" `elem` classes
741 let noStrong = "csl-no-strong" `elem` classes
734 let noSmallCaps = "csl-no-smallcaps" `elem` classes
742 let noSmallCaps = "csl-no-smallcaps" `elem` classes
743+ let rtl = ("dir","rtl") `elem` kvs
744+ let ltr = ("dir","ltr") `elem` kvs
735 ref <- toLabel id'
745 ref <- toLabel id'
736 let linkAnchor = if null id'
746 let linkAnchor = if null id'
737 then empty
747 then empty
@@ -741,7 +751,9 @@ inlineToLaTeX (Span (id',classes,_) ils) = do
741 ((if noEmph then inCmd "textup" else id) .
751 ((if noEmph then inCmd "textup" else id) .
742 (if noStrong then inCmd "textnormal" else id) .
752 (if noStrong then inCmd "textnormal" else id) .
743 (if noSmallCaps then inCmd "textnormal" else id) .
753 (if noSmallCaps then inCmd "textnormal" else id) .
754+ (if rtl then inCmd "RL" else id) .
755+ (if ltr then inCmd "LR" else id) .
744− (if not (noEmph || noStrong || noSmallCaps)
756+ (if not (noEmph || noStrong || noSmallCaps || rtl || ltr)
745 then braces
757 then braces
746 else id)) `fmap` inlineListToLaTeX ils
758 else id)) `fmap` inlineListToLaTeX ils
747inlineToLaTeX (Emph lst) =
759inlineToLaTeX (Emph lst) =