Repository: executablebooks/MyST-Parser

Issue:
support mermaid
**Describe the solution you'd like**

support mermaid

**Describe alternatives you've considered**

The conf.py I used to make work `mermaid` with `recommonmark`:

```
$ tail conf.py
extensions = [ 'recommonmark', 'sphinxcontrib.mermaid']
from recommonmark.transform import AutoStructify
def setup(app):
    app.add_transform(AutoStructify)
$
```

This mermaid is rendered

```
```mermaid::

  graph LR
    a --> b
\```
```

Note that the above need to have a new line after `mermaid::` and `graph` need to start with a space.

    

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/executablebooks/MyST-Parser/pull/742?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) Report
Patch coverage: **`100.00`**% and project coverage change: **`+0.03`** :tada:
> Comparison is base [(`1e440e6`)](https://codecov.io/gh/executablebooks/MyST-Parser/commit/1e440e6d38da18abd83c88519679b68768e64596?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) 89.96% compared to head [(`75ef9f3`)](https://codecov.io/gh/executablebooks/MyST-Parser/pull/742?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) 89.99%.

> :exclamation: Current head 75ef9f3 differs from pull request most recent head 926b4f5. Consider uploading reports for the commit 926b4f5 to get more accurate results

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #742      +/-   ##
==========================================
+ Coverage   89.96%   89.99%   +0.03%     
==========================================
  Files          23       23              
  Lines        2969     2978       +9     
==========================================
+ Hits         2671     2680       +9     
  Misses        298      298              
```

| Flag | Coverage Δ | |
|---|---|---|
| pytests | `89.99% <100.00%> (+0.03%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/executablebooks/MyST-Parser/pull/742?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) | Coverage Δ | |
|---|---|---|
| [myst\_parser/config/main.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/742?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvY29uZmlnL21haW4ucHk=) | `86.33% <100.00%> (+0.30%)` | :arrow_up: |
| [myst\_parser/mdit\_to\_docutils/base.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/742?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvbWRpdF90b19kb2N1dGlscy9iYXNlLnB5) | `92.69% <100.00%> (+0.03%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/executablebooks/MyST-Parser/pull/742?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).


Patch:
diff --git a/myst_parser/config/main.py b/myst_parser/config/main.py
index 4f3889d..f22791a 100644
--- a/myst_parser/config/main.py
+++ b/myst_parser/config/main.py
@@ -166,6 +166,14 @@ def _test_slug_func(text: str) -> str:
     return text[::-1]
 
 
+def check_fence_as_directive(
+    inst: "MdParserConfig", field: dc.Field, value: Any
+) -> None:
+    """Check that the extensions are a sequence of known strings"""
+    deep_iterable(instance_of(str), instance_of((list, tuple, set)))(inst, field, value)
+    setattr(inst, field.name, set(value))
+
+
 @dc.dataclass()
 class MdParserConfig:
     """Configuration options for the Markdown Parser.
@@ -250,6 +258,16 @@ class MdParserConfig:
         },
     )
 
+    fence_as_directive: Set[str] = dc.field(
+        default_factory=set,
+        metadata={
+            "validator": check_fence_as_directive,
+            "help": "Interpret a code fence as a directive, for certain language names. "
+            "This can be useful for fences like dot and mermaid, "
+            "and interoperability with other Markdown renderers.",
+        },
+    )
+
     number_code_blocks: Sequence[str] = dc.field(
         default_factory=list,
         metadata={
diff --git a/myst_parser/mdit_to_docutils/base.py b/myst_parser/mdit_to_docutils/base.py
index 653ce6a..c85f454 100644
--- a/myst_parser/mdit_to_docutils/base.py
+++ b/myst_parser/mdit_to_docutils/base.py
@@ -743,6 +743,13 @@ class DocutilsRenderer(RendererProtocol):
                 return self.render_restructuredtext(token)
             if name.startswith("{") and name.endswith("}"):
                 return self.render_directive(token, name[1:-1], arguments)
+            if name in self.md_config.fence_as_directive:
+                options = {k: str(v) for k, v in token.attrs.items()}
+                if "id" in options:
+                    options["name"] = options.pop("id")
+                return self.render_directive(
+                    token, name, arguments, additional_options=options
+                )
 
         if not name and self.sphinx_env is not None:
             # use the current highlight setting, via the ``highlight`` directive,
@@ -1664,7 +1671,12 @@ class DocutilsRenderer(RendererProtocol):
         self.current_node.extend(newdoc.children)
 
     def render_directive(
-        self, token: SyntaxTreeNode, name: str, arguments: str
+        self,
+        token: SyntaxTreeNode,
+        name: str,
+        arguments: str,
+        *,
+        additional_options: dict[str, str] | None = None,
     ) -> None:
         """Render special fenced code blocks as directives.
 
@@ -1673,7 +1685,13 @@ class DocutilsRenderer(RendererProtocol):
         :param arguments: The remaining text on the same line as the directive name.
         """
         position = token_line(token)
-        nodes_list = self.run_directive(name, arguments, token.content, position)
+        nodes_list = self.run_directive(
+            name,
+            arguments,
+            token.content,
+            position,
+            additional_options=additional_options,
+        )
         self.current_node += nodes_list
 
     def run_directive(


Test patch:
diff --git a/tests/test_renderers/fixtures/myst-config.txt b/tests/test_renderers/fixtures/myst-config.txt
index 62226c9..86e36d7 100644
--- a/tests/test_renderers/fixtures/myst-config.txt
+++ b/tests/test_renderers/fixtures/myst-config.txt
@@ -468,3 +468,31 @@ My paragraph
                 <reference id_link="True" refid="title">
                     reversed
 .
+
+[fence_as_directive] --myst-fence-as-directive=unknown,admonition --myst-enable-extensions=attrs_block
+.
+```unknown
+```
+
+{#myname .class1}
+{a=b}
+```admonition title
+content
+```
+.
+<document source="<string>">
+    <system_message level="2" line="1" source="<string>" type="WARNING">
+        <paragraph>
+            Unknown directive type: 'unknown' [myst.directive_unknown]
+    <system_message level="2" line="6" source="<string>" type="WARNING">
+        <paragraph>
+            'admonition': Unknown option keys: ['a'] (allowed: ['class', 'name']) [myst.directive_parse]
+    <admonition classes="class1" ids="myname" names="myname">
+        <title>
+            title
+        <paragraph>
+            content
+
+<string>:1: (WARNING/2) Unknown directive type: 'unknown' [myst.directive_unknown]
+<string>:6: (WARNING/2) 'admonition': Unknown option keys: ['a'] (allowed: ['class', 'name']) [myst.directive_parse]
+.