Skip to content

Fix function-url-quotes false positives for SCSS variable and @ character #7416

Merged
ybiquitous merged 4 commits intomainfrom
fix-function-url-quotes-fp-scss-and-at
Dec 24, 2023
Merged

Fix function-url-quotes false positives for SCSS variable and @ character #7416
ybiquitous merged 4 commits intomainfrom
fix-function-url-quotes-fp-scss-and-at

Conversation

@mattxwang
Copy link
Copy Markdown
Member

Which issue, if any, is this issue related to?

Closes #7404 (though, see discussion below).

Is there anything in the PR that needs further explanation?

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 briefly explain why #7404 is happening: function-url-quotes uses isStandardSyntaxUrl to bail out for nonstandard urls within url():

// In url without quotes scss variable can be everywhere
// But in this case it is allowed to use only specific characters
// Also forbidden "/" at the end of url
if (url.includes('$') && IS_SCSS_VARIABLE_IN_URL.test(url) && !url.endsWith('/')) {
return false;
}

The regex IS_SCSS_VARIABLE_IN_URL is:

const IS_SCSS_VARIABLE_IN_URL = /^[$\s\w+\-,./*'"]+$/;

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):

it('sass variable concat with single quotes string', () => {
expect(isStandardSyntaxUrl("$sass-variable + 'foo'")).toBeFalsy();
});

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:

http://domain.com:8080/path/to$to/file$2x.ext?$1=$2

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?

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Fix function-url-quotes false positives for SCSS variable and @ character

2 participants