From 9b23a9438cfe3d4f1e4576034a196525f2d38f03 Mon Sep 17 00:00:00 2001 From: fanich37 Date: Wed, 20 Nov 2019 21:18:28 +0300 Subject: [PATCH 1/3] Ignore `x` unit in some cases --- lib/rules/unit-no-unknown/__tests__/index.js | 23 ++++++++++++++++++++ lib/rules/unit-no-unknown/index.js | 19 +++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/rules/unit-no-unknown/__tests__/index.js b/lib/rules/unit-no-unknown/__tests__/index.js index a2e8d6bec7..8b1adf445e 100644 --- a/lib/rules/unit-no-unknown/__tests__/index.js +++ b/lib/rules/unit-no-unknown/__tests__/index.js @@ -220,6 +220,22 @@ testRule(rule, { code: "@import 'foo.css'", description: 'ignore non-media and non-variable at-rule', }, + { + code: "a { background-image: image-set('img-1x.jpg' 1x, 'img-2x.jpg' 2x, 'img-3x.jpg' 3x) }", + description: 'ignore `x` unit in image-set', + }, + { + code: '@media (resolution: 2x) {}', + description: 'ignore `x` unit in @media with `resolution`', + }, + { + code: '@media ( resOLution: 2x) {}', + description: 'ignore `x` unit in @media with `resolution`', + }, + { + code: 'a { image-resolution: 1x; }', + description: 'ignore `x` unit in image-resolution', + }, ], reject: [ @@ -356,6 +372,13 @@ testRule(rule, { line: 1, column: 13, }, + { + code: 'a { width: 400x; }', + message: messages.rejected('x'), + description: '`x` is not allowed for non-resolution props', + line: 1, + column: 12, + }, ], }); diff --git a/lib/rules/unit-no-unknown/index.js b/lib/rules/unit-no-unknown/index.js index 92bcfeabc8..fba31e0284 100644 --- a/lib/rules/unit-no-unknown/index.js +++ b/lib/rules/unit-no-unknown/index.js @@ -62,10 +62,27 @@ const rule = function(actual, options) { return; } - if (keywordSets.units.has(unit.toLowerCase())) { + if (keywordSets.units.has(unit.toLowerCase()) && unit.toLowerCase() !== 'x') { return; } + if (unit.toLowerCase() === 'x') { + if ( + node.type === 'atrule' && + node.name === 'media' && + node.params.toLowerCase().includes('resolution') + ) { + return; + } + + if ( + node.type === 'decl' && + (node.prop.toLowerCase() === 'image-resolution' || /^image-set/i.test(node.value)) + ) { + return; + } + } + report({ index: getIndex(node) + valueNode.sourceIndex, message: messages.rejected(unit), From c814b2169a06e83b1207241f1d3b17d51312ddf3 Mon Sep 17 00:00:00 2001 From: fanich37 Date: Thu, 21 Nov 2019 19:22:18 +0300 Subject: [PATCH 2/3] Complex @media case, update tests --- lib/rules/unit-no-unknown/__tests__/index.js | 14 ++++++++++++++ lib/rules/unit-no-unknown/index.js | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/rules/unit-no-unknown/__tests__/index.js b/lib/rules/unit-no-unknown/__tests__/index.js index 8b1adf445e..be2cb0c7ea 100644 --- a/lib/rules/unit-no-unknown/__tests__/index.js +++ b/lib/rules/unit-no-unknown/__tests__/index.js @@ -379,6 +379,20 @@ testRule(rule, { line: 1, column: 12, }, + { + code: '@media (resolution: 2x) and (min-width: 200x) {}', + message: messages.rejected('x'), + description: '`x` rejected with inappropriate property', + line: 1, + column: 41, + }, + { + code: '@media ( resolution: /* comment */ 2x ) and (min-width: 200x) {}', + message: messages.rejected('x'), + description: '`x` rejected with inappropriate property', + line: 1, + column: 44, + }, ], }); diff --git a/lib/rules/unit-no-unknown/index.js b/lib/rules/unit-no-unknown/index.js index fba31e0284..08fc756382 100644 --- a/lib/rules/unit-no-unknown/index.js +++ b/lib/rules/unit-no-unknown/index.js @@ -5,6 +5,7 @@ const atRuleParamIndex = require('../../utils/atRuleParamIndex'); const declarationValueIndex = require('../../utils/declarationValueIndex'); const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); const keywordSets = require('../../reference/keywordSets'); +const mediaParser = require('postcss-media-query-parser').default; const optionsMatches = require('../../utils/optionsMatches'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -72,7 +73,22 @@ const rule = function(actual, options) { node.name === 'media' && node.params.toLowerCase().includes('resolution') ) { - return; + let ignoreUnit = false; + + mediaParser(node.params).walk((mediaNode, i, mediaNodes) => { + if ( + mediaNode.value.toLowerCase().includes('resolution') && + _.last(mediaNodes).sourceIndex === valueNode.sourceIndex + ) { + ignoreUnit = true; + + return false; + } + }); + + if (ignoreUnit) { + return; + } } if ( From a2358bc2a70506e98b736e84ce3f2b218e071e40 Mon Sep 17 00:00:00 2001 From: fanich37 Date: Fri, 22 Nov 2019 11:06:12 +0300 Subject: [PATCH 3/3] Complex decl case, update tests --- lib/rules/unit-no-unknown/__tests__/index.js | 23 ++++++++++++++++++++ lib/rules/unit-no-unknown/index.js | 22 ++++++++++++++----- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/rules/unit-no-unknown/__tests__/index.js b/lib/rules/unit-no-unknown/__tests__/index.js index be2cb0c7ea..41319c467c 100644 --- a/lib/rules/unit-no-unknown/__tests__/index.js +++ b/lib/rules/unit-no-unknown/__tests__/index.js @@ -393,6 +393,29 @@ testRule(rule, { line: 1, column: 44, }, + { + code: + "a { background: image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; }", + message: messages.rejected('x'), + description: '`x` rejected with inappropriate property', + line: 1, + column: 64, + }, + { + code: + "a { background: /* comment */ image-set('img1x.png' 1x, 'img2x.png' 2x) left 20x / 15% 60% repeat-x; }", + message: messages.rejected('x'), + description: '`x` rejected with inappropriate property', + line: 1, + column: 78, + }, + { + code: "a { background-image: image-set('img1x.png' 1pix, 'img2x.png' 2x); }", + message: messages.rejected('pix'), + description: '`pix` rejected with inappropriate property', + line: 1, + column: 45, + }, ], }); diff --git a/lib/rules/unit-no-unknown/index.js b/lib/rules/unit-no-unknown/index.js index 08fc756382..763257bf33 100644 --- a/lib/rules/unit-no-unknown/index.js +++ b/lib/rules/unit-no-unknown/index.js @@ -42,7 +42,9 @@ const rule = function(actual, options) { // make sure multiplication operations (*) are divided - not handled // by postcss-value-parser value = value.replace(/\*/g, ','); - valueParser(value).walk(function(valueNode) { + const parsedValue = valueParser(value); + + parsedValue.walk(function(valueNode) { // Ignore wrong units within `url` function // and within functions listed in the `ignoreFunctions` option if ( @@ -91,11 +93,19 @@ const rule = function(actual, options) { } } - if ( - node.type === 'decl' && - (node.prop.toLowerCase() === 'image-resolution' || /^image-set/i.test(node.value)) - ) { - return; + if (node.type === 'decl') { + if (node.prop.toLowerCase() === 'image-resolution') { + return; + } + + if (/^image-set/i.test(value)) { + const imageSet = parsedValue.nodes.find((node) => node.value === 'image-set'); + const imageSetValueLastIndex = _.last(imageSet.nodes).sourceIndex; + + if (imageSetValueLastIndex >= valueNode.sourceIndex) { + return; + } + } } }