Skip to content

fix: apply the quote mark given to the attribute constructor - #361

Open
theRizwan wants to merge 1 commit into
postcss:mainfrom
theRizwan:fix/attribute-constructor-quote-mark
Open

theRizwan wants to merge 1 commit into
postcss:mainfrom
theRizwan:fix/attribute-constructor-quote-mark

Conversation

@theRizwan

Copy link
Copy Markdown
Contributor

The bug

Passing quoteMark to parser.attribute() has no effect on the output:

const attr = parser.attribute({ attribute: "href", operator: "=", value: "foo bar", quoteMark: '"' });
attr.quoteMark;    // '"'
attr.toString();   // '[href=foo bar]'

The constructor's deprecation message makes this the supported form ("The value should be unescaped now"). But the value is printed as given, neither quoted nor escaped, so [href=foo bar] does not parse back to the same value. quoteMark: null behaves the same way: foo bar is printed with its space unescaped. Even value: "foo" with quoteMark: '"' comes out unquoted, as [href=foo].

Doing the same after construction works, because the quoteMark setter and setValue() both call _syncRawValue(). The constructor sets _constructed only after the options are assigned, so that call never happens.

The fix

At the end of the constructor, if there is a string value and no raws.value, call _syncRawValue(). The deprecated form without quoteMark always sets raws.value itself, so it is unaffected.

The parser creates attributes through the same constructor and leaves raws.value unset when the spelling needs nothing kept. It now removes the raw value the constructor adds in that case, so parsed attributes keep their original spelling. This matters for non-standard values such as [x=@{v}], which would otherwise be escaped.

Verification

Six tests in attributes.mjs cover double and single quotes, a value containing its own quote mark, and null with and without a space. Each checks the output and that it parses back to the same value and quote mark. Five of them fail on main. The sixth, null with a plain identifier, passes either way. Two more tests check that an explicit raws.value wins, and that parsed attributes, including Less, print and clone unchanged.

npm test is green: lint, type check, and coverage gates.

`parser.attribute({ attribute: "href", operator: "=", value: "foo bar",
quoteMark: '"' })` printed as `[href=foo bar]`: the value was neither
quoted nor escaped, though `attr.quoteMark` reported `"`. Passing a quote
mark is the non-deprecated way to construct an attribute with a value, and
the value is unescaped in that form, so the result did not parse back to
the same value. Setting `quoteMark` or calling `setValue()` afterwards
already quoted it.

The constructor now quotes and escapes the value for its quote mark,
unless `raws.value` is given. The parser drops the raw value this adds
when it had none, so parsed attributes keep their original spelling.
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.

1 participant