hypie 0.1.1.dev2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hypie/__init__.py +34 -0
- hypie/cli/build_components.py +148 -0
- hypie/commands.py +220 -0
- hypie/dom_position.py +39 -0
- hypie/events.py +77 -0
- hypie/experimental/client_components.py +78 -0
- hypie/experimental/components.py +135 -0
- hypie/experimental/hyperscript.py +35 -0
- hypie/experimental/templates.py +50 -0
- hypie/features.py +46 -0
- hypie/hs_ast/commands.py +478 -0
- hypie/hs_ast/constants.py +1 -0
- hypie/hs_ast/contexts.py +3 -0
- hypie/hs_ast/expressions.py +719 -0
- hypie/hs_ast/features.py +181 -0
- hypie/hs_ast/helpers.py +85 -0
- hypie/literals.py +76 -0
- hypie-0.1.1.dev2.dist-info/METADATA +816 -0
- hypie-0.1.1.dev2.dist-info/RECORD +22 -0
- hypie-0.1.1.dev2.dist-info/WHEEL +4 -0
- hypie-0.1.1.dev2.dist-info/entry_points.txt +3 -0
- hypie-0.1.1.dev2.dist-info/licenses/LICENSE +7 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
from dataclasses import dataclass, is_dataclass
|
|
2
|
+
from typing import dataclass_transform
|
|
3
|
+
from textwrap import indent
|
|
4
|
+
|
|
5
|
+
import htpy
|
|
6
|
+
from markupsafe import Markup
|
|
7
|
+
|
|
8
|
+
from hypie.hs_ast.helpers import kebab_case_name, htpy_to_tree, tree_to_htpy
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def transform_root(el: dict, component_name: str):
|
|
12
|
+
if not isinstance(el, dict):
|
|
13
|
+
return el
|
|
14
|
+
k, v = next(iter(el.items()))
|
|
15
|
+
if k == "_fragment":
|
|
16
|
+
return {
|
|
17
|
+
k: {
|
|
18
|
+
"children": [transform_root(c, component_name) for c in v["children"]],
|
|
19
|
+
"attrs": v["attrs"],
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if "data-hypie-component" in v["attrs"]:
|
|
23
|
+
return el
|
|
24
|
+
return {
|
|
25
|
+
k: {
|
|
26
|
+
"children": v["children"],
|
|
27
|
+
"attrs": v["attrs"] + f' data-hypie-component="{component_name}"',
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
SPACES = " " * 2
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def parse_css_dict(k, v: dict):
|
|
36
|
+
parts = [f"{k} {{"]
|
|
37
|
+
for sub_k, sub_v in v.items():
|
|
38
|
+
if sub_k.strip() == "@apply":
|
|
39
|
+
if isinstance(sub_v, list):
|
|
40
|
+
parts.append(
|
|
41
|
+
indent(
|
|
42
|
+
f"@apply {' '.join(sub_v)};",
|
|
43
|
+
prefix=SPACES,
|
|
44
|
+
predicate=lambda _: True,
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
else:
|
|
48
|
+
parts.append(
|
|
49
|
+
indent(f"@apply {sub_v};", prefix=SPACES, predicate=lambda _: True)
|
|
50
|
+
)
|
|
51
|
+
elif isinstance(sub_v, str):
|
|
52
|
+
parts.append(
|
|
53
|
+
indent(f"{sub_k}: {sub_v};", prefix=SPACES, predicate=lambda _: True)
|
|
54
|
+
)
|
|
55
|
+
elif isinstance(sub_v, dict):
|
|
56
|
+
parts.append(
|
|
57
|
+
indent(
|
|
58
|
+
parse_css_dict(sub_k, sub_v),
|
|
59
|
+
prefix=SPACES,
|
|
60
|
+
predicate=lambda _: True,
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
parts.append("}")
|
|
64
|
+
return "\n".join(parts)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def generate_scoped_css(component_name, css_dict):
|
|
68
|
+
css_parts = [f"@scope ({component_name}) {{"]
|
|
69
|
+
for k, v in css_dict.items():
|
|
70
|
+
css_parts.append(
|
|
71
|
+
indent(parse_css_dict(k, v), prefix=SPACES, predicate=lambda _: True)
|
|
72
|
+
)
|
|
73
|
+
css_parts.append("}")
|
|
74
|
+
return "\n\n".join(css_parts)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class ComponentMeta(type):
|
|
78
|
+
def __getitem__(cls, children):
|
|
79
|
+
instance = Component.__new__(cls)
|
|
80
|
+
instance.children = children
|
|
81
|
+
return instance
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass_transform()
|
|
85
|
+
class Component(metaclass=ComponentMeta):
|
|
86
|
+
children = None
|
|
87
|
+
|
|
88
|
+
def __new__(cls, *args, **kwargs):
|
|
89
|
+
dataclass_cls = cls
|
|
90
|
+
if not is_dataclass(cls):
|
|
91
|
+
dataclass_cls = dataclass(cls)
|
|
92
|
+
instance = object.__new__(dataclass_cls)
|
|
93
|
+
return instance
|
|
94
|
+
|
|
95
|
+
def __init_subclass__(cls, as_fragment=False, hidden=False, contents=False):
|
|
96
|
+
cls._hs_dsl_component = True
|
|
97
|
+
cls.as_fragment = as_fragment
|
|
98
|
+
cls.hidden = hidden
|
|
99
|
+
cls.contents = contents
|
|
100
|
+
cls.component_name = kebab_case_name(cls.__name__)
|
|
101
|
+
cls.tag = f"div[data-hypie-component='{cls.component_name}']"
|
|
102
|
+
|
|
103
|
+
def __html__(self):
|
|
104
|
+
el = self.template()
|
|
105
|
+
new_el = tree_to_htpy(transform_root(htpy_to_tree(el), self.component_name))
|
|
106
|
+
# print(new_el)
|
|
107
|
+
return new_el
|
|
108
|
+
|
|
109
|
+
def __getitem__(self, children):
|
|
110
|
+
if hasattr(self, "children") and self.children:
|
|
111
|
+
raise Exception("Can not reassign children twice")
|
|
112
|
+
self.children = children
|
|
113
|
+
return self
|
|
114
|
+
|
|
115
|
+
def template(self):
|
|
116
|
+
return htpy.fragment[self.children]
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def style() -> dict:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
@classmethod
|
|
123
|
+
def generate_style(cls, with_style_tags=True):
|
|
124
|
+
output_style = cls.style()
|
|
125
|
+
if output_style:
|
|
126
|
+
css = generate_scoped_css(cls.tag, cls.style())
|
|
127
|
+
if with_style_tags:
|
|
128
|
+
return htpy.style[Markup(css)]
|
|
129
|
+
return Markup(css)
|
|
130
|
+
|
|
131
|
+
def encode(self, encoding: str = "utf-8", errors: str = "strict") -> bytes:
|
|
132
|
+
return str(self).encode(encoding, errors)
|
|
133
|
+
|
|
134
|
+
def __str__(self):
|
|
135
|
+
return str(self.__html__())
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
|
|
3
|
+
from hypie.literals import var
|
|
4
|
+
from hypie.commands import set_
|
|
5
|
+
from hypie import hs
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HyperScript:
|
|
9
|
+
def __new__(cls, *args, **kwargs):
|
|
10
|
+
raise Exception("HyperScript class is not meant to be instantiated.")
|
|
11
|
+
|
|
12
|
+
def __init_subclass__(cls):
|
|
13
|
+
if not dataclasses.is_dataclass(cls):
|
|
14
|
+
dataclasses.dataclass(cls, init=False)
|
|
15
|
+
cls._hs_dsl_hyperscript = True
|
|
16
|
+
cls._vars_script = hs()
|
|
17
|
+
for f in dataclasses.fields(cls):
|
|
18
|
+
setattr(cls, f.name, var(f"${cls.__name__}__{f.name}"))
|
|
19
|
+
cls._vars_script.add_features(
|
|
20
|
+
set_(
|
|
21
|
+
var(f"${cls.__name__}__{f.name}"),
|
|
22
|
+
to=f.default if f.default != dataclasses.MISSING else None,
|
|
23
|
+
)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def script(cls):
|
|
28
|
+
return hs()
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def register_hyperscript(cls):
|
|
32
|
+
_hs = hs()
|
|
33
|
+
_hs.add_features(cls._vars_script)
|
|
34
|
+
_hs.add_features(cls.script())
|
|
35
|
+
return _hs
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import htpy
|
|
3
|
+
|
|
4
|
+
# from hypie.literals import var
|
|
5
|
+
from hypie.hs_ast.expressions import TemplatedVariableLiteral
|
|
6
|
+
from hypie.hs_ast.helpers import (
|
|
7
|
+
kebab_case_name,
|
|
8
|
+
htpy_to_tree,
|
|
9
|
+
tranform_tree,
|
|
10
|
+
tree_to_htpy,
|
|
11
|
+
)
|
|
12
|
+
from hypie.hs_ast.expressions import VarTemplateString
|
|
13
|
+
from typing import dataclass_transform
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass_transform()
|
|
17
|
+
class Template:
|
|
18
|
+
field_names = None
|
|
19
|
+
|
|
20
|
+
def __init_subclass__(cls):
|
|
21
|
+
dataclasses.dataclass(cls)
|
|
22
|
+
cls._hs_dsl_template = True
|
|
23
|
+
for f in dataclasses.fields(cls):
|
|
24
|
+
setattr(cls, f.name, TemplatedVariableLiteral(f.name))
|
|
25
|
+
setattr(cls, "field_names", [f.name for f in dataclasses.fields(cls)])
|
|
26
|
+
cls.id = kebab_case_name(cls.__name__)
|
|
27
|
+
|
|
28
|
+
# @classmethod
|
|
29
|
+
def template(cls):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def register_template(cls):
|
|
34
|
+
template = cls(
|
|
35
|
+
**{f: TemplatedVariableLiteral(f) for f in cls.field_names}
|
|
36
|
+
).template()
|
|
37
|
+
tree = htpy_to_tree(template)
|
|
38
|
+
transformed_tree = tranform_tree(tree, rules={"text": cls.handle_text_nodes})
|
|
39
|
+
transformed_htpy = tree_to_htpy(transformed_tree)
|
|
40
|
+
return htpy.script(type="text/hyperscript-template", id=cls.id)[
|
|
41
|
+
transformed_htpy
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def handle_text_nodes(text):
|
|
46
|
+
# print(text)
|
|
47
|
+
exp_template = VarTemplateString(text)
|
|
48
|
+
if not exp_template.interpolations:
|
|
49
|
+
return text
|
|
50
|
+
return exp_template.transform(interp_func=lambda x: "${" + x + "}")
|
hypie/features.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from hypie.hs_ast.features import *
|
|
2
|
+
from hypie.commands import set_
|
|
3
|
+
from hypie.events import Event
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# so you can call it as init() or init[] both work
|
|
7
|
+
Init = InitF()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def On(*event_specs: EventSpecLiteral | str, queue: ON_QUEUE = None):
|
|
11
|
+
_event_specs = []
|
|
12
|
+
for event in event_specs:
|
|
13
|
+
if isinstance(event, type) and issubclass(event, Event):
|
|
14
|
+
_event_specs.append(
|
|
15
|
+
EventSpecLiteral(
|
|
16
|
+
event_name=event.event_name,
|
|
17
|
+
args=event.event_args,
|
|
18
|
+
filter=event.event_spec and event.event_spec.filter,
|
|
19
|
+
count=event.event_spec and event.event_spec.count,
|
|
20
|
+
from_=event.event_spec and event.event_spec.from_,
|
|
21
|
+
in_=event.event_spec and event.event_spec.in_,
|
|
22
|
+
debounce=event.event_spec and event.event_spec.debounce,
|
|
23
|
+
throttle=event.event_spec and event.event_spec.throttle,
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
else:
|
|
27
|
+
_event_specs.append(event)
|
|
28
|
+
return OnF(event_specs=_event_specs, queue=queue)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Live = LiveF()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def Bind(exprA: Expr, exprB: Expr, /):
|
|
35
|
+
return BindF(exprA=exprA, exprB=exprB)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
Set = set_
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def WhenChange(*exprs):
|
|
42
|
+
return WhenF(exprs=exprs)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def Js(javascript: str, /):
|
|
46
|
+
return JsF(javascript)
|