Skip to content

Commit

Permalink
[New] jsx-no-script-url: support linkAttributes setting
Browse files Browse the repository at this point in the history
  • Loading branch information
burtek authored and ljharb committed Jan 8, 2024
1 parent b2e744d commit 15c3f18
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 17 deletions.
5 changes: 5 additions & 0 deletions docs/rules/jsx-no-script-url.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Examples of **correct** code for this rule:
<a href={"javascript:"}></a>
```

This rule takes the `linkComponents` setting into account.

## Rule Options

```json
Expand All @@ -45,6 +47,9 @@ Examples of **correct** code for this rule:

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

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.
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.

### name

Component name.
Expand Down
33 changes: 16 additions & 17 deletions lib/rules/jsx-no-script-url.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

'use strict';

const includes = require('array-includes');
const docsUrl = require('../util/docsUrl');
const linkComponentsUtil = require('../util/linkComponents');
const report = require('../util/report');

// ------------------------------------------------------------------------------
Expand All @@ -21,26 +23,20 @@ function hasJavaScriptProtocol(attr) {
&& isJavaScriptProtocol.test(attr.value.value);
}

function shouldVerifyElement(node, config) {
const name = node.name && node.name.name;
return name === 'a' || config.find((i) => i.name === name);
}

function shouldVerifyProp(node, config) {
const name = node.name && node.name.name;
const parentName = node.parent.name && node.parent.name.name;

if (parentName === 'a' && name === 'href') {
return true;
}
if (!name || !parentName || !config.has(parentName)) return false;

const el = config.find((i) => i.name === parentName);
if (!el) {
return false;
}
const attributes = config.get(parentName);
return includes(attributes, name);
}

const props = el.props || [];
return node.name && props.indexOf(name) !== -1;
function parseLegacyOption(config, option) {
option.forEach((opt) => {
config.set(opt.name, opt.props);
});
}

const messages = {
Expand Down Expand Up @@ -82,11 +78,14 @@ module.exports = {
},

create(context) {
const config = context.options[0] || [];
const linkComponents = linkComponentsUtil.getLinkComponents(context);
if (context.options[0]) {
parseLegacyOption(linkComponents, context.options[0]);
}

return {
JSXAttribute(node) {
const parent = node.parent;
if (shouldVerifyElement(parent, config) && shouldVerifyProp(node, config) && hasJavaScriptProtocol(node)) {
if (shouldVerifyProp(node, linkComponents) && hasJavaScriptProtocol(node)) {
report(context, messages.noScriptURL, 'noScriptURL', {
node,
});
Expand Down
40 changes: 40 additions & 0 deletions tests/lib/rules/jsx-no-script-url.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,24 @@ ruleTester.run('jsx-no-script-url', rule, {
[{ name: 'Foo', props: ['to', 'href'] }],
],
},
{
code: '<Foo to="javascript:"></Foo>',
errors: [{ messageId: 'noScriptURL' }],
settings: {
linkComponents: [
{ name: 'Foo', linkAttribute: 'to' },
],
},
},
{
code: '<Foo href="javascript:"></Foo>',
errors: [{ messageId: 'noScriptURL' }],
settings: {
linkComponents: [
{ name: 'Foo', linkAttribute: ['to', 'href'] },
],
},
},
{
code: `
<div>
Expand All @@ -84,5 +102,27 @@ ruleTester.run('jsx-no-script-url', rule, {
],
],
},
{
code: `
<div>
<Foo href="javascript:"></Foo>
<Bar link="javascript:"></Bar>
</div>
`,
errors: [
{ messageId: 'noScriptURL' },
{ messageId: 'noScriptURL' },
],
options: [
[
{ name: 'Bar', props: ['link'] },
],
],
settings: {
linkComponents: [
{ name: 'Foo', linkAttribute: ['to', 'href'] },
],
},
},
]),
});

0 comments on commit 15c3f18

Please sign in to comment.