Skip to content

Commit

Permalink
some cleanup around the root template (#9)
Browse files Browse the repository at this point in the history
* some cleanup around the root template

* bump version
  • Loading branch information
ogrodnek authored May 15, 2024
1 parent 1ee6628 commit 698c60d
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 60 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.vscode/
node_modules/
_site/
# Byte-compiled / optimized / DLL files
Expand Down
8 changes: 7 additions & 1 deletion examples/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from fastapi.staticfiles import StaticFiles
from starlette.routing import Route
from pyview import PyView, defaultRootTemplate
from markupsafe import Markup

from .views import (
CountLiveView,
Expand All @@ -24,7 +25,12 @@
<link rel="stylesheet" href="https://unpkg.com/[email protected]/nprogress.css" />
"""

app.rootTemplate = defaultRootTemplate(css)

def content_wrapper(_context, content: Markup) -> Markup:
return Markup("<a href='/'>Home</a>") + content


app.rootTemplate = defaultRootTemplate(css=Markup(css), content_wrapper=content_wrapper)

routes = [
(
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ packages = [
{ include = "pyview" },
]

version = "0.0.7a"
version = "0.0.8a"
description = "LiveView in Python"
authors = ["Larry Ogrodnek <[email protected]>"]
license = "MIT"
Expand Down
66 changes: 8 additions & 58 deletions pyview/pyview.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,15 @@
from .ws_handler import LiveSocketHandler
from .live_view import LiveView
from .live_routes import LiveViewLookup
from typing import Callable, Optional, TypedDict


class RootTemplateContext(TypedDict):
id: str
content: str
title: Optional[str]
css: Optional[str]
csrf_token: str
session: Optional[str]


RootTemplate = Callable[[RootTemplateContext], str]
from .template import RootTemplate, RootTemplateContext, defaultRootTemplate


class PyView(Starlette):
rootTemplate: RootTemplate

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.rootTemplate = defaultRootTemplate("")
self.rootTemplate = defaultRootTemplate()
self.view_lookup = LiveViewLookup()
self.live_handler = LiveSocketHandler(self.view_lookup)

Expand All @@ -46,14 +34,18 @@ async def live_websocket_endpoint(websocket: WebSocket):

def add_live_view(self, path: str, view: type[LiveView]):
async def lv(request: Request):
return await liveview_container(self.rootTemplate, self.view_lookup, request)
return await liveview_container(
self.rootTemplate, self.view_lookup, request
)

self.view_lookup.add(path, view)
auth = AuthProviderFactory.get(view)
self.routes.append(Route(path, auth.wrap(lv), methods=["GET"]))


async def liveview_container(template: RootTemplate, view_lookup: LiveViewLookup, request: Request):
async def liveview_container(
template: RootTemplate, view_lookup: LiveViewLookup, request: Request
):
url = request.url
path = url.path
lv: LiveView = view_lookup.get(path)
Expand All @@ -72,49 +64,7 @@ async def liveview_container(template: RootTemplate, view_lookup: LiveViewLookup
"content": r.text(),
"title": s.live_title,
"csrf_token": generate_csrf_token("lv:phx-" + id),
"css": None,
"session": serialize_session(session),
}

return HTMLResponse(template(context))


def defaultRootTemplate(css: str) -> RootTemplate:
def template(context: RootTemplateContext) -> str:
context["css"] = css
return _defaultRootTemplate(context)

return template


def _defaultRootTemplate(context: RootTemplateContext) -> str:
suffix = " | LiveView"
render_title = (context["title"] + suffix) if context.get("title", None) is not None else "LiveView" # type: ignore
css = context["css"] if context.get("css", None) is not None else ""
return f"""
<!DOCTYPE html>
<html lang="en">
<head>
<title data-suffix="{suffix}">{render_title}</title>
<meta name="csrf-token" content="{context['csrf_token']}" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script defer type="text/javascript" src="/static/assets/app.js"></script>
{css}
</head>
<body>
<div>
<a href="/">Home</a>
<div
data-phx-main="true"
data-phx-session="{context['session']}"
data-phx-static=""
id="phx-{context['id']}"
>
{context['content']}
</div>
</div>
</body>
</html>
"""
1 change: 1 addition & 0 deletions pyview/template/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from pyview.vendor.ibis import Template
from .live_template import LiveTemplate, template_file, RenderedContent, LiveRender
from .root_template import RootTemplate, RootTemplateContext, defaultRootTemplate
71 changes: 71 additions & 0 deletions pyview/template/root_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from typing import Callable, Optional, TypedDict
from markupsafe import Markup


class RootTemplateContext(TypedDict):
id: str
content: str
title: Optional[str]
csrf_token: str
session: Optional[str]


RootTemplate = Callable[[RootTemplateContext], str]
ContentWrapper = Callable[[RootTemplateContext, Markup], Markup]


def defaultRootTemplate(
css: Optional[Markup] = None, content_wrapper: Optional[ContentWrapper] = None
) -> RootTemplate:
content_wrapper = content_wrapper or (lambda c, m: m)

def template(context: RootTemplateContext) -> str:
return _defaultRootTemplate(context, css or Markup(""), content_wrapper)

return template


def _defaultRootTemplate(
context: RootTemplateContext, css: Markup, contentWrapper: ContentWrapper
) -> str:
suffix = " | LiveView"
render_title = (context["title"] + suffix) if context.get("title", None) is not None else "LiveView" # type: ignore
main_content = contentWrapper(
context,
Markup(
f"""
<div
data-phx-main="true"
data-phx-session="{context['session']}"
data-phx-static=""
id="phx-{context['id']}"
>
{context['content']}
</div>"""
),
)

return (
Markup(
f"""
<!DOCTYPE html>
<html lang="en">
<head>
<title data-suffix="{suffix}">{render_title}</title>
<meta name="csrf-token" content="{context['csrf_token']}" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script defer type="text/javascript" src="/static/assets/app.js"></script>
{css}
</head>
<body>"""
)
+ main_content
+ Markup(
"""
</body>
</html>
"""
)
)

0 comments on commit 698c60d

Please sign in to comment.