Repository navigation
fix: lowercase HTML attribute names like browsers do - #364
Open
privatenumber wants to merge 1 commit into
Open
privatenumber wants to merge 1 commit into
privatenumber wants to merge 1 commit into
Conversation
privatenumber
marked this pull request as ready for review
November 4, 2026 16:05
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Browsers treat HTML attribute names as case-insensitive, but linkedom keeps them as written. Code that works in a browser silently finds nothing here:
In browsers, the HTML tokenizer lowercases attribute names, and DOM methods such as
getAttributeandcreateAttributelowercase their argument for HTML elements in HTML documents. Even[data-itemId]fails in linkedom today, because css-select lowercases the selector's name while the stored name keeps its capital letter. This came up in #235.Changes
Attribute names on HTML elements in HTML documents are now stored in lowercase, so lookups, selectors, and serialization match browsers.
setAttribute, andcreateAttributestore lowercase names. Lookups (getAttribute,hasAttribute,removeAttribute,toggleAttribute,getAttributeNode) try the name as given first and lowercase it only after a miss, so no comparison is case-insensitive. Lookups that find the attribute do no extra work; a miss scans the name once for capital letters.lowerCaseAttributeNamesstays off. SVG elements, includingsvg.innerHTML, keepviewBoxandtextLength, andtext/xml/image/svg+xmldocuments keep all casing.Attrattached from another document withsetAttributeNodekeeps its mixed-case name and is still found by that exact name. MathML attributes are lowercased too, because linkedom creates MathML elements as HTML elements.Measured with interleaved CPU-time A/B runs against
main(2M calls per round, median of 9 rounds):maingetAttribute, attribute foundgetAttribute, attribute missinggetAttribute('class')hasAttribute, attribute foundCode that depends on preserved casing changes:
setAttribute('someProp', v)now storessomeprop, andgetAttributeNames()returns lowercase names for HTML elements. A minor release seems appropriate. uhtml-ssr lowercases its own.propand?boolbindings and doesn't depend on linkedom, so it isn't affected.