Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ NEW: Add myst_fence_as_directive config #742

Merged
merged 2 commits into from Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions myst_parser/config/main.py
Expand Up @@ -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.
Expand Down Expand Up @@ -250,6 +258,16 @@ def __repr__(self) -> str:
},
)

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={
Expand Down
22 changes: 20 additions & 2 deletions myst_parser/mdit_to_docutils/base.py
Expand Up @@ -743,6 +743,13 @@ def render_fence(self, token: SyntaxTreeNode) -> None:
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,
Expand Down Expand Up @@ -1664,7 +1671,12 @@ def render_restructuredtext(self, token: SyntaxTreeNode) -> None:
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.

Expand All @@ -1673,7 +1685,13 @@ def render_directive(
: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(
Expand Down
28 changes: 28 additions & 0 deletions tests/test_renderers/fixtures/myst-config.txt
Expand Up @@ -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]
.