plain.htmx 0.10.2__tar.gz → 0.10.3__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 (57) hide show
  1. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/PKG-INFO +1 -1
  2. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/CHANGELOG.md +10 -0
  3. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/templates.py +45 -30
  4. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/views.py +12 -6
  5. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/pyproject.toml +1 -1
  6. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/.gitignore +0 -0
  7. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/LICENSE +0 -0
  8. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/README.md +0 -0
  9. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/deps.yml +0 -0
  10. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/package-lock.json +0 -0
  11. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/package.json +0 -0
  12. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/README.md +0 -0
  13. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/__init__.py +0 -0
  14. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/plainhtmx.js +0 -0
  15. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/idiomorph/idiomorph-ext.js +0 -0
  16. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/idiomorph/idiomorph-ext.min.js +0 -0
  17. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/idiomorph/idiomorph-htmx.js +0 -0
  18. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/idiomorph/idiomorph.amd.js +0 -0
  19. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/idiomorph/idiomorph.cjs.js +0 -0
  20. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/idiomorph/idiomorph.esm.js +0 -0
  21. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/idiomorph/idiomorph.js +0 -0
  22. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/idiomorph/idiomorph.min.js +0 -0
  23. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/README.md +0 -0
  24. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/ajax-header.js +0 -0
  25. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/alpine-morph.js +0 -0
  26. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/class-tools.js +0 -0
  27. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/client-side-templates.js +0 -0
  28. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/debug.js +0 -0
  29. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/disable-element.js +0 -0
  30. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/event-header.js +0 -0
  31. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/head-support.js +0 -0
  32. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/include-vals.js +0 -0
  33. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/json-enc.js +0 -0
  34. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/loading-states.js +0 -0
  35. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/method-override.js +0 -0
  36. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/morphdom-swap.js +0 -0
  37. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/multi-swap.js +0 -0
  38. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/path-deps.js +0 -0
  39. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/path-params.js +0 -0
  40. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/preload.js +0 -0
  41. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/rails-method.js +0 -0
  42. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/remove-me.js +0 -0
  43. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/response-targets.js +0 -0
  44. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/restored.js +0 -0
  45. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/sse.js +0 -0
  46. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/ext/ws.js +0 -0
  47. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/htmx.amd.js +0 -0
  48. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/htmx.cjs.js +0 -0
  49. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/htmx.esm.d.ts +0 -0
  50. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/htmx.esm.js +0 -0
  51. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/htmx.js +0 -0
  52. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/htmx.min.js +0 -0
  53. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/assets/htmx/vendor/src/htmx.min.js.gz +0 -0
  54. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/plain/htmx/templates/htmx/js.html +0 -0
  55. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/tests/app/settings.py +0 -0
  56. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/tests/app/urls.py +0 -0
  57. {plain_htmx-0.10.2 → plain_htmx-0.10.3}/tests/test_views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain.htmx
3
- Version: 0.10.2
3
+ Version: 0.10.3
4
4
  Summary: Integrate HTMX with templates and views.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-Expression: BSD-3-Clause
@@ -1,5 +1,15 @@
1
1
  # plain-htmx changelog
2
2
 
3
+ ## [0.10.3](https://github.com/dropseed/plain/releases/plain-htmx@0.10.3) (2025-10-06)
4
+
5
+ ### What's changed
6
+
7
+ - Added type annotations for improved IDE and type checker support ([8cdda13](https://github.com/dropseed/plain/commit/8cdda13a6c))
8
+
9
+ ### Upgrade instructions
10
+
11
+ - No changes required
12
+
3
13
  ## [0.10.2](https://github.com/dropseed/plain/releases/plain-htmx@0.10.2) (2025-10-02)
4
14
 
5
15
  ### What's changed
@@ -1,6 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
1
5
  import jinja2
2
6
  from jinja2 import meta, nodes
3
7
  from jinja2.ext import Extension
8
+ from jinja2.nodes import CallBlock, Node
9
+ from jinja2.parser import Parser
4
10
 
5
11
  from plain.runtime import settings
6
12
  from plain.templates import register_template_extension
@@ -12,7 +18,9 @@ class HTMXJSExtension(InclusionTagExtension):
12
18
  tags = {"htmx_js"}
13
19
  template_name = "htmx/js.html"
14
20
 
15
- def get_context(self, context, *args, **kwargs):
21
+ def get_context(
22
+ self, context: dict[str, Any], *args: Any, **kwargs: Any
23
+ ) -> dict[str, Any]:
16
24
  return {
17
25
  "DEBUG": settings.DEBUG,
18
26
  "extensions": kwargs.get("extensions", []),
@@ -23,11 +31,11 @@ class HTMXJSExtension(InclusionTagExtension):
23
31
  class HTMXFragmentExtension(Extension):
24
32
  tags = {"htmxfragment"}
25
33
 
26
- def __init__(self, environment):
34
+ def __init__(self, environment: jinja2.Environment):
27
35
  super().__init__(environment)
28
36
  environment.extend(htmx_fragment_nodes={})
29
37
 
30
- def parse(self, parser):
38
+ def parse(self, parser: Parser) -> Node:
31
39
  lineno = next(parser.stream).lineno
32
40
 
33
41
  fragment_name = parser.parse_expression()
@@ -42,25 +50,27 @@ class HTMXFragmentExtension(Extension):
42
50
  value = parser.parse_expression()
43
51
  kwargs.append(nodes.Keyword(key, value))
44
52
 
45
- body = parser.parse_statements(["name:endhtmxfragment"], drop_needle=True)
53
+ body = parser.parse_statements(("name:endhtmxfragment",), drop_needle=True)
46
54
 
47
55
  call = self.call_method(
48
56
  "_render_htmx_fragment",
49
- args=[fragment_name, jinja2.nodes.ContextReference()],
57
+ args=[fragment_name, nodes.ContextReference()],
50
58
  kwargs=kwargs,
51
59
  )
52
60
 
53
- node = jinja2.nodes.CallBlock(call, [], [], body).set_lineno(lineno)
61
+ node = CallBlock(call, [], [], body).set_lineno(lineno)
54
62
 
55
63
  # Store a reference to the node for later
56
- self.environment.htmx_fragment_nodes.setdefault(parser.name, {})[
57
- fragment_name.value
64
+ self.environment.htmx_fragment_nodes.setdefault(parser.name, {})[ # type: ignore[attr-defined]
65
+ fragment_name.value # type: ignore[attr-defined]
58
66
  ] = node
59
67
 
60
68
  return node
61
69
 
62
- def _render_htmx_fragment(self, fragment_name, context, caller, **kwargs):
63
- def attrs_to_str(attrs):
70
+ def _render_htmx_fragment(
71
+ self, fragment_name: str, context: dict[str, Any], caller: Any, **kwargs: Any
72
+ ) -> str:
73
+ def attrs_to_str(attrs: dict[str, Any]) -> str:
64
74
  parts = []
65
75
  for k, v in attrs.items():
66
76
  if v == "":
@@ -96,41 +106,46 @@ class HTMXFragmentExtension(Extension):
96
106
  return f'<{as_element} plain-hx-fragment="{fragment_name}" {attrs_str}>{caller()}</{as_element}>'
97
107
 
98
108
 
99
- def render_template_fragment(*, template, fragment_name, context):
109
+ def render_template_fragment(
110
+ *, template: jinja2.Template, fragment_name: str, context: dict[str, Any]
111
+ ) -> str:
100
112
  template = find_template_fragment(template, fragment_name)
101
113
  return template.render(context)
102
114
 
103
115
 
104
- def find_template_fragment(template: jinja2.Template, fragment_name: str):
116
+ def find_template_fragment(
117
+ template: jinja2.Template, fragment_name: str
118
+ ) -> jinja2.Template:
105
119
  # Look in this template for the fragment
106
- callblock_node = template.environment.htmx_fragment_nodes.get(
120
+ callblock_node = template.environment.htmx_fragment_nodes.get( # type: ignore[attr-defined]
107
121
  template.name, {}
108
122
  ).get(fragment_name)
109
123
 
110
124
  if not callblock_node:
111
125
  # Look in other templates for this fragment
112
126
  matching_callblock_nodes = []
113
- for fragments in template.environment.htmx_fragment_nodes.values():
127
+ for fragments in template.environment.htmx_fragment_nodes.values(): # type: ignore[attr-defined]
114
128
  if fragment_name in fragments:
115
129
  matching_callblock_nodes.append(fragments[fragment_name])
116
130
 
117
131
  if len(matching_callblock_nodes) == 0:
118
132
  # If we still haven't found anything, it's possible that we're
119
133
  # in a different/new worker/process and haven't parsed the related templates yet
120
- ast = template.environment.parse(
121
- template.environment.loader.get_source(
122
- template.environment, template.name
123
- )[0]
124
- )
125
- for ref in meta.find_referenced_templates(ast):
126
- if ref not in template.environment.htmx_fragment_nodes:
127
- # Trigger them to parse
128
- template.environment.get_template(ref)
129
-
130
- # Now look again
131
- for fragments in template.environment.htmx_fragment_nodes.values():
132
- if fragment_name in fragments:
133
- matching_callblock_nodes.append(fragments[fragment_name])
134
+ if template.environment.loader and template.name:
135
+ ast = template.environment.parse(
136
+ template.environment.loader.get_source(
137
+ template.environment, template.name
138
+ )[0]
139
+ )
140
+ for ref in meta.find_referenced_templates(ast):
141
+ if ref not in template.environment.htmx_fragment_nodes: # type: ignore[attr-defined]
142
+ # Trigger them to parse
143
+ template.environment.get_template(ref)
144
+
145
+ # Now look again
146
+ for fragments in template.environment.htmx_fragment_nodes.values(): # type: ignore[attr-defined]
147
+ if fragment_name in fragments:
148
+ matching_callblock_nodes.append(fragments[fragment_name])
134
149
 
135
150
  if len(matching_callblock_nodes) == 1:
136
151
  callblock_node = matching_callblock_nodes[0]
@@ -149,5 +164,5 @@ def find_template_fragment(template: jinja2.Template, fragment_name: str):
149
164
  )
150
165
 
151
166
  # Create a new template from the node
152
- template_node = jinja2.nodes.Template(callblock_node.body)
153
- return template.environment.from_string(template_node)
167
+ template_node = nodes.Template(callblock_node.body) # type: ignore[attr-defined]
168
+ return template.environment.from_string(template_node) # type: ignore[arg-type]
@@ -1,10 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable
4
+ from typing import Any
5
+
6
+ from plain.http import Response
1
7
  from plain.utils.cache import patch_vary_headers
2
8
 
3
9
  from .templates import render_template_fragment
4
10
 
5
11
 
6
12
  class HTMXViewMixin:
7
- def render_template(self):
13
+ def render_template(self) -> str:
8
14
  template = self.get_template()
9
15
  context = self.get_template_context()
10
16
 
@@ -17,7 +23,7 @@ class HTMXViewMixin:
17
23
 
18
24
  return template.render(context)
19
25
 
20
- def get_response(self):
26
+ def get_response(self) -> Response:
21
27
  response = super().get_response()
22
28
  # Tell browser caching to also consider the fragment header,
23
29
  # not just the url/cookie.
@@ -26,7 +32,7 @@ class HTMXViewMixin:
26
32
  )
27
33
  return response
28
34
 
29
- def get_request_handler(self):
35
+ def get_request_handler(self) -> Callable[..., Any]:
30
36
  if self.is_htmx_request():
31
37
  # You can use an htmx_{method} method on views
32
38
  # (or htmx_{method}_{action} for specific actions)
@@ -45,12 +51,12 @@ class HTMXViewMixin:
45
51
 
46
52
  return super().get_request_handler()
47
53
 
48
- def is_htmx_request(self):
54
+ def is_htmx_request(self) -> bool:
49
55
  return self.request.headers.get("HX-Request") == "true"
50
56
 
51
- def get_htmx_fragment_name(self):
57
+ def get_htmx_fragment_name(self) -> str:
52
58
  # A custom header that we pass with the {% htmxfragment %} tag
53
59
  return self.request.headers.get("Plain-HX-Fragment", "")
54
60
 
55
- def get_htmx_action_name(self):
61
+ def get_htmx_action_name(self) -> str:
56
62
  return self.request.headers.get("Plain-HX-Action", "")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "plain.htmx"
3
- version = "0.10.2"
3
+ version = "0.10.3"
4
4
  description = "Integrate HTMX with templates and views."
5
5
  authors = [{name = "Dave Gaeddert", email = "dave.gaeddert@dropseed.dev"}]
6
6
  license = "BSD-3-Clause"
File without changes
File without changes
File without changes
File without changes
File without changes