react-docgen-typescript
Version:
[](https://github.com/styleguidist/react-docgen-typescript/actions/workflows/nodejs.yml)
964 lines • 42.7 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDefaultExportForFile = exports.Parser = exports.withCompilerOptions = exports.withCustomConfig = exports.withDefaultConfig = exports.parse = exports.defaultOptions = exports.defaultParserOpts = void 0;
var fs = require("fs");
var path = require("path");
var ts = require("typescript");
var buildFilter_1 = require("./buildFilter");
var trimFileName_1 = require("./trimFileName");
exports.defaultParserOpts = {};
exports.defaultOptions = {
jsx: ts.JsxEmit.React,
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.Latest
};
/**
* Parses a file with default TS options
* @param filePathOrPaths component file that should be parsed
* @param parserOpts options used to parse the files
*/
function parse(filePathOrPaths, parserOpts) {
if (parserOpts === void 0) { parserOpts = exports.defaultParserOpts; }
return withCompilerOptions(exports.defaultOptions, parserOpts).parse(filePathOrPaths);
}
exports.parse = parse;
/**
* Constructs a parser for a default configuration.
*/
function withDefaultConfig(parserOpts) {
if (parserOpts === void 0) { parserOpts = exports.defaultParserOpts; }
return withCompilerOptions(exports.defaultOptions, parserOpts);
}
exports.withDefaultConfig = withDefaultConfig;
/**
* Constructs a parser for a specified tsconfig file.
*/
function withCustomConfig(tsconfigPath, parserOpts) {
var basePath = path.dirname(tsconfigPath);
var _a = ts.readConfigFile(tsconfigPath, function (filename) {
return fs.readFileSync(filename, 'utf8');
}), config = _a.config, error = _a.error;
if (error !== undefined) {
// tslint:disable-next-line: max-line-length
var errorText = "Cannot load custom tsconfig.json from provided path: " + tsconfigPath + ", with error code: " + error.code + ", message: " + error.messageText;
throw new Error(errorText);
}
var _b = ts.parseJsonConfigFileContent(config, ts.sys, basePath, {}, tsconfigPath), options = _b.options, errors = _b.errors;
if (errors && errors.length) {
if (errors[0] instanceof Error)
throw errors[0];
else if (errors[0].messageText)
throw new Error("TS" + errors[0].code + ": " + errors[0].messageText);
else
throw new Error(JSON.stringify(errors[0]));
}
return withCompilerOptions(options, parserOpts);
}
exports.withCustomConfig = withCustomConfig;
/**
* Constructs a parser for a specified set of TS compiler options.
*/
function withCompilerOptions(compilerOptions, parserOpts) {
if (parserOpts === void 0) { parserOpts = exports.defaultParserOpts; }
return {
parse: function (filePathOrPaths) {
return parseWithProgramProvider(filePathOrPaths, compilerOptions, parserOpts);
},
parseWithProgramProvider: function (filePathOrPaths, programProvider) {
return parseWithProgramProvider(filePathOrPaths, compilerOptions, parserOpts, programProvider);
}
};
}
exports.withCompilerOptions = withCompilerOptions;
var isOptional = function (prop) {
// tslint:disable-next-line:no-bitwise
return (prop.getFlags() & ts.SymbolFlags.Optional) !== 0;
};
var defaultJSDoc = {
description: '',
fullComment: '',
tags: {}
};
var Parser = /** @class */ (function () {
function Parser(program, opts) {
var savePropValueAsString = opts.savePropValueAsString, shouldExtractLiteralValuesFromEnum = opts.shouldExtractLiteralValuesFromEnum, shouldRemoveUndefinedFromOptional = opts.shouldRemoveUndefinedFromOptional, shouldExtractValuesFromUnion = opts.shouldExtractValuesFromUnion, shouldIncludePropTagMap = opts.shouldIncludePropTagMap, shouldIncludeExpression = opts.shouldIncludeExpression;
this.checker = program.getTypeChecker();
this.propFilter = (0, buildFilter_1.buildFilter)(opts);
this.shouldExtractLiteralValuesFromEnum = Boolean(shouldExtractLiteralValuesFromEnum);
this.shouldRemoveUndefinedFromOptional = Boolean(shouldRemoveUndefinedFromOptional);
this.shouldExtractValuesFromUnion = Boolean(shouldExtractValuesFromUnion);
this.savePropValueAsString = Boolean(savePropValueAsString);
this.shouldIncludePropTagMap = Boolean(shouldIncludePropTagMap);
this.shouldIncludeExpression = Boolean(shouldIncludeExpression);
}
Parser.prototype.getComponentFromExpression = function (exp) {
var declaration = exp.valueDeclaration || exp.declarations[0];
var type = this.checker.getTypeOfSymbolAtLocation(exp, declaration);
var typeSymbol = type.symbol || type.aliasSymbol;
if (!typeSymbol) {
return exp;
}
var symbolName = typeSymbol.getName();
if ((symbolName === 'MemoExoticComponent' ||
symbolName === 'ForwardRefExoticComponent') &&
exp.valueDeclaration &&
ts.isExportAssignment(exp.valueDeclaration) &&
ts.isCallExpression(exp.valueDeclaration.expression)) {
var component = this.checker.getSymbolAtLocation(exp.valueDeclaration.expression.arguments[0]);
if (component) {
exp = component;
}
}
return exp;
};
Parser.prototype.getComponentInfo = function (exp, source, componentNameResolver, customComponentTypes) {
if (componentNameResolver === void 0) { componentNameResolver = function () { return undefined; }; }
if (customComponentTypes === void 0) { customComponentTypes = []; }
if (!!exp.declarations && exp.declarations.length === 0) {
return null;
}
var rootExp = this.getComponentFromExpression(exp);
var declaration = rootExp.valueDeclaration || rootExp.declarations[0];
var type = this.checker.getTypeOfSymbolAtLocation(rootExp, declaration);
var commentSource = rootExp;
var typeSymbol = type.symbol || type.aliasSymbol;
var originalName = rootExp.getName();
var filePath = source.fileName;
if (!rootExp.valueDeclaration) {
if (!typeSymbol && (rootExp.flags & ts.SymbolFlags.Alias) !== 0) {
commentSource = this.checker.getAliasedSymbol(commentSource);
}
else if (!typeSymbol) {
return null;
}
else {
rootExp = typeSymbol;
var expName = rootExp.getName();
var defaultComponentTypes = [
'__function',
'StatelessComponent',
'Stateless',
'StyledComponentClass',
'StyledComponent',
'FunctionComponent',
'ForwardRefExoticComponent'
];
var supportedComponentTypes = __spreadArray(__spreadArray([], defaultComponentTypes, true), customComponentTypes, true);
if (supportedComponentTypes.indexOf(expName) !== -1) {
commentSource = this.checker.getAliasedSymbol(commentSource);
}
else {
commentSource = rootExp;
}
}
}
else if (type.symbol &&
(ts.isPropertyAccessExpression(declaration) ||
ts.isPropertyDeclaration(declaration))) {
commentSource = type.symbol;
}
// Skip over PropTypes that are exported
if (typeSymbol &&
(typeSymbol.getEscapedName() === 'Requireable' ||
typeSymbol.getEscapedName() === 'Validator')) {
return null;
}
var propsType = this.extractPropsFromTypeIfStatelessComponent(type) ||
this.extractPropsFromTypeIfStatefulComponent(type);
var nameSource = originalName === 'default' ? rootExp : commentSource;
var resolvedComponentName = componentNameResolver(nameSource, source);
var _a = this.findDocComment(commentSource), description = _a.description, tags = _a.tags;
var displayName = resolvedComponentName ||
tags.visibleName ||
computeComponentName(nameSource, source, customComponentTypes);
var methods = this.getMethodsInfo(type);
var result = null;
if (propsType) {
if (!commentSource.valueDeclaration) {
return null;
}
var defaultProps = this.extractDefaultPropsFromComponent(commentSource, commentSource.valueDeclaration.getSourceFile());
var props = this.getPropsInfo(propsType, defaultProps);
for (var _i = 0, _b = Object.keys(props); _i < _b.length; _i++) {
var propName = _b[_i];
var prop = props[propName];
var component = { name: displayName };
if (!this.propFilter(prop, component)) {
delete props[propName];
}
}
result = {
tags: tags,
filePath: filePath,
description: description,
displayName: displayName,
methods: methods,
props: props
};
}
else if (description && displayName) {
result = {
tags: tags,
filePath: filePath,
description: description,
displayName: displayName,
methods: methods,
props: {}
};
}
if (result !== null && this.shouldIncludeExpression) {
result.expression = rootExp;
}
return result;
};
Parser.prototype.extractPropsFromTypeIfStatelessComponent = function (type) {
var callSignatures = type.getCallSignatures();
if (callSignatures.length) {
// Could be a stateless component. Is a function, so the props object we're interested
// in is the (only) parameter.
for (var _i = 0, callSignatures_1 = callSignatures; _i < callSignatures_1.length; _i++) {
var sig = callSignatures_1[_i];
var params = sig.getParameters();
if (params.length === 0) {
continue;
}
// Maybe we could check return type instead,
// but not sure if Element, ReactElement<T> are all possible values
var propsParam = params[0];
if (propsParam.name === 'props' || params.length === 1) {
return propsParam;
}
}
}
return null;
};
Parser.prototype.extractPropsFromTypeIfStatefulComponent = function (type) {
var constructSignatures = type.getConstructSignatures();
if (constructSignatures.length) {
// React.Component. Is a class, so the props object we're interested
// in is the type of 'props' property of the object constructed by the class.
for (var _i = 0, constructSignatures_1 = constructSignatures; _i < constructSignatures_1.length; _i++) {
var sig = constructSignatures_1[_i];
var instanceType = sig.getReturnType();
var props = instanceType.getProperty('props');
if (props) {
return props;
}
}
}
return null;
};
Parser.prototype.extractMembersFromType = function (type) {
var _this = this;
var methodSymbols = [];
/**
* Need to loop over properties first so we capture any
* static methods. static methods aren't captured in type.symbol.members
*/
type.getProperties().forEach(function (property) {
// Only add members, don't add non-member properties
if (_this.getCallSignature(property)) {
methodSymbols.push(property);
}
});
if (type.symbol && type.symbol.members) {
type.symbol.members.forEach(function (member) {
methodSymbols.push(member);
});
}
return methodSymbols;
};
Parser.prototype.getMethodsInfo = function (type) {
var _this = this;
var members = this.extractMembersFromType(type);
var methods = [];
members.forEach(function (member) {
if (!_this.isTaggedPublic(member)) {
return;
}
var name = member.getName();
var docblock = _this.getFullJsDocComment(member).fullComment;
var callSignature = _this.getCallSignature(member);
var params = _this.getParameterInfo(callSignature);
var description = ts.displayPartsToString(member.getDocumentationComment(_this.checker));
var returnType = _this.checker.typeToString(callSignature.getReturnType());
var returnDescription = ts.displayPartsToString(_this.getReturnDescription(member));
var modifiers = _this.getModifiers(member);
methods.push({
description: description,
docblock: docblock,
modifiers: modifiers,
name: name,
params: params,
returns: returnDescription
? {
description: returnDescription,
type: returnType
}
: null
});
});
return methods;
};
Parser.prototype.getModifiers = function (member) {
var modifiers = [];
if (!member.valueDeclaration) {
return modifiers;
}
var flags = ts.getCombinedModifierFlags(member.valueDeclaration);
var isStatic = (flags & ts.ModifierFlags.Static) !== 0; // tslint:disable-line no-bitwise
if (isStatic) {
modifiers.push('static');
}
return modifiers;
};
Parser.prototype.getParameterInfo = function (callSignature) {
var _this = this;
return callSignature.parameters.map(function (param) {
var paramType = _this.checker.getTypeOfSymbolAtLocation(param, param.valueDeclaration);
var paramDeclaration = _this.checker.symbolToParameterDeclaration(param, undefined, undefined);
var isOptionalParam = !!(paramDeclaration && paramDeclaration.questionToken);
return {
description: ts.displayPartsToString(param.getDocumentationComment(_this.checker)) || null,
name: param.getName() + (isOptionalParam ? '?' : ''),
type: { name: _this.checker.typeToString(paramType) }
};
});
};
Parser.prototype.getCallSignature = function (symbol) {
var symbolType = this.checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
return symbolType.getCallSignatures()[0];
};
Parser.prototype.isTaggedPublic = function (symbol) {
var jsDocTags = symbol.getJsDocTags();
return Boolean(jsDocTags.find(function (tag) { return tag.name === 'public'; }));
};
Parser.prototype.getReturnDescription = function (symbol) {
var tags = symbol.getJsDocTags();
var returnTag = tags.find(function (tag) { return tag.name === 'returns'; });
if (!returnTag || !Array.isArray(returnTag.text)) {
return;
}
return returnTag.text;
};
Parser.prototype.getValuesFromUnionType = function (type) {
if (type.isStringLiteral())
return "\"" + type.value + "\"";
if (type.isNumberLiteral())
return "" + type.value;
return this.checker.typeToString(type);
};
Parser.prototype.getInfoFromUnionType = function (type) {
var commentInfo = {};
if (type.getSymbol()) {
commentInfo = __assign({}, this.getFullJsDocComment(type.getSymbol()));
}
return __assign({ value: this.getValuesFromUnionType(type) }, commentInfo);
};
Parser.prototype.getDocgenType = function (propType, isRequired) {
var _this = this;
// When we are going to process the type, we check if this type has a constraint (is a generic type with constraint)
if (propType.getConstraint()) {
// If so, we assing the property the type that is the constraint
propType = propType.getConstraint();
}
var propTypeString = this.checker.typeToString(propType);
if (this.shouldRemoveUndefinedFromOptional && !isRequired) {
propTypeString = propTypeString.replace(' | undefined', '');
}
if (propType.isUnion()) {
if (this.shouldExtractValuesFromUnion ||
(this.shouldExtractLiteralValuesFromEnum &&
propType.types.every(function (type) {
return type.getFlags() &
(ts.TypeFlags.StringLiteral |
ts.TypeFlags.NumberLiteral |
ts.TypeFlags.EnumLiteral |
ts.TypeFlags.Undefined);
}))) {
var value = propType.types.map(function (type) { return _this.getInfoFromUnionType(type); });
if (this.shouldRemoveUndefinedFromOptional && !isRequired) {
value = value.filter(function (option) { return option.value != 'undefined'; });
}
return {
name: 'enum',
raw: propTypeString,
value: value
};
}
}
if (this.shouldRemoveUndefinedFromOptional && !isRequired) {
propTypeString = propTypeString.replace(' | undefined', '');
}
return { name: propTypeString };
};
Parser.prototype.getPropsInfo = function (propsObj, defaultProps) {
var _this = this;
if (defaultProps === void 0) { defaultProps = {}; }
if (!propsObj.valueDeclaration) {
return {};
}
var propsType = this.checker.getTypeOfSymbolAtLocation(propsObj, propsObj.valueDeclaration);
var baseProps = propsType.getApparentProperties();
var propertiesOfProps = baseProps;
if (propsType.isUnionOrIntersection()) {
propertiesOfProps = __spreadArray(__spreadArray([], (propertiesOfProps = this
.checker.getAllPossiblePropertiesOfTypes(propsType.types)), true), baseProps, true);
if (!propertiesOfProps.length) {
var subTypes = this.checker.getAllPossiblePropertiesOfTypes(propsType.types.reduce(
// @ts-ignore
function (all, t) { return __spreadArray(__spreadArray([], all, true), (t.types || []), true); }, []));
propertiesOfProps = __spreadArray(__spreadArray([], subTypes, true), baseProps, true);
}
}
var result = {};
propertiesOfProps.forEach(function (prop) {
var propName = prop.getName();
// Find type of prop by looking in context of the props object itself.
var propType = _this.checker.getTypeOfSymbolAtLocation(prop, propsObj.valueDeclaration);
var jsDocComment = _this.findDocComment(prop);
var hasCodeBasedDefault = defaultProps[propName] !== undefined;
var defaultValue = null;
if (hasCodeBasedDefault) {
defaultValue = { value: defaultProps[propName] };
}
else if (jsDocComment.tags.default) {
defaultValue = { value: jsDocComment.tags.default };
}
var parent = getParentType(prop);
var parents = getDeclarations(prop);
var declarations = prop.declarations || [];
var baseProp = baseProps.find(function (p) { return p.getName() === propName; });
var required = !isOptional(prop) &&
!hasCodeBasedDefault &&
// If in a intersection or union check original declaration for "?"
// @ts-ignore
declarations.every(function (d) { return !d.questionToken; }) &&
(!baseProp || !isOptional(baseProp));
var type = jsDocComment.tags.type
? {
name: jsDocComment.tags.type
}
: _this.getDocgenType(propType, required);
var propTags = _this.shouldIncludePropTagMap
? { tags: jsDocComment.tags }
: {};
var description = _this.shouldIncludePropTagMap
? jsDocComment.description.replace(/\r\n/g, '\n')
: jsDocComment.fullComment.replace(/\r\n/g, '\n');
result[propName] = __assign({ defaultValue: defaultValue, description: description, name: propName, parent: parent, declarations: parents, required: required, type: type }, propTags);
});
return result;
};
Parser.prototype.findDocComment = function (symbol) {
var _this = this;
var comment = this.getFullJsDocComment(symbol);
if (comment.fullComment || comment.tags.default) {
return comment;
}
var rootSymbols = this.checker.getRootSymbols(symbol);
var commentsOnRootSymbols = rootSymbols
.filter(function (x) { return x !== symbol; })
.map(function (x) { return _this.getFullJsDocComment(x); })
.filter(function (x) { return !!x.fullComment || !!comment.tags.default; });
if (commentsOnRootSymbols.length) {
return commentsOnRootSymbols[0];
}
return defaultJSDoc;
};
/**
* Extracts a full JsDoc comment from a symbol, even
* though TypeScript has broken down the JsDoc comment into plain
* text and JsDoc tags.
*/
Parser.prototype.getFullJsDocComment = function (symbol) {
// in some cases this can be undefined (Pick<Type, 'prop1'|'prop2'>)
if (symbol.getDocumentationComment === undefined) {
return defaultJSDoc;
}
var mainComment = ts.displayPartsToString(symbol.getDocumentationComment(this.checker));
if (mainComment) {
mainComment = mainComment.replace(/\r\n/g, '\n');
}
var tags = symbol.getJsDocTags() || [];
var tagComments = [];
var tagMap = {};
tags.forEach(function (tag) {
var trimmedText = ts.displayPartsToString(tag.text).trim();
var currentValue = tagMap[tag.name];
tagMap[tag.name] = currentValue
? currentValue + '\n' + trimmedText
: trimmedText;
if (['default', 'type'].indexOf(tag.name) < 0) {
tagComments.push(formatTag(tag));
}
});
return {
description: mainComment,
fullComment: (mainComment + '\n' + tagComments.join('\n')).trim(),
tags: tagMap
};
};
Parser.prototype.getFunctionStatement = function (statement) {
if (ts.isFunctionDeclaration(statement)) {
return statement;
}
if (ts.isVariableStatement(statement)) {
var initializer = statement.declarationList &&
statement.declarationList.declarations[0].initializer;
// Look at forwardRef function argument
if (initializer && ts.isCallExpression(initializer)) {
var symbol = this.checker.getSymbolAtLocation(initializer.expression);
if (!symbol || symbol.getName() !== 'forwardRef')
return;
initializer = initializer.arguments[0];
}
if (initializer &&
(ts.isArrowFunction(initializer) ||
ts.isFunctionExpression(initializer))) {
return initializer;
}
}
};
Parser.prototype.extractDefaultPropsFromComponent = function (symbol, source) {
var _this = this;
var possibleStatements = __spreadArray(__spreadArray([], source.statements
// ensure that name property is available
.filter(function (stmt) { return !!stmt.name; })
.filter(function (stmt) {
return _this.checker.getSymbolAtLocation(stmt.name) === symbol;
}), true), source.statements.filter(function (stmt) { return ts.isExpressionStatement(stmt) || ts.isVariableStatement(stmt); }), true);
return possibleStatements.reduce(function (res, statement) {
if (statementIsClassDeclaration(statement) && statement.members.length) {
var possibleDefaultProps = statement.members.filter(function (member) {
return member.name && getPropertyName(member.name) === 'defaultProps';
});
if (!possibleDefaultProps.length) {
return res;
}
var defaultProps = possibleDefaultProps[0];
var initializer = defaultProps.initializer;
if (!initializer) {
return res;
}
var properties = initializer.properties;
while (ts.isIdentifier(initializer)) {
var defaultPropsReference = _this.checker.getSymbolAtLocation(initializer);
if (defaultPropsReference) {
var declarations = defaultPropsReference.getDeclarations();
if (declarations) {
if (ts.isImportSpecifier(declarations[0])) {
var symbol = _this.checker.getSymbolAtLocation(declarations[0].name);
if (!symbol) {
continue;
}
var aliasedSymbol = _this.checker.getAliasedSymbol(symbol);
if (aliasedSymbol &&
aliasedSymbol.declarations &&
aliasedSymbol.declarations.length) {
initializer = aliasedSymbol
.declarations[0].initializer;
}
else {
continue;
}
}
else {
initializer = declarations[0]
.initializer;
}
properties = initializer
.properties;
}
}
}
var propMap = {};
if (properties) {
propMap = _this.getPropMap(properties);
}
return __assign(__assign({}, res), propMap);
}
else if (statementIsStatelessWithDefaultProps(statement)) {
var propMap_1 = {};
statement.getChildren().forEach(function (child) {
var right = child.right;
if (right && ts.isIdentifier(right)) {
var value = source.locals.get(right.escapedText);
if (value &&
value.valueDeclaration &&
ts.isVariableDeclaration(value.valueDeclaration) &&
value.valueDeclaration.initializer) {
right = value.valueDeclaration.initializer;
}
}
if (right) {
var properties = right.properties;
if (properties) {
propMap_1 = _this.getPropMap(properties);
}
}
});
return __assign(__assign({}, res), propMap_1);
}
else {
}
var functionStatement = _this.getFunctionStatement(statement);
// Extracting default values from props destructuring
if (functionStatement &&
functionStatement.parameters &&
functionStatement.parameters.length) {
var name = functionStatement.parameters[0].name;
if (ts.isObjectBindingPattern(name)) {
return __assign(__assign({}, res), _this.getPropMap(name.elements));
}
}
return res;
}, {});
};
Parser.prototype.getLiteralValueFromImportSpecifier = function (property) {
if (ts.isImportSpecifier(property)) {
var symbol = this.checker.getSymbolAtLocation(property.name);
if (!symbol) {
return null;
}
var aliasedSymbol = this.checker.getAliasedSymbol(symbol);
if (aliasedSymbol &&
aliasedSymbol.declarations &&
aliasedSymbol.declarations.length) {
return this.getLiteralValueFromPropertyAssignment(aliasedSymbol.declarations[0]);
}
return null;
}
return null;
};
Parser.prototype.getLiteralValueFromPropertyAssignment = function (property) {
var initializer = property.initializer;
// Shorthand properties, so inflect their actual value
if (!initializer) {
if (ts.isShorthandPropertyAssignment(property)) {
var symbol = this.checker.getShorthandAssignmentValueSymbol(property);
var decl = symbol && symbol.valueDeclaration;
if (decl && decl.initializer) {
initializer = decl.initializer;
}
}
}
if (!initializer) {
return undefined;
}
// Literal values
switch (initializer.kind) {
case ts.SyntaxKind.FalseKeyword:
return this.savePropValueAsString ? 'false' : false;
case ts.SyntaxKind.TrueKeyword:
return this.savePropValueAsString ? 'true' : true;
case ts.SyntaxKind.StringLiteral:
return initializer.text.trim();
case ts.SyntaxKind.PrefixUnaryExpression:
return this.savePropValueAsString
? initializer.getFullText().trim()
: Number(initializer.getFullText());
case ts.SyntaxKind.NumericLiteral:
return this.savePropValueAsString
? "" + initializer.text
: Number(initializer.text);
case ts.SyntaxKind.NullKeyword:
return this.savePropValueAsString ? 'null' : null;
case ts.SyntaxKind.Identifier:
if (initializer.text === 'undefined') {
return 'undefined';
}
var symbol = this.checker.getSymbolAtLocation(initializer);
if (symbol && symbol.declarations && symbol.declarations.length) {
if (ts.isImportSpecifier(symbol.declarations[0])) {
return this.getLiteralValueFromImportSpecifier(symbol.declarations[0]);
}
return this.getLiteralValueFromPropertyAssignment(symbol.declarations[0]);
}
return null;
case ts.SyntaxKind.PropertyAccessExpression: {
var symbol_1 = this.checker.getSymbolAtLocation(initializer);
if (symbol_1 && symbol_1.declarations && symbol_1.declarations.length) {
var declaration = symbol_1.declarations[0];
if (ts.isBindingElement(declaration) ||
ts.isPropertyAssignment(declaration)) {
return this.getLiteralValueFromPropertyAssignment(declaration);
}
}
}
case ts.SyntaxKind.ObjectLiteralExpression:
default:
try {
return initializer.getText();
}
catch (e) {
return null;
}
}
};
Parser.prototype.getPropMap = function (properties) {
var _this = this;
return properties.reduce(function (acc, property) {
if (ts.isSpreadAssignment(property) || !property.name) {
return acc;
}
var literalValue = _this.getLiteralValueFromPropertyAssignment(property);
var propertyName = getPropertyName(property.name);
if ((typeof literalValue === 'string' ||
typeof literalValue === 'number' ||
typeof literalValue === 'boolean' ||
literalValue === null) &&
propertyName !== null) {
acc[propertyName] = literalValue;
}
return acc;
}, {});
};
return Parser;
}());
exports.Parser = Parser;
function statementIsClassDeclaration(statement) {
return !!statement.members;
}
function statementIsStatelessWithDefaultProps(statement) {
var children = statement.getChildren();
for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
var child = children_1[_i];
var left = child.left;
if (left) {
var name = left.name;
if (name && name.escapedText === 'defaultProps') {
return true;
}
}
}
return false;
}
function getPropertyName(name) {
switch (name.kind) {
case ts.SyntaxKind.NumericLiteral:
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.Identifier:
return name.text;
case ts.SyntaxKind.ComputedPropertyName:
return name.getText();
default:
return null;
}
}
function formatTag(tag) {
var result = '@' + tag.name;
if (tag.text) {
result += ' ' + ts.displayPartsToString(tag.text);
}
return result;
}
function getTextValueOfClassMember(classDeclaration, memberName) {
var classDeclarationMembers = classDeclaration.members || [];
var textValue = (classDeclarationMembers &&
classDeclarationMembers
.filter(function (member) { return ts.isPropertyDeclaration(member); })
.filter(function (member) {
var name = ts.getNameOfDeclaration(member);
return name && name.text === memberName;
})
.map(function (member) {
var property = member;
return (property.initializer && property.initializer.text);
}))[0];
return textValue || '';
}
function getTextValueOfFunctionProperty(exp, source, propertyName) {
var textValue = source.statements
.filter(function (statement) { return ts.isExpressionStatement(statement); })
.filter(function (statement) {
var expr = statement
.expression;
return (expr.left &&
expr.left.name &&
expr.left.name.escapedText ===
propertyName);
})
.filter(function (statement) {
return ts.isStringLiteral(statement
.expression.right);
})
.map(function (statement) {
return statement
.expression.right.text;
})[0];
return textValue || '';
}
function computeComponentName(exp, source, customComponentTypes) {
if (customComponentTypes === void 0) { customComponentTypes = []; }
var exportName = exp.getName();
var statelessDisplayName = getTextValueOfFunctionProperty(exp, source, 'displayName');
var statefulDisplayName = exp.valueDeclaration &&
ts.isClassDeclaration(exp.valueDeclaration) &&
getTextValueOfClassMember(exp.valueDeclaration, 'displayName');
if (statelessDisplayName || statefulDisplayName) {
return statelessDisplayName || statefulDisplayName || '';
}
var defaultComponentTypes = [
'default',
'__function',
'Stateless',
'StyledComponentClass',
'StyledComponent',
'FunctionComponent',
'StatelessComponent',
'ForwardRefExoticComponent'
];
var supportedComponentTypes = __spreadArray(__spreadArray([], defaultComponentTypes, true), customComponentTypes, true);
if (supportedComponentTypes.indexOf(exportName) !== -1) {
return getDefaultExportForFile(source);
}
else {
return exportName;
}
}
// Default export for a file: named after file
function getDefaultExportForFile(source) {
var name = path.basename(source.fileName, path.extname(source.fileName));
var filename = name === 'index' ? path.basename(path.dirname(source.fileName)) : name;
// JS identifiers must starts with a letter, and contain letters and/or numbers
// So, you could not take filename as is
var identifier = filename
.replace(/^[^A-Z]*/gi, '')
.replace(/[^A-Z0-9]*/gi, '');
return identifier.length ? identifier : 'DefaultName';
}
exports.getDefaultExportForFile = getDefaultExportForFile;
function isTypeLiteral(node) {
return node.kind === ts.SyntaxKind.TypeLiteral;
}
function getDeclarations(prop) {
var declarations = prop.getDeclarations();
if (declarations === undefined || declarations.length === 0) {
return undefined;
}
var parents = [];
for (var _i = 0, declarations_1 = declarations; _i < declarations_1.length; _i++) {
var declaration = declarations_1[_i];
var parent = declaration.parent;
if (!isTypeLiteral(parent) && !isInterfaceOrTypeAliasDeclaration(parent)) {
continue;
}
var parentName = 'name' in parent
? parent.name.text
: 'TypeLiteral';
var fileName = parent.getSourceFile().fileName;
parents.push({
fileName: (0, trimFileName_1.trimFileName)(fileName),
name: parentName
});
}
return parents;
}
function getParentType(prop) {
var declarations = prop.getDeclarations();
if (declarations == null || declarations.length === 0) {
return undefined;
}
// Props can be declared only in one place
var parent = declarations[0].parent;
if (!isInterfaceOrTypeAliasDeclaration(parent)) {
return undefined;
}
var parentName = parent.name.text;
var fileName = parent.getSourceFile().fileName;
return {
fileName: (0, trimFileName_1.trimFileName)(fileName),
name: parentName
};
}
function isInterfaceOrTypeAliasDeclaration(node) {
return (node.kind === ts.SyntaxKind.InterfaceDeclaration ||
node.kind === ts.SyntaxKind.TypeAliasDeclaration);
}
function parseWithProgramProvider(filePathOrPaths, compilerOptions, parserOpts, programProvider) {
var filePaths = Array.isArray(filePathOrPaths)
? filePathOrPaths
: [filePathOrPaths];
var program = programProvider
? programProvider()
: ts.createProgram(filePaths, compilerOptions);
var parser = new Parser(program, parserOpts);
var checker = program.getTypeChecker();
return filePaths
.map(function (filePath) { return program.getSourceFile(filePath); })
.filter(function (sourceFile) {
return typeof sourceFile !== 'undefined';
})
.reduce(function (docs, sourceFile) {
var moduleSymbol = checker.getSymbolAtLocation(sourceFile);
if (!moduleSymbol) {
return docs;
}
var components = checker.getExportsOfModule(moduleSymbol);
var componentDocs = [];
// First document all components
components.forEach(function (exp) {
var doc = parser.getComponentInfo(exp, sourceFile, parserOpts.componentNameResolver, parserOpts.customComponentTypes);
if (doc) {
componentDocs.push(doc);
}
if (!exp.exports) {
return;
}
// Then document any static sub-components
exp.exports.forEach(function (symbol) {
if (symbol.flags & ts.SymbolFlags.Prototype) {
return;
}
if (symbol.flags & ts.SymbolFlags.Method) {
var signature = parser.getCallSignature(symbol);
var returnType = checker.typeToString(signature.getReturnType());
if (returnType !== 'Element') {
return;
}
}
var doc = parser.getComponentInfo(symbol, sourceFile, parserOpts.componentNameResolver, parserOpts.customComponentTypes);
if (doc) {
componentDocs.push(__assign(__assign({}, doc), { displayName: exp.escapedName + "." + symbol.escapedName }));
}
});
});
// Remove any duplicates (for HOC where the names are the same)
var componentDocsNoDuplicates = componentDocs.reduce(function (prevVal, comp) {
var duplicate = prevVal.find(function (compDoc) {
return compDoc.displayName === comp.displayName;
});
if (duplicate)
return prevVal;
return __spreadArray(__spreadArray([], prevVal, true), [comp], false);
}, []);
var filteredComponentDocs = componentDocsNoDuplicates.filter(function (comp, index, comps) {
return comps
.slice(index + 1)
.every(function (innerComp) { return innerComp.displayName !== comp.displayName; });
});
return __spreadArray(__spreadArray([], docs, true), filteredComponentDocs, true);
}, []);
}
//# sourceMappingURL=parser.js.map