Просмотр исходного кода

Support custom styling for code in markdown (#1844)

Nikhil Rao 1 год назад
Родитель
Сommit
3113aecb30
3 измененных файлов с 46 добавлено и 27 удалено
  1. 1 10
      reflex/components/tags/tag.py
  2. 27 17
      reflex/components/typography/markdown.py
  3. 18 0
      reflex/utils/format.py

+ 1 - 10
reflex/components/tags/tag.py

@@ -51,16 +51,7 @@ class Tag(Base):
         Returns:
             The formatted props list.
         """
-        # If there are no props, return an empty string.
-        if len(self.props) == 0:
-            return []
-
-        # Format all the props.
-        return [
-            f"{name}={format.format_prop(prop)}"
-            for name, prop in sorted(self.props.items())
-            if prop is not None
-        ] + [str(prop) for prop in self.special_props]
+        return format.format_props(*self.special_props, **self.props)
 
     def add_props(self, **kwargs: Optional[Any]) -> Tag:
         """Add props to the tag.

+ 27 - 17
reflex/components/typography/markdown.py

@@ -91,6 +91,7 @@ class Markdown(Component):
         return super().create(src, **props)
 
     def _get_imports(self):
+        # Import here to avoid circular imports.
         from reflex.components.datadisplay.code import Code, CodeBlock
 
         imports = super()._get_imports()
@@ -118,30 +119,39 @@ class Markdown(Component):
         return imports
 
     def _render(self):
+        # Import here to avoid circular imports.
+        from reflex.components.datadisplay.code import Code, CodeBlock
         from reflex.components.tags.tag import Tag
 
+        def format_props(tag):
+            return "".join(
+                Tag(
+                    name="", props=Style(self.custom_styles.get(tag, {}))
+                ).format_props()
+            )
+
         components = {
-            tag: f"{{({{node, ...props}}) => <{(component().tag)} {{...props}} {''.join(Tag(name='', props=Style(self.custom_styles.get(tag, {}))).format_props())} />}}"
+            tag: f"{{({{node, ...props}}) => <{(component().tag)} {{...props}} {format_props(tag)} />}}"
             for tag, component in components_by_tag.items()
         }
         components[
             "code"
-        ] = """{({node, inline, className, children, ...props}) =>
-                    {
-        const match = (className || '').match(/language-(?<lang>.*)/);
-        return !inline ? (
-          <Prism
-            children={String(children).replace(/\n$/, '')}
-            language={match ? match[1] : ''}
-            theme={light}
-            {...props}
-          />
-        ) : (
-          <Code {...props}>
-            {children}
-          </Code>
-        );
-      }}""".replace(
+        ] = f"""{{({{node, inline, className, children, ...props}}) => {{
+    const match = (className || '').match(/language-(?<lang>.*)/);
+    return !inline ? (
+        <{CodeBlock().tag}
+        children={{String(children).replace(/\n$/, '')}}
+        language={{match ? match[1] : ''}}
+        style={{light}}
+        {{...props}}
+        {format_props("pre")}
+        />
+    ) : (
+        <{Code.create().tag} {{...props}} {format_props("code")}>
+        {{children}}
+        </{Code.create().tag}>
+    );
+      }}}}""".replace(
             "\n", " "
         )
 

+ 18 - 0
reflex/utils/format.py

@@ -327,6 +327,24 @@ def format_prop(
     return wrap(prop, "{", check_first=False)
 
 
+def format_props(*single_props, **key_value_props) -> list[str]:
+    """Format the tag's props.
+
+    Args:
+        single_props: Props that are not key-value pairs.
+        key_value_props: Props that are key-value pairs.
+
+    Returns:
+        The formatted props list.
+    """
+    # Format all the props.
+    return [
+        f"{name}={format_prop(prop)}"
+        for name, prop in sorted(key_value_props.items())
+        if prop is not None
+    ] + [str(prop) for prop in sorted(single_props)]
+
+
 def get_event_handler_parts(handler: EventHandler) -> tuple[str, str]:
     """Get the state and function name of an event handler.