Generating HTML comments
it-is-wednesday opened this issue · 4 comments
Hello:) Thank you so much for this project – a breath of fresh air after wrangling Django templates!
I wanted to ask whether you'd consider adding support for generating HTML comments (and I would love to implement it if you're in).
My use case stems from these problems/wishes which cannot be solved via plain Python comments:
- During web development, when I see an element is behaving unexpectedly, I like inspecting it and using comments surrounding it in order to quickly locate it in the codebase.
- I like having my HTML+JS code available for inspection by visitors; that's how we used to learn cool stuff about web programming. I don't minify anything for the hopes that someone will found it interesting.
I propose adding to all elements a special keyword, comment
, that will generate its value above the element. For example, this snippet:
div(comment="hello")
Will render this HTML:
<!-- hello -->
<div></div>
Perhaps comment
is a bad choice because it will break backwards compatibility? Maybe we can instead pick something such as _comment
?
Would love to hear your thoughts, and thanks again for this incredible piece of software:)
I agree, it would be nice to be able to put in HTML comments!
I think that a comment attribute on a custom element would not be too far fetched, someone might want to use something like <my-note comment="Hi"></my-note>
. I also think it is not clear that it would be a child before the current element.
What about a special "comment" helper from htpy import comment
? Can probably be implemented like this:
>>> from markupsafe import Markup, escape
>>> def comment(text: str) -> Markup:
... return Markup(f'<!-- {escape(text)} -->')
...
>>> from htpy import div
>>> print(div[
... comment("hello"),
... div["element contents"],
... ])
<div><!-- hello --><div>element contents</div></div>
>>>
I you think this is a good approach, feel free to open a PR, ideally with docs and tests. :)
I agree that comments should be managed like elements, especially if at some point we want to be able to handle conditional comments such as
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.js" integrity="sha512-BWbLJlfp8hzXlxT6K5KLdxPVAj+4Zn2e4FVq5P7NSFH/mkAJ18UiZRQUD4anR3jyp0/WYkeZ0Zmq5EWWrDxneQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<![endif]-->
The comment itself should be the content of the comment
tag, not an attribute (can be any valid Node
, not just a str
, even for regular comments).
comment(condition:str|None=None)[...]
That conditional "if .. IE" is special for IE and not something that is currently widely used, I think we should just aim for a simple <!-- X -->
helper.
Markup() is always available as an escape hatch to craft any comment or text as needed. With Markup(), it is easy enough for anyone to implement a custom function (we could maybe document this as an example):
from markupsafe import Markup
import htpy as h
def ie_conditional(condition: str, *children: h.Node) -> h.Node:
return [Markup(f"<!--[if {condition}]>"), children, Markup("<![endif]-->")]
print(h.render_node(ie_conditional("IE lt 9", h.p["Hello, IE!"])))
--> <!--[if IE lt 9]><p>Hello, IE!</p><![endif]-->
We should also consider how to escape the text properly. It needs to be safe to avoid breaking out of the comment. Someone may use comment(f"current user: {user.username}")
. where user.username could contain user supplied data like --><script>evil()</script><!--
.
After a looking into it a bit more, using escape() (as I suggested above) would not be useful. Maybe we can implement a check for https://developer.mozilla.org/en-US/docs/Web/HTML/Comments:
This text cannot start with the string > or ->, cannot contain the strings --> or --!>, nor end with the string <!-, though <! is allowed.". If it is not valid, we can just avoid rendering it altogether.
Or we could just always remove --
and add spaces.
This is part of the 24.8.1 release!