diff --git a/package.json b/package.json index 249b2a1e..d1d2d7f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-docgen-typescript", - "version": "1.1.0", + "version": "1.2.0", "description": "", "main": "lib/index.js", "scripts": { @@ -11,7 +11,6 @@ "print": "npm run tsc && node ./lib/print.js", "print:sample1": "npm run tsc && node ./lib/print.js ./src/__tests__/data/ColumnHigherOrderComponent.tsx simple" }, - "author": "pvasek", "license": "MIT", "dependencies": {}, "devDependencies": { diff --git a/src/__tests__/data/ColumnWithDefaultAnonymousExportOnly.tsx b/src/__tests__/data/ColumnWithDefaultAnonymousExportOnly.tsx new file mode 100644 index 00000000..c6ce2cc7 --- /dev/null +++ b/src/__tests__/data/ColumnWithDefaultAnonymousExportOnly.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; + +/** + * Column properties. + */ +export interface IColumnProps { + /** prop1 description */ + prop1?: string; + /** prop2 description */ + prop2: number; + /** + * prop3 description + */ + prop3: () => void; + /** prop4 description */ + prop4: 'option1' | 'option2' | "option3"; +} + +/** + * ColumnWithDefaultAnonymousExportOnly description + */ +export default class extends React.Component { + public static defaultProps: Partial = { + prop1: 'prop1' + }; + + render() { + const {prop1} = this.props; + return
{prop1}
; + } +} diff --git a/src/__tests__/data/ColumnWithDefaultExport.tsx b/src/__tests__/data/ColumnWithDefaultExport.tsx new file mode 100644 index 00000000..832ce531 --- /dev/null +++ b/src/__tests__/data/ColumnWithDefaultExport.tsx @@ -0,0 +1,33 @@ +import * as React from 'react'; + +/** + * Column properties. + */ +export interface IColumnProps { + /** prop1 description */ + prop1?: string; + /** prop2 description */ + prop2: number; + /** + * prop3 description + */ + prop3: () => void; + /** prop4 description */ + prop4: 'option1' | 'option2' | "option3"; +} + +/** + * Column description + */ +class Column extends React.Component { + public static defaultProps: Partial = { + prop1: 'prop1' + }; + + render() { + const {prop1} = this.props; + return
{prop1}
; + } +} + +export default Column; \ No newline at end of file diff --git a/src/__tests__/data/ColumnWithDefaultExportOnly.tsx b/src/__tests__/data/ColumnWithDefaultExportOnly.tsx new file mode 100644 index 00000000..b40a73a2 --- /dev/null +++ b/src/__tests__/data/ColumnWithDefaultExportOnly.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; + +/** + * Column properties. + */ +export interface IColumnProps { + /** prop1 description */ + prop1?: string; + /** prop2 description */ + prop2: number; + /** + * prop3 description + */ + prop3: () => void; + /** prop4 description */ + prop4: 'option1' | 'option2' | "option3"; +} + +/** + * ColumnWithDefaultExportOnly description + */ +export default class Column extends React.Component { + public static defaultProps: Partial = { + prop1: 'prop1' + }; + + render() { + const {prop1} = this.props; + return
{prop1}
; + } +} diff --git a/src/__tests__/data/ColumnWithHtmlAttributes.tsx b/src/__tests__/data/ColumnWithHtmlAttributes.tsx index a0e710d5..59afdd45 100644 --- a/src/__tests__/data/ColumnWithHtmlAttributes.tsx +++ b/src/__tests__/data/ColumnWithHtmlAttributes.tsx @@ -22,6 +22,4 @@ export class Column extends React.Component { const {prop1} = this.props; return
{prop1}
; } -} - -export default Column; \ No newline at end of file +} \ No newline at end of file diff --git a/src/__tests__/data/ColumnWithPick.tsx b/src/__tests__/data/ColumnWithPick.tsx index 5d4f893b..60cbf7c5 100644 --- a/src/__tests__/data/ColumnWithPick.tsx +++ b/src/__tests__/data/ColumnWithPick.tsx @@ -29,6 +29,4 @@ export class Column extends React.Component { const {prop1} = this.props; return
{prop1}
; } -} - -export default Column; \ No newline at end of file +} \ No newline at end of file diff --git a/src/__tests__/data/ColumnWithoutExportedProps.tsx b/src/__tests__/data/ColumnWithoutExportedProps.tsx index 104357f5..58021598 100644 --- a/src/__tests__/data/ColumnWithoutExportedProps.tsx +++ b/src/__tests__/data/ColumnWithoutExportedProps.tsx @@ -21,6 +21,4 @@ export class Column extends React.Component { const {prop1} = this.props; return
{prop1}
; } -} - -export default Column; \ No newline at end of file +} \ No newline at end of file diff --git a/src/__tests__/data/ConstExport.tsx b/src/__tests__/data/ConstExport.tsx index 4dac216a..377e3a06 100644 --- a/src/__tests__/data/ConstExport.tsx +++ b/src/__tests__/data/ConstExport.tsx @@ -36,6 +36,4 @@ export const Row = (props: IRowProps) => { const nonExportedFunc = (props: IRowProps) => { return
No Export
-}; - -export default Row; +}; \ No newline at end of file diff --git a/src/__tests__/data/FlippableImage.tsx b/src/__tests__/data/FlippableImage.tsx index b4419623..7638d9cc 100644 --- a/src/__tests__/data/FlippableImage.tsx +++ b/src/__tests__/data/FlippableImage.tsx @@ -33,6 +33,4 @@ export const FlippableImage = (props: Props) => { {...rest} /> ); -}; - -export default FlippableImage; \ No newline at end of file +}; \ No newline at end of file diff --git a/src/__tests__/data/PureRow.tsx b/src/__tests__/data/PureRow.tsx index 615ddbf9..909e64c4 100644 --- a/src/__tests__/data/PureRow.tsx +++ b/src/__tests__/data/PureRow.tsx @@ -19,5 +19,3 @@ export class Row extends React.PureComponent { return
Test
; } }; - -export default Row; \ No newline at end of file diff --git a/src/__tests__/data/Regression_v0_0_12.tsx b/src/__tests__/data/Regression_v0_0_12.tsx index b0d00bf1..d5e8fb6a 100644 --- a/src/__tests__/data/Regression_v0_0_12.tsx +++ b/src/__tests__/data/Regression_v0_0_12.tsx @@ -69,5 +69,3 @@ export class Zoomable extends React.PureComponent { ); } } - -export default Zoomable; \ No newline at end of file diff --git a/src/__tests__/data/Stateless.tsx b/src/__tests__/data/Stateless.tsx index fb86a1a2..0c8de7d7 100644 --- a/src/__tests__/data/Stateless.tsx +++ b/src/__tests__/data/Stateless.tsx @@ -9,5 +9,3 @@ export const Stateless: React.StatelessComponent = props =>
My Property = {props.myProp}
; - -export default Stateless; \ No newline at end of file diff --git a/src/__tests__/data/StatelessWithDefaultProps.tsx b/src/__tests__/data/StatelessWithDefaultProps.tsx index 90c1bd0b..c3425f30 100644 --- a/src/__tests__/data/StatelessWithDefaultProps.tsx +++ b/src/__tests__/data/StatelessWithDefaultProps.tsx @@ -17,4 +17,3 @@ StatelessWithDefaultProps.defaultProps = { sampleProp: 'test' }; -export default StatelessWithDefaultProps; diff --git a/src/__tests__/parser.ts b/src/__tests__/parser.ts index 5f1ef333..577cf1c6 100644 --- a/src/__tests__/parser.ts +++ b/src/__tests__/parser.ts @@ -17,6 +17,43 @@ describe('parser', () => { }); }); + + it('should parse simple react class component as default export', function() { + check('ColumnWithDefaultExport', { + Column: { + children, + prop1: { type: 'string', required: false }, + prop2: { type: 'number' }, + prop3: { type: '() => void'}, + prop4: { type: '"option1" | "option2" | "option3"' }, + } + }); + }); + + it('should parse simple react class component as default export only', function() { + check('ColumnWithDefaultExportOnly', { + ColumnWithDefaultExportOnly: { + children, + prop1: { type: 'string', required: false }, + prop2: { type: 'number' }, + prop3: { type: '() => void'}, + prop4: { type: '"option1" | "option2" | "option3"' }, + } + }); + }); + + it('should parse simple react class component as default anonymous export', function() { + check('ColumnWithDefaultAnonymousExportOnly', { + ColumnWithDefaultAnonymousExportOnly: { + children, + prop1: { type: 'string', required: false }, + prop2: { type: 'number' }, + prop3: { type: '() => void'}, + prop4: { type: '"option1" | "option2" | "option3"' }, + } + }); + }); + it('should parse simple react class component with state', () => { check('AppMenu', { AppMenu: { diff --git a/src/parser.ts b/src/parser.ts index 71f88018..abc12242 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -89,7 +89,17 @@ export function withCompilerOptions(compilerOptions: ts.CompilerOptions): FilePa .map(exp => parser.getComponentInfo(exp, sourceFile)) .filter(comp => comp); - return components; + // this should filter out components with the same name as default export + const filteredComponents = components + .filter((comp, index) => { + const isUnique = components + .slice(index + 1) + .filter(i => i.displayName === comp.displayName) + .length === 0; + return isUnique; + }); + + return filteredComponents; } }; } @@ -114,7 +124,11 @@ class Parser { } public getComponentInfo(exp: ts.Symbol, source: ts.SourceFile): ComponentDoc { - const type = this.checker.getTypeOfSymbolAtLocation(exp, exp.valueDeclaration); + const type = this.checker.getTypeOfSymbolAtLocation(exp, exp.valueDeclaration || exp.declarations[0]); + if (!exp.valueDeclaration) { + exp = type.symbol; + } + let propsType = this.extractPropsFromTypeIfStatelessComponent(type); if (!propsType) { propsType = this.extractPropsFromTypeIfStatefulComponent(type);