From 201383d233aa5eb6a88fc266d29e7c93cc6c3f6c Mon Sep 17 00:00:00 2001 From: Kyle King Date: Tue, 13 Dec 2022 23:00:15 -0500 Subject: [PATCH] feat: initial admon plugin attempt (#1) --- .pre-commit-config.yaml | 3 + mdformat-admon/plugin.py | 24 -- .../__init__.py | 0 mdformat_admon/plugin.py | 42 ++++ pyproject.toml | 8 +- tests/fixtures.md | 231 ++++++++++++++++-- tests/test_fixtures.py | 5 +- 7 files changed, 268 insertions(+), 45 deletions(-) delete mode 100644 mdformat-admon/plugin.py rename {mdformat-admon => mdformat_admon}/__init__.py (100%) create mode 100644 mdformat_admon/plugin.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0e5544b..dc82612 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,3 +27,6 @@ repos: - flake8-bugbear>=21.3.2 - flake8-builtins>=1.5.3 - flake8-comprehensions>=3.4.0 + args: [ + --ignore=E501 + ] diff --git a/mdformat-admon/plugin.py b/mdformat-admon/plugin.py deleted file mode 100644 index 8fff61c..0000000 --- a/mdformat-admon/plugin.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Mapping - -from markdown_it import MarkdownIt -from mdformat.renderer import RenderContext, RenderTreeNode -from mdformat.renderer.typing import Render - - -def update_mdit(mdit: MarkdownIt) -> None: - """Update the parser, e.g. by adding a plugin: `mdit.use(myplugin)`""" - pass - - -def _render_table(node: RenderTreeNode, context: RenderContext) -> str: - """Render a `RenderTreeNode` of type "table". - - Change "table" to the name of the syntax you want to render. - """ - return "" - - -# A mapping from syntax tree node type to a function that renders it. -# This can be used to overwrite renderer functions of existing syntax -# or add support for new syntax. -RENDERERS: Mapping[str, Render] = {"table": _render_table} diff --git a/mdformat-admon/__init__.py b/mdformat_admon/__init__.py similarity index 100% rename from mdformat-admon/__init__.py rename to mdformat_admon/__init__.py diff --git a/mdformat_admon/plugin.py b/mdformat_admon/plugin.py new file mode 100644 index 0000000..ed52746 --- /dev/null +++ b/mdformat_admon/plugin.py @@ -0,0 +1,42 @@ +import textwrap +from typing import Mapping + +from markdown_it import MarkdownIt +from mdformat.renderer import RenderContext, RenderTreeNode +from mdformat.renderer.typing import Render +from mdit_py_plugins.admon import admon_plugin + + +def update_mdit(mdit: MarkdownIt) -> None: + """Update the parser,""" + mdit.use(admon_plugin) + + +def _render_admon(node: RenderTreeNode, context: RenderContext) -> str: + """Render a `RenderTreeNode` of type `admonition`. + + Primarily based on: + + - https://github.com/executablebooks/mdformat-footnote/blob/80852fc20cfba7fd0330b9ac7a1a4df983542942/mdformat_footnote/plugin.py#LL24-L40C29 + + And based on: + + - https://github.com/hukkin/mdformat-gfm/blob/cf316a121b6cf35cbff7b0ad6e171f287803f8cb/src/mdformat_gfm/plugin.py + - https://github.com/hukkin/mdformat-toc/blob/42624b6f3468da4f793ec7425da872b030714774/mdformat_toc/plugin.py + - https://github.com/executablebooks/mdformat-footnote/blob/80852fc20cfba7fd0330b9ac7a1a4df983542942/mdformat_footnote/plugin.py + + """ + separator = "\n\n" # TODO: Is this configurable? + indent = " " * 4 # FIXME: Is this configurable? + title = node.info.strip() + body = f"{node.markup} {title}{separator}" + with context.indented(len(indent)): # Modifies context.env['indent_width'] + elements = [child.render(context) for child in node.children[1:]] + body += textwrap.indent(separator.join(elements), indent) + return body + + +# A mapping from syntax tree node type to a function that renders it. +# This can be used to overwrite renderer functions of existing syntax +# or add support for new syntax. +RENDERERS: Mapping[str, Render] = {"admonition": _render_admon} diff --git a/pyproject.toml b/pyproject.toml index baa15bb..0d58574 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,16 +15,16 @@ classifiers = [ "Topic :: Software Development :: Libraries :: Python Modules", ] keywords = ["mdformat", "markdown", "markdown-it"] -requires-python = ">=3.7" +requires-python = ">=3.7.2" dependencies = [ "mdformat >=0.7.0,<0.8.0", + "mdit-py-plugins >=0.3.2", ] dynamic = ["version", "description"] [project.optional-dependencies] test = [ - "pytest~=6.0", - "coverage", + "pytest>=6.0", "pytest-cov", ] dev = ["pre-commit"] @@ -33,7 +33,7 @@ dev = ["pre-commit"] Homepage = "https://github.com/executablebooks/mdformat-admon" [project.entry-points."mdformat.parser_extension"] -admon = "mdformat_admon" +admonition = "mdformat_admon" [tool.flit.sdist] include = [] diff --git a/tests/fixtures.md b/tests/fixtures.md index 31d6be2..fe2d2d9 100644 --- a/tests/fixtures.md +++ b/tests/fixtures.md @@ -1,24 +1,227 @@ -a test + +Simple admonition +. +!!! note + *content* +. +!!! note + *content* +. + + +Could contain block elements too +. +!!! note + ### heading + + ----------- + +. +!!! note + ### heading + + ______________________________________________________________________ + +. + + +Shows custom title +. +!!! note Custom title + + Some text + +. +!!! note Custom title + + Some text + +. + + +Shows no title +. +!!! note "" + Some text + . -This is the input Markdown test, -then below add the expected output. +!!! note "" + Some text + +. + + +Closes block after 2 empty lines +. +!!! note + Some text + + + A code block +. +!!! note + Some text + + + A code block +. + + +Nested blocks . -This is the input Markdown test, -then below add the expected output. +!!! note + !!! note + Some text + + code block . +!!! note + !!! note + Some text -another test + code block . -Some *markdown* -- a -- b -* c + +Consecutive admonitions . -Some *markdown* +!!! note -- a -- b +!!! warning +. +!!! note -* c +!!! warning +. + + +Marker may be indented up to 3 chars +. + !!! note + content +. + !!! note + content +. + + +But that's a code block +. + !!! note + content +. + !!! note + content +. + + +Some more indent checks +. + !!! note + not a code block + + code block +. + !!! note + not a code block + + code block +. + + +Type could be adjacent to marker +. +!!!note + xxx + +. +!!!note + xxx + +. + + +Type could be adjacent to marker and content may be shifted up to 3 chars +. +!!!note + xxx + +. +!!!note + xxx + +. + + +Or several spaces apart +. +!!! note + xxx +. +!!! note + xxx +. + + +Admonitions self-close at the end of the document +. +!!! note + xxx +. +!!! note + xxx +. + + +They could be nested in lists +. +- !!! note + - a + - b +- !!! warning + - c + - d +. +- !!! note + - a + - b +- !!! warning + - c + - d +. + + +Or in blockquotes +. +> !!! note +> xxx +> > yyy +> zzz +> +. +> !!! note +> xxx +> > yyy +> zzz +> +. + + +Renders unknown admonition type +. +!!! unknown title + content +. +!!! unknown title + content +. + + +Does not render +. +!!! + content +. +!!! + content . diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py index 5e19d41..313637b 100644 --- a/tests/test_fixtures.py +++ b/tests/test_fixtures.py @@ -12,6 +12,5 @@ "line,title,text,expected", fixtures, ids=[f[1] for f in fixtures] ) def test_fixtures(line, title, text, expected): - output = mdformat.text(text, extensions={"admon"}) - print(output) - assert output.rstrip() == expected.rstrip(), output + output = mdformat.text(text, extensions={"admonition"}) + assert output.rstrip() == expected.rstrip()