dgeni-packages
Version:
A collection of dgeni packages for generating documentation from source code
177 lines • 9.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReadTypeScriptModules = exports.readTypeScriptModules = void 0;
const ClassExportDoc_1 = require("../../api-doc-types/ClassExportDoc");
const ConstExportDoc_1 = require("../../api-doc-types/ConstExportDoc");
const EnumExportDoc_1 = require("../../api-doc-types/EnumExportDoc");
const FunctionExportDoc_1 = require("../../api-doc-types/FunctionExportDoc");
const InterfaceExportDoc_1 = require("../../api-doc-types/InterfaceExportDoc");
const MethodMemberDoc_1 = require("../../api-doc-types/MethodMemberDoc");
const ModuleDoc_1 = require("../../api-doc-types/ModuleDoc");
const PropertyMemberDoc_1 = require("../../api-doc-types/PropertyMemberDoc");
const TypeAliasExportDoc_1 = require("../../api-doc-types/TypeAliasExportDoc");
const TsParser_1 = require("../../services/TsParser");
const SourcePattern_1 = require("./SourcePattern");
// This import lacks type definitions.
const path = require('canonical-path');
function readTypeScriptModules(tsParser, tsHost, modules, exportSymbolsToDocsMap, createDocMessage, log) {
return new ReadTypeScriptModules(tsParser, tsHost, modules, exportSymbolsToDocsMap, createDocMessage, log);
}
exports.readTypeScriptModules = readTypeScriptModules;
class ReadTypeScriptModules {
constructor(tsParser, host, modules, exportSymbolsToDocsMap, createDocMessage, log) {
this.tsParser = tsParser;
this.host = host;
this.modules = modules;
this.exportSymbolsToDocsMap = exportSymbolsToDocsMap;
this.createDocMessage = createDocMessage;
this.log = log;
this.$runAfter = ['files-read'];
this.$runBefore = ['parsing-tags'];
this.$validate = {
basePath: { presence: true },
hidePrivateMembers: { inclusion: [true, false] },
ignoreExportsMatching: {},
sortClassMembers: { inclusion: [true, false] },
sourceFiles: { presence: true },
};
// A collection of globs that identify those modules for which we should create docs
this.sourceFiles = [];
// The base path from which to load the source files
this.basePath = '.';
// We can ignore members of classes that are private
this.hidePrivateMembers = true;
// We leave class members sorted in order of declaration
this.sortClassMembers = false;
// We can provide a collection of strings or regexes to ignore exports whose export names match
this.ignoreExportsMatching = ['__esModule'];
this.ignoreExportsRegexes = [];
}
$process(docs) {
// Convert ignoreExportsMatching to an array of regexes
this.ignoreExportsRegexes = convertToRegexCollection(this.ignoreExportsMatching);
// Extract the modules from source files via the TypeScript parser
const basePath = path.resolve(this.basePath);
const filesPaths = (0, SourcePattern_1.expandSourceFiles)(this.sourceFiles, basePath);
const parseInfo = this.tsParser.parse(filesPaths, this.basePath);
this.addModuleDocs(docs, parseInfo.moduleSymbols, basePath);
}
addModuleDocs(docs, moduleSymbols, basePath) {
// Iterate through each of the modules to generate module docs, export docs and member docs.
moduleSymbols.forEach(moduleSymbol => {
// Create a doc for this module and add it to the module lookup collection and the docs collection
const moduleDoc = new ModuleDoc_1.ModuleDoc(moduleSymbol, basePath, this.hidePrivateMembers, moduleSymbols.typeChecker);
this.modules[moduleDoc.id] = moduleDoc;
docs.push(moduleDoc);
this.addExportDocs(docs, moduleDoc);
});
}
addExportDocs(docs, moduleDoc) {
// Iterate through this module's exports and generate a doc for each
moduleDoc.symbol.exportArray.forEach(exportSymbol => {
// Ignore exports that match the configured regular expressions
if (anyMatches(this.ignoreExportsRegexes, exportSymbol.name))
return;
// If `exportSymbol.resolvedSymbol` is defined then the symbol has been "aliased":
// * `exportSymbol.resolvedSymbol` holds the actual info about the symbol being exported
// * `exportSymbol` is the "alias" symbol, which has the new name for the symbol being exported
const resolvedExport = exportSymbol.resolvedSymbol || exportSymbol;
const aliasSymbol = exportSymbol.resolvedSymbol ? exportSymbol : undefined;
// If the resolved symbol contains no declarations then it is invalid (perhaps an abstract class?)
// For the moment we are just going to ignore such exports (:scream:)
// TODO: find a way of generating docs for them
if (!resolvedExport.declarations) {
this.log.info(`Export has no declarations: ${resolvedExport.name}`);
return;
}
switch ((0, TsParser_1.getExportDocType)(resolvedExport)) {
case 'class':
const classDoc = new ClassExportDoc_1.ClassExportDoc(this.host, moduleDoc, resolvedExport, aliasSymbol);
this.addMemberDocs(docs, classDoc.members);
this.addMemberDocs(docs, classDoc.statics);
if (classDoc.constructorDoc)
this.addMemberDocs(docs, [classDoc.constructorDoc]);
this.addExportDoc(docs, moduleDoc, classDoc);
break;
case 'interface':
const interfaceDoc = new InterfaceExportDoc_1.InterfaceExportDoc(this.host, moduleDoc, resolvedExport, aliasSymbol);
this.addMemberDocs(docs, interfaceDoc.members);
this.addExportDoc(docs, moduleDoc, interfaceDoc);
break;
case 'enum':
const enumDoc = new EnumExportDoc_1.EnumExportDoc(this.host, moduleDoc, resolvedExport, aliasSymbol);
enumDoc.members.forEach(doc => docs.push(doc));
this.addExportDoc(docs, moduleDoc, enumDoc);
break;
case 'const':
case 'let':
case 'var':
this.addExportDoc(docs, moduleDoc, new ConstExportDoc_1.ConstExportDoc(this.host, moduleDoc, resolvedExport, aliasSymbol));
break;
case 'type-alias':
this.addExportDoc(docs, moduleDoc, new TypeAliasExportDoc_1.TypeAliasExportDoc(this.host, moduleDoc, resolvedExport, aliasSymbol));
break;
case 'function':
const functionDoc = new FunctionExportDoc_1.FunctionExportDoc(this.host, moduleDoc, resolvedExport, aliasSymbol);
this.addExportDoc(docs, moduleDoc, functionDoc);
this.addParamDocs(docs, functionDoc.parameterDocs);
functionDoc.overloads.forEach(overloadDoc => {
docs.push(overloadDoc);
this.addParamDocs(docs, overloadDoc.parameterDocs);
});
break;
default:
this.log.error(`Don't know how to create export document for ${resolvedExport.name}`);
break;
}
});
}
addExportDoc(docs, moduleDoc, exportDoc) {
this.log.debug('>>>> EXPORT: ' + exportDoc.name + ' (' + exportDoc.docType + ') from ' + moduleDoc.id);
moduleDoc.exports.push(exportDoc);
docs.push(exportDoc);
this.exportSymbolsToDocsMap.set(exportDoc.symbol, exportDoc);
}
addMemberDocs(docs, members) {
members.forEach(member => {
docs.push(member);
if (member instanceof MethodMemberDoc_1.MethodMemberDoc) {
this.addParamDocs(docs, member.parameterDocs);
member.overloads.forEach(overloadDoc => {
docs.push(overloadDoc);
this.addParamDocs(docs, overloadDoc.parameterDocs);
});
}
if (member instanceof PropertyMemberDoc_1.PropertyMemberDoc) {
if (member.getAccessor)
docs.push(member.getAccessor);
if (member.setAccessor) {
docs.push(member.setAccessor);
this.addParamDocs(docs, member.setAccessor.parameterDocs);
}
}
});
}
addParamDocs(docs, parameters) {
parameters.forEach(parameter => docs.push(parameter));
}
}
exports.ReadTypeScriptModules = ReadTypeScriptModules;
function convertToRegexCollection(items) {
if (!items)
return [];
// Must be an array
if (!Array.isArray(items))
items = [items];
// Convert string to exact matching regexes
return items.map(item => item instanceof RegExp ? item : new RegExp('^' + item + '$'));
}
function anyMatches(regexes, item) {
for (const regex of regexes) {
if (item.match(regex)) {
return true;
}
}
return false;
}
//# sourceMappingURL=index.js.map