-
-
Notifications
You must be signed in to change notification settings - Fork 929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ignore maps and lists in color-named #2182
Conversation
@@ -49,7 +50,7 @@ const rule = function (expectation, options) { | |||
const namedColors = Object.keys(namedColorData) | |||
|
|||
root.walkDecls(decl => { | |||
if (propertySets.acceptCustomIdents.has(decl.prop)) { | |||
if (propertySets.acceptCustomIdents.has(decl.prop) || !isStandardSyntaxDeclaration(decl)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use isStandardSyntaxDeclaration
we disabled check on color in variables, root and scss nested properties (see https://github.com/stylelint/stylelint/blob/master/lib/utils/isStandardSyntaxDeclaration.js).
@stylelint/core what do you think guys? I vote for the exclusion of non-standard syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mmase Thank you for the PR.
use isStandardSyntaxDeclaration we disabled check on color in variables, root and scss nested properties
I might have made a mistake suggesting the use of isStandardSyntaxDeclaration
to resolve this issue as it's a bit of a sledgehammer. In #2009 we agreed to ignore only maps and lists. This is because we made a design decision a while back to try to be as fine-grained as reasonably possible when ignoring non-standard constructs. This is particularly applicable to rules that check things within values e.g. color-*
, number-*
, unit-*
etc.
@mmase As such we might want to slightly rethink how we go about this. Perhaps the following would work?:
When we check a postcss-value-parser
's word
, we should first check if it has a parent node and if that parent node is a function
, and then check if that function is a standard one using isStandardSyntaxFunction. We'll want to do this inside the walk
.
This should ignore maps and lists like this:
colors: (white: #fff);
While not hammering nested props and variables.
Unfortunately, this is tricky first-stylelint-PR as it deals with the way postcss
and postcss-value-parser
parse non-standard syntax and constructs. Would you be willing to explore implementing this more fine-grained solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense! Will dig in and make some changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jeddy3 so far pretty straight forward, but the maps return false
for the isStandardSyntaxFunction
as maps aren't given a value by postcss-value-parser
. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a commit up with what seems to produce expected results, though sans isStandardSyntaxFunction
due to the above.
d7567e2
to
a676271
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mmase Thanks! I think this work well.
@davidtheclark Any thoughts on this approach?
valueParser(decl.value).walk(node => { | ||
const value = node.value, | ||
type = node.type, | ||
sourceIndex = node.sourceIndex | ||
|
||
if (type === "function") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we get a brief comment above this line stating what this is here for as it's not so obvious and I'm sure we'll come back to it in a couple of months time wondering what it does? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we definitely need a clarifying comment here. Also, I think the variable name functionNodes
is misleading. You're not actually putting nodes in it, right? Could you please try to name that array to match its contents?
Made requested changes, let me know if you have any other thoughts on improvements! |
} | ||
|
||
// Return early if node is inside of a function | ||
if (functionNodeIndexes.indexOf(sourceIndex) > -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we accomplish the same thing in a more standard way with blurFunctionArguments? Have you checked out what is happening in other rules that also ignore function arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was just about to mention that - as it appears that this is essentially the same behavior as the ignore
inside-function
option. Which makes me ask, what is #2009 asking of that can't be achieved with that option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, it appears returning false
inside of a function node is all that needs to be done.
@mmase I think the relevant suggestion in #2009 is
from @jeddy3. If we can't ignore maps without doing the same thing as |
Ah right. Apologies, missed that. Okay, will try a few things as this current implementation feels too harsh. |
Thank you! I think this issue has highlighted a few shortcomings in the tests of this rule as it's not immediately obvious from them if this rule is behaving as expected. I think that the default behaviour should be:
Then we provide an I think we're missing at least two tests in the And another test in the I think these new
I thought we might be able to use Thanks for sticking with us on this. Dealing with non-standard syntax is usually deceptively tricky. |
@jeddy3 Sorry for the delay on this. Declaration values should let us see if they are in a named function or non-standard syntax function (no name). However, I'm wondering if we need to go a step further. For example, in this case, we should ignore $colors: (
white: #000,
grey: #333
); But, in this case, we should probably still warn: $colors: (
white: white,
grey: grey
); Do you agree? |
@mmase Parsing a Sass map is not within the domain of stylelint — rather, a SCSS-specific plugin should take care of that. stylelint itself should just ignore the construction, avoiding mistaken warnings. |
@davidtheclark fair enough, that makes sense 👍 |
👍 @mmase If you're interested, David goes into a bit more background to this problem space here. And for some context specific to this instance... dollar-variables are parsed as Therefore, it would require additional code within stylelint to parse this non-standard construct. Which is why the suggestion is to use |
@jeddy3 thanks for that. However, the remaining issue is ignoring instances of color-mods like |
👍
We're ignoring neither by default. There is already the It sounds like what you've done so far is what we need. If you've also added those tests, then I think you can push up what you've got and we'll be able to see if it's behaving as expected :) |
I suppose that could be covered by |
Ha, just saw you commented the same :) Okay, will write some tests and push up 👍 |
db78ca6
to
80c36d9
Compare
@jeddy3 @davidtheclark made some changes. thanks for your patience with me on this one. I hope this is the solution you are looking for! |
@@ -70,6 +71,10 @@ const rule = function (expectation, options) { | |||
return false | |||
} | |||
|
|||
if (!isStandardSyntaxFunction(node)) { | |||
return false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better use just return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't appear to work. I don't know a ton about postcss-value-parser
, but returning undefined
on only a value
would work. However, since we are making an assertion on a node
, you need to return false
for it to skip the value
s within that node
. Otherwise, I would group it with the isStandardSyntaxValue
check below this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! I've a request for one last test at line 266...
{
code: "a { color: color(#000 a(50%)) }",
message: messages.expected("black", "#000"),
line: 1,
column: 12,
} ],
To make sure that we're checking inside of functions for the "always-where-possible"
option.
@@ -56,6 +56,9 @@ testRule(rule, { | |||
}, { | |||
code: "a { font: 10px/14px Brown, sans-serif; }", | |||
description: "ignore font family names that are colors", | |||
}, { | |||
code: "colors: (white: #fff, blue: #00f);", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use $colors
here to make it extra clear this is a non-standard.
@mmase Ooops, code for my test should be |
@jeddy3 ah, yeah I did the same thing a few times as well. all set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent. LGTM :)
thanks guys! |
Changelog entry:
|
#2009
No, it's self explanatory.