From 0a6d33e5e7f7a0361519874266d9f135a55fc057 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Sat, 30 Aug 2014 23:53:56 +0100 Subject: [PATCH] Fixes #350 - edge cases in `@import` processing. --- History.md | 1 + lib/imports/inliner.js | 19 ++++++++++++++--- test/unit-test.js | 46 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index dd9154c2..74b2fb5b 100644 --- a/History.md +++ b/History.md @@ -6,6 +6,7 @@ [2.2.15 / 2014-xx-xx](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.14...v2.2.15) ================== +* Fixed issue [#350](https://github.com/GoalSmashers/clean-css/issues/350) - edge cases in `@import` processing. * Fixed issue [#346](https://github.com/GoalSmashers/clean-css/issues/346) - overriding !important by !important. * Fixed issue [#345](https://github.com/GoalSmashers/clean-css/issues/345) - URL rebasing for document relative ones. * Fixed issue [#343](https://github.com/GoalSmashers/clean-css/issues/343) - too aggressive rgba/hsla minification. diff --git a/lib/imports/inliner.js b/lib/imports/inliner.js index 02f51036..5f4ff462 100644 --- a/lib/imports/inliner.js +++ b/lib/imports/inliner.js @@ -5,6 +5,7 @@ var https = require('https'); var url = require('url'); var UrlRewriter = require('../images/url-rewriter'); +var Splitter = require('../text/splitter.js'); var merge = function(source1, source2) { var target = {}; @@ -47,7 +48,7 @@ module.exports = function Inliner(context, options) { options.visited = options.visited || []; for (; nextEnd < data.length;) { - nextStart = data.indexOf('@import', cursor); + nextStart = nextImportAt(data, cursor); if (nextStart == -1) break; @@ -76,6 +77,18 @@ module.exports = function Inliner(context, options) { return processNext(options); }; + var nextImportAt = function (data, cursor) { + var nextLowerCase = data.indexOf('@import', cursor); + var nextUpperCase = data.indexOf('@IMPORT', cursor); + + if (nextLowerCase > -1 && nextUpperCase == -1) + return nextLowerCase; + else if (nextLowerCase == -1 && nextUpperCase > -1) + return nextUpperCase; + else + return Math.min(nextLowerCase, nextUpperCase); + }; + var processNext = function(options) { if (options._shared.left.length > 0) return process.apply(null, options._shared.left.shift()); @@ -154,7 +167,7 @@ module.exports = function Inliner(context, options) { options.shallow = data.indexOf('@shallow') > 0; var importDeclaration = data - .substring(data.indexOf(' ', nextStart) + 1, nextEnd) + .substring(nextImportAt(data, nextStart) + '@import'.length + 1, nextEnd) .replace(/@shallow\)$/, ')') .trim(); @@ -163,7 +176,7 @@ module.exports = function Inliner(context, options) { var isQuoted = /^['"]/.exec(importDeclaration.substring(urlStartsAt, urlStartsAt + 2)); var urlEndsAt = isQuoted ? importDeclaration.indexOf(isQuoted[0], urlStartsAt + 1) : - importDeclaration.split(' ')[0].length; + new Splitter(' ').split(importDeclaration)[0].length - (viaUrl ? 1 : 0); var importedFile = importDeclaration .substring(urlStartsAt, urlEndsAt) diff --git a/test/unit-test.js b/test/unit-test.js index c1ab439c..d9862ae1 100644 --- a/test/unit-test.js +++ b/test/unit-test.js @@ -1397,6 +1397,52 @@ title']{display:block}", ".one{color:red}" ] }, { root: process.cwd() }), + 'malformed but still valid @import': cssContext({ + 'prefixed with whitespace': [ + " @import 'test/data/partials/one.css';", + ".one{color:red}" + ], + 'no whitespace between @import and filename': [ + "@import'test/data/partials/one.css';", + ".one{color:red}" + ], + 'extra whitespace between @import and filename': [ + "@import 'test/data/partials/one.css';", + ".one{color:red}" + ], + 'line break between @import and filename': [ + "@import " + lineBreak + "'test/data/partials/one.css';", + ".one{color:red}" + ], + 'extra whitespace prefix in file name': [ + "@import ' test/data/partials/one.css';", + ".one{color:red}" + ], + 'extra whitespace suffix in file name': [ + "@import 'test/data/partials/one.css ';", + ".one{color:red}" + ], + 'extra whitespace after': [ + "@import 'test/data/partials/one.css' ;", + ".one{color:red}" + ], + 'uppercase @import': [ + "@IMPORT 'test/data/partials/one.css';", + ".one{color:red}" + ], + 'extra whitespace between url and filename': [ + "@import url( test/data/partials/one.css);", + ".one{color:red}" + ], + 'extra whitespace prefix in file name - url': [ + "@import url(' test/data/partials/one.css');", + ".one{color:red}" + ], + 'extra whitespace suffix in file name - url': [ + "@import url('test/data/partials/one.css ');", + ".one{color:red}" + ] + }, { root: process.cwd() }), '@import with absolute paths': cssContext({ 'of an unknown file': [ "@import url(/fake.css);", -- 2.34.1