UNPKG

4.01 kBJavaScriptView Raw
1/**
2 * disallow any other directive restrict than 'A' or 'E'
3 *
4 * Not all directive restrictions may be desirable.
5 * Also it might be desirable to define default restrictions, or explicitly not.
6 * The default configuration limits the restrictions `AE` and disallows explicitly specifying a default.
7 * ("directive-restrict": [0, {"restrict": "AE", "explicit": "never"}])
8 *
9 * @styleguideReference {johnpapa} `y074` Restrict to Elements and Attributes
10 * @version 0.12.0
11 * @category bestPractice
12 * @sinceAngularVersion 1.x
13 */
14'use strict';
15
16var utils = require('./utils/utils');
17
18module.exports = {
19 meta: {
20 schema: [{
21 type: 'object',
22 properties: {
23 restrict: {
24 type: 'string',
25 pattern: '^A|C|E|(AC)|(CA)|(AE)|(EA)|(EC)|(CE)|(AEC)|(ACE)|(EAC)|(CAE)|(ACE)|(AEC)|(CAE)|(ACE)|(AEC)$'
26 },
27 explicit: {
28 enum: ['always', 'never']
29 }
30 }
31 }]
32 },
33 create: function(context) {
34 var options = context.options[0] || {};
35 var restrictOpt = options.restrict || 'AE';
36 var explicitRestrict = options.explicit === 'always';
37 var restrictChars = restrictOpt.split('');
38
39 // Example RegExp for AE: /^A?E?$/
40 var restrictRegExp = new RegExp('^' + restrictChars.join('?') + '?$');
41 var foundDirectives = [];
42 var checkedDirectives = [];
43 var defaultRestrictions = ['AE', 'EA'];
44
45 function checkLiteralNode(node) {
46 if (node.type !== 'Literal') {
47 return;
48 }
49 var directiveNode;
50 context.getAncestors().some(function(ancestor) {
51 if (utils.isAngularDirectiveDeclaration(ancestor)) {
52 directiveNode = ancestor;
53 return true;
54 }
55 });
56 // The restrict property was not defined inside of a directive.
57 if (!directiveNode) {
58 return;
59 }
60 if (!explicitRestrict && defaultRestrictions.indexOf(node.value) !== -1) {
61 context.report(node, 'No need to explicitly specify a default directive restriction');
62 return;
63 }
64
65 if (!restrictRegExp.test(node.value)) {
66 context.report(directiveNode, 'Disallowed directive restriction. It must be one of {{allowed}} in that order', {
67 allowed: restrictOpt
68 });
69 }
70
71 checkedDirectives.push(directiveNode);
72 }
73
74 return {
75 CallExpression: function(node) {
76 if (utils.isAngularDirectiveDeclaration(node)) {
77 foundDirectives.push(node);
78 }
79 },
80 AssignmentExpression: function(node) {
81 // Only check for literal member property assignments.
82 if (node.left.type !== 'MemberExpression') {
83 return;
84 }
85 // Only check setting properties named 'restrict'.
86 if (node.left.property.name !== 'restrict') {
87 return;
88 }
89 checkLiteralNode(node.right);
90 },
91 Property: function(node) {
92 // This only checks for objects which have defined a literal restrict property.
93 if (node.key.name !== 'restrict') {
94 return;
95 }
96 checkLiteralNode(node.value);
97 },
98 'Program:exit': function() {
99 if (explicitRestrict) {
100 foundDirectives.filter(function(directive) {
101 return checkedDirectives.indexOf(directive) < 0;
102 }).forEach(function(directiveNode) {
103 context.report(directiveNode, 'Missing directive restriction');
104 });
105 }
106 }
107 };
108 }
109};