from dataclasses import dataclass from typing import Optional, Tuple, Union, Dict, List import random css_final:List[str] = [] css_lines:List[str] = [] def css_class(css_context:str): global css_lines output = f'{css_context}{{ {"".join(css_lines)} }}' css_lines = [] css_final.append(output) def css_write(str:str): css_lines.append(str) def css_dump(): global css_final output = "".join(css_final) css_final = [] return output class Unit(): unit = "px" def __init__(self, amount:float): self.amount = amount def __repr__(self) -> str: return f'{self.amount}{self.unit}' class PX(Unit): pass class EM(Unit): unit = "em" class REM(Unit): unit = "rem" class Cluster(): map:Dict[str, str] = {} def __init__(self): self.key = random.randrange(1000, 5000) pass def __repr__(self)->str: print("repr called on cluster") #todo: flesh this out / provide overrides for each inheriting class return self.render() def render(self)->str: output:List[str] = [] for key in self.map: value = self.__getattribute__(self.map[key]) if value: output.append(f'{key}:{value};') return "\n".join(output) @dataclass class Font(Cluster): family: Optional[str] = None kerning: Optional[str] = None size: Optional[Unit] = None map = { "font-family":"family", "font-kerning":"kerning", "font-size":"size" } @dataclass class Space(Cluster): top: Optional[Unit] = None right: Optional[Unit] = None bottom: Optional[Unit] = None left: Optional[Unit] = None @dataclass class XForm(Space): width: Optional[Unit] = None height: Optional[Unit] = None angle: Optional[float] = None class Chainer(): def __init__(self) -> None: self.accessed = 0 pass def __getitem__(self, args:Union[Cluster, Tuple[Cluster, ...]]): if isinstance(args, tuple): children = f'\n'.join(k.render() for k in args) else: children = args.render() if self.accessed: css_write(f'@media(max-width:{self.accessed}px){{ {children} }}') else: css_write(children) self.accessed = 0 return self def __call__(self, key:int): self.accessed = key return self CSS = Chainer() ########################## class _SHEET(type): last_accessed:Optional[str] = None def __getattribute__(cls, name:str): if name != "__name__" and name != "__module__": css_class(f'.{cls.__module__}.{cls.__name__}.{name}') return super().__getattribute__(name) class SHEET(metaclass=_SHEET): pass class UserMadeSheet(SHEET): Paragraph=CSS[ Font( size=PX(10) ), ](512)[ Font( size=PX(18), family="sans" ), ](1024)[ Font( size=PX(120) ), ] Anchor=CSS[ Font( size=PX(123) ) ]