source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/jsx-props-no-spreading.js@ d565449

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

Update repo after prototype presentation

  • Property mode set to 100644
File size: 4.0 KB
RevLine 
[d565449]1/**
2 * @fileoverview Prevent JSX prop spreading
3 * @author Ashish Gambhir
4 */
5
6'use strict';
7
8const docsUrl = require('../util/docsUrl');
9const report = require('../util/report');
10
11// ------------------------------------------------------------------------------
12// Constants
13// ------------------------------------------------------------------------------
14
15const OPTIONS = { ignore: 'ignore', enforce: 'enforce' };
16const DEFAULTS = {
17 html: OPTIONS.enforce,
18 custom: OPTIONS.enforce,
19 explicitSpread: OPTIONS.enforce,
20 exceptions: [],
21};
22
23const isException = (tag, allExceptions) => allExceptions.indexOf(tag) !== -1;
24const isProperty = (property) => property.type === 'Property';
25const getTagNameFromMemberExpression = (node) => {
26 if (node.property.parent) {
27 return `${node.property.parent.object.name}.${node.property.name}`;
28 }
29 // for eslint 3
30 return `${node.object.name}.${node.property.name}`;
31};
32
33// ------------------------------------------------------------------------------
34// Rule Definition
35// ------------------------------------------------------------------------------
36
37const messages = {
38 noSpreading: 'Prop spreading is forbidden',
39};
40
41/** @type {import('eslint').Rule.RuleModule} */
42module.exports = {
43 meta: {
44 docs: {
45 description: 'Disallow JSX prop spreading',
46 category: 'Best Practices',
47 recommended: false,
48 url: docsUrl('jsx-props-no-spreading'),
49 },
50
51 messages,
52
53 schema: [{
54 allOf: [{
55 type: 'object',
56 properties: {
57 html: {
58 enum: [OPTIONS.enforce, OPTIONS.ignore],
59 },
60 custom: {
61 enum: [OPTIONS.enforce, OPTIONS.ignore],
62 },
63 exceptions: {
64 type: 'array',
65 items: {
66 type: 'string',
67 uniqueItems: true,
68 },
69 },
70 },
71 }, {
72 not: {
73 type: 'object',
74 required: ['html', 'custom'],
75 properties: {
76 html: {
77 enum: [OPTIONS.ignore],
78 },
79 custom: {
80 enum: [OPTIONS.ignore],
81 },
82 exceptions: {
83 type: 'array',
84 minItems: 0,
85 maxItems: 0,
86 },
87 },
88 },
89 }],
90 }],
91 },
92
93 create(context) {
94 const configuration = context.options[0] || {};
95 const ignoreHtmlTags = (configuration.html || DEFAULTS.html) === OPTIONS.ignore;
96 const ignoreCustomTags = (configuration.custom || DEFAULTS.custom) === OPTIONS.ignore;
97 const ignoreExplicitSpread = (configuration.explicitSpread || DEFAULTS.explicitSpread) === OPTIONS.ignore;
98 const exceptions = configuration.exceptions || DEFAULTS.exceptions;
99 return {
100 JSXSpreadAttribute(node) {
101 const jsxOpeningElement = node.parent.name;
102 const type = jsxOpeningElement.type;
103
104 let tagName;
105 if (type === 'JSXIdentifier') {
106 tagName = jsxOpeningElement.name;
107 } else if (type === 'JSXMemberExpression') {
108 tagName = getTagNameFromMemberExpression(jsxOpeningElement);
109 } else {
110 tagName = undefined;
111 }
112
113 const isHTMLTag = tagName && tagName[0] !== tagName[0].toUpperCase();
114 const isCustomTag = tagName && (tagName[0] === tagName[0].toUpperCase() || tagName.includes('.'));
115 if (
116 isHTMLTag
117 && ((ignoreHtmlTags && !isException(tagName, exceptions))
118 || (!ignoreHtmlTags && isException(tagName, exceptions)))
119 ) {
120 return;
121 }
122 if (
123 isCustomTag
124 && ((ignoreCustomTags && !isException(tagName, exceptions))
125 || (!ignoreCustomTags && isException(tagName, exceptions)))
126 ) {
127 return;
128 }
129 if (
130 ignoreExplicitSpread
131 && node.argument.type === 'ObjectExpression'
132 && node.argument.properties.every(isProperty)
133 ) {
134 return;
135 }
136 report(context, messages.noSpreading, 'noSpreading', {
137 node,
138 });
139 },
140 };
141 },
142};
Note: See TracBrowser for help on using the repository browser.