yeahyeahyeaheyaehehahwrggvdf
This commit is contained in:
parent
4ff8c37160
commit
afa0170041
3 changed files with 71 additions and 35 deletions
|
@ -1,7 +1,7 @@
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from typing import TYPE_CHECKING, Optional, Self
|
from typing import TYPE_CHECKING, Iterable, Optional, Self
|
||||||
|
|
||||||
from bs4 import BeautifulSoup, Tag
|
from bs4 import BeautifulSoup, Tag
|
||||||
from ..clonable import Clonable
|
from ..clonable import Clonable
|
||||||
|
@ -15,10 +15,67 @@ class ShadowRootMode(StrEnum):
|
||||||
Open = "open"
|
Open = "open"
|
||||||
Closed = "closed"
|
Closed = "closed"
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Node(Clonable):
|
class Node(Clonable):
|
||||||
_value: Tag
|
@property
|
||||||
|
def value(self): pass
|
||||||
|
|
||||||
|
def from_path(path: str) -> Self:
|
||||||
|
with open(path, "r") as f:
|
||||||
|
soup = BeautifulSoup(f.read(), 'html.parser')
|
||||||
|
nodes = soup.find_all()
|
||||||
|
|
||||||
|
match len(nodes):
|
||||||
|
case 0: return EmptyNode()
|
||||||
|
case 1: return SingleNode(nodes[0])
|
||||||
|
case _: return NodeCollection(soup)
|
||||||
|
|
||||||
|
def attach_shadow(self, shadow_root_mode: ShadowRootMode, clonable: Optional[bool] = None, delegates_focus: Optional[bool] = None, serializable: Optional[bool] = None):
|
||||||
|
return ShadowRoot(
|
||||||
|
host=self.value,
|
||||||
|
mode=shadow_root_mode,
|
||||||
|
clonable=clonable,
|
||||||
|
delegates_focus=delegates_focus,
|
||||||
|
serializable=serializable
|
||||||
|
)
|
||||||
|
|
||||||
|
def find(self, *args, **kwargs):
|
||||||
|
return self.value.find(*args, **kwargs)
|
||||||
|
|
||||||
|
def find_all(self, *args, **kwargs):
|
||||||
|
return self.value.find_all(*args, **kwargs)
|
||||||
|
|
||||||
|
def append(self, *args, **kwargs):
|
||||||
|
return self.value.append(*args, **kwargs)
|
||||||
|
|
||||||
|
def insert(self, *args, **kwargs):
|
||||||
|
return self.value.insert(*args, **kwargs)
|
||||||
|
|
||||||
|
def has_attr(self, attr: str) -> bool:
|
||||||
|
return self.value.has_attr(attr)
|
||||||
|
|
||||||
|
def prettify(self) -> str:
|
||||||
|
return self.value.prettify()
|
||||||
|
|
||||||
|
class EmptyNode(Node):
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class NodeCollection(Node):
|
||||||
|
nodes: Iterable[Tag]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self.nodes
|
||||||
|
|
||||||
|
def clone(self) -> Self:
|
||||||
|
return NodeCollection(copy(self.value))
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SingleNode(Node):
|
||||||
|
_value: Tag
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self):
|
def value(self):
|
||||||
return self._value
|
return self._value
|
||||||
|
@ -32,26 +89,12 @@ class Node(Clonable):
|
||||||
serializable=serializable
|
serializable=serializable
|
||||||
)
|
)
|
||||||
|
|
||||||
def from_path(path: str) -> Self:
|
|
||||||
with open(path, "r") as f:
|
|
||||||
return Node(BeautifulSoup(f.read(), 'html.parser').find())
|
|
||||||
|
|
||||||
def from_element(element: "Parsable") -> Self:
|
|
||||||
if isinstance(element, Node):
|
|
||||||
return element
|
|
||||||
return Node(element)
|
|
||||||
|
|
||||||
def clone(self) -> "Self":
|
|
||||||
return Node(copy(self.value))
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
if name == '_value':
|
|
||||||
raise AttributeError()
|
|
||||||
return getattr(self._value, name)
|
|
||||||
|
|
||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
return self._value[index]
|
return self._value[index]
|
||||||
|
|
||||||
|
def clone(self) -> Self:
|
||||||
|
return SingleNode(copy(self.value))
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Template(Clonable):
|
class Template(Clonable):
|
||||||
_value: Node
|
_value: Node
|
||||||
|
@ -60,6 +103,10 @@ class Template(Clonable):
|
||||||
def value(self):
|
def value(self):
|
||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
return self._value["id"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def shadow_root_mode(self) -> ShadowRootMode | None:
|
def shadow_root_mode(self) -> ShadowRootMode | None:
|
||||||
return self._value.get("shadowrootmode")
|
return self._value.get("shadowrootmode")
|
||||||
|
@ -104,20 +151,9 @@ class Template(Clonable):
|
||||||
def clone(self) -> Self:
|
def clone(self) -> Self:
|
||||||
return Template(copy(self._value))
|
return Template(copy(self._value))
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
if name == '_value':
|
|
||||||
raise AttributeError()
|
|
||||||
return getattr(self._value, name)
|
|
||||||
|
|
||||||
def __getitem__(self, index):
|
|
||||||
return self._value[index]
|
|
||||||
|
|
||||||
def __setitem__(self, index, value):
|
|
||||||
self._value[index] = value
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ShadowRoot(Clonable):
|
class ShadowRoot(Clonable):
|
||||||
host: "Node"
|
host: Node
|
||||||
mode: ShadowRootMode
|
mode: ShadowRootMode
|
||||||
|
|
||||||
clonable: Optional[bool] = None
|
clonable: Optional[bool] = None
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Puppygirl[R: Renderer]:
|
||||||
|
|
||||||
def _create_template_dict(templates: Iterable[Parsable]) -> Templates:
|
def _create_template_dict(templates: Iterable[Parsable]) -> Templates:
|
||||||
templates = [Template.from_element(t) for t in templates]
|
templates = [Template.from_element(t) for t in templates]
|
||||||
return {t[IdAttr]: t for t in templates}
|
return {t.id: t for t in templates}
|
||||||
|
|
||||||
def add_template(self, template: Parsable):
|
def add_template(self, template: Parsable):
|
||||||
template = Template.from_element(template)
|
template = Template.from_element(template)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from importlib import resources
|
||||||
from typing import TYPE_CHECKING, Iterable, Protocol, runtime_checkable
|
from typing import TYPE_CHECKING, Iterable, Protocol, runtime_checkable
|
||||||
|
|
||||||
from puppygirl.elements import IdAttr, TemplateName
|
from puppygirl.elements import IdAttr, TemplateName
|
||||||
from puppygirl.elements.shadow_root import Node
|
from puppygirl.elements.shadow_root import Node, SingleNode
|
||||||
from puppygirl.puppytype import Templates
|
from puppygirl.puppytype import Templates
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
@ -47,7 +47,7 @@ class ServerSideRenderer(Renderer):
|
||||||
for element in puppygirl.elements:
|
for element in puppygirl.elements:
|
||||||
if hasattr(element, "name"):
|
if hasattr(element, "name"):
|
||||||
for tag in tree.find_all(element.name):
|
for tag in tree.find_all(element.name):
|
||||||
new_tag = element.render(Node(tag).clone(), templates)
|
new_tag = element.render(SingleNode(tag).clone(), templates)
|
||||||
|
|
||||||
if isinstance(new_tag, Iterable):
|
if isinstance(new_tag, Iterable):
|
||||||
tag.extend(new_tag)
|
tag.extend(new_tag)
|
||||||
|
|
Loading…
Add table
Reference in a new issue