Skip to content

👌 IMPROVE: Support colon fenced directives #36

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions mdformat_myst/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,70 @@
from mdit_py_plugins.dollarmath import dollarmath_plugin
from mdit_py_plugins.myst_blocks import myst_block_plugin
from mdit_py_plugins.myst_role import myst_role_plugin
from mdit_py_plugins.container import container_plugin

from mdformat_myst._directives import fence, render_fence_html

_TARGET_PATTERN = re.compile(r"^\s*\(.+\)=\s*$")
_ROLE_NAME_PATTERN = re.compile(r"({[a-zA-Z0-9_\-+:]+})")
_YAML_HEADER_PATTERN = re.compile(r"(?m)(^:\w+: .*$\n?)+|^---$\n(?s:.).*\n---\n")

container_names = [
"admonition",
"attention",
"caution",
"danger",
"div",
"dropdown",
"embed",
"error",
"exercise",
"exercise-end",
"exercise-start",
"figure",
"glossary",
"grid",
"grid-item",
"grid-item-card",
"hint",
"image",
"important",
"include",
"index",
"literal-include",
"margin",
"math",
"note",
"prf:algorithm",
"prf:assumption",
"prf:axiom",
"prf:conjecture",
"prf:corollary",
"prf:criterion",
"prf:definition",
"prf:example",
"prf:lemma",
"prf:observation",
"prf:proof",
"prf:property",
"prf:proposition",
"prf:remark",
"prf:theorem",
"seealso",
"show-index",
"sidebar",
"solution",
"solution-end",
"solution-start",
"span",
"tab-item",
"tab-set",
"table",
"tip",
"todo",
"topics",
"warning",
]


def update_mdit(mdit: MarkdownIt) -> None:
Expand Down Expand Up @@ -51,6 +110,36 @@ def update_mdit(mdit: MarkdownIt) -> None:
mdit.add_render_rule("fence", render_fence_html)
mdit.add_render_rule("code_block", render_fence_html)

for name in container_names:
container_plugin(mdit, name="{" + name + "}", marker=":")


def container_renderer(
node: RenderTreeNode, context: RenderContext, *args, **kwargs
) -> str:
children = node.children
paragraphs = []
if children:
# Look at the tokens forming the first paragraph and see if
# they form a YAML header. This could be stricter: there
# should be exactly three tokens: paragraph open, YAML
# header, paragraph end.
tokens = children[0].to_tokens()
if all(
token.type in {'paragraph_open', 'paragraph_close'} or
_YAML_HEADER_PATTERN.fullmatch(token.content)
for token in tokens
):
paragraphs.append('\n'.join(token.content.strip()
for token in tokens
if token.content))
# and skip that first paragraph
children = children[1:]

paragraphs.extend(child.render(context) for child in children)

return node.markup + node.info + "\n" + "\n\n".join(paragraphs) + "\n" + node.markup


def _role_renderer(node: RenderTreeNode, context: RenderContext) -> str:
role_name = "{" + node.meta["name"] + "}"
Expand Down Expand Up @@ -130,4 +219,9 @@ def _escape_text(text: str, node: RenderTreeNode, context: RenderContext) -> str
"math_block": _math_block_renderer,
"fence": fence,
}


for name in container_names:
RENDERERS["container_{" + name + "}"] = container_renderer

POSTPROCESSORS = {"paragraph": _escape_paragraph, "text": _escape_text}
91 changes: 91 additions & 0 deletions tests/data/fixtures.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,3 +406,94 @@ MyST directive, no opts or content
```{some-directive} args
```
.

:::{admonition} MyST colon fenced directive with a title
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
:::

.

:::{admonition} MyST colon fenced directive with simple metadata
:class: foo
:truc: bla

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
:::

::::{admonition} MyST colon fenced directive with nested directive with simple metadata
:::{image} foo.png
:class: foo
:truc: bla
:::
::::

% Admonitions with arbitrary yaml metadata are not yet supported.
% Issue: in a container, the `---` is interpreted as hrule by the parser
%
% :::{admonition} MyST colon fenced directive with arbitrary yaml metadata
% ---
% foo:
% bar: 1
% ---
%
% Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
% incididunt ut labore et dolore magna aliqua.
% :::

.

% Unknown colon-fenced directives are not yet implemented
% :::{exercise}
% This is an unknown admonition.
% :::

.

::::{admonition} MyST colon fenced directive with two nested admonitions
:::{admonition}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
:::

:::{admonition}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
:::

:::{admonition}
truc
:::
::::

.

::::{hint} A hint with alternating nested tips and texts
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.

:::{tip}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
:::

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.

:::{tip}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
:::

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
::::

.

- foo
:::{tip} A directive nested in bullet points
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
:::