or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-nodes.mdconfiguration.mdemitters.mdindex.mdparser.mdstandard-tags.mdtransforms.md

emitters.mddocs/

0

# Content Emitters

1

2

Utilities for rendering DocNode trees back to TSDoc markup or extracting plain text content from parsed comments.

3

4

## Capabilities

5

6

### TSDocEmitter

7

8

Renders a DocNode tree back to TSDoc markup, preserving the original comment structure and formatting.

9

10

```typescript { .api }

11

/**

12

* Renders a DocNode tree back to TSDoc markup

13

*/

14

class TSDocEmitter {

15

constructor();

16

17

/** Render any DocNode back to TSDoc format */

18

renderDocNode(docNode: DocNode): string;

19

20

/** Render a complete DocComment back to TSDoc format */

21

renderDocComment(docComment: DocComment): string;

22

}

23

```

24

25

**Usage Examples:**

26

27

```typescript

28

import { TSDocParser, TSDocEmitter } from "@microsoft/tsdoc";

29

30

const parser = new TSDocParser();

31

const emitter = new TSDocEmitter();

32

33

// Parse a comment

34

const context = parser.parseString(`

35

/**

36

* Calculates the area.

37

* @param width - The width value

38

* @param height - The height value

39

* @returns The calculated area

40

* @beta

41

* @example

42

* \`\`\`typescript

43

* const area = calculateArea(10, 20);

44

* console.log(area); // 200

45

* \`\`\`

46

*/

47

`);

48

49

// Render back to TSDoc

50

const renderedComment = emitter.renderDocComment(context.docComment);

51

console.log(renderedComment);

52

53

// Render individual sections

54

const remarksSection = context.docComment.remarksBlock;

55

if (remarksSection) {

56

const renderedRemarks = emitter.renderDocNode(remarksSection);

57

console.log("Remarks:", renderedRemarks);

58

}

59

60

// Render parameter blocks

61

context.docComment.parameterBlocks.forEach(paramBlock => {

62

const renderedParam = emitter.renderDocNode(paramBlock);

63

console.log("Parameter:", renderedParam);

64

});

65

```

66

67

### PlainTextEmitter

68

69

Extracts plain text from a DocNode tree, removing all TSDoc markup and formatting.

70

71

```typescript { .api }

72

/**

73

* Extracts plain text from a DocNode tree, removing markup

74

*/

75

class PlainTextEmitter {

76

constructor();

77

78

/** Extract plain text from any DocNode */

79

renderDocNode(docNode: DocNode): string;

80

81

/** Extract plain text from a complete DocComment */

82

renderDocComment(docComment: DocComment): string;

83

}

84

```

85

86

**Usage Examples:**

87

88

```typescript

89

import { TSDocParser, PlainTextEmitter } from "@microsoft/tsdoc";

90

91

const parser = new TSDocParser();

92

const plainTextEmitter = new PlainTextEmitter();

93

94

// Parse a complex comment with markup

95

const context = parser.parseString(`

96

/**

97

* This method {@link MyClass.helper | helps} with calculations.

98

*

99

* It supports **bold** and \`inline code\` formatting.

100

*

101

* @param value - The input {@link InputType | value}

102

* @returns Processed result

103

*

104

* @example

105

* Here's how to use it:

106

* \`\`\`typescript

107

* const result = process(42);

108

* \`\`\`

109

*/

110

`);

111

112

// Extract plain text (removes all markup)

113

const plainText = plainTextEmitter.renderDocComment(context.docComment);

114

console.log("Plain text:", plainText);

115

// Output: "This method helps with calculations. It supports bold and inline code formatting."

116

117

// Extract plain text from specific sections

118

const summaryText = plainTextEmitter.renderDocNode(context.docComment.summarySection);

119

console.log("Summary:", summaryText);

120

121

// Extract parameter descriptions

122

context.docComment.parameterBlocks.forEach(paramBlock => {

123

const paramText = plainTextEmitter.renderDocNode(paramBlock.content);

124

console.log(`${paramBlock.parameterName}: ${paramText}`);

125

});

126

```

127

128

### StringBuilder

129

130

Utility class for efficiently building strings with append operations. Used internally by emitters but also available for custom rendering logic.

131

132

```typescript { .api }

133

/**

134

* Utility for efficiently building strings

135

*/

136

class StringBuilder implements IStringBuilder {

137

constructor();

138

139

/** Append text to the string being built */

140

append(text: string): void;

141

142

/** Get the final built string */

143

toString(): string;

144

}

145

146

/**

147

* Interface for string building operations

148

*/

149

interface IStringBuilder {

150

/** Append text to the string being built */

151

append(text: string): void;

152

153

/** Get the final built string */

154

toString(): string;

155

}

156

```

157

158

**Usage Examples:**

159

160

```typescript

161

import { StringBuilder } from "@microsoft/tsdoc";

162

163

// Basic string building

164

const builder = new StringBuilder();

165

builder.append("Hello");

166

builder.append(" ");

167

builder.append("world");

168

console.log(builder.toString()); // "Hello world"

169

170

// Building formatted output

171

function formatParameterList(paramBlocks: ReadonlyArray<DocParamBlock>): string {

172

const builder = new StringBuilder();

173

174

builder.append("Parameters:\n");

175

paramBlocks.forEach((param, index) => {

176

builder.append(` ${index + 1}. ${param.parameterName}\n`);

177

});

178

179

return builder.toString();

180

}

181

182

// Custom rendering with StringBuilder

183

function renderCustomSummary(docComment: DocComment): string {

184

const builder = new StringBuilder();

185

const plainEmitter = new PlainTextEmitter();

186

187

// Extract summary text

188

const summaryText = plainEmitter.renderDocNode(docComment.summarySection);

189

builder.append("Summary: ");

190

builder.append(summaryText);

191

192

// Add parameter count

193

if (docComment.parameterBlocks.length > 0) {

194

builder.append(`\nParameters: ${docComment.parameterBlocks.length}`);

195

}

196

197

// Add modifiers

198

const modifiers = docComment.modifierTagSet;

199

if (modifiers.isBeta) {

200

builder.append("\n[BETA API]");

201

}

202

if (modifiers.isDeprecated) {

203

builder.append("\n[DEPRECATED]");

204

}

205

206

return builder.toString();

207

}

208

```

209

210

## Advanced Emitter Usage

211

212

### Custom Rendering Logic

213

214

Create custom rendering by combining emitters with AST traversal:

215

216

```typescript

217

import {

218

TSDocParser,

219

TSDocEmitter,

220

PlainTextEmitter,

221

DocNode,

222

DocCodeSpan,

223

DocFencedCode,

224

DocLinkTag

225

} from "@microsoft/tsdoc";

226

227

class CustomMarkdownEmitter {

228

private tsdocEmitter = new TSDocEmitter();

229

private plainEmitter = new PlainTextEmitter();

230

231

renderAsMarkdown(docComment: DocComment): string {

232

const builder = new StringBuilder();

233

234

// Render summary as markdown

235

const summaryText = this.plainEmitter.renderDocNode(docComment.summarySection);

236

builder.append(`## Summary\n\n${summaryText}\n\n`);

237

238

// Render parameters

239

if (docComment.parameterBlocks.length > 0) {

240

builder.append("## Parameters\n\n");

241

docComment.parameterBlocks.forEach(param => {

242

const description = this.plainEmitter.renderDocNode(param.content);

243

builder.append(`- **${param.parameterName}**: ${description}\n`);

244

});

245

builder.append("\n");

246

}

247

248

// Render examples

249

if (docComment.exampleBlocks.length > 0) {

250

builder.append("## Examples\n\n");

251

docComment.exampleBlocks.forEach((example, index) => {

252

const exampleText = this.extractCodeBlocks(example.content);

253

builder.append(`### Example ${index + 1}\n\n${exampleText}\n\n`);

254

});

255

}

256

257

return builder.toString();

258

}

259

260

private extractCodeBlocks(section: DocSection): string {

261

// Custom logic to find and format code blocks

262

const builder = new StringBuilder();

263

264

const findCodeNodes = (node: DocNode): void => {

265

if (node instanceof DocFencedCode) {

266

builder.append(`\`\`\`${node.language}\n${node.code}\n\`\`\`\n`);

267

} else if (node instanceof DocCodeSpan) {

268

builder.append(`\`${node.code}\`\n`);

269

}

270

271

for (const child of node.getChildNodes()) {

272

if (child) {

273

findCodeNodes(child);

274

}

275

}

276

};

277

278

findCodeNodes(section);

279

return builder.toString();

280

}

281

}

282

283

// Usage

284

const parser = new TSDocParser();

285

const customEmitter = new CustomMarkdownEmitter();

286

287

const context = parser.parseString("/** ... */");

288

const markdown = customEmitter.renderAsMarkdown(context.docComment);

289

```

290

291

### Selective Content Extraction

292

293

Extract specific types of content from comments:

294

295

```typescript

296

class ContentExtractor {

297

private plainEmitter = new PlainTextEmitter();

298

299

/** Extract all code examples from a comment */

300

extractCodeExamples(docComment: DocComment): string[] {

301

const examples: string[] = [];

302

303

const extractFromNode = (node: DocNode): void => {

304

if (node instanceof DocFencedCode) {

305

examples.push(node.code);

306

}

307

308

for (const child of node.getChildNodes()) {

309

if (child) {

310

extractFromNode(child);

311

}

312

}

313

};

314

315

// Extract from example blocks

316

docComment.exampleBlocks.forEach(block => {

317

extractFromNode(block.content);

318

});

319

320

return examples;

321

}

322

323

/** Extract all @see references */

324

extractSeeReferences(docComment: DocComment): string[] {

325

return docComment.seeBlocks.map(block =>

326

this.plainEmitter.renderDocNode(block.content).trim()

327

);

328

}

329

330

/** Extract parameter information */

331

extractParameterInfo(docComment: DocComment): Array<{name: string, description: string}> {

332

return docComment.parameterBlocks.map(param => ({

333

name: param.parameterName,

334

description: this.plainEmitter.renderDocNode(param.content).trim()

335

}));

336

}

337

338

/** Get API stability information */

339

getStabilityInfo(docComment: DocComment): {

340

stability: 'stable' | 'beta' | 'alpha' | 'experimental' | 'deprecated';

341

isInternal: boolean;

342

} {

343

const modifiers = docComment.modifierTagSet;

344

345

let stability: 'stable' | 'beta' | 'alpha' | 'experimental' | 'deprecated' = 'stable';

346

347

if (modifiers.isAlpha) stability = 'alpha';

348

else if (modifiers.isBeta) stability = 'beta';

349

else if (modifiers.isExperimental) stability = 'experimental';

350

else if (docComment.deprecatedBlock) stability = 'deprecated';

351

352

return {

353

stability,

354

isInternal: modifiers.isInternal

355

};

356

}

357

}

358

```