diff --git a/docs/rules/jsx-no-undef.md b/docs/rules/jsx-no-undef.md index 00cae519d5..63e927e64d 100644 --- a/docs/rules/jsx-no-undef.md +++ b/docs/rules/jsx-no-undef.md @@ -10,6 +10,17 @@ The following patterns are considered warnings: ; ``` +```jsx +// will ignore Text in the global scope and warn +var Hello = React.createClass({ + render: function() { + return Hello; + } +}); +module.exports = Hello; +``` + + The following patterns are not considered warnings: ```jsx @@ -18,6 +29,30 @@ var Hello = require('./Hello'); ; ``` +## Rule Options + +```js +... +"react/jsx-no-undef": [, { "allowGlobals": }] +... +``` + +### `allowGlobals` + +When `true` the rule will consider the global scope when checking for defined Components. + +The following patterns are considered okay and do not cause warnings: + +```jsx +var Text = require('./Text'); +var Hello = React.createClass({ + render: function() { + return Hello; + } +}); +module.exports = Hello; +``` + ## When Not To Use It If you are not using JSX then you can disable this rule. diff --git a/lib/rules/jsx-no-undef.js b/lib/rules/jsx-no-undef.js index d496081432..4192c51b4d 100644 --- a/lib/rules/jsx-no-undef.js +++ b/lib/rules/jsx-no-undef.js @@ -26,11 +26,22 @@ module.exports = { category: 'Possible Errors', recommended: true }, - schema: [] + schema: [{ + type: 'object', + properties: { + allowGlobals: { + type: 'boolean' + } + }, + additionalProperties: false + }] }, create: function(context) { + var config = context.options[0] || {}; + var allowGlobals = config.allowGlobals || false; + /** * Compare an identifier with the variables declared in the scope * @param {ASTNode} node - Identifier or JSXIdentifier node @@ -38,7 +49,10 @@ module.exports = { */ function checkIdentifierInJSX(node) { var scope = context.getScope(); + var sourceCode = context.getSourceCode(); + var sourceType = sourceCode.ast.sourceType; var variables = scope.variables; + var scopeType = 'global'; var i; var len; @@ -47,7 +61,11 @@ module.exports = { return; } - while (scope.type !== 'global') { + if (!allowGlobals && sourceType === 'module') { + scopeType = 'module'; + } + + while (scope.type !== scopeType) { scope = scope.upper; variables = scope.variables.concat(variables); } diff --git a/tests/lib/rules/jsx-no-undef.js b/tests/lib/rules/jsx-no-undef.js index 1fa3732acd..e5d5c84888 100644 --- a/tests/lib/rules/jsx-no-undef.js +++ b/tests/lib/rules/jsx-no-undef.js @@ -56,6 +56,26 @@ ruleTester.run('jsx-no-undef', rule, { '}' ].join('\n'), parserOptions: parserOptions + }, { + code: 'var React; React.render();', + parserOptions: parserOptions, + globals: { + Text: true + } + }, { + code: [ + 'import Text from "cool-module";', + 'const TextWrapper = function (props) {', + ' return (', + ' ', + ' );', + '};' + ].join('\n'), + options: [{ + allowGlobals: false + }], + parser: 'babel-eslint', + parserOptions: parserOptions }], invalid: [{ code: '/*eslint no-undef:1*/ var React; React.render();', @@ -87,5 +107,31 @@ ruleTester.run('jsx-no-undef', rule, { message: '\'appp\' is not defined.' }], parserOptions: parserOptions + }, { + code: [ + 'const TextWrapper = function (props) {', + ' return (', + ' ', + ' );', + '};', + 'export default TextWrapper;' + ].join('\n'), + errors: [{ + message: '\'Text\' is not defined.' + }], + options: [{ + allowGlobals: false + }], + parser: 'babel-eslint', + parserOptions: parserOptions, + globals: { + Text: true + } + }, { + code: '/*eslint no-undef:1*/ var React; React.render();', + errors: [{ + message: '\'Foo\' is not defined.' + }], + parserOptions: parserOptions }] });