diff --git a/css.py b/css.py index 4b34343..52145ad 100644 --- a/css.py +++ b/css.py @@ -1,6 +1,5 @@ from dataclasses import dataclass from typing import Optional, Tuple, Union, Dict, List -import random class Unit(): unit = "px" @@ -24,7 +23,6 @@ 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") @@ -101,9 +99,6 @@ class Kickoff(): CSS = Kickoff() -def TAG(*styles:Chainer): - for item in styles: - print(item) ########################## @@ -121,6 +116,12 @@ class Writer: 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): @@ -137,17 +138,3 @@ class _SHEET(type): 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) ) - ] - diff --git a/example.html b/example.html new file mode 100644 index 0000000..c69e3a3 --- /dev/null +++ b/example.html @@ -0,0 +1,33 @@ + + + + + +
+

+Welcome! +

+ + + +

+hello and lorem ipsum dolor sit amet, consectetur adipiscing elit. + Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi + ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit + in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. +

+
+ + \ No newline at end of file diff --git a/pyle_sheets.py b/pyle_sheets.py deleted file mode 100644 index bc4f387..0000000 --- a/pyle_sheets.py +++ /dev/null @@ -1,138 +0,0 @@ -from typing import TypedDict, Union, Literal, Tuple, Optional, cast -import re - -# --- Units and Sizes --- -MediaQueryCheck = Literal["max-width", "min-width", "max-height", "min-height"] -Unit = Literal["px", "em", "rem", "%", "vh", "vw"] -Size = Tuple[float, Unit] -MediaQuery = Tuple[MediaQueryCheck, float, Unit] - -# --- Colors --- -RGB = Tuple[float, float, float] -RGBA = Tuple[float, float, float, float] -Color = Union[RGB, RGBA] - -CSSValue = Union[Size, Color, str] - -# --- Positions --- -PositionKeyword = Literal["static", "relative", "absolute", "fixed", "sticky"] - -# --- Display --- -Display = Literal["none", "block", "inline", "inline-block", "flex", "grid"] - -# --- Alignment --- -TextAlign = Literal["left", "right", "center", "justify", "start", "end"] - -# --- Overflow --- -Overflow = Literal["visible", "hidden", "scroll", "auto", "clip"] - -# --- Border Style --- -BorderStyle = Literal["none", "solid", "dashed", "dotted", "double", "groove", "ridge", "inset", "outset"] - -# --- Length / Size or keyword --- -AutoSize = Union[Size, Literal["auto"]] - -class CSS(TypedDict, total=False): - color: Color - backgroundColor: Color - fontSize: Size - margin: Union[AutoSize, Tuple[AutoSize, AutoSize], Tuple[AutoSize, AutoSize, AutoSize, AutoSize]] - padding: Union[AutoSize, Tuple[AutoSize, AutoSize], Tuple[AutoSize, AutoSize, AutoSize, AutoSize]] - width: AutoSize - height: AutoSize - display: Display - position: PositionKeyword - top: AutoSize - left: AutoSize - right: AutoSize - bottom: AutoSize - textAlign: TextAlign - overflow: Overflow - borderColor: Color - borderWidth: Size - borderStyle: BorderStyle - opacity: float # 0.0 to 1.0 - zIndex: int - lineHeight: Union[float, Size] - -def Styles( - color: Optional[Color] = None, - backgroundColor: Optional[Color] = None, - fontSize: Optional[Size] = None, - margin: Optional[Union[AutoSize, Tuple[AutoSize, AutoSize], Tuple[AutoSize, AutoSize, AutoSize, AutoSize]]] = None, - padding: Optional[Union[AutoSize, Tuple[AutoSize, AutoSize], Tuple[AutoSize, AutoSize, AutoSize, AutoSize]]] = None, - width: Optional[AutoSize] = None, - height: Optional[AutoSize] = None, - display: Optional[Display] = None, - position: Optional[PositionKeyword] = None, - top: Optional[AutoSize] = None, - left: Optional[AutoSize] = None, - right: Optional[AutoSize] = None, - bottom: Optional[AutoSize] = None, - textAlign: Optional[TextAlign] = None, - overflow: Optional[Overflow] = None, - borderColor: Optional[Color] = None, - borderWidth: Optional[Size] = None, - borderStyle: Optional[BorderStyle] = None, - opacity: Optional[float] = None, - zIndex: Optional[int] = None, - lineHeight: Optional[Union[float, Size]] = None, -) -> CSS: - """ - Function alternative to create a block of CSS styles. - """ - return cast(CSS, {k: v for k, v in locals().items() if v is not None}) - -def Sheet(mq:MediaQuery, *css:CSS): - """ - Serialize a CSS sheet with a media query and multiple CSS dictionaries. - """ - lines:list[str] = [] - lines.append(f"@media ({mq[0]}: {mq[1]}{mq[2]}) {{") - - def camel_to_kebab(name): - # Insert hyphen before capital letters and convert to lowercase - s1 = re.sub(r'(.)([A-Z][a-z]+)', r'\1-\2', name) - kebab = re.sub(r'([a-z0-9])([A-Z])', r'\1-\2', s1).lower() - return kebab - - def concat(joiner:str, tuple:Union[RGB, RGBA, Size])->str: - return joiner.join(str(item) for item in tuple) - - - merged:CSS = {} - for d in css: - merged = {**merged, **d} - - - for key, value in merged.items(): - text = value - if isinstance(value, tuple): - size = len(value) - if size < 3: - text = concat("", value) - elif size == 3: - text = "rgb(" + concat(", ", value) + ")" - elif size == 4: - text = "rgba(" + concat(", ", value) + ")" - - lines.append(f" {camel_to_kebab(key)}: {text};") - - lines.append("}") - return "\n".join(lines) - -test = Sheet( - ("max-width", 1024, "px"), - { - "fontSize":(16, "px"), - "color":(255, 0, 0), - "backgroundColor":(0, 255, 0), - "display":"block", - }, - Styles( - color=(0, 0, 255), - backgroundColor=(255, 255, 0), - ) -) - -print(test) \ No newline at end of file diff --git a/pyx.py b/pyx.py index a93ab8d..bf1cbde 100644 --- a/pyx.py +++ b/pyx.py @@ -1,14 +1,17 @@ -from typing import List, Tuple, Union, Optional +from typing import Any, List, Tuple, Union, Optional +from css import Chainer, Writer +from dataclasses import dataclass Attributes = dict[str, Union[str, bool, None]] Stringy = Union[str, Tuple[str, ...]] Renderable = Union[str, 'Branch', 'Leaf'] +TAGGED = Union[Tuple[Chainer], Chainer] -def MakeAttrs(css:Optional[Stringy], id:Optional[str], attributes: Attributes) -> str: +def MakeAttrs(css:TAGGED, id:Optional[str], attributes: Attributes) -> str: if not attributes: attributes = {} if css: - attributes['class'] = " ".join(css) if isinstance(css, (list, tuple)) else css + attributes['class'] = " ".join(css) if isinstance(css, tuple) else css if id: attributes['id'] = id attrList: List[str] = [] @@ -24,12 +27,12 @@ class Leaf(): self.name = name self.attrs = None - def props(self, css:Optional[Stringy], id:Optional[str], attributes: Attributes): + def props(self, css:Optional[TAGGED], id:Optional[str], attributes: Attributes): clone = self.__class__(self.name) clone.attrs = MakeAttrs(css, id, attributes) return clone - def __call__(self, css:Optional[str] = None, id:Optional[str] = None): + def __call__(self, css:Optional[TAGGED] = None, id:Optional[str] = None): return self.props(css, id, {}) def __repr__(self) -> str: @@ -46,7 +49,7 @@ class Branch(Leaf): def __repr__(self) -> str: return f'<{self.name}{self.attrs or ""}>' - def __getitem__(self, key:Union[Renderable, Tuple[Renderable, ...]]) -> str: + def __getitem__(self, key:Union[Renderable, Tuple[Renderable, ...]]) -> Renderable: if isinstance(key, tuple): children = f'\n'.join(str(k) for k in key) else: @@ -55,12 +58,12 @@ class Branch(Leaf): class IMGTag(Leaf): name = "img" - def __call__(self, css:Optional[Stringy] = None, id:Optional[str] = None, src:Optional[str] = None): + def __call__(self, css:Optional[TAGGED] = None, id:Optional[str] = None, src:Optional[str] = None): return self.props(css, id, {"src":src}) class ATag(Branch): name = "a" - def __call__(self, css:Optional[Stringy] = None, id:Optional[str] = None, href:Optional[str] = None, target:Optional[str] = None): + def __call__(self, css:Optional[TAGGED] = None, id:Optional[str] = None, href:Optional[str] = None, target:Optional[str] = None): return self.props(css, id, {"href":href, "target":target}) IMG = IMGTag() @@ -77,3 +80,13 @@ H3 = Branch("h3") H4 = Branch("h4") SECTION = Branch("section") MAIN = Branch("main") +HTML = Branch("html") +HEAD = Branch("head") +BODY = Branch("body") +STYLE = Branch("style") + +@dataclass +class Capture: + def __init__(self, html:Renderable): + self.html = html + self.css = Writer.dump() \ No newline at end of file diff --git a/sheet.py b/sheet.py deleted file mode 100644 index bc4ca84..0000000 --- a/sheet.py +++ /dev/null @@ -1,5 +0,0 @@ -from css import UserMadeSheet, TAG, Writer - -print(TAG(UserMadeSheet.Paragraph)) - -print(Writer.log) diff --git a/template.py b/template.py deleted file mode 100644 index 87e6346..0000000 --- a/template.py +++ /dev/null @@ -1,12 +0,0 @@ -from pyx import DIV, H1, H2, P, SPAN, BR, IMG, A - -print( -DIV -[ - H1["Welcome!"], - A(css="www.site.com", href="www.site.com") - [ - IMG(id="image.png") - ] -] -) diff --git a/user_styles.py b/user_styles.py new file mode 100644 index 0000000..e04b7e1 --- /dev/null +++ b/user_styles.py @@ -0,0 +1,15 @@ +from css import SHEET, CSS, Font, PX + +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) ) + ] diff --git a/user_template.py b/user_template.py new file mode 100644 index 0000000..13757ee --- /dev/null +++ b/user_template.py @@ -0,0 +1,32 @@ +from pyx import DIV, H1, P, IMG, A, HTML, HEAD, BODY, STYLE, Capture +from user_styles import UserMadeSheet + + +output = Capture( + DIV + [ + H1["Welcome!"], + A(css=(UserMadeSheet.Anchor), href="www.site.com") + [ + IMG(src="image.png") + ], + P(css=UserMadeSheet.Paragraph) + [ + """hello and lorem ipsum dolor sit amet, consectetur adipiscing elit. + Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi + ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit + in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum.""" + ] + ] +) + +with open("example.html", "w") as file: + file.write(f'{HTML[ + HEAD[ + STYLE[ output.css ] + ], + BODY[ output.html ] + ]}')