Skip to content

Commit 859bb18

Browse files
committed
Better raverse package export patterns
1 parent 298288e commit 859bb18

File tree

3 files changed

+53
-25
lines changed

3 files changed

+53
-25
lines changed

django_esm/templatetags/esm.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,19 @@
1111

1212

1313
@register.simple_tag
14-
@functools.lru_cache
1514
def importmap():
15+
fn = _importmap if settings.DEBUG else _cached_importmap
16+
return fn()
17+
18+
19+
functools.lru_cache()
20+
21+
22+
def _cached_importmap():
23+
return _importmap()
24+
25+
26+
def _importmap():
1627
with (settings.BASE_DIR / "package.json").open() as f:
1728
package_json = json.load(f)
1829
return mark_safe( # nosec

django_esm/utils.py

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import itertools
12
import json
3+
import re
24
from pathlib import Path
35

46
from django.conf import settings
@@ -24,28 +26,32 @@ def parse_root_package(package_json):
2426
url = mod
2527
if mod[0] in [".", "/"]:
2628
# local file
27-
if mod.endswith("/*"):
28-
mod = mod[:-1]
29-
module_name = module_name[:-1]
30-
url = get_static_from_abs_path(settings.BASE_DIR / mod)
31-
yield module_name, url
29+
yield from get_static_from_abs_path(module_name, settings.BASE_DIR / mod)
30+
else:
31+
yield module_name, url
3232

3333
for dep_name, dep_version in package_json.get("dependencies", {}).items():
3434
yield from parse_package_json(settings.BASE_DIR / "node_modules" / dep_name)
3535

3636

37-
def get_static_from_abs_path(path: Path):
37+
def get_static_from_abs_path(mod: str, path: Path):
3838
for finder in get_finders():
3939
for storage in finder.storages.values():
4040
try:
4141
rel_path = path.relative_to(Path(storage.location).resolve())
4242
except ValueError:
4343
pass
4444
else:
45-
if path.is_dir():
46-
return settings.STATIC_URL + str(rel_path) + "/"
47-
return staticfiles_storage.url(str(rel_path))
48-
raise ValueError(f"Could not find {path} in staticfiles")
45+
if "*" in mod:
46+
for match in Path(storage.location).rglob(
47+
str(rel_path).replace("*", "**/*")
48+
):
49+
sp = str(match.relative_to(Path(storage.location).resolve()))
50+
pattern = re.escape(str(rel_path)).replace(r"\*", r"(.*)")
51+
bit = re.match(pattern, sp).group(1)
52+
yield mod.replace("*", bit), staticfiles_storage.url(sp)
53+
else:
54+
yield mod, staticfiles_storage.url(str(rel_path))
4955

5056

5157
# There is a long history how ESM is supported in Node.js
@@ -71,6 +77,18 @@ def cast_exports(package_json):
7177
return exports
7278

7379

80+
def find_default_key(module):
81+
try:
82+
yield module["default"]
83+
except TypeError:
84+
if isinstance(module, list):
85+
yield from itertools.chain(*(find_default_key(i) for i in module))
86+
else:
87+
yield module
88+
except KeyError:
89+
yield from find_default_key(module["import"])
90+
91+
7492
def parse_package_json(path: Path = None):
7593
"""Parse a project main package.json and return a dict of importmap entries."""
7694
with (path / "package.json").open() as f:
@@ -80,18 +98,19 @@ def parse_package_json(path: Path = None):
8098
exports = cast_exports(package_json)
8199

82100
for module_name, module in exports.items():
83-
try:
84-
mod = module["default"]
85-
except TypeError:
86-
mod = module
101+
module = next(find_default_key(module))
87102

88103
yield str(Path(name) / module_name), staticfiles_storage.url(
89-
str((path / mod).resolve().relative_to(settings.BASE_DIR / "node_modules"))
104+
str(
105+
(path / module)
106+
.resolve()
107+
.relative_to(settings.BASE_DIR / "node_modules")
108+
)
90109
)
91110

92-
if (path / "node_modules").exists():
93-
node_modules = path / "node_modules"
94-
else:
95-
node_modules = path / "/".join(".." for _ in Path(name).parts)
96111
for dep_name, dep_version in dependencies.items():
97-
yield from parse_package_json(node_modules / dep_name)
112+
dep_path = path
113+
while not (dep_path / "node_modules" / dep_name).exists():
114+
dep_path /= ".."
115+
116+
yield from parse_package_json((dep_path / "node_modules" / dep_name).resolve())

tests/test_utils.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_parse_root_package(package_json):
1717
)
1818
assert import_map["lit-html"] == "/static/lit-html/lit-html.js"
1919
assert import_map["#index"] == "/static/js/index.js"
20-
assert import_map["#components/"] == "/static/js/components/"
20+
assert import_map["#components/index.js"] == "/static/js/components/index.js"
2121
assert import_map["#htmx"] == "https://unpkg.com/htmx.org@1.9.10"
2222

2323

@@ -47,6 +47,4 @@ def test_cast_exports():
4747

4848

4949
def test_get_static_from_abs_path():
50-
with pytest.raises(ValueError) as e:
51-
utils.get_static_from_abs_path(Path("/foo/bar"))
52-
assert "Could not find" in str(e.value)
50+
assert not list(utils.get_static_from_abs_path("#some-module", Path("/foo/bar")))

0 commit comments

Comments
 (0)