diff --git a/proxy.py b/proxy.py new file mode 100644 index 0000000..42c5e0b --- /dev/null +++ b/proxy.py @@ -0,0 +1,56 @@ +from typing import List, Protocol, Tuple, Union + +def MakeAttrs(css:str|Tuple[str, ...]|None, id:str|None, attributes: dict[str, str | None] = {}) -> str: + if css: + attributes['class'] = " ".join(css) if isinstance(css, (list, tuple)) else css + if id: + attributes['id'] = id + attrList: List[str] = [] + for key, value in attributes.items(): + if value: + attrList.append(f'{key}="{value}"') + return " ".join(attrList) + +class ComplexProxyLeaf(dict): + name:str = "" + attrs:str = "" + def __init__(self, name:str): + self.name = name + def __call__(self, css:str|None = None, id:str|None = None): + self.attrs = MakeAttrs(css, id) + return self + def __repr__(self) -> str: + return f'<{self.name} {self.attrs}/>' + +class ComplexProxyBranch(ComplexProxyLeaf): + name:str = "" + attrs:str = "" + def __init__(self, name:str): + self.name = name + def __call__(self, css:str|None = None, id:str|None = None): + self.attrs = MakeAttrs(css, id) + return self + def __repr__(self) -> str: + return f'<{self.name} {self.attrs}>' + def __getitem__(self, key:Union[str, 'ComplexProxyBranch', ComplexProxyLeaf, Tuple[Union[str, 'ComplexProxyBranch', ComplexProxyLeaf], ...]]) -> str: + if isinstance(key, tuple): + children = "".join(str(k) for k in key) + else: + children = key + return f'<{self.name} {self.attrs}>{children}' + +IMG = ComplexProxyLeaf("img") +BR = ComplexProxyLeaf("br") +A = ComplexProxyBranch("a") + +print( + A + [ + "click here", + BR, + A(css="www.site.com") + [ + IMG(id="image.png") + ] + ] +) \ No newline at end of file diff --git a/py_jsx.py b/py_jsx.py index 3729834..a438f1d 100644 --- a/py_jsx.py +++ b/py_jsx.py @@ -1,4 +1,4 @@ -from typing import List, Protocol, Tuple +from typing import List, Protocol, Tuple, Union class StrArgsToStr(Protocol): def __call__(self, *children: str) -> str: @@ -6,64 +6,59 @@ class StrArgsToStr(Protocol): ClassArg = str|List[str]|Tuple[str, ...]|None -class ProxyDict(dict): - - name:str - attrs:str - - def __init__(self, name:str, attrs:str): - self.name = name - self.attrs = attrs - def __getitem__(self, key:str|Tuple[str, ...]): - return f'<{self.name}{self.attrs}>{"".join(key) if isinstance(key, tuple) else key}' +class ComplexProxy(Protocol): + def __repr__(self) -> str: + ... + def __getitem__(self, key:Tuple[Union['ComplexProxy',str], ...]) -> str: + ... def MakeAttrs(classes:ClassArg, id:str|None, attributes: dict[str, str | None]) -> str: - if classes: attributes['class'] = " ".join(classes) if isinstance(classes, (list, tuple)) else classes - if id: attributes['id'] = id - - attrList: List[str] = [""] + attrList: List[str] = [] for key, value in attributes.items(): if value: attrList.append(f'{key}="{value}"') return " ".join(attrList) -def ElWrapped(name: str, classes:ClassArg = None, id:str|None = None, attrs: dict[str, str | None] = {}, children:ClassArg = ()) -> ProxyDict: - return ProxyDict(name, MakeAttrs(classes, id, attrs)) +class NodeLeaf(): + name:str = "" + attrs:str = "" + def __init__(self): + pass + def __repr__(self) -> str: + return f'<{self.name} {self.attrs}/>' + def __getitem__(self, key:ComplexProxy) -> str: + ... -def ElInline(name: str, classes:ClassArg = None, id:str|None = None, attrs: dict[str, str | None] = {}) -> str: - return f'<{name} {MakeAttrs(classes, id, attrs)}/>' +class NodeBranch(dict): + name:str = "" + attrs:str = "" + def __init__(self): + pass + def __repr__(self) -> str: + return f'<{self.name} {self.attrs}>' + def __getitem__(self, key:Tuple[Union['ComplexProxy',str], ...]) -> str: + return f'<{self.name} {self.attrs}>{"".join(key) if isinstance(key, tuple) else key}' -def SimpleWrapped(name:str): - def proxy(classes:ClassArg = None, id:str|None = None): - return ElWrapped(name, classes, id) - return proxy -def SimpleInline(name:str): - def proxy(classes:ClassArg = None, id:str|None = None): - return ElInline(name, classes, id) - return proxy +class A(NodeBranch): + name = "a" + def __init__(self, classes:ClassArg = None, id:str|None = None, href:str|None = None, target:str|None = None): + self.attrs = MakeAttrs(classes, id, {"href":href, "target":target}) +class IMG(NodeLeaf): + name = "img" + def __init__(self, classes:ClassArg = None, id:str|None = None, src:str|None = None): + self.attrs = MakeAttrs(classes, id, {"src":src}) -def A(classes:ClassArg = None, id:str|None = None, href:str|None = None, target:str|None = None): - return ElWrapped("a", classes, id, {"href":href, "target":id}) - -def IMG(classes:ClassArg = None, id:str|None = None, src:str|None = None): - return ElInline("img", classes, id, {"src":src}) - -DIV = SimpleWrapped("div") -P = SimpleWrapped("P") -BR = SimpleInline("br") -HR = SimpleInline("hr") -SPAN = SimpleWrapped("span") +a = A() print( - - DIV(classes="outer") - [ - A(classes="CTA Orange", href="www.link")["click"] + A(href="outer")[ + IMG(src="image.jpg"), + IMG(src="image.jpg"), ] ) \ No newline at end of file