-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Add includeDOM option to rule "forbid-component-props". #850
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
base: master
Are you sure you want to change the base?
Conversation
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.
Either way, this will need tests.
docs/rules/forbid-component-props.md
Outdated
|
||
An array of strings, with the names of props that are forbidden. The default value of this option is `['className', 'style']`. | ||
|
||
### `includeDOM` |
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 seems like something that will vary per prop name. Perhaps the enhancement should be that forbid
can have strings or objects, and if an object, it can be something like { "property": "foo", "includeDOM": true }
?
How about If that API is okay, I'll get this PR updated with new documentation, the new API, and tests tomorrow. |
I think that allowing string-or-object in the array gives far greater flexibility - that would also let me potentially forbid a prop on one list of components, but not on others. |
I think the flexibility is the same:
would achieve the same thing, no? I think that's easier for users to manage than: `
Or:
(or any other permutation of nesting an object inside the array of string that I can imagine) It's a completely subjective decision and ultimately it's your code, so I'll do what you think is best, but IMO the first example is the easiest to read if I'm a hypothetical engineer and I'm reading someone else's .eslintrc and I'm not necessarily familiar with this particular plugin. |
@EdwardDrapkin imagine a hypothetical future option where you could forbid "foo" on a Foo component, but allow "foo" on anything else - or where you want to forbid "style" on both React and DOM components, but simultaneously forbid "className" only on React components. The latter certainly can be achieved with your suggestion, but that won't allow for the former, and that also requires that property names be duplicated in both lists, which can be hard to maintain. |
Ahhhhh, I wasn't even considering that! You make excellent points. Perhaps we could also take this opportunity to allow people the flexibility you imagine? I have two ideas. First, we could allow passing custom validator functions like:
where the function is just This would be pretty simple to implement, and is probably the most flexible approach, but not exactly user friendly because it's too complex for what I believe is likely to be the common use case... So maybe, instead we just allow a regular expression to be passed?
This is probably the easiest for users to use and covers like 99% of the cases people would want, but would require documentation to tell people to use something like What do you think? I'm not sure what to name the config options in either case to be the most user friendly. |
eslint configs are defined in JSON or yaml, so it'd be impossible to provide a function. I think adding regex support is unneeded complexity - being able to configure a boolean for DOM and another for React, along with simple component names per-property that can override the booleans, seems like it would cover all the current and potential use cases pretty well. |
Can't you use a JS file as an .eslintrc.js? It's irrelevant anyway... How does this look?
Is |
I think I'd prefer: {
"property": <string>,
"allowOnComponents": <boolean>, // default false
"allowOnDOM": <boolean>, // default false
"forbid": <array of component name strings>, // overrides previous two booleans
} where passing a simple string "foo" as the property name is equivalent to: {
"property": "foo",
"allowOnComponents": false,
"allowOnDOM": true, // simply so it's not a breaking change
"forbid": [],
} |
Perfect. I'll get this PR updated sometime in the next 24-48 hours with these changes! |
```js | ||
... | ||
"forbid-component-props": [<enabled>, { "forbid": [<string>] }] | ||
"forbid-component-props": [<enabled>, { "forbid": [<string>|<object>], "defaultAllowOnComponents": <bool>, "defaultAllowOnDOM": <bool>}] |
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.
the two "default" booleans need to be on the object, not on the outer config object. not sure how to denote this tho.
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.
unless you're suggesting that they'd be top-level settings as well? if so, i do think i like that.
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.
yeah, there's an outer config option for specifying the default behavior and an option for overloading the default, but i wasn't quite sure how to make that clear in the documentation other than in the examples...
Okay, the football sucked, so I went ahead and got to work on this. I did some extra work that we hadn't discussed, but I was adding examples to the documentation and surfaced some cases I wanted to address. I added I updated the documentation and I think it's okay, but please do read and update it if you feel it's lacking. Or tell me and I gladly will! I also added more test cases so Istanbul reports 100% coverage for me. Let me know if there's any issues this time. Thanks so much for your time helping me get this working (and for the rule in the first place)! |
I think this is looking much better, and I like the additions you've made! I think we'll want to add a very large quantity of test cases, that cover as many interesting combinations of rules as possible. |
I added some more test cases, up to 21 now. I'm having trouble coming up with cases that aren't already tested. |
lib/rules/forbid-component-props.js
Outdated
{ | ||
type: 'object', | ||
properties: { | ||
defaultAllowOnDOM: { |
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 think the schema is missing defaultAllowOnComponents
?
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.
oops is all i got
additionalProperties: true | ||
}] | ||
}, | ||
additionalProperties: true |
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 think we can maybe set this to false
, so nobody accidentally passes an invalid config 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.
okay, I can change it... I just didn't wanna mess with what you already had
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.
yeah that's a good point, it might constitute a breaking change. probably best to leave it true
for now.
defaultAllowOnDOM: { | ||
type: 'boolean' | ||
}, | ||
forbid: { |
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.
the schema also seems to be missing allow
, which i think should probably share a schema with forbid
? (ie, reuse the array schema in both)
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.
okay i was a little excited
lib/rules/forbid-component-props.js
Outdated
|
||
var forbid = configuration.forbid || DEFAULTS; | ||
return forbid.indexOf(prop) >= 0; | ||
for (var i = 0; i < input.length; i++) { |
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 use input.forEach
here, instead of a for loop?
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.
yep, done
lib/rules/forbid-component-props.js
Outdated
|
||
function getError(prop, tag) { | ||
if (rules[prop].forbid.indexOf(tag) > -1) { | ||
return 'Prop `' + prop + '` is specifically forbidden on tags named ' + tag; |
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.
'… on ' + tag + ' components'
?
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.
It swaps between "$tag Components" and "$tag DOM nodes" now.
] | ||
}, { | ||
code: [ | ||
'var First = React.createClass({', |
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.
for each of the tests you're using for React.createClass
, let's please also add a test case for an SFC, and a class-based component.
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 only added one total test case for each. I figure if one test case works for all three, all test cases should, because we're only getting at the JSX tags inside the (render) function body, right? I can add more if you think they're necessary.
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.
Ah, that's another thing - we should check for React.createElement
calls too (ie, non-JSX) :-)
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.
If you want me to, that's cool and I'm down to learn how, but I don't know... so can you point me in the right direction if there's another plugin I might be able to read? If not, I'll just RTFM I guess.
And do you have any problem if I do it in a separate pull request? It seems outside the scope of this one and I might not have time to get to it until this upcoming weekend.
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.
Hmm, you may have opened a can of worms, at first glance there are several other plugins that do things with props that rely on JSXExpression too... no-duplicate-props, no-unknown-property, sort-props, maybe more....
What is the best way to go forward if this is an issue that affects multiple rules? Open a new issue and then read each rule one by one and make sure they're not affected?
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.
There are a number of rules that address both - however, I'm fine if this rule covers jsx right now, but is expanded to non-JSX in a future PR.
defaultAllowOnComponents: { | ||
type: 'boolean' | ||
}, | ||
forbid: { |
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.
is there not a top-level allow
as well?
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.
Wouldn't that mean the entire plugin would have to switch into whitelist mode? Would that be useful to anyone?
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.
Hm, yeah i guess if i wanted to override a forbid
i'd now just modify the object inside the array. This is fine as-is.
I think I addressed everything from your notes - and I'll make a separate pull request to add |
this might clash with #936 |
@EdwardDrapkin would you be alright with @burabure building off your commits to achieve both this PR and #936? |
@EdwardDrapkin ping |
@ljharb I don't think @EdwardDrapkin is going to reply. Should I go ahead? |
Sure, go for it. |
I'm sorry, I've been really sick lately fighting off MRSA (yikes!) and I won't have time to get to this. You should definitely go ahead. |
Thanks for confirming - @burabure, do your thing :-) |
@EdwardDrapkin sorry to hear that, I have a friend that had MRSA and I know it really sucks. Hope you feel better soon! |
I don't have time to see this through, if anyone is up to it please do =) |
59af733
to
865ed16
Compare
069314a
to
181c68f
Compare
380e32c
to
51d342b
Compare
I wanted to forbid some prop types on DOM nodes as well as Components, so I added the option here. Let me know if there's anything that needs to be done here to get this approved. Thanks in advance!