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 ""}>{self.name}>'
- 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 ]
+ ]}')