Passed
Push — develop ( 7f9d57...99dd20 )
by Christophe
02:22
created

pandoc_beamer_multigraphics._main.main()   A

Complexity

Conditions 1

Size

Total Lines 15
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 1
dl 0
loc 15
rs 10
c 0
b 0
f 0
1
#!/usr/bin/env python
2
3
"""
4
Pandoc filter for using beamer multi-graphics ability.
5
"""
6
7
from panflute import (
8
    Doc,
9
    Element,
10
    Image,
11
    MetaInlines,
12
    MetaList,
13
    RawInline,
14
    run_filter,
15
)
16
17
18
def image(elem: Element, doc: Doc) -> RawInline | None:
19
    """
20
    Transform image element.
21
22
    Arguments
23
    ---------
24
    elem
25
        current element
26
    doc
27
        pandoc document
28
29
    Returns
30
    -------
31
    RawInline | None
32
        RawInline or None
33
    """
34
    if doc.format == "beamer" and isinstance(elem, Image):
35
        classes = frozenset(elem.classes)
36
37
        # Loop on all multi-graphics definition
38
        for definition in doc.defined:
39
            # Are the classes correct?
40
            if classes >= definition["classes"]:
41
                graphics: list[str] = []
42
43
                if (
44
                    "height" in elem.attributes
45
                    or "width" in elem.attributes
46
                    or "height" in definition
47
                    or "width" in definition
48
                ):
49
                    graphics.extend(
50
                        (
51
                            "height=%s"
52
                            % str(
53
                                elem.attributes.get(
54
                                    "height", definition.get("height", "\\textheight")
55
                                )
56
                            ),
57
                            "width=%s"
58
                            % str(
59
                                elem.attributes.get(
60
                                    "width", definition.get("width", "\\textwidth")
61
                                )
62
                            ),
63
                        ),
64
                    )
65
66
                options = []
67
68
                if "start" in elem.attributes:
69
                    options.append(f"start={int(elem.attributes['start']):d}")
70
71
                if "end" in elem.attributes:
72
                    options.append(f"end={int(elem.attributes['end']):d}")
73
74
                options.append(
75
                    f"format={elem.attributes.get('format', definition['format'])}"
76
                )
77
78
                return RawInline(
79
                    (
80
                        f"\\multiinclude"
81
                        f"[graphics={{{','.join(graphics)}}},{','.join(options)}]"
82
                        f"{{{elem.url}}}"
83
                    ),
84
                    "tex",
85
                )
86
87
    return None
88
89
90
def prepare(doc: Doc) -> None:
91
    """
92
    Prepare the document.
93
94
    Arguments
95
    ---------
96
    doc
97
        The pandoc document
98
    """
99
    # Prepare the definitions
100
    doc.defined = []
101
102
    # Get the meta data
103
    meta = doc.get_metadata("pandoc-beamer-multigraphics")
104
105
    if isinstance(meta, list):
106
        # Loop on all definitions
107
        for definition in meta:
108
            # Verify the definition
109
            if (
110
                isinstance(definition, dict)
111
                and "classes" in definition
112
                and isinstance(definition["classes"], list)
113
            ):
114
                definition["classes"] = frozenset(definition["classes"])
115
                definition["format"] = str(definition.get("format", "pdf"))
116
                if "width" in definition:
117
                    definition["width"] = str(definition["width"])
118
                if "height" in definition:
119
                    definition["height"] = str(definition["height"])
120
121
                doc.defined.append(definition)
122
123
124
def finalize(doc: Doc) -> None:
125
    """
126
    Finalize the document.
127
128
    Arguments
129
    ---------
130
    doc
131
        The pandoc document
132
    """
133
    # Add header-includes if necessary
134
    if "header-includes" not in doc.metadata:
135
        doc.metadata["header-includes"] = MetaList()
136
    # Convert header-includes to MetaList if necessary
137
    elif not isinstance(doc.metadata["header-includes"], MetaList):
138
        doc.metadata["header-includes"] = MetaList(doc.metadata["header-includes"])
139
140
    doc.metadata["header-includes"].append(
141
        MetaInlines(RawInline("\\usepackage{xmpmulti}", "tex"))
142
    )
143
144
145
def main(doc: Doc | None = None) -> Doc:
146
    """
147
    Transform the document.
148
149
    Arguments
150
    ---------
151
    doc
152
        pandoc document
153
154
    Returns
155
    -------
156
    Doc
157
        The transformed document.
158
    """
159
    return run_filter(image, doc=doc, prepare=prepare, finalize=finalize)
160
161
162
if __name__ == "__main__":
163
    main()
164