`html_params` does not work correctly for `Markup` values
Daverball opened this issue · 1 comments
While this is a bit of a corner case and could be considered bad form it can sometimes be the most simple solution when you want the rendering of dynamic elements to happen in the backend without having to involve AJAX. You can pass Markup into a HTML attribute just fine, since markupsafe.escape
will just pass through Markup
unchanged. However this will cause issues if the HTML contains any double quotes.
It's also worth noting that the same thing applies to any object that implements __html__
.
Actual Behavior
>>> from markupsafe import Markup
>>> from wtforms.widgets import html_params
>>> html_params(data_render=Markup('<a href="#"></a>'))
'data-render="<a href="#"></a>"'
Expected Behavior
>>> from markupsafe import Markup
>>> from wtforms.widgets import html_params
>>> html_params(data_render=Markup('<a href="#"></a>'))
'data-render="<a href="#"></a>"'
Environment
- Python version: 3.10
- wtforms version: 3.0.1
Suggested fix
Rather than doing the following in html_params
params.append(f'{str(k)}="{escape(v)}"')
You would do the following
v = escape(v).replace(Markup('"'), Markup('"'))
params.append(f'{str(k)}="{v}"')
It might also be a nice QoL improvement to wrap the return value in Markup
, that way it would be possible to pass it into a Markup.format
without having to wrap it manually.
So you could do this
Markup('<a {params}>{title}</a>').format(params=html_params(**params), title=title)
Instead of this (which could be marked as unsafe by a security linter)
Markup(f'<a {html_params(**params)}>{{title}}</a>').format(title=title)
Or this (which is more verbose)
Markup('<a {params}>{title}</a>').format(params=Markup(html_params(**params)), title=title)