Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit 67064b8

Browse files
committed
feat: support named exports as default
1 parent 872f806 commit 67064b8

File tree

4 files changed

+108
-47
lines changed

4 files changed

+108
-47
lines changed

Diff for: src/typings.ts

+80-47
Original file line numberDiff line numberDiff line change
@@ -460,49 +460,41 @@ function getReferencedPropTypesComponentName(ast: AstQuery, propTypes: any|undef
460460
}
461461

462462
function getComponentExportType(ast: AstQuery, componentName: string): dom.DeclarationFlags|undefined {
463-
if (componentName === '') {
464-
// case: unnamed default export
465-
const res = ast.query(`
466-
// ExportDefaultDeclaration[
467-
// ClassDeclaration
468-
||
469-
// FunctionDeclaration
470-
]
471-
`);
472-
if (res.length > 0 && !res[0].id) {
473-
return dom.DeclarationFlags.ExportDefault;
474-
}
475-
}
476-
let res = ast.query(`
477-
// ExportDefaultDeclaration[
478-
// ClassDeclaration
479-
/:id Identifier[@name == '${componentName}']
480-
||
481-
// FunctionDeclaration
482-
/:id Identifier[@name == '${componentName}']
483-
||
484-
// VariableDeclaration
485-
/ VariableDeclarator
486-
/:id Identifier[@name == '${componentName}']
487-
||
488-
/Identifier[@name == '${componentName}']
489-
]
490-
,
491-
// AssignmentExpression[
492-
/:left MemberExpression[
493-
/:object Identifier[@name == 'exports']
494-
&&
495-
/:property Identifier[@name == 'default']
496-
]
497-
&&
498-
/:right Identifier[@name == '${componentName}']
499-
]
500-
`);
501-
if (res.length > 0) {
463+
if (isDefaultExport(ast, componentName)) {
502464
return dom.DeclarationFlags.ExportDefault;
503465
}
504-
res = ast.query(`
505-
// ExportNamedDeclaration[
466+
467+
if (isNamedExport(ast, componentName)) {
468+
return dom.DeclarationFlags.Export;
469+
}
470+
471+
return undefined;
472+
}
473+
474+
function isDefaultExport(ast: AstQuery, componentName: string): boolean {
475+
return isUnnamedDefaultExport(ast, componentName) || isNamedDefaultExport(ast, componentName) ||
476+
isNamedExportAsDefault(ast, componentName);
477+
}
478+
479+
function isUnnamedDefaultExport(ast: AstQuery, componentName: string): boolean {
480+
if (componentName !== '') {
481+
return false;
482+
}
483+
484+
const res = ast.query(`
485+
// ExportDefaultDeclaration[
486+
// ClassDeclaration
487+
||
488+
// FunctionDeclaration
489+
]
490+
`);
491+
492+
return res.length > 0 && !res[0].id;
493+
}
494+
495+
function isNamedDefaultExport(ast: AstQuery, componentName: string): boolean {
496+
const res = ast.query(`
497+
// ExportDefaultDeclaration[
506498
// ClassDeclaration
507499
/:id Identifier[@name == '${componentName}']
508500
||
@@ -513,14 +505,55 @@ function getComponentExportType(ast: AstQuery, componentName: string): dom.Decla
513505
/ VariableDeclarator
514506
/:id Identifier[@name == '${componentName}']
515507
||
516-
// ExportSpecifier
517-
/:exported Identifier[@name == '${componentName}']
508+
/Identifier[@name == '${componentName}']
509+
]
510+
,
511+
// AssignmentExpression[
512+
/:left MemberExpression[
513+
/:object Identifier[@name == 'exports']
514+
&&
515+
/:property Identifier[@name == 'default']
516+
]
517+
&&
518+
/:right Identifier[@name == '${componentName}']
518519
]
519520
`);
520-
if (res.length > 0) {
521-
return dom.DeclarationFlags.Export;
522-
}
523-
return undefined;
521+
522+
return res.length > 0;
523+
}
524+
525+
function isNamedExportAsDefault(ast: AstQuery, componentName: string): boolean {
526+
const res = ast.query(`
527+
// ExportNamedDeclaration[
528+
// ExportSpecifier [
529+
/:local Identifier[@name == '${componentName}'] &&
530+
/:exported Identifier[@name == 'default']
531+
]
532+
]
533+
`);
534+
535+
return res.length > 0;
536+
}
537+
538+
function isNamedExport(ast: AstQuery, componentName: string): boolean {
539+
const res = ast.query(`
540+
// ExportNamedDeclaration[
541+
// ClassDeclaration
542+
/:id Identifier[@name == '${componentName}']
543+
||
544+
// FunctionDeclaration
545+
/:id Identifier[@name == '${componentName}']
546+
||
547+
// VariableDeclaration
548+
/ VariableDeclarator
549+
/:id Identifier[@name == '${componentName}']
550+
||
551+
// ExportSpecifier
552+
/:exported Identifier[@name == '${componentName}']
553+
]
554+
`);
555+
556+
return res.length > 0;
524557
}
525558

526559
function isClassComponent(ast: AstQuery, componentName: string,

Diff for: tests/parsing-test.ts

+3
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,6 @@ test('Parsing should suppport props-types repo', t => {
108108
test('Parsing should suppport props-types repo (with a default import)', t => {
109109
compare(t, 'path', 'prop-types-default-import.jsx', 'prop-types.d.ts', {});
110110
});
111+
test('Parsing should support an SFC with default export babeled to es6', t => {
112+
compare(t, 'component', 'stateless-export-as-default.js', 'stateless-export-as-default.d.ts');
113+
});

Diff for: tests/stateless-export-as-default.d.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
declare module 'component' {
2+
export interface ComponentProps {
3+
text: string;
4+
className?: string;
5+
}
6+
7+
export default function Component(props: ComponentProps): JSX.Element;
8+
}

Diff for: tests/stateless-export-as-default.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
const Component = ({ className, text }) => React.createElement(
5+
'div',
6+
{ className: className },
7+
text
8+
);
9+
10+
Component.displayName = 'Component';
11+
12+
Component.propTypes = {
13+
text: PropTypes.string.isRequired,
14+
className: PropTypes.string
15+
};
16+
17+
export { Component as default };

0 commit comments

Comments
 (0)