react-dts-generator
Version:
Simple .d.ts generator for React components.
162 lines (161 loc) • 6.89 kB
JavaScript
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const dom = __importStar(require("./dts-dom"));
const comment_parser_1 = __importDefault(require("comment-parser"));
function getType(type) {
switch (type.toLowerCase()) {
case 'any': return dom.type.any;
case 'array': return dom.type.array(dom.type.any);
case 'bool': return dom.type.boolean;
case 'number': return dom.type.number;
case 'object': return dom.type.object;
case 'string': return dom.type.string;
case 'this': return dom.type.this;
case 'element': return 'React.ReactElement<any>';
case 'node': return 'React.ReactNode';
case 'shape': return type;
default: return dom.type.any;
}
}
exports.getType = getType;
function generateProp(prop) {
function generate(name, type, flag) {
const property = dom.create.property(name, type, flag);
return { property };
}
function generateFunc(name, description, flag) {
const result = comment_parser_1.default(makeComment(description));
if (result && result.length > 0) {
const signature = result[0];
const parameters = [];
let returnType = dom.type.void;
signature.tags.forEach(item => {
if (item.tag === 'param') {
const type = item.type ? item.type : 'any';
parameters.push(dom.create.parameter(item.name, getType(type)));
}
else if (item.tag === 'return') {
returnType = getType(item.type);
}
});
const property = dom.create.method(name, parameters, returnType, flag);
return { property };
}
}
function generateShape(name, props, flag) {
const interfaces = [];
const shapeDefinition = generateShapeInterface(name, props, interfaces);
const property = dom.create.property(name, shapeDefinition.name, flag);
return { property, interfaces };
}
function generateArrayOf(name, prop, flag) {
const property = dom.create.property(name, dom.type.array(getType(prop.name)), flag);
return { property };
}
function generateOneOf(name, values, flag) {
let unions = '';
values.forEach(item => unions += `${item.value} | `);
unions = unions.substr(0, unions.length - 3);
const property = dom.create.property(name, unions, flag);
return { property };
}
function generateOneOfType(name, values, flag) {
let isAnyType = false;
const unionTypes = [];
const interfaces = [];
values.forEach(item => {
const t = getType(item.name);
if (t === dom.type.any) {
isAnyType = true;
}
else if (t === 'shape') {
const shapeDefinition = generateShapeInterface(name, item.value, interfaces);
unionTypes.push(shapeDefinition.name);
}
else {
unionTypes.push(getType(item.name));
}
});
const union = dom.create.union(unionTypes);
const property = dom.create.property(name, isAnyType ? dom.type.any : union, flag);
return { property, interfaces };
}
function generateShapeInterface(name, props, shapes) {
const interfaceName = getDeclarationName(name);
const shapeDefinition = dom.create.interface(interfaceName);
Object.keys(props).forEach(key => {
const { required, name } = props[key];
const flag = required ? dom.DeclarationFlags.None : dom.DeclarationFlags.Optional;
const type = getType(name);
if (type === 'shape') {
const childShape = generateShapeInterface(key, props[key].value, shapes);
shapeDefinition.members.push(dom.create.property(key, childShape.name, flag));
}
else if (name === 'union') {
const union = generateOneOfType(key, props[key].value, flag);
shapeDefinition.members.push(union.property);
shapes.push(...union.interfaces || []);
}
else {
shapeDefinition.members.push(dom.create.property(key, type, flag));
}
});
shapes.push(shapeDefinition);
return shapeDefinition;
}
function makeComment(doc) {
return `/**\r\n ${doc} \r\n*/`;
}
function getDeclarationName(prop) {
return prop.charAt(0).toUpperCase() + prop.slice(1);
}
const { name, required, type, description } = prop;
const flag = required ? dom.DeclarationFlags.None : dom.DeclarationFlags.Optional;
try {
switch (type.name.toLowerCase()) {
case 'any': return generate(name, dom.type.any, flag);
case 'bool': return generate(name, dom.type.boolean, flag);
case 'number': return generate(name, dom.type.number, flag);
case 'object': return generate(name, dom.type.object, flag);
case 'string': return generate(name, dom.type.string, flag);
case 'this': return generate(name, dom.type.this, flag);
case 'array': return generate(name, dom.type.array(dom.type.any), flag);
case 'element': return generate(name, 'React.ReactElement<any>', flag);
case 'node': return generate(name, 'React.ReactNode', flag);
case 'func': return generateFunc(name, description, flag);
case 'shape': return generateShape(name, type.value, flag);
case 'arrayof': return generateArrayOf(name, type.value, flag);
case 'enum': return generateOneOf(name, type.value, flag);
case 'union': return generateOneOfType(name, type.value, flag);
default: return generate(name, dom.type.any, flag);
}
}
catch (e) {
return generate(name, dom.type.any, flag);
}
}
exports.generateProp = generateProp;
function writeGeneric(out, type) {
return `${out}<${type}>`;
}
exports.writeGeneric = writeGeneric;
function createImport(from, defaultImport, namedImport) {
if (defaultImport) {
return dom.create.importDefault(defaultImport, from);
}
else if (namedImport) {
return dom.create.importNamed(namedImport, from);
}
return dom.create.import(from);
}
exports.createImport = createImport;