From 2028fad5a88a80e9921d9981c6247951b8c43d62 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Wed, 5 Aug 2015 07:45:51 +0100 Subject: [PATCH] Fixes #633 - handling data URI with brackets. We need to identify cases when data URI are escaped (and brackets are not) so we can get the whole URI. --- History.md | 1 + lib/urls/reduce.js | 20 +++++++++++++++++--- test/integration-test.js | 8 ++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 99fd231a..bfaac34e 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,7 @@ ================== * Fixed issue [#630](https://github.com/jakubpawlowicz/clean-css/issues/630) - vendor prefixed flex optimizations. +* Fixed issue [#633](https://github.com/jakubpawlowicz/clean-css/issues/633) - handling data URI with brackets. [3.3.7 / 2015-07-29](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.6...v3.3.7) ================== diff --git a/lib/urls/reduce.js b/lib/urls/reduce.js index 4a5fa54b..1f7d7fd5 100644 --- a/lib/urls/reduce.js +++ b/lib/urls/reduce.js @@ -9,6 +9,7 @@ function byUrl(data, context, callback) { var nextStart = 0; var nextStartUpperCase = 0; var nextEnd = 0; + var nextEndAhead = 0; var cursor = 0; var tempData = []; var hasUppercaseUrl = data.indexOf(UPPERCASE_URL_PREFIX) > -1; @@ -22,13 +23,26 @@ function byUrl(data, context, callback) { if (nextStart == -1 && nextStartUpperCase > -1) nextStart = nextStartUpperCase; - if (data[nextStart + URL_PREFIX.length] == '"') + if (data[nextStart + URL_PREFIX.length] == '"') { nextEnd = data.indexOf('"', nextStart + URL_PREFIX.length + 1); - else if (data[nextStart + URL_PREFIX.length] == '\'') + } else if (data[nextStart + URL_PREFIX.length] == '\'') { nextEnd = data.indexOf('\'', nextStart + URL_PREFIX.length + 1); - else + } else { nextEnd = data.indexOf(URL_SUFFIX, nextStart); + while (true) { + nextEndAhead = data.indexOf(URL_SUFFIX, nextEnd + 1); + // if it has whitespace then we should be out of URL, otherwise keep iterating + // if it has not but content is not escaped, it has to be quoted so it will be captured + // by either of two clauses above + if (nextEndAhead == -1 || /\s/.test(data.substring(nextEnd, nextEndAhead))) + break; + + nextEnd = nextEndAhead; + } + } + + // Following lines are a safety mechanism to ensure // incorrectly terminated urls are processed correctly. if (nextEnd == -1) { diff --git a/test/integration-test.js b/test/integration-test.js index 997ffc9d..59a3b27f 100644 --- a/test/integration-test.js +++ b/test/integration-test.js @@ -1346,6 +1346,14 @@ vows.describe('integration tests') 'keep quoting if whitespace inside @font-face': [ '@font-face{src:url("/Helvetica Neue.eot")}', '@font-face{src:url(\'/Helvetica Neue.eot\')}' + ], + 'keep SVG data URI unchanged for background-uri': [ + 'div{background-image:url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2018%2018%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20width%3D%2214%22%20height%3D%2214%22%20transform%3D%22translate(2%202)%22%2F%3E%3C%2Fsvg%3E)}', + 'div{background-image:url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2018%2018%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20width%3D%2214%22%20height%3D%2214%22%20transform%3D%22translate(2%202)%22%2F%3E%3C%2Fsvg%3E)}' + ], + 'keep SVG data URI unchanged1 for background': [ + 'div{background:url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2018%2018%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20width%3D%2214%22%20height%3D%2214%22%20transform%3D%22translate(2%202)%22%2F%3E%3C%2Fsvg%3E) bottom left}', + 'div{background:url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2018%2018%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20width%3D%2214%22%20height%3D%2214%22%20transform%3D%22translate(2%202)%22%2F%3E%3C%2Fsvg%3E) bottom left}' ] }, { root: process.cwd(), relativeTo: process.cwd() }) ) -- 2.34.1