python-fasthtml 0.12.9__tar.gz → 0.12.34__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_fasthtml-0.12.9/python_fasthtml.egg-info → python_fasthtml-0.12.34}/PKG-INFO +23 -7
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/README.md +4 -4
- python_fasthtml-0.12.34/fasthtml/__init__.py +2 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/_modidx.py +29 -4
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/cli.py +1 -1
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/common.py +1 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/components.py +42 -25
- python_fasthtml-0.12.34/fasthtml/components.pyi +209 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/core.py +165 -67
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/core.pyi +30 -14
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/fastapp.py +4 -2
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/jupyter.py +31 -15
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/oauth.py +43 -18
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/starlette.py +1 -1
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/toaster.py +13 -7
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/xtend.py +97 -10
- python_fasthtml-0.12.34/fasthtml/xtend.pyi +130 -0
- python_fasthtml-0.12.34/pyproject.toml +11 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34/python_fasthtml.egg-info}/PKG-INFO +23 -7
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/requires.txt +1 -1
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/settings.ini +6 -5
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/setup.py +2 -2
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/tests/test_toaster.py +6 -1
- python_fasthtml-0.12.9/fasthtml/__init__.py +0 -2
- python_fasthtml-0.12.9/fasthtml/components.pyi +0 -204
- python_fasthtml-0.12.9/fasthtml/xtend.pyi +0 -124
- python_fasthtml-0.12.9/pyproject.toml +0 -3
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/CONTRIBUTING.md +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/LICENSE +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/MANIFEST.in +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/authmw.py +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/basics.py +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/ft.py +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/js.py +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/katex.js +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/live_reload.py +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/pico.py +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/stripe_otp.py +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/fasthtml/svg.py +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/SOURCES.txt +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/dependency_links.txt +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/entry_points.txt +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/not-zip-safe +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/top_level.txt +0 -0
- {python_fasthtml-0.12.9 → python_fasthtml-0.12.34}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: python-fasthtml
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.34
|
|
4
4
|
Summary: The fastest way to create an HTML app
|
|
5
5
|
Home-page: https://github.com/AnswerDotAI/fasthtml
|
|
6
6
|
Author: Jeremy Howard and contributors
|
|
@@ -11,11 +11,14 @@ Classifier: Development Status :: 4 - Beta
|
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
12
|
Classifier: Natural Language :: English
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
17
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
18
|
Requires-Python: >=3.10
|
|
16
19
|
Description-Content-Type: text/markdown
|
|
17
20
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: fastcore>=1.
|
|
21
|
+
Requires-Dist: fastcore>=1.8.1
|
|
19
22
|
Requires-Dist: python-dateutil
|
|
20
23
|
Requires-Dist: starlette>0.33
|
|
21
24
|
Requires-Dist: oauthlib
|
|
@@ -30,6 +33,19 @@ Requires-Dist: ipython; extra == "dev"
|
|
|
30
33
|
Requires-Dist: lxml; extra == "dev"
|
|
31
34
|
Requires-Dist: pysymbol_llm; extra == "dev"
|
|
32
35
|
Requires-Dist: monsterui; extra == "dev"
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: classifier
|
|
39
|
+
Dynamic: description
|
|
40
|
+
Dynamic: description-content-type
|
|
41
|
+
Dynamic: home-page
|
|
42
|
+
Dynamic: keywords
|
|
43
|
+
Dynamic: license
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
Dynamic: provides-extra
|
|
46
|
+
Dynamic: requires-dist
|
|
47
|
+
Dynamic: requires-python
|
|
48
|
+
Dynamic: summary
|
|
33
49
|
|
|
34
50
|
# FastHTML
|
|
35
51
|
|
|
@@ -123,7 +139,7 @@ ChatGPT, Claude, and Copilot won’t give useful answers about it. To fix
|
|
|
123
139
|
that problem, we’ve provided an LLM-friendly guide that teaches them how
|
|
124
140
|
to use FastHTML. To use it, add this link for your AI helper to use:
|
|
125
141
|
|
|
126
|
-
- [/llms-ctx.txt](https://
|
|
142
|
+
- [/llms-ctx.txt](https://www.fastht.ml/docs/llms-ctx.txt)
|
|
127
143
|
|
|
128
144
|
This example is in a format based on recommendations from Anthropic for
|
|
129
145
|
use with [Claude
|
|
@@ -147,8 +163,8 @@ Start with the official sources to learn more about FastHTML:
|
|
|
147
163
|
|
|
148
164
|
- [About](https://fastht.ml/about): Learn about the core ideas behind
|
|
149
165
|
FastHTML
|
|
150
|
-
- [Documentation](https://
|
|
151
|
-
write FastHTML code
|
|
166
|
+
- [Documentation](https://www.fastht.ml/docs): Learn from examples how
|
|
167
|
+
to write FastHTML code
|
|
152
168
|
- [Idiomatic
|
|
153
169
|
app](https://github.com/AnswerDotAI/fasthtml/blob/main/examples/adv_app.py):
|
|
154
170
|
Heavily commented source code walking through a complete application,
|
|
@@ -171,7 +187,7 @@ repo’s notebooks and the official FastHTML examples repo:
|
|
|
171
187
|
Then explore the small but growing third-party ecosystem of FastHTML
|
|
172
188
|
tutorials, notebooks, libraries, and components:
|
|
173
189
|
|
|
174
|
-
- [FastHTML Gallery](https://fastht.ml
|
|
190
|
+
- [FastHTML Gallery](https://gallery.fastht.ml): Learn from minimal
|
|
175
191
|
examples of components (ie chat bubbles, click-to-edit, infinite
|
|
176
192
|
scroll, etc)
|
|
177
193
|
- [Creating Custom FastHTML Tags for Markdown
|
|
@@ -90,7 +90,7 @@ ChatGPT, Claude, and Copilot won’t give useful answers about it. To fix
|
|
|
90
90
|
that problem, we’ve provided an LLM-friendly guide that teaches them how
|
|
91
91
|
to use FastHTML. To use it, add this link for your AI helper to use:
|
|
92
92
|
|
|
93
|
-
- [/llms-ctx.txt](https://
|
|
93
|
+
- [/llms-ctx.txt](https://www.fastht.ml/docs/llms-ctx.txt)
|
|
94
94
|
|
|
95
95
|
This example is in a format based on recommendations from Anthropic for
|
|
96
96
|
use with [Claude
|
|
@@ -114,8 +114,8 @@ Start with the official sources to learn more about FastHTML:
|
|
|
114
114
|
|
|
115
115
|
- [About](https://fastht.ml/about): Learn about the core ideas behind
|
|
116
116
|
FastHTML
|
|
117
|
-
- [Documentation](https://
|
|
118
|
-
write FastHTML code
|
|
117
|
+
- [Documentation](https://www.fastht.ml/docs): Learn from examples how
|
|
118
|
+
to write FastHTML code
|
|
119
119
|
- [Idiomatic
|
|
120
120
|
app](https://github.com/AnswerDotAI/fasthtml/blob/main/examples/adv_app.py):
|
|
121
121
|
Heavily commented source code walking through a complete application,
|
|
@@ -138,7 +138,7 @@ repo’s notebooks and the official FastHTML examples repo:
|
|
|
138
138
|
Then explore the small but growing third-party ecosystem of FastHTML
|
|
139
139
|
tutorials, notebooks, libraries, and components:
|
|
140
140
|
|
|
141
|
-
- [FastHTML Gallery](https://fastht.ml
|
|
141
|
+
- [FastHTML Gallery](https://gallery.fastht.ml): Learn from minimal
|
|
142
142
|
examples of components (ie chat bubbles, click-to-edit, infinite
|
|
143
143
|
scroll, etc)
|
|
144
144
|
- [Creating Custom FastHTML Tags for Markdown
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Autogenerated by nbdev
|
|
2
2
|
|
|
3
3
|
d = { 'settings': { 'branch': 'main',
|
|
4
|
-
'doc_baseurl': '/',
|
|
5
|
-
'doc_host': 'https://
|
|
4
|
+
'doc_baseurl': '/docs/',
|
|
5
|
+
'doc_host': 'https://www.fastht.ml',
|
|
6
6
|
'git_url': 'https://github.com/AnswerDotAI/fasthtml',
|
|
7
7
|
'lib_path': 'fasthtml'},
|
|
8
8
|
'syms': { 'fasthtml.authmw': {},
|
|
@@ -45,7 +45,11 @@ d = { 'settings': { 'branch': 'main',
|
|
|
45
45
|
'fasthtml.core.FastHTML._add_ws': ('api/core.html#fasthtml._add_ws', 'fasthtml/core.py'),
|
|
46
46
|
'fasthtml.core.FastHTML._endp': ('api/core.html#fasthtml._endp', 'fasthtml/core.py'),
|
|
47
47
|
'fasthtml.core.FastHTML.add_route': ('api/core.html#fasthtml.add_route', 'fasthtml/core.py'),
|
|
48
|
+
'fasthtml.core.FastHTML.devtools_json': ('api/core.html#fasthtml.devtools_json', 'fasthtml/core.py'),
|
|
49
|
+
'fasthtml.core.FastHTML.get_client': ('api/core.html#fasthtml.get_client', 'fasthtml/core.py'),
|
|
48
50
|
'fasthtml.core.FastHTML.route': ('api/core.html#fasthtml.route', 'fasthtml/core.py'),
|
|
51
|
+
'fasthtml.core.FastHTML.set_lifespan': ('api/core.html#fasthtml.set_lifespan', 'fasthtml/core.py'),
|
|
52
|
+
'fasthtml.core.FastHTML.setup_ws': ('api/core.html#fasthtml.setup_ws', 'fasthtml/core.py'),
|
|
49
53
|
'fasthtml.core.FastHTML.static_route': ('api/core.html#fasthtml.static_route', 'fasthtml/core.py'),
|
|
50
54
|
'fasthtml.core.FastHTML.static_route_exts': ('api/core.html#fasthtml.static_route_exts', 'fasthtml/core.py'),
|
|
51
55
|
'fasthtml.core.FastHTML.ws': ('api/core.html#fasthtml.ws', 'fasthtml/core.py'),
|
|
@@ -58,6 +62,8 @@ d = { 'settings': { 'branch': 'main',
|
|
|
58
62
|
'fasthtml.core.HtmxHeaders.__bool__': ('api/core.html#htmxheaders.__bool__', 'fasthtml/core.py'),
|
|
59
63
|
'fasthtml.core.HtmxResponseHeaders': ('api/core.html#htmxresponseheaders', 'fasthtml/core.py'),
|
|
60
64
|
'fasthtml.core.HttpHeader': ('api/core.html#httpheader', 'fasthtml/core.py'),
|
|
65
|
+
'fasthtml.core.JSONResponse': ('api/core.html#jsonresponse', 'fasthtml/core.py'),
|
|
66
|
+
'fasthtml.core.JSONResponse.render': ('api/core.html#jsonresponse.render', 'fasthtml/core.py'),
|
|
61
67
|
'fasthtml.core.MiddlewareBase': ('api/core.html#middlewarebase', 'fasthtml/core.py'),
|
|
62
68
|
'fasthtml.core.MiddlewareBase.__call__': ('api/core.html#middlewarebase.__call__', 'fasthtml/core.py'),
|
|
63
69
|
'fasthtml.core.Redirect': ('api/core.html#redirect', 'fasthtml/core.py'),
|
|
@@ -68,10 +74,14 @@ d = { 'settings': { 'branch': 'main',
|
|
|
68
74
|
'fasthtml.core.RouteFuncs.__getattr__': ('api/core.html#routefuncs.__getattr__', 'fasthtml/core.py'),
|
|
69
75
|
'fasthtml.core.RouteFuncs.__init__': ('api/core.html#routefuncs.__init__', 'fasthtml/core.py'),
|
|
70
76
|
'fasthtml.core.RouteFuncs.__setattr__': ('api/core.html#routefuncs.__setattr__', 'fasthtml/core.py'),
|
|
77
|
+
'fasthtml.core.StaticNoCache': ('api/core.html#staticnocache', 'fasthtml/core.py'),
|
|
78
|
+
'fasthtml.core.StaticNoCache.file_response': ( 'api/core.html#staticnocache.file_response',
|
|
79
|
+
'fasthtml/core.py'),
|
|
71
80
|
'fasthtml.core.StringConvertor.to_string': ('api/core.html#stringconvertor.to_string', 'fasthtml/core.py'),
|
|
72
81
|
'fasthtml.core._add_ids': ('api/core.html#_add_ids', 'fasthtml/core.py'),
|
|
73
82
|
'fasthtml.core._annotations': ('api/core.html#_annotations', 'fasthtml/core.py'),
|
|
74
83
|
'fasthtml.core._apply_ft': ('api/core.html#_apply_ft', 'fasthtml/core.py'),
|
|
84
|
+
'fasthtml.core._canonical': ('api/core.html#_canonical', 'fasthtml/core.py'),
|
|
75
85
|
'fasthtml.core._find_p': ('api/core.html#_find_p', 'fasthtml/core.py'),
|
|
76
86
|
'fasthtml.core._find_targets': ('api/core.html#_find_targets', 'fasthtml/core.py'),
|
|
77
87
|
'fasthtml.core._find_wsp': ('api/core.html#_find_wsp', 'fasthtml/core.py'),
|
|
@@ -87,6 +97,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
87
97
|
'fasthtml.core._mk_list': ('api/core.html#_mk_list', 'fasthtml/core.py'),
|
|
88
98
|
'fasthtml.core._mk_locfunc': ('api/core.html#_mk_locfunc', 'fasthtml/core.py'),
|
|
89
99
|
'fasthtml.core._params': ('api/core.html#_params', 'fasthtml/core.py'),
|
|
100
|
+
'fasthtml.core._part_resp': ('api/core.html#_part_resp', 'fasthtml/core.py'),
|
|
90
101
|
'fasthtml.core._resp': ('api/core.html#_resp', 'fasthtml/core.py'),
|
|
91
102
|
'fasthtml.core._send_ws': ('api/core.html#_send_ws', 'fasthtml/core.py'),
|
|
92
103
|
'fasthtml.core._to_htmx_header': ('api/core.html#_to_htmx_header', 'fasthtml/core.py'),
|
|
@@ -98,7 +109,6 @@ d = { 'settings': { 'branch': 'main',
|
|
|
98
109
|
'fasthtml.core._wrap_ws': ('api/core.html#_wrap_ws', 'fasthtml/core.py'),
|
|
99
110
|
'fasthtml.core._ws_endp': ('api/core.html#_ws_endp', 'fasthtml/core.py'),
|
|
100
111
|
'fasthtml.core._xt_cts': ('api/core.html#_xt_cts', 'fasthtml/core.py'),
|
|
101
|
-
'fasthtml.core._xt_resp': ('api/core.html#_xt_resp', 'fasthtml/core.py'),
|
|
102
112
|
'fasthtml.core.cookie': ('api/core.html#cookie', 'fasthtml/core.py'),
|
|
103
113
|
'fasthtml.core.decode_uri': ('api/core.html#decode_uri', 'fasthtml/core.py'),
|
|
104
114
|
'fasthtml.core.def_hdrs': ('api/core.html#def_hdrs', 'fasthtml/core.py'),
|
|
@@ -106,6 +116,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
106
116
|
'fasthtml.core.flat_xt': ('api/core.html#flat_xt', 'fasthtml/core.py'),
|
|
107
117
|
'fasthtml.core.form2dict': ('api/core.html#form2dict', 'fasthtml/core.py'),
|
|
108
118
|
'fasthtml.core.get_key': ('api/core.html#get_key', 'fasthtml/core.py'),
|
|
119
|
+
'fasthtml.core.is_full_page': ('api/core.html#is_full_page', 'fasthtml/core.py'),
|
|
109
120
|
'fasthtml.core.nested_name': ('api/core.html#nested_name', 'fasthtml/core.py'),
|
|
110
121
|
'fasthtml.core.noop_body': ('api/core.html#noop_body', 'fasthtml/core.py'),
|
|
111
122
|
'fasthtml.core.parse_form': ('api/core.html#parse_form', 'fasthtml/core.py'),
|
|
@@ -114,7 +125,6 @@ d = { 'settings': { 'branch': 'main',
|
|
|
114
125
|
'fasthtml.core.reg_re_param': ('api/core.html#reg_re_param', 'fasthtml/core.py'),
|
|
115
126
|
'fasthtml.core.respond': ('api/core.html#respond', 'fasthtml/core.py'),
|
|
116
127
|
'fasthtml.core.serve': ('api/core.html#serve', 'fasthtml/core.py'),
|
|
117
|
-
'fasthtml.core.setup_ws': ('api/core.html#setup_ws', 'fasthtml/core.py'),
|
|
118
128
|
'fasthtml.core.signal_shutdown': ('api/core.html#signal_shutdown', 'fasthtml/core.py'),
|
|
119
129
|
'fasthtml.core.snake2hyphens': ('api/core.html#snake2hyphens', 'fasthtml/core.py'),
|
|
120
130
|
'fasthtml.core.unqid': ('api/core.html#unqid', 'fasthtml/core.py'),
|
|
@@ -132,6 +142,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
132
142
|
'fasthtml.jupyter.JupyUvi': ('api/jupyter.html#jupyuvi', 'fasthtml/jupyter.py'),
|
|
133
143
|
'fasthtml.jupyter.JupyUvi.__init__': ('api/jupyter.html#jupyuvi.__init__', 'fasthtml/jupyter.py'),
|
|
134
144
|
'fasthtml.jupyter.JupyUvi.start': ('api/jupyter.html#jupyuvi.start', 'fasthtml/jupyter.py'),
|
|
145
|
+
'fasthtml.jupyter.JupyUvi.start_async': ('api/jupyter.html#jupyuvi.start_async', 'fasthtml/jupyter.py'),
|
|
135
146
|
'fasthtml.jupyter.JupyUvi.stop': ('api/jupyter.html#jupyuvi.stop', 'fasthtml/jupyter.py'),
|
|
136
147
|
'fasthtml.jupyter.JupyUviAsync': ('api/jupyter.html#jupyuviasync', 'fasthtml/jupyter.py'),
|
|
137
148
|
'fasthtml.jupyter.JupyUviAsync.__init__': ( 'api/jupyter.html#jupyuviasync.__init__',
|
|
@@ -166,6 +177,8 @@ d = { 'settings': { 'branch': 'main',
|
|
|
166
177
|
'fasthtml.oauth.GitHubAppClient.__init__': ('api/oauth.html#githubappclient.__init__', 'fasthtml/oauth.py'),
|
|
167
178
|
'fasthtml.oauth.GoogleAppClient': ('api/oauth.html#googleappclient', 'fasthtml/oauth.py'),
|
|
168
179
|
'fasthtml.oauth.GoogleAppClient.__init__': ('api/oauth.html#googleappclient.__init__', 'fasthtml/oauth.py'),
|
|
180
|
+
'fasthtml.oauth.GoogleAppClient.consent_url': ( 'api/oauth.html#googleappclient.consent_url',
|
|
181
|
+
'fasthtml/oauth.py'),
|
|
169
182
|
'fasthtml.oauth.GoogleAppClient.creds': ('api/oauth.html#googleappclient.creds', 'fasthtml/oauth.py'),
|
|
170
183
|
'fasthtml.oauth.GoogleAppClient.from_file': ( 'api/oauth.html#googleappclient.from_file',
|
|
171
184
|
'fasthtml/oauth.py'),
|
|
@@ -189,6 +202,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
189
202
|
'fasthtml/oauth.py'),
|
|
190
203
|
'fasthtml.oauth._AppClient.retr_id': ('api/oauth.html#_appclient.retr_id', 'fasthtml/oauth.py'),
|
|
191
204
|
'fasthtml.oauth._AppClient.retr_info': ('api/oauth.html#_appclient.retr_info', 'fasthtml/oauth.py'),
|
|
205
|
+
'fasthtml.oauth.get_host': ('api/oauth.html#get_host', 'fasthtml/oauth.py'),
|
|
192
206
|
'fasthtml.oauth.load_creds': ('api/oauth.html#load_creds', 'fasthtml/oauth.py'),
|
|
193
207
|
'fasthtml.oauth.redir_url': ('api/oauth.html#redir_url', 'fasthtml/oauth.py'),
|
|
194
208
|
'fasthtml.oauth.url_match': ('api/oauth.html#url_match', 'fasthtml/oauth.py')},
|
|
@@ -247,8 +261,16 @@ d = { 'settings': { 'branch': 'main',
|
|
|
247
261
|
'fasthtml.xtend.CheckboxX': ('api/xtend.html#checkboxx', 'fasthtml/xtend.py'),
|
|
248
262
|
'fasthtml.xtend.Favicon': ('api/xtend.html#favicon', 'fasthtml/xtend.py'),
|
|
249
263
|
'fasthtml.xtend.Form': ('api/xtend.html#form', 'fasthtml/xtend.py'),
|
|
264
|
+
'fasthtml.xtend.Fragment': ('api/xtend.html#fragment', 'fasthtml/xtend.py'),
|
|
265
|
+
'fasthtml.xtend.Fragment.__init__': ('api/xtend.html#fragment.__init__', 'fasthtml/xtend.py'),
|
|
250
266
|
'fasthtml.xtend.Hidden': ('api/xtend.html#hidden', 'fasthtml/xtend.py'),
|
|
251
267
|
'fasthtml.xtend.HtmxOn': ('api/xtend.html#htmxon', 'fasthtml/xtend.py'),
|
|
268
|
+
'fasthtml.xtend.LdContactPoint': ('api/xtend.html#ldcontactpoint', 'fasthtml/xtend.py'),
|
|
269
|
+
'fasthtml.xtend.LdCourse': ('api/xtend.html#ldcourse', 'fasthtml/xtend.py'),
|
|
270
|
+
'fasthtml.xtend.LdCourseInstance': ('api/xtend.html#ldcourseinstance', 'fasthtml/xtend.py'),
|
|
271
|
+
'fasthtml.xtend.LdJson': ('api/xtend.html#ldjson', 'fasthtml/xtend.py'),
|
|
272
|
+
'fasthtml.xtend.LdOrg': ('api/xtend.html#ldorg', 'fasthtml/xtend.py'),
|
|
273
|
+
'fasthtml.xtend.LdWebsite': ('api/xtend.html#ldwebsite', 'fasthtml/xtend.py'),
|
|
252
274
|
'fasthtml.xtend.Nbsp': ('api/xtend.html#nbsp', 'fasthtml/xtend.py'),
|
|
253
275
|
'fasthtml.xtend.Now': ('api/xtend.html#now', 'fasthtml/xtend.py'),
|
|
254
276
|
'fasthtml.xtend.On': ('api/xtend.html#on', 'fasthtml/xtend.py'),
|
|
@@ -266,6 +288,9 @@ d = { 'settings': { 'branch': 'main',
|
|
|
266
288
|
'fasthtml.xtend.jsd': ('api/xtend.html#jsd', 'fasthtml/xtend.py'),
|
|
267
289
|
'fasthtml.xtend.loose_format': ('api/xtend.html#loose_format', 'fasthtml/xtend.py'),
|
|
268
290
|
'fasthtml.xtend.replace_css_vars': ('api/xtend.html#replace_css_vars', 'fasthtml/xtend.py'),
|
|
291
|
+
'fasthtml.xtend.robots_txt': ('api/xtend.html#robots_txt', 'fasthtml/xtend.py'),
|
|
269
292
|
'fasthtml.xtend.run_js': ('api/xtend.html#run_js', 'fasthtml/xtend.py'),
|
|
293
|
+
'fasthtml.xtend.sitemap_url': ('api/xtend.html#sitemap_url', 'fasthtml/xtend.py'),
|
|
294
|
+
'fasthtml.xtend.sitemap_xml': ('api/xtend.html#sitemap_xml', 'fasthtml/xtend.py'),
|
|
270
295
|
'fasthtml.xtend.undouble_braces': ('api/xtend.html#undouble_braces', 'fasthtml/xtend.py'),
|
|
271
296
|
'fasthtml.xtend.with_sid': ('api/xtend.html#with_sid', 'fasthtml/xtend.py')}}}
|
|
@@ -36,7 +36,7 @@ def railway_deploy(
|
|
|
36
36
|
):
|
|
37
37
|
"""Deploy a FastHTML app to Railway"""
|
|
38
38
|
nm,ver = check_output("railway --version".split()).decode().split()
|
|
39
|
-
assert nm
|
|
39
|
+
assert nm.startswith('railway'), f'Unexpected railway version string: {nm}'
|
|
40
40
|
if ver2tuple(ver)<(3,8): return print("Please update your railway CLI version to 3.8 or higher")
|
|
41
41
|
cp = run("railway status --json".split(), capture_output=True)
|
|
42
42
|
if not cp.returncode:
|
|
@@ -3,22 +3,23 @@
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/01_components.ipynb.
|
|
4
4
|
|
|
5
5
|
# %% auto 0
|
|
6
|
-
__all__ = ['named', 'html_attrs', 'hx_attrs', '
|
|
7
|
-
'
|
|
8
|
-
'
|
|
9
|
-
'
|
|
10
|
-
'
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
6
|
+
__all__ = ['named', 'html_attrs', 'hx_attrs', 'hx_evts', 'js_evts', 'hx_attrs_annotations', 'hx_evt_attrs', 'js_evt_attrs',
|
|
7
|
+
'evt_attrs', 'attrmap_x', 'ft_html', 'ft_hx', 'File', 'show', 'fill_form', 'fill_dataclass', 'find_inputs',
|
|
8
|
+
'html2ft', 'sse_message', 'A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi',
|
|
9
|
+
'Bdo', 'Blockquote', 'Body', 'Br', 'Button', 'Canvas', 'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data',
|
|
10
|
+
'Datalist', 'Dd', 'Del', 'Details', 'Dfn', 'Dialog', 'Div', 'Dl', 'Dt', 'Em', 'Embed', 'Fencedframe',
|
|
11
|
+
'Fieldset', 'Figcaption', 'Figure', 'Footer', 'Form', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Head', 'Header',
|
|
12
|
+
'Hgroup', 'Hr', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li', 'Link', 'Main', 'Map',
|
|
13
|
+
'Mark', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript', 'Object', 'Ol', 'Optgroup', 'Option', 'Output', 'P',
|
|
14
|
+
'Picture', 'PortalExperimental', 'Pre', 'Progress', 'Q', 'Rp', 'Rt', 'Ruby', 'S', 'Samp', 'Script', 'Search',
|
|
15
|
+
'Section', 'Select', 'Slot', 'Small', 'Source', 'Span', 'Strong', 'Style', 'Sub', 'Summary', 'Sup', 'Table',
|
|
16
|
+
'Tbody', 'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul',
|
|
17
|
+
'Var', 'Video', 'Wbr']
|
|
17
18
|
|
|
18
19
|
# %% ../nbs/api/01_components.ipynb
|
|
19
20
|
from dataclasses import dataclass, asdict, is_dataclass, make_dataclass, replace, astuple, MISSING
|
|
20
21
|
from bs4 import BeautifulSoup, Comment
|
|
21
|
-
from typing import Literal, Optional
|
|
22
|
+
from typing import Literal, Mapping, Optional
|
|
22
23
|
|
|
23
24
|
from fastcore.utils import *
|
|
24
25
|
from fastcore.xml import *
|
|
@@ -31,15 +32,9 @@ import types, json
|
|
|
31
32
|
try: from IPython import display
|
|
32
33
|
except ImportError: display=None
|
|
33
34
|
|
|
34
|
-
# %% ../nbs/api/01_components.ipynb
|
|
35
|
-
def show(ft,*rest):
|
|
36
|
-
"Renders FT Components into HTML within a Jupyter notebook."
|
|
37
|
-
if rest: ft = (ft,)+rest
|
|
38
|
-
display.display(display.HTML(to_xml(ft)))
|
|
39
|
-
|
|
40
35
|
# %% ../nbs/api/01_components.ipynb
|
|
41
36
|
@patch
|
|
42
|
-
def __str__(self:FT): return self.id if self.id else
|
|
37
|
+
def __str__(self:FT): return self.id if self.id else to_xml(self, indent=False)
|
|
43
38
|
|
|
44
39
|
# %% ../nbs/api/01_components.ipynb
|
|
45
40
|
@patch
|
|
@@ -53,6 +48,9 @@ def __add__(self:FT, b): return f'{self}{b}'
|
|
|
53
48
|
named = set('a button form frame iframe img input map meta object param select textarea'.split())
|
|
54
49
|
html_attrs = 'id cls title style accesskey contenteditable dir draggable enterkeyhint hidden inert inputmode lang popover spellcheck tabindex translate'.split()
|
|
55
50
|
hx_attrs = 'get post put delete patch trigger target swap swap_oob include select select_oob indicator push_url confirm disable replace_url vals disabled_elt ext headers history history_elt indicator inherit params preserve prompt replace_url request sync validate'
|
|
51
|
+
|
|
52
|
+
hx_evts = 'abort afterOnLoad afterProcessNode afterRequest afterSettle afterSwap beforeCleanupElement beforeOnLoad beforeProcessNode beforeRequest beforeSwap beforeSend beforeTransition configRequest confirm historyCacheError historyCacheMiss historyCacheMissError historyCacheMissLoad historyRestore beforeHistorySave load noSSESourceError onLoadError oobAfterSwap oobBeforeSwap oobErrorNoTarget prompt pushedIntoHistory replacedInHistory responseError sendAbort sendError sseError sseOpen swapError targetError timeout validation:validate validation:failed validation:halted xhr:abort xhr:loadend xhr:loadstart xhr:progress'
|
|
53
|
+
js_evts = "blur change contextmenu focus input invalid reset select submit keydown keypress keyup click dblclick mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup wheel"
|
|
56
54
|
hx_attrs = [f'hx_{o}' for o in hx_attrs.split()]
|
|
57
55
|
hx_attrs_annotations = {
|
|
58
56
|
"hx_swap": Literal["innerHTML", "outerHTML", "afterbegin", "beforebegin", "beforeend", "afterend", "delete", "none"] | str,
|
|
@@ -68,6 +66,10 @@ hx_attrs_annotations |= {o: str for o in set(hx_attrs) - set(hx_attrs_annotation
|
|
|
68
66
|
hx_attrs_annotations = {k: Optional[v] for k,v in hx_attrs_annotations.items()}
|
|
69
67
|
hx_attrs = html_attrs + hx_attrs
|
|
70
68
|
|
|
69
|
+
hx_evt_attrs = ['hx_on__'+camel2snake(o).replace(':','_') for o in hx_evts.split()]
|
|
70
|
+
js_evt_attrs = ['hx_on_'+o for o in js_evts.split()]
|
|
71
|
+
evt_attrs = js_evt_attrs+hx_evt_attrs
|
|
72
|
+
|
|
71
73
|
# %% ../nbs/api/01_components.ipynb
|
|
72
74
|
def attrmap_x(o):
|
|
73
75
|
if o.startswith('_at_'): o = '@'+o[4:]
|
|
@@ -82,7 +84,7 @@ fh_cfg['auto_name']=True
|
|
|
82
84
|
|
|
83
85
|
# %% ../nbs/api/01_components.ipynb
|
|
84
86
|
def ft_html(tag: str, *c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=None, **kwargs):
|
|
85
|
-
ds,c = partition(c, risinstance(
|
|
87
|
+
ds,c = partition(c, risinstance(Mapping))
|
|
86
88
|
for d in ds: kwargs = {**kwargs, **d}
|
|
87
89
|
if ft_cls is None: ft_cls = fh_cfg.ft_cls
|
|
88
90
|
if attrmap is None: attrmap=fh_cfg.attrmap
|
|
@@ -96,7 +98,7 @@ def ft_html(tag: str, *c, id=None, cls=None, title=None, style=None, attrmap=Non
|
|
|
96
98
|
return ft_cls(tag,c,kw, void_=tag in voids)
|
|
97
99
|
|
|
98
100
|
# %% ../nbs/api/01_components.ipynb
|
|
99
|
-
@use_kwargs(hx_attrs, keep=True)
|
|
101
|
+
@use_kwargs(hx_attrs+evt_attrs, keep=True)
|
|
100
102
|
def ft_hx(tag: str, *c, target_id=None, hx_vals=None, hx_target=None, **kwargs):
|
|
101
103
|
if hx_vals: kwargs['hx_vals'] = json.dumps(hx_vals) if isinstance (hx_vals,dict) else hx_vals
|
|
102
104
|
if hx_target: kwargs['hx_target'] = '#'+hx_target.id if isinstance(hx_target,FT) else hx_target
|
|
@@ -122,6 +124,20 @@ def File(fname):
|
|
|
122
124
|
"Use the unescaped text in file `fname` directly"
|
|
123
125
|
return NotStr(Path(fname).read_text())
|
|
124
126
|
|
|
127
|
+
# %% ../nbs/api/01_components.ipynb
|
|
128
|
+
def show(ft, *rest, iframe=False, height='auto', style=None):
|
|
129
|
+
"Renders FT Components into HTML within a Jupyter notebook."
|
|
130
|
+
if isinstance(ft, str): ft = Safe(ft)
|
|
131
|
+
if rest: ft = (ft,)+rest
|
|
132
|
+
res = to_xml(ft)
|
|
133
|
+
if iframe:
|
|
134
|
+
style = "border: none; " + (style or "")
|
|
135
|
+
cfg = dict(frameborder=0, width='100%', height=height, style=style)
|
|
136
|
+
res = to_xml(Iframe(srcdoc=res, **cfg))
|
|
137
|
+
with warnings.catch_warnings():
|
|
138
|
+
warnings.simplefilter("ignore", UserWarning)
|
|
139
|
+
display.display(display.HTML(res))
|
|
140
|
+
|
|
125
141
|
# %% ../nbs/api/01_components.ipynb
|
|
126
142
|
def _fill_item(item, obj):
|
|
127
143
|
if not isinstance(item,FT): return item
|
|
@@ -191,18 +207,19 @@ _re_h2x_attr_key = re.compile(r'^[A-Za-z_-][\w-]*$')
|
|
|
191
207
|
def html2ft(html, attr1st=False):
|
|
192
208
|
"""Convert HTML to an `ft` expression"""
|
|
193
209
|
rev_map = {'class': 'cls', 'for': 'fr'}
|
|
194
|
-
|
|
210
|
+
|
|
195
211
|
def _parse(elm, lvl=0, indent=4):
|
|
196
|
-
if isinstance(elm, str): return repr(elm.strip()) if elm.strip() else ''
|
|
212
|
+
if isinstance(elm, str): return repr(elm.strip("\n")) if elm.strip() else ''
|
|
197
213
|
if isinstance(elm, list): return '\n'.join(_parse(o, lvl) for o in elm)
|
|
198
214
|
tag_name = elm.name.capitalize().replace("-", "_")
|
|
199
215
|
if tag_name=='[document]': return _parse(list(elm.children), lvl)
|
|
200
216
|
cts = elm.contents
|
|
201
|
-
cs = [repr(c.strip()) if isinstance(c, str) else _parse(c, lvl+1)
|
|
217
|
+
cs = [repr(c.strip("\n")) if isinstance(c, str) else _parse(c, lvl+1)
|
|
202
218
|
for c in cts if str(c).strip()]
|
|
203
219
|
attrs, exotic_attrs = [], {}
|
|
204
220
|
for key, value in sorted(elm.attrs.items(), key=lambda x: x[0]=='class'):
|
|
205
|
-
if
|
|
221
|
+
if value is None or value == True: value = True # handle boolean attributes
|
|
222
|
+
elif isinstance(value,(tuple,list)): value = " ".join(value)
|
|
206
223
|
key, value = rev_map.get(key, key), value or True
|
|
207
224
|
if _re_h2x_attr_key.match(key): attrs.append(f'{key.replace("-", "_")}={value!r}')
|
|
208
225
|
else: exotic_attrs[key] = value
|