diff --git a/.gitignore b/.gitignore index f24b23e..1f0ec97 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules *.log lib -*.DS_Store \ No newline at end of file +*.DS_Store +.vscode diff --git a/src/index.js b/src/index.js index 7166272..5b84106 100644 --- a/src/index.js +++ b/src/index.js @@ -65,7 +65,14 @@ function injectReactDocgenInfo(path, state, code, t) { t.memberExpression(t.identifier(exportName), t.identifier('__docgenInfo')), docNode )); - program.pushContainer('body', docgenInfo); + + const exportPath = program.get('body').find((node) => isExportCurrent(node, exportName, t)); + + if (exportPath) { + exportPath.insertBefore(docgenInfo); + } else { + program.pushContainer('body', docgenInfo); + } injectDocgenGlobal(exportName, path, state, t); }); @@ -151,3 +158,34 @@ function buildObjectExpression(obj, t){ return t.nullLiteral(); } } + +function getComponentFromHoC(path) { + if (path.isCallExpression()) { + return getComponentFromHoC(path.get('arguments.0')); + } + return path.isIdentifier() ? path.node.name : null; +} + +function isExportCurrent(path, exportName, t) { + if (t.isExportDefaultDeclaration(path)) { + const decl = path.get('declaration'); + + const identifier = ( + decl.isIdentifier() // export default MyComp + ? decl.node.name + : getComponentFromHoC(decl) // export default withHoC(MyComp) + ); + + if (identifier === exportName) { + return true + } + } + + if (t.isExportNamedDeclaration(path)) { + return path.get('specifiers').find((sp) => ( + sp.node.exported.name === exportName + )) + } + + return false +} diff --git a/test/fixtures/case2/expected.js b/test/fixtures/case2/expected.js index ad39945..650330c 100644 --- a/test/fixtures/case2/expected.js +++ b/test/fixtures/case2/expected.js @@ -56,8 +56,6 @@ function (_React$Component) { ErrorBox.propTypes = { children: _react["default"].PropTypes.node.isRequired }; -var _default = ErrorBox; -exports["default"] = _default; ErrorBox.__docgenInfo = { "description": "", "methods": [], @@ -72,6 +70,8 @@ ErrorBox.__docgenInfo = { } } }; +var _default = ErrorBox; +exports["default"] = _default; if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/case2/actual.js"] = { @@ -79,4 +79,4 @@ if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { docgenInfo: ErrorBox.__docgenInfo, path: "test/fixtures/case2/actual.js" }; -} \ No newline at end of file +} diff --git a/test/fixtures/case3/expected.js b/test/fixtures/case3/expected.js index de356e5..cd1bf42 100644 --- a/test/fixtures/case3/expected.js +++ b/test/fixtures/case3/expected.js @@ -25,17 +25,6 @@ Button.propTypes = { onClick: _react["default"].PropTypes.func, style: _react["default"].PropTypes.object }; -var _default = Button; -exports["default"] = _default; -var A; -A = [1, 2, 2, 2]; - -function abc() { - var c = function cef() { - A = 'str'; - }; -} - Button.__docgenInfo = { "description": "", "methods": [], @@ -68,6 +57,16 @@ Button.__docgenInfo = { } } }; +var _default = Button; +exports["default"] = _default; +var A; +A = [1, 2, 2, 2]; + +function abc() { + var c = function cef() { + A = 'str'; + }; +} if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/case3/actual.js"] = { diff --git a/test/fixtures/case4/expected.js b/test/fixtures/case4/expected.js index a828624..3450869 100644 --- a/test/fixtures/case4/expected.js +++ b/test/fixtures/case4/expected.js @@ -25,17 +25,6 @@ Button.propTypes = { onClick: _react["default"].PropTypes.func, style: _react["default"].PropTypes.object }; -var _default = Button; -exports["default"] = _default; -var A; -A = [1, 2, 2, 2]; - -function abc() { - var c = function cef() { - A = 'str'; - }; -} - Button.__docgenInfo = { "description": "", "methods": [], @@ -68,6 +57,16 @@ Button.__docgenInfo = { } } }; +var _default = Button; +exports["default"] = _default; +var A; +A = [1, 2, 2, 2]; + +function abc() { + var c = function cef() { + A = 'str'; + }; +} if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/case4/actual.js"] = { @@ -75,4 +74,4 @@ if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { docgenInfo: Button.__docgenInfo, path: "test/fixtures/case4/actual.js" }; -} \ No newline at end of file +} diff --git a/test/fixtures/case5/expected.js b/test/fixtures/case5/expected.js index c74d450..6b9e9d1 100644 --- a/test/fixtures/case5/expected.js +++ b/test/fixtures/case5/expected.js @@ -21,8 +21,6 @@ var First = function First(_ref) { First.propTypes = { children: _react.PropTypes.node }; -var _default = First; -exports["default"] = _default; First.__docgenInfo = { "description": "", "methods": [], @@ -37,6 +35,8 @@ First.__docgenInfo = { } } }; +var _default = First; +exports["default"] = _default; if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/case5/actual.js"] = { @@ -44,4 +44,4 @@ if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { docgenInfo: First.__docgenInfo, path: "test/fixtures/case5/actual.js" }; -} \ No newline at end of file +} diff --git a/test/fixtures/example/expected.js b/test/fixtures/example/expected.js index b1b107d..2b359f0 100644 --- a/test/fixtures/example/expected.js +++ b/test/fixtures/example/expected.js @@ -64,13 +64,13 @@ function (_Component) { return App; }(_react.Component); -var _default = App; -exports["default"] = _default; App.__docgenInfo = { "description": "", "methods": [], "displayName": "App" }; +var _default = App; +exports["default"] = _default; if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/example/actual.js"] = { diff --git a/test/fixtures/flowType/expected.js b/test/fixtures/flowType/expected.js index 25a1306..5d44fc9 100644 --- a/test/fixtures/flowType/expected.js +++ b/test/fixtures/flowType/expected.js @@ -66,8 +66,6 @@ function (_React$Component) { return FlowTypeButton; }(_react["default"].Component); -var _default = FlowTypeButton; -exports["default"] = _default; FlowTypeButton.__docgenInfo = { "description": "", "methods": [{ @@ -107,6 +105,8 @@ FlowTypeButton.__docgenInfo = { } } }; +var _default = FlowTypeButton; +exports["default"] = _default; if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/flowType/actual.js"] = { diff --git a/test/fixtures/functionDeclaration/expected.js b/test/fixtures/functionDeclaration/expected.js index 6af94e1..498e6c0 100644 --- a/test/fixtures/functionDeclaration/expected.js +++ b/test/fixtures/functionDeclaration/expected.js @@ -21,8 +21,6 @@ function FuncDeclaration(_ref) { FuncDeclaration.propTypes = { children: _react.PropTypes.node }; -var _default = FuncDeclaration; -exports["default"] = _default; FuncDeclaration.__docgenInfo = { "description": "", "methods": [], @@ -37,6 +35,8 @@ FuncDeclaration.__docgenInfo = { } } }; +var _default = FuncDeclaration; +exports["default"] = _default; if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/functionDeclaration/actual.js"] = { diff --git a/test/fixtures/hoc-function/expected.js b/test/fixtures/hoc-function/expected.js index 8ee411b..0d380f1 100644 --- a/test/fixtures/hoc-function/expected.js +++ b/test/fixtures/hoc-function/expected.js @@ -30,10 +30,6 @@ TestComponent.propTypes = { /** Called on click */ onClick: _propTypes["default"].func }; - -var _default = (0, _reactRedux.connect)(_testSelector.mapStateToProps, _testSelector.mapDispatchToProps)(TestComponent); - -exports["default"] = _default; TestComponent.__docgenInfo = { "description": "", "methods": [], @@ -56,6 +52,10 @@ TestComponent.__docgenInfo = { } }; +var _default = (0, _reactRedux.connect)(_testSelector.mapStateToProps, _testSelector.mapDispatchToProps)(TestComponent); + +exports["default"] = _default; + if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/hoc-function/actual.js"] = { name: "TestComponent", diff --git a/test/fixtures/hoc-multiple/actual.js b/test/fixtures/hoc-multiple/actual.js index b0f335a..b1eb3f1 100644 --- a/test/fixtures/hoc-multiple/actual.js +++ b/test/fixtures/hoc-multiple/actual.js @@ -17,3 +17,14 @@ Component.propTypes = { } export default withHoc()(deeperHoc(Component)) + +class CompA extends React.Component { + render() { return null } +} + +CompA.propTypes = { + /** Fancy styles in here */ + myProp: React.PropTypes.object, +} + +export { CompA } diff --git a/test/fixtures/hoc-multiple/expected.js b/test/fixtures/hoc-multiple/expected.js index af058a7..e751650 100644 --- a/test/fixtures/hoc-multiple/expected.js +++ b/test/fixtures/hoc-multiple/expected.js @@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports["default"] = void 0; +exports.CompA = exports["default"] = void 0; function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } @@ -59,10 +59,6 @@ Component.propTypes = { /** Fancy styles in here */ style: React.PropTypes.object }; - -var _default = withHoc()(deeperHoc(Component)); - -exports["default"] = _default; Component.__docgenInfo = { "description": "Super tiny component", "methods": [], @@ -95,10 +91,64 @@ Component.__docgenInfo = { } }; +var _default = withHoc()(deeperHoc(Component)); + +exports["default"] = _default; + +var CompA = +/*#__PURE__*/ +function (_React$Component2) { + _inherits(CompA, _React$Component2); + + function CompA() { + _classCallCheck(this, CompA); + + return _possibleConstructorReturn(this, _getPrototypeOf(CompA).apply(this, arguments)); + } + + _createClass(CompA, [{ + key: "render", + value: function render() { + return null; + } + }]); + + return CompA; +}(React.Component); + +exports.CompA = CompA; +CompA.propTypes = { + /** Fancy styles in here */ + myProp: React.PropTypes.object +}; +CompA.__docgenInfo = { + "description": "", + "methods": [], + "displayName": "CompA", + "props": { + "myProp": { + "type": { + "name": "custom", + "raw": "React.PropTypes.object" + }, + "required": false, + "description": "Fancy styles in here" + } + } +}; + if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/hoc-multiple/actual.js"] = { name: "Component", docgenInfo: Component.__docgenInfo, path: "test/fixtures/hoc-multiple/actual.js" }; -} \ No newline at end of file +} + +if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { + STORYBOOK_REACT_CLASSES["test/fixtures/hoc-multiple/actual.js"] = { + name: "CompA", + docgenInfo: CompA.__docgenInfo, + path: "test/fixtures/hoc-multiple/actual.js" + }; +} diff --git a/test/fixtures/hoc/expected.js b/test/fixtures/hoc/expected.js index 00fc67d..4c4d4e1 100644 --- a/test/fixtures/hoc/expected.js +++ b/test/fixtures/hoc/expected.js @@ -59,10 +59,6 @@ Component.propTypes = { /** Fancy styles in here */ style: React.PropTypes.object }; - -var _default = withHoc(Component); - -exports["default"] = _default; Component.__docgenInfo = { "description": "Super tiny component", "methods": [], @@ -95,10 +91,14 @@ Component.__docgenInfo = { } }; +var _default = withHoc(Component); + +exports["default"] = _default; + if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/hoc/actual.js"] = { name: "Component", docgenInfo: Component.__docgenInfo, path: "test/fixtures/hoc/actual.js" }; -} \ No newline at end of file +} diff --git a/test/fixtures/multiple-exports/expected.js b/test/fixtures/multiple-exports/expected.js index d78d39f..528befd 100644 --- a/test/fixtures/multiple-exports/expected.js +++ b/test/fixtures/multiple-exports/expected.js @@ -56,6 +56,20 @@ function (_React$Component) { ErrorBox.propTypes = { children: _react["default"].PropTypes.node.isRequired }; +ErrorBox.__docgenInfo = { + "description": "", + "methods": [], + "displayName": "ErrorBox", + "props": { + "children": { + "type": { + "name": "node" + }, + "required": true, + "description": "" + } + } +}; var _default = ErrorBox; exports["default"] = _default; @@ -87,12 +101,12 @@ exports.ErrorBox2 = ErrorBox2; ErrorBox2.propTypes = { children2: _react["default"].PropTypes.node.isRequired }; -ErrorBox.__docgenInfo = { +ErrorBox2.__docgenInfo = { "description": "", "methods": [], - "displayName": "ErrorBox", + "displayName": "ErrorBox2", "props": { - "children": { + "children2": { "type": { "name": "node" }, @@ -110,25 +124,10 @@ if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { }; } -ErrorBox2.__docgenInfo = { - "description": "", - "methods": [], - "displayName": "ErrorBox2", - "props": { - "children2": { - "type": { - "name": "node" - }, - "required": true, - "description": "" - } - } -}; - if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/multiple-exports/actual.js"] = { name: "ErrorBox2", docgenInfo: ErrorBox2.__docgenInfo, path: "test/fixtures/multiple-exports/actual.js" }; -} \ No newline at end of file +} diff --git a/test/fixtures/multipleExports2/expected.js b/test/fixtures/multipleExports2/expected.js index 118be05..1b37a79 100644 --- a/test/fixtures/multipleExports2/expected.js +++ b/test/fixtures/multipleExports2/expected.js @@ -137,8 +137,6 @@ Breadcrumb.defaultProps = { className: '', foreColor: '' }; -var _default = Breadcrumb; -exports["default"] = _default; Breadcrumb.__docgenInfo = { "description": "", "methods": [], @@ -263,6 +261,8 @@ Breadcrumb.__docgenInfo = { } } }; +var _default = Breadcrumb; +exports["default"] = _default; if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/multipleExports2/actual.js"] = { @@ -270,4 +270,4 @@ if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { docgenInfo: Breadcrumb.__docgenInfo, path: "test/fixtures/multipleExports2/actual.js" }; -} \ No newline at end of file +} diff --git a/test/fixtures/reactCreateElement/expected.js b/test/fixtures/reactCreateElement/expected.js index f6c1aea..6ac4c00 100644 --- a/test/fixtures/reactCreateElement/expected.js +++ b/test/fixtures/reactCreateElement/expected.js @@ -32,8 +32,6 @@ Kitten.defaultProps = { isWide: false, isLong: false }; -var _default = Kitten; -exports["default"] = _default; Kitten.__docgenInfo = { "description": "", "methods": [], @@ -63,6 +61,8 @@ Kitten.__docgenInfo = { } } }; +var _default = Kitten; +exports["default"] = _default; if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/reactCreateElement/actual.js"] = { @@ -70,4 +70,4 @@ if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { docgenInfo: Kitten.__docgenInfo, path: "test/fixtures/reactCreateElement/actual.js" }; -} \ No newline at end of file +} diff --git a/test/fixtures/with-custom-handlers/expected.js b/test/fixtures/with-custom-handlers/expected.js index 2f12aa1..5e59b5b 100644 --- a/test/fixtures/with-custom-handlers/expected.js +++ b/test/fixtures/with-custom-handlers/expected.js @@ -57,8 +57,6 @@ ErrorBox.propTypes = { /** @deprecated This is the description for prop */ deprecatedProp: _react["default"].PropTypes.number }; -var _default = ErrorBox; -exports["default"] = _default; ErrorBox.__docgenInfo = { "description": "", "methods": [], @@ -74,6 +72,8 @@ ErrorBox.__docgenInfo = { } } }; +var _default = ErrorBox; +exports["default"] = _default; if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { STORYBOOK_REACT_CLASSES["test/fixtures/with-custom-handlers/actual.js"] = { @@ -81,4 +81,4 @@ if (typeof STORYBOOK_REACT_CLASSES !== "undefined") { docgenInfo: ErrorBox.__docgenInfo, path: "test/fixtures/with-custom-handlers/actual.js" }; -} \ No newline at end of file +} diff --git a/test/index.js b/test/index.js index 3291d9f..442421f 100644 --- a/test/index.js +++ b/test/index.js @@ -8,7 +8,7 @@ function trim(str) { return str.replace(/^\s+|\s+$/, ''); } -describe('Add propType doc to react classes', () => { +describe('Add propType doc to react components', () => { const fixturesDir = path.join(__dirname, 'fixtures'); fs.readdirSync(fixturesDir).map((caseName) => { // Ignore macOS directory files