From ec0c1067c2510b6d9b26ff9d75ee622f94e8a871 Mon Sep 17 00:00:00 2001 From: krister Date: Wed, 6 Feb 2019 17:45:11 -0300 Subject: [PATCH 1/3] operator-no-unspaced: improve handling of URLs --- .../operator-no-unspaced/__tests__/index.js | 78 +++++++++++++++++++ src/utils/sassValueParser/index.js | 26 ++++++- 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/src/rules/operator-no-unspaced/__tests__/index.js b/src/rules/operator-no-unspaced/__tests__/index.js index 8238dc7d..840e12c6 100644 --- a/src/rules/operator-no-unspaced/__tests__/index.js +++ b/src/rules/operator-no-unspaced/__tests__/index.js @@ -65,6 +65,22 @@ testRule(rule, { `, description: "background-image with relative path inside url function and interpolation." + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i + 2}-down-dark.svg); + } + `, + description: + "Op +: background-image with absolute path inside url function and interpolation." + }, + { + code: ` + div { background-image: url(https://99-0a.x.y.rackcdn.com/z.jpg); } + `, + description: "Op +: background-image with url that has a hyphen" } ], @@ -105,6 +121,19 @@ testRule(rule, { message: messages.expectedAfter("+"), line: 4, column: 62 + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i +2}-down-dark.svg); + } + `, + description: + "Op +: background-image with relative path inside url function and interpolation.", + message: messages.expectedAfter("+"), + line: 4, + column: 86 } ] }); @@ -146,6 +175,19 @@ testRule(rule, { description: "Op (ss+). b4: ss+ +#{1 + 2}.", message: messages.expectedBefore("+"), column: 11 + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i+ 2}-down-dark.svg); + } + `, + description: + "Op +: background-image with relative path inside url function and interpolation.", + message: messages.expectedBefore("+"), + line: 4, + column: 85 } ] }); @@ -450,6 +492,16 @@ testRule(rule, { { code: "a { b3: ss- -#{$var}; }", description: "Sign: ss- -#{$var}." + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i - 2}-down-dark.svg); + } + `, + description: + "Op -: background-image with absolute path inside url function and interpolation." } ], @@ -465,6 +517,19 @@ testRule(rule, { description: "Op (ss+): ss+ -#{1 + 2}.", message: messages.expectedBefore("+"), column: 11 + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i- 2}-down-dark.svg); + } + `, + description: + "Op -: background-image with relative path inside url function and interpolation.", + message: messages.expectedBefore("-"), + line: 4, + column: 85 } ] }); @@ -645,6 +710,19 @@ testRule(rule, { { code: "a { minusafter15: 1- #{$var}; }", description: "Op (though concatenated): 1- #{$var}." + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i -2}-down-dark.svg); + } + `, + description: + "Op -: background-image with relative path inside url function and interpolation.", + message: messages.expectedAfter("-"), + line: 4, + column: 86 } ] }); diff --git a/src/utils/sassValueParser/index.js b/src/utils/sassValueParser/index.js index 88af1529..bd722a21 100644 --- a/src/utils/sassValueParser/index.js +++ b/src/utils/sassValueParser/index.js @@ -347,6 +347,11 @@ function checkMinus(string, index) { return "op"; } + // e.g. `#{10px -1}` + if (isInsideInterpolation(string, index)) { + return "op"; + } + // e.g. `sth -1px`, `sth -1`. // Always a sign, even inside parens/function args if ( @@ -405,6 +410,11 @@ function checkMinus(string, index) { return "op"; } + // e.g. `#{10px- 1}` + if (isInsideInterpolation(string, index)) { + return "op"; + } + if (isNumberBefore(before) || isHexColorBefore(before)) { // console.log('`-, op: 10- , #aff- `') return "op"; @@ -491,6 +501,13 @@ function checkSlash(string, index, isAfterColon) { return "char"; } + // e.g. `(1px/1)`, `fn(7 / 15)`, but not `url(8/11)` + const isInsideFn = isInsideFunctionCall(string, index); + + if (isInsideFn.is && isInsideFn.fn === "url" && isProtocolBefore(before)) { + return "char"; + } + // e.g. `10px/normal` if (isStringBefore(before).is || isStringAfter(after)) { // console.log("/, string") @@ -548,9 +565,6 @@ function checkSlash(string, index, isAfterColon) { return "op"; } - // e.g. `(1px/1)`, `fn(7 / 15)`, but not `url(8/11)` - const isInsideFn = isInsideFunctionCall(string, index); - if ( isInsideParens(string, index) || (isInsideFn.is && isInsideFn.fn !== "url") @@ -679,7 +693,7 @@ function isInsideFunctionCall(string, index) { const after = string.substring(index + 1).trim(); const beforeMatch = before.match(/([a-zA-Z_-][a-zA-Z0-9_-]*)\([^(){},]+$/); - if (beforeMatch && beforeMatch[0] && after.search(/^[^({},]+\)/) !== -1) { + if (beforeMatch && beforeMatch[0] && after.search(/^[^(,]+\)/) !== -1) { result.is = true; result.fn = beforeMatch[1]; } @@ -887,6 +901,10 @@ function isDotBefore(before) { return before.slice(-1) === "."; } +function isProtocolBefore(before) { + return before.search(/https?:/) !== 1; +} + function isFunctionBefore(before) { return before.trim().search(/[a-zA-Z0-9_-]\(.*?\)\s*$/) !== -1; } From 238b09397fe8c45cfb8982c412a060cc5d7bb8c5 Mon Sep 17 00:00:00 2001 From: krister Date: Wed, 6 Feb 2019 19:57:30 -0300 Subject: [PATCH 2/3] make sure that there are tests for all operators --- .../operator-no-unspaced/__tests__/index.js | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/rules/operator-no-unspaced/__tests__/index.js b/src/rules/operator-no-unspaced/__tests__/index.js index 840e12c6..e88be537 100644 --- a/src/rules/operator-no-unspaced/__tests__/index.js +++ b/src/rules/operator-no-unspaced/__tests__/index.js @@ -1077,6 +1077,16 @@ testRule(rule, { `, description: "background-image with relative path inside url function and interpolation." + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i / 2}-down-dark.svg); + } + `, + description: + "Op /: background-image with absolute path inside url function and interpolation." } ], @@ -1138,6 +1148,32 @@ testRule(rule, { message: messages.expectedAfter("/"), line: 4, column: 62 + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i /2}-down-dark.svg); + } + `, + description: + "Op /: background-image with relative path inside url function and interpolation.", + message: messages.expectedAfter("/"), + line: 4, + column: 86 + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i/ 2}-down-dark.svg); + } + `, + description: + "Op /: background-image with relative path inside url function and interpolation.", + message: messages.expectedBefore("/"), + line: 4, + column: 85 } ] }); @@ -1199,6 +1235,19 @@ testRule(rule, { syntax: "scss", skipBasicChecks: true, + accept: [ + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i * 2}-down-dark.svg); + } + `, + description: + "Op *: background-image with absolute path inside url function and interpolation." + } + ], + reject: [ { code: "a { width: 10* 1; }", @@ -1211,6 +1260,32 @@ testRule(rule, { description: "Op: 10 *1.", message: messages.expectedAfter("*"), column: 15 + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i *2}-down-dark.svg); + } + `, + description: + "Op *: background-image with relative path inside url function and interpolation.", + message: messages.expectedAfter("*"), + line: 4, + column: 86 + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i* 2}-down-dark.svg); + } + `, + description: + "Op *: background-image with relative path inside url function and interpolation.", + message: messages.expectedBefore("*"), + line: 4, + column: 85 } ] }); @@ -1290,6 +1365,16 @@ testRule(rule, { { code: "a { width: 10% - (1 + 3); }", description: "10% - (1 + 3)." + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i % 2}-down-dark.svg); + } + `, + description: + "Op %: background-image with absolute path inside url function and interpolation." } ], @@ -1374,6 +1459,32 @@ testRule(rule, { code: "a { width: 10% -(1 + 3); }", description: "10% -(1 + 3).", message: messages.expectedAfter("-") + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i %2}-down-dark.svg); + } + `, + description: + "Op %: background-image with relative path inside url function and interpolation.", + message: messages.expectedAfter("%"), + line: 4, + column: 86 + }, + { + code: ` + $i: 10; + .thing { + background-image: url(https://99-0a.x.y.rackcdn.com/img/build/svg/arrow-#{$i% 2}-down-dark.svg); + } + `, + description: + "Op %: background-image with relative path inside url function and interpolation.", + message: messages.expectedBefore("%"), + line: 4, + column: 85 } ] }); From 3dba74dd7ceb84fdc119179dde015cfc6cb1c19f Mon Sep 17 00:00:00 2001 From: krister Date: Wed, 6 Feb 2019 20:02:58 -0300 Subject: [PATCH 3/3] add missing minus sign --- src/utils/sassValueParser/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/sassValueParser/index.js b/src/utils/sassValueParser/index.js index bd722a21..a26f44bb 100644 --- a/src/utils/sassValueParser/index.js +++ b/src/utils/sassValueParser/index.js @@ -902,7 +902,7 @@ function isDotBefore(before) { } function isProtocolBefore(before) { - return before.search(/https?:/) !== 1; + return before.search(/https?:/) !== -1; } function isFunctionBefore(before) {