CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-microsoft--tsdoc

A parser for the TypeScript doc comment syntax

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

emitters.mddocs/

Content Emitters

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

Capabilities

TSDocEmitter

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

/**
 * Renders a DocNode tree back to TSDoc markup
 */
class TSDocEmitter {
  constructor();
  
  /** Render any DocNode back to TSDoc format */
  renderDocNode(docNode: DocNode): string;
  
  /** Render a complete DocComment back to TSDoc format */
  renderDocComment(docComment: DocComment): string;
}

Usage Examples:

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

const parser = new TSDocParser();
const emitter = new TSDocEmitter();

// Parse a comment
const context = parser.parseString(`
  /**
   * Calculates the area.
   * @param width - The width value
   * @param height - The height value
   * @returns The calculated area
   * @beta
   * @example
   * \`\`\`typescript
   * const area = calculateArea(10, 20);
   * console.log(area); // 200
   * \`\`\`
   */
`);

// Render back to TSDoc
const renderedComment = emitter.renderDocComment(context.docComment);
console.log(renderedComment);

// Render individual sections
const remarksSection = context.docComment.remarksBlock;
if (remarksSection) {
  const renderedRemarks = emitter.renderDocNode(remarksSection);
  console.log("Remarks:", renderedRemarks);
}

// Render parameter blocks
context.docComment.parameterBlocks.forEach(paramBlock => {
  const renderedParam = emitter.renderDocNode(paramBlock);
  console.log("Parameter:", renderedParam);
});

PlainTextEmitter

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

/**
 * Extracts plain text from a DocNode tree, removing markup
 */
class PlainTextEmitter {
  constructor();
  
  /** Extract plain text from any DocNode */
  renderDocNode(docNode: DocNode): string;
  
  /** Extract plain text from a complete DocComment */
  renderDocComment(docComment: DocComment): string;
}

Usage Examples:

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

const parser = new TSDocParser();
const plainTextEmitter = new PlainTextEmitter();

// Parse a complex comment with markup
const context = parser.parseString(`
  /**
   * This method {@link MyClass.helper | helps} with calculations.
   * 
   * It supports **bold** and \`inline code\` formatting.
   * 
   * @param value - The input {@link InputType | value}
   * @returns Processed result
   * 
   * @example
   * Here's how to use it:
   * \`\`\`typescript
   * const result = process(42);
   * \`\`\`
   */
`);

// Extract plain text (removes all markup)
const plainText = plainTextEmitter.renderDocComment(context.docComment);
console.log("Plain text:", plainText);
// Output: "This method helps with calculations. It supports bold and inline code formatting."

// Extract plain text from specific sections
const summaryText = plainTextEmitter.renderDocNode(context.docComment.summarySection);
console.log("Summary:", summaryText);

// Extract parameter descriptions
context.docComment.parameterBlocks.forEach(paramBlock => {
  const paramText = plainTextEmitter.renderDocNode(paramBlock.content);
  console.log(`${paramBlock.parameterName}: ${paramText}`);
});

StringBuilder

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

/**
 * Utility for efficiently building strings
 */
class StringBuilder implements IStringBuilder {
  constructor();
  
  /** Append text to the string being built */
  append(text: string): void;
  
  /** Get the final built string */
  toString(): string;
}

/**
 * Interface for string building operations
 */
interface IStringBuilder {
  /** Append text to the string being built */
  append(text: string): void;
  
  /** Get the final built string */
  toString(): string;
}

Usage Examples:

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

// Basic string building
const builder = new StringBuilder();
builder.append("Hello");
builder.append(" ");
builder.append("world");
console.log(builder.toString()); // "Hello world"

// Building formatted output
function formatParameterList(paramBlocks: ReadonlyArray<DocParamBlock>): string {
  const builder = new StringBuilder();
  
  builder.append("Parameters:\n");
  paramBlocks.forEach((param, index) => {
    builder.append(`  ${index + 1}. ${param.parameterName}\n`);
  });
  
  return builder.toString();
}

// Custom rendering with StringBuilder
function renderCustomSummary(docComment: DocComment): string {
  const builder = new StringBuilder();
  const plainEmitter = new PlainTextEmitter();
  
  // Extract summary text
  const summaryText = plainEmitter.renderDocNode(docComment.summarySection);
  builder.append("Summary: ");
  builder.append(summaryText);
  
  // Add parameter count
  if (docComment.parameterBlocks.length > 0) {
    builder.append(`\nParameters: ${docComment.parameterBlocks.length}`);
  }
  
  // Add modifiers
  const modifiers = docComment.modifierTagSet;
  if (modifiers.isBeta) {
    builder.append("\n[BETA API]");
  }
  if (modifiers.isDeprecated) {
    builder.append("\n[DEPRECATED]");
  }
  
  return builder.toString();
}

Advanced Emitter Usage

Custom Rendering Logic

Create custom rendering by combining emitters with AST traversal:

import { 
  TSDocParser, 
  TSDocEmitter, 
  PlainTextEmitter,
  DocNode,
  DocCodeSpan,
  DocFencedCode,
  DocLinkTag
} from "@microsoft/tsdoc";

class CustomMarkdownEmitter {
  private tsdocEmitter = new TSDocEmitter();
  private plainEmitter = new PlainTextEmitter();
  
  renderAsMarkdown(docComment: DocComment): string {
    const builder = new StringBuilder();
    
    // Render summary as markdown
    const summaryText = this.plainEmitter.renderDocNode(docComment.summarySection);
    builder.append(`## Summary\n\n${summaryText}\n\n`);
    
    // Render parameters
    if (docComment.parameterBlocks.length > 0) {
      builder.append("## Parameters\n\n");
      docComment.parameterBlocks.forEach(param => {
        const description = this.plainEmitter.renderDocNode(param.content);
        builder.append(`- **${param.parameterName}**: ${description}\n`);
      });
      builder.append("\n");
    }
    
    // Render examples
    if (docComment.exampleBlocks.length > 0) {
      builder.append("## Examples\n\n");
      docComment.exampleBlocks.forEach((example, index) => {
        const exampleText = this.extractCodeBlocks(example.content);
        builder.append(`### Example ${index + 1}\n\n${exampleText}\n\n`);
      });
    }
    
    return builder.toString();
  }
  
  private extractCodeBlocks(section: DocSection): string {
    // Custom logic to find and format code blocks
    const builder = new StringBuilder();
    
    const findCodeNodes = (node: DocNode): void => {
      if (node instanceof DocFencedCode) {
        builder.append(`\`\`\`${node.language}\n${node.code}\n\`\`\`\n`);
      } else if (node instanceof DocCodeSpan) {
        builder.append(`\`${node.code}\`\n`);
      }
      
      for (const child of node.getChildNodes()) {
        if (child) {
          findCodeNodes(child);
        }
      }
    };
    
    findCodeNodes(section);
    return builder.toString();
  }
}

// Usage
const parser = new TSDocParser();
const customEmitter = new CustomMarkdownEmitter();

const context = parser.parseString("/** ... */");
const markdown = customEmitter.renderAsMarkdown(context.docComment);

Selective Content Extraction

Extract specific types of content from comments:

class ContentExtractor {
  private plainEmitter = new PlainTextEmitter();
  
  /** Extract all code examples from a comment */
  extractCodeExamples(docComment: DocComment): string[] {
    const examples: string[] = [];
    
    const extractFromNode = (node: DocNode): void => {
      if (node instanceof DocFencedCode) {
        examples.push(node.code);
      }
      
      for (const child of node.getChildNodes()) {
        if (child) {
          extractFromNode(child);
        }
      }
    };
    
    // Extract from example blocks
    docComment.exampleBlocks.forEach(block => {
      extractFromNode(block.content);
    });
    
    return examples;
  }
  
  /** Extract all @see references */
  extractSeeReferences(docComment: DocComment): string[] {
    return docComment.seeBlocks.map(block => 
      this.plainEmitter.renderDocNode(block.content).trim()
    );
  }
  
  /** Extract parameter information */
  extractParameterInfo(docComment: DocComment): Array<{name: string, description: string}> {
    return docComment.parameterBlocks.map(param => ({
      name: param.parameterName,
      description: this.plainEmitter.renderDocNode(param.content).trim()
    }));
  }
  
  /** Get API stability information */
  getStabilityInfo(docComment: DocComment): {
    stability: 'stable' | 'beta' | 'alpha' | 'experimental' | 'deprecated';
    isInternal: boolean;
  } {
    const modifiers = docComment.modifierTagSet;
    
    let stability: 'stable' | 'beta' | 'alpha' | 'experimental' | 'deprecated' = 'stable';
    
    if (modifiers.isAlpha) stability = 'alpha';
    else if (modifiers.isBeta) stability = 'beta';
    else if (modifiers.isExperimental) stability = 'experimental';
    else if (docComment.deprecatedBlock) stability = 'deprecated';
    
    return {
      stability,
      isInternal: modifiers.isInternal
    };
  }
}

docs

ast-nodes.md

configuration.md

emitters.md

index.md

parser.md

standard-tags.md

transforms.md

tile.json