Skip to content

Commit c417946

Browse files
committed
fixes #48
1 parent 122e5ac commit c417946

File tree

8 files changed

+45
-15
lines changed

8 files changed

+45
-15
lines changed

fasthtml/_modidx.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
'fasthtml.cli.railway_deploy': ('cli.html#railway_deploy', 'fasthtml/cli.py'),
1111
'fasthtml.cli.railway_link': ('cli.html#railway_link', 'fasthtml/cli.py')},
1212
'fasthtml.common': {},
13-
'fasthtml.components': { 'fasthtml.components.__getattr__': ('components.html#__getattr__', 'fasthtml/components.py'),
13+
'fasthtml.components': { 'fasthtml.components.File': ('components.html#file', 'fasthtml/components.py'),
14+
'fasthtml.components.__getattr__': ('components.html#__getattr__', 'fasthtml/components.py'),
1415
'fasthtml.components._fill_item': ('components.html#_fill_item', 'fasthtml/components.py'),
1516
'fasthtml.components.fill_dataclass': ('components.html#fill_dataclass', 'fasthtml/components.py'),
1617
'fasthtml.components.fill_form': ('components.html#fill_form', 'fasthtml/components.py'),

fasthtml/components.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_components.ipynb.
22

33
# %% auto 0
4-
__all__ = ['voids', 'named', 'html_attrs', 'hx_attrs', 'show', 'xt_html', 'xt_hx', 'fill_form', 'fill_dataclass', 'find_inputs',
5-
'html2xt', 'A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi', 'Bdo',
6-
'Blockquote', 'Body', 'Br', 'Button', 'Canvas', 'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data',
4+
__all__ = ['voids', 'named', 'html_attrs', 'hx_attrs', 'show', 'xt_html', 'xt_hx', 'File', 'fill_form', 'fill_dataclass',
5+
'find_inputs', 'html2xt', 'A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi',
6+
'Bdo', 'Blockquote', 'Body', 'Br', 'Button', 'Canvas', 'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data',
77
'Datalist', 'Dd', 'Del', 'Details', 'Dfn', 'Dialog', 'Div', 'Dl', 'Dt', 'Em', 'Embed', 'Fencedframe',
88
'Fieldset', 'Figcaption', 'Figure', 'Footer', 'Form', 'H1', 'Head', 'Header', 'Hgroup', 'Hr', 'Html', 'I',
99
'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li', 'Link', 'Main', 'Map', 'Mark', 'Menu',
@@ -65,7 +65,12 @@ def xt_hx(tag: str, *c, target_id=None, **kwargs):
6565
'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul', 'Var', 'Video', 'Wbr']
6666
for o in _all_: _g[o] = partial(xt_hx, o.lower())
6767

68-
# %% ../nbs/01_components.ipynb 13
68+
# %% ../nbs/01_components.ipynb 9
69+
def File(fname):
70+
"Use the unescaped text in file `fname` directly"
71+
return NotStr(Path(fname).read_text())
72+
73+
# %% ../nbs/01_components.ipynb 14
6974
def _fill_item(item, obj):
7075
if not isinstance(item,list): return item
7176
tag,cs,attr = item
@@ -81,19 +86,19 @@ def _fill_item(item, obj):
8186
if tag=='textarea': cs=(val,)
8287
return XT(tag,cs,attr)
8388

84-
# %% ../nbs/01_components.ipynb 14
89+
# %% ../nbs/01_components.ipynb 15
8590
def fill_form(form:XT, obj)->XT:
8691
"Fills named items in `form` using attributes in `obj`"
8792
if not isinstance(obj,dict): obj = asdict(obj)
8893
return _fill_item(form, obj)
8994

90-
# %% ../nbs/01_components.ipynb 16
95+
# %% ../nbs/01_components.ipynb 17
9196
def fill_dataclass(src, dest):
9297
"Modifies dataclass in-place and returns it"
9398
for nm,val in asdict(src).items(): setattr(dest, nm, val)
9499
return dest
95100

96-
# %% ../nbs/01_components.ipynb 18
101+
# %% ../nbs/01_components.ipynb 19
97102
def find_inputs(e, tags='input', **kw):
98103
# Recursively find all elements in `e` with `tags` and attrs matching `kw`
99104
if not isinstance(e, (list,tuple)): return []
@@ -107,14 +112,14 @@ def find_inputs(e, tags='input', **kw):
107112
for o in cs: inputs += find_inputs(o, tags, **kw)
108113
return inputs
109114

110-
# %% ../nbs/01_components.ipynb 22
115+
# %% ../nbs/01_components.ipynb 23
111116
def __getattr__(tag):
112117
if tag.startswith('_') or tag[0].islower(): raise AttributeError
113118
tag = tag.replace("_", "-")
114119
def _f(*c, target_id=None, **kwargs): return xt_hx(tag, *c, target_id=target_id, **kwargs)
115120
return _f
116121

117-
# %% ../nbs/01_components.ipynb 23
122+
# %% ../nbs/01_components.ipynb 24
118123
def html2xt(html):
119124
rev_map = {'class': 'cls', 'for': 'fr'}
120125

fasthtml/components.pyi

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__all__ = ['voids', 'named', 'html_attrs', 'hx_attrs', 'show', 'xt_html', 'xt_hx', 'fill_form', 'fill_dataclass', 'find_inputs', 'html2xt', 'A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi', 'Bdo', 'Blockquote', 'Body', 'Br', 'Button', 'Canvas', 'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data', 'Datalist', 'Dd', 'Del', 'Details', 'Dfn', 'Dialog', 'Div', 'Dl', 'Dt', 'Em', 'Embed', 'Fencedframe', 'Fieldset', 'Figcaption', 'Figure', 'Footer', 'Form', 'H1', 'Head', 'Header', 'Hgroup', 'Hr', 'Html', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li', 'Link', 'Main', 'Map', 'Mark', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript', 'Object', 'Ol', 'Optgroup', 'Option', 'Output', 'P', 'Picture', 'PortalExperimental', 'Pre', 'Progress', 'Q', 'Rp', 'Rt', 'Ruby', 'S', 'Samp', 'Script', 'Search', 'Section', 'Select', 'Slot', 'Small', 'Source', 'Span', 'Strong', 'Style', 'Sub', 'Summary', 'Sup', 'Table', 'Tbody', 'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul', 'Var', 'Video', 'Wbr']
1+
__all__ = ['voids', 'named', 'html_attrs', 'hx_attrs', 'show', 'xt_html', 'xt_hx', 'File', 'fill_form', 'fill_dataclass', 'find_inputs', 'html2xt', 'A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi', 'Bdo', 'Blockquote', 'Body', 'Br', 'Button', 'Canvas', 'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data', 'Datalist', 'Dd', 'Del', 'Details', 'Dfn', 'Dialog', 'Div', 'Dl', 'Dt', 'Em', 'Embed', 'Fencedframe', 'Fieldset', 'Figcaption', 'Figure', 'Footer', 'Form', 'H1', 'Head', 'Header', 'Hgroup', 'Hr', 'Html', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li', 'Link', 'Main', 'Map', 'Mark', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript', 'Object', 'Ol', 'Optgroup', 'Option', 'Output', 'P', 'Picture', 'PortalExperimental', 'Pre', 'Progress', 'Q', 'Rp', 'Rt', 'Ruby', 'S', 'Samp', 'Script', 'Search', 'Section', 'Select', 'Slot', 'Small', 'Source', 'Span', 'Strong', 'Style', 'Sub', 'Summary', 'Sup', 'Table', 'Tbody', 'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul', 'Var', 'Video', 'Wbr']
22
from dataclasses import dataclass, asdict, is_dataclass, make_dataclass, replace, astuple, MISSING
33
from bs4 import BeautifulSoup
44
from fastcore.utils import *
@@ -29,6 +29,10 @@ _all_ = ['A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base
2929
for o in _all_:
3030
_g[o] = partial(xt_hx, o.lower())
3131

32+
def File(fname):
33+
"""Use the unescaped text in file `fname` directly"""
34+
...
35+
3236
def _fill_item(item, obj):
3337
...
3438

fasthtml/fastapp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def fast_app(db=None, render=None, hdrs=None, tbls=None, before=None, middleware
1717
sess_path='/', same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey', **kwargs):
1818

1919
h = ()
20-
if not default_hdrs: h += (picolink, )
20+
if default_hdrs: h += (picolink, )
2121
if hdrs: h += tuple(hdrs)
2222
app_cls = FastHTMLWithLiveReload if live else FastHTML
2323
app = app_cls(hdrs=h, before=before, middleware=middleware, debug=debug, routes=routes, exception_handlers=exception_handlers,

fasthtml/xtend.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,21 +148,23 @@ def loose_format(s, **kw):
148148

149149
# %% ../nbs/02_xtend.ipynb 34
150150
def ScriptX(fname, type=None, _async=None, defer=None, charset=None, crossorigin=None, integrity=None, **kw):
151-
"Create a Script from the text of a file"
151+
"A `script` element with contents read from `fname`"
152152
attrs = ['src', 'type', 'async', 'defer', 'charset', 'crossorigin', 'integrity', 'nomodule']
153153
scr_kw = {k:kw.pop(k) for k in attrs if k in kw}
154154
s = loose_format(Path(fname).read_text(), **kw)
155155
return Script(s, **scr_kw)
156156

157157
# %% ../nbs/02_xtend.ipynb 35
158158
def replace_css_vars(css, pre='tpl', **kwargs):
159+
"Replace `var(--)` CSS variables with `kwargs` if name prefix matches `pre`"
159160
def replace_var(m):
160161
var_name = m.group(1).replace('-', '_')
161162
return kwargs.get(var_name, m.group(0))
162163
return re.sub(fr'var\(--{pre}-([\w-]+)\)', replace_var, css)
163164

164165
# %% ../nbs/02_xtend.ipynb 36
165166
def StyleX(fname, **kw):
167+
"A `style` element with contents read from `fname` and variables replaced from `kw`"
166168
s = Path(fname).read_text()
167169
attrs = ['type', 'media', 'scoped', 'title', 'nonce', 'integrity', 'crossorigin']
168170
sty_kw = {k:kw.pop(k) for k in attrs if k in kw}

fasthtml/xtend.pyi

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,15 @@ def loose_format(s, **kw):
8282
...
8383

8484
def ScriptX(fname, type=None, _async=None, defer=None, charset=None, crossorigin=None, integrity=None, **kw):
85-
"""Create a Script from the text of a file"""
85+
"""A `script` element with contents read from `fname`"""
8686
...
8787

8888
def replace_css_vars(css, pre='tpl', **kwargs):
89+
"""Replace `var(--)` CSS variables with `kwargs` if name prefix matches `pre`"""
8990
...
9091

9192
def StyleX(fname, **kw):
93+
"""A `style` element with contents read from `fname` and variables replaced from `kw`"""
9294
...
9395

9496
def run_js(js, id=None, **kw):

nbs/01_components.ipynb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,19 @@
129129
"for o in _all_: _g[o] = partial(xt_hx, o.lower())"
130130
]
131131
},
132+
{
133+
"cell_type": "code",
134+
"execution_count": null,
135+
"id": "7ccf4371",
136+
"metadata": {},
137+
"outputs": [],
138+
"source": [
139+
"#| export\n",
140+
"def File(fname):\n",
141+
" \"Use the unescaped text in file `fname` directly\"\n",
142+
" return NotStr(Path(fname).read_text())"
143+
]
144+
},
132145
{
133146
"cell_type": "code",
134147
"execution_count": null,
@@ -151,6 +164,7 @@
151164
"both_attrs = html_attrs+hx_attrs\n",
152165
"\n",
153166
"create_pyi('../fasthtml/components.py', 'fasthtml')\n",
167+
"create_pyi('../fasthtml/xtend.py', 'fasthtml')\n",
154168
"with open('../fasthtml/components.pyi', 'a') as f:\n",
155169
" attrs_str = ', '.join(f'{t}:str|None=None' for t in both_attrs)\n",
156170
" f.write(f\"\\ndef xt_html(tag: str, *c, {attrs_str}, **kwargs): ...\\n\")\n",

nbs/02_xtend.ipynb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@
618618
"source": [
619619
"#| export\n",
620620
"def ScriptX(fname, type=None, _async=None, defer=None, charset=None, crossorigin=None, integrity=None, **kw):\n",
621-
" \"Create a Script from the text of a file\"\n",
621+
" \"A `script` element with contents read from `fname`\"\n",
622622
" attrs = ['src', 'type', 'async', 'defer', 'charset', 'crossorigin', 'integrity', 'nomodule']\n",
623623
" scr_kw = {k:kw.pop(k) for k in attrs if k in kw}\n",
624624
" s = loose_format(Path(fname).read_text(), **kw)\n",
@@ -634,6 +634,7 @@
634634
"source": [
635635
"#| export\n",
636636
"def replace_css_vars(css, pre='tpl', **kwargs):\n",
637+
" \"Replace `var(--)` CSS variables with `kwargs` if name prefix matches `pre`\"\n",
637638
" def replace_var(m):\n",
638639
" var_name = m.group(1).replace('-', '_')\n",
639640
" return kwargs.get(var_name, m.group(0))\n",
@@ -649,6 +650,7 @@
649650
"source": [
650651
"#| export\n",
651652
"def StyleX(fname, **kw):\n",
653+
" \"A `style` element with contents read from `fname` and variables replaced from `kw`\"\n",
652654
" s = Path(fname).read_text()\n",
653655
" attrs = ['type', 'media', 'scoped', 'title', 'nonce', 'integrity', 'crossorigin']\n",
654656
" sty_kw = {k:kw.pop(k) for k in attrs if k in kw}\n",

0 commit comments

Comments
 (0)