Skip to content

Commit b5674e9

Browse files
committed
Conditionally include link components defined in settings
1 parent 15c3f18 commit b5674e9

File tree

3 files changed

+142
-43
lines changed

3 files changed

+142
-43
lines changed

docs/rules/jsx-no-script-url.md

+40-5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ This rule takes the `linkComponents` setting into account.
2727

2828
## Rule Options
2929

30+
This rule accepts array option (optional) and object option (optional).
31+
32+
### Array option (default `[]`)
33+
3034
```json
3135
{
3236
"react/jsx-no-script-url": [
@@ -47,14 +51,11 @@ This rule takes the `linkComponents` setting into account.
4751

4852
Allows you to indicate a specific list of properties used by a custom component to be checked.
4953

50-
NOTE: This rule now takes into account the `linkComponents` config in [global shared settings](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/README.md#configuration), which should be used as the sole source of truth for link components.
51-
The rule still allows passing link components as rule option for backwards compatibility, but this option is deprecated. If specified, this option will be used together with global `linkComponents` config.
52-
53-
### name
54+
#### name
5455

5556
Component name.
5657

57-
### props
58+
#### props
5859

5960
List of properties that should be validated.
6061

@@ -65,3 +66,37 @@ Examples of **incorrect** code for this rule, when configured with the above opt
6566
<Foo href="javascript:void(0)"></Foo>
6667
<Foo to="javascript:void(0)"></Foo>
6768
```
69+
70+
### Object option
71+
72+
#### includeFromSettings (default `false`)
73+
74+
Indicates if the `linkComponents` config in [global shared settings](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/README.md#configuration) should also be taken into account. If enabled, components and properties defined in settings will be added to the list provided in first option (if provided):
75+
76+
```json
77+
{
78+
"react/jsx-no-script-url": [
79+
"error",
80+
[
81+
{
82+
"name": "Link",
83+
"props": ["to"]
84+
},
85+
{
86+
"name": "Foo",
87+
"props": ["href", "to"]
88+
}
89+
],
90+
{ "includeFromSettings": true }
91+
]
92+
}
93+
```
94+
95+
If only global settings should be used for this rule, the array option can be omitted:
96+
97+
```jsonc
98+
{
99+
// same as ["error", [], { "includeFromSettings": true }]
100+
"react/jsx-no-script-url": ["error", { "includeFromSettings": true }]
101+
}
102+
```

lib/rules/jsx-no-script-url.js

+63-21
Original file line numberDiff line numberDiff line change
@@ -54,34 +54,76 @@ module.exports = {
5454

5555
messages,
5656

57-
schema: [{
58-
type: 'array',
59-
uniqueItems: true,
60-
items: {
61-
type: 'object',
62-
properties: {
63-
name: {
64-
type: 'string',
65-
},
66-
props: {
67-
type: 'array',
68-
items: {
69-
type: 'string',
57+
schema: {
58+
anyOf: [
59+
{
60+
type: 'array',
61+
items: [
62+
{
63+
type: 'array',
7064
uniqueItems: true,
65+
items: {
66+
type: 'object',
67+
properties: {
68+
name: {
69+
type: 'string',
70+
},
71+
props: {
72+
type: 'array',
73+
items: {
74+
type: 'string',
75+
uniqueItems: true,
76+
},
77+
},
78+
},
79+
required: ['name', 'props'],
80+
additionalProperties: false,
81+
},
7182
},
72-
},
83+
{
84+
type: 'object',
85+
properties: {
86+
includeFromSettings: {
87+
type: 'boolean',
88+
},
89+
},
90+
},
91+
],
92+
additionalItems: false,
7393
},
74-
required: ['name', 'props'],
75-
additionalProperties: false,
76-
},
77-
}],
94+
{
95+
type: 'array',
96+
items: [
97+
{
98+
type: 'object',
99+
properties: {
100+
includeFromSettings: {
101+
type: 'boolean',
102+
},
103+
},
104+
},
105+
],
106+
additionalItems: false,
107+
},
108+
],
109+
},
78110
},
79111

80112
create(context) {
81-
const linkComponents = linkComponentsUtil.getLinkComponents(context);
82-
if (context.options[0]) {
83-
parseLegacyOption(linkComponents, context.options[0]);
113+
const options = context.options.slice();
114+
let legacyOptions = [];
115+
let includeFromSettings = false;
116+
117+
if (Array.isArray(options[0])) {
118+
legacyOptions = options.shift();
84119
}
120+
if (typeof options[0] === 'object') {
121+
const objOption = options.shift();
122+
includeFromSettings = objOption.includeFromSettings || includeFromSettings;
123+
}
124+
125+
const linkComponents = linkComponentsUtil.getLinkComponents(includeFromSettings ? context : {});
126+
parseLegacyOption(linkComponents, legacyOptions);
85127

86128
return {
87129
JSXAttribute(node) {

tests/lib/rules/jsx-no-script-url.js

+39-17
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,22 @@ ruleTester.run('jsx-no-script-url', rule, {
3838
{ code: '<a href={"javascript:"}></a>' },
3939
{ code: '<Foo href="javascript:"></Foo>' },
4040
{ code: '<a href />' },
41+
{
42+
code: '<Foo href="javascript:"></Foo>',
43+
settings: {
44+
linkComponents: [{ name: 'Foo', linkAttribute: ['to', 'href'] }],
45+
},
46+
},
47+
{
48+
code: '<Foo href="javascript:"></Foo>',
49+
options: [[], { includeFromSettings: false }],
50+
settings: {
51+
linkComponents: [{ name: 'Foo', linkAttribute: ['to', 'href'] }],
52+
},
53+
},
4154
]),
4255
invalid: parsers.all([
56+
// defaults
4357
{
4458
code: '<a href="javascript:"></a>',
4559
errors: [{ messageId: 'noScriptURL' }],
@@ -52,6 +66,8 @@ ruleTester.run('jsx-no-script-url', rule, {
5266
code: '<a href="j\n\n\na\rv\tascript:"></a>',
5367
errors: [{ messageId: 'noScriptURL' }],
5468
},
69+
70+
// with component passed by options
5571
{
5672
code: '<Foo to="javascript:"></Foo>',
5773
errors: [{ messageId: 'noScriptURL' }],
@@ -66,22 +82,32 @@ ruleTester.run('jsx-no-script-url', rule, {
6682
[{ name: 'Foo', props: ['to', 'href'] }],
6783
],
6884
},
85+
{ // make sure it still uses defaults when passed options
86+
code: '<a href="javascript:void(0)"></a>',
87+
errors: [{ messageId: 'noScriptURL' }],
88+
options: [
89+
[{ name: 'Foo', props: ['to', 'href'] }],
90+
],
91+
},
92+
93+
// with components passed by settings
6994
{
7095
code: '<Foo to="javascript:"></Foo>',
7196
errors: [{ messageId: 'noScriptURL' }],
97+
options: [
98+
[{ name: 'Bar', props: ['to', 'href'] }],
99+
{ includeFromSettings: true },
100+
],
72101
settings: {
73-
linkComponents: [
74-
{ name: 'Foo', linkAttribute: 'to' },
75-
],
102+
linkComponents: [{ name: 'Foo', linkAttribute: 'to' }],
76103
},
77104
},
78105
{
79106
code: '<Foo href="javascript:"></Foo>',
80107
errors: [{ messageId: 'noScriptURL' }],
108+
options: [{ includeFromSettings: true }],
81109
settings: {
82-
linkComponents: [
83-
{ name: 'Foo', linkAttribute: ['to', 'href'] },
84-
],
110+
linkComponents: [{ name: 'Foo', linkAttribute: ['to', 'href'] }],
85111
},
86112
},
87113
{
@@ -96,11 +122,12 @@ ruleTester.run('jsx-no-script-url', rule, {
96122
{ messageId: 'noScriptURL' },
97123
],
98124
options: [
99-
[
100-
{ name: 'Foo', props: ['to', 'href'] },
101-
{ name: 'Bar', props: ['link'] },
102-
],
125+
[{ name: 'Bar', props: ['link'] }],
126+
{ includeFromSettings: true },
103127
],
128+
settings: {
129+
linkComponents: [{ name: 'Foo', linkAttribute: ['to', 'href'] }],
130+
},
104131
},
105132
{
106133
code: `
@@ -111,17 +138,12 @@ ruleTester.run('jsx-no-script-url', rule, {
111138
`,
112139
errors: [
113140
{ messageId: 'noScriptURL' },
114-
{ messageId: 'noScriptURL' },
115141
],
116142
options: [
117-
[
118-
{ name: 'Bar', props: ['link'] },
119-
],
143+
[{ name: 'Bar', props: ['link'] }],
120144
],
121145
settings: {
122-
linkComponents: [
123-
{ name: 'Foo', linkAttribute: ['to', 'href'] },
124-
],
146+
linkComponents: [{ name: 'Foo', linkAttribute: ['to', 'href'] }],
125147
},
126148
},
127149
]),

0 commit comments

Comments
 (0)