python-fragments 0.25__tar.gz → 0.27__tar.gz
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.
- {python_fragments-0.25 → python_fragments-0.27}/PKG-INFO +1 -1
- {python_fragments-0.25 → python_fragments-0.27}/fragments/ast_nodes.py +5 -3
- {python_fragments-0.25 → python_fragments-0.27}/fragments/grammar.py +3 -1
- {python_fragments-0.25 → python_fragments-0.27}/fragments/html/elements.py +1 -1
- {python_fragments-0.25 → python_fragments-0.27}/pyproject.toml +1 -1
- {python_fragments-0.25 → python_fragments-0.27}/python_fragments.egg-info/PKG-INFO +1 -1
- {python_fragments-0.25 → python_fragments-0.27}/python_fragments.egg-info/SOURCES.txt +1 -0
- {python_fragments-0.25 → python_fragments-0.27}/tests/test_grammar.py +23 -0
- python_fragments-0.27/tests/test_html_elements.py +31 -0
- {python_fragments-0.25 → python_fragments-0.27}/README.md +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/__init__.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/cli.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/html/__init__.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/loader.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/__init__.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/based_proxy.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/__init__.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/code_actions.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/completion.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/definition.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/diagnostics.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/document_highlight.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/document_symbols.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/folding_range.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/hover.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/inlay_hints.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/lifecycle.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/references.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/rename.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/semantic_tokens.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/signature_help.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/file_state.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/message_queue.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/pyright_notification_handlers/__init__.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/pyright_notification_handlers/capability.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/pyright_notification_handlers/configuration.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/pyright_notification_handlers/diagnostics.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/types.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/source.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/transpiler.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/fragments/types.py +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/python_fragments.egg-info/dependency_links.txt +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/python_fragments.egg-info/entry_points.txt +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/python_fragments.egg-info/requires.txt +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/python_fragments.egg-info/top_level.txt +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/setup.cfg +0 -0
- {python_fragments-0.25 → python_fragments-0.27}/tests/test_source_map.py +0 -0
|
@@ -91,7 +91,8 @@ class ASTFragment:
|
|
|
91
91
|
for child in self.children:
|
|
92
92
|
child.transpile(transpiled_start)
|
|
93
93
|
transpiled_start = child.transpiled_end + 1
|
|
94
|
-
|
|
94
|
+
if len(self.children) > 0:
|
|
95
|
+
transpiled_start -= 1
|
|
95
96
|
|
|
96
97
|
self.transpiled_content = self.__template__.format(",".join(child.transpiled_content for child in self.children))
|
|
97
98
|
self.transpiled_end = self.transpiled_start + len(self.transpiled_content)
|
|
@@ -133,7 +134,7 @@ class ASTHTMLElement:
|
|
|
133
134
|
for child in self.children:
|
|
134
135
|
child.transpile(transpiled_start)
|
|
135
136
|
transpiled_start = child.transpiled_end + 1
|
|
136
|
-
if self.children:
|
|
137
|
+
if len(self.children) > 0:
|
|
137
138
|
transpiled_start -= 1
|
|
138
139
|
children = ",".join(child.transpiled_content for child in self.children)
|
|
139
140
|
oneline_offset = len(str(self.one_line))
|
|
@@ -406,7 +407,8 @@ class ASTHTMLComment:
|
|
|
406
407
|
|
|
407
408
|
def transpile(self, transpiled_start: int) -> None:
|
|
408
409
|
self.transpiled_start = transpiled_start
|
|
409
|
-
|
|
410
|
+
escaped_content = self.content.replace("\n", "\\n").replace("\t", "\\t").replace("\r", "\\r").replace('"', '\\"')
|
|
411
|
+
self.transpiled_content = self.__template__.format(escaped_content)
|
|
410
412
|
self.transpiled_end = self.transpiled_start + len(self.transpiled_content)
|
|
411
413
|
|
|
412
414
|
def map_offset(self, offset: int) -> None:
|
|
@@ -269,7 +269,9 @@ def expect_children(source: Source) -> tuple[Source, list[ASTHTMLChild]]:
|
|
|
269
269
|
while not source.remaining().startswith("</"):
|
|
270
270
|
source, child = expect_child(source)
|
|
271
271
|
children.append(child)
|
|
272
|
-
|
|
272
|
+
source_after_whitespace, _ = source.eat_whitespace()
|
|
273
|
+
if not source_after_whitespace.remaining().startswith("{{"):
|
|
274
|
+
source = source_after_whitespace
|
|
273
275
|
return source, children
|
|
274
276
|
|
|
275
277
|
|
|
@@ -18,7 +18,7 @@ def el(
|
|
|
18
18
|
name,
|
|
19
19
|
className_to_string(attributes.pop("className")) if "className" in attributes else None,
|
|
20
20
|
style_to_string(attributes.pop("style")) if "style" in attributes else None,
|
|
21
|
-
attributes_to_string(attributes) if attributes
|
|
21
|
+
attributes_to_string(attributes) if attributes else None,
|
|
22
22
|
]
|
|
23
23
|
tag_contents = [item for item in tag_contents if item is not None]
|
|
24
24
|
tag_contents_string = " ".join(tag_contents)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-fragments"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.27"
|
|
8
8
|
description = "Modern HTML template rendering in Python"
|
|
9
9
|
authors = [{ name = "The Running Algorithm", email = "services@therunningalgorithm.info" }]
|
|
10
10
|
readme = "README.md"
|
|
@@ -46,6 +46,16 @@ def test_comment_multiline():
|
|
|
46
46
|
]))
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
def test_comment_multiline_escaped_in_transpile():
|
|
50
|
+
source = Source.from_string("<><!-- line one\nline two --></>")
|
|
51
|
+
_, fragment = grammar.expect_fragment(source)
|
|
52
|
+
fragment.transpile(0)
|
|
53
|
+
comment = fragment.children[0]
|
|
54
|
+
assert isinstance(comment, ASTHTMLComment)
|
|
55
|
+
assert "\\n" in comment.transpiled_content
|
|
56
|
+
assert "\n" not in comment.transpiled_content
|
|
57
|
+
|
|
58
|
+
|
|
49
59
|
def test_comment_inside_element():
|
|
50
60
|
source = Source.from_string("<><div><!-- note --></div></>")
|
|
51
61
|
source, fragment = grammar.expect_fragment(source)
|
|
@@ -362,6 +372,19 @@ def test_html_text_multiline_before_child_element():
|
|
|
362
372
|
]))
|
|
363
373
|
|
|
364
374
|
|
|
375
|
+
def test_whitespace_between_adjacent_interpolations_is_preserved():
|
|
376
|
+
source = Source.from_string("<><p>{{ a }} {{ b }}</p></>")
|
|
377
|
+
source, fragment = grammar.expect_fragment(source)
|
|
378
|
+
assert source.at_end()
|
|
379
|
+
assert _transpiled(fragment) == _transpiled(ASTFragment(-1, -1, [
|
|
380
|
+
ASTHTMLElement(-1, -1, "p", {}, [
|
|
381
|
+
ASTInterpolation(-1, -1, "a", 1, 1),
|
|
382
|
+
ASTHTMLText(-1, -1, " "),
|
|
383
|
+
ASTInterpolation(-1, -1, "b", 1, 1),
|
|
384
|
+
], False)
|
|
385
|
+
]))
|
|
386
|
+
|
|
387
|
+
|
|
365
388
|
# ---------------------------------------------------------------------------
|
|
366
389
|
# Full integration (updated for new AST structure)
|
|
367
390
|
# ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from fragments.html.elements import el, className_to_string
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_className_list_joined_with_spaces():
|
|
5
|
+
result = className_to_string(["foo", "bar", "baz"])
|
|
6
|
+
assert result == 'class="foo bar baz"'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_className_empty_list():
|
|
10
|
+
result = className_to_string([])
|
|
11
|
+
assert result == 'class=""'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_className_single_item_list():
|
|
15
|
+
result = className_to_string(["only"])
|
|
16
|
+
assert result == 'class="only"'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_className_string_passthrough():
|
|
20
|
+
result = className_to_string("already-a-string")
|
|
21
|
+
assert result == 'class="already-a-string"'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_el_className_list_attribute():
|
|
25
|
+
result = el("div", ["content"], False, {"className": ["foo", "bar"]})
|
|
26
|
+
assert result == '<div class="foo bar">content</div>'
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_el_className_empty_list():
|
|
30
|
+
result = el("div", [], True, {"className": []})
|
|
31
|
+
assert result == '<div class="" />'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/completion.py
RENAMED
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/definition.py
RENAMED
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/diagnostics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/hover.py
RENAMED
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/inlay_hints.py
RENAMED
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/lifecycle.py
RENAMED
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/references.py
RENAMED
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/fragments/lsp/client_message_handlers/rename.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_fragments-0.25 → python_fragments-0.27}/python_fragments.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|