quizcomp.parser.math

 1import html
 2import typing
 3
 4import markdown_it
 5import markdown_it.token
 6
 7import quizcomp.external.katex
 8import quizcomp.model.constants
 9import quizcomp.parser.common
10
11_katex_available: typing.Union[bool, None] = None  # pylint: disable=invalid-name
12
13def render(
14        format: quizcomp.model.constants.Format,
15        inline: bool,
16        tokens: typing.List[markdown_it.token.Token],
17        token_index: int,
18        options: markdown_it.utils.OptionsDict,
19        env: typing.Dict[str, typing.Any],
20        ) -> str:
21    """ Render the given token in the specified format. """
22
23    context = typing.cast(quizcomp.parser.common.RenderContext, env[quizcomp.parser.common.ENV_KEY_CONTEXT])
24
25    text = tokens[token_index].content
26
27    if (format == quizcomp.model.constants.Format.HTML):
28        return _render_html(text, inline, context)
29    elif (format == quizcomp.model.constants.Format.MD):
30        return _render_md(text, inline, context)
31    elif (format == quizcomp.model.constants.Format.TEX):
32        return _render_tex(text, inline, context)
33    elif (format == quizcomp.model.constants.Format.TEXT):
34        return _render_md(text, inline, context)
35    else:
36        raise ValueError(f"Unknown format '{format.value}'.")
37
38def _render_tex(text: str, inline: bool, context: quizcomp.parser.common.RenderContext) -> str:
39    """ Render the given token content as TeX. """
40
41    text = text.replace('$', r'\$')
42
43    if (inline):
44        text = text.strip()
45        return f"$ {text} $"
46
47    return f"$$\n{text}\n$$"
48
49def _render_html(text: str, inline: bool, context: quizcomp.parser.common.RenderContext) -> str:
50    """ Render the given token content as HTML. """
51
52    global _katex_available  # pylint: disable=global-statement
53
54    if (_katex_available is None):
55        _katex_available = quizcomp.external.katex.is_available()
56
57    if (inline):
58        text = text.strip()
59
60    if (_katex_available):
61        content = quizcomp.external.katex.to_html(text)
62    else:
63        text = html.escape(text)
64        content = f"<code>{text}</code>"
65
66    element = 'span'
67    attributes = 'class="qg-math"'
68    if (not inline):
69        element = 'p'
70
71    return f"<{element} {attributes}>{content}</{element}>"
72
73def _render_md(text: str, inline: bool, context: quizcomp.parser.common.RenderContext) -> str:
74    """ Render the given token content as Markdown. """
75
76    if (inline):
77        text = text.strip()
78        return f"$ {text} $"
79
80    return f"$$\n{text}\n$$"
def render( format: quizcomp.model.constants.Format, inline: bool, tokens: List[markdown_it.token.Token], token_index: int, options: markdown_it.utils.OptionsDict, env: Dict[str, Any]) -> str:
14def render(
15        format: quizcomp.model.constants.Format,
16        inline: bool,
17        tokens: typing.List[markdown_it.token.Token],
18        token_index: int,
19        options: markdown_it.utils.OptionsDict,
20        env: typing.Dict[str, typing.Any],
21        ) -> str:
22    """ Render the given token in the specified format. """
23
24    context = typing.cast(quizcomp.parser.common.RenderContext, env[quizcomp.parser.common.ENV_KEY_CONTEXT])
25
26    text = tokens[token_index].content
27
28    if (format == quizcomp.model.constants.Format.HTML):
29        return _render_html(text, inline, context)
30    elif (format == quizcomp.model.constants.Format.MD):
31        return _render_md(text, inline, context)
32    elif (format == quizcomp.model.constants.Format.TEX):
33        return _render_tex(text, inline, context)
34    elif (format == quizcomp.model.constants.Format.TEXT):
35        return _render_md(text, inline, context)
36    else:
37        raise ValueError(f"Unknown format '{format.value}'.")

Render the given token in the specified format.