Skip to content

Commit caf714e

Browse files
committed
[Feat] no-danger: allow custom components as option for no-danger
1 parent 03cd4b5 commit caf714e

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

lib/rules/no-danger.js

+28-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ const messages = {
4343
dangerousProp: 'Dangerous property \'{{name}}\' found',
4444
};
4545

46-
/** @type {import('eslint').Rule.RuleModule} */
4746
module.exports = {
4847
meta: {
4948
docs: {
@@ -55,13 +54,39 @@ module.exports = {
5554

5655
messages,
5756

58-
schema: [],
57+
schema: [{
58+
type: 'object',
59+
properties: {
60+
checkCustomComponents: {
61+
default: false,
62+
type: 'boolean',
63+
},
64+
customComponentNames: {
65+
items: {
66+
type: 'string',
67+
},
68+
minItems: 1,
69+
type: 'array',
70+
uniqueItems: true,
71+
},
72+
},
73+
}],
5974
},
6075

6176
create(context) {
77+
const configuration = context.options[0] || {};
78+
const checkCustomComponents = configuration.checkCustomComponents;
79+
const customComponentNames = configuration.customComponentNames;
80+
6281
return {
6382
JSXAttribute(node) {
64-
if (jsxUtil.isDOMComponent(node.parent) && isDangerous(node.name.name)) {
83+
const functionName = node.parent.name.name;
84+
85+
const enableCheckingCustomComponent = customComponentNames
86+
? checkCustomComponents && customComponentNames.some((name) => functionName === name)
87+
: checkCustomComponents;
88+
89+
if ((enableCheckingCustomComponent || jsxUtil.isDOMComponent(node.parent)) && isDangerous(node.name.name)) {
6590
report(context, messages.dangerousProp, 'dangerousProp', {
6691
node,
6792
data: {

tests/lib/rules/no-danger.js

+36
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ ruleTester.run('no-danger', rule, {
3232
{ code: '<App />;' },
3333
{ code: '<App dangerouslySetInnerHTML={{ __html: "" }} />;' },
3434
{ code: '<div className="bar"></div>;' },
35+
{ code: '<div className="bar"></div>;', options: [{ checkCustomComponents: false }] },
36+
{ code: '<div className="bar"></div>;', options: [{ checkCustomComponents: true }] },
37+
{ code: '<App />;', options: [{ checkCustomComponents: false }] },
38+
{ code: '<App dangerouslySetInnerHTML={{ __html: "" }} />;', options: [{ checkCustomComponents: false }] },
39+
{
40+
code: `
41+
function App() {
42+
return <Title dangerouslySetInnerHTML={{ __html: "<span>hello</span>" }} />;
43+
}
44+
`,
45+
options: [{ checkCustomComponents: true, customComponentNames: ['Home'] }],
46+
},
3547
]),
3648
invalid: parsers.all([
3749
{
@@ -43,5 +55,29 @@ ruleTester.run('no-danger', rule, {
4355
},
4456
],
4557
},
58+
{
59+
code: '<App dangerouslySetInnerHTML={{ __html: "<span>hello</span>" }} />;',
60+
errors: [
61+
{
62+
messageId: 'dangerousProp',
63+
data: { name: 'dangerouslySetInnerHTML' },
64+
},
65+
],
66+
options: [{ checkCustomComponents: true }],
67+
},
68+
{
69+
code: `
70+
function App() {
71+
return <Title dangerouslySetInnerHTML={{ __html: "<span>hello</span>" }} />;
72+
}
73+
`,
74+
errors: [
75+
{
76+
messageId: 'dangerousProp',
77+
data: { name: 'dangerouslySetInnerHTML' },
78+
},
79+
],
80+
options: [{ checkCustomComponents: true, customComponentNames: ['Title'] }],
81+
},
4682
]),
4783
});

0 commit comments

Comments
 (0)