pandoc_beamer_multigraphics._main   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 23
eloc 63
dl 0
loc 152
rs 10
c 0
b 0
f 0

4 Functions

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