Skip to content

Commit 586fec9

Browse files
committed
Fix fingerprinting of assets
For components with prefixes or loaded from cache.
1 parent 4fdb53f commit 586fec9

4 files changed

Lines changed: 33 additions & 29 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ requires = ["setuptools"]
44

55
[project]
66
name = "jinjax"
7-
version = "0.59"
7+
version = "0.60"
88
description = "Replace your HTML templates with Python server-Side components"
99
authors = [
1010
{name = "Juan Pablo Scaletti", email = "juanpablo@jpscaletti.com"},

src/jinjax/component.py

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def __init__(
133133

134134
self.path = path
135135
self.relpath = relpath
136-
self.root_path = Path(str(path).removesuffix(str(relpath))) if path else None
136+
self.root_path = self._get_root_path()
137137
self.mtime = mtime
138138
self.tmpl = tmpl
139139

@@ -152,37 +152,19 @@ def from_cache(
152152
return None
153153

154154
self = cls(name=cache["name"])
155-
self.prefix = cache["prefix"]
156-
self.url_prefix = cache["url_prefix"]
157-
self.required = cache["required"]
158-
self.optional = cache["optional"]
159-
self.css = cache["css"]
160-
self.js = cache["js"]
161-
self.path = path
162-
self.mtime = cache["mtime"]
163-
self.tmpl = cache["tmpl"]
155+
for key in self.__slots__:
156+
setattr(self, key, cache[key])
164157

165-
if self.tmpl and globals:
158+
if self.tmpl:
166159
# Create a copy of the globals dictionary to ensure thread safety
167160
globals_copy = {**self.tmpl.globals}
168-
globals_copy.update(globals)
161+
globals_copy.update(globals or {})
169162
self.tmpl.globals = globals_copy
170163

171164
return self
172165

173166
def serialize(self) -> dict[str, t.Any]:
174-
return {
175-
"name": self.name,
176-
"prefix": self.prefix,
177-
"url_prefix": self.url_prefix,
178-
"required": self.required,
179-
"optional": self.optional,
180-
"css": self.css,
181-
"js": self.js,
182-
"path": self.path,
183-
"mtime": self.mtime,
184-
"tmpl": self.tmpl,
185-
}
167+
return {k: getattr(self, k) for k in self.__slots__}
186168

187169
def load_metadata(self, source: str) -> None:
188170
match = RX_META_HEADER.match(source)
@@ -279,3 +261,13 @@ def render(self, **kwargs):
279261

280262
def __repr__(self) -> str:
281263
return f'<Component "{self.name}">'
264+
265+
def _get_root_path(self) -> Path | None:
266+
"""Get the root path of the component."""
267+
if self.path is None or self.relpath is None:
268+
return None
269+
suffix = str(self.relpath.as_posix())
270+
if self.url_prefix:
271+
suffix = f"{self.url_prefix}{suffix}"
272+
273+
return Path(str(self.path).removesuffix(str(suffix)))

tests/test_render_assets.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,19 @@ def test_fingerprint_assets(catalog, folder: Path, autoescape, undefined):
139139

140140
subfolder = folder / "sub"
141141
subfolder.mkdir()
142+
prefixed = folder/ "ui"
143+
prefixed.mkdir()
144+
145+
catalog.add_folder(prefixed, prefix="ui")
146+
142147
(folder / "app.css").write_text("...")
143148
(subfolder / "sub.css").write_text("...")
149+
(prefixed / "button.css").write_text("...")
150+
151+
(prefixed / "Button.jinja").write_text("""
152+
{#css button.css #}
153+
<button class="btn">{{ content }}</button>
154+
""")
144155

145156
(folder / "Layout.jinja").write_text("""
146157
<html>
@@ -150,9 +161,9 @@ def test_fingerprint_assets(catalog, folder: Path, autoescape, undefined):
150161
""")
151162

152163
(folder / "Page.jinja").write_text("""
153-
{#css app.css, sub/sub.css, http://example.com/super.css #}
164+
{#css app.css, sub/sub.css, http://example.com/external.css #}
154165
{#js app.js #}
155-
<Layout>Hi</Layout>
166+
<Layout><ui:Button>Hi</ui:Button></Layout>
156167
""")
157168

158169
catalog.fingerprint = True
@@ -163,11 +174,12 @@ def test_fingerprint_assets(catalog, folder: Path, autoescape, undefined):
163174
assert 'src="/static/components/app.js"' in html
164175

165176
# external URLs are not fingerprinted
166-
assert 'href="http://example.com/super.css' in html
177+
assert 'href="http://example.com/external.css' in html
167178

168179
# fingerprinted assets
169180
assert 'href="/static/components/sub/sub-' in html
170181
assert 'href="/static/components/app-' in html
182+
assert 'href="/static/components/ui/button-' in html
171183

172184

173185
@pytest.mark.parametrize("undefined", [jinja2.Undefined, jinja2.StrictUndefined])

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)