pandoc_latex_fontsize._main   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 222
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 23
eloc 79
dl 0
loc 222
rs 10
c 0
b 0
f 0

7 Functions

Rating   Name   Duplication   Size   Complexity  
A add_latex() 0 34 5
A latex_code() 0 15 1
A main() 0 15 1
A add_definition() 0 23 2
A get_correct_size() 0 33 2
B fontsize() 0 38 6
B prepare() 0 25 6
1
#!/usr/bin/env python
2
3
"""
4
Pandoc filter for changing font size in LaTeX.
5
"""
6
7
from typing import Any
8
9
from panflute import (
10
    Code,
11
    CodeBlock,
12
    Div,
13
    Doc,
14
    Element,
15
    RawBlock,
16
    RawInline,
17
    Span,
18
    debug,
19
    run_filter,
20
)
21
22
23
def latex_code(size: str) -> str:
24
    """
25
    Get LaTeX code for size.
26
27
    Arguments
28
    ---------
29
    size
30
        The size name.
31
32
    Returns
33
    -------
34
    str
35
        LaTeX code for size.
36
    """
37
    return "\\" + size + " "
38
39
40
def get_correct_size(size: str) -> str:
41
    """
42
    Get correct size.
43
44
    Arguments
45
    ---------
46
    size
47
        The size name.
48
49
    Returns
50
    -------
51
    str
52
        The correct size.
53
    """
54
    if size in (
55
        "Huge",
56
        "huge",
57
        "LARGE",
58
        "Large",
59
        "large",
60
        "normalsize",
61
        "small",
62
        "footnotesize",
63
        "scriptsize",
64
        "tiny",
65
    ):
66
        return size
67
    debug(
68
        "[WARNING] pandoc-latex-fontsize: "
69
        + size
70
        + " is not a correct LaTeX size; using normalsize"
71
    )
72
    return "normalsize"
73
74
75
def add_latex(elem: Element, latex: str) -> list[Element] | None:
76
    """
77
    Add LaTeX code to elem.
78
79
    Arguments
80
    ---------
81
    elem
82
        A pandoc element
83
    latex
84
        A LaTeX code
85
86
    Returns
87
    -------
88
    list[Element] | None
89
        A list of pandoc elements or None
90
    """
91
    # Is it a Span?
92
    if isinstance(elem, Span):
93
        elem.content.insert(0, RawInline(latex, "tex"))
94
95
    # Is it a Div?
96
    elif isinstance(elem, Div):
97
        elem.content.insert(0, RawBlock("{" + latex, "tex"))
98
        elem.content.append(RawBlock("}", "tex"))
99
100
    # Is it a Code?
101
    elif isinstance(elem, Code):  # noqa: R505
102
        return [RawInline("{" + latex, "tex"), elem, RawInline("}", "tex")]
103
104
    # Is it a CodeBlock?
105
    elif isinstance(elem, CodeBlock):
106
        return [RawBlock("{" + latex, "tex"), elem, RawBlock("}", "tex")]
107
108
    return None
109
110
111
def fontsize(elem: Element, doc: Doc) -> list[Element] | None:
112
    """
113
    Generate fontsize for elem.
114
115
    Arguments
116
    ---------
117
    elem
118
        A pandoc element
119
    doc
120
        The pandoc document
121
122
    Returns
123
    -------
124
    list[Element] | None
125
        A list of pandoc elements or None
126
    """
127
    # Is it in the right format and is it a Span, Div, Code or CodeBlock?
128
    if doc.format in ("latex", "beamer") and elem.tag in (
129
        "Span",
130
        "Div",
131
        "Code",
132
        "CodeBlock",
133
    ):
134
        # Is there a latex-fontsize attribute?
135
        if "latex-fontsize" in elem.attributes:
136
            return add_latex(
137
                elem, latex_code(get_correct_size(elem.attributes["latex-fontsize"]))
138
            )
139
        # Get the classes
140
        classes = set(elem.classes)
141
142
        # Loop on all fontsize definition
143
        for definition in doc.defined:
144
            # Are the classes correct?
145
            if classes >= definition["classes"]:
146
                return add_latex(elem, definition["latex"])
147
148
    return None
149
150
151
def prepare(doc: Doc) -> None:
152
    """
153
    Prepare the doc.
154
155
    Arguments
156
    ---------
157
    doc
158
        The pandoc document
159
    """
160
    # Prepare the definitions
161
    doc.defined = []
162
163
    # Get the meta data
164
    meta = doc.get_metadata("pandoc-latex-fontsize")
165
166
    if isinstance(meta, list):
167
        # Loop on all definitions
168
        for definition in meta:
169
            # Verify the definition
170
            if (
171
                isinstance(definition, dict)
172
                and "classes" in definition
173
                and isinstance(definition["classes"], list)
174
            ):
175
                add_definition(doc.defined, definition)
176
177
178
def add_definition(defined: list[dict[str, Any]], definition: dict[str, Any]) -> None:
179
    """
180
    Add definition to doc.
181
182
    Arguments
183
    ---------
184
    defined
185
        A list of definition
186
    definition
187
        A new definition
188
    """
189
    # Get the classes
190
    classes = definition["classes"]
191
192
    # Get the size
193
    if "size" in definition:
194
        size = get_correct_size(definition["size"])
195
    else:
196
        debug("[WARNING] pandoc-latex-fontsize: size is not defined; using normalsize")
197
        size = "normalsize"
198
199
    # Add a definition
200
    defined.append({"classes": set(classes), "latex": latex_code(size)})
201
202
203
def main(doc: Doc | None = None) -> Doc:
204
    """
205
    Convert the pandoc document.
206
207
    Arguments
208
    ---------
209
    doc
210
        The pandoc document.
211
212
    Returns
213
    -------
214
    Doc
215
        The modified document.
216
    """
217
    return run_filter(fontsize, prepare=prepare, doc=doc)
218
219
220
if __name__ == "__main__":
221
    main()
222