Clean up tags.

This commit is contained in:
Nikhil Rao 2022-11-18 13:04:16 -08:00
parent b1c10d3ada
commit 2008417bd7
6 changed files with 35 additions and 34 deletions

View File

@ -15,7 +15,7 @@ class Link(Component):
rel: Var[str]
def _render(self) -> Tag:
return Tag(name="link").add_attrs(
return Tag(name="link").add_props(
href=self.href,
rel=self.rel,
)

View File

@ -30,7 +30,7 @@ class Component(Base, ABC):
# The style of the component.
style: Style = Style()
# A mapping of event chains to event triggers.
# A mapping from event triggers to event chains.
event_triggers: Dict[str, EventChain] = {}
# The library that the component is based on.
@ -114,10 +114,9 @@ class Component(Base, ABC):
del kwargs[key]
# Add style props to the component.
style = kwargs["style"] if "style" in kwargs else {}
kwargs["style"] = Style(
{
**style,
**kwargs.get("style", {}),
**{attr: value for attr, value in kwargs.items() if attr not in fields},
}
)
@ -220,14 +219,17 @@ class Component(Base, ABC):
Returns:
The tag to render.
"""
tag = Tag(name=self.tag).add_attrs(
**{attr: getattr(self, attr) for attr in self.get_props()}
)
# Create the base tag.
tag = Tag(name=self.tag)
# Add component props to the tag.
props = {attr: getattr(self, attr) for attr in self.get_props()}
# Special case for props named `type_`.
if hasattr(self, "type_"):
tag.add_attrs(type=getattr(self, "type_"))
return tag
props["type"] = getattr(self, "type_")
return tag.add_props(**props)
@classmethod
def get_props(cls) -> Set[str]:
@ -297,7 +299,7 @@ class Component(Base, ABC):
"""
tag = self._render()
return str(
tag.add_attrs(**self.event_triggers, key=self.key, sx=self.style).set(
tag.add_props(**self.event_triggers, key=self.key, sx=self.style).set(
contents=utils.join(
[str(tag.contents)] + [child.render() for child in self.children]
),

View File

@ -17,7 +17,7 @@ class Box(ChakraComponent):
return (
super()
._render()
.add_attrs(
.add_props(
**{
"as": self.element,
}

View File

@ -7,7 +7,6 @@ import os
import re
from typing import Any, Dict, Optional, Union
import pydantic
from plotly.graph_objects import Figure
from plotly.io import to_json
@ -23,8 +22,8 @@ class Tag(Base):
# The name of the tag.
name: str = ""
# The attributes of the tag.
attrs: Dict[str, Any] = {}
# The props of the tag.
props: Dict[str, Any] = {}
# The inner contents of the tag.
contents: str = ""
@ -36,10 +35,10 @@ class Tag(Base):
*args: Args to initialize the tag.
**kwargs: Kwargs to initialize the tag.
"""
# Convert any attrs to properties.
if "attrs" in kwargs:
kwargs["attrs"] = {
name: Var.create(value) for name, value in kwargs["attrs"].items()
# Convert any props to vars.
if "props" in kwargs:
kwargs["props"] = {
name: Var.create(value) for name, value in kwargs["props"].items()
}
super().__init__(*args, **kwargs)
@ -109,21 +108,21 @@ class Tag(Base):
assert isinstance(value, str), "The value must be a string."
return utils.wrap(value, "{", check_first=False)
def format_attrs(self) -> str:
def format_props(self) -> str:
"""Format a dictionary of attributes.
Returns:
The formatted attributes.
"""
# If there are no attributes, return an empty string.
if len(self.attrs) == 0:
if len(self.props) == 0:
return ""
# Get the string representation of all the attributes joined.
# We need a space at the beginning for formatting.
return os.linesep.join(
f"{name}={self.format_attr_value(value)}"
for name, value in self.attrs.items()
for name, value in self.props.items()
if value is not None
)
@ -134,22 +133,22 @@ class Tag(Base):
The React code to render the tag.
"""
# Get the tag attributes.
attrs_str = self.format_attrs()
if len(attrs_str) > 0:
attrs_str = " " + attrs_str
props_str = self.format_props()
if len(props_str) > 0:
props_str = " " + props_str
if len(self.contents) == 0:
# If there is no inner content, we don't need a closing tag.
tag_str = utils.wrap(f"{self.name}{attrs_str}/", "<")
tag_str = utils.wrap(f"{self.name}{props_str}/", "<")
else:
# Otherwise wrap it in opening and closing tags.
open = utils.wrap(f"{self.name}{attrs_str}", "<")
open = utils.wrap(f"{self.name}{props_str}", "<")
close = utils.wrap(f"/{self.name}", "<")
tag_str = utils.wrap(self.contents, open, close)
return tag_str
def add_attrs(self, **kwargs: Optional[Any]) -> Tag:
def add_props(self, **kwargs: Optional[Any]) -> Tag:
"""Add attributes to the tag.
Args:
@ -158,7 +157,7 @@ class Tag(Base):
Returns:
The tag with the attributes added.
"""
self.attrs.update(
self.props.update(
{
utils.to_camel_case(name): attr
if utils._isinstance(attr, Union[EventChain, dict])
@ -169,7 +168,7 @@ class Tag(Base):
)
return self
def remove_attrs(self, *args: str) -> Tag:
def remove_props(self, *args: str) -> Tag:
"""Remove attributes from the tag.
Args:
@ -179,8 +178,8 @@ class Tag(Base):
The tag with the attributes removed.
"""
for name in args:
if name in self.attrs:
del self.attrs[name]
if name in self.props:
del self.props[name]
return self
@staticmethod

View File

@ -28,7 +28,7 @@ class Markdown(Component):
def _render(self):
tag = super()._render()
return tag.add_attrs(
return tag.add_props(
children=utils.wrap(str(self.src).strip(), "`"),
components={
"h1": "{({node, ...props}) => <Heading size='2xl' {...props} />}",

View File

@ -111,9 +111,9 @@ def test_is_valid_attr(attr: Var, valid: bool):
assert Tag.is_valid_attr(attr) == valid
def test_add_attrs():
def test_add_props():
"""Test that the attributes are added."""
tag = Tag().add_attrs(key="value", key2=42, invalid=None, invalid2={})
tag = Tag().add_props(key="value", key2=42, invalid=None, invalid2={})
assert tag.attrs["key"] == Var.create("value")
assert tag.attrs["key2"] == Var.create(42)
assert "invalid" not in tag.attrs