-
-
Notifications
You must be signed in to change notification settings - Fork 606
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: proper URL escaping and wrapping (url()
)
#627
Changes from all commits
d14e8b8
2db8469
74431ba
fdac0b0
1ac7661
87caf33
d34841f
f144280
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module.exports = function escape(url) { | ||
// If url is already wrapped in quotes, remove them | ||
if (/^['"].*['"]$/.test(url)) { | ||
url = url.slice(1, -1); | ||
} | ||
// Should url be wrapped? | ||
// See https://drafts.csswg.org/css-values-3/#urls | ||
if (/["'() \t\n]/.test(url)) { | ||
return '"' + url.replace(/"/g, '\\"').replace(/\n/g, '\\n') + '"' | ||
} | ||
|
||
return url | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
background: url({./module}); | ||
background: url({./module}); | ||
background: url("{./module module}"); | ||
background: url('{./module module}'); | ||
background: url("{./module module}"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, but "break something" here means "result in a slightly longer string since double-quotes are escaped". The whole point of this change is to make it impossible for other loaders to break your CSS. My arguments for using only double-quotes summed up:
Of course it is not my package, and I'm not that experienced with writing loaders, so I defer entirely to your judgements. If I have failed to convince you, I'll change it so there is a separate escape-function for single-quotes. If that is the case, should I also make an unquoted escape-function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm no debating That has nothing to do with not merging it, just saying it's going to happen & we now we have context as to why. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to keep in mind that Anything that lands in this repo has to be vetted, pondered, picked apart & poked so we at the very least can have a reason why there are 4 new issues with version Changes in behaviors get that & the rubber glove treatment, it's just too easy to not account for a path in this vast ecosystem where Change X has an unintended side effect on Y & people show up with torches & pitch forks. |
||
background: url({./module}); | ||
background: url({./module}#?iefix); | ||
background: url("#hash"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ describe("url", function() { | |
[1, ".class { background: green url(\"{./img img.png}\") xyz }", ""] | ||
]); | ||
test("background 2 img contain space in name", ".class { background: green url( 'img img.png' ) xyz }", [ | ||
[1, ".class { background: green url('{./img img.png}') xyz }", ""] | ||
[1, ".class { background: green url(\"{./img img.png}\") xyz }", ""] | ||
]); | ||
test("background img absolute", ".class { background: green url(/img.png) xyz }", [ | ||
[1, ".class { background: green url(/img.png) xyz }", ""] | ||
|
@@ -103,6 +103,28 @@ describe("url", function() { | |
test("external schema-less url", ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", [ | ||
[1, ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", ""] | ||
]); | ||
|
||
test("module wrapped in spaces", ".class { background: green url(module) xyz }", [ | ||
[1, ".class { background: green url(module-wrapped) xyz }", ""] | ||
], "", { './module': "\"module-wrapped\"" }); | ||
test("module with space", ".class { background: green url(module) xyz }", [ | ||
[1, ".class { background: green url(\"module with space\") xyz }", ""] | ||
], "", { './module': "module with space" }); | ||
test("module with quote", ".class { background: green url(module) xyz }", [ | ||
[1, ".class { background: green url(\"module\\\"with\\\"quote\") xyz }", ""] | ||
], "", { './module': "module\"with\"quote" }); | ||
test("module with quote wrapped", ".class { background: green url(module) xyz }", [ | ||
[1, ".class { background: green url(\"module\\\"with\\\"quote\\\"wrapped\") xyz }", ""] | ||
], "", { './module': "\"module\"with\"quote\"wrapped\"" }); | ||
test("module with parens", ".class { background: green url(module) xyz }", [ | ||
[1, ".class { background: green url(\"module(with-parens)\") xyz }", ""] | ||
], "", { './module': 'module(with-parens)' }); | ||
test("module with newline", ".class { background: green url(module) xyz }", [ | ||
[1, ".class { background: green url(\"module\\nwith\\nnewline\") xyz }", ""] | ||
], "", { './module': "module\nwith\nnewline" }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to test There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test added of one of the url-loader outputs from this article. It's a very small file, but as far as I know all base64-encoded data-URIs are valid in CSS when unquoted. If you have an example in mind of something that might fail I'll add that too though. |
||
test("module from url-loader", ".class { background: green url(module) xyz }", [ | ||
[1, ".class { background: green url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA) xyz }", ""] | ||
], "", { './module': "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA" }); | ||
|
||
test("background img with url", ".class { background: green url( \"img.png\" ) xyz }", [ | ||
[1, ".class { background: green url( \"img.png\" ) xyz }", ""] | ||
|
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.
Why we change
'
to"
? Can we save original quotes?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.
In principle it could be done. It will complicate things quite a bit, though, since the whole point of the update is to quote based on module-content instead of name. The type of quotes would have to be passed to the client (something like
escapeSingle(require(<resource>))
).I skipped it, since I can't really imagine a scenario where it would be important to use single quotes.
svg-url-loader
already assumes double-quotes, since this is what is commonly used in HTML, I assume other loaders will make similar choices. If not, the worst case scenario is a slightly longer string.If this is implemented, there should maybe also be an
escapeUnquoted
function for handling unquoted modules. That way the quotes used will be entirely up to the user, the loader will just ensure valid CSS is produced.