diff --git a/README.md b/README.md index 2f77dd8..a6ae696 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,15 @@ Modify your `.eslintrc` file to load the plugin and enable the rules you want to A rule to enforce a certain file naming convention using a regular expression. -The convention can be configured using a regular expression (the default is `camelCase.js`): +The convention can be configured using a regular expression (the default is `camelCase.js`). Additionally +exporting files can be ignored with a second configuration parameter. ```json -"filenames/match-regex": [2, "^[a-z_]+$"] +"filenames/match-regex": [2, "^[a-z_]+$", true] ``` With these configuration options, `camelCase.js` will be reported as an error while `snake_case.js` will pass. +Additionally the files that have a named default export (according to the logic in the `match-exported` rule) will be ignored. ### Matching Exported Values (match-exported) diff --git a/lib/common/getExportedName.js b/lib/common/getExportedName.js new file mode 100644 index 0000000..e8fc6cd --- /dev/null +++ b/lib/common/getExportedName.js @@ -0,0 +1,32 @@ +function getNodeName(node) { + if (node.type === "Identifier") { + return node.name; + } + + if (node.id && node.id.type === "Identifier") { + return node.id.name; + } +} + +module.exports = function getExportedName(programNode) { + for (var i = 0; i < programNode.body.length; i += 1) { + var node = programNode.body[i]; + + // export default ... + if (node.type === "ExportDefaultDeclaration") { + return getNodeName(node.declaration); + } + + // module.exports = ... + if (node.type === "ExpressionStatement" && + node.expression.type === "AssignmentExpression" && + node.expression.left.type === "MemberExpression" && + node.expression.left.object.type === "Identifier" && + node.expression.left.object.name === "module" && + node.expression.left.property.type === "Identifier" && + node.expression.left.property.name === "exports" + ) { + return getNodeName(node.expression.right); + } + } +}; \ No newline at end of file diff --git a/lib/common/isIgnoredFilename.js b/lib/common/isIgnoredFilename.js index 98256c1..e6cfec6 100644 --- a/lib/common/isIgnoredFilename.js +++ b/lib/common/isIgnoredFilename.js @@ -2,4 +2,4 @@ var ignoredFilenames = [ "", "" ]; module.exports = function isIndexFile(filename) { return ignoredFilenames.indexOf(filename) !== -1; -}; \ No newline at end of file +}; diff --git a/lib/common/isIndexFile.js b/lib/common/isIndexFile.js index 1048d88..d8863df 100644 --- a/lib/common/isIndexFile.js +++ b/lib/common/isIndexFile.js @@ -1,3 +1,3 @@ module.exports = function isIndexFile(parsed) { return parsed.name === 'index'; -}; \ No newline at end of file +}; diff --git a/lib/common/parseFilename.js b/lib/common/parseFilename.js index b60e5ea..dc701c9 100644 --- a/lib/common/parseFilename.js +++ b/lib/common/parseFilename.js @@ -9,4 +9,4 @@ module.exports = function parseFilename(filename) { ext: ext, name: path.basename(filename, ext) } -}; \ No newline at end of file +}; diff --git a/lib/rules/match-exported.js b/lib/rules/match-exported.js index f9eec42..0639cf8 100644 --- a/lib/rules/match-exported.js +++ b/lib/rules/match-exported.js @@ -10,41 +10,9 @@ var path = require('path'), parseFilename = require('../common/parseFilename'), isIgnoredFilename = require('../common/isIgnoredFilename'), + getExportedName = require('../common/getExportedName'), isIndexFile = require('../common/isIndexFile'); -function getNodeName(node) { - if (node.type === "Identifier") { - return node.name; - } - - if (node.id && node.id.type === "Identifier") { - return node.id.name; - } -} - -function getExportedName(programNode) { - for (var i = 0; i < programNode.body.length; i += 1) { - var node = programNode.body[i]; - - // export default ... - if (node.type === "ExportDefaultDeclaration") { - return getNodeName(node.declaration); - } - - // module.exports = ... - if (node.type === "ExpressionStatement" && - node.expression.type === "AssignmentExpression" && - node.expression.left.type === "MemberExpression" && - node.expression.left.object.type === "Identifier" && - node.expression.left.object.name === "module" && - node.expression.left.property.type === "Identifier" && - node.expression.left.property.name === "exports" - ) { - return getNodeName(node.expression.right); - } - } -} - function getStringToCheckAgainstExport(parsed) { var dirArray = parsed.dir.split(path.sep); var lastDirectory = dirArray[dirArray.length - 1]; diff --git a/lib/rules/match-regex.js b/lib/rules/match-regex.js index 889e95f..fd88269 100644 --- a/lib/rules/match-regex.js +++ b/lib/rules/match-regex.js @@ -11,11 +11,13 @@ var path = require("path"), parseFilename = require('../common/parseFilename'), + getExportedName = require('../common/getExportedName'), isIgnoredFilename = require('../common/isIgnoredFilename'); module.exports = function(context) { var defaultRegexp = /^([a-z0-9]+)([A-Z][a-z0-9]+)*$/g, - conventionRegexp = context.options[0] ? new RegExp(context.options[0]) : defaultRegexp; + conventionRegexp = context.options[0] ? new RegExp(context.options[0]) : defaultRegexp, + ignoreExporting = context.options[1] ? context.options[1] : false; return { "Program": function(node) { @@ -23,9 +25,11 @@ module.exports = function(context) { absoluteFilename = path.resolve(filename), parsed = parseFilename(absoluteFilename), shouldIgnore = isIgnoredFilename(filename), + isExporting = Boolean(getExportedName(node)), matchesRegex = conventionRegexp.test(parsed.name); if (shouldIgnore) return; + if (ignoreExporting && isExporting) return; if (!matchesRegex) { context.report(node, "Filename '{{name}}' does not match the naming convention.", { name: parsed.base diff --git a/test/rules/match-regex.js b/test/rules/match-regex.js index fda0142..6adb6b8 100644 --- a/test/rules/match-regex.js +++ b/test/rules/match-regex.js @@ -1,7 +1,8 @@ var regexRule = require("../../lib/rules/match-regex"), RuleTester = require("eslint").RuleTester; -var testCode = "var foo = 'bar';", +var exportingCode = 'module.exports = foo', + testCode = "var foo = 'bar';", ruleTester = new RuleTester(); ruleTester.run("lib/rules/match-regex", regexRule, { @@ -41,19 +42,14 @@ ruleTester.run("lib/rules/match-regex", regexRule, { filename: "/foo/dir/fooBar.js" }, { - code: testCode, - filename: "/some/dir/exported.js", - options: [ null, "match-regex-and-exported" ] - }, - { - code: testCode, - filename: "/some/dir/exported.js", - options: [ null, "match-regex-or-exported" ] + code: exportingCode, + filename: "foo_bar.js", + options: [ null, true ] }, { - code: testCode, - filename: "/some/dir/exported.js", - options: [ null, "match-exported-or-regex" ] + code: exportingCode, + filename: "fooBar.js", + options: [ "^[a-z_]$", true ] } ],