UNPKG

typedoc

Version:

Create api documentation for TypeScript projects.

659 lines (658 loc) 38.2 kB
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; import ts from "typescript"; import { Comment, DocumentReflection, ProjectReflection, ReflectionKind, } from "../models/index.js"; import { Context } from "./context.js"; import { AbstractComponent } from "../utils/component.js"; import { Option, MinimalSourceFile, readFile, unique, getDocumentEntryPoints, } from "../utils/index.js"; import { convertType } from "./types.js"; import { ConverterEvents } from "./converter-events.js"; import { convertSymbol } from "./symbols.js"; import { createMinimatch, matchesAny, nicePath } from "../utils/paths.js"; import { hasAllFlags, hasAnyFlag } from "../utils/enum.js"; import { parseCommentString } from "./comments/parser.js"; import { lexCommentString } from "./comments/rawLexer.js"; import { resolvePartLinks, resolveLinks, } from "./comments/linkResolver.js"; import { meaningToString, } from "./comments/declarationReference.js"; import { basename, dirname, resolve } from "path"; import { GroupPlugin } from "./plugins/GroupPlugin.js"; import { CategoryPlugin } from "./plugins/CategoryPlugin.js"; import { CommentPlugin } from "./plugins/CommentPlugin.js"; import { ImplementsPlugin } from "./plugins/ImplementsPlugin.js"; import { InheritDocPlugin } from "./plugins/InheritDocPlugin.js"; import { LinkResolverPlugin } from "./plugins/LinkResolverPlugin.js"; import { PackagePlugin } from "./plugins/PackagePlugin.js"; import { SourcePlugin } from "./plugins/SourcePlugin.js"; import { TypePlugin } from "./plugins/TypePlugin.js"; import { IncludePlugin } from "./plugins/IncludePlugin.js"; import { MergeModuleWithPlugin } from "./plugins/MergeModuleWithPlugin.js"; /** * Compiles source files using TypeScript and converts compiler symbols to reflections. * * @group Common * @summary Responsible for converting TypeScript symbols into {@link Reflection}s and {@link Type}s. */ let Converter = (() => { let _classSuper = AbstractComponent; let _externalPattern_decorators; let _externalPattern_initializers = []; let _externalPattern_extraInitializers = []; let _excludeExternals_decorators; let _excludeExternals_initializers = []; let _excludeExternals_extraInitializers = []; let _excludeNotDocumented_decorators; let _excludeNotDocumented_initializers = []; let _excludeNotDocumented_extraInitializers = []; let _excludePrivate_decorators; let _excludePrivate_initializers = []; let _excludePrivate_extraInitializers = []; let _excludeProtected_decorators; let _excludeProtected_initializers = []; let _excludeProtected_extraInitializers = []; let _excludeReferences_decorators; let _excludeReferences_initializers = []; let _excludeReferences_extraInitializers = []; let _commentStyle_decorators; let _commentStyle_initializers = []; let _commentStyle_extraInitializers = []; let _validation_decorators; let _validation_initializers = []; let _validation_extraInitializers = []; let _externalSymbolLinkMappings_decorators; let _externalSymbolLinkMappings_initializers = []; let _externalSymbolLinkMappings_extraInitializers = []; let _preserveLinkText_decorators; let _preserveLinkText_initializers = []; let _preserveLinkText_extraInitializers = []; let _maxTypeConversionDepth_decorators; let _maxTypeConversionDepth_initializers = []; let _maxTypeConversionDepth_extraInitializers = []; return class Converter extends _classSuper { static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _externalPattern_decorators = [Option("externalPattern")]; _excludeExternals_decorators = [Option("excludeExternals")]; _excludeNotDocumented_decorators = [Option("excludeNotDocumented")]; _excludePrivate_decorators = [Option("excludePrivate")]; _excludeProtected_decorators = [Option("excludeProtected")]; _excludeReferences_decorators = [Option("excludeReferences")]; _commentStyle_decorators = [Option("commentStyle")]; _validation_decorators = [Option("validation")]; _externalSymbolLinkMappings_decorators = [Option("externalSymbolLinkMappings")]; _preserveLinkText_decorators = [Option("preserveLinkText")]; _maxTypeConversionDepth_decorators = [Option("maxTypeConversionDepth")]; __esDecorate(this, null, _externalPattern_decorators, { kind: "accessor", name: "externalPattern", static: false, private: false, access: { has: obj => "externalPattern" in obj, get: obj => obj.externalPattern, set: (obj, value) => { obj.externalPattern = value; } }, metadata: _metadata }, _externalPattern_initializers, _externalPattern_extraInitializers); __esDecorate(this, null, _excludeExternals_decorators, { kind: "accessor", name: "excludeExternals", static: false, private: false, access: { has: obj => "excludeExternals" in obj, get: obj => obj.excludeExternals, set: (obj, value) => { obj.excludeExternals = value; } }, metadata: _metadata }, _excludeExternals_initializers, _excludeExternals_extraInitializers); __esDecorate(this, null, _excludeNotDocumented_decorators, { kind: "accessor", name: "excludeNotDocumented", static: false, private: false, access: { has: obj => "excludeNotDocumented" in obj, get: obj => obj.excludeNotDocumented, set: (obj, value) => { obj.excludeNotDocumented = value; } }, metadata: _metadata }, _excludeNotDocumented_initializers, _excludeNotDocumented_extraInitializers); __esDecorate(this, null, _excludePrivate_decorators, { kind: "accessor", name: "excludePrivate", static: false, private: false, access: { has: obj => "excludePrivate" in obj, get: obj => obj.excludePrivate, set: (obj, value) => { obj.excludePrivate = value; } }, metadata: _metadata }, _excludePrivate_initializers, _excludePrivate_extraInitializers); __esDecorate(this, null, _excludeProtected_decorators, { kind: "accessor", name: "excludeProtected", static: false, private: false, access: { has: obj => "excludeProtected" in obj, get: obj => obj.excludeProtected, set: (obj, value) => { obj.excludeProtected = value; } }, metadata: _metadata }, _excludeProtected_initializers, _excludeProtected_extraInitializers); __esDecorate(this, null, _excludeReferences_decorators, { kind: "accessor", name: "excludeReferences", static: false, private: false, access: { has: obj => "excludeReferences" in obj, get: obj => obj.excludeReferences, set: (obj, value) => { obj.excludeReferences = value; } }, metadata: _metadata }, _excludeReferences_initializers, _excludeReferences_extraInitializers); __esDecorate(this, null, _commentStyle_decorators, { kind: "accessor", name: "commentStyle", static: false, private: false, access: { has: obj => "commentStyle" in obj, get: obj => obj.commentStyle, set: (obj, value) => { obj.commentStyle = value; } }, metadata: _metadata }, _commentStyle_initializers, _commentStyle_extraInitializers); __esDecorate(this, null, _validation_decorators, { kind: "accessor", name: "validation", static: false, private: false, access: { has: obj => "validation" in obj, get: obj => obj.validation, set: (obj, value) => { obj.validation = value; } }, metadata: _metadata }, _validation_initializers, _validation_extraInitializers); __esDecorate(this, null, _externalSymbolLinkMappings_decorators, { kind: "accessor", name: "externalSymbolLinkMappings", static: false, private: false, access: { has: obj => "externalSymbolLinkMappings" in obj, get: obj => obj.externalSymbolLinkMappings, set: (obj, value) => { obj.externalSymbolLinkMappings = value; } }, metadata: _metadata }, _externalSymbolLinkMappings_initializers, _externalSymbolLinkMappings_extraInitializers); __esDecorate(this, null, _preserveLinkText_decorators, { kind: "accessor", name: "preserveLinkText", static: false, private: false, access: { has: obj => "preserveLinkText" in obj, get: obj => obj.preserveLinkText, set: (obj, value) => { obj.preserveLinkText = value; } }, metadata: _metadata }, _preserveLinkText_initializers, _preserveLinkText_extraInitializers); __esDecorate(this, null, _maxTypeConversionDepth_decorators, { kind: "accessor", name: "maxTypeConversionDepth", static: false, private: false, access: { has: obj => "maxTypeConversionDepth" in obj, get: obj => obj.maxTypeConversionDepth, set: (obj, value) => { obj.maxTypeConversionDepth = value; } }, metadata: _metadata }, _maxTypeConversionDepth_initializers, _maxTypeConversionDepth_extraInitializers); if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } #externalPattern_accessor_storage = __runInitializers(this, _externalPattern_initializers, void 0); /** @internal */ get externalPattern() { return this.#externalPattern_accessor_storage; } set externalPattern(value) { this.#externalPattern_accessor_storage = value; } externalPatternCache = __runInitializers(this, _externalPattern_extraInitializers); excludeCache; #excludeExternals_accessor_storage = __runInitializers(this, _excludeExternals_initializers, void 0); /** @internal */ get excludeExternals() { return this.#excludeExternals_accessor_storage; } set excludeExternals(value) { this.#excludeExternals_accessor_storage = value; } #excludeNotDocumented_accessor_storage = (__runInitializers(this, _excludeExternals_extraInitializers), __runInitializers(this, _excludeNotDocumented_initializers, void 0)); /** @internal */ get excludeNotDocumented() { return this.#excludeNotDocumented_accessor_storage; } set excludeNotDocumented(value) { this.#excludeNotDocumented_accessor_storage = value; } #excludePrivate_accessor_storage = (__runInitializers(this, _excludeNotDocumented_extraInitializers), __runInitializers(this, _excludePrivate_initializers, void 0)); /** @internal */ get excludePrivate() { return this.#excludePrivate_accessor_storage; } set excludePrivate(value) { this.#excludePrivate_accessor_storage = value; } #excludeProtected_accessor_storage = (__runInitializers(this, _excludePrivate_extraInitializers), __runInitializers(this, _excludeProtected_initializers, void 0)); /** @internal */ get excludeProtected() { return this.#excludeProtected_accessor_storage; } set excludeProtected(value) { this.#excludeProtected_accessor_storage = value; } #excludeReferences_accessor_storage = (__runInitializers(this, _excludeProtected_extraInitializers), __runInitializers(this, _excludeReferences_initializers, void 0)); /** @internal */ get excludeReferences() { return this.#excludeReferences_accessor_storage; } set excludeReferences(value) { this.#excludeReferences_accessor_storage = value; } #commentStyle_accessor_storage = (__runInitializers(this, _excludeReferences_extraInitializers), __runInitializers(this, _commentStyle_initializers, void 0)); /** @internal */ get commentStyle() { return this.#commentStyle_accessor_storage; } set commentStyle(value) { this.#commentStyle_accessor_storage = value; } #validation_accessor_storage = (__runInitializers(this, _commentStyle_extraInitializers), __runInitializers(this, _validation_initializers, void 0)); /** @internal */ get validation() { return this.#validation_accessor_storage; } set validation(value) { this.#validation_accessor_storage = value; } #externalSymbolLinkMappings_accessor_storage = (__runInitializers(this, _validation_extraInitializers), __runInitializers(this, _externalSymbolLinkMappings_initializers, void 0)); /** @internal */ get externalSymbolLinkMappings() { return this.#externalSymbolLinkMappings_accessor_storage; } set externalSymbolLinkMappings(value) { this.#externalSymbolLinkMappings_accessor_storage = value; } #preserveLinkText_accessor_storage = (__runInitializers(this, _externalSymbolLinkMappings_extraInitializers), __runInitializers(this, _preserveLinkText_initializers, void 0)); /** @internal */ get preserveLinkText() { return this.#preserveLinkText_accessor_storage; } set preserveLinkText(value) { this.#preserveLinkText_accessor_storage = value; } #maxTypeConversionDepth_accessor_storage = (__runInitializers(this, _preserveLinkText_extraInitializers), __runInitializers(this, _maxTypeConversionDepth_initializers, void 0)); /** @internal */ get maxTypeConversionDepth() { return this.#maxTypeConversionDepth_accessor_storage; } set maxTypeConversionDepth(value) { this.#maxTypeConversionDepth_accessor_storage = value; } _config = __runInitializers(this, _maxTypeConversionDepth_extraInitializers); _externalSymbolResolvers = []; get config() { return this._config || this._buildCommentParserConfig(); } /** * General events */ /** * Triggered when the converter begins converting a project. * The listener will be given a {@link Context} object. * @event */ static EVENT_BEGIN = ConverterEvents.BEGIN; /** * Triggered when the converter has finished converting a project. * The listener will be given a {@link Context} object. * @event */ static EVENT_END = ConverterEvents.END; /** * Factory events */ /** * Triggered when the converter has created a project reflection. * The listener will be given {@link Context} and a {@link Models.ProjectReflection}. * @event */ static EVENT_CREATE_PROJECT = ConverterEvents.CREATE_PROJECT; /** * Triggered when the converter has created a declaration reflection. * The listener will be given {@link Context} and a {@link Models.DeclarationReflection}. * @event */ static EVENT_CREATE_DECLARATION = ConverterEvents.CREATE_DECLARATION; /** * Triggered when the converter has created a document reflection. * The listener will be given `undefined` (for consistency with the * other create events) and a {@link Models.DocumentReflection}. * @event */ static EVENT_CREATE_DOCUMENT = ConverterEvents.CREATE_DOCUMENT; /** * Triggered when the converter has created a signature reflection. * The listener will be given {@link Context}, {@link Models.SignatureReflection} | {@link Models.ProjectReflection} the declaration, * `ts.SignatureDeclaration | ts.IndexSignatureDeclaration | ts.JSDocSignature | undefined`, * and `ts.Signature | undefined`. The signature will be undefined if the created signature is an index signature. * @event */ static EVENT_CREATE_SIGNATURE = ConverterEvents.CREATE_SIGNATURE; /** * Triggered when the converter has created a parameter reflection. * The listener will be given {@link Context}, {@link Models.ParameterReflection} and a `ts.Node?` * @event */ static EVENT_CREATE_PARAMETER = ConverterEvents.CREATE_PARAMETER; /** * Triggered when the converter has created a type parameter reflection. * The listener will be given {@link Context} and a {@link Models.TypeParameterReflection} * @event */ static EVENT_CREATE_TYPE_PARAMETER = ConverterEvents.CREATE_TYPE_PARAMETER; /** * Resolve events */ /** * Triggered when the converter begins resolving a project. * The listener will be given {@link Context}. * @event */ static EVENT_RESOLVE_BEGIN = ConverterEvents.RESOLVE_BEGIN; /** * Triggered when the converter resolves a reflection. * The listener will be given {@link Context} and a {@link Reflection}. * @event */ static EVENT_RESOLVE = ConverterEvents.RESOLVE; /** * Triggered when the converter has finished resolving a project. * The listener will be given {@link Context}. * @event */ static EVENT_RESOLVE_END = ConverterEvents.RESOLVE_END; /** @internal @hidden */ includePlugin; constructor(owner) { super(owner); const userConfiguredSymbolResolver = (ref, refl, _part, symbolId) => { if (symbolId) { return userConfiguredSymbolResolver(symbolId.toDeclarationReference(), refl, undefined, undefined); } // Require global links, matching local ones will likely hide mistakes where the // user meant to link to a local type. if (ref.resolutionStart !== "global" || !ref.symbolReference) { return; } const modLinks = this.externalSymbolLinkMappings[ref.moduleSource ?? "global"]; if (typeof modLinks !== "object") { return; } let name = ""; if (ref.symbolReference.path) { name += ref.symbolReference.path.map((p) => p.path).join("."); } if (ref.symbolReference.meaning) { name += meaningToString(ref.symbolReference.meaning); } if (typeof modLinks[name] === "string") { return modLinks[name]; } if (typeof modLinks["*"] === "string") { return modLinks["*"]; } }; this.addUnknownSymbolResolver(userConfiguredSymbolResolver); new CategoryPlugin(this); new CommentPlugin(this); new GroupPlugin(this); new ImplementsPlugin(this); new InheritDocPlugin(this); new LinkResolverPlugin(this); new PackagePlugin(this); new SourcePlugin(this); new TypePlugin(this); this.includePlugin = new IncludePlugin(this); new MergeModuleWithPlugin(this); } /** * Compile the given source files and create a project reflection for them. */ convert(entryPoints) { const programs = unique(entryPoints.map((e) => e.program)); this.externalPatternCache = void 0; const project = new ProjectReflection(this.application.options.getValue("name"), this.application.files); const context = new Context(this, programs, project); this.trigger(Converter.EVENT_BEGIN, context); this.addProjectDocuments(project); this.compile(entryPoints, context); this.resolve(context); this.trigger(Converter.EVENT_END, context); this._config = undefined; return project; } /** @internal */ addProjectDocuments(project) { const projectDocuments = getDocumentEntryPoints(this.application.logger, this.application.options); for (const { displayName, path } of projectDocuments) { let file; try { file = new MinimalSourceFile(readFile(path), path); } catch (error) { this.application.logger.error(this.application.logger.i18n.failed_to_read_0_when_processing_project_document(path)); continue; } this.addDocument(project, file, displayName); } } /** @internal */ convertSymbol(context, symbol, exportSymbol) { convertSymbol(context, symbol, exportSymbol); } /** * Convert the given TypeScript type into its TypeDoc type reflection. * * @param context The context object describing the current state the converter is in. * @returns The TypeDoc type reflection representing the given node and type. * @internal */ convertType(context, node) { return convertType(context, node); } /** * Parse the given file into a comment. Intended to be used with markdown files. */ parseRawComment(file, files) { return parseCommentString(lexCommentString(file.text), this.config, file, this.application.logger, files); } /** * Adds a new resolver that the theme can use to try to figure out how to link to a symbol declared * by a third-party library which is not included in the documentation. * * The resolver function will be passed a declaration reference which it can attempt to resolve. If * resolution fails, the function should return undefined. * * Note: This will be used for both references to types declared in node_modules (in which case the * reference passed will have the `moduleSource` set and the `symbolReference` will navigate via `.`) * and user defined \{\@link\} tags which cannot be resolved. If the link being resolved is inferred * from a type, then no `part` will be passed to the resolver function. */ addUnknownSymbolResolver(resolver) { this._externalSymbolResolvers.push(resolver); } /** @internal */ resolveExternalLink(ref, refl, part, symbolId) { for (const resolver of this._externalSymbolResolvers) { const resolved = resolver(ref, refl, part, symbolId); if (resolved) return resolved; } } resolveLinks(comment, owner) { if (comment instanceof Comment) { resolveLinks(comment, owner, (ref, part, refl, id) => this.resolveExternalLink(ref, part, refl, id), { preserveLinkText: this.preserveLinkText }); } else { return resolvePartLinks(owner, comment, (ref, part, refl, id) => this.resolveExternalLink(ref, part, refl, id), { preserveLinkText: this.preserveLinkText }); } } /** * Compile the files within the given context and convert the compiler symbols to reflections. * * @param context The context object describing the current state the converter is in. * @returns An array containing all errors generated by the TypeScript compiler. */ compile(entryPoints, context) { const entries = entryPoints.map((e) => { return { entryPoint: e, context: undefined, }; }); let createModuleReflections = entries.length > 1; if (!createModuleReflections) { const opts = this.application.options; createModuleReflections = opts.isSet("alwaysCreateEntryPointModule") ? opts.getValue("alwaysCreateEntryPointModule") : !!context.scope.documents; } if (createModuleReflections) { this.trigger(ConverterEvents.CREATE_PROJECT, context, context.project); } entries.forEach((e) => { context.setActiveProgram(e.entryPoint.program); e.context = this.convertExports(context, e.entryPoint, createModuleReflections); }); for (const { entryPoint, context } of entries) { // active program is already set on context // if we don't have a context, then this entry point is being ignored if (context) { this.convertReExports(context, entryPoint.sourceFile); } } context.setActiveProgram(undefined); } convertExports(context, entryPoint, createModuleReflections) { const node = entryPoint.sourceFile; const entryName = entryPoint.displayName; const symbol = getSymbolForModuleLike(context, node); let moduleContext; if (createModuleReflections === false) { // Special case for when we're giving a single entry point, we don't need to // create modules for each entry. Register the project as this module. context.project.registerReflection(context.project, symbol, entryPoint.sourceFile.fileName); context.project.comment = symbol ? context.getComment(symbol, context.project.kind) : context.getFileComment(node); this.processDocumentTags(context.project, context.project); this.trigger(ConverterEvents.CREATE_PROJECT, context, context.project); moduleContext = context; } else { const reflection = context.createDeclarationReflection(ReflectionKind.Module, symbol, void 0, entryName); if (!reflection.comment && !symbol) { reflection.comment = context.getFileComment(node); } context.finalizeDeclarationReflection(reflection); moduleContext = context.withScope(reflection); } const allExports = getExports(context, node, symbol); for (const exp of allExports.filter((exp) => isDirectExport(context.resolveAliasedSymbol(exp), node))) { this.convertSymbol(moduleContext, exp); } return moduleContext; } convertReExports(moduleContext, node) { for (const exp of getExports(moduleContext, node, moduleContext.project.getSymbolFromReflection(moduleContext.scope)).filter((exp) => !isDirectExport(moduleContext.resolveAliasedSymbol(exp), node))) { this.convertSymbol(moduleContext, exp); } } /** * Resolve the project within the given context. * * @param context The context object describing the current state the converter is in. * @returns The final project reflection. */ resolve(context) { this.trigger(Converter.EVENT_RESOLVE_BEGIN, context); const project = context.project; for (const id in project.reflections) { this.trigger(Converter.EVENT_RESOLVE, context, project.reflections[id]); } this.trigger(Converter.EVENT_RESOLVE_END, context); } /** * Used to determine if we should immediately bail when creating a reflection. * Note: This should not be used for excludeNotDocumented because we don't have enough * information at this point since comment discovery hasn't happened. * @internal */ shouldIgnore(symbol) { if (this.isExcluded(symbol)) { return true; } return this.excludeExternals && this.isExternal(symbol); } isExcluded(symbol) { this.excludeCache ??= createMinimatch(this.application.options.getValue("exclude")); const cache = this.excludeCache; return (symbol.getDeclarations() ?? []).some((node) => matchesAny(cache, node.getSourceFile().fileName)); } /** @internal */ isExternal(symbol) { this.externalPatternCache ??= createMinimatch(this.externalPattern); const cache = this.externalPatternCache; return (symbol.getDeclarations() ?? []).some((node) => matchesAny(cache, node.getSourceFile().fileName)); } processDocumentTags(reflection, parent) { let relativeTo = reflection.comment?.sourcePath; if (relativeTo) { relativeTo = dirname(relativeTo); const tags = reflection.comment?.getTags("@document") || []; reflection.comment?.removeTags("@document"); for (const tag of tags) { const path = Comment.combineDisplayParts(tag.content); let file; try { const resolved = resolve(relativeTo, path); file = new MinimalSourceFile(readFile(resolved), resolved); } catch { this.application.logger.warn(this.application.logger.i18n.failed_to_read_0_when_processing_document_tag_in_1(nicePath(path), nicePath(reflection.comment.sourcePath))); continue; } this.addDocument(parent, file, basename(file.fileName).replace(/\.[^.]+$/, "")); } } } addDocument(parent, file, displayName) { const { content, frontmatter } = this.parseRawComment(file, parent.project.files); const children = frontmatter["children"]; delete frontmatter["children"]; const docRefl = new DocumentReflection(displayName, parent, content, frontmatter); parent.addChild(docRefl); parent.project.registerReflection(docRefl, undefined, file.fileName); this.trigger(ConverterEvents.CREATE_DOCUMENT, undefined, docRefl); const childrenToAdd = []; if (children && typeof children === "object") { if (Array.isArray(children)) { for (const child of children) { if (typeof child === "string") { childrenToAdd.push([ basename(child).replace(/\.[^.]+$/, ""), child, ]); } else { this.application.logger.error(this.application.i18n.frontmatter_children_0_should_be_an_array_of_strings_or_object_with_string_values(nicePath(file.fileName))); return; } } } else { for (const [name, path] of Object.entries(children)) { if (typeof path === "string") { childrenToAdd.push([name, path]); } else { this.application.logger.error(this.application.i18n.frontmatter_children_0_should_be_an_array_of_strings_or_object_with_string_values(nicePath(file.fileName))); return; } } } } for (const [displayName, path] of childrenToAdd) { const absPath = resolve(dirname(file.fileName), path); let childFile; try { childFile = new MinimalSourceFile(readFile(absPath), absPath); } catch (error) { this.application.logger.error(this.application.logger.i18n.failed_to_read_0_when_processing_document_child_in_1(path, nicePath(file.fileName))); continue; } this.addDocument(docRefl, childFile, displayName); } } _buildCommentParserConfig() { this._config = { blockTags: new Set(this.application.options.getValue("blockTags")), inlineTags: new Set(this.application.options.getValue("inlineTags")), modifierTags: new Set(this.application.options.getValue("modifierTags")), jsDocCompatibility: this.application.options.getValue("jsDocCompatibility"), suppressCommentWarningsInDeclarationFiles: this.application.options.getValue("suppressCommentWarningsInDeclarationFiles"), useTsLinkResolution: this.application.options.getValue("useTsLinkResolution"), commentStyle: this.application.options.getValue("commentStyle"), }; // Can't be included in options because the TSDoc parser blows up if we do. // TypeDoc supports it as one, so it should always be included here. this._config.blockTags.add("@inheritDoc"); return this._config; } }; })(); export { Converter }; function getSymbolForModuleLike(context, node) { const symbol = context.checker.getSymbolAtLocation(node) ?? node.symbol; if (symbol) { return symbol; } // This is a global file, get all symbols declared in this file... // this isn't the best solution, it would be nice to have all globals given to a special // "globals" file, but this is uncommon enough that I'm skipping it for now. const sourceFile = node.getSourceFile(); const globalSymbols = context.checker .getSymbolsInScope(node, ts.SymbolFlags.ModuleMember) .filter((s) => s.getDeclarations()?.some((d) => d.getSourceFile() === sourceFile)); // Detect declaration files with declare module "foo" as their only export // and lift that up one level as the source file symbol if (globalSymbols.length === 1 && globalSymbols[0] .getDeclarations() ?.every((declaration) => ts.isModuleDeclaration(declaration) && ts.isStringLiteral(declaration.name))) { return globalSymbols[0]; } } function getExports(context, node, symbol) { let result; // The generated docs aren't great, but you really ought not be using // this in the first place... so it's better than nothing. const exportEq = symbol?.exports?.get("export="); if (exportEq) { // JS users might also have exported types here. // We need to filter for types because otherwise static methods can show up as both // members of the export= class and as functions if a class is directly exported. result = [exportEq].concat(context.checker .getExportsOfModule(symbol) .filter((s) => !hasAnyFlag(s.flags, ts.SymbolFlags.Prototype | ts.SymbolFlags.Value))); } else if (symbol) { result = context.checker .getExportsOfModule(symbol) .filter((s) => !hasAllFlags(s.flags, ts.SymbolFlags.Prototype)); if (result.length === 0) { const globalDecl = node.statements.find((s) => ts.isModuleDeclaration(s) && s.flags & ts.NodeFlags.GlobalAugmentation); if (globalDecl) { const globalSymbol = context.getSymbolAtLocation(globalDecl); if (globalSymbol) { result = context.checker .getExportsOfModule(globalSymbol) .filter((exp) => exp.declarations?.some((d) => d.getSourceFile() === node)) .map((s) => context.checker.getMergedSymbol(s)); } } } } else { // Global file with no inferred top level symbol, get all symbols declared in this file. const sourceFile = node.getSourceFile(); result = context.checker .getSymbolsInScope(node, ts.SymbolFlags.ModuleMember) .filter((s) => s .getDeclarations() ?.some((d) => d.getSourceFile() === sourceFile)); } // Put symbols named "default" last, #1795 result.sort((a, b) => { if (a.name === "default") { return 1; } else if (b.name === "default") { return -1; } return 0; }); return result; } function isDirectExport(symbol, file) { return (symbol .getDeclarations() ?.every((decl) => decl.getSourceFile() === file) ?? false); }