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

Commit a4cb090

Browse files
committed
feat: Adds option create write typings to top-level (#116)
This options adds the ability to create typings definition which could be used to add them to npm packages
1 parent 2b394fe commit a4cb090

File tree

6 files changed

+67
-12
lines changed

6 files changed

+67
-12
lines changed

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ npm install -g react-to-typescript-definitions
3636
## CLI
3737

3838
```sh
39+
# Create a definition which exports a module named 'module-name'
3940
cat <some/react/component.jsx> |react2dts --name module-name
41+
42+
# Create a definition which exports top level definitions
43+
cat <some/react/component.jsx> |react2dts --top-level-module
4044
```
4145

4246
## API

Diff for: cli.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ var react2dts = require('./index');
33
var minimist = require('minimist');
44

55
var options = minimist(process.argv.slice(2), {
6-
string: ['name']
6+
string: ['name', 'module-name'],
7+
boolean: ['top-level-module'],
8+
alias: {
9+
'module-name': 'name'
10+
}
711
});
812

913
react2dts.cli(options);

Diff for: index.ts

+20-10
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,22 @@ export function cli(options: any): void {
4646
}
4747
});
4848
process.stdin.on('end', () => {
49-
if (!options.name) {
50-
console.error('Failed to specify --name parameter');
49+
if (options['top-level-module']) {
50+
process.stdout.write(generateFromSource(null, stdinCode.join('')));
51+
} else if (options['module-name']) {
52+
process.stdout.write(generateFromSource(options['module-name'], stdinCode.join('')));
53+
} else {
54+
console.error('Failed to specify --module-name or --top-level-module parameter');
5155
process.exit(1);
5256
}
53-
process.stdout.write(generateFromSource(options.name, stdinCode.join('')));
5457
});
5558
}
5659

57-
export function generateFromFile(name: string, path: string, options?: IOptions): string {
58-
return generateFromSource(name, fs.readFileSync(path).toString(), options);
60+
export function generateFromFile(moduleName: string, path: string, options?: IOptions): string {
61+
return generateFromSource(moduleName, fs.readFileSync(path).toString(), options);
5962
}
6063

61-
export function generateFromSource(name: string, code: string, options: IOptions = {}): string {
64+
export function generateFromSource(moduleName: string, code: string, options: IOptions = {}): string {
6265
const ast: any = babylon.parse(code, {
6366
sourceType: 'module',
6467
allowReturnOutsideFunction: true,
@@ -81,15 +84,16 @@ export function generateFromSource(name: string, code: string, options: IOptions
8184
'functionSent'
8285
]
8386
});
84-
return generateFromAst(name, ast, options);
87+
return generateFromAst(moduleName, ast, options);
8588
}
8689

8790
const defaultInstanceOfResolver: InstanceOfResolver = (name: string): string => undefined;
8891

89-
export function generateFromAst(name: string, ast: any, options: IOptions = {}): string {
92+
export function generateFromAst(moduleName: string, ast: any, options: IOptions = {}): string {
9093
const {exportType, classname, propTypes}: IParsingResult = parseAst(ast, options.instanceOfResolver);
9194
const generator: Generator = options.generator || new Generator();
92-
generator.declareModule(name, () => {
95+
96+
const generateTypings: () => void = () => {
9397
generator.import('* as React', 'react');
9498
if (propTypes) {
9599
Object.keys(propTypes).forEach((propName: string) => {
@@ -105,7 +109,13 @@ export function generateFromAst(name: string, ast: any, options: IOptions = {}):
105109
generator.exportDeclaration(exportType, () => {
106110
generator.class(classname, !!propTypes);
107111
});
108-
});
112+
};
113+
114+
if (moduleName === null) {
115+
generateTypings();
116+
} else {
117+
generator.declareModule(moduleName, generateTypings);
118+
}
109119
return generator.toString();
110120
}
111121

Diff for: tests/es7-class-top-level-module.d.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import * as React from 'react';
2+
import Message from './path/to/Message';
3+
4+
export interface ComponentProps {
5+
/**
6+
* This is a jsdoc comment for optionalAny.
7+
*/
8+
optionalAny?: any;
9+
optionalArray?: any[];
10+
optionalBool?: boolean;
11+
optionalFunc?: (...args: any[]) => any;
12+
optionalNumber?: number;
13+
optionalObject?: Object;
14+
optionalString?: string;
15+
optionalNode?: React.ReactNode;
16+
optionalElement?: React.ReactElement<any>;
17+
optionalMessage?: typeof Message;
18+
optionalUnion?: string|number;
19+
optionalArrayOf?: number[];
20+
requiredFunc: (...args: any[]) => any;
21+
requiredAny: any;
22+
requiredUnion: any[]|boolean;
23+
requiredArrayOf: string[];
24+
}
25+
26+
export default class Component extends React.Component<ComponentProps, any> {
27+
}

Diff for: tests/parsing-test.ts

+9
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,13 @@ describe('Parsing', () => {
2323
fs.readFileSync(path.join(__dirname, 'es7-class.d.ts')).toString()
2424
);
2525
});
26+
it('should create top-level module definition from es7 class component', () => {
27+
const opts: react2dts.IOptions = {
28+
instanceOfResolver: (name: string): string => './path/to/Message'
29+
};
30+
assert.equal(
31+
react2dts.generateFromFile(null, path.join(__dirname, 'es7-class.jsx'), opts),
32+
fs.readFileSync(path.join(__dirname, 'es7-class-top-level-module.d.ts')).toString()
33+
);
34+
});
2635
});

Diff for: tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"exclude": [
1111
"node_modules",
1212
"tests/es6-class.d.ts",
13-
"tests/es7-class.d.ts"
13+
"tests/es7-class.d.ts",
14+
"tests/es7-class-top-level-module.d.ts"
1415
]
1516
}

0 commit comments

Comments
 (0)