Merge pull request #2419 from mb21/bidi
Support bidirectional text output with XeLaTeX, ConTeXt and HTML
This commit is contained in:
commit
fdfc961284
3 changed files with 59 additions and 13 deletions
19
README
19
README
|
@ -959,6 +959,25 @@ as `title`, `author`, and `date`) as well as the following:
|
||||||
Currently only used by XeTeX through the generated
|
Currently only used by XeTeX through the generated
|
||||||
`polyglossia-otherlangs` variable.
|
`polyglossia-otherlangs` variable.
|
||||||
|
|
||||||
|
`dir`
|
||||||
|
: the base direction of the document, either `rtl` (right-to-left)
|
||||||
|
or `ltr` (left-to-right).
|
||||||
|
|
||||||
|
For bidirectional documents, native pandoc `span`s and `div`s
|
||||||
|
with the `dir` attribute (value `rtl` or `ltr`) can be used to
|
||||||
|
override the base direction in some output formats.
|
||||||
|
This may not always be necessary if the final renderer
|
||||||
|
(e.g. the browser, when generating HTML) supports the
|
||||||
|
[Unicode Bidirectional Algorithm][uba-basics].
|
||||||
|
|
||||||
|
When using LaTeX for bidi documents, only the XeLaTeX engine
|
||||||
|
is fully supported (see `--latex-engine`).
|
||||||
|
Setting the `dir` variable enables bidirectional text
|
||||||
|
handling in LaTeX and ConTeXt, thus even if the base direction
|
||||||
|
is the default left-to-right, you should set `dir: ltr` for
|
||||||
|
documents that also contain some right-to-left script.
|
||||||
|
|
||||||
|
|
||||||
`slidy-url`
|
`slidy-url`
|
||||||
: base URL for Slidy documents (defaults to
|
: base URL for Slidy documents (defaults to
|
||||||
`http://www.w3.org/Talks/Tools/Slidy2`)
|
`http://www.w3.org/Talks/Tools/Slidy2`)
|
||||||
|
|
|
@ -83,13 +83,18 @@ pandocToConTeXt options (Pandoc meta blocks) = do
|
||||||
$ metadata
|
$ metadata
|
||||||
let context' = defField "context-lang" (maybe "" (fromBcp47 . splitBy (=='-')) $
|
let context' = defField "context-lang" (maybe "" (fromBcp47 . splitBy (=='-')) $
|
||||||
getField "lang" context)
|
getField "lang" context)
|
||||||
context
|
$ defField "context-dir" (toContextDir $ getField "dir" context)
|
||||||
|
$ context
|
||||||
return $ if writerStandalone options
|
return $ if writerStandalone options
|
||||||
then renderTemplate' (writerTemplate options) context'
|
then renderTemplate' (writerTemplate options) context'
|
||||||
else main
|
else main
|
||||||
|
|
||||||
-- escape things as needed for ConTeXt
|
toContextDir :: Maybe String -> String
|
||||||
|
toContextDir (Just "rtl") = "r2l"
|
||||||
|
toContextDir (Just "ltr") = "l2r"
|
||||||
|
toContextDir _ = ""
|
||||||
|
|
||||||
|
-- | escape things as needed for ConTeXt
|
||||||
escapeCharForConTeXt :: WriterOptions -> Char -> String
|
escapeCharForConTeXt :: WriterOptions -> Char -> String
|
||||||
escapeCharForConTeXt opts ch =
|
escapeCharForConTeXt opts ch =
|
||||||
let ligatures = writerTeXLigatures opts in
|
let ligatures = writerTeXLigatures opts in
|
||||||
|
@ -151,13 +156,18 @@ blockToConTeXt (CodeBlock _ str) =
|
||||||
-- blankline because \stoptyping can't have anything after it, inc. '}'
|
-- blankline because \stoptyping can't have anything after it, inc. '}'
|
||||||
blockToConTeXt (RawBlock "context" str) = return $ text str <> blankline
|
blockToConTeXt (RawBlock "context" str) = return $ text str <> blankline
|
||||||
blockToConTeXt (RawBlock _ _ ) = return empty
|
blockToConTeXt (RawBlock _ _ ) = return empty
|
||||||
blockToConTeXt (Div (ident,_,_) bs) = do
|
blockToConTeXt (Div (ident,_,kvs) bs) = do
|
||||||
contents <- blockListToConTeXt bs
|
contents <- blockListToConTeXt bs
|
||||||
if null ident
|
let contents' = if null ident
|
||||||
then return contents
|
then contents
|
||||||
else return $
|
else ("\\reference" <> brackets (text $ toLabel ident) <>
|
||||||
("\\reference" <> brackets (text $ toLabel ident) <> braces empty <>
|
braces empty <> "%") $$ contents
|
||||||
"%") $$ contents
|
let align dir = blankline <> "\\startalignment[" <> dir <> "]"
|
||||||
|
$$ contents' $$ "\\stopalignment" <> blankline
|
||||||
|
return $ case lookup "dir" kvs of
|
||||||
|
Just "rtl" -> align "righttoleft"
|
||||||
|
Just "ltr" -> align "lefttoright"
|
||||||
|
_ -> contents'
|
||||||
blockToConTeXt (BulletList lst) = do
|
blockToConTeXt (BulletList lst) = do
|
||||||
contents <- mapM listItemToConTeXt lst
|
contents <- mapM listItemToConTeXt lst
|
||||||
return $ ("\\startitemize" <> if isTightList lst
|
return $ ("\\startitemize" <> if isTightList lst
|
||||||
|
@ -335,7 +345,12 @@ inlineToConTeXt (Note contents) = do
|
||||||
then text "\\footnote{" <> nest 2 contents' <> char '}'
|
then text "\\footnote{" <> nest 2 contents' <> char '}'
|
||||||
else text "\\startbuffer " <> nest 2 contents' <>
|
else text "\\startbuffer " <> nest 2 contents' <>
|
||||||
text "\\stopbuffer\\footnote{\\getbuffer}"
|
text "\\stopbuffer\\footnote{\\getbuffer}"
|
||||||
inlineToConTeXt (Span _ ils) = inlineListToConTeXt ils
|
inlineToConTeXt (Span (_,_,kvs) ils) = do
|
||||||
|
contents <- inlineListToConTeXt ils
|
||||||
|
return $ case lookup "dir" kvs of
|
||||||
|
Just "rtl" -> braces $ "\\righttoleft " <> contents
|
||||||
|
Just "ltr" -> braces $ "\\lefttoright " <> contents
|
||||||
|
_ -> contents
|
||||||
|
|
||||||
-- | Craft the section header, inserting the secton reference, if supplied.
|
-- | Craft the section header, inserting the secton reference, if supplied.
|
||||||
sectionHeader :: Attr
|
sectionHeader :: Attr
|
||||||
|
|
|
@ -187,6 +187,9 @@ pandocToLaTeX options (Pandoc meta blocks) = do
|
||||||
$ defField "polyglossia-otherlangs"
|
$ defField "polyglossia-otherlangs"
|
||||||
(maybe [] (map $ fst . toPolyglossia . splitBy (=='-')) $
|
(maybe [] (map $ fst . toPolyglossia . splitBy (=='-')) $
|
||||||
getField "otherlangs" context)
|
getField "otherlangs" context)
|
||||||
|
$ defField "latex-dir-rtl" (case (getField "dir" context)::Maybe String of
|
||||||
|
Just "rtl" -> True
|
||||||
|
_ -> False)
|
||||||
$ context
|
$ context
|
||||||
return $ if writerStandalone options
|
return $ if writerStandalone options
|
||||||
then renderTemplate' template context'
|
then renderTemplate' template context'
|
||||||
|
@ -323,14 +326,19 @@ isLineBreakOrSpace _ = False
|
||||||
blockToLaTeX :: Block -- ^ Block to convert
|
blockToLaTeX :: Block -- ^ Block to convert
|
||||||
-> State WriterState Doc
|
-> State WriterState Doc
|
||||||
blockToLaTeX Null = return empty
|
blockToLaTeX Null = return empty
|
||||||
blockToLaTeX (Div (identifier,classes,_) bs) = do
|
blockToLaTeX (Div (identifier,classes,kvs) bs) = do
|
||||||
beamer <- writerBeamer `fmap` gets stOptions
|
beamer <- writerBeamer `fmap` gets stOptions
|
||||||
ref <- toLabel identifier
|
ref <- toLabel identifier
|
||||||
let linkAnchor = if null identifier
|
let linkAnchor = if null identifier
|
||||||
then empty
|
then empty
|
||||||
else "\\hyperdef{}" <> braces (text ref) <>
|
else "\\hyperdef{}" <> braces (text ref) <>
|
||||||
braces ("\\label" <> braces (text ref))
|
braces ("\\label" <> braces (text ref))
|
||||||
contents <- blockListToLaTeX bs
|
contents' <- blockListToLaTeX bs
|
||||||
|
let align dir = inCmd "begin" dir $$ contents' $$ inCmd "end" dir
|
||||||
|
let contents = case lookup "dir" kvs of
|
||||||
|
Just "rtl" -> align "RTL"
|
||||||
|
Just "ltr" -> align "LTR"
|
||||||
|
_ -> contents'
|
||||||
if beamer && "notes" `elem` classes -- speaker notes
|
if beamer && "notes" `elem` classes -- speaker notes
|
||||||
then return $ "\\note" <> braces contents
|
then return $ "\\note" <> braces contents
|
||||||
else return (linkAnchor $$ contents)
|
else return (linkAnchor $$ contents)
|
||||||
|
@ -727,10 +735,12 @@ isQuoted _ = False
|
||||||
-- | Convert inline element to LaTeX
|
-- | Convert inline element to LaTeX
|
||||||
inlineToLaTeX :: Inline -- ^ Inline to convert
|
inlineToLaTeX :: Inline -- ^ Inline to convert
|
||||||
-> State WriterState Doc
|
-> State WriterState Doc
|
||||||
inlineToLaTeX (Span (id',classes,_) ils) = do
|
inlineToLaTeX (Span (id',classes,kvs) ils) = do
|
||||||
let noEmph = "csl-no-emph" `elem` classes
|
let noEmph = "csl-no-emph" `elem` classes
|
||||||
let noStrong = "csl-no-strong" `elem` classes
|
let noStrong = "csl-no-strong" `elem` classes
|
||||||
let noSmallCaps = "csl-no-smallcaps" `elem` classes
|
let noSmallCaps = "csl-no-smallcaps" `elem` classes
|
||||||
|
let rtl = ("dir","rtl") `elem` kvs
|
||||||
|
let ltr = ("dir","ltr") `elem` kvs
|
||||||
ref <- toLabel id'
|
ref <- toLabel id'
|
||||||
let linkAnchor = if null id'
|
let linkAnchor = if null id'
|
||||||
then empty
|
then empty
|
||||||
|
@ -740,7 +750,9 @@ inlineToLaTeX (Span (id',classes,_) ils) = do
|
||||||
((if noEmph then inCmd "textup" else id) .
|
((if noEmph then inCmd "textup" else id) .
|
||||||
(if noStrong then inCmd "textnormal" else id) .
|
(if noStrong then inCmd "textnormal" else id) .
|
||||||
(if noSmallCaps then inCmd "textnormal" else id) .
|
(if noSmallCaps then inCmd "textnormal" else id) .
|
||||||
(if not (noEmph || noStrong || noSmallCaps)
|
(if rtl then inCmd "RL" else id) .
|
||||||
|
(if ltr then inCmd "LR" else id) .
|
||||||
|
(if not (noEmph || noStrong || noSmallCaps || rtl || ltr)
|
||||||
then braces
|
then braces
|
||||||
else id)) `fmap` inlineListToLaTeX ils
|
else id)) `fmap` inlineListToLaTeX ils
|
||||||
inlineToLaTeX (Emph lst) =
|
inlineToLaTeX (Emph lst) =
|
||||||
|
|
Loading…
Add table
Reference in a new issue