python-fragments 0.26__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.
Files changed (47) hide show
  1. {python_fragments-0.26 → python_fragments-0.27}/PKG-INFO +1 -1
  2. {python_fragments-0.26 → python_fragments-0.27}/fragments/ast_nodes.py +5 -3
  3. {python_fragments-0.26 → python_fragments-0.27}/fragments/html/elements.py +1 -1
  4. {python_fragments-0.26 → python_fragments-0.27}/pyproject.toml +1 -1
  5. {python_fragments-0.26 → python_fragments-0.27}/python_fragments.egg-info/PKG-INFO +1 -1
  6. {python_fragments-0.26 → python_fragments-0.27}/python_fragments.egg-info/SOURCES.txt +1 -0
  7. {python_fragments-0.26 → python_fragments-0.27}/tests/test_grammar.py +10 -0
  8. python_fragments-0.27/tests/test_html_elements.py +31 -0
  9. {python_fragments-0.26 → python_fragments-0.27}/README.md +0 -0
  10. {python_fragments-0.26 → python_fragments-0.27}/fragments/__init__.py +0 -0
  11. {python_fragments-0.26 → python_fragments-0.27}/fragments/cli.py +0 -0
  12. {python_fragments-0.26 → python_fragments-0.27}/fragments/grammar.py +0 -0
  13. {python_fragments-0.26 → python_fragments-0.27}/fragments/html/__init__.py +0 -0
  14. {python_fragments-0.26 → python_fragments-0.27}/fragments/loader.py +0 -0
  15. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/__init__.py +0 -0
  16. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/based_proxy.py +0 -0
  17. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/__init__.py +0 -0
  18. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/code_actions.py +0 -0
  19. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/completion.py +0 -0
  20. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/definition.py +0 -0
  21. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/diagnostics.py +0 -0
  22. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/document_highlight.py +0 -0
  23. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/document_symbols.py +0 -0
  24. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/folding_range.py +0 -0
  25. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/hover.py +0 -0
  26. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/inlay_hints.py +0 -0
  27. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/lifecycle.py +0 -0
  28. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/references.py +0 -0
  29. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/rename.py +0 -0
  30. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/semantic_tokens.py +0 -0
  31. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/client_message_handlers/signature_help.py +0 -0
  32. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/file_state.py +0 -0
  33. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/message_queue.py +0 -0
  34. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/pyright_notification_handlers/__init__.py +0 -0
  35. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/pyright_notification_handlers/capability.py +0 -0
  36. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/pyright_notification_handlers/configuration.py +0 -0
  37. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/pyright_notification_handlers/diagnostics.py +0 -0
  38. {python_fragments-0.26 → python_fragments-0.27}/fragments/lsp/types.py +0 -0
  39. {python_fragments-0.26 → python_fragments-0.27}/fragments/source.py +0 -0
  40. {python_fragments-0.26 → python_fragments-0.27}/fragments/transpiler.py +0 -0
  41. {python_fragments-0.26 → python_fragments-0.27}/fragments/types.py +0 -0
  42. {python_fragments-0.26 → python_fragments-0.27}/python_fragments.egg-info/dependency_links.txt +0 -0
  43. {python_fragments-0.26 → python_fragments-0.27}/python_fragments.egg-info/entry_points.txt +0 -0
  44. {python_fragments-0.26 → python_fragments-0.27}/python_fragments.egg-info/requires.txt +0 -0
  45. {python_fragments-0.26 → python_fragments-0.27}/python_fragments.egg-info/top_level.txt +0 -0
  46. {python_fragments-0.26 → python_fragments-0.27}/setup.cfg +0 -0
  47. {python_fragments-0.26 → python_fragments-0.27}/tests/test_source_map.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fragments
3
- Version: 0.26
3
+ Version: 0.27
4
4
  Summary: Modern HTML template rendering in Python
5
5
  Author-email: The Running Algorithm <services@therunningalgorithm.info>
6
6
  License: Proprietary
@@ -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
- transpiled_start -= 1
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
- self.transpiled_content = self.__template__.format(self.content)
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:
@@ -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 is not None else None,
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.26"
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"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fragments
3
- Version: 0.26
3
+ Version: 0.27
4
4
  Summary: Modern HTML template rendering in Python
5
5
  Author-email: The Running Algorithm <services@therunningalgorithm.info>
6
6
  License: Proprietary
@@ -41,4 +41,5 @@ python_fragments.egg-info/entry_points.txt
41
41
  python_fragments.egg-info/requires.txt
42
42
  python_fragments.egg-info/top_level.txt
43
43
  tests/test_grammar.py
44
+ tests/test_html_elements.py
44
45
  tests/test_source_map.py
@@ -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)
@@ -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="" />'