aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/docutils/writers/xetex/__init__.py
blob: a7bad3fd593ccf995c560867a4713714a2301874 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python3
# :Author: Günter Milde <milde@users.sf.net>
# :Revision: $Revision: 9293 $
# :Date: $Date: 2022-12-01 22:13:54 +0100 (Do, 01. Dez 2022) $
# :Copyright: © 2010 Günter Milde.
# :License: Released under the terms of the `2-Clause BSD license`_, in short:
#
#    Copying and distribution of this file, with or without modification,
#    are permitted in any medium without royalty provided the copyright
#    notice and this notice are preserved.
#    This file is offered as-is, without any warranty.
#
# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause

"""
XeLaTeX document tree Writer.

A variant of Docutils' standard 'latex2e' writer producing LaTeX output
suited for processing with the Unicode-aware TeX engines
LuaTeX and XeTeX.
"""

__docformat__ = 'reStructuredText'

from docutils import frontend
from docutils.writers import latex2e


class Writer(latex2e.Writer):
    """A writer for Unicode-aware LaTeX variants (XeTeX, LuaTeX)"""

    supported = ('latex', 'tex', 'xetex', 'xelatex', 'luatex', 'lualatex')
    """Formats this writer supports."""

    default_template = 'xelatex.tex'
    default_preamble = """\
% Linux Libertine (free, wide coverage, not only for Linux)
\\setmainfont{Linux Libertine O}
\\setsansfont{Linux Biolinum O}
\\setmonofont[HyphenChar=None,Scale=MatchLowercase]{DejaVu Sans Mono}"""

    config_section = 'xetex writer'
    config_section_dependencies = ('writers', 'latex writers')

    # use a copy of the parent spec with some modifications:
    settings_spec = frontend.filter_settings_spec(
        latex2e.Writer.settings_spec,
        # removed settings
        'font_encoding',
        # changed settings:
        template=('Template file. Default: "%s".' % default_template,
                  ['--template'],
                  {'default': default_template, 'metavar': '<file>'}),
        latex_preamble=('Customization by LaTeX code in the preamble. '
                        'Default: select "Linux Libertine" fonts.',
                        ['--latex-preamble'],
                        {'default': default_preamble}),
        )

    def __init__(self):
        latex2e.Writer.__init__(self)
        self.settings_defaults.update({'fontencoding': ''})  # use default (TU)
        self.translator_class = XeLaTeXTranslator


class Babel(latex2e.Babel):
    """Language specifics for XeTeX.

    Use `polyglossia` instead of `babel` and adapt settings.
    """
    language_codes = latex2e.Babel.language_codes.copy()
    # Additionally supported or differently named languages:
    language_codes.update({
        # code        Polyglossia-name  comment
        'cop':        'coptic',
        'de':         'german',         # new spelling (de_1996)
        'de-1901':    'ogerman',        # old spelling
        'dv':         'divehi',         # Maldivian
        'dsb':        'lsorbian',
        'el-polyton': 'polygreek',
        'fa':         'farsi',
        'grc':        'ancientgreek',
        'ko':         'korean',
        'hsb':        'usorbian',
        'sh-Cyrl':    'serbian',        # Serbo-Croatian, Cyrillic script
        'sh-Latn':    'croatian',       # Serbo-Croatian, Latin script
        'sq':         'albanian',
        'sr':         'serbian',        # Cyrillic script (sr-Cyrl)
        'th':         'thai',
        'vi':         'vietnamese',
        # zh-Latn:    ???               # Chinese Pinyin
        })
    # normalize (downcase) keys
    language_codes = {k.lower(): v for k, v in language_codes.items()}

    # Languages without Polyglossia support:
    for key in ('af',           # 'afrikaans',
                'de-AT',        # 'naustrian',
                'de-AT-1901',   # 'austrian',
                # TODO: use variant=... for English variants
                'en-CA',        # 'canadian',
                'en-GB',        # 'british',
                'en-NZ',        # 'newzealand',
                'en-US',        # 'american',
                'fr-CA',        # 'canadien',
                'grc-ibycus',   # 'ibycus', (Greek Ibycus encoding)
                'sr-Latn',      # 'serbian script=latin'
                ):
        del language_codes[key.lower()]

    def __init__(self, language_code, reporter):
        self.language_code = language_code
        self.reporter = reporter
        self.language = self.language_name(language_code)
        self.otherlanguages = {}
        self.warn_msg = 'Language "%s" not supported by Polyglossia.'
        self.quote_index = 0
        self.quotes = ('"', '"')
        # language dependent configuration:
        # double quotes are "active" in some languages (e.g. German).
        self.literal_double_quote = '"'  # TODO: use \textquotedbl ?

    def __call__(self):
        setup = [r'\usepackage{polyglossia}',
                 r'\setdefaultlanguage{%s}' % self.language]
        if self.otherlanguages:
            setup.append(r'\setotherlanguages{%s}' %
                         ','.join(sorted(self.otherlanguages.keys())))
        return '\n'.join(setup)


class XeLaTeXTranslator(latex2e.LaTeXTranslator):
    """
    Generate code for LaTeX using Unicode fonts (XeLaTex or LuaLaTeX).

    See the docstring of docutils.writers._html_base.HTMLTranslator for
    notes on and examples of safe subclassing.
    """

    def __init__(self, document):
        self.is_xetex = True  # typeset with XeTeX or LuaTeX engine
        latex2e.LaTeXTranslator.__init__(self, document, Babel)
        if self.latex_encoding == 'utf8':
            self.requirements.pop('_inputenc', None)
        else:
            self.requirements['_inputenc'] = (r'\XeTeXinputencoding %s '
                                              % self.latex_encoding)