From 32cf4e182f3d8638118b320fb50b2a4815857b99 Mon Sep 17 00:00:00 2001 From: Kyle King Date: Tue, 30 Jan 2024 15:33:11 -0500 Subject: [PATCH] feat: restore mdformat-gfm dependency --- .../_copy_of_mdformat_gfm/__init__.py | 3 - .../_copy_of_mdformat_gfm/plugin.py | 152 ------------------ mdformat_mkdocs/plugin.py | 6 - pyproject.toml | 6 +- tests/fixtures-semantic-indent.md | 10 +- tests/format/fixtures/text.md | 14 +- tests/pre-commit-test-numbered.md | 4 +- tests/test_wrap.py | 6 +- 8 files changed, 20 insertions(+), 181 deletions(-) delete mode 100644 mdformat_mkdocs/_copy_of_mdformat_gfm/__init__.py delete mode 100644 mdformat_mkdocs/_copy_of_mdformat_gfm/plugin.py diff --git a/mdformat_mkdocs/_copy_of_mdformat_gfm/__init__.py b/mdformat_mkdocs/_copy_of_mdformat_gfm/__init__.py deleted file mode 100644 index 9c41f82..0000000 --- a/mdformat_mkdocs/_copy_of_mdformat_gfm/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .plugin import POSTPROCESSORS as GFM_POSTPROCESSORS -from .plugin import RENDERERS as GFM_RENDERERS -from .plugin import update_mdit as gfm_update_mdit diff --git a/mdformat_mkdocs/_copy_of_mdformat_gfm/plugin.py b/mdformat_mkdocs/_copy_of_mdformat_gfm/plugin.py deleted file mode 100644 index b20f86c..0000000 --- a/mdformat_mkdocs/_copy_of_mdformat_gfm/plugin.py +++ /dev/null @@ -1,152 +0,0 @@ -"""Copied from . - -Will be removed when released (Workaround for https://github.com/hukkin/mdformat-gfm/issues/31) - -""" - -import re - -import mdformat.plugins -from markdown_it import MarkdownIt -from mdformat.renderer import DEFAULT_RENDERERS, RenderContext, RenderTreeNode -from mdit_py_plugins.tasklists import tasklists_plugin - -# A regex that matches a URL scheme and a following colon, as is valid in CommonMark -RE_COMMONMARK_URL_SCHEME = re.compile("[A-Za-z][A-Za-z0-9+.-]{1,31}:") - - -def update_mdit(mdit: MarkdownIt) -> None: - # Enable linkify-it-py (for GFM autolink extension) - mdit.options["linkify"] = True - mdit.enable("linkify") - - # Enable mdformat-tables plugin - tables_plugin = mdformat.plugins.PARSER_EXTENSIONS["tables"] - if tables_plugin not in mdit.options["parser_extension"]: - mdit.options["parser_extension"].append(tables_plugin) - tables_plugin.update_mdit(mdit) - - # Enable strikethrough markdown-it extension - mdit.enable("strikethrough") - - # Enable tasklist markdown-it extension - mdit.use(tasklists_plugin) - - -def _strikethrough_renderer(node: RenderTreeNode, context: RenderContext) -> str: - content = "".join(child.render(context) for child in node.children) - return f"~~{content}~~" - - -def _render_with_default_renderer(node: RenderTreeNode, context: RenderContext) -> str: - """Render the node using default renderer instead of the one in `context`. - - We don't use `RenderContext.with_default_renderer_for` because that - changes the default renderer in context, where it's applied - recursively to render functions of children. - """ - syntax_type = node.type - text = DEFAULT_RENDERERS[syntax_type](node, context) - for postprocessor in context.postprocessors.get(syntax_type, ()): - text = postprocessor(text, node, context) - return text - - -def _is_task_list_item(node: RenderTreeNode) -> bool: - assert node.type == "list_item" # noqa: S101 - classes = node.attrs.get("class", "") - assert isinstance(classes, str) # noqa: S101 - return "task-list-item" in classes - - -def _list_item_renderer(node: RenderTreeNode, context: RenderContext) -> str: - if not _is_task_list_item(node): - return _render_with_default_renderer(node, context) - - # Tasklists extension makes a bit weird token stream where - # tasks are annotated by html. We need to remove the HTML. - paragraph_node = node.children[0] - inline_node = paragraph_node.children[0] - assert inline_node.type == "inline" # noqa: S101 - assert inline_node.children, "inline token must have children" # noqa: S101 - html_inline_node = inline_node.children[0] - assert 'class="task-list-item-checkbox"' in html_inline_node.content # noqa: S101 - - # This is naughty, shouldn't mutate and rely on `.remove` here - inline_node.children.remove(html_inline_node) - - checkmark = "x" if 'checked="checked"' in html_inline_node.content else " " - - text = _render_with_default_renderer(node, context) - - if context.do_wrap: - wrap_mode = context.options["mdformat"]["wrap"] - if isinstance(wrap_mode, int): - text = text[4:] # Remove the "xxxx" added in `_postprocess_inline` - # Strip leading space chars (numeric representations) - text = re.sub(r"^( )+", "", text) - text = text.lstrip() - return f"[{checkmark}] {text}" - - -def _postprocess_inline(text: str, node: RenderTreeNode, context: RenderContext) -> str: - """Postprocess inline tokens. - - Fix word wrap of the first line in a task list item. It should be - wrapped narrower than normal because of the "[ ] " prefix that - indicates a task list item. We fool word wrap by prefixing an - unwrappable dummy string of the same length. This prefix needs to be - later removed (in `_list_item_renderer`). - """ - if not context.do_wrap: - return text - wrap_mode = context.options["mdformat"]["wrap"] - if not isinstance(wrap_mode, int): - return text - if ( - node.parent # noqa: PLR0916 - and node.parent.type == "paragraph" - and not node.parent.previous_sibling - and node.parent.parent - and node.parent.parent.type == "list_item" - and _is_task_list_item(node.parent.parent) - ): - text = text.lstrip("\x00") - text = f"xxxx{text.lstrip()}" - return text - - -def _link_renderer(node: RenderTreeNode, context: RenderContext) -> str: - """Extend the default link renderer to handle linkify links.""" - if node.markup == "linkify": - autolink_url = node.attrs["href"] - assert isinstance(autolink_url, str) # noqa: S101 - startswith_scheme = RE_COMMONMARK_URL_SCHEME.match(autolink_url) - if startswith_scheme and not node.children[0].content.startswith( - startswith_scheme.group(), - ): - autolink_url = autolink_url.split(":", maxsplit=1)[1] - if autolink_url.startswith("//"): - autolink_url = autolink_url[2:] - return autolink_url - return _render_with_default_renderer(node, context) - - -def _escape_text( - text: str, - node: RenderTreeNode, # noqa: ARG001 - context: RenderContext, # noqa: ARG001 -) -> str: - # Escape strikethroughs - return text.replace("~~", "\\~~") - - -RENDERERS = { - "s": _strikethrough_renderer, - "list_item": _list_item_renderer, - "link": _link_renderer, -} -POSTPROCESSORS = { - "text": _escape_text, - "inline": _postprocess_inline, -} diff --git a/mdformat_mkdocs/plugin.py b/mdformat_mkdocs/plugin.py index e546889..335b29e 100644 --- a/mdformat_mkdocs/plugin.py +++ b/mdformat_mkdocs/plugin.py @@ -10,7 +10,6 @@ from mdformat.renderer.typing import Postprocess, Render from mdformat_admon import RENDERERS as ADMON_RENDERS # type: ignore[import-untyped] -from ._copy_of_mdformat_gfm import GFM_POSTPROCESSORS, GFM_RENDERERS, gfm_update_mdit from ._normalize_list import normalize_list as unbounded_normalize_list from ._postprocess_inline import postprocess_inline from .mdit_plugins import content_tabs_plugin, mkdocs_admon_plugin @@ -44,9 +43,6 @@ def update_mdit(mdit: MarkdownIt) -> None: False, ) - # HACK: Only temporary pending the mdformat-gfm release - gfm_update_mdit(mdit) - # A mapping from `RenderTreeNode.type` to a `Render` function that can # render the given `RenderTreeNode` type. These override the default @@ -56,7 +52,6 @@ def update_mdit(mdit: MarkdownIt) -> None: "admonition_mkdocs_title": ADMON_RENDERS["admonition_title"], "content_tab_mkdocs": ADMON_RENDERS["admonition"], "content_tab_mkdocs_title": ADMON_RENDERS["admonition_title"], - **GFM_RENDERERS, # HACK: Only temporary pending the mdformat-gfm release } @@ -79,5 +74,4 @@ def check_if_align_semantic_breaks_in_lists() -> bool: "bullet_list": normalize_list, "inline": postprocess_inline, "ordered_list": normalize_list, - **GFM_POSTPROCESSORS, # HACK: Only temporary pending the mdformat-gfm release } diff --git a/pyproject.toml b/pyproject.toml index 4da609c..c9fbfa9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,10 +19,8 @@ requires-python = ">=3.8.4" dependencies = [ "mdformat >= 0.7.16", "mdformat-admon >= 2.0.1", - "more-itertools >= 10.2.0", - # "mdformat-gfm >= 0.4.0", TODO: Pending release (https://github.com/hukkin/mdformat-gfm/issues/31) - "markdown-it-py[linkify] >= 3.0.0 ", # HACK: Only temporary pending the mdformat-gfm release - "mdformat-tables >= 0.4.1", # HACK: Only temporary pending the mdformat-gfm release + "mdformat-gfm >= 0.3.6", + "more-itertools >= 10.2.0" ] dynamic = ["version", "description"] diff --git a/tests/fixtures-semantic-indent.md b/tests/fixtures-semantic-indent.md index 702e54a..7145625 100644 --- a/tests/fixtures-semantic-indent.md +++ b/tests/fixtures-semantic-indent.md @@ -258,9 +258,9 @@ Table |:---------------|---------:|:---------------------| | Name | 2| | . -| Label | Rating | Comment | -| :---- | -----: | :--------------- | -| Name | 2 | | +| Label | Rating | Comment | +|:---------------|---------:|:---------------------| +| Name | 2| | . Floating Link @@ -306,8 +306,8 @@ Task List / Check List (WARN: escaping is prevented by mdformat-gfm. Tested by p - [x] #739 - [ ] Add delight to the experience when all tasks are complete :tada: . -- [x] #739 - - [ ] Add delight to the experience when all tasks are complete :tada: +- \[x\] #739 + - \[ \] Add delight to the experience when all tasks are complete :tada: . Footnotes (WARN: escaping is prevented by mdformat-gfm. Tested by py#-hook) diff --git a/tests/format/fixtures/text.md b/tests/format/fixtures/text.md index 76db07b..59cde0c 100644 --- a/tests/format/fixtures/text.md +++ b/tests/format/fixtures/text.md @@ -251,15 +251,15 @@ Nested semantic lines (https://github.com/KyleKing/mdformat-mkdocs/issues/7) . -Table (with GFM formatting) +Table . | Label | Rating | Comment | |:---------------|---------:|:---------------------| | Name | 2| | . -| Label | Rating | Comment | -| :---- | -----: | :--------------- | -| Name | 2 | | +| Label | Rating | Comment | +|:---------------|---------:|:---------------------| +| Name | 2| | . Floating Link @@ -300,13 +300,13 @@ Headings ###### \[h6\] The smallest heading . -Task List / Check List (temporarily fixed with mdformat-gfm HACK) +Task List / Check List (WARN: escaping is prevented by mdformat-gfm. Tested by py#-hook) . - [x] #739 - [ ] Add delight to the experience when all tasks are complete :tada: . -- [x] #739 - - [ ] Add delight to the experience when all tasks are complete :tada: +- \[x\] #739 + - \[ \] Add delight to the experience when all tasks are complete :tada: . Footnotes (WARN: escaping is prevented by mdformat-gfm. Tested by py#-hook) diff --git a/tests/pre-commit-test-numbered.md b/tests/pre-commit-test-numbered.md index 86722c6..612ec1d 100644 --- a/tests/pre-commit-test-numbered.md +++ b/tests/pre-commit-test-numbered.md @@ -6,6 +6,6 @@ list item 2 2. If you store artifacts in the repository, you need to remember to - compile the application before every - commit. + compile the application before + every commit. 3. Compiled application. diff --git a/tests/test_wrap.py b/tests/test_wrap.py index dad76fa..c9f6212 100644 --- a/tests/test_wrap.py +++ b/tests/test_wrap.py @@ -25,7 +25,8 @@ # Content - Test Testing Test Testing Test Testing - Test Testing Test Testing Test Testing + Test Testing Test Testing Test + Testing - Test Testing Test Testing Test Testing Test Testing Test Testing Test Testing Test Testing Test @@ -58,7 +59,8 @@ # Content - Test Testing Test Testing Test Testing - Test Testing Test Testing Test Testing + Test Testing Test Testing Test + Testing - Test Testing Test Testing Test Testing Test Testing Test Testing Test Testing Test Testing Test