Auto-escaping on function and block handlers is underdefined
function and block handlers should at least somehow indicate what they are returning, i.e. plain text, html, js, etc. That way, we would be able to apply auto-escaping when needed and refrain from it when not needed.
see #906
This also needs to be documented
Have you considered adding something like SafeString (shamelessly borrowed from Django, https://docs.djangoproject.com/en/4.2/_modules/django/utils/safestring/ ), a small wrapper class around a string to indicate that the user has taken responsibility for escaping, and that the contained string is safe for output?
That would allow a function to indicate that it has taken care of escaping by returning SafeString, or that its output should be escaped (by returning string).
As an added bonus, the same mechanism would also allow for users to supply escaped HTML in normal template variables. So, {$foo} would render <html> when one has done $smarty->assign('foo', new Smarty\SafeString('<html>')). If one instead did $smarty->assign('foo', '<html>'), it would render <html> (as it currently does).
As a secondary bonus, {capture} in templates could use SafeString (as what is captured will have been escaped), which would get rid of needing to use nofilter when one prints captured content.
Very interesting idea, @gkreitz !