From 076160e2813b9c77a50f92f5d26ed9a1b9c59413 Mon Sep 17 00:00:00 2001 From: Kiran Jonnalagadda Date: Wed, 28 Feb 2024 11:57:12 +0530 Subject: [PATCH 1/3] Revise Markdown-It plugin imports --- funnel/utils/markdown/base.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/funnel/utils/markdown/base.py b/funnel/utils/markdown/base.py index f785b9b94..8b64cdb85 100644 --- a/funnel/utils/markdown/base.py +++ b/funnel/utils/markdown/base.py @@ -1,5 +1,11 @@ """Markdown parser and config profiles.""" +# The `mdit_py_plugins` package does not use `__all__` to explicitly export symbols, so +# Pyright complains that we're not importing from the correct locations. We are using +# the documented API, so we must silence Pyright here: + +# pyright: reportPrivateImportUsage=false + from __future__ import annotations from collections.abc import Callable, Iterable, Mapping @@ -8,12 +14,16 @@ from markdown_it import MarkdownIt from markupsafe import Markup -from mdit_py_plugins import anchors, container, deflist, footnote, tasklists +from mdit_py_plugins.anchors import anchors_plugin +from mdit_py_plugins.container import container_plugin +from mdit_py_plugins.deflist import deflist_plugin +from mdit_py_plugins.footnote import footnote_plugin +from mdit_py_plugins.tasklists import tasklists_plugin from coaster.utils import make_name from coaster.utils.text import normalize_spaces_multiline -from .mdit_plugins import ( # toc_plugin, +from .mdit_plugins import ( abbr_plugin, block_code_extend_plugin, del_plugin, @@ -155,11 +165,11 @@ def render(self, text: str | None) -> Markup | None: MarkdownPlugin.register('abbr', abbr_plugin) -MarkdownPlugin.register('deflists', deflist.deflist_plugin) -MarkdownPlugin.register('footnote', footnote.footnote_plugin) +MarkdownPlugin.register('deflists', deflist_plugin) +MarkdownPlugin.register('footnote', footnote_plugin) MarkdownPlugin.register( 'heading_anchors', - anchors.anchors_plugin, + anchors_plugin, { 'min_level': 1, 'max_level': 6, @@ -177,7 +187,7 @@ def render(self, text: str | None) -> Markup | None: MarkdownPlugin.register( 'tasklists', - tasklists.tasklists_plugin, + tasklists_plugin, {'enabled': True, 'label': True, 'label_after': False}, ) MarkdownPlugin.register('ins', ins_plugin) @@ -188,7 +198,7 @@ def render(self, text: str | None) -> Markup | None: MarkdownPlugin.register( 'tab_container', - container.container_plugin, + container_plugin, {'name': 'tab', 'marker': ':', 'render': render_tab}, ) MarkdownPlugin.register('markmap', embeds_plugin, {'name': 'markmap'}) From 8b906a37d3dd4a9a9a7b344c5a68e666cc53f088 Mon Sep 17 00:00:00 2001 From: Kiran Jonnalagadda Date: Tue, 5 Mar 2024 13:59:50 +0530 Subject: [PATCH 2/3] Reproduce init call sig in register classmethod --- funnel/utils/markdown/base.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/funnel/utils/markdown/base.py b/funnel/utils/markdown/base.py index 8b64cdb85..5e95d66e2 100644 --- a/funnel/utils/markdown/base.py +++ b/funnel/utils/markdown/base.py @@ -63,11 +63,13 @@ class MarkdownPlugin: config: dict[str, Any] | None = None @classmethod - def register(cls, name: str, *args: Any, **kwargs: Any) -> Self: + def register( + cls, name: str, func: Callable, config: dict[str, Any] | None = None + ) -> Self: """Create a new instance and add it to the registry.""" if name in cls.registry: raise NameError(f"MarkdownPlugin {name} has already been registered") - obj = cls(name, *args, **kwargs) + obj = cls(name, func, config) cls.registry[name] = obj return obj From 6009a02cc2de9650f4c3cb642c02c634bc1ff9f0 Mon Sep 17 00:00:00 2001 From: Kiran Jonnalagadda Date: Mon, 22 Apr 2024 14:22:46 +0530 Subject: [PATCH 3/3] Add type hints where missing --- .../markdown/mdit_plugins/block_code_ext.py | 8 ++--- funnel/utils/markdown/mdit_plugins/del_tag.py | 8 ++--- funnel/utils/markdown/mdit_plugins/embeds.py | 6 ++-- .../markdown/mdit_plugins/footnote_ext.py | 6 ++-- funnel/utils/markdown/mdit_plugins/ins_tag.py | 8 ++--- .../utils/markdown/mdit_plugins/mark_tag.py | 8 ++--- funnel/utils/markdown/mdit_plugins/sub_tag.py | 8 ++--- funnel/utils/markdown/mdit_plugins/sup_tag.py | 8 ++--- funnel/utils/markdown/mdit_plugins/toc.py | 18 +++++------ funnel/utils/markdown/tabs.py | 30 ++++++++++++------- 10 files changed, 58 insertions(+), 50 deletions(-) diff --git a/funnel/utils/markdown/mdit_plugins/block_code_ext.py b/funnel/utils/markdown/mdit_plugins/block_code_ext.py index c02cf170c..fe87ae0dd 100644 --- a/funnel/utils/markdown/mdit_plugins/block_code_ext.py +++ b/funnel/utils/markdown/mdit_plugins/block_code_ext.py @@ -2,13 +2,13 @@ from __future__ import annotations -from collections.abc import MutableMapping, Sequence +from collections.abc import Sequence from typing import Any from markdown_it import MarkdownIt from markdown_it.renderer import RendererHTML from markdown_it.token import Token -from markdown_it.utils import OptionsDict +from markdown_it.utils import EnvType, OptionsDict __all__ = ['block_code_extend_plugin'] @@ -18,7 +18,7 @@ def fence( tokens: Sequence[Token], idx: int, options: OptionsDict, - env: MutableMapping, + env: EnvType, ) -> str: output = RendererHTML.fence(renderer, tokens, idx, options, env) output = output.replace('
', '
')
@@ -30,7 +30,7 @@ def code_block(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     output = RendererHTML.code_block(renderer, tokens, idx, options, env)
     output = output.replace('
', '
')
diff --git a/funnel/utils/markdown/mdit_plugins/del_tag.py b/funnel/utils/markdown/mdit_plugins/del_tag.py
index 6a1583ae0..3ee5a4904 100644
--- a/funnel/utils/markdown/mdit_plugins/del_tag.py
+++ b/funnel/utils/markdown/mdit_plugins/del_tag.py
@@ -2,12 +2,12 @@
 
 from __future__ import annotations
 
-from collections.abc import MutableMapping, Sequence
+from collections.abc import Sequence
 
 from markdown_it import MarkdownIt
 from markdown_it.renderer import RendererHTML
 from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
+from markdown_it.utils import EnvType, OptionsDict
 
 __all__ = ['del_plugin']
 
@@ -17,7 +17,7 @@ def del_open(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
@@ -27,7 +27,7 @@ def del_close(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
diff --git a/funnel/utils/markdown/mdit_plugins/embeds.py b/funnel/utils/markdown/mdit_plugins/embeds.py
index ebea0444e..af786aed7 100644
--- a/funnel/utils/markdown/mdit_plugins/embeds.py
+++ b/funnel/utils/markdown/mdit_plugins/embeds.py
@@ -8,7 +8,7 @@
 from __future__ import annotations
 
 import re
-from collections.abc import MutableMapping, Sequence
+from collections.abc import Sequence
 from math import floor
 
 from markdown_it import MarkdownIt
@@ -16,7 +16,7 @@
 from markdown_it.renderer import RendererHTML
 from markdown_it.rules_block import StateBlock
 from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
+from markdown_it.utils import EnvType, OptionsDict
 
 __all__ = ['embeds_plugin']
 
@@ -43,7 +43,7 @@ def render(
         tokens: Sequence[Token],
         idx: int,
         options: OptionsDict,
-        env: MutableMapping,
+        env: EnvType,
     ) -> str:
         token = tokens[idx]
         content = md.utils.escapeHtml(token.content)
diff --git a/funnel/utils/markdown/mdit_plugins/footnote_ext.py b/funnel/utils/markdown/mdit_plugins/footnote_ext.py
index 85bd41d02..939275d79 100644
--- a/funnel/utils/markdown/mdit_plugins/footnote_ext.py
+++ b/funnel/utils/markdown/mdit_plugins/footnote_ext.py
@@ -2,13 +2,13 @@
 
 from __future__ import annotations
 
-from collections.abc import MutableMapping, Sequence
+from collections.abc import Sequence
 from typing import Any
 
 from markdown_it import MarkdownIt
 from markdown_it.renderer import RendererHTML
 from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
+from markdown_it.utils import EnvType, OptionsDict
 from mdit_py_plugins.footnote.index import render_footnote_caption
 
 __all__ = ['footnote_extend_plugin']
@@ -19,7 +19,7 @@ def caption(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     output = render_footnote_caption(renderer, tokens, idx, options, env)
     return output.replace('[', '').replace(']', '')
diff --git a/funnel/utils/markdown/mdit_plugins/ins_tag.py b/funnel/utils/markdown/mdit_plugins/ins_tag.py
index d6076cfa6..72aedf4a9 100644
--- a/funnel/utils/markdown/mdit_plugins/ins_tag.py
+++ b/funnel/utils/markdown/mdit_plugins/ins_tag.py
@@ -6,14 +6,14 @@
 
 from __future__ import annotations
 
-from collections.abc import MutableMapping, Sequence
+from collections.abc import Sequence
 
 from markdown_it import MarkdownIt
 from markdown_it.renderer import RendererHTML
 from markdown_it.rules_inline import StateInline
 from markdown_it.rules_inline.state_inline import Delimiter
 from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
+from markdown_it.utils import EnvType, OptionsDict
 
 __all__ = ['ins_plugin']
 
@@ -124,7 +124,7 @@ def ins_open(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
@@ -134,7 +134,7 @@ def ins_close(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
diff --git a/funnel/utils/markdown/mdit_plugins/mark_tag.py b/funnel/utils/markdown/mdit_plugins/mark_tag.py
index c21801304..62aebe9df 100644
--- a/funnel/utils/markdown/mdit_plugins/mark_tag.py
+++ b/funnel/utils/markdown/mdit_plugins/mark_tag.py
@@ -6,14 +6,14 @@
 
 from __future__ import annotations
 
-from collections.abc import MutableMapping, Sequence
+from collections.abc import Sequence
 
 from markdown_it import MarkdownIt
 from markdown_it.renderer import RendererHTML
 from markdown_it.rules_inline import StateInline
 from markdown_it.rules_inline.state_inline import Delimiter
 from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
+from markdown_it.utils import EnvType, OptionsDict
 
 __all__ = ['mark_plugin']
 
@@ -141,7 +141,7 @@ def mark_open(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
@@ -151,7 +151,7 @@ def mark_close(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
diff --git a/funnel/utils/markdown/mdit_plugins/sub_tag.py b/funnel/utils/markdown/mdit_plugins/sub_tag.py
index 582e131be..dba83dbc3 100644
--- a/funnel/utils/markdown/mdit_plugins/sub_tag.py
+++ b/funnel/utils/markdown/mdit_plugins/sub_tag.py
@@ -8,13 +8,13 @@
 from __future__ import annotations
 
 import re
-from collections.abc import MutableMapping, Sequence
+from collections.abc import Sequence
 
 from markdown_it import MarkdownIt
 from markdown_it.renderer import RendererHTML
 from markdown_it.rules_inline import StateInline
 from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
+from markdown_it.utils import EnvType, OptionsDict
 
 __all__ = ['sub_plugin']
 
@@ -82,7 +82,7 @@ def sub_open(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
@@ -92,7 +92,7 @@ def sub_close(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
diff --git a/funnel/utils/markdown/mdit_plugins/sup_tag.py b/funnel/utils/markdown/mdit_plugins/sup_tag.py
index c60f97741..cbf76f31f 100644
--- a/funnel/utils/markdown/mdit_plugins/sup_tag.py
+++ b/funnel/utils/markdown/mdit_plugins/sup_tag.py
@@ -8,13 +8,13 @@
 from __future__ import annotations
 
 import re
-from collections.abc import MutableMapping, Sequence
+from collections.abc import Sequence
 
 from markdown_it import MarkdownIt
 from markdown_it.renderer import RendererHTML
 from markdown_it.rules_inline import StateInline
 from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
+from markdown_it.utils import EnvType, OptionsDict
 
 __all__ = ['sup_plugin']
 
@@ -82,7 +82,7 @@ def sup_open(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
@@ -92,7 +92,7 @@ def sup_close(
     tokens: Sequence[Token],
     idx: int,
     options: OptionsDict,
-    env: MutableMapping,
+    env: EnvType,
 ) -> str:
     return ''
 
diff --git a/funnel/utils/markdown/mdit_plugins/toc.py b/funnel/utils/markdown/mdit_plugins/toc.py
index 1c7bb27a6..646627fb6 100644
--- a/funnel/utils/markdown/mdit_plugins/toc.py
+++ b/funnel/utils/markdown/mdit_plugins/toc.py
@@ -13,7 +13,7 @@
 from __future__ import annotations
 
 import re
-from collections.abc import MutableMapping, Sequence
+from collections.abc import Sequence
 from functools import reduce
 from typing import Any, TypedDict
 
@@ -22,7 +22,7 @@
 from markdown_it.rules_core import StateCore
 from markdown_it.rules_inline import StateInline
 from markdown_it.token import Token
-from markdown_it.utils import OptionsDict
+from markdown_it.utils import EnvType, OptionsDict
 
 from coaster.utils import make_name
 
@@ -229,8 +229,8 @@ def toc_open(
         tokens: Sequence[Token],
         idx: int,
         options: OptionsDict,
-        env: MutableMapping,
-    ):
+        env: EnvType,
+    ) -> str:
         open_html = f'
' if opts['container_header_html'] is not None: open_html = open_html + opts['container_header_html'] @@ -241,8 +241,8 @@ def toc_close( tokens: Sequence[Token], idx: int, options: OptionsDict, - env: MutableMapping, - ): + env: EnvType, + ) -> str: footer = '' if opts['container_footer_html']: footer = opts['container_footer_html'] @@ -253,14 +253,14 @@ def toc_body( tokens: Sequence[Token], idx: int, options: OptionsDict, - env: MutableMapping, - ): + env: EnvType, + ) -> str: items = find_elements(opts['include_level'], env['gstate'].tokens, opts) toc = items_to_tree(items) html = toc_item_to_html(toc, opts, md) return html - def grab_state(state: StateCore): + def grab_state(state: StateCore) -> None: state.env['gstate'] = state md.core.ruler.push('grab_state', grab_state) diff --git a/funnel/utils/markdown/tabs.py b/funnel/utils/markdown/tabs.py index 145426955..968324510 100644 --- a/funnel/utils/markdown/tabs.py +++ b/funnel/utils/markdown/tabs.py @@ -1,4 +1,4 @@ -"""MDIT renderer and helpers for tabs.""" +"""Markdown-It renderer and helpers for tabs.""" from __future__ import annotations @@ -6,12 +6,20 @@ from functools import reduce from typing import Any, ClassVar +from markdown_it.renderer import RendererProtocol from markdown_it.token import Token +from markdown_it.utils import EnvType, OptionsDict __all__ = ['render_tab'] -def render_tab(self, tokens: list[Token], idx, _options, env): +def render_tab( + _renderer: RendererProtocol, + tokens: list[Token], + idx: int, + _options: OptionsDict, + env: EnvType, +) -> str: if 'manager' not in env: env['manager'] = TabsManager(tokens) @@ -40,7 +48,7 @@ def flatten(self) -> list[TabNode]: return tabs @property - def html_open(self): + def html_open(self) -> str: items_html = ''.join([item.html_tab_item for item in self.children]) return ( f'
' @@ -52,7 +60,7 @@ def tabset_id(self) -> str: return 'md-tabset-' + self._tabset_id @tabset_id.setter - def tabset_id(self, value) -> None: + def tabset_id(self, value: str) -> None: self._tabset_id = value @@ -76,7 +84,7 @@ class TabNode: + ' aria-controls="{tab_id}-panel"{accessibility}>{title}' ) - def _class_attr(self, classes=None): + def _class_attr(self, classes: list[str] | None = None) -> str: if classes is None: classes = [] classes = classes + self._active_class @@ -85,7 +93,7 @@ def _class_attr(self, classes=None): return f' class="{" ".join(classes)}"' if len(classes) > 0 else '' @property - def _item_aria(self): + def _item_aria(self) -> str: if self.is_first: return ' tabindex="0" aria-selected="true"' return ' tabindex="-1" aria-selected="false"' @@ -98,11 +106,11 @@ def flatten(self) -> list[TabsetNode]: return tabsets @property - def _active_class(self): + def _active_class(self) -> list[str]: return ['md-tab-active'] if self.is_first else [] @property - def title(self): + def title(self) -> str: tab_title = ' '.join(self.info.strip().split()[1:]) return tab_title or 'Tab ' + str(self.parent.children.index(self) + 1) @@ -111,7 +119,7 @@ def tab_id(self) -> str: return 'md-tab-' + self._tab_id @tab_id.setter - def tab_id(self, value) -> None: + def tab_id(self, value: str) -> None: self._tab_id = value @property @@ -137,7 +145,7 @@ def html_close(self) -> str: return self._closing + (self.parent.html_close if self.is_last else '') @property - def html_tab_item(self): + def html_tab_item(self) -> str: return self._item_html.format( tab_id=self.tab_id, tabset_id=self.parent.tabset_id, @@ -211,7 +219,7 @@ def _get_tab_tokens(self, tokens: list[Token]) -> list[dict[str, Any]]: ] def _tab_token_pair( - self, tab_tokens: list[dict[str, Any]], start=0 + self, tab_tokens: list[dict[str, Any]], start: int = 0 ) -> tuple[int, int] | None: i = 1 while i < len(tab_tokens):