jx 0.1.0__py3-none-any.whl → 0.3.0__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.
jx/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
1
  """
2
- Jx | Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
2
+ Jx | Copyright (c) Juan-Pablo Scaletti
3
3
  """
4
+
4
5
  from .catalog import CData, Catalog # noqa
5
6
  from .exceptions import * # noqa
jx/attrs.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
- Jx | Copyright (c) Juan-Pablo Scaletti <juanpablo@jpscaletti.com>
2
+ Jx | Copyright (c) Juan-Pablo Scaletti
3
3
  """
4
- import re
4
+
5
5
  import typing as t
6
6
  from collections import UserString
7
7
  from functools import cached_property
@@ -14,10 +14,6 @@ CLASS_ALT_KEY = "classes"
14
14
  CLASS_KEYS = (CLASS_KEY, CLASS_ALT_KEY)
15
15
 
16
16
 
17
- def split(ssl: str) -> list[str]:
18
- return re.split(r"\s+", ssl.strip())
19
-
20
-
21
17
  def quote(text: str) -> str:
22
18
  if '"' in text:
23
19
  if "'" in text:
@@ -30,14 +26,13 @@ def quote(text: str) -> str:
30
26
 
31
27
 
32
28
  class LazyString(UserString):
33
- """
34
- Behave like regular strings, but the actual casting of the initial value
35
- is deferred until the value is actually required.
36
- """
37
-
38
29
  __slots__ = ("_seq",)
39
30
 
40
31
  def __init__(self, seq):
32
+ """
33
+ Behave like regular strings, but the actual casting of the initial value
34
+ is deferred until the value is actually required.
35
+ """
41
36
  self._seq = seq
42
37
 
43
38
  @cached_property
@@ -46,29 +41,36 @@ class LazyString(UserString):
46
41
 
47
42
 
48
43
  class Attrs:
49
- """
50
- Contains all the HTML attributes/properties (a property is an
51
- attribute without a value) passed to a component but that weren't
52
- in the declared attributes list.
44
+ __classes: tuple[str, ...]
45
+ __attributes: dict[str, str | LazyString]
46
+ __properties: set[str]
53
47
 
54
- For HTML classes you can use the name "classes" (instead of "class")
55
- if you need to.
48
+ def __init__(self, attrs: "dict[str, t.Any| LazyString]") -> None:
49
+ """
50
+ Contains all the HTML attributes/properties (a property is an
51
+ attribute without a value) passed to a component but that weren't
52
+ in the declared attributes list.
56
53
 
57
- **NOTE**: The string values passed to this class, are not cast to `str` until
58
- the string representation is actually needed, for example when
59
- `attrs.render()` is invoked.
54
+ For HTML classes you can use the name "classes" (instead of "class")
55
+ if you need to.
60
56
 
61
- """
57
+ **NOTE**: The string values passed to this class, are not cast to `str` until
58
+ the string representation is actually needed, for example when
59
+ `attrs.render()` is invoked.
62
60
 
63
- def __init__(self, attrs: "dict[str, t.Any| LazyString]") -> None:
61
+ """
64
62
  attributes: "dict[str, str | LazyString]" = {}
65
63
  properties: set[str] = set()
66
64
 
67
- class_names = split(" ".join([
65
+ class_names = (" ".join([
68
66
  str(attrs.pop(CLASS_KEY, "")),
69
67
  str(attrs.get(CLASS_ALT_KEY, "")),
70
- ]))
71
- self.__classes = {name for name in class_names if name}
68
+ ])).strip().split()
69
+ classes = []
70
+ for name in class_names:
71
+ if name and name not in classes:
72
+ classes.append(name)
73
+ self.__classes = tuple(classes)
72
74
 
73
75
  for name, value in attrs.items():
74
76
  if name.startswith("_"):
@@ -85,19 +87,19 @@ class Attrs:
85
87
  @property
86
88
  def classes(self) -> str:
87
89
  """
88
- All the HTML classes alphabetically sorted and separated by a space.
90
+ All the HTML classes separated by a space.
89
91
 
90
92
  Example:
91
93
 
92
94
  ```python
93
- attrs = HTMLAttrs({"class": "italic bold bg-blue wide abcde"})
95
+ attrs = Attrs({"class": "italic bold bg-blue wide abcde"})
94
96
  attrs.set(class="bold text-white")
95
97
  print(attrs.classes)
96
- abcde bg-blue bold italic text-white wide
98
+ italic bold bg-blue wide abcde text-white
97
99
  ```
98
100
 
99
101
  """
100
- return " ".join(sorted((self.__classes)))
102
+ return " ".join(self.__classes)
101
103
 
102
104
  @property
103
105
  def as_dict(self) -> dict[str, t.Any]:
@@ -108,7 +110,7 @@ class Attrs:
108
110
  Example:
109
111
 
110
112
  ```python
111
- attrs = HTMLAttrs({
113
+ attrs = Attrs({
112
114
  "class": "lorem ipsum",
113
115
  "data_test": True,
114
116
  "hidden": True,
@@ -118,7 +120,7 @@ class Attrs:
118
120
  attrs.as_dict
119
121
  {
120
122
  "aria_label": "hello",
121
- "class": "ipsum lorem",
123
+ "class": "lorem ipsum",
122
124
  "id": "world",
123
125
  "data_test": True,
124
126
  "hidden": True
@@ -160,7 +162,7 @@ class Attrs:
160
162
  Example:
161
163
 
162
164
  ```python
163
- attrs = HTMLAttrs({"secret": "qwertyuiop"})
165
+ attrs = Attrs({"secret": "qwertyuiop"})
164
166
  attrs.set(secret=False)
165
167
  attrs.as_dict
166
168
  {}
@@ -169,10 +171,10 @@ class Attrs:
169
171
  attrs.as_dict
170
172
  {"count":42, "lorem":"ipsum", "data_good": True}
171
173
 
172
- attrs = HTMLAttrs({"class": "b c a"})
174
+ attrs = Attrs({"class": "b c a"})
173
175
  attrs.set(class="c b f d e")
174
176
  attrs.as_dict
175
- {"class": "a b c d e f"}
177
+ {"class": "b c a f d e"}
176
178
  ```
177
179
 
178
180
  """
@@ -199,7 +201,7 @@ class Attrs:
199
201
  Example:
200
202
 
201
203
  ```python
202
- attrs = HTMLAttrs({"lorem": "ipsum"})
204
+ attrs = Attrs({"lorem": "ipsum"})
203
205
  attrs.setdefault(tabindex=0, lorem="meh")
204
206
  attrs.as_dict
205
207
  # "tabindex" changed but "lorem" didn't
@@ -212,7 +214,9 @@ class Attrs:
212
214
  continue
213
215
 
214
216
  if name in CLASS_KEYS:
215
- self.add_class(value)
217
+ if not self.__classes:
218
+ self.add_class(value)
219
+ continue
216
220
 
217
221
  name = name.replace("_", "-")
218
222
  if name not in self.__attributes:
@@ -220,21 +224,55 @@ class Attrs:
220
224
 
221
225
  def add_class(self, *values: str) -> None:
222
226
  """
223
- Adds one or more classes to the list of classes, if not already present.
227
+ Adds one or more classes to the end of the list of classes,
228
+ if not already present.
229
+
230
+ Arguments:
231
+ values:
232
+ One or more class names to add, separated by spaces.
224
233
 
225
234
  Example:
226
235
 
227
236
  ```python
228
- attrs = HTMLAttrs({"class": "a b c"})
229
- attrs.add_class("c", "d")
237
+ attrs = Attrs({"class": "a b c"})
238
+ attrs.add_class("c d")
230
239
  attrs.as_dict
231
240
  {"class": "a b c d"}
232
241
  ```
233
242
 
234
243
  """
235
244
  for names in values:
236
- for name in split(names):
237
- self.__classes.add(name)
245
+ for name in names.strip().split():
246
+ if name not in self.__classes:
247
+ self.__classes += (name,)
248
+
249
+ def prepend_class(self, *values: str) -> None:
250
+ """
251
+ Adds one or more classes to the beginning of the list of classes,
252
+ if not already present.
253
+
254
+ Arguments:
255
+ values:
256
+ One or more class names to add, separated by spaces.
257
+
258
+ Example:
259
+
260
+ ```python
261
+ attrs = Attrs({"class": "a b c"})
262
+ attrs.add_class("c d |")
263
+ attrs.as_dict
264
+ {"class": "d | a b c"}
265
+ ```
266
+
267
+ """
268
+ new_classes = [
269
+ name
270
+ for names in values
271
+ for name in names.strip().split()
272
+ if name not in self.__classes
273
+ ]
274
+
275
+ self.__classes = tuple(new_classes) + self.__classes
238
276
 
239
277
  def remove_class(self, *names: str) -> None:
240
278
  """
@@ -243,25 +281,32 @@ class Attrs:
243
281
  Example:
244
282
 
245
283
  ```python
246
- attrs = HTMLAttrs({"class": "a b c"})
284
+ attrs = Attrs({"class": "a b c"})
247
285
  attrs.remove_class("c", "d")
248
286
  attrs.as_dict
249
287
  {"class": "a b"}
250
288
  ```
251
289
 
252
290
  """
253
- for name in names:
254
- self.__classes.remove(name)
291
+ self.__classes = tuple(c for c in self.__classes if c not in names)
255
292
 
256
293
  def get(self, name: str, default: t.Any = None) -> t.Any:
257
294
  """
258
295
  Returns the value of the attribute or property,
259
296
  or the default value if it doesn't exists.
260
297
 
298
+ Arguments:
299
+
300
+ name:
301
+ The name of the attribute or property to get.
302
+
303
+ default:
304
+ The default value to return if the attribute or property doesn't exist.
305
+
261
306
  Example:
262
307
 
263
308
  ```python
264
- attrs = HTMLAttrs({"lorem": "ipsum", "hidden": True})
309
+ attrs = Attrs({"lorem": "ipsum", "hidden": True})
265
310
 
266
311
  attrs.get("lorem", defaut="bar")
267
312
  'ipsum'
@@ -291,7 +336,7 @@ class Attrs:
291
336
  Renders the attributes and properties as a string.
292
337
 
293
338
  Any arguments you use with this function are merged with the existing
294
- attibutes/properties by the same rules as the `HTMLAttrs.set()` function:
339
+ attibutes/properties by the same rules as the `Attrs.set()` function:
295
340
 
296
341
  - Pass a name and a value to set an attribute (e.g. `type="text"`)
297
342
  - Use `True` as a value to set a property (e.g. `disabled`)
@@ -308,7 +353,7 @@ class Attrs:
308
353
  Example:
309
354
 
310
355
  ```python
311
- attrs = HTMLAttrs({"class": "ipsum", "data_good": True, "width": 42})
356
+ attrs = Attrs({"class": "ipsum", "data_good": True, "width": 42})
312
357
 
313
358
  attrs.render()
314
359
  'class="ipsum" width="42" data-good'
@@ -345,7 +390,7 @@ class Attrs:
345
390
  Removes an attribute or property.
346
391
  """
347
392
  if name in CLASS_KEYS:
348
- self.__classes = set()
393
+ self.__classes = ()
349
394
  if name in self.__attributes:
350
395
  del self.__attributes[name]
351
396
  if name in self.__properties: