Repository navigation
fix: keep a trailing slash in an unquoted attribute value - #330
Open
OsamaAnsar wants to merge 1 commit into
Open
OsamaAnsar wants to merge 1 commit into
OsamaAnsar wants to merge 1 commit into
Conversation
In '<a href=/foo/>x</a>' the tag regex captured the final '/' as a
self-closing slash, so the value became '/foo' and the element was closed
immediately, moving its content out of it ('<a href=/foo></a>x').
In the HTML tokenizer's unquoted attribute value state '/' is an ordinary
value character and only whitespace or '>' ends the value, so the slash
belongs to the value. Treat it that way for non-void elements.
Void elements keep their lenient behaviour ('<img src=a.png/>' is still a
self-closed tag with src 'a.png'); they never have content, and
test/tests/issues/207.js relies on it.
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.
A
/right before>after an unquoted attribute value is currently taken as a self-closing slash. The slash is dropped from the value and the element is closed immediately, so its content ends up outside it:<a href=/foo/ >x</a>(space before>) already worked.Reading of the spec: in the "attribute value (unquoted) state" (13.2.5.38) only whitespace and
>end the value;/falls under "Anything else" and is appended to the value. So<a href=/foo/>is anawithhref="/foo/"that is not self-closing.Fix: the tag regex captures
(\/?)>as the closing slash. After destructuring, if that slash directly follows an unquoted value (name=valuewith nothing after it) it is moved back ontoattributes. This only runs when a closing slash was captured and is a single anchored regex test.Judgment call you may want to weigh in on: void elements are deliberately left as they were.
<img src=a.png/>is still a self-closedimgwithsrc="a.png", because (a) a void element never has content so nothing is lost structurally, and (b)test/tests/issues/207.js(<foo attr=bar/>withvoidTag.tags: ['foo']) relies on it; applying the spec reading there as well fails that test ('<foo attr=bar/ />'vs the expected'<foo attr=bar />'), and I did not want to change an existing test. If you would rather apply the spec reading to void elements too, it is just dropping the!voidTag.isVoidElement(tagName)condition plus updating that test.Other cases, unchanged by this PR:
<a href="/foo/"/>(quoted),<custom-el disabled/>(no value),<a href=/foo />(space before the slash is still a self-closing start tag).Tests: new
test/tests/unquoted-attribute-slash.jswith 7 tests. With only thesrc/change reverted, 4 of them fail (the 3 others are guards for the unchanged cases above); with the change they pass.How I ran things: bun is not installed here, so I bundled
src/index.tswith esbuild (css-select 5.2.2, entities 8.0.0 as inbun.lock) and ran mocha on Node 22 against that bundle, skippingissues/280.js(needs the published npm packages).main: 303 passing, 4 failing. This branch: 310 passing, same 4 failing. Those 4 are artifacts of my setup (the twoModule Importtests and twounclosed tag repairsubprocess tests needts-node/ a builtdist).tsc --noEmitis clean.Not tested:
bun run build/test:distagainst a realdist, eslint, Node 24/26, benchmarks.