Skip to content

Commit

Permalink
fixes #48
Browse files Browse the repository at this point in the history
  • Loading branch information
jph00 committed Jul 13, 2024
1 parent 122e5ac commit c417946
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 15 deletions.
3 changes: 2 additions & 1 deletion fasthtml/_modidx.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
'fasthtml.cli.railway_deploy': ('cli.html#railway_deploy', 'fasthtml/cli.py'),
'fasthtml.cli.railway_link': ('cli.html#railway_link', 'fasthtml/cli.py')},
'fasthtml.common': {},
'fasthtml.components': { 'fasthtml.components.__getattr__': ('components.html#__getattr__', 'fasthtml/components.py'),
'fasthtml.components': { 'fasthtml.components.File': ('components.html#file', 'fasthtml/components.py'),
'fasthtml.components.__getattr__': ('components.html#__getattr__', 'fasthtml/components.py'),
'fasthtml.components._fill_item': ('components.html#_fill_item', 'fasthtml/components.py'),
'fasthtml.components.fill_dataclass': ('components.html#fill_dataclass', 'fasthtml/components.py'),
'fasthtml.components.fill_form': ('components.html#fill_form', 'fasthtml/components.py'),
Expand Down
23 changes: 14 additions & 9 deletions fasthtml/components.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_components.ipynb.

# %% auto 0
__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',
__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',
Expand Down Expand Up @@ -65,7 +65,12 @@ def xt_hx(tag: str, *c, target_id=None, **kwargs):
'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul', 'Var', 'Video', 'Wbr']
for o in _all_: _g[o] = partial(xt_hx, o.lower())

# %% ../nbs/01_components.ipynb 13
# %% ../nbs/01_components.ipynb 9
def File(fname):
"Use the unescaped text in file `fname` directly"
return NotStr(Path(fname).read_text())

# %% ../nbs/01_components.ipynb 14
def _fill_item(item, obj):
if not isinstance(item,list): return item
tag,cs,attr = item
Expand All @@ -81,19 +86,19 @@ def _fill_item(item, obj):
if tag=='textarea': cs=(val,)
return XT(tag,cs,attr)

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

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

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

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

# %% ../nbs/01_components.ipynb 23
# %% ../nbs/01_components.ipynb 24
def html2xt(html):
rev_map = {'class': 'cls', 'for': 'fr'}

Expand Down
6 changes: 5 additions & 1 deletion fasthtml/components.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__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']
__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']
from dataclasses import dataclass, asdict, is_dataclass, make_dataclass, replace, astuple, MISSING
from bs4 import BeautifulSoup
from fastcore.utils import *
Expand Down Expand Up @@ -29,6 +29,10 @@ _all_ = ['A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base
for o in _all_:
_g[o] = partial(xt_hx, o.lower())

def File(fname):
"""Use the unescaped text in file `fname` directly"""
...

def _fill_item(item, obj):
...

Expand Down
2 changes: 1 addition & 1 deletion fasthtml/fastapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def fast_app(db=None, render=None, hdrs=None, tbls=None, before=None, middleware
sess_path='/', same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey', **kwargs):

h = ()
if not default_hdrs: h += (picolink, )
if default_hdrs: h += (picolink, )
if hdrs: h += tuple(hdrs)
app_cls = FastHTMLWithLiveReload if live else FastHTML
app = app_cls(hdrs=h, before=before, middleware=middleware, debug=debug, routes=routes, exception_handlers=exception_handlers,
Expand Down
4 changes: 3 additions & 1 deletion fasthtml/xtend.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,21 +148,23 @@ def loose_format(s, **kw):

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

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

# %% ../nbs/02_xtend.ipynb 36
def StyleX(fname, **kw):
"A `style` element with contents read from `fname` and variables replaced from `kw`"
s = Path(fname).read_text()
attrs = ['type', 'media', 'scoped', 'title', 'nonce', 'integrity', 'crossorigin']
sty_kw = {k:kw.pop(k) for k in attrs if k in kw}
Expand Down
4 changes: 3 additions & 1 deletion fasthtml/xtend.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,15 @@ def loose_format(s, **kw):
...

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

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

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

def run_js(js, id=None, **kw):
Expand Down
14 changes: 14 additions & 0 deletions nbs/01_components.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,19 @@
"for o in _all_: _g[o] = partial(xt_hx, o.lower())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7ccf4371",
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"def File(fname):\n",
" \"Use the unescaped text in file `fname` directly\"\n",
" return NotStr(Path(fname).read_text())"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -151,6 +164,7 @@
"both_attrs = html_attrs+hx_attrs\n",
"\n",
"create_pyi('../fasthtml/components.py', 'fasthtml')\n",
"create_pyi('../fasthtml/xtend.py', 'fasthtml')\n",
"with open('../fasthtml/components.pyi', 'a') as f:\n",
" attrs_str = ', '.join(f'{t}:str|None=None' for t in both_attrs)\n",
" f.write(f\"\\ndef xt_html(tag: str, *c, {attrs_str}, **kwargs): ...\\n\")\n",
Expand Down
4 changes: 3 additions & 1 deletion nbs/02_xtend.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@
"source": [
"#| export\n",
"def ScriptX(fname, type=None, _async=None, defer=None, charset=None, crossorigin=None, integrity=None, **kw):\n",
" \"Create a Script from the text of a file\"\n",
" \"A `script` element with contents read from `fname`\"\n",
" attrs = ['src', 'type', 'async', 'defer', 'charset', 'crossorigin', 'integrity', 'nomodule']\n",
" scr_kw = {k:kw.pop(k) for k in attrs if k in kw}\n",
" s = loose_format(Path(fname).read_text(), **kw)\n",
Expand All @@ -634,6 +634,7 @@
"source": [
"#| export\n",
"def replace_css_vars(css, pre='tpl', **kwargs):\n",
" \"Replace `var(--)` CSS variables with `kwargs` if name prefix matches `pre`\"\n",
" def replace_var(m):\n",
" var_name = m.group(1).replace('-', '_')\n",
" return kwargs.get(var_name, m.group(0))\n",
Expand All @@ -649,6 +650,7 @@
"source": [
"#| export\n",
"def StyleX(fname, **kw):\n",
" \"A `style` element with contents read from `fname` and variables replaced from `kw`\"\n",
" s = Path(fname).read_text()\n",
" attrs = ['type', 'media', 'scoped', 'title', 'nonce', 'integrity', 'crossorigin']\n",
" sty_kw = {k:kw.pop(k) for k in attrs if k in kw}\n",
Expand Down

0 comments on commit c417946

Please sign in to comment.