From: Jakub Pawlowicz Date: Tue, 14 Mar 2017 09:35:54 +0000 (+0100) Subject: Fixes #902 - case insensitive attribute matchers. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=134972c693ec26daa860e713d68b7d56f10cf68e;p=clean-css.git Fixes #902 - case insensitive attribute matchers. Why: * CSS 4 spec defines case insensitive matchers which were treated incorrectly by attribute tidying code. --- diff --git a/History.md b/History.md index 454c8264..583fbb4e 100644 --- a/History.md +++ b/History.md @@ -8,6 +8,7 @@ [4.0.9 / 2017-xx-xx](https://github.com/jakubpawlowicz/clean-css/compare/v4.0.8...4.0) ================== +* Fixed issue [#902](https://github.com/jakubpawlowicz/clean-css/issues/902) - case insensitive attribute matchers. * Fixed issue [#907](https://github.com/jakubpawlowicz/clean-css/issues/907) - space after closing brace in `@supports`. * Fixed issue [#910](https://github.com/jakubpawlowicz/clean-css/issues/910) - too aggressive precision optimizations. diff --git a/lib/optimizer/level-1/tidy-rules.js b/lib/optimizer/level-1/tidy-rules.js index 0bd7073b..5aba2c7b 100644 --- a/lib/optimizer/level-1/tidy-rules.js +++ b/lib/optimizer/level-1/tidy-rules.js @@ -2,7 +2,13 @@ var Spaces = require('../../options/format').Spaces; var Marker = require('../../tokenizer/marker'); var formatPosition = require('../../utils/format-position'); +var CASE_ATTRIBUTE_PATTERN = /[\s"'][iI]\s*\]/; +var CASE_RESTORE_PATTERN = /([\d\w])([iI])\]/g; +var DOUBLE_QUOTE_CASE_PATTERN = /="([a-zA-Z][a-zA-Z\d\-_]+)"([iI])/g; +var DOUBLE_QUOTE_PATTERN = /="([a-zA-Z][a-zA-Z\d\-_]+)"(\s|\])/g; var HTML_COMMENT_PATTERN = /^(?:(?:)\s*)+/; +var SINGLE_QUOTE_CASE_PATTERN = /='([a-zA-Z][a-zA-Z\d\-_]+)'([iI])/g; +var SINGLE_QUOTE_PATTERN = /='([a-zA-Z][a-zA-Z\d\-_]+)'(\s|\])/g; var RELATION_PATTERN = /[>\+~]/; var WHITESPACE_PATTERN = /\s/; @@ -54,6 +60,7 @@ function removeWhitespace(value, format) { var roundBracketLevel = 0; var wasRelation = false; var wasWhitespace = false; + var withCaseAttribute = CASE_ATTRIBUTE_PATTERN.test(value); var spaceAroundRelation = format && format.spaces[Spaces.AroundSelectorRelation]; var i, l; @@ -128,13 +135,21 @@ function removeWhitespace(value, format) { wasWhitespace = isWhitespace; } - return stripped.join(''); + return stripped + .join('') + .replace(withCaseAttribute ? CASE_RESTORE_PATTERN : null, '$1 $2]'); } function removeQuotes(value) { + if (value.indexOf('\'') == -1 && value.indexOf('"') == -1) { + return value; + } + return value - .replace(/='([a-zA-Z][a-zA-Z\d\-_]+)'/g, '=$1') - .replace(/="([a-zA-Z][a-zA-Z\d\-_]+)"/g, '=$1'); + .replace(SINGLE_QUOTE_CASE_PATTERN, '=$1 $2') + .replace(SINGLE_QUOTE_PATTERN, '=$1$2') + .replace(DOUBLE_QUOTE_CASE_PATTERN, '=$1 $2') + .replace(DOUBLE_QUOTE_PATTERN, '=$1$2'); } function tidyRules(rules, removeUnsupported, adjacentSpace, format, warnings) { diff --git a/test/optimizer/level-1/optimize-test.js b/test/optimizer/level-1/optimize-test.js index bedebdba..6f66d932 100644 --- a/test/optimizer/level-1/optimize-test.js +++ b/test/optimizer/level-1/optimize-test.js @@ -105,6 +105,18 @@ vows.describe('level 1 optimizations') '.b[data-json=\'"aaaa":"bbbb"\']{color:red}', '.b[data-json=\'"aaaa":"bbbb"\']{color:red}' ], + 'single word case insensitive attribute with quotes': [ + '.block[data-value="test" i]{color:red}', + '.block[data-value=test i]{color:red}' + ], + 'multiword case insensitive attribute with quotes': [ + '.block[data-value="test me" i]{color:red}', + '.block[data-value="test me"i]{color:red}' + ], + 'single word case insensitive attribute without quotes': [ + '.block[data-value=test i]{color:red}', + '.block[data-value=test i]{color:red}' + ], 'no rule scope': [ '{overflow:hidden}', ''