New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix function-url-quotes
false positives for SCSS variable and @
character
#7416
Conversation
🦋 Changeset detectedLatest commit: 57c373d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
it('url with at sign at the start', () => { | ||
expect(isStandardSyntaxUrl('@url/path')).toBeTruthy(); | ||
}); | ||
it('url with ampersand in the middle', () => { | ||
it('url with at sign in the middle', () => { | ||
expect(isStandardSyntaxUrl('some/@url/path')).toBeTruthy(); | ||
}); | ||
it('url with ampersand at the end', () => { | ||
it('url with at sign at the end', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separately fixing typos I noticed!
it('sass variable concat with escaped single quotes string', () => { | ||
expect(isStandardSyntaxUrl("$sass-variable + 'foo'")).toBeFalsy(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a duplicate test case that doesn't actually escape the quotes!
it('sass variable concat with double quotes string', () => { | ||
expect(isStandardSyntaxUrl("$sass-variable + 'foo'")).toBeFalsy(); | ||
expect(isStandardSyntaxUrl('$sass-variable + "foo"')).toBeFalsy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test case didn't do what it said earlier (?)
@mattxwang Thanks for the pull request! First, don't hesitate to make a PR ready for review if you finish implementation. If a PR is still draft, we may ignore it ("Oh, it's not ready"). 😃 Second, I don't think it's necessary to parse SCSS code in To resolve the example below that you mentioned, adding 'https://' + $asset-prefix + 'assets/images/fa_calculator_blue@2x.png' In conclusion, I agree with your current solution adding |
Ah good point, my mistake - I'll make sure not to do that in the future!
Gotcha, I agree with the overall rationale. Unfortunately, this actually (by itself) doesn't resolve the problem, since this will still then (incorrectly) trip this condition first: stylelint/lib/utils/isStandardSyntaxUrl.mjs Lines 26 to 32 in b34a184
So, we'd need to shuffle around the order of checks - though that introduces more of a headache 😓
Maybe I'll leave this PR as-is for now, and address the (with that in mind, have marked this PR as ready to review) |
Ya, sounds good for now 👍🏼 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. LGTM 👍🏼
Closes #7404 (though, see discussion below).
tl;dr: this PR (right now) contains a bandaid fix, but there may be a bigger problem of
isStandardSyntaxUrl
's heuristic regex not doing what it should be. Would love to get some opinions since I don't have all the context for the util!long explanation / context for problem
First, to
brieflyexplain why #7404 is happening:function-url-quotes
usesisStandardSyntaxUrl
to bail out for nonstandard urls withinurl()
:stylelint/lib/utils/isStandardSyntaxUrl.mjs
Lines 41 to 46 in b34a184
The regex
IS_SCSS_VARIABLE_IN_URL
is:stylelint/lib/utils/isStandardSyntaxUrl.mjs
Line 7 in b34a184
Based off of the name and the comment in the condition, it seems like the purpose of this regex is to capture an SCSS variable within
url
. Makes sense! In fact, we have tests for SCSS variables + interpolation (which left me very confused as to why adding an@
sign caused an error):stylelint/lib/utils/__tests__/isStandardSyntaxUrl.test.mjs
Lines 137 to 139 in b34a184
However, I want to point out that the regex is anchored. It only matches if the entire string matches that regex. So, in
$sass-variable + 'foo'
,IS_SCSS_VARIABLE_IN_URL
is matching all of$sass-variable + 'foo'
, instead of just$sass-variable
. So, we're not "really" dealing with concatenation; we're just pretending that there is one SCSS variable called$sass-variable + 'foo'
. Here's a regex101 explaining this.This then explains why #7404 occurred: because
@
is not part of the character set,IS_SCSS_VARIABLE_IN_URL
doesn't match the entire string$asset-prefix + 'assets/images/fa_calculator_blue@2x.png'
, even though it probably "should" match$asset-prefix
. Here is an accompanying regex101.I've introduced some failing tests in 48485ef to showcase this.
solutions?
The minimum solution to fix this problem is to just add
@
to the regex. I did this in 90422c2, which resolves the failing tests in 48485ef. In terms of the above explanation, this now just lets us treat$asset-prefix + 'assets/images/fa_calculator_blue@2x.png'
as "one-giant SCSS variable".However, I'm not super satisfied with this, since (in my eyes) it punts the problem down the line. For example, the similar declaration still has an error (see accompanying regex101):
'https://' + $asset-prefix + 'assets/images/fa_calculator_blue@2x.png'
Unanchoring itself doesn't work, since it will then incorrectly flag strings with
$
within them, like this current test case:So, a "robust"/full solution probably needs to actually parse the value. I'd be happy to spend some time exploring this if we think it's worthwhile, but we could also stick with the current heuristic and add
@
to resolve the immediate issue. I'm also cognizant that I may be missing context (e.g. I didn't write the original util). What are our thoughts?