working!
This commit is contained in:
parent
dd440fa779
commit
61fac50e20
25
css.py
25
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) )
|
||||
]
|
||||
|
||||
|
33
example.html
Normal file
33
example.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!doctype html><html>
|
||||
<head>
|
||||
<style>
|
||||
.user_styles_UserMadeSheet_Anchor {
|
||||
font-size:123px;
|
||||
}
|
||||
.user_styles_UserMadeSheet_Paragraph {
|
||||
font-size:10px;
|
||||
@media(min-width:512px){ font-family:sans;font-size:18px; }
|
||||
@media(min-width:1024px){ font-size:120px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>
|
||||
Welcome!
|
||||
</h1>
|
||||
<a href="www.site.com" class="user_styles_UserMadeSheet_Anchor">
|
||||
<img src="image.png"/>
|
||||
</a>
|
||||
<p class="user_styles_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.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
138
pyle_sheets.py
138
pyle_sheets.py
@ -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)
|
29
pyx.py
29
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()
|
5
sheet.py
5
sheet.py
@ -1,5 +0,0 @@
|
||||
from css import UserMadeSheet, TAG, Writer
|
||||
|
||||
print(TAG(UserMadeSheet.Paragraph))
|
||||
|
||||
print(Writer.log)
|
12
template.py
12
template.py
@ -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")
|
||||
]
|
||||
]
|
||||
)
|
15
user_styles.py
Normal file
15
user_styles.py
Normal file
@ -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) )
|
||||
]
|
32
user_template.py
Normal file
32
user_template.py
Normal file
@ -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'<!doctype html>{HTML[
|
||||
HEAD[
|
||||
STYLE[ output.css ]
|
||||
],
|
||||
BODY[ output.html ]
|
||||
]}')
|
Loading…
Reference in New Issue
Block a user