Skip to content

<input> is not valid XHTML regression in Svelte 5 #15801

Closed
@reckart

Description

@reckart

Describe the bug

Describe the bug

Svelte 4 could be used on XHTML documents. With Svelte 5, this seems to be no longer the case.

One issue is that <input> and similar elements are no longer automatically self-closed by Svelte 5.

HTML fragments containing non-closed <input> elements to create_fragment_from_html in reconciler.js:

export function create_fragment_from_html(html) {
	var elem = document.createElement('template');
	elem.innerHTML = html;
	return elem.content;
}

This then fails when trying to assign the HTML fragment to the element.innerHTML with the error message that the fragment is not valid XML. If the underlying document open in the browser is an XHTML document, the browser will require the fragments injected into the document to also be valid XML.

The only workaround I found was post-processing the generated JS file and replacing instances of <input ...> with <input .../>. With this replacement, the code seems to work. However, having to post-process the generated JS file using string operations is a really bad hack.

I understand that Svelte 5 had a major refactoring to make it more compliant with HTML 5. However, it seems this has come at the cost of no longer being compatible with XHTML documents.

Since the strings are generated directly into the JS files, I believe there is not much that can be done about this at runtime.
One option at runtime might be to change create_fragment_from_html to create a temporary HTML5 document, render the fragment into that and then copy the DOM over into the original document. It seems to be quite a bit of overkill though.

Another option would be adding a compiler switch to instruct Svelte to generate valid XHTML fragments (at the expense of being a little less nice to HTML5) - but at least it would be compatible again with XHTML documents.

Yet another option would be adding an option to not generate an error when a user explicitly writes <input ...></input> into their templates and just pass that along as is.

Reproduction

I don't think my report is vague.

Logs

System Info

System:
    OS: macOS 14.7.4
    CPU: (8) arm64 Apple M2
    Memory: 134.42 MB / 24.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.18.0 - ~/.nvm/versions/node/v18.18.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.18.0/bin/yarn
    npm: 9.8.1 - ~/.nvm/versions/node/v18.18.0/bin/npm
  Browsers:
    Chrome: 135.0.7049.96
  npmPackages:
    svelte: ^5.25.12 => 5.27.1

Severity

blocking an upgrade

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions