UNPKG

typedoc-plugin-typescript-declaration

Version:

Typedoc plugin to render to typescript declaration file

1,265 lines (1,223 loc) 62.6 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var typedoc = require('typedoc'); var utils = require('typedoc/dist/lib/utils'); var fs = require('fs'); var path = require('path'); var declaration = require('typedoc/dist/lib/utils/options/declaration'); var models = require('typedoc/dist/lib/models'); var renderer = require('typedoc/dist/lib/output/renderer'); var components = require('typedoc/dist/lib/output/components'); var events = require('typedoc/dist/lib/output/events'); var mkdir = _interopDefault(require('make-dir')); var help = require('typedoc/dist/lib/utils/options/help'); var converter = require('typedoc/dist/lib/converter'); var components$1 = require('typedoc/dist/lib/converter/components'); class PausableLogger extends utils.ConsoleLogger { constructor(startLogging = false) { super(); this._isLogging = startLogging; this._logBuffer = []; } pause() { this._isLogging = false; } resume() { this.flushLogs(); this._isLogging = true; } flushLogs() { let message; while ((message = this._logBuffer.shift())) { this.logForReal(message.message, message.level, message.newLine); } } log(message, level, newLine) { if (level === utils.LogLevel.Error) { this.errorCount++; } if (this._isLogging) { this.logForReal(message, level, newLine); } else { this._logBuffer.push({ message, level, newLine }); } } logForReal(message, level, newLine) { this.errorCount--; // error count already incremented before this call. super.log(message, level, newLine); } } /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function join(delimiter, ...values) { return values.filter(v => v !== null && v !== undefined && v !== '') .join(delimiter); } class CommentRenderer { render(node) { var _a; let lines = []; const sections = []; const comment = node.comment; if (comment) { if (comment.shortText) { sections.push(this.renderMultilineComment('', comment.shortText)); } if (comment.text) { sections.push(this.renderMultilineComment('', comment.text)); } if (node.kind === models.ReflectionKind.Event) { sections.push(' * @event'); } const signature = node; const paramsSection = []; if (signature.parameters) { const paramComments = signature.parameters .filter(p => { var _a, _b; return ((_a = p.comment) === null || _a === void 0 ? void 0 : _a.text) || ((_b = p.comment) === null || _b === void 0 ? void 0 : _b.shortText); }) .map(p => { var _a, _b; return this.renderMultilineComment(`@param ${p.name}`, ((_a = p.comment) === null || _a === void 0 ? void 0 : _a.text) || ((_b = p.comment) === null || _b === void 0 ? void 0 : _b.shortText) || ''); }) .join('\n'); if (paramComments.length) { paramsSection.push(paramComments); } } if (comment.returns) { paramsSection.push(this.renderMultilineComment('@returns', comment.returns)); } if (paramsSection.length) { sections.push(paramsSection.join('\n')); } if ((_a = comment.tags) === null || _a === void 0 ? void 0 : _a.length) { sections.push(comment.tags .map(t => this.renderMultilineComment(`@${t.tagName}`, t.text)) .join('\n')); } if (sections.length) { lines.push(sections.join('\n *\n')); } } if (lines.length) { lines = ['/**', ...lines, ' */']; } return lines.join('\n'); } renderMultilineComment(prefix, comment) { const [firstLine, ...remainingLines] = comment.replace(/\n$/, '').split(/\n/gm); return ` * ${join(' ', prefix, firstLine || '')}${(remainingLines === null || remainingLines === void 0 ? void 0 : remainingLines.length) ? `\n${remainingLines.map(l => ` * ${l}`.trimRight()).join('\n')}` : ''}`; } } class Indentor { constructor(indentString) { this._indentCache = {}; this._indentString = indentString; } getIndent(size) { var _a; if (size === 0) return ''; const indentString = (_a = this._indentString) !== null && _a !== void 0 ? _a : Indentor.indentString; const key = `${indentString}_${size}`; let indent = this._indentCache[key]; if (indent === undefined) { indent = new Array(size).fill(indentString).join(''); this._indentCache[key] = indent; } return indent; } static instance() { if (!Indentor._instance) { Indentor._instance = new Indentor(); } return Indentor._instance; } } Indentor.indentString = ' '; class ReflectionRenderer { constructor() { this._indentor = Indentor.instance(); this._commentRenderer = new CommentRenderer(); } getModifiers(node, parent) { if (!node) return []; const modifiers = []; const flags = node.flags; const parentFlags = parent === null || parent === void 0 ? void 0 : parent.flags; // if (flags.isExported || parentFlags?.isExported) { // modifiers.push('export'); // } if (flags.isPublic || (parentFlags === null || parentFlags === void 0 ? void 0 : parentFlags.isPublic)) { modifiers.push('public'); } else if (flags.isProtected || (parentFlags === null || parentFlags === void 0 ? void 0 : parentFlags.isProtected)) { modifiers.push('protected'); } else if (flags.isPrivate || (parentFlags === null || parentFlags === void 0 ? void 0 : parentFlags.isPrivate)) { modifiers.push('private'); } if (flags.isStatic || (parentFlags === null || parentFlags === void 0 ? void 0 : parentFlags.isStatic)) { modifiers.push('static'); } if (flags.isAbstract || (parentFlags === null || parentFlags === void 0 ? void 0 : parentFlags.isAbstract)) { modifiers.push('abstract'); } if (flags.isConst || (parentFlags === null || parentFlags === void 0 ? void 0 : parentFlags.isConst)) { modifiers.push('const'); } if (flags.isLet || (parentFlags === null || parentFlags === void 0 ? void 0 : parentFlags.isLet)) { modifiers.push('let'); } return modifiers; } renderComment(node) { return this._commentRenderer.render(node); } encodeName(name) { return /[^\w]/.test(name) ? JSON.stringify(name) : name; } isTop(node) { return !node.parent || (node.parent && node.parent.kind === models.ReflectionKind.Global); } getTag(node, tag) { var _a, _b; return (_b = (_a = node.comment) === null || _a === void 0 ? void 0 : _a.tags) === null || _b === void 0 ? void 0 : _b.find(t => t.tagName === tag); } pushIfTruthy(array, value) { if (value) { array.push(value); } } } class AccessorRenderer extends ReflectionRenderer { render(node, terminationCharacter) { const method = node; return join('\n', ReflectionFormatter.instance().render(method.getSignature, terminationCharacter), ReflectionFormatter.instance().render(method.setSignature, terminationCharacter)); } } const defaultOptions = { isOptionalType: false, includeConstraints: true, }; class TypeFormatter { static format(type, options) { const mergedOptions = Object.assign(Object.assign({}, defaultOptions), options); if (type.type === 'array') { return `${TypeFormatter.format(type.elementType)}[]`; } if (type.type === 'conditional') { const conType = type; return `${TypeFormatter.format(conType.checkType)} extends ${TypeFormatter.format(conType.extendsType)} ? ${TypeFormatter.format(conType.trueType)} : ${TypeFormatter.format(conType.falseType)}`; } if (type.type === 'indexedAccess') { const indexType = type; return `${TypeFormatter.format(indexType.objectType)}[${TypeFormatter.format(indexType.indexType)}]`; } if (type.type === 'intersection') { return type.types.map(t => TypeFormatter.format(t)).join(' & '); } if (type.type === 'predicate') { const predType = type; if (predType.targetType) { return `${predType.name} is ${TypeFormatter.format(predType.targetType)}`; } } if (type.type === 'reference') { const refType = type; let declaration = refType.name; if (refType.typeArguments) { declaration += `<${refType.typeArguments.map(t => TypeFormatter.format(t)).join(', ')}>`; } if (declaration === '__type') { declaration = '{}'; } return declaration; } if (type.type === 'reflection') { const refType = type; return ReflectionFormatter.instance().render(refType.declaration); } if (type.type === 'stringLiteral') { return JSON.stringify(type.value); } if (type.type === 'tuple') { return `[${type.elements.map(t => TypeFormatter.format(t)).join(', ')}]`; } if (type.type === 'typeOperator') { const typeOperatorType = type; return `${typeOperatorType.operator} ${TypeFormatter.format(typeOperatorType.target)}`; } if (type.type === 'typeParameter') { const typeParamType = type; if (typeParamType.constraint && mergedOptions.includeConstraints) { return `${typeParamType.name} extends ${TypeFormatter.format(typeParamType.constraint)}`; } } if (type.type === 'union') { return type.types .filter(t => { const intrinsicType = t; return !mergedOptions.isOptionalType || !(intrinsicType.type === 'intrinsic' && intrinsicType.name === 'undefined'); }) .map(t => TypeFormatter.format(t)).join(' | '); } if (type.type === 'query') { return `typeof ${TypeFormatter.format(type.queryType)}`; } const other = type; if (other.name) { return other.name; } throw (`Unrecognized type: ${type.type}`); } } class SignatureRenderer extends ReflectionRenderer { renderTypeParameters(method) { if (method.typeParameters) { return `<${method.typeParameters.map(p => ReflectionFormatter.instance().render(p)).join(', ')}>`; } return ''; } renderParameters(method) { let declaration = '('; if (method.parameters) { declaration += method.parameters.map(p => ReflectionFormatter.instance().render(p)).join(', '); } declaration += ')'; return declaration; } renderReturnType(method) { var _a; if (method.type) { return `${((_a = method.parent) === null || _a === void 0 ? void 0 : _a.kind) === models.ReflectionKind.TypeLiteral && method.kind !== models.ReflectionKind.IndexSignature ? ' =>' : ':'} ${TypeFormatter.format(method.type, { includeConstraints: false })}`; } return ''; } } class CallSignatureRenderer extends SignatureRenderer { render(node, terminationCharacter) { var _a, _b; const lines = []; const declarationParts = [ this.isTop(node) ? 'declare' : '', ...this.getModifiers(node, node.parent), ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.kind) === models.ReflectionKind.Function ? 'function' : '', ((_b = node.parent) === null || _b === void 0 ? void 0 : _b.kind) === models.ReflectionKind.TypeLiteral ? '' : node.name, ]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const method = node; let declaration = join(' ', ...declarationParts); declaration += this.renderTypeParameters(method); declaration += this.renderParameters(method); declaration += this.renderReturnType(method); if (terminationCharacter) { declaration += terminationCharacter; } lines.push(declaration); return lines.join('\n'); } } class ConstructorSignatureRenderer extends SignatureRenderer { render(node, terminationCharacter) { var _a, _b; const lines = []; const isTypeLiteral = ((_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.kind) === models.ReflectionKind.TypeLiteral; const declarationParts = [...this.getModifiers(node, node.parent), isTypeLiteral ? 'new' : 'constructor']; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const method = node; let declaration = join(' ', ...declarationParts); declaration += this.renderTypeParameters(method); declaration += this.renderParameters(method); if (isTypeLiteral) { declaration += this.renderReturnType(method); } if (terminationCharacter) { declaration += terminationCharacter; } lines.push(declaration); return lines.join('\n'); } } function propertySorter(selector) { return (a, b) => { const valA = selector(a); const valB = selector(b); if (valA > valB) { return 1; } if (valA < valB) { return -1; } return 0; }; } class ContainerRenderer extends ReflectionRenderer { constructor(type) { super(); this._type = type; } render(node) { const lines = []; const declarationParts = [ this.isTop(node) ? 'declare' : '', ...this.getModifiers(node), this._type, `${node.name}${this.renderTypeParameters(node)}` ]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const declarationNode = node; if (declarationNode.extendedTypes) { if (declarationNode.extendedTypes.length >= 1) { declarationParts.push('extends', TypeFormatter.format(declarationNode.extendedTypes[0])); if (declarationNode.extendedTypes.length > 1) { declarationParts.push('implements', declarationNode.extendedTypes.slice(1).map(t => TypeFormatter.format(t)).join(', ')); } } } lines.push(join(' ', ...declarationParts, '{')); const body = this.renderBody(declarationNode); if (body) { lines.push(body); } lines.push('}'); return lines.join('\n'); } renderBody(declarationNode, indentBy = 1, delimiter = ';') { let sorter; const isGroupType = !!['module', 'project'].find(type => type === this._type); const insertBlankLine = !!['class', 'module', 'interface', 'project'].find(type => type === this._type); sorter = propertySorter(node => node.id); if ((isGroupType && this.isSortFlag(declarationNode, ReflectionSortFlags.container)) || !isGroupType && this.isSortFlag(declarationNode, ReflectionSortFlags.leaf)) { sorter = propertySorter(node => node.name); } const children = []; if (declarationNode.children) { children.push(...declarationNode.children); } if (declarationNode.indexSignature) { children.push(declarationNode.indexSignature); } if (children.length) { const members = children .filter(node => !node.inheritedFrom) .filter(node => { var _a; const ownedSources = (_a = node.sources) === null || _a === void 0 ? void 0 : _a.filter(s => !/^node_modules\//i.test(s.fileName)); return !node.sources || (ownedSources === null || ownedSources === void 0 ? void 0 : ownedSources.length) !== 0; }) .sort(sorter) .map(node => ReflectionFormatter.instance().render(node, delimiter)) .filter(s => s) .join(insertBlankLine ? '\n\n' : '\n'); const indent = this._indentor.getIndent(indentBy); if (indent) { return members.split(/\r?\n(?=.)/gm).map(l => `${indent}${l}`).join('\n'); } return members; } return ''; } renderTypeParameters(node) { if (node.typeParameters) { return `<${node.typeParameters.map(p => ReflectionFormatter.instance().render(p)).join(', ')}>`; } return ''; } isSortFlag(node, ...flags) { return !!flags.find(flag => (this.getSortOption(node) & flag) === flag); } getSortOption(node) { var _a; let current = node; let sort = ''; while (current) { sort = ((_a = this.getTag(current, 'sortoption')) === null || _a === void 0 ? void 0 : _a.text.trim()) || ''; if (sort) { break; } current = current.parent; } return sortMapping[sort] || ReflectionFormatter.sortOption; } } class EnumMemberRenderer extends ReflectionRenderer { render(node) { const lines = []; const declarationParts = [...this.getModifiers(node), node.name]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const member = node; let declaration = join(' ', ...declarationParts); if (member.defaultValue) { declaration += ` = ${member.defaultValue}`; } declaration += ','; lines.push(declaration); return lines.join('\n'); } } class EventRenderer extends CallSignatureRenderer { render(node, terminationCharacter) { const method = node; if (method.signatures) { const lines = method.signatures .map(s => ReflectionFormatter.instance().render(s, terminationCharacter)); return lines.join('\n'); } return super.render(method, terminationCharacter); } } class FunctionRenderer extends ReflectionRenderer { render(node, terminationCharacter) { const method = node; const lines = method.signatures .map(s => ReflectionFormatter.instance().render(s, ';')); return lines.join('\n'); } } class GetSignatureRenderer extends SignatureRenderer { render(node, terminationCharacter) { var _a; const lines = []; const declarationParts = [ ...this.getModifiers(node, node.parent), 'get', ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.name) || node.name, ]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const method = node; let declaration = join(' ', ...declarationParts); declaration += this.renderTypeParameters(method); declaration += this.renderParameters(method); declaration += this.renderReturnType(method); if (terminationCharacter) { declaration += terminationCharacter; } lines.push(declaration); return lines.join('\n'); } } class IndexSignatureRenderer extends SignatureRenderer { render(node, terminationCharacter) { const lines = []; const declarationParts = [ ...this.getModifiers(node, node.parent), ]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const method = node; let declaration = join(' ', ...declarationParts); declaration += this.renderParameters(method).replace(/^\(/, '[').replace(/\)$/, ']'); declaration += this.renderReturnType(method); if (terminationCharacter) { declaration += terminationCharacter; } lines.push(declaration); return lines.join('\n'); } } class MethodRenderer extends ReflectionRenderer { render(node, terminationCharacter) { const method = node; const lines = method.signatures .map(s => ReflectionFormatter.instance().render(s, terminationCharacter)); return lines.join('\n'); } } class ModuleRenderer extends ContainerRenderer { constructor() { super('module'); } render(node) { var _a; if (this.isNamespace(node)) { let renderNode = node; const nodeNames = []; let latestComment; let currentComment; do { currentComment = this.renderComment(renderNode); // cannot combine modules into namespace because comments differ if (latestComment && currentComment && latestComment !== currentComment) { break; } if (currentComment) { latestComment = currentComment; } nodeNames.push(renderNode.name); if (((_a = renderNode.children) === null || _a === void 0 ? void 0 : _a.length) === 1 && renderNode.children[0].kindOf(models.ReflectionKind.SomeModule)) { const nextNode = renderNode.children[0]; const nextComment = this.renderComment(nextNode); // cannot combine modules into namespace because comments differ if (latestComment && nextComment && latestComment !== nextComment) { break; } renderNode = nextNode; } else { break; } } while (this.isNamespace(renderNode)); const lines = []; const declarationParts = [ this.isTop(node) ? 'declare' : '', 'namespace', `${nodeNames.join('.')}` ]; if (latestComment) { this.pushIfTruthy(lines, latestComment); } lines.push(join(' ', ...declarationParts, '{')); const body = this.renderBody(renderNode); if (body) { lines.push(body); } lines.push('}'); return lines.join('\n'); } return super.render(node); } isNamespace(node) { const hasSpecialCharacterExpression = /[^\w]/; return !hasSpecialCharacterExpression.test(node.name); } } class ObjectLiteralRenderer extends ContainerRenderer { constructor() { super('object_literal'); } render(node, terminationCharacter) { const lines = []; const declarationParts = [ this.isTop(node) ? 'declare' : '', ...this.getModifiers(node), `${node.name}:`, ]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const declarationNode = node; lines.push(join(' ', ...declarationParts, '{')); const body = this.renderBody(declarationNode, 1, ','); if (body) { lines.push(body); } lines.push('};'); return lines.join('\n'); } getModifiers(node, parent) { let modifiers = super.getModifiers(node, parent); if (!modifiers.find(m => m === 'const' || m === 'let')) { modifiers = [...modifiers, 'var']; } return modifiers; } } class ParameterRenderer extends ReflectionRenderer { render(node) { const p = node; let declaration = `${p.flags.isRest ? '...' : ''}${this.getName(p)}${p.flags.isOptional ? '?' : ''}${p.type ? `: ${TypeFormatter.format(p.type, { isOptionalType: p.flags.isOptional, includeConstraints: false, })}` : ''}`; return declaration; } getName(parameter) { var _a; const type = parameter.type; if (parameter.name === '__namedParameters') { if ((_a = type.declaration) === null || _a === void 0 ? void 0 : _a.children) { return join(' ', '{', type.declaration.children.map(c => c.name).join(', '), '}'); } if (parameter.originalName) { const origMatch = /^__(\d+)$/.exec(parameter.originalName); if (origMatch) { const origNumber = parseInt(origMatch[1], 10); return `__param${origNumber + 1}`; } } } return parameter.name; } } class ProjectRenderer extends ContainerRenderer { constructor() { super('project'); } render(node) { return this.renderBody(node, 0); } } class PropertyRenderer extends ReflectionRenderer { render(node, terminationCharacter) { const lines = []; const declarationParts = [...this.getModifiers(node), `${this.encodeName(node.name)}${node.flags.isOptional ? '?' : ''}`]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const member = node; let declaration = join(' ', ...declarationParts); if (member.type) { declaration += `: ${TypeFormatter.format(member.type, { isOptionalType: node.flags.isOptional })}`; } if (terminationCharacter) { declaration += terminationCharacter; } lines.push(declaration); return lines.join('\n'); } } class SetSignatureRenderer extends SignatureRenderer { render(node, terminationCharacter) { var _a; const lines = []; const declarationParts = [ ...this.getModifiers(node, node.parent), 'set', ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.name) || node.name, ]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const method = node; let declaration = join(' ', ...declarationParts); declaration += this.renderTypeParameters(method); declaration += this.renderParameters(method); if (terminationCharacter) { declaration += terminationCharacter; } lines.push(declaration); return lines.join('\n'); } } class TypeAliasRenderer extends ContainerRenderer { constructor() { super('type_alias'); } render(node, terminationCharacter) { var _a; const lines = []; const declarationParts = [ this.isTop(node) ? 'declare' : '', ...this.getModifiers(node), 'type', node.name, '=' ]; if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } const declarationNode = node; // body const type = declarationNode.type; if ((_a = type.declaration) === null || _a === void 0 ? void 0 : _a.children) { lines.push(join(' ', ...declarationParts, '{')); const body = this.renderBody(type.declaration); if (body) { lines.push(body); } lines.push('}'); } else if (type) { lines.push(join(' ', ...declarationParts, `${TypeFormatter.format(type)}${terminationCharacter}`)); } return lines.join('\n'); } } class TypeLiteralRenderer extends ContainerRenderer { constructor() { super('type_literal'); } render(node) { var _a, _b; const lines = []; const member = node; let indent = false; if (member.signatures && ((_a = member.signatures[0]) === null || _a === void 0 ? void 0 : _a.comment)) { indent = true; } else if (node.comment) { this.pushIfTruthy(lines, this.renderComment(node)); } if (member.children || member.indexSignature) { const children = [...(member.children || []), member.indexSignature].filter(c => c); if (((_b = node.parent) === null || _b === void 0 ? void 0 : _b.kind) === models.ReflectionKind.TypeAlias) { const body = this.renderBody(member, 1, ','); if (body) { lines.push('{', body, '}'); } } else { lines.push(join(' ', '{', children.map(c => ReflectionFormatter.instance().render(c)).join(', '), '}')); } } else if (member.signatures) { let signature = ReflectionFormatter.instance().render(member.signatures[0]); if (indent) { lines.push(''); signature = signature.split('\n').map(l => `${this._indentor.getIndent(1)}${l}`).join('\n'); } lines.push(signature); } else if (member.name === '__type') { lines.push('{}'); } return lines.join('\n'); } } class TypeParameterRenderer extends ReflectionRenderer { render(node) { const p = node; let declaration = p.name; if (p.type) { declaration += ` extends ${TypeFormatter.format(p.type)}`; } return declaration; } } const renderers = { [models.ReflectionKind.Accessor]: new AccessorRenderer(), [models.ReflectionKind.CallSignature]: new CallSignatureRenderer(), [models.ReflectionKind.Class]: new ContainerRenderer('class'), [models.ReflectionKind.Constructor]: new MethodRenderer(), [models.ReflectionKind.ConstructorSignature]: new ConstructorSignatureRenderer(), [models.ReflectionKind.Enum]: new ContainerRenderer('enum'), [models.ReflectionKind.EnumMember]: new EnumMemberRenderer(), [models.ReflectionKind.Event]: new EventRenderer(), [models.ReflectionKind.Function]: new FunctionRenderer(), [models.ReflectionKind.GetSignature]: new GetSignatureRenderer(), [models.ReflectionKind.Global]: new ProjectRenderer(), [models.ReflectionKind.IndexSignature]: new IndexSignatureRenderer(), [models.ReflectionKind.Interface]: new ContainerRenderer('interface'), [models.ReflectionKind.Method]: new MethodRenderer(), [models.ReflectionKind.Module]: new ModuleRenderer(), [models.ReflectionKind.Namespace]: new ModuleRenderer(), [models.ReflectionKind.ObjectLiteral]: new ObjectLiteralRenderer(), [models.ReflectionKind.Parameter]: new ParameterRenderer(), [models.ReflectionKind.Property]: new PropertyRenderer(), [models.ReflectionKind.SetSignature]: new SetSignatureRenderer(), [models.ReflectionKind.TypeAlias]: new TypeAliasRenderer(), [models.ReflectionKind.TypeLiteral]: new TypeLiteralRenderer(), [models.ReflectionKind.TypeParameter]: new TypeParameterRenderer(), [models.ReflectionKind.Variable]: new PropertyRenderer(), }; /** * Sort flags */ var ReflectionSortFlags; (function (ReflectionSortFlags) { ReflectionSortFlags[ReflectionSortFlags["none"] = 0] = "none"; /** * @internal */ ReflectionSortFlags[ReflectionSortFlags["tag"] = 1] = "tag"; ReflectionSortFlags[ReflectionSortFlags["container"] = 2] = "container"; ReflectionSortFlags[ReflectionSortFlags["leaf"] = 4] = "leaf"; ReflectionSortFlags[ReflectionSortFlags["all"] = 7] = "all"; })(ReflectionSortFlags || (ReflectionSortFlags = {})); const sortMapping = { none: ReflectionSortFlags.none, tag: ReflectionSortFlags.tag, container: ReflectionSortFlags.container, leaf: ReflectionSortFlags.leaf, all: ReflectionSortFlags.all, }; class ReflectionFormatter { render(reflection, terminatorCharacter) { if (reflection) { const renderer = renderers[reflection.kind]; if (renderer) { return renderer.render(reflection, terminatorCharacter); } throw new Error(`Unrecognized reflection for kind ${reflection.kindString} ${reflection.name}`); } return ''; } static instance() { if (!ReflectionFormatter._instance) { ReflectionFormatter._instance = new ReflectionFormatter(); } return ReflectionFormatter._instance; } } ReflectionFormatter.sortOption = ReflectionSortFlags.none; const declarationFileOption = { name: 'declarationFile', hint: declaration.ParameterHint.File, type: declaration.ParameterType.String, help: 'The output file location to write the declaration to', }; const declarationOnlyOption = { name: 'declarationOnly', type: declaration.ParameterType.Boolean, help: 'Render the type declaration file only, other renderers will be removed (must be used with --declarationFile option)', }; const sortOptionOption = { name: 'sortOption', type: declaration.ParameterType.Map, help: 'Sort types in declaration file by name instead of the typedoc default', defaultValue: ReflectionSortFlags.none, map: sortMapping, }; const indentStringOption = { name: 'indentString', type: declaration.ParameterType.String, help: 'Indent declarations using this string. Defaults to \' \'', defaultValue: ' ', }; class TypeScriptDeclarationPlugin extends components.RendererComponent { initialize() { this.listenTo(this.owner, { [events.RendererEvent.BEGIN]: this.onRenderBegin, }); } applyConfiguration() { const app = this.application; app.options.read(app.logger); const options = app.options.getRawValues(); if (options.declarationOnly || !options.out) { app.options.setValue('out', './docs'); app.options.setValue('disableOutputCheck', true); app.options.setValue(declarationOnlyOption.name, true); if (options.mode === undefined) { app.options.setValue('mode', utils.SourceFileMode.File); } renderer.Renderer.getDefaultTheme = () => path.join(__dirname, 'themes/noop'); renderer.Renderer.getThemeDirectory = () => path.join(__dirname, 'themes'); app.options.setValue('theme', renderer.Renderer.getDefaultTheme()); app.renderer.getComponents() .filter(c => c.componentName !== 'typescript-declaration') .forEach(c => app.renderer.removeComponent(c.componentName)); } Indentor.indentString = app.options.getValue('indentString'); } verifyProject(project) { if (this._declarationOnly && !this._declarationFile) { throw new Error('--declarationFile file must be specified when using the --declarationOnly option'); } if (!project.children) { const message = ['', 'ERROR: No types found, nothing to write']; const includesDeclaration = !!process.argv.find(arg => arg !== this._declarationFile && /\.d\.ts$/.test(arg)); if (this._declarationOnly && includesDeclaration) { message.push('Consider using the --includeDeclarations option'); } console.error(message.join('\n')); process.exit(1); } } onRenderBegin(event) { this.verifyProject(event.project); } static generateTypeDeclarations(project, sortOption, filename) { const formatter = ReflectionFormatter.instance(); let file = filename; ReflectionFormatter.sortOption = sortOption; const result = formatter.render(project); if (file) { file = path.resolve(process.cwd(), file); const directory = path.dirname(file); if (!fs.existsSync(directory)) { mkdir.sync(directory); } fs.writeFileSync(file, result); console.log(`TypeScript definition file written to ${file}.`); } else { console.log(result); } } } TypeScriptDeclarationPlugin.options = [ declarationFileOption, declarationOnlyOption, sortOptionOption, indentStringOption, ]; __decorate([ utils.BindOption(declarationFileOption.name) ], TypeScriptDeclarationPlugin.prototype, "_declarationFile", void 0); __decorate([ utils.BindOption(declarationOnlyOption.name) ], TypeScriptDeclarationPlugin.prototype, "_declarationOnly", void 0); __decorate([ utils.BindOption(sortOptionOption.name) ], TypeScriptDeclarationPlugin.prototype, "_sortOption", void 0); const packageInfo = require('../package.json'); class CliApplication extends typedoc.Application { constructor(options) { super(); this.logger = new PausableLogger(); this.bootstrap(options); } get pausableLogger() { if (this.logger instanceof PausableLogger) { return this.logger; } return undefined; } bootstrap(options) { var _a; this.options.addReader(new typedoc.ArgumentsReader(0)); this.options.addReader(new typedoc.TypeDocReader()); this.options.addReader(new typedoc.TSConfigReader()); this.options.addReader(new typedoc.ArgumentsReader(300)); const result = super.bootstrap(options); if (result.hasErrors) { (_a = this.pausableLogger) === null || _a === void 0 ? void 0 : _a.resume(); return process.exit(1); } this._inputFiles = result.inputFiles; return result; } start() { var _a, _b, _c; this.options.read(this.logger); const options = this.options.getRawValues(); let { help: help$1, json, out, version } = options; let { declarationFile, declarationOnly, sorOption } = options; if (declarationFile) { (_a = this.pausableLogger) === null || _a === void 0 ? void 0 : _a.resume(); } if (version) { console.log(`${packageInfo.name} ${packageInfo.version}`); console.log(this.toString()); } else if (help$1) { console.log(help.getOptionsHelp(this.options)); } else if (this._inputFiles.length === 0) { console.log(help.getOptionsHelp(this.options)); process.exit(2 /* NoInputFiles */); } else { const src = this.expandInputFiles(this._inputFiles); const project = this.convert(src); if (project) { if (out && !declarationOnly) { this.generateDocs(project, out); } if (json) { this.generateJson(project, json); } TypeScriptDeclarationPlugin.generateTypeDeclarations(project, sorOption, declarationFile); if (this.logger.hasErrors()) { (_b = this.pausableLogger) === null || _b === void 0 ? void 0 : _b.resume(); process.exit(5 /* OutputError */); } } else { (_c = this.pausableLogger) === null || _c === void 0 ? void 0 : _c.resume(); process.exit(4 /* CompileError */); } } } } class KeyOfCommentResolver { shouldResolveKeys(project, reflection) { const node = reflection; if (node.kind === models.ReflectionKind.TypeAlias) { const type = node.type; if ((type === null || type === void 0 ? void 0 : type.type) === 'typeOperator' && (type === null || type === void 0 ? void 0 : type.operator) === 'keyof' && (type === null || type === void 0 ? void 0 : type.target)) { const reference = this.getDeclaration(project, type.target); if (this.getKeys(reference)) { return true; } } } return false; } inlineKeys(project, reflection) { const node = reflection; const type = node.type; const reference = this.getDeclaration(project, type.target); let keys = this.getKeys(reference) .sort(propertySorter(r => r.id)); let types = keys.map(k => new models.StringLiteralType(k.name)); node.type = new models.UnionType(types); if (!node.comment) { node.comment = new models.Comment(); } const lines = []; if (node.comment.text) { lines.push(node.comment.text, ''); } lines.push('Options:', '', ...keys.map(k => { var _a, _b; return `- \`${k.name}\`${((_a = k.comment) === null || _a === void 0 ? void 0 : _a.shortText) || ((_b = k.comment) === null || _b === void 0 ? void 0 : _b.text) ? `:\n${join('\n\n', k.comment.shortText, k.comment.text).replace(/\n$/, '').split(/\n/gm).map(l => ` ${l}`).join('\n')}` : ''}\n`; })); node.comment.text = lines.join('\n'); // remove @inline tag if (node.comment.tags) { const index = node.comment.tags.findIndex(t => t.tagName === 'inline'); if (index !== -1) { node.comment.tags.splice(index, 1); } } } shouldInlineKeys(project, reflection) { var _a; return this.shouldResolveKeys(project, reflection) && ((_a = reflection.comment) === null || _a === void 0 ? void 0 : _a.getTag('inline')); } getDeclaration(project, type) { let reference; if (type.type === 'reference') { const targetType = type; reference = project.findReflectionByName(targetType.name); } else if (type.type === 'reflection') { const reflectionType = type; reference = reflectionType.declaration; } return reference; } getKeys(reflection) { var _a, _b; return (reflection === null || reflection === void 0 ? void 0 : reflection.children) || ((_b = (_a = reflection === null || reflection === void 0 ? void 0 : reflection.type) === null || _a === void 0 ? void 0 : _a.declaration) === null || _b === void 0 ? void 0 : _b.children) || []; } static instance() { if (!KeyOfCommentResolver._instance) { KeyOfCommentResolver._instance = new KeyOfCommentResolver(); } return KeyOfCommentResolver._instance; } } class KeyOfPlugin extends components$1.ConverterComponent { initialize() { this.listenTo(this.owner, { [converter.Converter.EVENT_RESOLVE_BEGIN]: this.onBeginResolve, }); } onBeginResolve(context) { const resolver = KeyOfCommentResolver.instance(); Object.values(context.project.reflections) .filter(item => resolver.shouldInlineKeys(context.project, item)) .forEach(item => resolver.inlineKeys(context.project, item)); } } KeyOfPlugin.options = []; const omitTagOption = { name: 'omitTag', type: declaration.ParameterType.Array, help: 'A list of tags to remove from the generated output', }; class OmitTagsPlugin extends components$1.ConverterComponent { initialize() { this.listenTo(this.owner, { [converter.Converter.EVENT_RESOLVE_BEGIN]: this.onBeginResolve, }); } onBeginResolve(context) { if (this._omitTags) { const project = context.project; OmitTagsPlugin.removeTags(Object.values(project.reflections), this._omitTags); } } static removeTags(reflections, tags) { reflections.forEach(r => { var _a; if ((_a = r.comment) === null || _a === void 0 ? void 0 : _a.tags) { const tagsToKeep = r.comment.tags .filter(t => !tags.find(o => o === t.tagName)); r.comment.tags = tagsToKeep; } }); } } OmitTagsPlugin.options = [ omitTagOption, ]; __decorate([ typedoc.BindOption(omitTagOption.name) ], OmitTagsPlugin.prototype, "_omitTags", void 0); const removeSourceOption = { name: 'removeSource', type: declaration.ParameterType.Boolean, help: 'Remove source elements from rendered output', defaultValue: false, }; class RemoveSourcePlugin extends components$1.ConverterComponent { initialize() { this.listenTo(this.owner, { [converter.Converter.EVENT_RESOLVE_END]: this.onEndResolve, }); } onEndResolve(context) { if (this._removeSource) { Object.values(context.project.reflections).forEach(reflection => { reflection.sources = undefined; }); } } } RemoveSourcePlugin.options = [ removeSourceOption, ]; __decorate([ utils.BindOption(removeSourceOption.name) ], RemoveSourcePlugin.prototype, "_removeSource", void 0); class UnresolvedTypesMapper { constructor(project) { this._project = project; this._knownReflectionNames = new Set(); this._knownReflections = new Set(); this._currentReflections = new Set(); } clearKnownReflections() { this._knownReflectionNames.clear(); this._knownReflections.clear(); } registerKnownReflection(reflection) { this._knownReflections.add(reflection); if (reflection.kindOf(models.ReflectionKind.ClassOrInterface | models.ReflectionKind.TypeAlias | models.ReflectionKind.SomeModule)) { const namespace = reflection.getFullName('.').split('.'); for (let i = 0; i < namespace.length; i++) { this._knownReflectionNames.add(namespace.slice(i).join('.')); } } } registerKnownReflections(reflections) { reflections.forEach(reflection => { this.registerKnownReflection(reflection); }); } resolve() { this._currentReflections.clear(); Object.values(this._project.reflections).forEach(reflection => this._currentReflections.add(reflection)); this.getReflectionsByInstanceType(this._project, typedoc.DeclarationReflection).forEach(reflection => { var _a; reflection.extendedTypes = (_a = reflection.extendedTypes) === null || _a === void 0 ? void 0 : _a.filter(t => this.isMapped(t)); reflection.type = this.remapType(reflection.type); }); this.getReflectionsByInstanceType(this._project, models.SignatureReflection).forEach(reflection => { var _a, _b; reflection.type = this.remapType(reflection.type); (_a = reflection.parameters) === null || _a === void 0 ? void 0 : _a.forEach(p => p.type = this.remapType(p.type)); (_b = reflection.typeParameters) === null || _b === void 0 ? void 0 : _b.forEach(p => p.type = this.rema