Skip to content

Add option to allow self-closing void tags#100

Closed
The0x539 wants to merge 3 commits into
kristoff-it:mainfrom
The0x539:main
Closed

Add option to allow self-closing void tags#100
The0x539 wants to merge 3 commits into
kristoff-it:mainfrom
The0x539:main

Conversation

@The0x539

@The0x539 The0x539 commented Sep 16, 2025

Copy link
Copy Markdown

à la Pretter.

For lsp and fmt, there are three modes:

  • never: Treat <br /> as invalid, and convert to a void tag when doing an LSP format. (Default. Should match status quo.)
  • preserve: Accept <br />, but do not automatically add or remove the slashes.
  • always: Automatically convert all void elements into self-closing tags.

To do:

  • Help text (I wasn't sure how to format it.)
  • Expose the option through something other than command-line args. My changes are fine for me in Helix, but there's no way to specify it in VS Code.
  • Five modes instead of three? (forbid, remove, preserve, insert, require)

(This is my first time writing any Zig. I've probably done something quite dubious.)

@The0x539
The0x539 marked this pull request as draft September 16, 2025 20:57
@kristoff-it

kristoff-it commented Sep 16, 2025

Copy link
Copy Markdown
Owner

Sorry for abruptly closing a PR that contains work you've done, but I don't intend to support breaking away from the HTML spec for no real reason.

Prettier is doing the world a disservice by helping perpetuate the wrong fact that self closing tags are a thing in HTML. I do understand that functionality-wise self-closing tags on void elements are not harmful in any way, but they are harmful in the fact that they create confusion about what's what in HTML.

Additionally, editors like VSCode have simplistic formatters that seem to suggest that self-closing tags have semantic meaning, causing even more confusion and mistakes:

In VSCode (and any editor that uses vscode's extracted LSPs) this:

<body>
<div />
   <div>
</body>

Is formatted like this (divs seem siblings):

<body>
   <div />
   <div>
</body>

While in reality the second div is nested into the first div (because html elements can't self-close).

One of the goals of SuperHTML is to teach its users about HTML and, while the HTML spec can be put into question, there has to be a practical reason for breaking away from it.

I will open an Issue for adding automatic removal of self-closing tags by fmt on void elements.

@The0x539

Copy link
Copy Markdown
Author

I will note that these changes only affect behavior for void elements. Constructs like <div /> are still unconditionally rejected.

@kristoff-it

Copy link
Copy Markdown
Owner

I've added the behavior I mentioned above in 2bf8f4d in case you're interested. Note that contributions are welcome but I'm generally against adding configuration options. I would recommend opening an issue for discussion before jumping into coding in the future.

@Zorgatone

Copy link
Copy Markdown

@kristoff-it, technically, I think if I'm not mistaken, HTML allows void elements to have the self-closing tag (which would only be forbidden for non-void elements).
The LSP at the moment always report the self-closing tag as an error, regardless if it's self-closing or not. Isn't that wrong?

@kristoff-it

Copy link
Copy Markdown
Owner

If you want to entertain a discussion about what HTML allows or not, you must start from quoting a passage of the WHATWG Living HTML spec that corroborates your understanding.

Additionally, you need to differentiate between things that the HTML spec considers allowed and things that the spec offers fallback behavior for. For example some passages about parsing attribute value sublanguages offer procedures for ignoring certain kinds of syntax errors, which does not mean that those are part of the spec.

My understanding is that self-closing elements are not a concept that exists in HTML and, as a fallback, self-closing slashes are ignored by the parser.

Additionally, I'm actively against allowing self-closing slashes because, as stated above, it causes confusion, resulting in unexpected resulting nesting, which is something that a tool like SuperHTML should provide guaranteed protection against.

@Zorgatone

Zorgatone commented Oct 11, 2025

Copy link
Copy Markdown

If you want to entertain a discussion about what HTML allows or not, you must start from quoting a passage of the WHATWG Living HTML spec that corroborates your understanding.

Additionally, you need to differentiate between things that the HTML spec considers allowed and things that the spec offers fallback behavior for. For example some passages about parsing attribute value sublanguages offer procedures for ignoring certain kinds of syntax errors, which does not mean that those are part of the spec.

My understanding is that self-closing elements are not a concept that exists in HTML and, as a fallback, self-closing slashes are ignored by the parser.

Additionally, I'm actively against allowing self-closing slashes because, as stated above, it causes confusion, resulting in unexpected resulting nesting, which is something that a tool like SuperHTML should provide guaranteed protection against.

@kristoff-it

https://html.spec.whatwg.org/multipage/syntax.html#start-tags

13.1.2.1 Start tags

Start tags must have the following format:

  1. The first character of a start tag must be a U+003C LESS-THAN SIGN character (<).
  2. The next few characters of a start tag must be the element's tag name.
  3. If there are to be any attributes in the next step, there must first be one or more ASCII whitespace.
  4. Then, the start tag may have a number of attributes, the syntax for which is described below. Attributes must be separated from each other by one or more ASCII whitespace.
  5. After the attributes, or after the tag name if there are no attributes, there may be one or more ASCII whitespace. (Some attributes are required to be followed by a space. See the attributes section below.)
  6. Then, if the element is one of the void elements, or if the element is a foreign element, then there may be a single U+002F SOLIDUS character (/), which on foreign elements marks the start tag as self-closing. On void elements, it does not mark the start tag as self-closing but instead is unnecessary and has no effect of any kind. For such void elements, it should be used only with caution — especially since, if directly preceded by an unquoted attribute value, it becomes part of the attribute value rather than being discarded by the parser.
  7. Finally, start tags must be closed by a U+003E GREATER-THAN SIGN character (>).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants