Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENG-4010]Codeblock cleanup in markdown #4233

Merged
merged 21 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions reflex/.templates/jinja/web/pages/custom_component.js.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,6 @@
{% endfor %}

export const {{component.name}} = memo(({ {{-component.props|join(", ")-}} }) => {
{% if component.name == "CodeBlock" and "language" in component.props %}
if (language) {
(async () => {
try {
const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${language}`);
SyntaxHighlighter.registerLanguage(language, module.default);
} catch (error) {
console.error(`Error importing language module for ${language}:`, error);
}
})();


}
{% endif %}
{% for hook in component.hooks %}
{{ hook }}
{% endfor %}
Expand Down
82 changes: 45 additions & 37 deletions reflex/components/datadisplay/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
from reflex.components.component import Component, ComponentNamespace
from reflex.components.core.cond import color_mode_cond
from reflex.components.lucide.icon import Icon
from reflex.components.markdown.markdown import _LANGUAGE, MarkdownComponentMap
from reflex.components.radix.themes.components.button import Button
from reflex.components.radix.themes.layout.box import Box
from reflex.constants.colors import Color
from reflex.event import set_clipboard
from reflex.style import Style
from reflex.utils import console, format
from reflex.utils.imports import ImportDict, ImportVar
from reflex.utils.imports import ImportVar
from reflex.vars.base import LiteralVar, Var, VarData

LiteralCodeLanguage = Literal[
Expand Down Expand Up @@ -378,7 +379,7 @@ class Theme:
setattr(Theme, theme_name, getattr(Theme, theme_name)._replace(_var_type=Theme))


class CodeBlock(Component):
class CodeBlock(Component, MarkdownComponentMap):
"""A code block."""

library = "[email protected]"
Expand Down Expand Up @@ -417,39 +418,6 @@ class CodeBlock(Component):
# A custom copy button to override the default one.
copy_button: Optional[Union[bool, Component]] = None

def add_imports(self) -> ImportDict:
"""Add imports for the CodeBlock component.

Returns:
The import dict.
"""
imports_: ImportDict = {}

if (
self.language is not None
and (language_without_quotes := str(self.language).replace('"', ""))
in LiteralCodeLanguage.__args__ # type: ignore
):
imports_[
f"react-syntax-highlighter/dist/cjs/languages/prism/{language_without_quotes}"
] = [
ImportVar(
tag=format.to_camel_case(language_without_quotes),
is_default=True,
install=False,
)
]

return imports_

def _get_custom_code(self) -> Optional[str]:
if (
self.language is not None
and (language_without_quotes := str(self.language).replace('"', ""))
in LiteralCodeLanguage.__args__ # type: ignore
):
return f"{self.alias}.registerLanguage('{language_without_quotes}', {format.to_camel_case(language_without_quotes)})"

@classmethod
def create(
cls,
Expand Down Expand Up @@ -534,15 +502,55 @@ def _render(self):

theme = self.theme

out.add_props(style=theme).remove_props("theme", "code").add_props(
children=self.code
out.add_props(style=theme).remove_props("theme", "code", "language").add_props(
children=self.code, language=_LANGUAGE
)

return out

def _exclude_props(self) -> list[str]:
return ["can_copy", "copy_button"]

@classmethod
def _get_language_registration_hook(cls) -> str:
"""Get the hook to register the language.

Returns:
The hook to register the language.
"""
return f"""
if ({str(_LANGUAGE)}) {{
(async () => {{
try {{
const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${{{str(_LANGUAGE)}}}`);
SyntaxHighlighter.registerLanguage({str(_LANGUAGE)}, module.default);
}} catch (error) {{
console.error(`Error importing language module for ${{{str(_LANGUAGE)}}}:`, error);
}}
}})();
}}
"""

@classmethod
def get_component_map_custom_code(cls) -> str:
"""Get the custom code for the component.

Returns:
The custom code for the component.
"""
return cls._get_language_registration_hook()

def add_hooks(self) -> list[str | Var]:
"""Add hooks for the component.

Returns:
The hooks for the component.
"""
return [
f"const {str(_LANGUAGE)} = {str(self.language)}",
self._get_language_registration_hook(),
]


class CodeblockNamespace(ComponentNamespace):
"""Namespace for the CodeBlock component."""
Expand Down
8 changes: 5 additions & 3 deletions reflex/components/datadisplay/code.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import dataclasses
from typing import Any, ClassVar, Dict, Literal, Optional, Union, overload

from reflex.components.component import Component, ComponentNamespace
from reflex.components.markdown.markdown import MarkdownComponentMap
from reflex.constants.colors import Color
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
from reflex.utils.imports import ImportDict
from reflex.vars.base import Var

LiteralCodeLanguage = Literal[
Expand Down Expand Up @@ -349,8 +349,7 @@ for theme_name in dir(Theme):
continue
setattr(Theme, theme_name, getattr(Theme, theme_name)._replace(_var_type=Theme))

class CodeBlock(Component):
def add_imports(self) -> ImportDict: ...
class CodeBlock(Component, MarkdownComponentMap):
@overload
@classmethod
def create( # type: ignore
Expand Down Expand Up @@ -984,6 +983,9 @@ class CodeBlock(Component):
...

def add_style(self): ...
@classmethod
def get_component_map_custom_code(cls) -> str: ...
def add_hooks(self) -> list[str | Var]: ...

class CodeblockNamespace(ComponentNamespace):
themes = Theme
Expand Down
3 changes: 2 additions & 1 deletion reflex/components/datadisplay/shiki_code_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from reflex.components.core.cond import color_mode_cond
from reflex.components.el.elements.forms import Button
from reflex.components.lucide.icon import Icon
from reflex.components.markdown.markdown import MarkdownComponentMap
from reflex.components.props import NoExtrasAllowedProps
from reflex.components.radix.themes.layout.box import Box
from reflex.event import run_script, set_clipboard
Expand Down Expand Up @@ -528,7 +529,7 @@ def __init__(self, **kwargs):
super().__init__(**kwargs)


class ShikiCodeBlock(Component):
class ShikiCodeBlock(Component, MarkdownComponentMap):
"""A Code block."""

library = "/components/shiki/code"
Expand Down
3 changes: 2 additions & 1 deletion reflex/components/datadisplay/shiki_code_block.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ from typing import Any, Dict, Literal, Optional, Union, overload

from reflex.base import Base
from reflex.components.component import Component, ComponentNamespace
from reflex.components.markdown.markdown import MarkdownComponentMap
from reflex.components.props import NoExtrasAllowedProps
from reflex.event import BASE_STATE, EventType
from reflex.style import Style
Expand Down Expand Up @@ -350,7 +351,7 @@ class ShikiJsTransformer(ShikiBaseTransformers):
fns: list[FunctionStringVar]
style: Optional[Style]

class ShikiCodeBlock(Component):
class ShikiCodeBlock(Component, MarkdownComponentMap):
@overload
@classmethod
def create( # type: ignore
Expand Down
Loading
Loading