fix: handle multiple url()#237
Conversation
📊 Bundle size report🤖 This report was generated against 28641c5bc7616ffe3ec327b0de67625bbd9c727c |
2d0b301 to
7fa5811
Compare
| @@ -0,0 +1,3 @@ | |||
| export function isAssetUrl(value: string): boolean { | |||
There was a problem hiding this comment.
I intentionally didn't cover this by tests directly as it will be changed/removed in #234.
| // Quotes in URL are optional, so we can also normalize them | ||
| // https://www.w3.org/TR/CSS2/syndata.html#value-def-uri | ||
| const url = result.url.replace(/['|"](.+)['|"]/, '$1'); | ||
| return tokenize(ruleValue).reduce((result, token, index, array) => { |
There was a problem hiding this comment.
Instead of a regex I am using tokenize() from stylis so we can parse all url() entries properly.
| const quasis: t.TemplateElement[] = []; | ||
| const expressions: t.Identifier[] = []; | ||
|
|
||
| let acc = ''; | ||
|
|
||
| for (let i = 0, l = tokens.length; i < l; i++) { | ||
| for (; i < l; i++) { | ||
| acc += tokens[i]; | ||
|
|
||
| if (tokens[i] === 'url') { | ||
| const url = tokens[i + 1].slice(1, -1); | ||
|
|
||
| if (isAssetUrl(url)) { | ||
| quasis.push(t.templateElement({ raw: acc + '(' }, false)); | ||
| expressions.push(getAssetIdentifier(url)); | ||
|
|
||
| acc = ')'; | ||
| i++; | ||
|
|
||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| quasis.push(t.templateElement({ raw: acc }, true)); |
There was a problem hiding this comment.
It's not the loop that makes me proud, but it works ¯_(ツ)_/¯ (opened for suggestions).
Based on tokens ('.foo', '{', 'url', '(image.png)', '}') we need to create:
- N
TemplateElements (t.templateElement({ raw: '.foo{url(' }, false),t.templateElement({ raw: ')}' }, true)) - N-1 expressions (
t.identifier('image.png'))
N & N-1 are a requirement as it's how Babel manages template literals...
There was a problem hiding this comment.
I can't think of much better....
but I don't quite understand why you need the second nested loop, once you find the url token you break out of the inner loop and the outer one continues where the inner one left off anyway ??
There was a problem hiding this comment.
but I don't quite understand why you need the second nested loop, once you find the
urltoken you break out of the inner loop and the outer one continues where the inner one left off anyway ??
Good catch, it's a leftover from the previous attempt. Removed.
| { | ||
| title: 'assets import handling', | ||
| fixture: path.resolve(fixturesDir, 'assets', 'code.ts'), | ||
| outputFixture: path.resolve(fixturesDir, 'assets', 'output.ts'), | ||
| }, |
There was a problem hiding this comment.
Moved into a separate group.
| const expressionPaths = literalPath.get('expressions'); | ||
|
|
||
| expressionPaths.map(expressionPath => { |
There was a problem hiding this comment.
The inner part is 100% percent the same: now we parse all expressions instead of only first.
| function buildTemplateLiteralFromValue(value: string): t.TemplateLiteral { | ||
| const tokens = tokenize(value); | ||
|
|
||
| const quasis: t.TemplateElement[] = []; |
There was a problem hiding this comment.
It's how Babel names string in template literals i.e. foo from foo${bar}:
| acc += tokens[i]; | ||
|
|
||
| if (tokens[i] === 'url') { | ||
| const url = tokens[i + 1].slice(1, -1); |
There was a problem hiding this comment.
why ignore the first and last characters of a url ?
There was a problem hiding this comment.
I'm going by your example of tokens: ('.foo', '{', 'url', 'image.png', '}')
There was a problem hiding this comment.
The first and last characters are parens. url(image.png) tokenizes to ["url", "(image.png)"]
7fa5811 to
a3f91c9
Compare
ling1726
left a comment
There was a problem hiding this comment.
I have doubts about the ugly nested loop in the preset, but otherwise LGTM
Bump svgo 3.2.0 → 3.3.3 (fixes Dependabot microsoft#237, Billion Laughs DoS) and serve-handler 6.1.6 → 6.1.7 which brings minimatch 3.1.2 → 3.1.5 (fixes Dependabot microsoft#230, ReDoS via GLOBSTAR). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: bump svgo and serve-handler to fix security advisories Bump svgo 3.2.0 → 3.3.3 (fixes Dependabot #237, Billion Laughs DoS) and serve-handler 6.1.6 → 6.1.7 which brings minimatch 3.1.2 → 3.1.5 (fixes Dependabot #230, ReDoS via GLOBSTAR). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: dedupe sax Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Fixes #238. See the bug for the issue description in detail.
The main change is that we use
tokenizefromstylisinstead of regexps. This is more robust and allows to parse multipleurl()expressions.@griffel/babel-presetand@griffel/webpack-extraction-pluginwere updated/adjusted to handle this scenario.