Skip to content

Extension

Tip

Reference for the Python-Markdown extension can be found here.

rst_in_md.RestructuredTextInMarkdown

Bases: Extension

Extension to convert restructured text to html in markdown.

Source code in rst_in_md/extension.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class RestructuredTextInMarkdown(Extension):
    """Extension to convert restructured text to html in markdown."""

    @staticmethod
    def _pymdownx_installed() -> bool:
        try:
            import pymdownx.superfences  # noqa: F401
        except ImportError:
            return False
        return True

    def extendMarkdown(self, md: Markdown) -> None:  # noqa: N802
        """Register the RestructuredTextInMarkdownPreProcessor.

        Register the
        [RestructuredTextInMarkdownPreProcessor](extension.md#rst_in_md.RestructuredTextInMarkdownPreProcessor)
        with the markdown instance. This allows the preprocessor to be used when
        markdown is rendered to html.

        The priority of the preprocessor is set to `27`. This is higher than
        the [fenced_code_block](https://github.com/Python-Markdown/markdown/blob/33359faa385f59b84cd87df5f4b0996055a482e2/markdown/extensions/fenced_code.py#L50)
        preprocessor, so that `rst` blocks are processed beforehand. But it is
        lower than [normalize_whitespace](https://github.com/Python-Markdown/markdown/blob/33359faa385f59b84cd87df5f4b0996055a482e2/markdown/preprocessors.py#L40)
        so that the rst blocks can be processed in a similar manner to code blocks.

        Also register the
        [RestructuredTextInMarkdownAutoConfigurator](superfence.md#rst_in_md.RestructuredTextInMarkdownAutoConfigurator)
        if `pymdownx.superfences` is installed.

        Args:
            md (Markdown): The Markdown instance.
        """
        md.preprocessors.register(
            RestructuredTextInMarkdownPreProcessor(md),
            "rst-in-md",
            27,
        )

        if self._pymdownx_installed():
            md.preprocessors.register(
                RestructuredTextInMarkdownAutoConfigurator(md),
                "rst-in-md-auto-configurator",
                300,
            )

extendMarkdown(md)

Register the RestructuredTextInMarkdownPreProcessor.

Register the RestructuredTextInMarkdownPreProcessor with the markdown instance. This allows the preprocessor to be used when markdown is rendered to html.

The priority of the preprocessor is set to 27. This is higher than the fenced_code_block preprocessor, so that rst blocks are processed beforehand. But it is lower than normalize_whitespace so that the rst blocks can be processed in a similar manner to code blocks.

Also register the RestructuredTextInMarkdownAutoConfigurator if pymdownx.superfences is installed.

Parameters:

Name Type Description Default
md Markdown

The Markdown instance.

required
Source code in rst_in_md/extension.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
def extendMarkdown(self, md: Markdown) -> None:  # noqa: N802
    """Register the RestructuredTextInMarkdownPreProcessor.

    Register the
    [RestructuredTextInMarkdownPreProcessor](extension.md#rst_in_md.RestructuredTextInMarkdownPreProcessor)
    with the markdown instance. This allows the preprocessor to be used when
    markdown is rendered to html.

    The priority of the preprocessor is set to `27`. This is higher than
    the [fenced_code_block](https://github.com/Python-Markdown/markdown/blob/33359faa385f59b84cd87df5f4b0996055a482e2/markdown/extensions/fenced_code.py#L50)
    preprocessor, so that `rst` blocks are processed beforehand. But it is
    lower than [normalize_whitespace](https://github.com/Python-Markdown/markdown/blob/33359faa385f59b84cd87df5f4b0996055a482e2/markdown/preprocessors.py#L40)
    so that the rst blocks can be processed in a similar manner to code blocks.

    Also register the
    [RestructuredTextInMarkdownAutoConfigurator](superfence.md#rst_in_md.RestructuredTextInMarkdownAutoConfigurator)
    if `pymdownx.superfences` is installed.

    Args:
        md (Markdown): The Markdown instance.
    """
    md.preprocessors.register(
        RestructuredTextInMarkdownPreProcessor(md),
        "rst-in-md",
        27,
    )

    if self._pymdownx_installed():
        md.preprocessors.register(
            RestructuredTextInMarkdownAutoConfigurator(md),
            "rst-in-md-auto-configurator",
            300,
        )

rst_in_md.RestructuredTextInMarkdownPreProcessor

Bases: Preprocessor

Preprocessor to convert restructured text to html in markdown.

Source code in rst_in_md/processor.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class RestructuredTextInMarkdownPreProcessor(Preprocessor):
    """Preprocessor to convert restructured text to html in markdown."""

    _Processor = FencedBlockPreprocessor(Markdown(), {})
    FENCED_BLOCK_RE = _Processor.FENCED_BLOCK_RE
    handle_attrs = _Processor.handle_attrs

    def run(self, lines: list[str]) -> list[str]:
        """Strip restuctured text from markdown and replace it with converted html.

        This method will look for fenced code blocks in markdown that are marked as
        restructured text (`rst`, `rest`, `restructuredtext`) and convert them to html.
        It leverages the same regex as the [FencedBlockPreprocessor](https://github.com/Python-Markdown/markdown/blob/33359faa385f59b84cd87df5f4b0996055a482e2/markdown/extensions/fenced_code.py#L56-L67)
        to find the blocks.

        You can also ignore a block from being converted by `rst-in-md` adding
        `rst-in-md=false` to the attributes: ````{.rst rst-in-md=false}`. You can see an
        example of this [here](../guides/inline_ignore.md).

        Args:
            lines (list[str]): List of lines in markdown.

        Returns:
            list[str]: List of lines in markdown with rst replaced with html.
        """
        text = "\n".join(lines)
        processed = ""
        index = 0
        for match in self.FENCED_BLOCK_RE.finditer(text):
            lang = None
            attrs = []
            classes = []
            config = {}
            if match.group("lang") is not None:
                lang = match.group("lang")
            elif match.group("attrs") is not None:
                attrs, remainder = get_attrs_and_remainder(match.group("attrs"))
                if remainder:  # skip this match due to invalid syntax
                    warnings.warn("Invalid syntax parsing attributes", stacklevel=1)
                    processed += text[match.start() : match.end()]
                    index = match.end()
                    continue
                _, classes, config = self.handle_attrs(attrs)
                if len(classes) > 0:
                    lang = classes.pop(0)

            processed += text[index : match.start()]

            if lang not in LANGUAGES or config.get("rst-in-md") == "false":
                processed += text[match.start() : match.end()]
            else:
                try:
                    processed += rst_to_soup(match.group("code")).prettify(
                        formatter=BS4_FORMATTER,
                    )
                except ValueError as e:
                    warnings.warn(str(e), stacklevel=1)
                    processed += text[match.start() : match.end()]

            index = match.end()
        processed += text[index:]
        return processed.split("\n")

run(lines)

Strip restuctured text from markdown and replace it with converted html.

This method will look for fenced code blocks in markdown that are marked as restructured text (rst, rest, restructuredtext) and convert them to html. It leverages the same regex as the FencedBlockPreprocessor to find the blocks.

You can also ignore a block from being converted by rst-in-md adding rst-in-md=false to the attributes: ```{.rst rst-in-md=false}. You can see an example of this here.

Parameters:

Name Type Description Default
lines list[str]

List of lines in markdown.

required

Returns:

Type Description
list[str]

list[str]: List of lines in markdown with rst replaced with html.

Source code in rst_in_md/processor.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
def run(self, lines: list[str]) -> list[str]:
    """Strip restuctured text from markdown and replace it with converted html.

    This method will look for fenced code blocks in markdown that are marked as
    restructured text (`rst`, `rest`, `restructuredtext`) and convert them to html.
    It leverages the same regex as the [FencedBlockPreprocessor](https://github.com/Python-Markdown/markdown/blob/33359faa385f59b84cd87df5f4b0996055a482e2/markdown/extensions/fenced_code.py#L56-L67)
    to find the blocks.

    You can also ignore a block from being converted by `rst-in-md` adding
    `rst-in-md=false` to the attributes: ````{.rst rst-in-md=false}`. You can see an
    example of this [here](../guides/inline_ignore.md).

    Args:
        lines (list[str]): List of lines in markdown.

    Returns:
        list[str]: List of lines in markdown with rst replaced with html.
    """
    text = "\n".join(lines)
    processed = ""
    index = 0
    for match in self.FENCED_BLOCK_RE.finditer(text):
        lang = None
        attrs = []
        classes = []
        config = {}
        if match.group("lang") is not None:
            lang = match.group("lang")
        elif match.group("attrs") is not None:
            attrs, remainder = get_attrs_and_remainder(match.group("attrs"))
            if remainder:  # skip this match due to invalid syntax
                warnings.warn("Invalid syntax parsing attributes", stacklevel=1)
                processed += text[match.start() : match.end()]
                index = match.end()
                continue
            _, classes, config = self.handle_attrs(attrs)
            if len(classes) > 0:
                lang = classes.pop(0)

        processed += text[index : match.start()]

        if lang not in LANGUAGES or config.get("rst-in-md") == "false":
            processed += text[match.start() : match.end()]
        else:
            try:
                processed += rst_to_soup(match.group("code")).prettify(
                    formatter=BS4_FORMATTER,
                )
            except ValueError as e:
                warnings.warn(str(e), stacklevel=1)
                processed += text[match.start() : match.end()]

        index = match.end()
    processed += text[index:]
    return processed.split("\n")