add some stuff

This commit is contained in:
Rowan 2025-10-08 11:40:26 -04:00
parent 4210f500c4
commit 3deafd4d97
7 changed files with 99 additions and 40 deletions

View file

@ -2,7 +2,7 @@
from argparse import ArgumentParser from argparse import ArgumentParser
from puppygirl import Puppygirl from puppygirl import Puppygirl
from puppygirl.elements.domme import PuppygirlDomme from puppygirl.elements.host import PuppygirlHost, PuppygirlPart
from puppygirl.elements import Node from puppygirl.elements import Node
from puppygirl.renderer import ClientSideRenderer, ServerSideRenderer from puppygirl.renderer import ClientSideRenderer, ServerSideRenderer
@ -24,7 +24,7 @@ def main():
case _: case _:
renderer = ServerSideRenderer() renderer = ServerSideRenderer()
pg = Puppygirl(renderer=renderer, elements=[PuppygirlDomme]) pg = Puppygirl(renderer=renderer, elements=[PuppygirlHost, PuppygirlPart])
html = pg.parse(Node.from_path(args.input)) html = pg.parse(Node.from_path(args.input))
if args.pretty: if args.pretty:

View file

@ -1,4 +1,4 @@
class PuppygirlDomme extends HTMLElement { class PuppygirlHost extends HTMLElement {
constructor() { constructor() {
super() super()
} }
@ -14,4 +14,4 @@ class PuppygirlDomme extends HTMLElement {
} }
customElements.define("puppygirl-domme", PuppygirlDomme) customElements.define("pg-host", PuppygirlDomme)

View file

@ -1,3 +1,3 @@
from .constants import * from .constants import *
from .domme import * from .host import *
from .shadow_root import * from .shadow_root import *

View file

@ -1,31 +0,0 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING
from .constants import TemplateAttr
from .shadow_root import ShadowRootMode
from ..renderer import Renderable
if TYPE_CHECKING:
from .. import Puppygirl
from .shadow_root import Node
from ..puppytype import RenderableElement, Templates
@dataclass
class PuppygirlDomme(Renderable):
puppygirl: "Puppygirl"
@property
def name(self):
return "puppygirl-domme"
def render(self, node: "Node", templates: "Templates") -> "RenderableElement":
if not node.has_attr(TemplateAttr):
return node
template = templates[node[TemplateAttr]]
shadow_root = node.attach_shadow(ShadowRootMode.Open)
shadow_root.append_child(template.clone())
return node

View file

@ -0,0 +1,67 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING
from .constants import TemplateAttr
from .shadow_root import ShadowRootMode
from ..renderer import Query, Renderable
if TYPE_CHECKING:
from .. import Puppygirl
from .shadow_root import Node
from ..puppytype import RenderableElement, Templates
@dataclass
class PuppygirlHost(Renderable):
puppygirl: "Puppygirl"
@property
def name(self):
return "pg-host"
def query(self) -> Query:
return Query(self.name, attrs={ "template": True })
def render(self, node: "Node", templates: "Templates") -> "RenderableElement":
template = templates[node[TemplateAttr]]
shadow_root = node.attach_shadow(ShadowRootMode.Open)
shadow_root.append_child(template.clone())
return node
@dataclass
class PuppygirlPart(Renderable):
puppygirl: "Puppygirl"
@property
def name(self):
return "pg-part"
def query(self) -> Query:
return Query(self.name, attrs={ "for": True })
def render(self, node: "Node", templates: "Templates") -> "RenderableElement":
template = node.parent.find("template", recursive=False)
if template is None:
return node
part_name = node["for"]
parts = template.find_all(attrs={ "part": part_name })
attrs = {
attr: value
for attr, value in node.value.attrs.items()
if attr != "for"
}
for attr, value in attrs.items():
for part in parts:
part[attr] = value
return []

View file

@ -80,6 +80,10 @@ class SingleNode(Node):
def value(self): def value(self):
return self._value return self._value
@property
def parent(self):
return self._value.parent
def attach_shadow(self, shadow_root_mode: ShadowRootMode, clonable: Optional[bool] = None, delegates_focus: Optional[bool] = None, serializable: Optional[bool] = None): def attach_shadow(self, shadow_root_mode: ShadowRootMode, clonable: Optional[bool] = None, delegates_focus: Optional[bool] = None, serializable: Optional[bool] = None):
return ShadowRoot( return ShadowRoot(
host=self, host=self,

View file

@ -1,6 +1,8 @@
from dataclasses import InitVar, dataclass, field from dataclasses import InitVar, dataclass, field
from importlib import resources from importlib import resources
from typing import TYPE_CHECKING, Iterable, Protocol, runtime_checkable from typing import TYPE_CHECKING, Any, Iterable, Protocol, Self, runtime_checkable
from bs4 import Tag
from puppygirl.elements import IdAttr, TemplateName from puppygirl.elements import IdAttr, TemplateName
from puppygirl.elements.shadow_root import Node, SingleNode from puppygirl.elements.shadow_root import Node, SingleNode
@ -10,10 +12,24 @@ if TYPE_CHECKING:
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from puppygirl import Puppygirl from puppygirl import Puppygirl
class Query:
_args: Iterable[Any]
_kwargs: dict[str, Any]
def __init__(self, *args, **kwargs):
self._args = args
self._kwargs = kwargs
def query(self, tree: "BeautifulSoup") -> Iterable[Tag]:
return tree.find_all(*self._args, **self._kwargs)
@runtime_checkable @runtime_checkable
class Renderable(Protocol): class Renderable(Protocol):
def query(self) -> Query:
return Query()
def render(self, tree: "BeautifulSoup") -> "BeautifulSoup": def render(self, tree: "BeautifulSoup") -> "BeautifulSoup":
pass return tree
class Renderer(Protocol): class Renderer(Protocol):
def render(self, puppygirl: "Puppygirl", tree: "BeautifulSoup") -> "BeautifulSoup": def render(self, puppygirl: "Puppygirl", tree: "BeautifulSoup") -> "BeautifulSoup":
@ -35,6 +51,7 @@ class ClientSideRenderer(Renderer):
head.append(script) head.append(script)
return tree return tree
class ServerSideRenderer(Renderer): class ServerSideRenderer(Renderer):
def _find_local_templates(puppygirl: "Puppygirl", tree: "BeautifulSoup") -> "Templates": def _find_local_templates(puppygirl: "Puppygirl", tree: "BeautifulSoup") -> "Templates":
templates = tree.find_all(TemplateName) templates = tree.find_all(TemplateName)
@ -46,11 +63,13 @@ class ServerSideRenderer(Renderer):
for element in puppygirl.elements: for element in puppygirl.elements:
if hasattr(element, "name"): if hasattr(element, "name"):
tags = tree.find_all(element.name) query = element.query()
tags = query.query(tree)
tags.reverse() tags.reverse()
for tag in tags: for tag in tags:
new_tag = element.render( new_tag = element.render(
SingleNode(tag).clone(), SingleNode(tag),
# SingleNode(tag).clone(),
templates templates
) )