Repository: vitejs/vite
File: packages/vite/src/node/plugins/css.ts (TypeScript)

Code before:
    wrap = '"'
  }
  // If wrapping in single quotes and newUrl also contains single quotes, switch to double quotes.
  // Give preference to double quotes since SVG inlining converts double quotes to single quotes.
  if (wrap === "'" && newUrl.includes("'")) {
    wrap = '"'
  }
  // Escape double quotes if they exist (they also tend to be rarer than single quotes)
  if (wrap === '"' && newUrl.includes('"')) {
    newUrl = newUrl.replace(nonEscapedDoubleQuoteRe, '\\"')
  }
  return `${funcName}(${wrap}${newUrl}${wrap})`
}

async function doImportCSSReplace(
  rawUrl: string,
  matched: string,
  replacer: CssUrlReplacer,
) {
  let wrap = ''
  const first = rawUrl[0]
  if (first === `"` || first === `'`) {
    wrap = first
    rawUrl = rawUrl.slice(1, -1)
  }
  if (isExternalUrl(rawUrl) || isDataUrl(rawUrl) || rawUrl[0] === '#') {
    return matched
  }

  const prefix = matched.includes('url(') ? 'url(' : ''
  return `@import ${prefix}${wrap}${await replacer(rawUrl)}${wrap}`
}

async function minifyCSS(
  css: string,
  config: ResolvedConfig,
  inlined: boolean,
) {
  // We want inlined CSS to not end with a linebreak, while ensuring that
  // regular CSS assets do end with a linebreak.
  // See https://github.com/vitejs/vite/pull/13893#issuecomment-1678628198

  if (config.build.cssMinify === 'lightningcss') {
    try {
      const { code, warnings } = (await importLightningCSS()).transform({
        ...config.css.lightningcss,
        targets: convertTargets(config.build.cssTarget),
        cssModules: undefined,
        // TODO: Pass actual filename here, which can also be passed to esbuild's
        // `sourcefile` option below to improve error messages
        filename: defaultCssBundleName,

Review comment (suggestion):
This now checks `functionCallRE.test(unquotedUrl)` additionally.
The following code works and the URL replacement should be skipped.
```scss
@function foo() {
  @return 'foo.css';
}

@import url(foo());
```

Code after:
  }

  let newUrl = await replacer(unquotedUrl, rawUrl)
  if (newUrl === false) {
    return matched
  }

  // The new url might need wrapping even if the original did not have it, e.g. if a space was added during replacement
  if (wrap === '' && newUrl !== encodeURI(newUrl)) {
    wrap = '"'
  }
  // If wrapping in single quotes and newUrl also contains single quotes, switch to double quotes.
  // Give preference to double quotes since SVG inlining converts double quotes to single quotes.
  if (wrap === "'" && newUrl.includes("'")) {
    wrap = '"'
  }
  // Escape double quotes if they exist (they also tend to be rarer than single quotes)
  if (wrap === '"' && newUrl.includes('"')) {
    newUrl = newUrl.replace(nonEscapedDoubleQuoteRe, '\\"')
  }
  return `${funcName}(${wrap}${newUrl}${wrap})`
}

async function doImportCSSReplace(
  rawUrl: string,
  matched: string,
  replacer: CssUrlReplacer,
) {
  let wrap = ''
  const first = rawUrl[0]
  let unquotedUrl = rawUrl
  if (first === `"` || first === `'`) {
    wrap = first
    unquotedUrl = rawUrl.slice(1, -1)
  }
  if (skipUrlReplacer(unquotedUrl)) {
    return matched
  }

  const newUrl = await replacer(unquotedUrl, rawUrl)
  if (newUrl === false) {
    return matched
  }

  const prefix = matched.includes('url(') ? 'url(' : ''
  return `@import ${prefix}${wrap}${newUrl}${wrap}`
}

async function minifyCSS(
  css: string,
  config: ResolvedConfig,