1 | "use strict";
|
2 |
|
3 |
|
4 | Object.defineProperty(exports, "__esModule", { value: true });
|
5 | exports.MarkdownEmitter = void 0;
|
6 | const tsdoc_1 = require("@microsoft/tsdoc");
|
7 | const node_core_library_1 = require("@rushstack/node-core-library");
|
8 | const IndentedWriter_1 = require("../utils/IndentedWriter");
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | class MarkdownEmitter {
|
14 | emit(stringBuilder, docNode, options) {
|
15 | const writer = new IndentedWriter_1.IndentedWriter(stringBuilder);
|
16 | const context = {
|
17 | writer,
|
18 | insideTable: false,
|
19 | boldRequested: false,
|
20 | italicRequested: false,
|
21 | writingBold: false,
|
22 | writingItalic: false,
|
23 | options
|
24 | };
|
25 | this.writeNode(docNode, context, false);
|
26 | writer.ensureNewLine();
|
27 | return writer.toString();
|
28 | }
|
29 | getEscapedText(text) {
|
30 | const textWithBackslashes = text
|
31 | .replace(/\\/g, '\\\\')
|
32 | .replace(/[*#[\]_|`~]/g, (x) => '\\' + x)
|
33 | .replace(/---/g, '\\-\\-\\-')
|
34 | .replace(/&/g, '&')
|
35 | .replace(/</g, '<')
|
36 | .replace(/>/g, '>');
|
37 | return textWithBackslashes;
|
38 | }
|
39 | getTableEscapedText(text) {
|
40 | return text
|
41 | .replace(/&/g, '&')
|
42 | .replace(/"/g, '"')
|
43 | .replace(/</g, '<')
|
44 | .replace(/>/g, '>')
|
45 | .replace(/\|/g, '|');
|
46 | }
|
47 | |
48 |
|
49 |
|
50 | writeNode(docNode, context, docNodeSiblings) {
|
51 | const writer = context.writer;
|
52 | switch (docNode.kind) {
|
53 | case tsdoc_1.DocNodeKind.PlainText: {
|
54 | const docPlainText = docNode;
|
55 | this.writePlainText(docPlainText.text, context);
|
56 | break;
|
57 | }
|
58 | case tsdoc_1.DocNodeKind.HtmlStartTag:
|
59 | case tsdoc_1.DocNodeKind.HtmlEndTag: {
|
60 | const docHtmlTag = docNode;
|
61 |
|
62 | writer.write(docHtmlTag.emitAsHtml());
|
63 | break;
|
64 | }
|
65 | case tsdoc_1.DocNodeKind.CodeSpan: {
|
66 | const docCodeSpan = docNode;
|
67 | if (context.insideTable) {
|
68 | writer.write('<code>');
|
69 | }
|
70 | else {
|
71 | writer.write('`');
|
72 | }
|
73 | if (context.insideTable) {
|
74 | const code = this.getTableEscapedText(docCodeSpan.code);
|
75 | const parts = code.split(/\r?\n/g);
|
76 | writer.write(parts.join('</code><br/><code>'));
|
77 | }
|
78 | else {
|
79 | writer.write(docCodeSpan.code);
|
80 | }
|
81 | if (context.insideTable) {
|
82 | writer.write('</code>');
|
83 | }
|
84 | else {
|
85 | writer.write('`');
|
86 | }
|
87 | break;
|
88 | }
|
89 | case tsdoc_1.DocNodeKind.LinkTag: {
|
90 | const docLinkTag = docNode;
|
91 | if (docLinkTag.codeDestination) {
|
92 | this.writeLinkTagWithCodeDestination(docLinkTag, context);
|
93 | }
|
94 | else if (docLinkTag.urlDestination) {
|
95 | this.writeLinkTagWithUrlDestination(docLinkTag, context);
|
96 | }
|
97 | else if (docLinkTag.linkText) {
|
98 | this.writePlainText(docLinkTag.linkText, context);
|
99 | }
|
100 | break;
|
101 | }
|
102 | case tsdoc_1.DocNodeKind.Paragraph: {
|
103 | const docParagraph = docNode;
|
104 | const trimmedParagraph = tsdoc_1.DocNodeTransforms.trimSpacesInParagraph(docParagraph);
|
105 | if (context.insideTable) {
|
106 | if (docNodeSiblings) {
|
107 | writer.write('<p>');
|
108 | this.writeNodes(trimmedParagraph.nodes, context);
|
109 | writer.write('</p>');
|
110 | }
|
111 | else {
|
112 |
|
113 | this.writeNodes(trimmedParagraph.nodes, context);
|
114 | }
|
115 | }
|
116 | else {
|
117 | this.writeNodes(trimmedParagraph.nodes, context);
|
118 | writer.ensureNewLine();
|
119 | writer.writeLine();
|
120 | }
|
121 | break;
|
122 | }
|
123 | case tsdoc_1.DocNodeKind.FencedCode: {
|
124 | const docFencedCode = docNode;
|
125 | writer.ensureNewLine();
|
126 | writer.write('```');
|
127 | writer.write(docFencedCode.language);
|
128 | writer.writeLine();
|
129 | writer.write(docFencedCode.code);
|
130 | writer.ensureNewLine();
|
131 | writer.writeLine('```');
|
132 | break;
|
133 | }
|
134 | case tsdoc_1.DocNodeKind.Section: {
|
135 | const docSection = docNode;
|
136 | this.writeNodes(docSection.nodes, context);
|
137 | break;
|
138 | }
|
139 | case tsdoc_1.DocNodeKind.SoftBreak: {
|
140 | if (!/^\s?$/.test(writer.peekLastCharacter())) {
|
141 | writer.write(' ');
|
142 | }
|
143 | break;
|
144 | }
|
145 | case tsdoc_1.DocNodeKind.EscapedText: {
|
146 | const docEscapedText = docNode;
|
147 | this.writePlainText(docEscapedText.decodedText, context);
|
148 | break;
|
149 | }
|
150 | case tsdoc_1.DocNodeKind.ErrorText: {
|
151 | const docErrorText = docNode;
|
152 | this.writePlainText(docErrorText.text, context);
|
153 | break;
|
154 | }
|
155 | case tsdoc_1.DocNodeKind.InlineTag: {
|
156 | break;
|
157 | }
|
158 | case tsdoc_1.DocNodeKind.BlockTag: {
|
159 | const tagNode = docNode;
|
160 | console.warn('Unsupported block tag: ' + tagNode.tagName);
|
161 | break;
|
162 | }
|
163 | default:
|
164 | throw new node_core_library_1.InternalError('Unsupported DocNodeKind kind: ' + docNode.kind);
|
165 | }
|
166 | }
|
167 |
|
168 | writeLinkTagWithCodeDestination(docLinkTag, context) {
|
169 |
|
170 | throw new node_core_library_1.InternalError('writeLinkTagWithCodeDestination()');
|
171 | }
|
172 |
|
173 | writeLinkTagWithUrlDestination(docLinkTag, context) {
|
174 | const linkText = docLinkTag.linkText !== undefined ? docLinkTag.linkText : docLinkTag.urlDestination;
|
175 | const encodedLinkText = this.getEscapedText(linkText.replace(/\s+/g, ' '));
|
176 | context.writer.write('[');
|
177 | context.writer.write(encodedLinkText);
|
178 | context.writer.write(`](${docLinkTag.urlDestination})`);
|
179 | }
|
180 | writePlainText(text, context) {
|
181 | const writer = context.writer;
|
182 |
|
183 | const parts = text.match(/^(\s*)(.*?)(\s*)$/) || [];
|
184 | writer.write(parts[1]);
|
185 | const middle = parts[2];
|
186 | if (middle !== '') {
|
187 | switch (writer.peekLastCharacter()) {
|
188 | case '':
|
189 | case '\n':
|
190 | case ' ':
|
191 | case '[':
|
192 | case '>':
|
193 |
|
194 | break;
|
195 | default:
|
196 |
|
197 |
|
198 |
|
199 | writer.write('<!-- -->');
|
200 | break;
|
201 | }
|
202 | if (context.boldRequested) {
|
203 | writer.write('<b>');
|
204 | }
|
205 | if (context.italicRequested) {
|
206 | writer.write('<i>');
|
207 | }
|
208 | writer.write(this.getEscapedText(middle));
|
209 | if (context.italicRequested) {
|
210 | writer.write('</i>');
|
211 | }
|
212 | if (context.boldRequested) {
|
213 | writer.write('</b>');
|
214 | }
|
215 | }
|
216 | writer.write(parts[3]);
|
217 | }
|
218 | writeNodes(docNodes, context) {
|
219 | for (const docNode of docNodes) {
|
220 | this.writeNode(docNode, context, docNodes.length > 1);
|
221 | }
|
222 | }
|
223 | }
|
224 | exports.MarkdownEmitter = MarkdownEmitter;
|
225 |
|
\ | No newline at end of file |