Skip to content

Superfence

Tip

Reference for PyMdown Extensions Superfences can be found here.

rst_in_md.superfence_formatter(source, language, css_class, options, md, **kwargs)

Convert superfenced reStructuredText to html.

This function will convert the reStructuredText to html using the same method as the standard python markdown extension.

Unused Arguments

This function is passed a few arguments that are not used. It must adhere to the required signature set by pymdownx.superfences.

Parameters:

Name Type Description Default
source str

Language of the superfence.

required
language str

Language of the superfence (required, but not used).

required
css_class str

CSS class of the superfence (required, but not used).

required
options dict

Options of the superfence (required, but not used).

required
md Markdown

The markdown instance (required, but not used).

required

Returns:

Name Type Description
str str

The converted html.

Source code in rst_in_md/superfence.py
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
def superfence_formatter(  # noqa: D417
    source: str,
    language: str,  # noqa: ARG001
    css_class: str,  # noqa: ARG001
    options: dict,  # noqa: ARG001
    md: Markdown,  # noqa: ARG001
    **kwargs: dict,  # noqa: ARG001
) -> str:
    """Convert superfenced reStructuredText to html.

    This function will convert the reStructuredText to html using the same method as
    the standard python markdown extension.

    !!! note "Unused Arguments"
        This function is passed a few arguments that are not used. It must adhere to
        [the required signature](https://facelessuser.github.io/pymdown-extensions/extensions/superfences/#formatters)
        set by `pymdownx.superfences`.

    Args:
        source (str): Language of the superfence.
        language (str): Language of the superfence _(required, but not used)_.
        css_class (str): CSS class of the superfence _(required, but not used)_.
        options (dict): Options of the superfence _(required, but not used)_.
        md (Markdown): The markdown instance _(required, but not used)_.

    Returns:
        str: The converted html.
    """
    return rst_to_soup(source).prettify(formatter=BS4_FORMATTER)

rst_in_md.superfence_validator(language, inputs, options, attrs, md)

Validate that the superfence should be processed.

This function will validate that the superfence should be processed by rst-in-md. This includes:

  • Checking if the language is supported.
  • Checking if the rst-in-md attribute is set to false or not.
  • Checking if any options or attributes are passed.

Unused Arguments

md is passed to this function but is not used. It must adhere to the required signature set by pymdownx.superfences.

Parameters:

Name Type Description Default
language str

Language of the superfence.

required
inputs dict

All the parsed options/attributes of the superfence.

required
options dict

A dictionary to which all valid options should be assigned to.

required
attrs dict

A dictionary to which all valid attributes should be assigned to.

required
md Markdown

the markdown instance (required, but not used).

required

Returns:

Name Type Description
bool bool

If the superfence should be processed or not.

Source code in rst_in_md/superfence.py
 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
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def superfence_validator(
    language: str,
    inputs: dict,
    options: dict,
    attrs: dict,
    md: Markdown,  # noqa: ARG001
) -> bool:
    """Validate that the superfence should be processed.

    This function will validate that the superfence should be processed by `rst-in-md`.
    This includes:

    * Checking if the language is supported.
    * Checking if the `rst-in-md` attribute is set to `false` or not.
    * Checking if any options or attributes are passed.

    !!! note "Unused Arguments"
        `md` is passed to this function but is not used. It must adhere to
        [the required signature](https://facelessuser.github.io/pymdown-extensions/extensions/superfences/#validators)
        set by `pymdownx.superfences`.

    Args:
        language (str): Language of the superfence.
        inputs (dict): All the parsed options/attributes of the superfence.
        options (dict): A dictionary to which all valid options should be assigned to.
        attrs (dict): A dictionary to which all valid attributes should be assigned to.
        md (Markdown): the markdown instance _(required, but not used)_.

    Returns:
        bool: If the superfence should be processed or not.
    """
    if language not in LANGUAGES:
        msg = f"language '{language}' is not supported."
        logging.error(msg)
        return False

    allowed = {"rst-in-md"}
    if (keys := set(inputs.keys())) > allowed:
        msg = f"keys '{keys - allowed}' are not supported."
        logging.error(msg)
        return False

    if inputs.get("rst-in-md") == "false":
        logging.info("rst-in-md is set to false.")
        return False

    if len(options) > 0:
        logging.error("options are not supported.")
        return False

    if len(attrs) > 0:
        logging.error("attrs are not supported.")
        return False

    return True

rst_in_md.RestructuredTextInMarkdownAutoConfigurator

Bases: Preprocessor

Preprocessor to adapt rst-in-md to work with pymdownx.superfences.

Source code in rst_in_md/superfence.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
class RestructuredTextInMarkdownAutoConfigurator(Preprocessor):
    """Preprocessor to adapt `rst-in-md` to work with `pymdownx.superfences`."""

    initialized = False

    def superfences_installed(self) -> bool:
        """Check if the `pymdownx.superfences` extension is installed.

        Returns:
            bool: If the extension is installed or not.
        """
        try:
            from pymdownx.superfences import SuperFencesBlockPreprocessor
        except ImportError:
            return False

        return isinstance(
            self.md.preprocessors["fenced_code_block"],
            SuperFencesBlockPreprocessor,
        )

    @staticmethod
    def construct_fence_config(language: str) -> dict:
        """Create a fence configuration dictionary for `pymdownx.superfences`.

        Create a fence configuration for `pymdownx.superfences` with the given language,
        in the given [structure](https://github.com/facelessuser/pymdown-extensions/blob/cd7c704487a3a79b6619bfcd0c6af83104d630a8/pymdownx/superfences.py#L273-L276).
        This configuration will be read by `pymdownx.superfences` to determine how to
        process the superfence.

        Args:
            language (str): Language of the superfence.

        Returns:
            dict: Dictionary of the fence configuration.
        """
        return {
            "name": language,
            "class": "rst-in-md",
            "format": superfence_formatter,
            "validator": superfence_validator,
        }

    @staticmethod
    def construct_superfence(language: str) -> dict:
        """Create a superfence dictionary for `pymdownx.superfences`.

        Create a superfence dict for `pymdownx.superfences` with the given language,
        in the given [structure](https://github.com/facelessuser/pymdown-extensions/blob/cd7c704487a3a79b6619bfcd0c6af83104d630a8/pymdownx/superfences.py#L240-L245).
        This dictionary will be appended to `SuperFencesCodeExtension().superfences`.

        Args:
            language (str): Language of the superfence.

        Returns:
            dict: Dictionary of the superfence for `pymdownx.superfences`.

        Raises:
            ImportError: pymdown-extensions is not properly installed.
        """
        try:
            from pymdownx.superfences import _formatter, _test, _validator
        except ImportError as e:
            msg = "pymdown-extensions is not properly installed."
            raise ImportError(msg) from e

        return {
            "name": language,
            "test": partial(_test, test_language=language),
            "formatter": partial(
                _formatter,
                class_name="rst-in-md",
                _fmt=superfence_formatter,
            ),
            "validator": partial(
                _validator,
                validator=superfence_validator,
            ),
        }

    def inject_custom_configs(self) -> None:
        """Add custom fence configs to `pymdownx.superfences`, if not already present.

        Raises:
            ImportError: pymdown-extensions is not properly installed.
            ValueError: SuperFencesCodeExtension not found.
        """
        try:
            from pymdownx.superfences import SuperFencesCodeExtension
        except ImportError as e:
            msg = "pymdown-extensions is not properly installed."
            raise ImportError(msg) from e

        registered = self.md.registeredExtensions
        extensions = [e for e in registered if isinstance(e, SuperFencesCodeExtension)]
        if len(extensions) != 1:
            msg = "Unable to find SuperFencesCodeExtension."
            raise ValueError(msg)
        ext = extensions[0]

        config = self.md.preprocessors["fenced_code_block"].config  # pyright: ignore[reportAttributeAccessIssue]
        custom_fences = config.get("custom_fences", [])
        for language in LANGUAGES:
            if (fence := self.construct_fence_config(language)) not in custom_fences:
                custom_fences.append(fence)
                ext.superfences.append(self.construct_superfence(language))

        config["custom_fences"] = custom_fences

    def run(self, lines: list[str]) -> list[str]:
        """Auto-configure `pymdownx.superfences` if installed.

        This method will check if `pymdownx.superfences` is installed. If it is, it will
        deregister `rst-in-md`, since `pymdownx.superfences` will handle the fenced code
        blocks. It will also provide the custom fence configurations needed for
        `pymdownx.superfences` to properly process the fenced code.

        !!! question "Why is this a preprocessor?"

            This preprocessor will not actually process any markdown, even if it is
            called for each markdown file. It much be run after all extensions have been
            initialized.

        Args:
            lines (list[str]): Input lines _(required, but not used)_.

        Returns:
            list[str]: Identical as the input lines.
        """
        if not self.initialized and self.superfences_installed():
            self.md.preprocessors.deregister("rst-in-md")
            self.inject_custom_configs()
            self.initialized = True

        return lines

construct_fence_config(language) staticmethod

Create a fence configuration dictionary for pymdownx.superfences.

Create a fence configuration for pymdownx.superfences with the given language, in the given structure. This configuration will be read by pymdownx.superfences to determine how to process the superfence.

Parameters:

Name Type Description Default
language str

Language of the superfence.

required

Returns:

Name Type Description
dict dict

Dictionary of the fence configuration.

Source code in rst_in_md/superfence.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
@staticmethod
def construct_fence_config(language: str) -> dict:
    """Create a fence configuration dictionary for `pymdownx.superfences`.

    Create a fence configuration for `pymdownx.superfences` with the given language,
    in the given [structure](https://github.com/facelessuser/pymdown-extensions/blob/cd7c704487a3a79b6619bfcd0c6af83104d630a8/pymdownx/superfences.py#L273-L276).
    This configuration will be read by `pymdownx.superfences` to determine how to
    process the superfence.

    Args:
        language (str): Language of the superfence.

    Returns:
        dict: Dictionary of the fence configuration.
    """
    return {
        "name": language,
        "class": "rst-in-md",
        "format": superfence_formatter,
        "validator": superfence_validator,
    }

construct_superfence(language) staticmethod

Create a superfence dictionary for pymdownx.superfences.

Create a superfence dict for pymdownx.superfences with the given language, in the given structure. This dictionary will be appended to SuperFencesCodeExtension().superfences.

Parameters:

Name Type Description Default
language str

Language of the superfence.

required

Returns:

Name Type Description
dict dict

Dictionary of the superfence for pymdownx.superfences.

Raises:

Type Description
ImportError

pymdown-extensions is not properly installed.

Source code in rst_in_md/superfence.py
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
@staticmethod
def construct_superfence(language: str) -> dict:
    """Create a superfence dictionary for `pymdownx.superfences`.

    Create a superfence dict for `pymdownx.superfences` with the given language,
    in the given [structure](https://github.com/facelessuser/pymdown-extensions/blob/cd7c704487a3a79b6619bfcd0c6af83104d630a8/pymdownx/superfences.py#L240-L245).
    This dictionary will be appended to `SuperFencesCodeExtension().superfences`.

    Args:
        language (str): Language of the superfence.

    Returns:
        dict: Dictionary of the superfence for `pymdownx.superfences`.

    Raises:
        ImportError: pymdown-extensions is not properly installed.
    """
    try:
        from pymdownx.superfences import _formatter, _test, _validator
    except ImportError as e:
        msg = "pymdown-extensions is not properly installed."
        raise ImportError(msg) from e

    return {
        "name": language,
        "test": partial(_test, test_language=language),
        "formatter": partial(
            _formatter,
            class_name="rst-in-md",
            _fmt=superfence_formatter,
        ),
        "validator": partial(
            _validator,
            validator=superfence_validator,
        ),
    }

inject_custom_configs()

Add custom fence configs to pymdownx.superfences, if not already present.

Raises:

Type Description
ImportError

pymdown-extensions is not properly installed.

ValueError

SuperFencesCodeExtension not found.

Source code in rst_in_md/superfence.py
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
def inject_custom_configs(self) -> None:
    """Add custom fence configs to `pymdownx.superfences`, if not already present.

    Raises:
        ImportError: pymdown-extensions is not properly installed.
        ValueError: SuperFencesCodeExtension not found.
    """
    try:
        from pymdownx.superfences import SuperFencesCodeExtension
    except ImportError as e:
        msg = "pymdown-extensions is not properly installed."
        raise ImportError(msg) from e

    registered = self.md.registeredExtensions
    extensions = [e for e in registered if isinstance(e, SuperFencesCodeExtension)]
    if len(extensions) != 1:
        msg = "Unable to find SuperFencesCodeExtension."
        raise ValueError(msg)
    ext = extensions[0]

    config = self.md.preprocessors["fenced_code_block"].config  # pyright: ignore[reportAttributeAccessIssue]
    custom_fences = config.get("custom_fences", [])
    for language in LANGUAGES:
        if (fence := self.construct_fence_config(language)) not in custom_fences:
            custom_fences.append(fence)
            ext.superfences.append(self.construct_superfence(language))

    config["custom_fences"] = custom_fences

run(lines)

Auto-configure pymdownx.superfences if installed.

This method will check if pymdownx.superfences is installed. If it is, it will deregister rst-in-md, since pymdownx.superfences will handle the fenced code blocks. It will also provide the custom fence configurations needed for pymdownx.superfences to properly process the fenced code.

Why is this a preprocessor?

This preprocessor will not actually process any markdown, even if it is called for each markdown file. It much be run after all extensions have been initialized.

Parameters:

Name Type Description Default
lines list[str]

Input lines (required, but not used).

required

Returns:

Type Description
list[str]

list[str]: Identical as the input lines.

Source code in rst_in_md/superfence.py
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
def run(self, lines: list[str]) -> list[str]:
    """Auto-configure `pymdownx.superfences` if installed.

    This method will check if `pymdownx.superfences` is installed. If it is, it will
    deregister `rst-in-md`, since `pymdownx.superfences` will handle the fenced code
    blocks. It will also provide the custom fence configurations needed for
    `pymdownx.superfences` to properly process the fenced code.

    !!! question "Why is this a preprocessor?"

        This preprocessor will not actually process any markdown, even if it is
        called for each markdown file. It much be run after all extensions have been
        initialized.

    Args:
        lines (list[str]): Input lines _(required, but not used)_.

    Returns:
        list[str]: Identical as the input lines.
    """
    if not self.initialized and self.superfences_installed():
        self.md.preprocessors.deregister("rst-in-md")
        self.inject_custom_configs()
        self.initialized = True

    return lines

superfences_installed()

Check if the pymdownx.superfences extension is installed.

Returns:

Name Type Description
bool bool

If the extension is installed or not.

Source code in rst_in_md/superfence.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
def superfences_installed(self) -> bool:
    """Check if the `pymdownx.superfences` extension is installed.

    Returns:
        bool: If the extension is installed or not.
    """
    try:
        from pymdownx.superfences import SuperFencesBlockPreprocessor
    except ImportError:
        return False

    return isinstance(
        self.md.preprocessors["fenced_code_block"],
        SuperFencesBlockPreprocessor,
    )