From 3c320b6e9349f0b3392f1a8f65279ef9a920b8fd Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Thu, 15 Jun 2023 01:39:17 -0700 Subject: [PATCH 1/2] Create template tag --- src/py/reactpy/pyproject.toml | 6 ++++- src/py/reactpy/reactpy/templatetag.py | 39 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/py/reactpy/reactpy/templatetag.py diff --git a/src/py/reactpy/pyproject.toml b/src/py/reactpy/pyproject.toml index 659ddbf94..d8c67c8fd 100644 --- a/src/py/reactpy/pyproject.toml +++ b/src/py/reactpy/pyproject.toml @@ -41,23 +41,27 @@ all = ["reactpy[starlette,sanic,fastapi,flask,tornado,testing]"] starlette = [ "starlette >=0.13.6", "uvicorn[standard] >=0.19.0", + "jinja2-simple-tags", ] sanic = [ "sanic >=21", "sanic-cors", "uvicorn[standard] >=0.19.0", + "jinja2-simple-tags", ] fastapi = [ "fastapi >=0.63.0", "uvicorn[standard] >=0.19.0", + "jinja2-simple-tags", ] flask = [ "flask", "markupsafe>=1.1.1,<2.1", "flask-cors", "flask-sock", + "jinja2-simple-tags", ] -tornado = [ +tornado = [ # TODO: Torando does not use Jinja. We will need to write something custom for this. "tornado", ] testing = [ diff --git a/src/py/reactpy/reactpy/templatetag.py b/src/py/reactpy/reactpy/templatetag.py new file mode 100644 index 000000000..647ae9fc3 --- /dev/null +++ b/src/py/reactpy/reactpy/templatetag.py @@ -0,0 +1,39 @@ +from jinja2_simple_tags import StandaloneTag +from uuid import uuid4 +import urllib.parse + +REACTPY_WEBSOCKET_URL: str +REACTPY_WEB_MODULES_URL: str +REACTPY_RECONNECT_MAX: str +REACTPY_CLIENT_URL_PATH: str + +class ComponentTag(StandaloneTag): + safe_output = True + tags = {"component"} + + def render(self, dotted_path: str, *args, **kwargs): + uuid = uuid4().hex + class_ = kwargs.pop("class", "") + kwargs.pop("key", "") # `key` is effectively useless for the root node + url_path = REACTPY_CLIENT_URL_PATH + if kwargs.get("args") is not None: + raise ValueError("Cannot specify `args` as a keyword argument") + if args: + kwargs["args"] = args + if kwargs: + url_path += f"?{urllib.parse.urlencode(kwargs)}" + + return ( + f'
' + '" + ) From 0a59c46bc0c7a1b94dd7a38edd2a469f4f89b5b1 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Thu, 15 Jun 2023 02:24:00 -0700 Subject: [PATCH 2/2] websocket URL --- src/py/reactpy/reactpy/templatetag.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/py/reactpy/reactpy/templatetag.py b/src/py/reactpy/reactpy/templatetag.py index 647ae9fc3..1fd525b49 100644 --- a/src/py/reactpy/reactpy/templatetag.py +++ b/src/py/reactpy/reactpy/templatetag.py @@ -5,9 +5,11 @@ REACTPY_WEBSOCKET_URL: str REACTPY_WEB_MODULES_URL: str REACTPY_RECONNECT_MAX: str -REACTPY_CLIENT_URL_PATH: str +REACTPY_CLIENT_URL: str + class ComponentTag(StandaloneTag): + """This allows enables a `component` tag to be used in any Jinja2 rendering context.""" safe_output = True tags = {"component"} @@ -15,22 +17,25 @@ def render(self, dotted_path: str, *args, **kwargs): uuid = uuid4().hex class_ = kwargs.pop("class", "") kwargs.pop("key", "") # `key` is effectively useless for the root node - url_path = REACTPY_CLIENT_URL_PATH + + # Generate the websocket URL + # TODO: This will require rewriting the websocket URL to `reactpy-ws/?` + component_ws_url = f"{REACTPY_WEBSOCKET_URL}/{uuid}" if kwargs.get("args") is not None: raise ValueError("Cannot specify `args` as a keyword argument") if args: kwargs["args"] = args if kwargs: - url_path += f"?{urllib.parse.urlencode(kwargs)}" + component_ws_url += f"?{urllib.parse.urlencode(kwargs)}" return ( f'
' '