Spaces:
Running
Running
import importlib | |
import json | |
from dataclasses import dataclass | |
from pathlib import Path | |
import fasthtml.common as fh | |
from fasthtml.common import H4, A, Div, Pre, Table, Tbody, Td, Th, Thead, Tr | |
from tutorial import utils | |
from tutorial.example import Example | |
hdrs = ( | |
fh.MarkdownJS(), | |
utils.HighlightJS(langs=["python", "javascript", "html", "css"]), | |
utils.social_card(), | |
utils.alpine(), | |
fh.Script(src="/script.js"), | |
fh.Script("init_main_page()"), | |
utils.piwik(), | |
) | |
html_kv = { | |
"x-data": """{ | |
showRequests: localStorage.getItem('showRequests') == 'true', | |
darkMode: localStorage.getItem('darkMode') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') | |
}""", | |
"x-init": "$watch('darkMode', val => localStorage.setItem('darkMode', val));$watch('showRequests', val => localStorage.setItem('showRequests', val))", | |
"x-bind:data-theme": "darkMode !== 'system'? darkMode : (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')", | |
} | |
app, rt = fh.fast_app(hdrs=hdrs, static_path="public", htmlkw=html_kv, surreal=False) | |
htmx_examples = sorted([f.stem for f in Path(__file__).parent.glob("htmx/*.py") if f.stem not in ["__init__"]]) | |
INTRO = """ | |
# HTMX examples with FastHTML | |
Reproduction of HTMX official [examples](https://htmx.org/examples/) with Python [FastHTML](https://docs.fastht.ml/). | |
The code can be found on [GitHub](https://github.com/phihung/fasthtml_examples). | |
""" | |
def homepage(): | |
ls = [get_example(name) for name in htmx_examples] | |
return ( | |
fh.Title("HTMX examples with FastHTML"), | |
fh.Main(cls="container")( | |
Div(INTRO, cls="marked"), | |
Div( | |
"Choose theme ", | |
fh.Select(style="display:inline-block;max-width:100px;", **{"x-model": "darkMode"})( | |
fh.Option("Light", value="light"), | |
fh.Option("Dark", value="dark"), | |
), | |
), | |
Table( | |
Thead(Tr(Th("Pattern"), Th("Description"))), | |
Tbody(tuple(Tr(Td(A(ex.title, href="/" + ex.slug)), Td(ex.desc)) for ex in ls)), | |
), | |
), | |
) | |
class RequestInfo: | |
verb: str | |
path: str | |
parameters: str | |
headers: str | |
response: str | |
def requests(r: RequestInfo): | |
headers = json.loads(r.headers) | |
headers = { | |
k: v for k, v in headers.items() if k in ("HX-Trigger", "HX-Trigger-Name", "HX-Target", "HX-Prompt") and v | |
} | |
return Div(**{"x-data": "{show: false}", "@click": "show = !show"})( | |
H4(x_text="(show?'▽':'▶') + ' " + r.verb.upper() + " " + r.path + "'"), | |
Div(**{"x-show": "show"})( | |
Div(Pre("Input: " + r.parameters)) if r.parameters != "{}" else None, | |
Div(Pre("Headers: " + str(headers))) if headers else None, | |
Div(Pre(r.response or "(empty response)"), style="max-height:150px;overflow:scroll;"), | |
), | |
) | |
def get_app(): | |
for name in htmx_examples: | |
get_example(name).create_routes(app) | |
return app | |
def get_example(name): | |
module = importlib.import_module(f"tutorial.htmx.{name}") | |
return Example(module, name[4:]) | |
def start(): | |
fh.serve("tutorial.__init__", app="get_app", reload=False) | |
if __name__ == "__main__": | |
fh.serve(app="get_app") | |