Passed
Push — develop ( 2ecf19...d105e9 )
by Christophe
01:05
created

pandoc_glfm._main.alert()   F

Complexity

Conditions 17

Size

Total Lines 115
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 59
dl 0
loc 115
rs 1.8
c 0
b 0
f 0
cc 17
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like pandoc_glfm._main.alert() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/env python
2
3
"""
4
Pandoc filter for adding glfm features to pandoc.
5
"""
6
7
from panflute import (
8
    Div,
9
    Doc,
10
    Element,
11
    Para,
12
    Plain,
13
    Str,
14
    Strikeout,
15
    convert_text,
16
    run_filters,
17
)
18
19
20
# pylint: disable=inconsistent-return-statements,unused-argument
21
def alert(elem: Element, doc: Doc) -> Element | None:
22
    """
23
    Transform some blockquote elements to alerts.
24
25
    Arguments
26
    ---------
27
    elem
28
        The current element
29
    doc
30
        The pandoc document
31
32
    Returns
33
    -------
34
    Element | None
35
        The modified element or None
36
    """
37
    if (
38
        elem.tag == "BlockQuote"
39
        and elem.content
40
        and elem.content[0].tag == "Para"
41
        and elem.content[0].content
42
        and elem.content[0].content[0].tag == "Str"
43
    ):
44
45
        def extract_first_lines(
46
            first: list[Element],
47
            rest: list[Element],
48
        ) -> list[Element]:
49
            result = []
50
            for item in first:
51
                if item.tag == "Str":
52
                    result.append(item.text)
53
                elif item.tag == "SoftBreak":
54
                    result.append("\n")
55
                elif item.tag == "Space":
56
                    result.append(" ")
57
                else:
58
                    result.append(
59
                        convert_text(
60
                            Plain(item),
61
                            input_format="panflute",
62
                            output_format="markdown",
63
                        ),
64
                    )
65
            for item in rest:
66
                result.extend(
67
                    [
68
                        "\n",
69
                        convert_text(
70
                            item,
71
                            input_format="panflute",
72
                            output_format="markdown",
73
                        ),
74
                    ]
75
                )
76
77
            return convert_text("".join(result))
78
79
        text = elem.content[0].content[0].text.lower()
80
        if text in ("[!note]", "[!tip]", "[!important]", "[!caution]", "[!warning]"):
81
            # Case
82
            #
83
            # > [!tip]
84
            #
85
            # and
86
            #
87
            # > [!tip]
88
            # >
89
            # > Rest of text
90
            if len(elem.content[0].content) == 1:
91
                title = Div(Para(Str(text[2:-1].capitalize())), classes=["title"])
92
                content = [*elem.content[1:]]
93
            # Case
94
            #
95
            # > [!tip]
96
            # > Rest of text
97
            elif elem.content[0].content[1].tag == "SoftBreak":
98
                title = Div(Para(Str(text[2:-1].capitalize())), classes=["title"])
99
                content = extract_first_lines(
100
                    elem.content[0].content[2:],
101
                    elem.content[1:],
102
                )
103
            # Case
104
            #
105
            # > [!tip] title
106
            # > Rest of text
107
            #
108
            # and
109
            #
110
            # > [!tip] title
111
            # >
112
            # > Rest of text
113
            else:
114
                alternate = []
115
                for index in range(2, len(elem.content[0].content)):
116
                    if elem.content[0].content[index].tag == "SoftBreak":
117
                        title = Div(Para(*alternate), classes=["title"])
118
                        content = extract_first_lines(
119
                            elem.content[0].content[index:],
120
                            elem.content[1:],
121
                        )
122
                        break
123
                    alternate.append(elem.content[0].content[index])
124
                else:
125
                    title = Div(Para(*alternate), classes=["title"])
126
                    content = [*elem.content[1:]]
127
128
            return convert_text(
129
                convert_text(
130
                    Div(title, *content, classes=[text[2:-1]]),
131
                    input_format="panflute",
132
                    output_format="markdown",
133
                )
134
            )
135
    return None
136
137
138
def task(elem: Element, doc: Doc) -> None:
139
    """
140
    Deal with glfm task lists.
141
142
    Arguments
143
    ---------
144
    elem
145
        The current element
146
    doc
147
        The pandoc document
148
    """
149
    if elem.tag in ("BulletList", "OrderedList"):
150
        for item in elem.content:
151
            if (
152
                item.content[0].tag in ("Plain", "Para")
153
                and item.content[0].content
154
                and item.content[0].content[0].tag == "Str"
155
                and item.content[0].content[0].text == "[~]"
156
                and len(item.content[0].content) >= 3
157
            ):
158
                item.content[0].content[0].text = "☐"
159
                item.content[0].content[2] = Strikeout(
160
                    *remove_strikeout(item.content[0].content[2:]),
161
                )
162
                item.content[0].content[3:] = []
163
                for block in item.content[1:]:
164
                    if block.tag in ("Plain", "Para"):
165
                        block.content[0] = Strikeout(*remove_strikeout(block.content))
166
                        block.content[1:] = []
167
168
169
def remove_strikeout(elems: list[Element]) -> list[Element]:
170
    """
171
    Remove Strikeout from elements.
172
173
    Parameters
174
    ----------
175
    elems
176
        Elements from which Strikeout must be removed
177
178
    Returns
179
    -------
180
    list[Element]
181
        The elements without the Strikeout.
182
    """
183
    result = []
184
    for elem in elems:
185
        if elem.tag == "Strikeout":
186
            result.extend(elem.content)
187
        else:
188
            result.append(elem)
189
    return result
190
191
192
def main(doc: Doc | None = None) -> Doc:
193
    """
194
    Convert the pandoc document.
195
196
    Arguments
197
    ---------
198
    doc
199
        The pandoc document
200
201
    Returns
202
    -------
203
    Doc
204
        The modified pandoc document
205
    """
206
    return run_filters([alert, task], doc=doc)
207
208
209
if __name__ == "__main__":
210
    main()
211