Skip to content

Commit 21c0bd2

Browse files
committed
fixes #634
1 parent 0d05029 commit 21c0bd2

File tree

8 files changed

+220
-145
lines changed

8 files changed

+220
-145
lines changed

fasthtml/components.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi', 'Bdo', 'Blockquote', 'Body', 'Br', 'Button', 'Canvas',
99
'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data', 'Datalist', 'Dd', 'Del', 'Details', 'Dfn', 'Dialog',
1010
'Div', 'Dl', 'Dt', 'Em', 'Embed', 'Fencedframe', 'Fieldset', 'Figcaption', 'Figure', 'Footer', 'Form', 'H1',
11-
'H2', 'H3', 'H4', 'H5', 'H6', 'Head', 'Header', 'Hgroup', 'Hr', 'Html', 'I', 'Iframe', 'Img', 'Input', 'Ins',
12-
'Kbd', 'Label', 'Legend', 'Li', 'Link', 'Main', 'Map', 'Mark', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript',
13-
'Object', 'Ol', 'Optgroup', 'Option', 'Output', 'P', 'Picture', 'PortalExperimental', 'Pre', 'Progress', 'Q',
14-
'Rp', 'Rt', 'Ruby', 'S', 'Samp', 'Script', 'Search', 'Section', 'Select', 'Slot', 'Small', 'Source', 'Span',
11+
'H2', 'H3', 'H4', 'H5', 'H6', 'Head', 'Header', 'Hgroup', 'Hr', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd',
12+
'Label', 'Legend', 'Li', 'Link', 'Main', 'Map', 'Mark', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript', 'Object',
13+
'Ol', 'Optgroup', 'Option', 'Output', 'P', 'Picture', 'PortalExperimental', 'Pre', 'Progress', 'Q', 'Rp',
14+
'Rt', 'Ruby', 'S', 'Samp', 'Script', 'Search', 'Section', 'Select', 'Slot', 'Small', 'Source', 'Span',
1515
'Strong', 'Style', 'Sub', 'Summary', 'Sup', 'Table', 'Tbody', 'Td', 'Template', 'Textarea', 'Tfoot', 'Th',
1616
'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul', 'Var', 'Video', 'Wbr']
1717

@@ -110,7 +110,7 @@ def ft_hx(tag: str, *c, target_id=None, hx_vals=None, hx_target=None, **kwargs):
110110
'Button', 'Canvas', 'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data', 'Datalist', 'Dd', 'Del', 'Details', 'Dfn',
111111
'Dialog', 'Div', 'Dl', 'Dt', 'Em', 'Embed', 'Fencedframe', 'Fieldset', 'Figcaption', 'Figure', 'Footer', 'Form',
112112
'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Head', 'Header',
113-
'Hgroup', 'Hr', 'Html', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li',
113+
'Hgroup', 'Hr', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li',
114114
'Link', 'Main', 'Map', 'Mark', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript', 'Object', 'Ol', 'Optgroup', 'Option', 'Output',
115115
'P', 'Picture', 'PortalExperimental', 'Pre', 'Progress', 'Q', 'Rp', 'Rt', 'Ruby', 'S', 'Samp', 'Script', 'Search',
116116
'Section', 'Select', 'Slot', 'Small', 'Source', 'Span', 'Strong', 'Style', 'Sub', 'Summary', 'Sup', 'Table', 'Tbody',

fasthtml/components.pyi

Lines changed: 17 additions & 5 deletions
Large diffs are not rendered by default.

fasthtml/core.pyi

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""The `FastHTML` subclass of `Starlette`, along with the `RouterX` and `RouteX` classes it automatically uses."""
2-
__all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmx_exts', 'htmxsrc', 'fhjsscr', 'surrsrc', 'scopesrc', 'viewport', 'charset', 'cors_allow', 'iframe_scr', 'all_meths', 'parsed_date', 'snake2hyphens', 'HtmxHeaders', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'flat_xt', 'Beforeware', 'EventStream', 'signal_shutdown', 'uri', 'decode_uri', 'flat_tuple', 'noop_body', 'respond', 'Redirect', 'get_key', 'def_hdrs', 'FastHTML', 'serve', 'Client', 'APIRouter', 'cookie', 'reg_re_param', 'MiddlewareBase', 'FtResponse', 'unqid', 'setup_ws']
3-
import json, uuid, inspect, types, uvicorn, signal, asyncio, threading
2+
__all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmx_exts', 'htmxsrc', 'fhjsscr', 'surrsrc', 'scopesrc', 'viewport', 'charset', 'cors_allow', 'iframe_scr', 'all_meths', 'parsed_date', 'snake2hyphens', 'HtmxHeaders', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'flat_xt', 'Beforeware', 'EventStream', 'signal_shutdown', 'uri', 'decode_uri', 'flat_tuple', 'noop_body', 'respond', 'Redirect', 'get_key', 'qp', 'def_hdrs', 'FastHTML', 'nested_name', 'serve', 'Client', 'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param', 'MiddlewareBase', 'FtResponse', 'unqid', 'setup_ws']
3+
import json, uuid, inspect, types, uvicorn, signal, asyncio, threading, inspect
44
from fastcore.utils import *
55
from fastcore.xml import *
66
from fastcore.meta import use_kwargs_dict
@@ -167,6 +167,7 @@ def _apply_ft(o):
167167

168168
def _to_xml(req, resp, indent):
169169
...
170+
_iter_typs = (tuple, list, map, filter, range, types.GeneratorType)
170171

171172
def flat_tuple(o):
172173
"""Flatten lists"""
@@ -203,9 +204,9 @@ class Redirect:
203204

204205
async def _wrap_call(f, req, params):
205206
...
206-
htmx_exts = {'head-support': 'https://unpkg.com/[email protected].1/head-support.js', 'preload': 'https://unpkg.com/htmx-ext-preload@2.0.1/preload.js', 'class-tools': 'https://unpkg.com/[email protected]/class-tools.js', 'loading-states': 'https://unpkg.com/[email protected]/loading-states.js', 'multi-swap': 'https://unpkg.com/[email protected]/multi-swap.js', 'path-deps': 'https://unpkg.com/[email protected]/path-deps.js', 'remove-me': 'https://unpkg.com/[email protected]/remove-me.js', 'ws': 'https://unpkg.com/htmx-ext-ws/ws.js', 'chunked-transfer': 'https://unpkg.com/htmx-ext-transfer-encoding-chunked/transfer-encoding-chunked.js'}
207-
htmxsrc = Script(src='https://unpkg.com/htmx.org@next/dist/htmx.min.js')
208-
fhjsscr = Script(src='https://cdn.jsdelivr.net/gh/answerdotai/[email protected].4/fasthtml.js')
207+
htmx_exts = {'head-support': 'https://unpkg.com/[email protected].3/head-support.js', 'preload': 'https://unpkg.com/htmx-ext-preload@2.1.0/preload.js', 'class-tools': 'https://unpkg.com/[email protected]/class-tools.js', 'loading-states': 'https://unpkg.com/[email protected]/loading-states.js', 'multi-swap': 'https://unpkg.com/[email protected]/multi-swap.js', 'path-deps': 'https://unpkg.com/[email protected]/path-deps.js', 'remove-me': 'https://unpkg.com/[email protected]/remove-me.js', 'ws': 'https://unpkg.com/htmx-ext-ws@2.0.2/ws.js', 'chunked-transfer': 'https://unpkg.com/htmx-ext-transfer-encoding-chunked@0.4.0/transfer-encoding-chunked.js'}
208+
htmxsrc = Script(src='https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js')
209+
fhjsscr = Script(src='https://cdn.jsdelivr.net/gh/answerdotai/[email protected].12/fasthtml.js')
209210
surrsrc = Script(src='https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js')
210211
scopesrc = Script(src='https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js')
211212
viewport = Meta(name='viewport', content='width=device-width, initial-scale=1, viewport-fit=cover')
@@ -220,7 +221,8 @@ def _list(o):
220221
def _wrap_ex(f, hdrs, ftrs, htmlkw, bodykw, body_wrap):
221222
...
222223

223-
def _mk_locfunc(f, p):
224+
def qp(p: str, **kw) -> str:
225+
"""Add query parameters to path p"""
224226
...
225227

226228
def def_hdrs(htmx=True, surreal=True):
@@ -231,7 +233,7 @@ iframe_scr = Script(NotStr("\n function sendmsg() {\n window.parent.po
231233

232234
class FastHTML(Starlette):
233235

234-
def __init__(self, debug=False, routes=None, middleware=None, exception_handlers=None, on_startup=None, on_shutdown=None, lifespan=None, hdrs=None, ftrs=None, exts=None, before=None, after=None, surreal=True, htmx=True, default_hdrs=True, sess_cls=SessionMiddleware, secret_key=None, session_cookie='session_', max_age=365 * 24 * 3600, sess_path='/', same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey', body_wrap=noop_body, htmlkw=None, nb_hdrs=True, **bodykw):
236+
def __init__(self, debug=False, routes=None, middleware=None, title: str='FastHTML page', exception_handlers=None, on_startup=None, on_shutdown=None, lifespan=None, hdrs=None, ftrs=None, exts=None, before=None, after=None, surreal=True, htmx=True, default_hdrs=True, sess_cls=SessionMiddleware, secret_key=None, session_cookie='session_', max_age=365 * 24 * 3600, sess_path='/', same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey', body_wrap=noop_body, htmlkw=None, nb_hdrs=False, **bodykw):
235237
...
236238

237239
def add_route(self, route):
@@ -250,7 +252,7 @@ class FastHTML(Starlette):
250252
def _add_route(self, func, path, methods, name, include_in_schema, body_wrap):
251253
...
252254

253-
def route(self, path: str=None, methods=None, name=None, include_in_schema=True, body_wrap=noop_body):
255+
def route(self, path: str=None, methods=None, name=None, include_in_schema=True, body_wrap=None):
254256
"""Add a route at `path`"""
255257
...
256258

@@ -262,6 +264,13 @@ class FastHTML(Starlette):
262264
"""Add a static route at URL path `prefix` with files from `static_path` and single `ext` (including the '.')"""
263265
...
264266
all_meths = 'get post put delete patch head trace options'.split()
267+
268+
def _mk_locfunc(f, p):
269+
...
270+
271+
def nested_name(f):
272+
"""Get name of function `f` using '_' to join nested function names"""
273+
...
265274
for o in all_meths:
266275
setattr(FastHTML, o, partialmethod(FastHTML.route, methods=o))
267276

@@ -280,21 +289,41 @@ class Client:
280289
for o in ('get', 'post', 'delete', 'put', 'patch', 'options'):
281290
setattr(Client, o, partialmethod(Client._sync, o))
282291

292+
class RouteFuncs:
293+
294+
def __init__(self):
295+
...
296+
297+
def __setattr__(self, name, value):
298+
...
299+
300+
def __getattr__(self, name):
301+
...
302+
303+
def __dir__(self):
304+
...
305+
283306
class APIRouter:
284307
"""Add routes to an app"""
285308

286-
def __init__(self):
309+
def __init__(self, prefix: str | None=None, body_wrap=noop_body):
287310
...
288311

289-
def __call__(self: FastHTML, path: str=None, methods=None, name=None, include_in_schema=True, body_wrap=noop_body):
312+
def _wrap_func(self, func, path=None):
313+
...
314+
315+
def __call__(self, path: str=None, methods=None, name=None, include_in_schema=True, body_wrap=None):
290316
"""Add a route at `path`"""
291317
...
292318

319+
def __getattr__(self, name):
320+
...
321+
293322
def to_app(self, app):
294323
"""Add routes to `app`"""
295324
...
296325

297-
def ws(self: FastHTML, path: str, conn=None, disconn=None, name=None, middleware=None):
326+
def ws(self, path: str, conn=None, disconn=None, name=None, middleware=None):
298327
"""Add a websocket route at `path`"""
299328
...
300329
for o in all_meths:
@@ -307,7 +336,7 @@ def cookie(key: str, value='', max_age=None, expires=None, path='/', domain=None
307336
def reg_re_param(m, s):
308337
...
309338
reg_re_param('path', '.*?')
310-
reg_re_param('static', 'ico|gif|jpg|jpeg|webm|css|js|woff|png|svg|mp4|webp|ttf|otf|eot|woff2|txt|html|map')
339+
reg_re_param('static', 'ico|gif|jpg|jpeg|webm|css|js|woff|png|svg|mp4|webp|ttf|otf|eot|woff2|txt|html|map|pdf')
311340

312341
class MiddlewareBase:
313342

fasthtml/xtend.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ def CheckboxX(checked: bool=False, label=None, value='1', id=None, name=None, *,
3333
"""A Checkbox optionally inside a Label, preceded by a `Hidden` with matching name"""
3434
...
3535

36-
def Script(code: str='', *, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=None, auto_id=None, **kwargs) -> FT:
36+
def Script(code: str='', *, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=None, **kwargs) -> FT:
3737
"""A Script tag that doesn't escape its code"""
3838
...
3939

40-
def Style(*c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=None, auto_id=None, **kwargs) -> FT:
40+
def Style(*c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=None, **kwargs) -> FT:
4141
"""A Style tag that doesn't escape its code"""
4242
...
4343

nbs/api/01_components.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@
543543
" 'Button', 'Canvas', 'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data', 'Datalist', 'Dd', 'Del', 'Details', 'Dfn',\n",
544544
" 'Dialog', 'Div', 'Dl', 'Dt', 'Em', 'Embed', 'Fencedframe', 'Fieldset', 'Figcaption', 'Figure', 'Footer', 'Form',\n",
545545
" 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Head', 'Header',\n",
546-
" 'Hgroup', 'Hr', 'Html', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li',\n",
546+
" 'Hgroup', 'Hr', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li',\n",
547547
" 'Link', 'Main', 'Map', 'Mark', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript', 'Object', 'Ol', 'Optgroup', 'Option', 'Output',\n",
548548
" 'P', 'Picture', 'PortalExperimental', 'Pre', 'Progress', 'Q', 'Rp', 'Rt', 'Ruby', 'S', 'Samp', 'Script', 'Search',\n",
549549
" 'Section', 'Select', 'Slot', 'Small', 'Source', 'Span', 'Strong', 'Style', 'Sub', 'Summary', 'Sup', 'Table', 'Tbody',\n",

nbs/apilist.txt

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,22 @@
9090
- `def __init__(self, loc)`
9191
- `def __response__(self, req)`
9292

93+
- `def qp(p, **kw)`
94+
Add query parameters to path p
95+
9396
- `def def_hdrs(htmx, surreal)`
9497
Default headers for a FastHTML app
9598

9699
- `class FastHTML`
97-
- `def __init__(self, debug, routes, middleware, exception_handlers, on_startup, on_shutdown, lifespan, hdrs, ftrs, exts, before, after, surreal, htmx, default_hdrs, sess_cls, secret_key, session_cookie, max_age, sess_path, same_site, sess_https_only, sess_domain, key_fname, body_wrap, htmlkw, nb_hdrs, **bodykw)`
100+
- `def __init__(self, debug, routes, middleware, title, exception_handlers, on_startup, on_shutdown, lifespan, hdrs, ftrs, exts, before, after, surreal, htmx, default_hdrs, sess_cls, secret_key, session_cookie, max_age, sess_path, same_site, sess_https_only, sess_domain, key_fname, body_wrap, htmlkw, nb_hdrs, **bodykw)`
98101
- `def add_route(self, route)`
99102

100103
- `@patch def ws(self, path, conn, disconn, name, middleware)`
101104
Add a websocket route at `path`
102105

106+
- `def nested_name(f)`
107+
Get name of function `f` using '_' to join nested function names
108+
103109
- `@patch def route(self, path, methods, name, include_in_schema, body_wrap)`
104110
Add a route at `path`
105111

@@ -111,13 +117,20 @@
111117

112118
- `def __init__(self, app, url)`
113119

120+
- `class RouteFuncs`
121+
- `def __init__(self)`
122+
- `def __setattr__(self, name, value)`
123+
- `def __getattr__(self, name)`
124+
- `def __dir__(self)`
125+
114126
- `class APIRouter`
115127
Add routes to an app
116128

117-
- `def __init__(self)`
129+
- `def __init__(self, prefix, body_wrap)`
118130
- `def __call__(self, path, methods, name, include_in_schema, body_wrap)`
119131
Add a route at `path`
120132

133+
- `def __getattr__(self, name)`
121134
- `def to_app(self, app)`
122135
Add routes to `app`
123136

@@ -147,7 +160,7 @@
147160

148161
> The `fast_app` convenience wrapper
149162

150-
- `def fast_app(db_file, render, hdrs, ftrs, tbls, before, middleware, live, debug, routes, exception_handlers, on_startup, on_shutdown, lifespan, default_hdrs, pico, surreal, htmx, exts, secret_key, key_fname, session_cookie, max_age, sess_path, same_site, sess_https_only, sess_domain, htmlkw, bodykw, reload_attempts, reload_interval, static_path, body_wrap, **kwargs)`
163+
- `def fast_app(db_file, render, hdrs, ftrs, tbls, before, middleware, live, debug, routes, exception_handlers, on_startup, on_shutdown, lifespan, default_hdrs, pico, surreal, htmx, exts, secret_key, key_fname, session_cookie, max_age, sess_path, same_site, sess_https_only, sess_domain, htmlkw, bodykw, reload_attempts, reload_interval, static_path, body_wrap, nb_hdrs, **kwargs)`
151164
Create a FastHTML or FastHTMLWithLiveReload app.
152165

153166
## fasthtml.js
@@ -158,7 +171,7 @@
158171
Render light media for day mode views
159172

160173
- `def dark_media(css)`
161-
Render dark media for nught mode views
174+
Render dark media for night mode views
162175

163176
- `def MarkdownJS(sel)`
164177
Implements browser-based markdown rendering.
@@ -192,7 +205,7 @@
192205
- `def start(self)`
193206
- `def stop(self)`
194207

195-
- `def HTMX(path, host, port, iframe_height)`
208+
- `def HTMX(path, app, host, port, height, link, iframe)`
196209
An iframe which displays the HTMX application in a notebook.
197210

198211
## fasthtml.live_reload
@@ -249,6 +262,12 @@
249262
- `def login_link(self)`
250263
- `def parse_response(self, code)`
251264

265+
- `class Auth0AppClient`
266+
A `WebApplicationClient` for Auth0 OAuth2
267+
268+
- `def __init__(self, domain, client_id, client_secret, code, scope, redirect_uri, **kwargs)`
269+
- `def login_link(self, req)`
270+
252271
- `@patch def login_link(self, redirect_uri, scope, state)`
253272
Get a login link for this client
254273

@@ -268,12 +287,13 @@
268287
Call `retr_info` and then return id/subscriber value
269288

270289
- `class OAuth`
271-
- `def __init__(self, app, cli, skip, redir_path, logout_path, login_path, https, http_patterns)`
290+
- `def __init__(self, app, cli, skip, redir_path, error_path, logout_path, login_path, https, http_patterns)`
291+
- `def redir_login(self, session)`
272292
- `def redir_url(self, req)`
273293
- `def login_link(self, req, scope, state)`
274-
- `def login(self, info, state)`
294+
- `def check_invalid(self, req, session, auth)`
275295
- `def logout(self, session)`
276-
- `def chk_auth(self, info, ident, session)`
296+
- `def get_auth(self, info, ident, session, state)`
277297

278298
## fasthtml.pico
279299

0 commit comments

Comments
 (0)