source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/jsx-no-script-url.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/**
2 * @fileoverview Prevent usage of `javascript:` URLs
3 * @author Sergei Startsev
4 */
5
6'use strict';
7
8const includes = require('array-includes');
9const docsUrl = require('../util/docsUrl');
10const linkComponentsUtil = require('../util/linkComponents');
11const report = require('../util/report');
12
13// ------------------------------------------------------------------------------
14// Rule Definition
15// ------------------------------------------------------------------------------
16
17// https://github.com/facebook/react/blob/d0ebde77f6d1232cefc0da184d731943d78e86f2/packages/react-dom/src/shared/sanitizeURL.js#L30
18/* eslint-disable-next-line max-len, no-control-regex */
19const isJavaScriptProtocol = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*:/i;
20
21function hasJavaScriptProtocol(attr) {
22 return attr.value && attr.value.type === 'Literal'
23 && isJavaScriptProtocol.test(attr.value.value);
24}
25
26function shouldVerifyProp(node, config) {
27 const name = node.name && node.name.name;
28 const parentName = node.parent.name && node.parent.name.name;
29
30 if (!name || !parentName || !config.has(parentName)) return false;
31
32 const attributes = config.get(parentName);
33 return includes(attributes, name);
34}
35
36function parseLegacyOption(config, option) {
37 option.forEach((opt) => {
38 config.set(opt.name, opt.props);
39 });
40}
41
42const messages = {
43 noScriptURL: 'A future version of React will block javascript: URLs as a security precaution. Use event handlers instead if you can. If you need to generate unsafe HTML, try using dangerouslySetInnerHTML instead.',
44};
45
46/** @type {import('eslint').Rule.RuleModule} */
47module.exports = {
48 meta: {
49 docs: {
50 description: 'Disallow usage of `javascript:` URLs',
51 category: 'Best Practices',
52 recommended: false,
53 url: docsUrl('jsx-no-script-url'),
54 },
55
56 messages,
57
58 schema: {
59 anyOf: [
60 {
61 type: 'array',
62 items: [
63 {
64 type: 'array',
65 uniqueItems: true,
66 items: {
67 type: 'object',
68 properties: {
69 name: {
70 type: 'string',
71 },
72 props: {
73 type: 'array',
74 items: {
75 type: 'string',
76 uniqueItems: true,
77 },
78 },
79 },
80 required: ['name', 'props'],
81 additionalProperties: false,
82 },
83 },
84 {
85 type: 'object',
86 properties: {
87 includeFromSettings: {
88 type: 'boolean',
89 },
90 },
91 additionalItems: false,
92 },
93 ],
94 additionalItems: false,
95 },
96 {
97 type: 'array',
98 items: [
99 {
100 type: 'object',
101 properties: {
102 includeFromSettings: {
103 type: 'boolean',
104 },
105 },
106 additionalItems: false,
107 },
108 ],
109 additionalItems: false,
110 },
111 ],
112 },
113 },
114
115 create(context) {
116 const options = context.options;
117 const hasLegacyOption = Array.isArray(options[0]);
118 const legacyOptions = hasLegacyOption ? options[0] : [];
119 // eslint-disable-next-line no-nested-ternary
120 const objectOption = (hasLegacyOption && options.length > 1)
121 ? options[1]
122 : (options.length > 0
123 ? options[0]
124 : {
125 includeFromSettings: false,
126 }
127 );
128 const includeFromSettings = objectOption.includeFromSettings;
129
130 const linkComponents = linkComponentsUtil.getLinkComponents(includeFromSettings ? context : {});
131 parseLegacyOption(linkComponents, legacyOptions);
132
133 return {
134 JSXAttribute(node) {
135 if (shouldVerifyProp(node, linkComponents) && hasJavaScriptProtocol(node)) {
136 report(context, messages.noScriptURL, 'noScriptURL', {
137 node,
138 });
139 }
140 },
141 };
142 },
143};
Note: See TracBrowser for help on using the repository browser.