组件

ft_html and ft_hx functions to add some conveniences to ft, along with a full set of basic HTML components, and functions to work with forms and FT conversion
from lxml import html as lx
from pprint import pprint

字符串、显示和表示


source

显示

 show (ft, *rest)

在 Jupyter 笔记本中将 FT 组件渲染为 HTML。

sentence = P(Strong("FastHTML is ", I("Fast")), id='sentence_id')

当放置在 show() 函数中时,这将会在Jupyter笔记本中渲染HTML。

show(sentence)

FastHTML 是 快速

在笔记本中,FT组件以其语法高亮的XML/HTML呈现:

sentence
<p id="sentence_id">
<strong>FastHTML is <i>Fast</i></strong></p>

在其他地方,它们被表示为其基础数据结构:

print(repr(sentence))
p((strong(('FastHTML is ', i(('Fast',),{})),{}),),{'id': 'sentence_id'})

FT.__str__

 FT.__str__ ()

返回 str(self)。

如果它们有一个id,那么该id将作为组件的str表示:

f'hx_target=#{sentence}'
'hx_target=#sentence_id'

FT.__radd__

 FT.__radd__ (b)
'hx_target=#' + sentence
'hx_target=#sentence_id'

FT.__add__

 FT.__add__ (b)
sentence + '...'
'sentence_id...'

fh_html 和 fh_hx


来源

属性映射_x

 attrmap_x (o)

来源

ft_html

 ft_html (tag:str, *c, id=None, cls=None, title=None, style=None,
          attrmap=None, valmap=None, ft_cls=None, **kwargs)
ft_html('a', **{'@click.away':1})
<a @click.away="1"></a>
ft_html('a', {'@click.away':1})
<a @click.away="1"></a>
c = Div(id='someid')
ft_html('a', id=c)
<a id="someid" name="someid"></a>

来源

ft_hx

 ft_hx (tag:str, *c, target_id=None, hx_vals=None, hx_target=None,
        id=None, cls=None, title=None, style=None, accesskey=None,
        contenteditable=None, dir=None, draggable=None, enterkeyhint=None,
        hidden=None, inert=None, inputmode=None, lang=None, popover=None,
        spellcheck=None, tabindex=None, translate=None, hx_get=None,
        hx_post=None, hx_put=None, hx_delete=None, hx_patch=None,
        hx_trigger=None, hx_swap=None, hx_swap_oob=None, hx_include=None,
        hx_select=None, hx_select_oob=None, hx_indicator=None,
        hx_push_url=None, hx_confirm=None, hx_disable=None,
        hx_replace_url=None, hx_disabled_elt=None, hx_ext=None,
        hx_headers=None, hx_history=None, hx_history_elt=None,
        hx_inherit=None, hx_params=None, hx_preserve=None, hx_prompt=None,
        hx_request=None, hx_sync=None, hx_validate=None, **kwargs)
ft_hx('a', hx_vals={'a':1})
<a hx-vals='{"a": 1}'></a>
ft_hx('a', hx_target=c)
<a hx-target="#someid"></a>

对于具有 name 属性的标签,如果未明确提供,则将其设置为 id 的值:

Form(Button(target_id='foo', id='btn'),
     hx_post='/', target_id='tgt', id='frm')
<form hx-post="/" hx-target="#tgt" id="frm" name="frm"><button hx-target="#foo" id="btn" name="btn"></button></form>

来源

文件

 File (fname)

直接使用文件 fname 中的未转义文本

a = Input(name='nm')
a
<input name="nm">
a(hx_swap_oob='true')
<input name="nm" hx-swap-oob="true">
a
<input name="nm" hx-swap-oob="true">

填写表单和查找输入字段


来源

填写表单

 fill_form (form:fastcore.xml.FT, obj)

使用obj中的属性填充form中的命名项

@dataclass
class TodoItem:
    title:str; id:int; done:bool; details:str; opt:str='a'

todo = TodoItem(id=2, title="Profit", done=True, details="Details", opt='b')
check = Label(Input(type="checkbox", cls="checkboxer", name="done", data_foo="bar"), "Done", cls='px-2')
form = Form(Fieldset(Input(cls="char", id="title", value="a"), check, Input(type="hidden", id="id"),
                     Select(Option(value='a'), Option(value='b'), name='opt'),
                     Textarea(id='details'), Button("Save"),
                     name="stuff"))
form = fill_form(form, todo)
assert '<textarea id="details" name="details">Details</textarea>' in to_xml(form)
form
<form><fieldset name="stuff">    <input value="Profit" id="title" class="char" name="title">
<label class="px-2">      <input type="checkbox" name="done" data-foo="bar" class="checkboxer" checked="1">
Done</label>    <input type="hidden" id="id" name="id" value="2">
<select name="opt"><option value="a"></option><option value="b" selected="1"></option></select><textarea id="details" name="details">Details</textarea><button>Save</button></fieldset></form>
@dataclass
class MultiSelect:
    items: list[str]

multiselect = MultiSelect(items=['a', 'c'])
multiform = Form(Select(Option('a', value='a'), Option('b', value='b'), Option('c', value='c'), multiple='1', name='items'))
multiform = fill_form(multiform, multiselect)
assert '<option value="a" selected="1">a</option>' in to_xml(multiform)
assert '<option value="b">b</option>' in to_xml(multiform)
assert '<option value="c" selected="1">c</option>' in to_xml(multiform)
multiform
<form><select multiple="1" name="items"><option value="a" selected="1">a</option><option value="b">b</option><option value="c" selected="1">c</option></select></form>
@dataclass
class MultiCheck:
    items: list[str]

multicheck = MultiCheck(items=['a', 'c'])
multiform = Form(Fieldset(Label(Input(type='checkbox', name='items', value='a'), 'a'),
                          Label(Input(type='checkbox', name='items', value='b'), 'b'),
                          Label(Input(type='checkbox', name='items', value='c'), 'c')))
multiform = fill_form(multiform, multicheck)
assert '<input type="checkbox" name="items" value="a" checked="1">' in to_xml(multiform)
assert '<input type="checkbox" name="items" value="b">' in to_xml(multiform)
assert '<input type="checkbox" name="items" value="c" checked="1">' in to_xml(multiform)
multiform
<form><fieldset><label>      <input type="checkbox" name="items" value="a" checked="1">
a</label><label>      <input type="checkbox" name="items" value="b">
b</label><label>      <input type="checkbox" name="items" value="c" checked="1">
c</label></fieldset></form>

来源

填充数据类

 fill_dataclass (src, dest)

就地修改数据类并返回

nt = TodoItem('', 0, False, '')
fill_dataclass(todo, nt)
nt
TodoItem(title='Profit', id=2, done=True, details='Details', opt='b')

来源

查找输入

 find_inputs (e, tags='input', **kw)

递归查找所有在 e 中与 tags 和 attrs 匹配 kw 的元素

inps = find_inputs(form, id='title')
test_eq(len(inps), 1)
inps
[input((),{'value': 'Profit', 'id': 'title', 'class': 'char', 'name': 'title'})]

您还可以使用 lxml 进行更复杂的搜索:

elem = lx.fromstring(to_xml(form))
test_eq(elem.xpath("//input[@id='title']/@value"), ['Profit'])

来源

获取属性

 __getattr__ (tag)

html2ft


来源

html2ft

 html2ft (html, attr1st=False)

将HTML转换为ft表达式

h = to_xml(form)
hl_md(html2ft(h), 'python')
Form(
    Fieldset(
        Input(value='Profit', id='title', name='title', cls='char'),
        Label(
            Input(type='checkbox', name='done', data_foo='bar', checked='1', cls='checkboxer'),
            'Done',
            cls='px-2'
        ),
        Input(type='hidden', id='id', name='id', value='2'),
        Select(
            Option(value='a'),
            Option(value='b', selected='1'),
            name='opt'
        ),
        Textarea('Details', id='details', name='details'),
        Button('Save'),
        name='stuff'
    )
)
hl_md(html2ft(h, attr1st=True), 'python')
Form(
    Fieldset(name='stuff')(
        Input(value='Profit', id='title', name='title', cls='char')(),
        Label(cls='px-2')(
            Input(type='checkbox', name='done', data_foo='bar', checked='1', cls='checkboxer')(),
            'Done'
        ),
        Input(type='hidden', id='id', name='id', value='2')(),
        Select(name='opt')(
            Option(value='a')(),
            Option(value='b', selected='1')()
        ),
        Textarea(id='details', name='details')('Details'),
        Button()('Save')
    )
)

来源

sse_message

 sse_message (elm, event='message')

将元素 elm 转换为适合 SSE 流式传输的格式

print(sse_message(Div(P('hi'), P('there'))))
event: message
data: <div>
data:   <p>hi</p>
data:   <p>there</p>
data: </div>

测试

test_html2ft('<input value="Profit" name="title" id="title" class="char">', attr1st=True)
test_html2ft('<input value="Profit" name="title" id="title" class="char">')
test_html2ft('<div id="foo"></div>')
test_html2ft('<div id="foo">hi</div>')
test_html2ft('<div x-show="open" x-transition:enter="transition duration-300" x-transition:enter-start="opacity-0 scale-90">Hello 👋</div>')
test_html2ft('<div x-transition:enter.scale.80 x-transition:leave.scale.90>hello</div>')
assert html2ft('<div id="foo">hi</div>', attr1st=True) == "Div(id='foo')('hi')"
assert html2ft("""
  <div x-show="open" x-transition:enter="transition duration-300" x-transition:enter-start="opacity-0 scale-90">Hello 👋</div>
""") == "Div('Hello 👋', x_show='open', **{'x-transition:enter': 'transition duration-300', 'x-transition:enter-start': 'opacity-0 scale-90'})"
assert html2ft('<div x-transition:enter.scale.80 x-transition:leave.scale.90>hello</div>') == "Div('hello', **{'x-transition:enter.scale.80': True, 'x-transition:leave.scale.90': True})"
assert html2ft("<img alt=' ' />") == "Img(alt=' ')"