Skip to content

Commit e4f5901

Browse files
committed
functional rendering on standalone pyscript
1 parent 9dccf73 commit e4f5901

File tree

8 files changed

+30
-12
lines changed

8 files changed

+30
-12
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# --- Build Artifacts ---
2-
src/reactpy/static/*
2+
src/reactpy/static/index.js*
3+
src/reactpy/static/morphdom/
4+
src/reactpy/static/pyscript/
35

46
# --- Jupyter ---
57
*.ipynb_checkpoints
8.39 KB
Binary file not shown.

src/js/packages/@reactpy/app/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
"preact": "^10.25.4"
99
},
1010
"devDependencies": {
11-
"typescript": "^5.7.3"
11+
"typescript": "^5.7.3",
12+
"@pyscript/core": "^0.6",
13+
"morphdom": "^2"
1214
},
1315
"scripts": {
1416
"build": "bun build \"src/index.ts\" --outdir=\"dist\" --minify --sourcemap=\"linked\"",

src/reactpy/asgi/executors/pyscript.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from email.utils import formatdate
88
from pathlib import Path
99

10+
from asgiref.typing import WebSocketScope
1011
from typing_extensions import Unpack
1112

1213
from reactpy import html
@@ -55,6 +56,9 @@ def __init__(
5556
self.html_head = html_head or html.head()
5657
self.html_lang = html_lang
5758

59+
def match_dispatch_path(self, scope: WebSocketScope) -> bool:
60+
return False
61+
5862

5963
@dataclass
6064
class ReactPyAppCSR(ReactPyApp):
@@ -78,7 +82,7 @@ def render_index_html(self) -> None:
7882
initial=self.parent.initial,
7983
root=self.parent.root_name,
8084
)
81-
head_content.replace("</head>", f"{pyscript_setup}</head>")
85+
head_content = head_content.replace("</head>", f"{pyscript_setup}</head>")
8286

8387
self._index_html = (
8488
"<!doctype html>"

src/reactpy/asgi/middleware.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from typing import Any
1212

1313
import orjson
14-
from asgi_tools import ResponseWebSocket
14+
from asgi_tools import ResponseText, ResponseWebSocket
1515
from asgiref import typing as asgi_types
1616
from asgiref.compatibility import guarantee_single_callable
1717
from servestatic import ServeStaticASGI
@@ -81,8 +81,6 @@ def __init__(
8181
self.dispatcher_pattern = re.compile(
8282
f"^{self.dispatcher_path}(?P<dotted_path>[a-zA-Z0-9_.]+)/$"
8383
)
84-
self.js_modules_pattern = re.compile(f"^{self.web_modules_path}.*")
85-
self.static_pattern = re.compile(f"^{self.static_path}.*")
8684

8785
# User defined ASGI apps
8886
self.extra_http_routes: dict[str, AsgiHttpApp] = {}
@@ -134,13 +132,13 @@ def match_dispatch_path(self, scope: asgi_types.WebSocketScope) -> bool:
134132
return bool(re.match(self.dispatcher_pattern, scope["path"]))
135133

136134
def match_static_path(self, scope: asgi_types.HTTPScope) -> bool:
137-
return bool(re.match(self.static_pattern, scope["path"]))
135+
return scope["path"].startswith(self.static_path)
138136

139137
def match_web_modules_path(self, scope: asgi_types.HTTPScope) -> bool:
140-
return bool(re.match(self.js_modules_pattern, scope["path"]))
138+
return scope["path"].startswith(self.web_modules_path)
141139

142140
def match_extra_paths(self, scope: asgi_types.Scope) -> AsgiApp | None:
143-
# Custom defined routes are unused within middleware to encourage users to handle
141+
# Custom defined routes are unused by default to encourage users to handle
144142
# routing within their root ASGI application.
145143
return None
146144

@@ -263,7 +261,7 @@ async def __call__(
263261
"""ASGI app for ReactPy static files."""
264262
if not self._static_file_server:
265263
self._static_file_server = ServeStaticASGI(
266-
self.parent.asgi_app,
264+
Error404App(),
267265
root=self.parent.static_dir,
268266
prefix=self.parent.static_path,
269267
)
@@ -285,10 +283,16 @@ async def __call__(
285283
"""ASGI app for ReactPy web modules."""
286284
if not self._static_file_server:
287285
self._static_file_server = ServeStaticASGI(
288-
self.parent.asgi_app,
286+
Error404App(),
289287
root=self.parent.web_modules_dir,
290288
prefix=self.parent.web_modules_path,
291289
autorefresh=True,
292290
)
293291

294292
await self._static_file_server(scope, receive, send)
293+
294+
295+
class Error404App:
296+
async def __call__(self, scope, receive, send):
297+
response = ResponseText("Resource not found on this server.", status_code=404)
298+
await response(scope, receive, send)

src/reactpy/pyscript/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def pyscript_setup_html(
7777
f"{'' if REACTPY_DEBUG.current else hide_pyscript_debugger}"
7878
f'<script type="module" async crossorigin="anonymous" src="{REACTPY_PATH_PREFIX.current}static/pyscript/core.js">'
7979
"</script>"
80-
f'<py-script async config="{pyscript_config}">{PYSCRIPT_LAYOUT_HANDLER}</py-script>'
80+
f"<py-script async config='{pyscript_config}'>{PYSCRIPT_LAYOUT_HANDLER}</py-script>"
8181
)
8282

8383

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
py-script {
2+
display: none;
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.py-error {
2+
display: none;
3+
}

0 commit comments

Comments
 (0)