Skip to content

fix(css): should not wrap with double quote when the url rebase feature bailed out #20068

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

Conversation

sapphi-red
Copy link
Member

Description

rebaseUrl was replacing url($var-c1 + $var-c2) with url("$var-c1 + $var-c2").

fixes #19196

@sapphi-red sapphi-red added feat: css p3-minor-bug An edge case that only affects very specific usage (priority) labels May 20, 2025
Comment on lines 2061 to 2063
if (rawUrl === newUrl) {
return matched
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could add a comment here that says that the replacer will bail out when checking the first variable in the case of a concat and this is why it works? I think it would be better to check this in skipUrlReplacer but I understand it is a big refactoring to pass the variablePrefix to it. So good to go for me if we add the comment to avoid confusion later on.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be better. Added a comment for now 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I see the comment, what happens when rawUrl has a space and rawUrl === newUrl? Don't we still need to re-wrap it in that case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the rawUrl contains a space and rawUrl is not quoted, the input is not valid. The value in url() should be quoted to contain a space. So this code will keep the invalid code as-is when rawUrl === newUrl.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rawUrl can originally have a space and be quoted, and we are removing the quotes here in that case https://github.com/vitejs/vite/pull/20068/files#diff-2cfbd4f4d8c32727cd8e1a561cffbde0b384a3ce0789340440e144f9d64c10f6R2053

Or am I reading this wrong? I think it is probably good to have a local unquotedUrl instead of overriding rawUrl, as this is indeed confusing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I overlooked that 🤦

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me come up with a more proper way to fix this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the impl to allow returning false from CssUrlReplacer. The previous impl didn't handle interpolation properly and that is not possible to have it inside skipUrlReplacer because the behavior is different for each preprocessors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see now that the comment confused me as it was

// If the replacer output is same with the input, we don't need to wrap it with quotes.

but the code was returning matched, so it was working before but the new code is way better and you fixed other issues so this was good in the end :)

@sapphi-red sapphi-red marked this pull request as draft May 23, 2025 02:37
@sapphi-red sapphi-red marked this pull request as ready for review May 23, 2025 07:40
Comment on lines +2100 to -2090
if (skipUrlReplacer(unquotedUrl)) {
return matched
}
if (isExternalUrl(rawUrl) || isDataUrl(rawUrl) || rawUrl[0] === '#') {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now checks functionCallRE.test(unquotedUrl) additionally.
The following code works and the URL replacement should be skipped.

@function foo() {
  @return 'foo.css';
}

@import url(foo());

Comment on lines +2557 to +2565
const skipRebaseUrls = (unquotedUrl: string, rawUrl: string) => {
const isQuoted = rawUrl[0] === '"' || rawUrl[0] === "'"
// matches `url($foo)`
if (!isQuoted && unquotedUrl[0] === '$') {
return true
}
// matches `url(#{foo})` and `url('#{foo}')`
return unquotedUrl.startsWith('#{')
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@patak-dev patak-dev merged commit a33d0c7 into vitejs:main May 23, 2025
15 checks passed
@sapphi-red sapphi-red deleted the fix/css-sass-rebase-url-starting-should-not-wrap branch May 24, 2025 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: css p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

rebaseUrls runs before Sass variables are resolved
2 participants