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

rafalp / Misago / 14252691788

03 Apr 2025 09:01PM UTC coverage: 97.097% (-0.08%) from 97.173%
14252691788

push

github

web-flow
Replace default parser with `markdown-it-py` (#1901)

1902 of 1969 new or added lines in 66 files covered. (96.6%)

20 existing lines in 7 files now uncovered.

68959 of 71021 relevant lines covered (97.1%)

0.97 hits per line

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

97.01
/misago/parser/plugins/codebbcode.py
1
from textwrap import dedent
1✔
2
from typing import Sequence
1✔
3

4
from markdown_it import MarkdownIt
1✔
5
from markdown_it.common.utils import escapeHtml
1✔
6
from markdown_it.renderer import RendererHTML
1✔
7
from markdown_it.rules_block.state_block import StateBlock
1✔
8
from markdown_it.token import Token
1✔
9
from markdown_it.utils import EnvType, OptionsDict
1✔
10

11
from ..bbcode import (
1✔
12
    BBCodeBlockEnd,
13
    BBCodeBlockRule,
14
    BBCodeBlockStart,
15
    bbcode_block_end_rule,
16
    bbcode_block_start_rule,
17
)
18
from ..codeargs import parse_code_args
1✔
19

20

21
def code_bbcode_plugin(md: MarkdownIt):
1✔
22
    md.block.ruler.before(
1✔
23
        "paragraph",
24
        "code_bbcode",
25
        CodeBBCodeBlockRule(
26
            name="code_bbcode",
27
            element="code",
28
            start=code_bbcode_start,
29
            end=code_bbcode_end,
30
        ),
31
        {"alt": ["paragraph"]},
32
    )
33

34
    md.add_render_rule("code_bbcode", code_bbcode_renderer)
1✔
35

36

37
class CodeBBCodeBlockRule(BBCodeBlockRule):
1✔
38
    def parse_single_line(
1✔
39
        self,
40
        state: StateBlock,
41
        startLine: int,
42
        start: BBCodeBlockStart,
43
        end: BBCodeBlockEnd,
44
    ):
45
        content_start = start[3]
1✔
46
        content_end = end[1]
1✔
47
        content = state.src[content_start:content_end].strip()
1✔
48

49
        token = self.state_push_void_token(state, startLine, start)
1✔
50
        token.content = content
1✔
51

52
        state.line += 1
1✔
53

54
        return True
1✔
55

56
    def parse_multiple_lines(
1✔
57
        self,
58
        state: StateBlock,
59
        startLine: int,
60
        endLine: int,
61
        silent: bool,
62
        start: BBCodeBlockStart,
63
    ) -> bool:
64
        line = startLine
1✔
65
        pos = state.bMarks[line] + state.tShift[line] + start[3]
1✔
66
        maximum = state.eMarks[line]
1✔
67

68
        if state.src[pos:maximum].strip():
1✔
NEW
69
            return False
×
70

71
        end = None
1✔
72

73
        while line < endLine:
1✔
74
            line += 1
1✔
75

76
            if (
1✔
77
                state.isEmpty(line)
78
                or state.is_code_block(line)
79
                or all(self.scan_full_line(state, line))
80
                or line > state.lineMax
81
            ):
82
                continue
1✔
83

84
            if match := self.scan_line_for_end(state, line):
1✔
85
                end = match
1✔
86

87
        if silent or not end:
1✔
NEW
88
            return bool(end)
×
89

90
        token = self.state_push_void_token(state, startLine, start)
1✔
91
        token.content = self.get_lines(state, startLine + 1, line - 1)
1✔
92

93
        state.line = line + 1
1✔
94
        return True
1✔
95

96
    def get_lines(self, state: StateBlock, startLine: int, endLine: int):
1✔
97
        length = state.sCount[startLine]
1✔
98
        content = state.getLines(startLine, endLine, length, False).rstrip()
1✔
99

100
        lines: list[str] = []
1✔
101
        for line in content.splitlines():
1✔
102
            if line.strip() or lines:
1✔
103
                lines.append(line)
1✔
104

105
        return dedent("\n".join(lines))
1✔
106

107
    def get_meta(self, attrs: dict) -> dict | None:
1✔
108
        if attrs.get("syntax"):
1✔
109
            return {"syntax": attrs["syntax"]}
1✔
110

111
        return None
1✔
112

113

114
def code_bbcode_start(
1✔
115
    state: StateBlock, line: int
116
) -> tuple[str, dict | None, int, int] | None:
117
    start = bbcode_block_start_rule("code", state, line, args=True)
1✔
118
    if not start:
1✔
119
        return None
1✔
120

121
    markup, args_str, start, end = start
1✔
122

123
    if args_str:
1✔
124
        args = parse_code_args(args_str)
1✔
125
    else:
126
        args = None
1✔
127

128
    return markup, args, start, end
1✔
129

130

131
def code_bbcode_end(state: StateBlock, line: int) -> tuple[str, int, int] | None:
1✔
132
    return bbcode_block_end_rule("code", state, line)
1✔
133

134

135
def code_bbcode_renderer(
1✔
136
    renderer: RendererHTML,
137
    tokens: Sequence[Token],
138
    idx: int,
139
    options: OptionsDict,
140
    env: EnvType,
141
) -> str:
142
    token = tokens[idx]
1✔
143

144
    return (
1✔
145
        "<misago-code"
146
        + renderer.renderAttrs(token)
147
        + ">"
148
        + escapeHtml(token.content)
149
        + "</misago-code>\n"
150
    )
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