379 lines
17 KiB
JavaScript
379 lines
17 KiB
JavaScript
"use strict";
|
|
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
|
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
|
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
|
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
|
r[k] = a[j];
|
|
return r;
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.TSDocEmitter = void 0;
|
|
var DocNode_1 = require("../nodes/DocNode");
|
|
var DocNodeTransforms_1 = require("../transforms/DocNodeTransforms");
|
|
var StandardTags_1 = require("../details/StandardTags");
|
|
var LineState;
|
|
(function (LineState) {
|
|
LineState[LineState["Closed"] = 0] = "Closed";
|
|
LineState[LineState["StartOfLine"] = 1] = "StartOfLine";
|
|
LineState[LineState["MiddleOfLine"] = 2] = "MiddleOfLine";
|
|
})(LineState || (LineState = {}));
|
|
/**
|
|
* Renders a DocNode tree as a code comment.
|
|
*/
|
|
var TSDocEmitter = /** @class */ (function () {
|
|
function TSDocEmitter() {
|
|
this.eol = '\n';
|
|
// Whether to emit the /** */ framing
|
|
this._emitCommentFraming = true;
|
|
// This state machine is used by the writer functions to generate the /** */ framing around the emitted lines
|
|
this._lineState = LineState.Closed;
|
|
// State for _ensureLineSkipped()
|
|
this._previousLineHadContent = false;
|
|
// Normally a paragraph is precede by a blank line (unless it's the first thing written).
|
|
// But sometimes we want the paragraph to be attached to the previous element, e.g. when it's part of
|
|
// an "@param" block. Setting _hangingParagraph=true accomplishes that.
|
|
this._hangingParagraph = false;
|
|
}
|
|
TSDocEmitter.prototype.renderComment = function (output, docComment) {
|
|
this._emitCommentFraming = true;
|
|
this._renderCompleteObject(output, docComment);
|
|
};
|
|
TSDocEmitter.prototype.renderHtmlTag = function (output, htmlTag) {
|
|
this._emitCommentFraming = false;
|
|
this._renderCompleteObject(output, htmlTag);
|
|
};
|
|
TSDocEmitter.prototype.renderDeclarationReference = function (output, declarationReference) {
|
|
this._emitCommentFraming = false;
|
|
this._renderCompleteObject(output, declarationReference);
|
|
};
|
|
TSDocEmitter.prototype._renderCompleteObject = function (output, docNode) {
|
|
this._output = output;
|
|
this._lineState = LineState.Closed;
|
|
this._previousLineHadContent = false;
|
|
this._hangingParagraph = false;
|
|
this._renderNode(docNode);
|
|
this._writeEnd();
|
|
};
|
|
TSDocEmitter.prototype._renderNode = function (docNode) {
|
|
var _this = this;
|
|
if (docNode === undefined) {
|
|
return;
|
|
}
|
|
switch (docNode.kind) {
|
|
case DocNode_1.DocNodeKind.Block:
|
|
var docBlock = docNode;
|
|
this._ensureLineSkipped();
|
|
this._renderNode(docBlock.blockTag);
|
|
if (docBlock.blockTag.tagNameWithUpperCase === StandardTags_1.StandardTags.returns.tagNameWithUpperCase) {
|
|
this._writeContent(' ');
|
|
this._hangingParagraph = true;
|
|
}
|
|
this._renderNode(docBlock.content);
|
|
break;
|
|
case DocNode_1.DocNodeKind.BlockTag:
|
|
var docBlockTag = docNode;
|
|
if (this._lineState === LineState.MiddleOfLine) {
|
|
this._writeContent(' ');
|
|
}
|
|
this._writeContent(docBlockTag.tagName);
|
|
break;
|
|
case DocNode_1.DocNodeKind.CodeSpan:
|
|
var docCodeSpan = docNode;
|
|
this._writeContent('`');
|
|
this._writeContent(docCodeSpan.code);
|
|
this._writeContent('`');
|
|
break;
|
|
case DocNode_1.DocNodeKind.Comment:
|
|
var docComment = docNode;
|
|
this._renderNodes(__spreadArrays([
|
|
docComment.summarySection,
|
|
docComment.remarksBlock,
|
|
docComment.privateRemarks,
|
|
docComment.deprecatedBlock,
|
|
docComment.params,
|
|
docComment.typeParams,
|
|
docComment.returnsBlock
|
|
], docComment.customBlocks, docComment.seeBlocks, [
|
|
docComment.inheritDocTag
|
|
]));
|
|
if (docComment.modifierTagSet.nodes.length > 0) {
|
|
this._ensureLineSkipped();
|
|
this._renderNodes(docComment.modifierTagSet.nodes);
|
|
}
|
|
break;
|
|
case DocNode_1.DocNodeKind.DeclarationReference:
|
|
var docDeclarationReference = docNode;
|
|
this._writeContent(docDeclarationReference.packageName);
|
|
this._writeContent(docDeclarationReference.importPath);
|
|
if (docDeclarationReference.packageName !== undefined ||
|
|
docDeclarationReference.importPath !== undefined) {
|
|
this._writeContent('#');
|
|
}
|
|
this._renderNodes(docDeclarationReference.memberReferences);
|
|
break;
|
|
case DocNode_1.DocNodeKind.ErrorText:
|
|
var docErrorText = docNode;
|
|
this._writeContent(docErrorText.text);
|
|
break;
|
|
case DocNode_1.DocNodeKind.EscapedText:
|
|
var docEscapedText = docNode;
|
|
this._writeContent(docEscapedText.encodedText);
|
|
break;
|
|
case DocNode_1.DocNodeKind.FencedCode:
|
|
var docFencedCode = docNode;
|
|
this._ensureAtStartOfLine();
|
|
this._writeContent('```');
|
|
this._writeContent(docFencedCode.language);
|
|
this._writeNewline();
|
|
this._writeContent(docFencedCode.code);
|
|
this._writeContent('```');
|
|
this._writeNewline();
|
|
this._writeNewline();
|
|
break;
|
|
case DocNode_1.DocNodeKind.HtmlAttribute:
|
|
var docHtmlAttribute = docNode;
|
|
this._writeContent(docHtmlAttribute.name);
|
|
this._writeContent(docHtmlAttribute.spacingAfterName);
|
|
this._writeContent('=');
|
|
this._writeContent(docHtmlAttribute.spacingAfterEquals);
|
|
this._writeContent(docHtmlAttribute.value);
|
|
this._writeContent(docHtmlAttribute.spacingAfterValue);
|
|
break;
|
|
case DocNode_1.DocNodeKind.HtmlEndTag:
|
|
var docHtmlEndTag = docNode;
|
|
this._writeContent('</');
|
|
this._writeContent(docHtmlEndTag.name);
|
|
this._writeContent('>');
|
|
break;
|
|
case DocNode_1.DocNodeKind.HtmlStartTag:
|
|
var docHtmlStartTag = docNode;
|
|
this._writeContent('<');
|
|
this._writeContent(docHtmlStartTag.name);
|
|
this._writeContent(docHtmlStartTag.spacingAfterName);
|
|
var needsSpace = docHtmlStartTag.spacingAfterName === undefined || docHtmlStartTag.spacingAfterName.length === 0;
|
|
for (var _i = 0, _a = docHtmlStartTag.htmlAttributes; _i < _a.length; _i++) {
|
|
var attribute = _a[_i];
|
|
if (needsSpace) {
|
|
this._writeContent(' ');
|
|
}
|
|
this._renderNode(attribute);
|
|
needsSpace = attribute.spacingAfterValue === undefined || attribute.spacingAfterValue.length === 0;
|
|
}
|
|
this._writeContent(docHtmlStartTag.selfClosingTag ? '/>' : '>');
|
|
break;
|
|
case DocNode_1.DocNodeKind.InheritDocTag:
|
|
var docInheritDocTag_1 = docNode;
|
|
this._renderInlineTag(docInheritDocTag_1, function () {
|
|
if (docInheritDocTag_1.declarationReference) {
|
|
_this._writeContent(' ');
|
|
_this._renderNode(docInheritDocTag_1.declarationReference);
|
|
}
|
|
});
|
|
break;
|
|
case DocNode_1.DocNodeKind.InlineTag:
|
|
var docInlineTag_1 = docNode;
|
|
this._renderInlineTag(docInlineTag_1, function () {
|
|
if (docInlineTag_1.tagContent.length > 0) {
|
|
_this._writeContent(' ');
|
|
_this._writeContent(docInlineTag_1.tagContent);
|
|
}
|
|
});
|
|
break;
|
|
case DocNode_1.DocNodeKind.LinkTag:
|
|
var docLinkTag_1 = docNode;
|
|
this._renderInlineTag(docLinkTag_1, function () {
|
|
if (docLinkTag_1.urlDestination !== undefined || docLinkTag_1.codeDestination !== undefined) {
|
|
if (docLinkTag_1.urlDestination !== undefined) {
|
|
_this._writeContent(' ');
|
|
_this._writeContent(docLinkTag_1.urlDestination);
|
|
}
|
|
else if (docLinkTag_1.codeDestination !== undefined) {
|
|
_this._writeContent(' ');
|
|
_this._renderNode(docLinkTag_1.codeDestination);
|
|
}
|
|
}
|
|
if (docLinkTag_1.linkText !== undefined) {
|
|
_this._writeContent(' ');
|
|
_this._writeContent('|');
|
|
_this._writeContent(' ');
|
|
_this._writeContent(docLinkTag_1.linkText);
|
|
}
|
|
});
|
|
break;
|
|
case DocNode_1.DocNodeKind.MemberIdentifier:
|
|
var docMemberIdentifier = docNode;
|
|
if (docMemberIdentifier.hasQuotes) {
|
|
this._writeContent('"');
|
|
this._writeContent(docMemberIdentifier.identifier); // todo: encoding
|
|
this._writeContent('"');
|
|
}
|
|
else {
|
|
this._writeContent(docMemberIdentifier.identifier);
|
|
}
|
|
break;
|
|
case DocNode_1.DocNodeKind.MemberReference:
|
|
var docMemberReference = docNode;
|
|
if (docMemberReference.hasDot) {
|
|
this._writeContent('.');
|
|
}
|
|
if (docMemberReference.selector) {
|
|
this._writeContent('(');
|
|
}
|
|
if (docMemberReference.memberSymbol) {
|
|
this._renderNode(docMemberReference.memberSymbol);
|
|
}
|
|
else {
|
|
this._renderNode(docMemberReference.memberIdentifier);
|
|
}
|
|
if (docMemberReference.selector) {
|
|
this._writeContent(':');
|
|
this._renderNode(docMemberReference.selector);
|
|
this._writeContent(')');
|
|
}
|
|
break;
|
|
case DocNode_1.DocNodeKind.MemberSelector:
|
|
var docMemberSelector = docNode;
|
|
this._writeContent(docMemberSelector.selector);
|
|
break;
|
|
case DocNode_1.DocNodeKind.MemberSymbol:
|
|
var docMemberSymbol = docNode;
|
|
this._writeContent('[');
|
|
this._renderNode(docMemberSymbol.symbolReference);
|
|
this._writeContent(']');
|
|
break;
|
|
case DocNode_1.DocNodeKind.Section:
|
|
var docSection = docNode;
|
|
this._renderNodes(docSection.nodes);
|
|
break;
|
|
case DocNode_1.DocNodeKind.Paragraph:
|
|
var trimmedParagraph = DocNodeTransforms_1.DocNodeTransforms.trimSpacesInParagraph(docNode);
|
|
if (trimmedParagraph.nodes.length > 0) {
|
|
if (this._hangingParagraph) {
|
|
// If it's a hanging paragraph, then don't skip a line
|
|
this._hangingParagraph = false;
|
|
}
|
|
else {
|
|
this._ensureLineSkipped();
|
|
}
|
|
this._renderNodes(trimmedParagraph.nodes);
|
|
this._writeNewline();
|
|
}
|
|
break;
|
|
case DocNode_1.DocNodeKind.ParamBlock:
|
|
var docParamBlock = docNode;
|
|
this._ensureLineSkipped();
|
|
this._renderNode(docParamBlock.blockTag);
|
|
this._writeContent(' ');
|
|
this._writeContent(docParamBlock.parameterName);
|
|
this._writeContent(' - ');
|
|
this._hangingParagraph = true;
|
|
this._renderNode(docParamBlock.content);
|
|
this._hangingParagraph = false;
|
|
break;
|
|
case DocNode_1.DocNodeKind.ParamCollection:
|
|
var docParamCollection = docNode;
|
|
this._renderNodes(docParamCollection.blocks);
|
|
break;
|
|
case DocNode_1.DocNodeKind.PlainText:
|
|
var docPlainText = docNode;
|
|
this._writeContent(docPlainText.text);
|
|
break;
|
|
}
|
|
};
|
|
TSDocEmitter.prototype._renderInlineTag = function (docInlineTagBase, writeInlineTagContent) {
|
|
this._writeContent('{');
|
|
this._writeContent(docInlineTagBase.tagName);
|
|
writeInlineTagContent();
|
|
this._writeContent('}');
|
|
};
|
|
TSDocEmitter.prototype._renderNodes = function (docNodes) {
|
|
for (var _i = 0, docNodes_1 = docNodes; _i < docNodes_1.length; _i++) {
|
|
var docNode = docNodes_1[_i];
|
|
this._renderNode(docNode);
|
|
}
|
|
};
|
|
// Calls _writeNewline() only if we're not already at the start of a new line
|
|
TSDocEmitter.prototype._ensureAtStartOfLine = function () {
|
|
if (this._lineState === LineState.MiddleOfLine) {
|
|
this._writeNewline();
|
|
}
|
|
};
|
|
// Calls _writeNewline() if needed to ensure that we have skipped at least one line
|
|
TSDocEmitter.prototype._ensureLineSkipped = function () {
|
|
this._ensureAtStartOfLine();
|
|
if (this._previousLineHadContent) {
|
|
this._writeNewline();
|
|
}
|
|
};
|
|
// Writes literal text content. If it contains newlines, they will automatically be converted to
|
|
// _writeNewline() calls, to ensure that "*" is written at the start of each line.
|
|
TSDocEmitter.prototype._writeContent = function (content) {
|
|
if (content === undefined || content.length === 0) {
|
|
return;
|
|
}
|
|
var splitLines = content.split(/\r?\n/g);
|
|
if (splitLines.length > 1) {
|
|
var firstLine = true;
|
|
for (var _i = 0, splitLines_1 = splitLines; _i < splitLines_1.length; _i++) {
|
|
var line = splitLines_1[_i];
|
|
if (firstLine) {
|
|
firstLine = false;
|
|
}
|
|
else {
|
|
this._writeNewline();
|
|
}
|
|
this._writeContent(line);
|
|
}
|
|
return;
|
|
}
|
|
if (this._lineState === LineState.Closed) {
|
|
if (this._emitCommentFraming) {
|
|
this._output.append('/**' + this.eol + ' *');
|
|
}
|
|
this._lineState = LineState.StartOfLine;
|
|
}
|
|
if (this._lineState === LineState.StartOfLine) {
|
|
if (this._emitCommentFraming) {
|
|
this._output.append(' ');
|
|
}
|
|
}
|
|
this._output.append(content);
|
|
this._lineState = LineState.MiddleOfLine;
|
|
this._previousLineHadContent = true;
|
|
};
|
|
// Starts a new line, and inserts "/**" or "*" as appropriate.
|
|
TSDocEmitter.prototype._writeNewline = function () {
|
|
if (this._lineState === LineState.Closed) {
|
|
if (this._emitCommentFraming) {
|
|
this._output.append('/**' + this.eol + ' *');
|
|
}
|
|
this._lineState = LineState.StartOfLine;
|
|
}
|
|
this._previousLineHadContent = this._lineState === LineState.MiddleOfLine;
|
|
if (this._emitCommentFraming) {
|
|
this._output.append(this.eol + ' *');
|
|
}
|
|
else {
|
|
this._output.append(this.eol);
|
|
}
|
|
this._lineState = LineState.StartOfLine;
|
|
this._hangingParagraph = false;
|
|
};
|
|
// Closes the comment, adding the final "*/" delimiter
|
|
TSDocEmitter.prototype._writeEnd = function () {
|
|
if (this._lineState === LineState.MiddleOfLine) {
|
|
if (this._emitCommentFraming) {
|
|
this._writeNewline();
|
|
}
|
|
}
|
|
if (this._lineState !== LineState.Closed) {
|
|
if (this._emitCommentFraming) {
|
|
this._output.append('/' + this.eol);
|
|
}
|
|
this._lineState = LineState.Closed;
|
|
}
|
|
};
|
|
return TSDocEmitter;
|
|
}());
|
|
exports.TSDocEmitter = TSDocEmitter;
|
|
//# sourceMappingURL=TSDocEmitter.js.map
|