UNPKG

2.84 kBJavaScriptView Raw
1/**
2 * @fileoverview Forbid certain props on components
3 * @author Joe Lencioni
4 */
5
6'use strict';
7
8const docsUrl = require('../util/docsUrl');
9
10// ------------------------------------------------------------------------------
11// Constants
12// ------------------------------------------------------------------------------
13
14const DEFAULTS = ['className', 'style'];
15
16// ------------------------------------------------------------------------------
17// Rule Definition
18// ------------------------------------------------------------------------------
19
20module.exports = {
21 meta: {
22 docs: {
23 description: 'Forbid certain props on components',
24 category: 'Best Practices',
25 recommended: false,
26 url: docsUrl('forbid-component-props')
27 },
28
29 schema: [{
30 type: 'object',
31 properties: {
32 forbid: {
33 type: 'array',
34 items: {
35 oneOf: [{
36 type: 'string'
37 }, {
38 type: 'object',
39 properties: {
40 propName: {
41 type: 'string'
42 },
43 allowedFor: {
44 type: 'array',
45 uniqueItems: true,
46 items: {
47 type: 'string'
48 }
49 },
50 message: {
51 type: 'string'
52 }
53 }
54 }]
55 }
56 }
57 }
58 }]
59 },
60
61 create(context) {
62 const configuration = context.options[0] || {};
63 const forbid = new Map((configuration.forbid || DEFAULTS).map((value) => {
64 const propName = typeof value === 'string' ? value : value.propName;
65 const options = {
66 allowList: typeof value === 'string' ? [] : (value.allowedFor || []),
67 message: typeof value === 'string' ? null : value.message
68 };
69 return [propName, options];
70 }));
71
72 function isForbidden(prop, tagName) {
73 const options = forbid.get(prop);
74 const allowList = options ? options.allowList : undefined;
75 // if the tagName is undefined (`<this.something>`), we assume it's a forbidden element
76 return typeof allowList !== 'undefined' && (typeof tagName === 'undefined' || allowList.indexOf(tagName) === -1);
77 }
78
79 return {
80 JSXAttribute(node) {
81 const tag = node.parent.name.name;
82 if (tag && tag[0] !== tag[0].toUpperCase()) {
83 // This is a DOM node, not a Component, so exit.
84 return;
85 }
86
87 const prop = node.name.name;
88
89 if (!isForbidden(prop, tag)) {
90 return;
91 }
92
93 const customMessage = forbid.get(prop).message;
94 const errorMessage = customMessage || `Prop \`${prop}\` is forbidden on Components`;
95
96 context.report({
97 node,
98 message: errorMessage
99 });
100 }
101 };
102 }
103};