pyx/css.py
2025-08-21 13:39:30 -04:00

141 lines
3.4 KiB
Python

from dataclasses import dataclass
from typing import Optional, Tuple, Union, Dict, List
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):
pass
def __repr__(self)->str:
print("repr called on cluster")
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 "".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.size = 0
self.dump_id:int = -1
self.log:List[str] = []
pass
def __getitem__(self, args:Union[Cluster, Tuple[Cluster, ...]]):
print("bracket access", args)
styledata = "".join(c.render() for c in args) if isinstance(args, tuple) else args.render()
if self.size:
self.log.append(f'\n@media(min-width:{self.size}px){{ {styledata} }}')
else:
self.log.append(styledata)
return self
def __call__(self, key:int):
print("call access", key)
self.size = key
return self
def dump(self, log:List[str], fullName:str, dump_id:int):
if self.dump_id != dump_id:
log.append(f'.{fullName} {{\n {"".join(self.log)} \n}}')
self.dump_id = dump_id
self.log = []
self.size = 0
class Kickoff():
def __getitem__(self, args:Union[Cluster, Tuple[Cluster, ...]]):
return Chainer().__getitem__(args)
def __call__(self, key:int):
return Chainer().__call__(key)
CSS = Kickoff()
##########################
class Writer:
dump_id = 0
log:List[str] = []
@classmethod
def start(cls):
cls.dump_id += 1
cls.log.clear()
print("Writer reset, dump_id:", cls.dump_id)
@classmethod
def capture(cls, fullName:str, chainer:Chainer):
chainer.dump(cls.log, fullName, Writer.dump_id)
@classmethod
def dump(cls) -> str:
output = "\n".join(cls.log)
cls.start() # Reset after dumping
return output
class _SHEET(type):
def __getattribute__(cls, name:str):
if name != "__name__" and name != "__module__":
print("class name access", name)
value = super().__getattribute__(name)
if isinstance(value, Chainer):
fullName = f'{cls.__module__}_{cls.__name__}_{name}'
Writer.capture(fullName, value)
return fullName
return super().__getattribute__(name)
class SHEET(metaclass=_SHEET):
pass