typedoc-plugin-typescript-declaration
Version:
Typedoc plugin to render to typescript declaration file
1,265 lines (1,223 loc) • 62.6 kB
JavaScript
'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