@remotex-labs/xmap
Version:
A library with a sourcemap parser and TypeScript code formatter for the CLI
424 lines (423 loc) • 15.7 kB
TypeScript
import type * as ts from "typescript";
/**
* Defines the color scheme for syntax highlighting different code elements.
*
* @interface HighlightSchemeInterface
*
* @property enumColor - Color code for enum declarations and references
* @property typeColor - Color code for type annotations and primitive types
* @property classColor - Color code for class declarations and references
* @property stringColor - Color code for string literals and template strings
* @property keywordColor - Color code for language keywords
* @property commentColor - Color code for comments (single-line and multi-line)
* @property functionColor - Color code for function declarations and calls
* @property variableColor - Color code for variable declarations and references
* @property interfaceColor - Color code for interface declarations and references
* @property parameterColor - Color code for function and method parameters
* @property getAccessorColor - Color code for getter accessor methods
* @property numericLiteralColor - Color code for numeric literals
* @property methodSignatureColor - Color code for method signatures in interfaces
* @property regularExpressionColor - Color code for regular expression literals
* @property propertyAssignmentColor - Color code for property assignments in object literals
* @property propertyAccessExpressionColor - Color code for property access expressions
* @property expressionWithTypeArgumentsColor - Color code for type arguments in expressions
*
* @example
* ```ts
* const darkTheme: HighlightSchemeInterface = {
* enumColor: Colors.cyan,
* typeColor: Colors.blue,
* classColor: Colors.yellow,
* // ...other color definitions
* };
* ```
*
* @since 1.0.0
*/
export interface HighlightSchemeInterface {
enumColor: string;
typeColor: string;
classColor: string;
stringColor: string;
keywordColor: string;
commentColor: string;
functionColor: string;
variableColor: string;
interfaceColor: string;
parameterColor: string;
getAccessorColor: string;
numericLiteralColor: string;
methodSignatureColor: string;
regularExpressionColor: string;
propertyAssignmentColor: string;
propertyAccessExpressionColor: string;
expressionWithTypeArgumentsColor: string;
}
/**
* Represents a segment of source code to be highlighted with specific styling.
*
* @interface HighlightNodeSegmentInterface
*
* @property start - The starting character position of the segment in the source text
* @property end - The ending character position of the segment in the source text
* @property color - The color or style code to apply to this segment
* @property reset - The reset code that returns formatting to normal after this segment
*
* @remarks
* Segments are the fundamental units of the highlighting system.
* Each segment represents a portion of text that should receive specific styling.
* When the source code is processed for display,
* these segments are used to insert the appropriate color/style codes at the correct positions.
*
* The highlighter maintains a collection of these segments and applies them
* in position order to create the complete highlighted output.
*
* @example
* ```ts
* const keywordSegment: HighlightNodeSegmentInterface = {
* start: 0,
* end: 6,
* color: '\x1b[34m', // Blue for the keyword "import"
* reset: '\x1b[0m' // Reset to default
* };
* ```
*
* @see HighlightSchemeInterface
* @see addSegment
*
* @since 1.0.0
*/
export interface HighlightNodeSegmentInterface {
end: number;
start: number;
color: string;
reset: string;
}
/**
* An enum containing ANSI escape sequences for various colors
*
* @remarks
* This enum is primarily intended for terminal output and won't work directly in JavaScript for web development.
* It defines color codes for various colors and a reset code to return to the default text color.
*
* @example
* ```ts
* console.log(`${Colors.red}This text will be red in the terminal.${Colors.reset}`);
* ```
*
* @since 1.0.0
*/
export declare const enum Colors {
reset = "\u001B[0m",
gray = "\u001B[38;5;243m",
darkGray = "\u001B[38;5;238m",
lightCoral = "\u001B[38;5;203m",
lightOrange = "\u001B[38;5;215m",
oliveGreen = "\u001B[38;5;149m",
burntOrange = "\u001B[38;5;208m",
lightGoldenrodYellow = "\u001B[38;5;221m",
lightYellow = "\u001B[38;5;230m",
canaryYellow = "\u001B[38;5;227m",
deepOrange = "\u001B[38;5;166m",
lightGray = "\u001B[38;5;252m",
brightPink = "\u001B[38;5;197m"
}
/**
* Class responsible for applying semantic highlighting to a source code string based on a given color scheme
*
* @remarks
* Processes TypeScript AST nodes and applies color formatting to different code elements
* according to the provided color scheme.
*
* @example
* ```ts
* const sourceFile = ts.createSourceFile('example.ts', code, ts.ScriptTarget.Latest);
* const highlighter = new CodeHighlighter(sourceFile, code, customScheme);
* highlighter.parseNode(sourceFile);
* const highlightedCode = highlighter.highlight();
* ```
*
* @since 1.0.0
*/
export declare class CodeHighlighter {
private sourceFile;
private code;
private schema;
/**
* A Map of segments where the key is a combination of start and end positions.
*
* @remarks
* This structure ensures unique segments and allows for fast lookups and updates.
*
* @see HighlightNodeSegmentInterface
* @since 1.0.0
*/
private segments;
/**
* Creates an instance of the CodeHighlighter class.
*
* @param sourceFile - The TypeScript AST node representing the source file
* @param code - The source code string to be highlighted
* @param schema - The color scheme used for highlighting different elements in the code
*
* @since 1.0.0
*/
constructor(sourceFile: ts.Node, code: string, schema: HighlightSchemeInterface);
/**
* Parses a TypeScript AST node and processes its comments to identify segments that need highlighting.
*
* @param node - The TypeScript AST node to be parsed
*
* @since 1.0.0
*/
parseNode(node: ts.Node): void;
/**
* Generates a string with highlighted code segments based on the provided color scheme.
*
* @returns The highlighted code as a string, with ANSI color codes applied to the segments
*
* @remarks
* This method processes the stored segments, applies the appropriate colors to each segment,
* and returns the resulting highlighted code as a single string.
*
* @since 1.0.0
*/
highlight(): string;
/**
* Extracts a text segment from the source code using position indices.
*
* @param start - The starting index position in the source text
* @param end - The ending index position in the source text (optional)
* @returns The substring of source text between the start and end positions
*
* @remarks
* This utility method provides access to specific portions of the source code
* based on character positions. When the end parameter is omitted, the extraction
* will continue to the end of the source text.
*
* This method is typically used during the highlighting process to access the
* actual text content that corresponds to syntax nodes or other text ranges
* before applying formatting.
*
* @example
* ```ts
* // Extract a variable name
* const variableName = this.getSegmentSource(10, 15);
*
* // Extract from a position to the end of source
* const remaining = this.getSegmentSource(100);
* ```
*
* @see addSegment
* @see highlight
*
* @since 1.0.0
*/
private getSegmentSource;
/**
* Registers a text segment for syntax highlighting with specified style information.
*
* @param start - The starting position of the segment in the source text
* @param end - The ending position of the segment in the source text
* @param color - The color code to apply to this segment
* @param reset - The color reset code to apply after the segment (defaults to the standard reset code)
*
* @remarks
* This method creates a unique key for each segment based on its position and stores the segment information in a map.
* Each segment contains its position information, styling code,
* and reset code which will later be used during the highlighting process.
*
* If multiple segments are added with the same positions, the later additions will
* overwrite earlier ones due to the map's key-based storage.
*
* @example
* ```ts
* // Highlight a variable name in red
* this.addSegment(10, 15, Colors.red);
*
* // Highlight a keyword with custom color and reset
* this.addSegment(20, 26, Colors.blue, Colors.customReset);
* ```
*
* @see Colors
* @see processNode
*
* @since 1.0.0
*/
private addSegment;
/**
* Processes and highlights comments associated with a TypeScript AST node.
*
* @param node - The TypeScript AST node whose comments are to be processed
*
* @remarks
* This method identifies both leading and trailing comments associated with the given node
* and adds them to the highlighting segments.
* The comments are extracted from the full source text using TypeScript's utility functions
* and are highlighted using the color specified
* in the schema's commentColor property.
*
* Leading comments appear before the node, while trailing comments appear after it.
* Both types are processed with the same highlighting style.
*
* @example
* ```ts
* // For a node that might have comments like:
* // This is a leading comment
* const x = 5; // This is a trailing comment
*
* this.processComments(someNode);
* // Both comments will be added to segments with the comment color
* ```
*
* @see addSegment
* @see ts.getLeadingCommentRanges
* @see ts.getTrailingCommentRanges
*
* @since 1.0.0
*/
private processComments;
/**
* Processes TypeScript keywords and primitive type references in an AST node for syntax highlighting.
*
* @param node - The TypeScript AST node to be processed for keywords
*
* @remarks
* This method handles two categories of tokens that require special highlighting:
*
* 1. Primitive type references: Highlights references to built-in types like `null`,
* `void`, `string`, `number`, `boolean`, and `undefined` using the type color.
*
* 2. TypeScript keywords: Identifies any node whose kind falls within the TypeScript
* keyword range (between FirstKeyword and LastKeyword) and highlights it using
* the keyword color.
*
* Each identified token is added to the segments collection with appropriate position
* and color information.
*
* @example
* ```ts
* // Inside syntax highlighting process
* this.processKeywords(someNode);
* // If the node represents a keyword like 'const' or a primitive type like 'string',
* // it will be added to the segments with the appropriate color
* ```
*
* @see addSegment
* @see ts.SyntaxKind
*
* @since 1.0.0
*/
private processKeywords;
/**
* Processes identifier nodes and applies appropriate syntax highlighting based on their context.
*
* @param node - The TypeScript AST node representing the identifier to be processed
*
* @remarks
* This method determines the appropriate color for an identifier by examining its parent node's kind.
* Different colors are applied based on the identifier's role in the code:
* - Enum members use enumColor
* - Interface names use interfaceColor
* - Class names use classColor
* - Function and method names use functionColor
* - Parameters use parameterColor
* - Variables and properties use variableColor
* - Types use typeColor
* - And more specialized cases for other syntax kinds
*
* Special handling is applied to property access expressions to differentiate between
* the object being accessed and the property being accessed.
*
* @example
* ```ts
* // Inside the CodeHighlighter class
* const identifierNode = getIdentifierNode(); // Get some identifier node
* this.processIdentifier(identifierNode);
* // The identifier is now added to segments with appropriate color based on its context
* ```
*
* @see addSegment
* @see HighlightSchemeInterface
*
* @since 1.0.0
*/
private processIdentifier;
/**
* Processes a TypeScript template expression and adds highlighting segments for its literal parts.
*
* @param templateExpression - The TypeScript template expression to be processed
*
* @remarks
* This method adds color segments for both the template head and each template span's literal part.
* All template string components are highlighted using the color defined in the schema's stringColor.
*
* @example
* ```ts
* // Given a template expression like: `Hello ${name}`
* this.processTemplateExpression(templateNode);
* // Both "Hello " and the closing part after the expression will be highlighted
* ```
*
* @see addSegment
*
* @since 1.0.0
*/
private processTemplateExpression;
/**
* Processes a TypeScript AST node and adds highlighting segments based on the node's kind.
*
* @param node - The TypeScript AST node to be processed
*
* @remarks
* This method identifies the node's kind and applies the appropriate color for highlighting.
* It handles various syntax kinds including literals (string, numeric, regular expressions),
* template expressions, identifiers, and type references.
* For complex node types like template expressions and identifiers, it delegates to specialized processing methods.
*
* @throws Error - When casting to TypeParameterDeclaration fails for non-compatible node kinds
*
* @example
* ```ts
* // Inside the CodeHighlighter class
* const node = sourceFile.getChildAt(0);
* this.processNode(node);
* // Node is now added to the segments map with appropriate colors
* ```
*
* @see processTemplateExpression
* @see processIdentifier
*
* @since 1.0.0
*/
private processNode;
}
/**
* Applies semantic highlighting to the provided code string using the specified color scheme.
*
* @param code - The source code to be highlighted
* @param schema - An optional partial schema defining the color styles for various code elements
*
* @returns A string with the code elements wrapped in the appropriate color styles
*
* @remarks
* If no schema is provided, the default schema will be used. The function creates a TypeScript
* source file from the provided code and walks through its AST to apply syntax highlighting.
*
* @example
* ```ts
* const code = 'const x: number = 42;';
* const schema = {
* keywordColor: '\x1b[34m', // Blue
* numberColor: '\x1b[31m', // Red
* };
* const highlightedCode = highlightCode(code, schema);
* console.log(highlightedCode);
* ```
*
* @see CodeHighlighter
* @see HighlightSchemeInterface
*
* @since 1.0.0
*/
export declare function highlightCode(code: string, schema?: Partial<HighlightSchemeInterface>): string;