From bd0cecc9b1871e210f4f3b338f6e90da44c52d18 Mon Sep 17 00:00:00 2001 From: GoalSmashers Date: Sat, 11 Jan 2014 16:56:34 +0100 Subject: [PATCH] Fixes #207 - bug in parsing protocol `@import`s. Spaces inside url part of import declaration were incorrectly parsed. --- History.md | 1 + lib/imports/inliner.js | 29 +++++++++++++++++++---------- test/protocol-imports-test.js | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/History.md b/History.md index 396c05ae..b1539f94 100644 --- a/History.md +++ b/History.md @@ -11,6 +11,7 @@ * Fixed issue [#163](https://github.com/GoalSmashers/clean-css/issues/163) - round pixels to 2nd decimal place. * Fixed issue [#165](https://github.com/GoalSmashers/clean-css/issues/165) - extra space after trailing parenthesis. * Fixed issue [#186](https://github.com/GoalSmashers/clean-css/issues/186) - strip unit from 0rem. +* Fixed issue [#207](https://github.com/GoalSmashers/clean-css/issues/207) - bug in parsing protocol `@import`s. [2.0.6 / 2014-01-04](https://github.com/GoalSmashers/clean-css/compare/v2.0.5...v2.0.6) ================== diff --git a/lib/imports/inliner.js b/lib/imports/inliner.js index 6384bfba..29d309c5 100644 --- a/lib/imports/inliner.js +++ b/lib/imports/inliner.js @@ -126,17 +126,26 @@ module.exports = function Inliner(context, options) { }; var inline = function(data, nextStart, nextEnd, options) { - var strippedImport = data + var importDeclaration = data .substring(data.indexOf(' ', nextStart) + 1, nextEnd) - .replace(/^url\(/, '') - .replace(/['"]/g, ''); - - var separatorIndex = strippedImport.indexOf(' '); - var importedFile = strippedImport - .substring(0, separatorIndex > 0 ? separatorIndex : strippedImport.length) - .replace(')', ''); - var mediaQuery = strippedImport - .substring(importedFile.length + 1) + .trim(); + + var viaUrl = importDeclaration.indexOf('url(') === 0; + var urlStartsAt = viaUrl ? 4 : 0; + var isQuoted = /^['"]/.exec(importDeclaration.substring(urlStartsAt, urlStartsAt + 2)); + var urlEndsAt = isQuoted ? + importDeclaration.indexOf(isQuoted[0], urlStartsAt + 1) : + importDeclaration.split(' ')[0].length; + + var importedFile = importDeclaration + .substring(urlStartsAt, urlEndsAt) + .replace(/['"]/g, '') + .replace(/\)$/, '') + .trim(); + + var mediaQuery = importDeclaration + .substring(urlEndsAt + 1) + .replace(/^\)/, '') .trim(); var isRemote = options.isRemote || diff --git a/test/protocol-imports-test.js b/test/protocol-imports-test.js index f0d1a3bc..b440a939 100644 --- a/test/protocol-imports-test.js +++ b/test/protocol-imports-test.js @@ -50,6 +50,25 @@ vows.describe('protocol imports').addBatch({ nock.restore(); } }, + 'of an existing file with spaces in path': { + topic: function() { + this.reqMocks = nock('http://fonts.googleapis.com') + .get('/css?family=Oleo%20Script%20Swash%20Caps') + .reply(200, 'p{font-size:13px}'); + + new CleanCSS().minify('@import url(\'//fonts.googleapis.com/css?family=Oleo Script Swash Caps\');', this.callback); + }, + 'should not raise errors': function(errors, minified) { + assert.isNull(errors); + }, + 'should process @import': function(errors, minified) { + assert.equal(minified, 'p{font-size:13px}'); + }, + teardown: function() { + assert.equal(this.reqMocks.isDone(), true); + nock.restore(); + } + }, 'of an existing file via HTTPS': { topic: function() { this.reqMocks = nock('https://goalsmashers.com') -- 2.34.1