1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | 'use strict';
|
21 |
|
22 | var path = require('path');
|
23 |
|
24 | var utils = require('./utils/utils');
|
25 |
|
26 | module.exports = {
|
27 | meta: {
|
28 | schema: [{
|
29 | type: ['object']
|
30 | }]
|
31 | },
|
32 | create: (function() {
|
33 | var fileEnding = '.js';
|
34 |
|
35 | var separators = {
|
36 | dot: '.',
|
37 | dash: '-',
|
38 | underscore: '_'
|
39 | };
|
40 |
|
41 | function createComponentTypeMappings(options) {
|
42 | var componentTypeMappingOptions = options.componentTypeMappings || {};
|
43 |
|
44 | return {
|
45 | module: componentTypeMappingOptions.module || 'module',
|
46 | controller: componentTypeMappingOptions.controller || 'controller',
|
47 | directive: componentTypeMappingOptions.directive || 'directive',
|
48 | filter: componentTypeMappingOptions.filter || 'filter',
|
49 | service: componentTypeMappingOptions.service || 'service',
|
50 | factory: componentTypeMappingOptions.factory || 'service',
|
51 | provider: componentTypeMappingOptions.provider || 'service',
|
52 | value: componentTypeMappingOptions.value || 'service',
|
53 | constant: componentTypeMappingOptions.constant || 'constant',
|
54 | component: componentTypeMappingOptions.component || 'component'
|
55 | };
|
56 | }
|
57 |
|
58 | var filenameUtil = {
|
59 | firstToUpper: function(value) {
|
60 | return value[0].toUpperCase() + value.slice(1);
|
61 | },
|
62 | firstToLower: function(value) {
|
63 | return value[0].toLowerCase() + value.slice(1);
|
64 | },
|
65 | removeTypeSuffix: function(name, type) {
|
66 | var nameTypeLengthDiff = name.length - type.length;
|
67 | if (nameTypeLengthDiff <= 0) {
|
68 | return name;
|
69 | }
|
70 | var typeCamelCase = this.firstToUpper(type);
|
71 | if (name.indexOf(typeCamelCase) === nameTypeLengthDiff) {
|
72 | return name.slice(0, nameTypeLengthDiff);
|
73 | }
|
74 | return name;
|
75 | },
|
76 | removePrefix: function(name, options) {
|
77 | var regName = '^' + options.ignorePrefix.replace(/[\.]/g, '\\$&');
|
78 | regName += options.ignorePrefix.indexOf('\.') === -1 ? '[A-Z]' : '[a-zA-z]';
|
79 | if (new RegExp(regName).test(name)) {
|
80 | return this.firstToLower(name.slice(options.ignorePrefix.length));
|
81 | }
|
82 | return name;
|
83 | },
|
84 | transformComponentName: function(name, options) {
|
85 | var nameStyle = options.nameStyle;
|
86 | var nameSeparator = separators[nameStyle];
|
87 | if (nameSeparator) {
|
88 | var replacement = '$1' + nameSeparator + '$2';
|
89 | name = name.replace(/([a-z0-9])([A-Z])/g, replacement).toLowerCase();
|
90 | }
|
91 | return name;
|
92 | },
|
93 | createExpectedName: function(name, type, options) {
|
94 | var typeSeparator = separators[options.typeSeparator];
|
95 |
|
96 | if (options.ignoreTypeSuffix) {
|
97 | name = filenameUtil.removeTypeSuffix(name, type);
|
98 | }
|
99 | if (options.ignorePrefix && options.ignorePrefix.length > 0) {
|
100 | name = filenameUtil.removePrefix(name, options);
|
101 | }
|
102 | if (options.nameStyle) {
|
103 | name = filenameUtil.transformComponentName(name, options);
|
104 | }
|
105 | if (typeSeparator !== undefined) {
|
106 | name = name + typeSeparator + type;
|
107 | }
|
108 | if (options.casing === 'camel') {
|
109 | name = filenameUtil.firstToLower(name);
|
110 | }
|
111 | if (options.casing === 'pascal') {
|
112 | name = filenameUtil.firstToUpper(name);
|
113 | }
|
114 | return name + fileEnding;
|
115 | }
|
116 | };
|
117 |
|
118 | return function(context) {
|
119 | var options = context.options[0] || {};
|
120 | var filename = path.basename(context.getFilename());
|
121 | var componentTypeMappings = createComponentTypeMappings(options);
|
122 |
|
123 | return {
|
124 | CallExpression: function(node) {
|
125 | if ((utils.isAngularComponent(node) || utils.isAngularComponentDeclaration(node)) && utils.isMemberExpression(node.callee)) {
|
126 | var name = node.arguments[0].value;
|
127 | var type = componentTypeMappings[node.callee.property.name];
|
128 | var expectedName;
|
129 |
|
130 | if (type === undefined || (type === 'service' && node.callee.object.name === '$provide')) {
|
131 | return;
|
132 | }
|
133 |
|
134 | if (!name) {
|
135 | return;
|
136 | }
|
137 | expectedName = filenameUtil.createExpectedName(name, type, options);
|
138 |
|
139 | if (expectedName !== filename) {
|
140 | context.report(node, 'Filename must be "{{expectedName}}"', {
|
141 | expectedName: expectedName
|
142 | });
|
143 | }
|
144 | }
|
145 | }
|
146 | };
|
147 | };
|
148 | }())
|
149 | };
|