yaqwsx / PcbDraw

Convert your KiCAD board into a nicely looking 2D drawing suitable for pinout diagrams
MIT License
1.16k stars 91 forks source link

Support all major mistune versions #166

Closed smkent closed 7 months ago

smkent commented 7 months ago

This adds support for mistune 3.0.0 while preserving support for mistune 0.8.4 and 2.x

smkent commented 7 months ago

This should resolve https://github.com/yaqwsx/PcbDraw/issues/147 and https://github.com/yaqwsx/PcbDraw/issues/162.

yaqwsx commented 7 months ago

Thank you very much for your contribution!

set-soft commented 7 months ago

Does this really work? I tried mistune 3.0.2 and it doesn't work. The register_rule mechanism doesn't work anymore, in 3.0.2 it raises an exception saying its deprecated. We must use register. I also found that list and list_item now has more arguments. I'm currently trying this:

diff --git a/kibot/PcbDraw/populate.py b/kibot/PcbDraw/populate.py
index 1956e9c6..9943aaa2 100644
--- a/kibot/PcbDraw/populate.py
+++ b/kibot/PcbDraw/populate.py
@@ -10,20 +10,12 @@ from copy import deepcopy
 from itertools import chain
 from typing import List, Optional, Any, Tuple, Dict

-from . import mistune # type: ignore
-# The following try-catch is used to support mistune 0.8.4 and 2.x
-try:
-    from .mistune.plugins.table import plugin_table # type: ignore
-    from .mistune.plugins.footnotes import plugin_footnotes # type: ignore
-    InlineParser = mistune.inline_parser.InlineParser
-    HTMLRenderer = mistune.renderers.HTMLRenderer
-except ModuleNotFoundError:
-    InlineParser = mistune.InlineLexer
-    HTMLRenderer = mistune.Renderer
 from . import pybars # type: ignore
 import yaml

 from . import mdrenderer
+from .mistune_shim import mistune  # type: ignore
+from .mistune_shim import HTMLRenderer, InlineParser, plugin_footnotes, plugin_table
 from .plot import find_data_file, get_global_datapaths

 PKG_BASE = os.path.dirname(__file__)
@@ -34,6 +26,15 @@ def parse_pcbdraw(lexer: Any, m: re.Match, state: Any=None) -> Any:
     components = list(map(lambda x: x.strip(), components.split(",")))
     return 'pcbdraw', side, components

+
+def parse_pcbdraw_v3(inline, m, state):
+    text = m.group('scomp')
+    side, components = text.split("|")
+    components = list(map(lambda x: x.strip(), components.split(",")))
+    state.append_token({'type': 'pcbdraw_v3', 'raw': text, 'attrs': {'side': side, 'components': components}})
+    return m.end()
+
+
 class PcbDrawInlineLexer(InlineParser): # type: ignore
     def __init__(self, renderer: Any, **kwargs: Any) -> None:
         super(PcbDrawInlineLexer, self).__init__(renderer, **kwargs)
@@ -41,11 +42,14 @@ class PcbDrawInlineLexer(InlineParser): # type: ignore

     def enable_pcbdraw(self) -> None:
         pcbdraw_pattern = (
-            r"\[\["                   # [[
-            r"([\s\S]+?\|[\s\S]+?)"   # side| component
-            r"\]\](?!\])"             # ]]
+            r"\[\["                           # [[
+            r"(?P<scomp>[\s\S]+?\|[\s\S]+?)"  # side| component
+            r"\]\](?!\])"                     # ]]
         )
-        if hasattr(self, 'register_rule'):
+        if hasattr(self, 'register'):
+            # mistune v3 API
+            self.register('pcbdraw', pcbdraw_pattern, parse_pcbdraw_v3, before='link')
+        elif hasattr(self, 'register_rule'):
             # mistune v2 API
             self.rules.insert(3, 'pcbdraw')
             self.register_rule('pcbdraw', pcbdraw_pattern, parse_pcbdraw)
@@ -101,6 +105,11 @@ def Renderer(BaseRenderer, initial_components: List[str], format: str): # type:
                 items.append(self.current_item)
             return items

+        def pcbdraw_v3(self, text, **attrs) -> str:
+            side = attrs['side']
+            components = attrs['components']
+            return self.pcbdraw(side, components)
+
         def pcbdraw(self, side: str, components: List[str]) -> str:
             self.active_side = side
             self.visited_components += components
@@ -153,19 +162,19 @@ def Renderer(BaseRenderer, initial_components: List[str], format: str): # type:
             self.append_comment(retval)
             return retval

-        def list(self, text: Any, ordered: bool, level: Any=None, start: Any=None) -> str:
+        def list(self, text: Any, ordered: bool, level: Any=None, start: Any=None, **attrs) -> str:
             if not text:
                 return ""
-            retval = super(Tmp, self).list(text, ordered, level, start)
+            retval = super(Tmp, self).list(text, ordered, level, start, **attrs)
             if level == 1:
                 # Add the result from the list when finished and only if not empty
                 self.append_comment(retval)
             return retval

-        def list_item(self, text: str, level: Any=None) -> str:
+        def list_item(self, text: str, level: Any=None, **attrs) -> str:
             if not self.found_step:
                 # If we don't have an image for this step assume this is a regular list
-                return super(Tmp, self).list_item(text, level)
+                return super(Tmp, self).list_item(text, level, **attrs)
             # Add a step
             step = {
                 "side": self.active_side,
@@ -203,12 +212,8 @@ def load_content(filename: str) -> Tuple[Optional[Dict[str, Any]], str]:
 def parse_content(renderer: Any, content: str) -> List[Dict[str, Any]]:
     lexer = PcbDrawInlineLexer(renderer)
     processor = mistune.Markdown(renderer=renderer, inline=lexer)
-    try:
-        plugin_table(processor)
-        plugin_footnotes(processor)
-    except NameError:
-        # Mistune v0.8.4 doesn't define the above functions
-        pass
+    plugin_table(processor)
+    plugin_footnotes(processor)
     processor(content)
     return renderer.output() # type: ignore
yaqwsx commented 7 months ago

It worked on a few (poor) tests I tried. It is broken. I'll fix it by only supporting Mistune 3.

set-soft commented 7 months ago

It worked on a few (poor) tests I tried. It is broken. I'll fix it by only supporting Mistune 3.

The above patch passed all my tests. Is against my forked code, but is simple to adapt. Looking at the current code list and list_item are slightly different in your code. But the idea of how to solve the extra arguments is the same.