UNPKG

3 kBJavaScriptView Raw
1/**
2 * @fileoverview Forbid certain elements
3 * @author Kenneth Chung
4 */
5
6'use strict';
7
8const has = require('has');
9const docsUrl = require('../util/docsUrl');
10
11// ------------------------------------------------------------------------------
12// Rule Definition
13// ------------------------------------------------------------------------------
14
15module.exports = {
16 meta: {
17 docs: {
18 description: 'Forbid certain elements',
19 category: 'Best Practices',
20 recommended: false,
21 url: docsUrl('forbid-elements')
22 },
23
24 schema: [{
25 type: 'object',
26 properties: {
27 forbid: {
28 type: 'array',
29 items: {
30 anyOf: [
31 {type: 'string'},
32 {
33 type: 'object',
34 properties: {
35 element: {type: 'string'},
36 message: {type: 'string'}
37 },
38 required: ['element'],
39 additionalProperties: false
40 }
41 ]
42 }
43 }
44 },
45 additionalProperties: false
46 }]
47 },
48
49 create(context) {
50 const configuration = context.options[0] || {};
51 const forbidConfiguration = configuration.forbid || [];
52
53 const indexedForbidConfigs = {};
54
55 forbidConfiguration.forEach((item) => {
56 if (typeof item === 'string') {
57 indexedForbidConfigs[item] = {element: item};
58 } else {
59 indexedForbidConfigs[item.element] = item;
60 }
61 });
62
63 function errorMessageForElement(name) {
64 const message = `<${name}> is forbidden`;
65 const additionalMessage = indexedForbidConfigs[name].message;
66
67 if (additionalMessage) {
68 return `${message}, ${additionalMessage}`;
69 }
70
71 return message;
72 }
73
74 function isValidCreateElement(node) {
75 return node.callee
76 && node.callee.type === 'MemberExpression'
77 && node.callee.object.name === 'React'
78 && node.callee.property.name === 'createElement'
79 && node.arguments.length > 0;
80 }
81
82 function reportIfForbidden(element, node) {
83 if (has(indexedForbidConfigs, element)) {
84 context.report({
85 node,
86 message: errorMessageForElement(element)
87 });
88 }
89 }
90
91 return {
92 JSXOpeningElement(node) {
93 reportIfForbidden(context.getSourceCode().getText(node.name), node.name);
94 },
95
96 CallExpression(node) {
97 if (!isValidCreateElement(node)) {
98 return;
99 }
100
101 const argument = node.arguments[0];
102 const argType = argument.type;
103
104 if (argType === 'Identifier' && /^[A-Z_]/.test(argument.name)) {
105 reportIfForbidden(argument.name, argument);
106 } else if (argType === 'Literal' && /^[a-z][^.]*$/.test(argument.value)) {
107 reportIfForbidden(argument.value, argument);
108 } else if (argType === 'MemberExpression') {
109 reportIfForbidden(context.getSourceCode().getText(argument), argument);
110 }
111 }
112 };
113 }
114};