diff --git a/package.json b/package.json index 1b5f64c..e1c8bf6 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,9 @@ "main": "lib/index.js", "devDependencies": { "babel-cli": "6.x.x", - "babel-preset-es2015": "6.x.x", - "babel-preset-stage-0": "6.x.x", + "babel-preset-es2015": "6.18.0", + "babel-preset-stage-0": "6.16.0", + "babel-preset-react": "6.16.0", "mocha": "2.x.x" }, "scripts": { @@ -25,7 +26,6 @@ "babel-plugin" ], "dependencies": { - "babel-preset-react": "6.x.x", "babel-types": "^6.16.0", "lodash": "4.x.x", "react-docgen": "^2.12.1" diff --git a/src/index.js b/src/index.js index 9081bd4..30c5137 100644 --- a/src/index.js +++ b/src/index.js @@ -8,26 +8,58 @@ export default function ({types: t}) { return { visitor: { Class(path, state) { - if(isReactComponentClass(path)) { - const className = path.node.id.name; - injectReactDocgenInfo(className, path, state, this.file.code, t); + if(!isReactComponentClass(path)) { + return; } + const className = path.node.id.name; + + if(!isExported(path, className, t)){ + return; + } + injectReactDocgenInfo(className, path, state, this.file.code, t); }, 'FunctionDeclaration|FunctionExpression|ArrowFunctionExpression'(path, state) { - if(isStatelessComponent(path)) { - let className = ''; - if(path.parentPath.node.id) { - className = path.parentPath.node.id.name; - } else { - return; - } - injectReactDocgenInfo(className, path, state, this.file.code, t); + if(!isStatelessComponent(path)) { + return; } + if(!path.parentPath.node.id) { + return; + } + const className = path.parentPath.node.id.name; + + if(!isExported(path, className, t)) { + return; + } + injectReactDocgenInfo(className, path, state, this.file.code, t); }, } }; } +function isExported(path, className, t){ + const types = [ + 'ExportDefaultDeclaration', + 'ExportNamedDeclaration' + ]; + + if(path.parentPath.node && + types.some(type => {return path.parentPath.node.type === type;})) { + return true; + } + + const program = path.scope.getProgramParent().path; + return program.get('body').some(path => { + if(path.node.type === 'ExportNamedDeclaration' && + path.node.specifiers && + path.node.specifiers.length) { + return className === path.node.specifiers[0].exported.name; + } else if(path.node.type === 'ExportDefaultDeclaration') { + return className === path.node.declaration.name; + } + return false; + }); +} + function alreadyVisited(program, t) { return program.node.body.some(node => { if(t.isExpressionStatement(node) && diff --git a/test/fixtures/case1/expected.js b/test/fixtures/case1/expected.js index 02ebbe6..d9b887b 100644 --- a/test/fixtures/case1/expected.js +++ b/test/fixtures/case1/expected.js @@ -133,9 +133,9 @@ var CalendarDay = function (_React$Component) { value: function render() { var _this3 = this; - var _props = this.props; - var day = _props.day; - var modifiers = _props.modifiers; + var _props = this.props, + day = _props.day, + modifiers = _props.modifiers; return _react2.default.createElement( diff --git a/test/fixtures/case3/expected.js b/test/fixtures/case3/expected.js index 5797e0c..53b47df 100644 --- a/test/fixtures/case3/expected.js +++ b/test/fixtures/case3/expected.js @@ -11,10 +11,10 @@ var _react2 = _interopRequireDefault(_react); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var Button = function Button(_ref) { - var children = _ref.children; - var onClick = _ref.onClick; - var _ref$style = _ref.style; - var style = _ref$style === undefined ? {} : _ref$style; + var children = _ref.children, + onClick = _ref.onClick, + _ref$style = _ref.style, + style = _ref$style === undefined ? {} : _ref$style; return _react2.default.createElement( 'button', { diff --git a/test/fixtures/case4/expected.js b/test/fixtures/case4/expected.js index aab4cac..8b89fc4 100644 --- a/test/fixtures/case4/expected.js +++ b/test/fixtures/case4/expected.js @@ -11,10 +11,10 @@ var _react2 = _interopRequireDefault(_react); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var Button = function Button(_ref) { - var children = _ref.children; - var onClick = _ref.onClick; - var _ref$style = _ref.style; - var style = _ref$style === undefined ? {} : _ref$style; + var children = _ref.children, + onClick = _ref.onClick, + _ref$style = _ref.style, + style = _ref$style === undefined ? {} : _ref$style; return _react2.default.createElement( 'button', diff --git a/test/fixtures/case5/actual.js b/test/fixtures/case5/actual.js new file mode 100644 index 0000000..0423626 --- /dev/null +++ b/test/fixtures/case5/actual.js @@ -0,0 +1,18 @@ +import React, { PropTypes } from 'react' + +const Second = () => ( +
Sample
+) + +const First = ({ children }) => ( +
+ { children } + +
+) + +First.propTypes = { + children: PropTypes.node +} + +export default First diff --git a/test/fixtures/case5/expected.js b/test/fixtures/case5/expected.js new file mode 100644 index 0000000..42ca70c --- /dev/null +++ b/test/fixtures/case5/expected.js @@ -0,0 +1,55 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Second = function Second() { + return _react2.default.createElement( + 'div', + null, + 'Sample' + ); +}; + +var First = function First(_ref) { + var children = _ref.children; + return _react2.default.createElement( + 'div', + null, + children, + _react2.default.createElement(Second, null) + ); +}; + +First.propTypes = { + children: _react.PropTypes.node +}; + +exports.default = First; +First.__docgenInfo = { + description: '', + props: { + children: { + type: { + name: 'node' + }, + required: false, + description: '' + } + } +}; + +if (typeof STORYBOOK_REACT_CLASSES !== 'undefined') { + STORYBOOK_REACT_CLASSES['test/fixtures/case5/actual.js'] = { + name: 'First', + docgenInfo: First.__docgenInfo, + path: 'test/fixtures/case5/actual.js' + }; +} diff --git a/test/fixtures/case6/actual.js b/test/fixtures/case6/actual.js new file mode 100644 index 0000000..ad1ffc6 --- /dev/null +++ b/test/fixtures/case6/actual.js @@ -0,0 +1,17 @@ +import React from 'react'; +export function hoc (Inner) { + const C1 = (props) => + const C2 = (props) => + return { + C1, + C2 + } +} + +class ActualC1 extends React.Component { + render() { return
} +} + +class ActualC2 extends React.Component { + render() { return
} +} diff --git a/test/fixtures/case6/expected.js b/test/fixtures/case6/expected.js new file mode 100644 index 0000000..81327f4 --- /dev/null +++ b/test/fixtures/case6/expected.js @@ -0,0 +1,72 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +exports.hoc = hoc; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +function hoc(Inner) { + var C1 = function C1(props) { + return _react2.default.createElement(ActualC1, props); + }; + var C2 = function C2(props) { + return _react2.default.createElement(ActualC2, props); + }; + return { + C1: C1, + C2: C2 + }; +} + +var ActualC1 = function (_React$Component) { + _inherits(ActualC1, _React$Component); + + function ActualC1() { + _classCallCheck(this, ActualC1); + + return _possibleConstructorReturn(this, (ActualC1.__proto__ || Object.getPrototypeOf(ActualC1)).apply(this, arguments)); + } + + _createClass(ActualC1, [{ + key: 'render', + value: function render() { + return _react2.default.createElement('div', null); + } + }]); + + return ActualC1; +}(_react2.default.Component); + +var ActualC2 = function (_React$Component2) { + _inherits(ActualC2, _React$Component2); + + function ActualC2() { + _classCallCheck(this, ActualC2); + + return _possibleConstructorReturn(this, (ActualC2.__proto__ || Object.getPrototypeOf(ActualC2)).apply(this, arguments)); + } + + _createClass(ActualC2, [{ + key: 'render', + value: function render() { + return _react2.default.createElement('div', null); + } + }]); + + return ActualC2; +}(_react2.default.Component); diff --git a/test/fixtures/case7/actual.js b/test/fixtures/case7/actual.js new file mode 100644 index 0000000..8fb135a --- /dev/null +++ b/test/fixtures/case7/actual.js @@ -0,0 +1,18 @@ +import React, { PropTypes } from 'react' + +const Second = () => ( +
Sample
+) + +const First = ({ children }) => ( +
+ { children } + +
+) + +First.propTypes = { + children: PropTypes.node +} + +export {First} diff --git a/test/fixtures/case7/expected.js b/test/fixtures/case7/expected.js new file mode 100644 index 0000000..39fb4cf --- /dev/null +++ b/test/fixtures/case7/expected.js @@ -0,0 +1,56 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.First = undefined; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Second = function Second() { + return _react2.default.createElement( + 'div', + null, + 'Sample' + ); +}; + +var First = function First(_ref) { + var children = _ref.children; + return _react2.default.createElement( + 'div', + null, + children, + _react2.default.createElement(Second, null) + ); +}; + +First.propTypes = { + children: _react.PropTypes.node +}; + +exports.First = First; +First.__docgenInfo = { + description: '', + props: { + children: { + type: { + name: 'node' + }, + required: false, + description: '' + } + } +}; + +if (typeof STORYBOOK_REACT_CLASSES !== 'undefined') { + STORYBOOK_REACT_CLASSES['test/fixtures/case7/actual.js'] = { + name: 'First', + docgenInfo: First.__docgenInfo, + path: 'test/fixtures/case7/actual.js' + }; +} diff --git a/test/fixtures/case8/actual.js b/test/fixtures/case8/actual.js new file mode 100644 index 0000000..a2bfff1 --- /dev/null +++ b/test/fixtures/case8/actual.js @@ -0,0 +1,26 @@ +import React from 'react'; + +export const wrapComopnent = (Component) => { + const WrappedComponent = props => ( + + + + ); + return WrappedComponent; +}; + +export class Wrapper extends React.Component { + render() { + const { children } = this.props; + + return ( +
+ {children} +
+ ); + } +} + +Wrapper.propTypes = { + children: React.PropTypes.node.isRequired, +}; diff --git a/test/fixtures/case8/expected.js b/test/fixtures/case8/expected.js new file mode 100644 index 0000000..45d77bf --- /dev/null +++ b/test/fixtures/case8/expected.js @@ -0,0 +1,81 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Wrapper = exports.wrapComopnent = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require("react"); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var wrapComopnent = exports.wrapComopnent = function wrapComopnent(Component) { + var WrappedComponent = function WrappedComponent(props) { + return _react2.default.createElement( + Wrapper, + null, + _react2.default.createElement(Component, null) + ); + }; + return WrappedComponent; +}; + +var Wrapper = exports.Wrapper = function (_React$Component) { + _inherits(Wrapper, _React$Component); + + function Wrapper() { + _classCallCheck(this, Wrapper); + + return _possibleConstructorReturn(this, (Wrapper.__proto__ || Object.getPrototypeOf(Wrapper)).apply(this, arguments)); + } + + _createClass(Wrapper, [{ + key: "render", + value: function render() { + var children = this.props.children; + + + return _react2.default.createElement( + "div", + { className: "error-box" }, + children + ); + } + }]); + + return Wrapper; +}(_react2.default.Component); + +Wrapper.propTypes = { + children: _react2.default.PropTypes.node.isRequired +}; +Wrapper.__docgenInfo = { + description: "", + props: { + children: { + type: { + name: "node" + }, + required: true, + description: "" + } + } +}; + +if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { + STORYBOOK_REACT_CLASSES["test/fixtures/case8/actual.js"] = { + name: "Wrapper", + docgenInfo: Wrapper.__docgenInfo, + path: "test/fixtures/case8/actual.js" + }; +}