diff options
Diffstat (limited to 'packages/react-docs/src/utils/typedoc_utils.ts')
-rw-r--r-- | packages/react-docs/src/utils/typedoc_utils.ts | 251 |
1 files changed, 165 insertions, 86 deletions
diff --git a/packages/react-docs/src/utils/typedoc_utils.ts b/packages/react-docs/src/utils/typedoc_utils.ts index a6d938e94..b45dc73a8 100644 --- a/packages/react-docs/src/utils/typedoc_utils.ts +++ b/packages/react-docs/src/utils/typedoc_utils.ts @@ -19,8 +19,11 @@ import { TypeParameter, TypescriptFunction, TypescriptMethod, + GeneratedDocJson, } from '../types'; +import { constants } from './constants'; + export const typeDocUtils = { isType(entity: TypeDocNode): boolean { return ( @@ -55,65 +58,89 @@ export const typeDocUtils = { }); return moduleDefinitions; }, - convertToDocAgnosticFormat(typeDocJson: TypeDocNode, docsInfo: DocsInfo): DocAgnosticFormat { - const subMenus = _.values(docsInfo.getMenu()); - const orderedSectionNames = _.flatten(subMenus); + convertToDocAgnosticFormat(generatedDocJson: GeneratedDocJson, docsInfo: DocsInfo): DocAgnosticFormat { + const exportPathOrder = generatedDocJson.metadata.exportPathOrder; + const exportPathToTypedocNames = generatedDocJson.metadata.exportPathToTypedocNames; + const typeDocJson = generatedDocJson.typedocJson; + + // TODO: Extract the non typeDoc exports, and render them somehow + const typeDocNameOrder = _.compact( + _.flatten( + _.map(exportPathOrder, exportPath => { + return exportPathToTypedocNames[exportPath]; + }), + ), + ); + const docAgnosticFormat: DocAgnosticFormat = {}; - _.each(orderedSectionNames, sectionName => { - const modulePathsIfExists = docsInfo.getModulePathsIfExists(sectionName); - if (_.isUndefined(modulePathsIfExists)) { - return; // no-op - } - const packageDefinitions = typeDocUtils.getModuleDefinitionsBySectionName(typeDocJson, modulePathsIfExists); - let packageDefinitionWithMergedChildren; - if (_.isEmpty(packageDefinitions)) { - return; // no-op - } else if (packageDefinitions.length === 1) { - packageDefinitionWithMergedChildren = packageDefinitions[0]; - } else { - // HACK: For now, if there are two modules to display in a single section, - // we simply concat the children. This works for our limited use-case where - // we want to display types stored in two files under a single section - packageDefinitionWithMergedChildren = packageDefinitions[0]; - for (let i = 1; i < packageDefinitions.length; i++) { - packageDefinitionWithMergedChildren.children = [ - ...packageDefinitionWithMergedChildren.children, - ...packageDefinitions[i].children, - ]; + const typeEntities: TypeDocNode[] = []; + _.each(typeDocNameOrder, typeDocName => { + const fileChildIndex = _.findIndex(typeDocJson.children, child => child.name === typeDocName); + const fileChild = typeDocJson.children[fileChildIndex]; + let sectionName: string; + _.each(fileChild.children, child => { + switch (child.kindString) { + case KindString.Class: + case KindString.ObjectLiteral: { + sectionName = child.name; + docsInfo.sections[sectionName] = sectionName; + docsInfo.menu[sectionName] = [sectionName]; + const entities = child.children; + const commentObj = child.comment; + const sectionComment = !_.isUndefined(commentObj) ? commentObj.shortText : ''; + const isClassOrObjectLiteral = true; + const docSection = typeDocUtils._convertEntitiesToDocSection( + entities, + docsInfo, + sectionName, + isClassOrObjectLiteral, + ); + docSection.comment = sectionComment; + docAgnosticFormat[sectionName] = docSection; + break; + } + case KindString.Function: { + sectionName = child.name; + docsInfo.sections[sectionName] = sectionName; + docsInfo.menu[sectionName] = [sectionName]; + const entities = [child]; + const commentObj = child.comment; + const SectionComment = !_.isUndefined(commentObj) ? commentObj.shortText : ''; + const docSection = typeDocUtils._convertEntitiesToDocSection(entities, docsInfo, sectionName); + docSection.comment = SectionComment; + docAgnosticFormat[sectionName] = docSection; + break; + } + case KindString.Interface: + case KindString.Variable: + case KindString.Enumeration: + case KindString.TypeAlias: + typeEntities.push(child); + break; + default: + throw errorUtils.spawnSwitchErr('kindString', child.kindString); } - } - - let entities; - let packageComment = ''; - // HACK: We assume 1 exported class per file - const classChildren = _.filter(packageDefinitionWithMergedChildren.children, (child: TypeDocNode) => { - return child.kindString === KindString.Class; }); - if (classChildren.length > 1 && sectionName !== 'types') { - throw new Error('`react-docs` only supports projects with 1 exported class per file'); - } - const isClassExport = packageDefinitionWithMergedChildren.children[0].kindString === KindString.Class; - const isObjectLiteralExport = - packageDefinitionWithMergedChildren.children[0].kindString === KindString.ObjectLiteral; - if (isClassExport) { - entities = packageDefinitionWithMergedChildren.children[0].children; - const commentObj = packageDefinitionWithMergedChildren.children[0].comment; - packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment; - } else if (isObjectLiteralExport) { - entities = packageDefinitionWithMergedChildren.children[0].children; - const commentObj = packageDefinitionWithMergedChildren.children[0].comment; - packageComment = !_.isUndefined(commentObj) ? commentObj.shortText : packageComment; - } else { - entities = packageDefinitionWithMergedChildren.children; - } - - const docSection = typeDocUtils._convertEntitiesToDocSection(entities, docsInfo, sectionName); - docSection.comment = packageComment; - docAgnosticFormat[sectionName] = docSection; }); + if (!_.isEmpty(typeEntities)) { + docsInfo.sections[constants.TYPES_SECTION_NAME] = constants.TYPES_SECTION_NAME; + docsInfo.menu[constants.TYPES_SECTION_NAME] = [constants.TYPES_SECTION_NAME]; + const docSection = typeDocUtils._convertEntitiesToDocSection( + typeEntities, + docsInfo, + constants.TYPES_SECTION_NAME, + ); + docAgnosticFormat[constants.TYPES_SECTION_NAME] = docSection; + } + return docAgnosticFormat; }, - _convertEntitiesToDocSection(entities: TypeDocNode[], docsInfo: DocsInfo, sectionName: string): DocSection { + _convertEntitiesToDocSection( + entities: TypeDocNode[], + docsInfo: DocsInfo, + sectionName: string, + isClassOrObjectLiteral: boolean = false, + ): DocSection { const docSection: DocSection = { comment: '', constructors: [], @@ -140,8 +167,18 @@ export const typeDocUtils = { case KindString.Function: if (entity.flags.isExported) { - const func = typeDocUtils._convertFunction(entity, docsInfo.sections, sectionName, docsInfo.id); - docSection.functions.push(func); + const funcName = (entity as TypeDocNode).signatures[0].name; + const isPublicFunc = !_.startsWith(funcName, '_'); + if (isPublicFunc) { + const func = typeDocUtils._convertFunction( + entity, + docsInfo.sections, + sectionName, + docsInfo.id, + isClassOrObjectLiteral, + ); + docSection.functions.push(func); + } } break; @@ -171,11 +208,18 @@ export const typeDocUtils = { } break; - case KindString.Interface: case KindString.Variable: - case KindString.Enumeration: - case KindString.TypeAlias: - if (docsInfo.isPublicType(entity.name)) { + if (isClassOrObjectLiteral) { + // Render as a property + const property = typeDocUtils._convertProperty( + entity, + docsInfo.sections, + sectionName, + docsInfo.id, + ); + docSection.properties.push(property); + } else { + // Otherwise, render as a type const customType = typeDocUtils._convertCustomType( entity, docsInfo.sections, @@ -190,6 +234,23 @@ export const typeDocUtils = { } break; + case KindString.Interface: + case KindString.Variable: + case KindString.Enumeration: + case KindString.TypeAlias: + const customType = typeDocUtils._convertCustomType( + entity, + docsInfo.sections, + sectionName, + docsInfo.id, + ); + const seenTypeNames = _.map(docSection.types, t => t.name); + const isUnseen = !_.includes(seenTypeNames, customType.name); + if (isUnseen) { + docSection.types.push(customType); + } + break; + case KindString.Class: // We currently do not support more then a single class per file // except for the types section, where we ignore classes since we @@ -211,13 +272,7 @@ export const typeDocUtils = { ? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, docId) : undefined; const doesIndexSignatureExist = !_.isUndefined(entity.indexSignature); - const isIndexSignatureArray = _.isArray(entity.indexSignature); - // HACK: TypeDoc Versions <0.9.0 indexSignature is of type TypeDocNode[] - // Versions >0.9.0 have it as type TypeDocNode - const indexSignature = - doesIndexSignatureExist && isIndexSignatureArray - ? (entity.indexSignature as TypeDocNode[])[0] - : (entity.indexSignature as TypeDocNode); + const indexSignature = entity.indexSignature as TypeDocNode; const indexSignatureIfExists = doesIndexSignatureExist ? typeDocUtils._convertIndexSignature(indexSignature, sections, sectionName, docId) : undefined; @@ -276,6 +331,9 @@ export const typeDocUtils = { _convertProperty(entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: string): Property { const source = entity.sources[0]; const commentIfExists = !_.isUndefined(entity.comment) ? entity.comment.shortText : undefined; + const isConstructor = false; + const isStatic = _.isUndefined(entity.flags.isStatic) ? false : entity.flags.isStatic; + const callPath = typeDocUtils._getCallPath(sectionName, isStatic, isConstructor, entity.name); const property = { name: entity.name, type: typeDocUtils._convertType(entity.type, sections, sectionName, docId), @@ -284,6 +342,7 @@ export const typeDocUtils = { line: source.line, }, comment: commentIfExists, + callPath, }; return property; }, @@ -299,22 +358,6 @@ export const typeDocUtils = { const hasComment = !_.isUndefined(signature.comment); const isStatic = _.isUndefined(entity.flags.isStatic) ? false : entity.flags.isStatic; - // HACK: we use the fact that the sectionName is the same as the property name at the top-level - // of the public interface. In the future, we shouldn't use this hack but rather get it from the JSON. - let callPath; - if (isConstructor || entity.name === '__type') { - callPath = ''; - // TODO: Get rid of this 0x-specific logic - } else if (docId === 'ZERO_EX_JS') { - const topLevelInterface = isStatic ? 'ZeroEx.' : 'zeroEx.'; - callPath = - !_.isUndefined(sections.zeroEx) && sectionName !== sections.zeroEx - ? `${topLevelInterface}${sectionName}.` - : topLevelInterface; - } else { - callPath = `${sectionName}.`; - } - const parameters = _.map(signature.parameters, param => { return typeDocUtils._convertParameter(param, sections, sectionName, docId); }); @@ -323,6 +366,7 @@ export const typeDocUtils = { ? undefined : typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName, docId); + const callPath = typeDocUtils._getCallPath(sectionName, isStatic, isConstructor, entity.name); const method = { isConstructor, isStatic, @@ -340,11 +384,25 @@ export const typeDocUtils = { }; return method; }, + _getCallPath(sectionName: string, isStatic: boolean, isConstructor: boolean, entityName: string) { + // HACK: we use the fact that the sectionName is the same as the property name at the top-level + // of the public interface. In the future, we shouldn't use this hack but rather get it from the JSON. + let callPath; + if (isConstructor || entityName === '__type') { + callPath = ''; + // TODO: Get rid of this 0x-specific logic + } else { + const prefix = isStatic ? sectionName : `${sectionName[0].toLowerCase()}${sectionName.slice(1)}`; + callPath = `${prefix}.`; + } + return callPath; + }, _convertFunction( entity: TypeDocNode, sections: SectionsMap, sectionName: string, docId: string, + isObjectLiteral: boolean, ): TypescriptFunction { const signature = entity.signatures[0]; const source = entity.sources[0]; @@ -358,10 +416,17 @@ export const typeDocUtils = { ? undefined : typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName, docId); + let callPath = ''; + if (isObjectLiteral) { + const isConstructor = false; + const isStatic = false; + callPath = typeDocUtils._getCallPath(sectionName, isStatic, isConstructor, entity.name); + } const func = { name: signature.name, comment: hasComment ? signature.comment.shortText : undefined, returnComment: hasComment && signature.comment.returns ? signature.comment.returns : undefined, + callPath, source: { fileName: source.fileName, line: source.line, @@ -414,10 +479,23 @@ export const typeDocUtils = { return typeDocUtils._convertType(t, sections, sectionName, docId); }); - const isConstructor = false; - const methodIfExists = !_.isUndefined(entity.declaration) - ? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, docId) - : undefined; + let indexSignatureIfExists; + let methodIfExists; + const doesIndexSignatureExist = + !_.isUndefined(entity.declaration) && !_.isUndefined(entity.declaration.indexSignature); + if (doesIndexSignatureExist) { + const indexSignature = entity.declaration.indexSignature as TypeDocNode; + indexSignatureIfExists = typeDocUtils._convertIndexSignature(indexSignature, sections, sectionName, docId); + } else if (!_.isUndefined(entity.declaration)) { + const isConstructor = false; + methodIfExists = typeDocUtils._convertMethod( + entity.declaration, + isConstructor, + sections, + sectionName, + docId, + ); + } const elementTypeIfExists = !_.isUndefined(entity.elementType) ? { @@ -434,6 +512,7 @@ export const typeDocUtils = { elementType: elementTypeIfExists, types, method: methodIfExists, + indexSignature: indexSignatureIfExists, }; return type; }, |