all files / eslint-plugin-angular/rules/ file-name.js

100% Statements 50/50
96.97% Branches 32/33
100% Functions 9/9
100% Lines 50/50
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                                                                        10×         12× 12×   10× 10×                   36×   36× 12×   36×   36×   36× 27×   36×       46× 46×   46×     50× 38× 38× 38×   38×     36×   36× 10×                  
/**
 * require and specify a consistent component name pattern
 *
 * All your file names should match the angular component name.
 * The second parameter can be a config object [2, {nameStyle: 'dash', typeSeparator: 'dot', ignoreTypeSuffix: true, ignorePrefix: 'ui'}] to match 'avenger-profile.directive.js' or 'avanger-api.service.js'.
 * Possible values for 'typeSeparator' and 'nameStyle' are 'dot', 'dash' and 'underscore'.
 * The options 'ignoreTypeSuffix' ignores camel cased suffixes like 'someController' or 'myService' and 'ignorePrefix' ignores namespace prefixes like 'ui'.
 *
 * @styleguideReference {johnpapa} `y120` Naming - Naming Guidelines
 * @styleguideReference {johnpapa} `y121` Naming - Feature File Names
 * @version 0.7.0
 * @category naming
 */
'use strict';
 
var path = require('path');
 
var utils = require('./utils/utils');
 
module.exports = (function() {
    var fileEnding = '.js';
 
    var separators = {
        dot: '.',
        dash: '-',
        underscore: '_'
    };
 
    var componentTypeMappings = {
        module: 'module',
        controller: 'controller',
        directive: 'directive',
        filter: 'filter',
        service: 'service',
        factory: 'service',
        provider: 'service',
        value: 'service',
        constant: 'constant',
        component: 'component'
    };
 
    var filenameUtil = {
        firstToUpper: function(value) {
            return value[0].toUpperCase() + value.slice(1);
        },
        firstToLower: function(value) {
            return value[0].toLowerCase() + value.slice(1);
        },
        removeTypeSuffix: function(name, type) {
            var nameTypeLengthDiff = name.length - type.length;
            if (nameTypeLengthDiff <= 0) {
                return name;
            }
            var typeCamelCase = this.firstToUpper(type);
            if (name.indexOf(typeCamelCase) === nameTypeLengthDiff) {
                return name.slice(0, nameTypeLengthDiff);
            }
            return name;
        },
        removePrefix: function(name, options) {
            var regName = '^' + options.ignorePrefix.replace(/[\.]/g, '\\$&');
            regName += options.ignorePrefix.indexOf('\.') === -1 ? '[A-Z]' : '[a-zA-z]';
            if (new RegExp(regName).test(name)) {
                return this.firstToLower(name.slice(options.ignorePrefix.length));
            }
            return name;
        },
        transformComponentName: function(name, options) {
            var nameStyle = options.nameStyle;
            var nameSeparator = separators[nameStyle];
            Eif (nameSeparator) {
                var replacement = '$1' + nameSeparator + '$2';
                name = name.replace(/([a-z0-9])([A-Z])/g, replacement).toLowerCase();
            }
            return name;
        },
        createExpectedName: function(name, type, options) {
            var typeSeparator = separators[options.typeSeparator];
 
            if (options.ignoreTypeSuffix) {
                name = filenameUtil.removeTypeSuffix(name, type);
            }
            if (options.ignorePrefix && options.ignorePrefix.length > 0) {
                name = filenameUtil.removePrefix(name, options);
            }
            if (options.nameStyle) {
                name = filenameUtil.transformComponentName(name, options);
            }
            if (typeSeparator !== undefined) {
                name = name + typeSeparator + type;
            }
            return name + fileEnding;
        }
    };
 
    return function(context) {
        var options = context.options[0] || {};
        var filename = path.basename(context.getFilename());
 
        return {
 
            CallExpression: function(node) {
                if (utils.isAngularComponent(node) && utils.isMemberExpression(node.callee)) {
                    var name = node.arguments[0].value;
                    var type = componentTypeMappings[node.callee.property.name];
                    var expectedName;
 
                    if (type === undefined || (type === 'service' && node.callee.object.name === '$provide')) {
                        return;
                    }
 
                    expectedName = filenameUtil.createExpectedName(name, type, options);
 
                    if (expectedName !== filename) {
                        context.report(node, 'Filename must be "{{expectedName}}"', {
                            expectedName: expectedName
                        });
                    }
                }
            }
        };
    };
}());