UNPKG

typedoc-plugin-external-module-map

Version:

Specify the Typedoc Module of a file using a regular expression on the filename

110 lines 4.95 kB
import { Application, ContainerReflection, Context, Converter, Reflection, ReflectionKind } from "typedoc"; /** * This plugin allows you to provide a mapping regexp between your source folder structure, and the module that should be * reported in typedoc. It will match the first capture group of your regex and use that as the module name. * * Based on https://github.com/christopherthielen/typedoc-plugin-external-module-name * * */ export class ExternalModuleMapPlugin { constructor() { /** List of module reflections which are models to rename */ this.moduleRenames = new Array(); this.externalmap = ''; this.mapRegExs = new Array(); this.isMappingEnabled = false; } initialize(app) { app.converter.on(Converter.EVENT_BEGIN, this.onBegin.bind(this)); app.converter.on(Converter.EVENT_CREATE_DECLARATION, this.onDeclarationBegin.bind(this)); app.converter.on(Converter.EVENT_RESOLVE_BEGIN, this.onBeginResolve.bind(this)); } /** * Triggered when the converter begins converting a project. * * @param context The context object describing the current state the converter is in. */ onBegin(context) { this.moduleRenames = []; //this.options.read(); this.externalmap = context.converter.application.options.getValue("external-modulemap"); if (!!this.externalmap) { try { console.log("INFO: applying regexp ", this.externalmap, " to calculate module names"); this.mapRegExs = Array.isArray(this.externalmap) ? this.externalmap.map(reg => new RegExp(reg)) : [new RegExp(this.externalmap)]; this.isMappingEnabled = true; console.log("INFO: Enabled", this.isMappingEnabled); } catch (e) { console.log("WARN: external map not recognized. Not processing.", e); } } } onDeclarationBegin(context, reflection, node) { if (!this.isMappingEnabled) { return; } if (!(reflection.kindOf(ReflectionKind.SomeModule))) { return; } const symbol = reflection.project.getSymbolFromReflection(reflection); for (const node of (symbol === null || symbol === void 0 ? void 0 : symbol.declarations) || []) { const sourceFile = node.getSourceFile(); const fileName = sourceFile.fileName; let match; for (const reg of this.mapRegExs) { match = reg.exec(fileName); if (null != match) { break; } } if (null != match) { console.log(' Mapping ', fileName, ' ==> ', match[1]); this.moduleRenames.push({ renameTo: match[1], reflection: reflection }); } } } /** * Triggered when the converter begins resolving a project. * * @param context The context object describing the current state the converter is in. */ onBeginResolve(context) { let projRefs = context.project.reflections; let refsArray = Object.keys(projRefs).reduce((m, k) => { m.push(projRefs[k]); return m.filter((y) => y instanceof ContainerReflection); }, []); // Process each rename this.moduleRenames.forEach(item => { let renaming = item.reflection; // Find an existing module that already has the "rename to" name. Use it as the merge target. let mergeTarget = refsArray.filter(ref => ref.kind === renaming.kind && ref.name === item.renameTo)[0]; // If there wasn't a merge target, just change the name of the current module and exit. if (!mergeTarget) { renaming.name = item.renameTo; return; } if (!mergeTarget.children) { mergeTarget.children = []; } // Since there is a merge target, relocate all the renaming module's children to the mergeTarget. let childrenOfRenamed = refsArray.filter(ref => ref.parent === renaming); childrenOfRenamed.forEach((ref) => { // update links in both directions //console.log(' merging ', mergeTarget, ref); ref.parent = mergeTarget; if (mergeTarget && mergeTarget.children) { mergeTarget.children.push(ref); } }); // Now that all the children have been relocated to the mergeTarget, delete the empty module // Make sure the module being renamed doesn't have children, or they will be deleted if (renaming.children) renaming.children.length = 0; context.project.removeReflection(renaming); }); } } //# sourceMappingURL=plugin.js.map