• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rafalp / Misago / 9302269434

30 May 2024 12:10PM UTC coverage: 97.65% (-1.1%) from 98.716%
9302269434

Pull #1742

github

web-flow
Merge 1460b9c42 into abad4f068
Pull Request #1742: Replace forum options with account settings

752 of 805 new or added lines in 35 files covered. (93.42%)

651 existing lines in 146 files now uncovered.

52224 of 53481 relevant lines covered (97.65%)

0.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.55
/misago/markup/bbcode/code.py
1
import re
1✔
2

3
import markdown
1✔
4
from markdown.extensions.attr_list import AttrListExtension
1✔
5
from markdown.extensions.fenced_code import FencedBlockPreprocessor
1✔
6
from markdown.extensions.codehilite import CodeHilite, CodeHiliteExtension
1✔
7
from markdown.serializers import _escape_attrib_html
1✔
8

9

10
class CodeBlockExtension(markdown.Extension):
1✔
11
    def extendMarkdown(self, md):
1✔
12
        md.registerExtension(self)
1✔
13

14
        md.preprocessors.register(
1✔
15
            CodeBlockPreprocessor(md, self.getConfigs()), "misago_code_bbcode", 24
16
        )
17

18

19
class CodeBlockPreprocessor(FencedBlockPreprocessor):
1✔
20
    FENCED_BLOCK_RE = re.compile(
1✔
21
        r"""
22
\[code(=("?)(?P<lang>.*?)("?))?](([ ]*\n)+)?(?P<code>.*?)((\s|\n)+)?\[/code\]
23
""",
24
        re.IGNORECASE | re.MULTILINE | re.DOTALL | re.VERBOSE,
25
    )
26

27
    def run(self, lines):
1✔
28
        """Match and store Fenced Code Blocks in the HtmlStash."""
29

30
        # Check for dependent extensions
31
        if not self.checked_for_deps:
1✔
32
            for ext in self.md.registeredExtensions:
1✔
33
                if isinstance(ext, CodeHiliteExtension):
1✔
UNCOV
34
                    self.codehilite_conf = ext.getConfigs()
×
35
                if isinstance(ext, AttrListExtension):
1✔
UNCOV
36
                    self.use_attr_list = True
×
37

38
            self.checked_for_deps = True
1✔
39

40
        text = "\n".join(lines)
1✔
41
        while 1:
1✔
42
            m = self.FENCED_BLOCK_RE.search(text)
1✔
43
            if m:
1✔
44
                lang, id, classes, config = None, "", [], {}
1✔
45
                if m.group("lang"):
1✔
46
                    lang = m.group("lang")
1✔
47

48
                # If config is not empty, then the codehighlite extension
49
                # is enabled, so we call it to highlight the code
50
                if (
1✔
51
                    self.codehilite_conf
52
                    and self.codehilite_conf["use_pygments"]
53
                    and config.get("use_pygments", True)
54
                ):
UNCOV
55
                    local_config = self.codehilite_conf.copy()
×
UNCOV
56
                    local_config.update(config)
×
57
                    # Combine classes with cssclass. Ensure cssclass is at end
58
                    # as pygments appends a suffix under certain circumstances.
59
                    # Ignore ID as Pygments does not offer an option to set it.
UNCOV
60
                    if classes:
×
UNCOV
61
                        local_config["css_class"] = "{} {}".format(
×
62
                            " ".join(classes), local_config["css_class"]
63
                        )
UNCOV
64
                    highliter = CodeHilite(
×
65
                        m.group("code"),
66
                        lang=lang,
67
                        style=local_config.pop("pygments_style", "default"),
68
                        **local_config,
69
                    )
70

UNCOV
71
                    code = highliter.hilite(shebang=False)
×
72
                else:
73
                    id_attr = lang_attr = class_attr = kv_pairs = ""
1✔
74
                    if lang:
1✔
75
                        lang_attr = f' class="language-{_escape_attrib_html(lang)}"'
1✔
76
                    if classes:
1✔
UNCOV
77
                        class_attr = (
×
78
                            f' class="{_escape_attrib_html(" ".join(classes))}"'
79
                        )
80
                    if id:
1✔
UNCOV
81
                        id_attr = f' id="{_escape_attrib_html(id)}"'
×
82
                    if (
1✔
83
                        self.use_attr_list
84
                        and config
85
                        and not config.get("use_pygments", False)
86
                    ):
87
                        # Only assign key/value pairs to code element if attr_list ext is enabled, key/value pairs
88
                        # were defined on the code block, and the `use_pygments` key was not set to True. The
89
                        # `use_pygments` key could be either set to False or not defined. It is omitted from output.
UNCOV
90
                        kv_pairs = "".join(
×
91
                            f' {k}="{_escape_attrib_html(v)}"'
92
                            for k, v in config.items()
93
                            if k != "use_pygments"
94
                        )
95
                    code = self._escape(m.group("code"))
1✔
96
                    code = f"<pre{id_attr}{class_attr}><code{lang_attr}{kv_pairs}>{code}</code></pre>"
1✔
97

98
                placeholder = self.md.htmlStash.store(code)
1✔
99
                text = f"{text[:m.start()]}\n{placeholder}\n{text[m.end():]}"
1✔
100
            else:
101
                break
1✔
102
        return text.split("\n")
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc