|
2 | 2 |
|
3 | 3 | from pathlib import Path
|
4 | 4 | from typing import Any
|
| 5 | +from urllib.parse import urljoin |
5 | 6 | from uuid import uuid4
|
6 | 7 |
|
7 |
| -from reactpy import component, html |
| 8 | +from reactpy import component, event, html, use_connection |
8 | 9 | from reactpy.backend.types import Location
|
9 | 10 | from reactpy.core.component import Component
|
10 | 11 | from reactpy.core.types import VdomDict
|
|
25 | 26 | )
|
26 | 27 | """Client-side portion of link handling"""
|
27 | 28 |
|
| 29 | +link_js_content = (Path(__file__).parent / "static" / "link.js").read_text(encoding="utf-8") |
| 30 | + |
28 | 31 |
|
29 | 32 | def link(attributes: dict[str, Any], *children: Any) -> Component:
|
30 | 33 | """Create a link with the given attributes and children."""
|
@@ -55,10 +58,42 @@ def _link(attributes: dict[str, Any], *children: Any) -> VdomDict:
|
55 | 58 | "className": class_name,
|
56 | 59 | }
|
57 | 60 |
|
| 61 | + # FIXME: This component currently works in a "dumb" way by trusting that ReactPy's script tag \ |
| 62 | + # properly sets the location due to bugs in ReactPy rendering. |
| 63 | + # https://github.com/reactive-python/reactpy/pull/1224 |
| 64 | + current_path = use_connection().location.pathname |
| 65 | + |
| 66 | + @event(prevent_default=True) |
58 | 67 | def on_click(_event: dict[str, Any]) -> None:
|
59 |
| - set_location(Location(**_event)) |
| 68 | + pathname, search = to.split("?", 1) if "?" in to else (to, "") |
| 69 | + if search: |
| 70 | + search = f"?{search}" |
| 71 | + |
| 72 | + # Resolve relative paths that match `../foo` |
| 73 | + if pathname.startswith("../"): |
| 74 | + pathname = urljoin(current_path, pathname) |
| 75 | + |
| 76 | + # Resolve relative paths that match `foo` |
| 77 | + if not pathname.startswith("/"): |
| 78 | + pathname = urljoin(current_path, pathname) |
| 79 | + |
| 80 | + # Resolve relative paths that match `/foo/../bar` |
| 81 | + while "/../" in pathname: |
| 82 | + part_1, part_2 = pathname.split("/../", 1) |
| 83 | + pathname = urljoin(f"{part_1}/", f"../{part_2}") |
| 84 | + |
| 85 | + # Resolve relative paths that match `foo/./bar` |
| 86 | + pathname = pathname.replace("/./", "/") |
| 87 | + |
| 88 | + set_location(Location(pathname, search)) |
| 89 | + |
| 90 | + attrs["onClick"] = on_click |
| 91 | + |
| 92 | + return html._(html.a(attrs, *children), html.script(link_js_content.replace("UUID", uuid_string))) |
60 | 93 |
|
61 |
| - return html._(html.a(attrs, *children), Link({"onClick": on_click, "linkClass": uuid_string})) |
| 94 | + # def on_click(_event: dict[str, Any]) -> None: |
| 95 | + # set_location(Location(**_event)) |
| 96 | + # return html._(html.a(attrs, *children), Link({"onClick": on_click, "linkClass": uuid_string})) |
62 | 97 |
|
63 | 98 |
|
64 | 99 | def route(path: str, element: Any | None, *routes: Route) -> Route:
|
|
0 commit comments