@remotex-labs/xmap 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/formatter.component.js.map +3 -3
- package/dist/cjs/highlighter.component.js.map +3 -3
- package/dist/cjs/index.js.map +3 -3
- package/dist/cjs/parser.component.js +2 -2
- package/dist/cjs/parser.component.js.map +4 -4
- package/dist/esm/formatter.component.js.map +3 -3
- package/dist/esm/highlighter.component.js.map +3 -3
- package/dist/esm/index.js.map +3 -3
- package/dist/esm/parser.component.js +2 -2
- package/dist/esm/parser.component.js.map +4 -4
- package/dist/formatter.component.d.ts +258 -0
- package/dist/{components/highlighter.component.d.ts → highlighter.component.d.ts} +94 -11
- package/dist/index.d.ts +866 -3
- package/dist/{components/parser.component.d.ts → parser.component.d.ts} +58 -14
- package/package.json +22 -18
- package/dist/components/base64.component.d.ts +0 -70
- package/dist/components/formatter.component.d.ts +0 -68
- package/dist/components/interfaces/formatter-component.interface.d.ts +0 -60
- package/dist/components/interfaces/highlighter-component.interface.d.ts +0 -94
- package/dist/components/interfaces/parse-component.interface.d.ts +0 -52
- package/dist/providers/interfaces/mapping-provider.interface.d.ts +0 -141
- package/dist/providers/mapping.provider.d.ts +0 -317
- package/dist/services/interfaces/source-service.interface.d.ts +0 -139
- package/dist/services/source.service.d.ts +0 -216
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/formatter.component.ts"],
|
|
4
|
-
"sourceRoot": "https://github.com/remotex-lab/xmap/tree/v3.0.
|
|
5
|
-
"sourcesContent": ["/**\n * Export interfaces\n */\nexport type * from '@components/interfaces/formatter-component.interface';\n/**\n * Import will remove at compile time\n */\nimport type { PositionWithCodeInterface } from '@services/interfaces/source-service.interface';\nimport type { AnsiOptionInterface, FormatCodeInterface } from '@components/interfaces/formatter-component.interface';\n/**\n * Formats a code snippet with optional line padding and custom actions\n *\n * @param code - The source code | stack to be formatted\n * @param options - Configuration options for formatting the code\n * @returns A formatted string of the code snippet with applied padding and custom actions\n *\n * @remarks\n * This function takes a code string and an options object to format the code snippet.\n * It applies padding to line numbers and can trigger custom actions for specific lines.\n * Options include padding (default 10), startLine (default 0), and custom actions for specific lines.\n *\n * @example\n * ```ts\n * const formattedCode = formatCode(code, {\n * padding: 8,\n * startLine: 5,\n * action: {\n * triggerLine: 7,\n * callback: (lineString, padding, lineNumber) => {\n * return `Custom formatting for line ${lineNumber}: ${lineString}`;\n * }\n * }\n * });\n * ```\n *\n * @since 1.0.0\n */\nexport function formatCode(code: string, options: FormatCodeInterface = {}): string {\n const lines = code.split('\\n');\n const padding = options.padding ?? 10;\n const startLine = options.startLine ?? 0;\n return lines.map((lineContent, index) => {\n const currentLineNumber = index + startLine + 1;\n const prefix = `${currentLineNumber} | `;\n const string = `${prefix.padStart(padding)}${lineContent}`;\n if (options.action && currentLineNumber === options.action.triggerLine) {\n return options.action.callback(string, padding, currentLineNumber);\n }\n return string;\n }).join('\\n');\n}\n/**\n * Formats a code snippet around an error location with special highlighting\n *\n * @param sourcePosition - An object containing information about the source code and error location\n * @param ansiOption - Optional configuration for ANSI color codes\n * @returns A formatted string representing the relevant code snippet with error highlighting\n *\n * @throws Error - If the provided sourcePosition object has invalid line or column numbers\n *\n * @remarks\n * This function takes a sourcePosition object with code content and error location information,\n * then uses formatCode to format and highlight the relevant code snippet around the error.\n * The sourcePosition object should contain code (string), line (number), column (number),\n * and optional startLine (number, defaults to 1).\n *\n * @example\n * ```ts\n * const formattedErrorCode = formatErrorCode({\n * code: \"const x = 1;\\nconst y = x.undefined;\\n\",\n * line: 2,\n * column: 15,\n * startLine: 1\n * });\n * ```\n *\n * @see formatCode - The underlying function used for basic code formatting\n *\n * @since 1.0.0\n */\nexport function formatErrorCode(sourcePosition: PositionWithCodeInterface, ansiOption?: AnsiOptionInterface): string {\n const { code, line: errorLine, column: errorColumn, startLine } = sourcePosition;\n // Validate line and column numbers\n if (errorLine < startLine || errorColumn < 1) {\n throw new Error('Invalid line or column number.');\n }\n return formatCode(code, {\n startLine,\n action: {\n triggerLine: errorLine,\n callback: (lineString, padding, line) => {\n let pointer = '^';\n let ansiPadding = padding - 1; // 1 size of the char we added\n let prefixPointer = '>';\n if (ansiOption) {\n pointer = `${ansiOption.color}${pointer}${ansiOption.reset}`;\n ansiPadding += (ansiOption.color.length + ansiOption.reset.length);\n prefixPointer = `${ansiOption.color}>${ansiOption.reset}`;\n }\n const errorMarker = ' | '.padStart(padding) + ' '.repeat(errorColumn - 1) + `${pointer}`;\n lineString = `${prefixPointer} ${line} |`.padStart(ansiPadding) + lineString.split('|')[1];\n return lineString + `\\n${errorMarker}`;\n }\n }\n });\n}\n"],
|
|
6
|
-
"mappings": "
|
|
4
|
+
"sourceRoot": "https://github.com/remotex-lab/xmap/tree/v3.0.3/",
|
|
5
|
+
"sourcesContent": ["/**\n * Export interfaces\n */\n\nexport type * from '@components/interfaces/formatter-component.interface';\n\n/**\n * Import will remove at compile time\n */\n\nimport type { PositionWithCodeInterface } from '@services/interfaces/source-service.interface';\nimport type { AnsiOptionInterface, FormatCodeInterface } from '@components/interfaces/formatter-component.interface';\n\n/**\n * Formats a code snippet with optional line padding and custom actions\n *\n * @param code - The source code | stack to be formatted\n * @param options - Configuration options for formatting the code\n * @returns A formatted string of the code snippet with applied padding and custom actions\n *\n * @remarks\n * This function takes a code string and an options object to format the code snippet.\n * It applies padding to line numbers and can trigger custom actions for specific lines.\n * Options include padding (default 10), startLine (default 0), and custom actions for specific lines.\n *\n * @example\n * ```ts\n * const formattedCode = formatCode(code, {\n * padding: 8,\n * startLine: 5,\n * action: {\n * triggerLine: 7,\n * callback: (lineString, padding, lineNumber) => {\n * return `Custom formatting for line ${lineNumber}: ${lineString}`;\n * }\n * }\n * });\n * ```\n *\n * @since 1.0.0\n */\n\nexport function formatCode(code: string, options: FormatCodeInterface = {}): string {\n const lines = code.split('\\n');\n const padding = options.padding ?? 10;\n const startLine = options.startLine ?? 0;\n\n return lines.map((lineContent, index) => {\n const currentLineNumber = index + startLine + 1;\n const prefix = `${ currentLineNumber} | `;\n const string = `${ prefix.padStart(padding) }${ lineContent }`;\n\n if (options.action && currentLineNumber === options.action.triggerLine) {\n return options.action.callback(string, padding, currentLineNumber);\n }\n\n return string;\n }).join('\\n');\n}\n\n/**\n * Formats a code snippet around an error location with special highlighting\n *\n * @param sourcePosition - An object containing information about the source code and error location\n * @param ansiOption - Optional configuration for ANSI color codes\n * @returns A formatted string representing the relevant code snippet with error highlighting\n *\n * @throws Error - If the provided sourcePosition object has invalid line or column numbers\n *\n * @remarks\n * This function takes a sourcePosition object with code content and error location information,\n * then uses formatCode to format and highlight the relevant code snippet around the error.\n * The sourcePosition object should contain code (string), line (number), column (number),\n * and optional startLine (number, defaults to 1).\n *\n * @example\n * ```ts\n * const formattedErrorCode = formatErrorCode({\n * code: \"const x = 1;\\nconst y = x.undefined;\\n\",\n * line: 2,\n * column: 15,\n * startLine: 1\n * });\n * ```\n *\n * @see formatCode - The underlying function used for basic code formatting\n *\n * @since 1.0.0\n */\n\nexport function formatErrorCode(sourcePosition: PositionWithCodeInterface, ansiOption?: AnsiOptionInterface): string {\n const { code, line: errorLine, column: errorColumn, startLine } = sourcePosition;\n\n // Validate line and column numbers\n if (errorLine < startLine || errorColumn < 1) {\n throw new Error('Invalid line or column number.');\n }\n\n return formatCode(code, {\n startLine,\n action: {\n triggerLine: errorLine,\n callback: (lineString, padding, line) => {\n let pointer = '^';\n let ansiPadding = padding - 1; // 1 size of the char we added\n let prefixPointer = '>';\n\n if (ansiOption) {\n pointer = `${ ansiOption.color }${ pointer }${ ansiOption.reset }`;\n ansiPadding += (ansiOption.color.length + ansiOption.reset.length);\n prefixPointer = `${ ansiOption.color }>${ ansiOption.reset }`;\n }\n\n const errorMarker = ' | '.padStart(padding) + ' '.repeat(errorColumn - 1) + `${ pointer }`;\n lineString = `${ prefixPointer } ${ line } |`.padStart(ansiPadding) + lineString.split('|')[1];\n\n return lineString + `\\n${ errorMarker }`;\n }\n }\n });\n}\n"],
|
|
6
|
+
"mappings": "AA0CO,SAASA,EAAWC,EAAcC,EAA+B,CAAC,EAAW,CAChF,IAAMC,EAAQF,EAAK,MAAM;AAAA,CAAI,EACvBG,EAAUF,EAAQ,SAAW,GAC7BG,EAAYH,EAAQ,WAAa,EAEvC,OAAOC,EAAM,IAAI,CAACG,EAAaC,IAAU,CACrC,IAAMC,EAAoBD,EAAQF,EAAY,EAExCI,EAAS,GADA,GAAID,CAAiB,MACV,SAASJ,CAAO,CAAE,GAAIE,CAAY,GAE5D,OAAIJ,EAAQ,QAAUM,IAAsBN,EAAQ,OAAO,YAChDA,EAAQ,OAAO,SAASO,EAAQL,EAASI,CAAiB,EAG9DC,CACX,CAAC,EAAE,KAAK;AAAA,CAAI,CAChB,CAgCO,SAASC,EAAgBC,EAA2CC,EAA0C,CACjH,GAAM,CAAE,KAAAX,EAAM,KAAMY,EAAW,OAAQC,EAAa,UAAAT,CAAU,EAAIM,EAGlE,GAAIE,EAAYR,GAAaS,EAAc,EACvC,MAAM,IAAI,MAAM,gCAAgC,EAGpD,OAAOd,EAAWC,EAAM,CACpB,UAAAI,EACA,OAAQ,CACJ,YAAaQ,EACb,SAAU,CAACE,EAAYX,EAASY,IAAS,CACrC,IAAIC,EAAU,IACVC,EAAcd,EAAU,EACxBe,EAAgB,IAEhBP,IACAK,EAAU,GAAIL,EAAW,KAAM,GAAIK,CAAQ,GAAIL,EAAW,KAAM,GAChEM,GAAgBN,EAAW,MAAM,OAASA,EAAW,MAAM,OAC3DO,EAAgB,GAAIP,EAAW,KAAM,IAAKA,EAAW,KAAM,IAG/D,IAAMQ,EAAc,MAAM,SAAShB,CAAO,EAAI,IAAI,OAAOU,EAAc,CAAC,EAAI,GAAIG,CAAQ,GACxF,OAAAF,EAAa,GAAII,CAAc,IAAKH,CAAK,KAAK,SAASE,CAAW,EAAIH,EAAW,MAAM,GAAG,EAAE,CAAC,EAEtFA,EAAa;AAAA,EAAMK,CAAY,EAC1C,CACJ,CACJ,CAAC,CACL",
|
|
7
7
|
"names": ["formatCode", "code", "options", "lines", "padding", "startLine", "lineContent", "index", "currentLineNumber", "string", "formatErrorCode", "sourcePosition", "ansiOption", "errorLine", "errorColumn", "lineString", "line", "pointer", "ansiPadding", "prefixPointer", "errorMarker"]
|
|
8
8
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/highlighter.component.ts"],
|
|
4
|
-
"sourceRoot": "https://github.com/remotex-lab/xmap/tree/v3.0.
|
|
5
|
-
"sourcesContent": ["/**\n * Export interfaces\n */\nexport type * from '@components/interfaces/highlighter-component.interface';\n/**\n * Import will remove at compile time\n */\nimport type { HighlightSchemeInterface, HighlightNodeSegmentInterface } from '@components/interfaces/highlighter-component.interface';\n/**\n * Imports\n */\nimport * as ts from 'typescript';\nimport { SyntaxKind } from 'typescript';\n/**\n * An enum containing ANSI escape sequences for various colors\n *\n * @remarks\n * This enum is primarily intended for terminal output and won't work directly in JavaScript for web development.\n * It defines color codes for various colors and a reset code to return to the default text color.\n *\n * @example\n * ```ts\n * console.log(`${Colors.red}This text will be red in the terminal.${Colors.reset}`);\n * ```\n *\n * @since 1.0.0\n */\nexport const enum Colors {\n reset = '\\x1b[0m',\n gray = '\\x1b[38;5;243m',\n darkGray = '\\x1b[38;5;238m',\n lightCoral = '\\x1b[38;5;203m',\n lightOrange = '\\x1b[38;5;215m',\n oliveGreen = '\\x1b[38;5;149m',\n burntOrange = '\\x1b[38;5;208m',\n lightGoldenrodYellow = '\\x1b[38;5;221m',\n lightYellow = '\\x1b[38;5;230m',\n canaryYellow = '\\x1b[38;5;227m',\n deepOrange = '\\x1b[38;5;166m',\n lightGray = '\\x1b[38;5;252m',\n brightPink = '\\x1b[38;5;197m'\n}\n/**\n * Default color scheme for semantic highlighting\n *\n * @remarks\n * This scheme defines colors for different code elements to be used for syntax highlighting.\n *\n * @example\n * ```ts\n * const scheme = defaultScheme;\n * console.log(scheme.typeColor); // Outputs: the color code for types\n * ```\n *\n * @see HighlightSchemeInterface\n * @see Colors\n *\n * @since 1.0.0\n */\nconst defaultScheme: HighlightSchemeInterface = {\n enumColor: Colors.burntOrange,\n typeColor: Colors.lightGoldenrodYellow,\n classColor: Colors.lightOrange,\n stringColor: Colors.oliveGreen,\n keywordColor: Colors.lightCoral,\n commentColor: Colors.darkGray,\n functionColor: Colors.lightOrange,\n variableColor: Colors.burntOrange,\n interfaceColor: Colors.lightGoldenrodYellow,\n parameterColor: Colors.deepOrange,\n getAccessorColor: Colors.lightYellow,\n numericLiteralColor: Colors.lightGray,\n methodSignatureColor: Colors.burntOrange,\n regularExpressionColor: Colors.oliveGreen,\n propertyAssignmentColor: Colors.canaryYellow,\n propertyAccessExpressionColor: Colors.lightYellow,\n expressionWithTypeArgumentsColor: Colors.lightOrange\n};\n/**\n * Class responsible for applying semantic highlighting to a source code string based on a given color scheme\n *\n * @remarks\n * Processes TypeScript AST nodes and applies color formatting to different code elements\n * according to the provided color scheme.\n *\n * @example\n * ```ts\n * const sourceFile = ts.createSourceFile('example.ts', code, ts.ScriptTarget.Latest);\n * const highlighter = new CodeHighlighter(sourceFile, code, customScheme);\n * highlighter.parseNode(sourceFile);\n * const highlightedCode = highlighter.highlight();\n * ```\n *\n * @since 1.0.0\n */\nexport class CodeHighlighter {\n /**\n * A Map of segments where the key is a combination of start and end positions.\n *\n * @remarks\n * This structure ensures unique segments and allows for fast lookups and updates.\n *\n * @see HighlightNodeSegmentInterface\n * @since 1.0.0\n */\n private segments: Map<string, HighlightNodeSegmentInterface> = new Map();\n /**\n * Creates an instance of the CodeHighlighter class.\n *\n * @param sourceFile - The TypeScript AST node representing the source file\n * @param code - The source code string to be highlighted\n * @param schema - The color scheme used for highlighting different elements in the code\n *\n * @since 1.0.0\n */\n constructor(private sourceFile: ts.Node, private code: string, private schema: HighlightSchemeInterface) {\n }\n /**\n * Parses a TypeScript AST node and processes its comments to identify segments that need highlighting.\n *\n * @param node - The TypeScript AST node to be parsed\n *\n * @since 1.0.0\n */\n parseNode(node: ts.Node): void {\n this.processComments(node);\n this.processKeywords(node);\n this.processNode(node);\n }\n /**\n * Generates a string with highlighted code segments based on the provided color scheme.\n *\n * @returns The highlighted code as a string, with ANSI color codes applied to the segments\n *\n * @remarks\n * This method processes the stored segments, applies the appropriate colors to each segment,\n * and returns the resulting highlighted code as a single string.\n *\n * @since 1.0.0\n */\n highlight(): string {\n let previousSegmentEnd = 0;\n let parent: HighlightNodeSegmentInterface | undefined;\n const result: Array<string> = [];\n const segments = Array.from(this.segments.values()).sort((a, b) => a.start - b.start || a.end - b.end);\n segments.forEach((segment) => {\n if (parent && segment.start < parent.end) {\n const lastSegment = result.pop();\n if (!lastSegment)\n return;\n const source = this.getSegmentSource(segment.start, segment.end);\n const combinedSource = `${segment.color}${source}${parent.color}`;\n result.push(lastSegment.replace(source, combinedSource));\n return;\n }\n result.push(this.getSegmentSource(previousSegmentEnd, segment.start));\n result.push(`${segment.color}${this.getSegmentSource(segment.start, segment.end)}${segment.reset}`);\n previousSegmentEnd = segment.end;\n parent = segment;\n });\n return result.join('') + this.getSegmentSource(previousSegmentEnd);\n }\n /**\n * Extracts a text segment from the source code using position indices.\n *\n * @param start - The starting index position in the source text\n * @param end - The ending index position in the source text (optional)\n * @returns The substring of source text between the start and end positions\n *\n * @remarks\n * This utility method provides access to specific portions of the source code\n * based on character positions. When the end parameter is omitted, the extraction\n * will continue to the end of the source text.\n *\n * This method is typically used during the highlighting process to access the\n * actual text content that corresponds to syntax nodes or other text ranges\n * before applying formatting.\n *\n * @example\n * ```ts\n * // Extract a variable name\n * const variableName = this.getSegmentSource(10, 15);\n *\n * // Extract from a position to the end of source\n * const remaining = this.getSegmentSource(100);\n * ```\n *\n * @see addSegment\n * @see highlight\n *\n * @since 1.0.0\n */\n private getSegmentSource(start: number, end?: number): string {\n return this.code.slice(start, end);\n }\n /**\n * Registers a text segment for syntax highlighting with specified style information.\n *\n * @param start - The starting position of the segment in the source text\n * @param end - The ending position of the segment in the source text\n * @param color - The color code to apply to this segment\n * @param reset - The color reset code to apply after the segment (defaults to the standard reset code)\n *\n * @remarks\n * This method creates a unique key for each segment based on its position and stores the segment information in a map.\n * Each segment contains its position information, styling code,\n * and reset code which will later be used during the highlighting process.\n *\n * If multiple segments are added with the same positions, the later additions will\n * overwrite earlier ones due to the map's key-based storage.\n *\n * @example\n * ```ts\n * // Highlight a variable name in red\n * this.addSegment(10, 15, Colors.red);\n *\n * // Highlight a keyword with custom color and reset\n * this.addSegment(20, 26, Colors.blue, Colors.customReset);\n * ```\n *\n * @see Colors\n * @see processNode\n *\n * @since 1.0.0\n */\n private addSegment(start: number, end: number, color: string, reset: string = Colors.reset) {\n const key = `${start}-${end}`;\n this.segments.set(key, { start, end, color, reset });\n }\n /**\n * Processes and highlights comments associated with a TypeScript AST node.\n *\n * @param node - The TypeScript AST node whose comments are to be processed\n *\n * @remarks\n * This method identifies both leading and trailing comments associated with the given node\n * and adds them to the highlighting segments.\n * The comments are extracted from the full source text using TypeScript's utility functions\n * and are highlighted using the color specified\n * in the schema's commentColor property.\n *\n * Leading comments appear before the node, while trailing comments appear after it.\n * Both types are processed with the same highlighting style.\n *\n * @example\n * ```ts\n * // For a node that might have comments like:\n * // This is a leading comment\n * const x = 5; // This is a trailing comment\n *\n * this.processComments(someNode);\n * // Both comments will be added to segments with the comment color\n * ```\n *\n * @see addSegment\n * @see ts.getLeadingCommentRanges\n * @see ts.getTrailingCommentRanges\n *\n * @since 1.0.0\n */\n private processComments(node: ts.Node): void {\n const comments = [\n ...ts.getTrailingCommentRanges(this.sourceFile.getFullText(), node.getFullStart()) || [],\n ...ts.getLeadingCommentRanges(this.sourceFile.getFullText(), node.getFullStart()) || []\n ];\n comments.forEach(comment => this.addSegment(comment.pos, comment.end, this.schema.commentColor));\n }\n /**\n * Processes TypeScript keywords and primitive type references in an AST node for syntax highlighting.\n *\n * @param node - The TypeScript AST node to be processed for keywords\n *\n * @remarks\n * This method handles two categories of tokens that require special highlighting:\n *\n * 1. Primitive type references: Highlights references to built-in types like `null`,\n * `void`, `string`, `number`, `boolean`, and `undefined` using the type color.\n *\n * 2. TypeScript keywords: Identifies any node whose kind falls within the TypeScript\n * keyword range (between FirstKeyword and LastKeyword) and highlights it using\n * the keyword color.\n *\n * Each identified token is added to the segments collection with appropriate position\n * and color information.\n *\n * @example\n * ```ts\n * // Inside syntax highlighting process\n * this.processKeywords(someNode);\n * // If the node represents a keyword like 'const' or a primitive type like 'string',\n * // it will be added to the segments with the appropriate color\n * ```\n *\n * @see addSegment\n * @see ts.SyntaxKind\n *\n * @since 1.0.0\n */\n private processKeywords(node: ts.Node): void {\n if ([\n SyntaxKind.NullKeyword,\n SyntaxKind.VoidKeyword,\n SyntaxKind.StringKeyword,\n SyntaxKind.NumberKeyword,\n SyntaxKind.BooleanKeyword,\n SyntaxKind.UndefinedKeyword\n ].includes(node.kind)) {\n return this.addSegment(node.getStart(), node.getEnd(), this.schema.typeColor);\n }\n if (node && node.kind >= ts.SyntaxKind.FirstKeyword && node.kind <= ts.SyntaxKind.LastKeyword) {\n this.addSegment(node.getStart(), node.getEnd(), this.schema.keywordColor);\n }\n }\n /**\n * Processes identifier nodes and applies appropriate syntax highlighting based on their context.\n *\n * @param node - The TypeScript AST node representing the identifier to be processed\n *\n * @remarks\n * This method determines the appropriate color for an identifier by examining its parent node's kind.\n * Different colors are applied based on the identifier's role in the code:\n * - Enum members use enumColor\n * - Interface names use interfaceColor\n * - Class names use classColor\n * - Function and method names use functionColor\n * - Parameters use parameterColor\n * - Variables and properties use variableColor\n * - Types use typeColor\n * - And more specialized cases for other syntax kinds\n *\n * Special handling is applied to property access expressions to differentiate between\n * the object being accessed and the property being accessed.\n *\n * @example\n * ```ts\n * // Inside the CodeHighlighter class\n * const identifierNode = getIdentifierNode(); // Get some identifier node\n * this.processIdentifier(identifierNode);\n * // The identifier is now added to segments with appropriate color based on its context\n * ```\n *\n * @see addSegment\n * @see HighlightSchemeInterface\n *\n * @since 1.0.0\n */\n private processIdentifier(node: ts.Node): void {\n const end = node.getEnd();\n const start = node.getStart();\n switch (node.parent.kind) {\n case ts.SyntaxKind.EnumMember:\n return this.addSegment(start, end, this.schema.enumColor);\n case ts.SyntaxKind.CallExpression:\n case ts.SyntaxKind.EnumDeclaration:\n case ts.SyntaxKind.PropertySignature:\n case ts.SyntaxKind.ModuleDeclaration:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.InterfaceDeclaration:\n return this.addSegment(start, end, this.schema.interfaceColor);\n case ts.SyntaxKind.GetAccessor:\n return this.addSegment(start, end, this.schema.getAccessorColor);\n case ts.SyntaxKind.PropertyAssignment:\n return this.addSegment(start, end, this.schema.propertyAssignmentColor);\n case ts.SyntaxKind.MethodSignature:\n return this.addSegment(start, end, this.schema.methodSignatureColor);\n case ts.SyntaxKind.MethodDeclaration:\n case ts.SyntaxKind.FunctionDeclaration:\n return this.addSegment(start, end, this.schema.functionColor);\n case ts.SyntaxKind.ClassDeclaration:\n return this.addSegment(start, end, this.schema.classColor);\n case ts.SyntaxKind.Parameter:\n return this.addSegment(start, end, this.schema.parameterColor);\n case ts.SyntaxKind.VariableDeclaration:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.PropertyDeclaration:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.PropertyAccessExpression: {\n if (node.parent.getChildAt(0).getText() === node.getText()) {\n return this.addSegment(start, end, this.schema.variableColor);\n }\n return this.addSegment(start, end, this.schema.propertyAccessExpressionColor);\n }\n case ts.SyntaxKind.ExpressionWithTypeArguments:\n return this.addSegment(start, end, this.schema.expressionWithTypeArgumentsColor);\n case ts.SyntaxKind.BreakStatement:\n case ts.SyntaxKind.ShorthandPropertyAssignment:\n case ts.SyntaxKind.BindingElement:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.BinaryExpression:\n case ts.SyntaxKind.SwitchStatement:\n case ts.SyntaxKind.TemplateSpan:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.TypeReference:\n case ts.SyntaxKind.TypeAliasDeclaration:\n return this.addSegment(start, end, this.schema.typeColor);\n case ts.SyntaxKind.NewExpression:\n return this.addSegment(start, end, this.schema.variableColor);\n }\n }\n /**\n * Processes a TypeScript template expression and adds highlighting segments for its literal parts.\n *\n * @param templateExpression - The TypeScript template expression to be processed\n *\n * @remarks\n * This method adds color segments for both the template head and each template span's literal part.\n * All template string components are highlighted using the color defined in the schema's stringColor.\n *\n * @example\n * ```ts\n * // Given a template expression like: `Hello ${name}`\n * this.processTemplateExpression(templateNode);\n * // Both \"Hello \" and the closing part after the expression will be highlighted\n * ```\n *\n * @see addSegment\n *\n * @since 1.0.0\n */\n private processTemplateExpression(templateExpression: ts.TemplateExpression): void {\n const start = templateExpression.head.getStart();\n const end = templateExpression.head.getEnd();\n this.addSegment(start, end, this.schema.stringColor);\n templateExpression.templateSpans.forEach(span => {\n const spanStart = span.literal.getStart();\n const spanEnd = span.literal.getEnd();\n this.addSegment(spanStart, spanEnd, this.schema.stringColor);\n });\n }\n /**\n * Processes a TypeScript AST node and adds highlighting segments based on the node's kind.\n *\n * @param node - The TypeScript AST node to be processed\n *\n * @remarks\n * This method identifies the node's kind and applies the appropriate color for highlighting.\n * It handles various syntax kinds including literals (string, numeric, regular expressions),\n * template expressions, identifiers, and type references.\n * For complex node types like template expressions and identifiers, it delegates to specialized processing methods.\n *\n * @throws Error - When casting to TypeParameterDeclaration fails for non-compatible node kinds\n *\n * @example\n * ```ts\n * // Inside the CodeHighlighter class\n * const node = sourceFile.getChildAt(0);\n * this.processNode(node);\n * // Node is now added to the segments map with appropriate colors\n * ```\n *\n * @see processTemplateExpression\n * @see processIdentifier\n *\n * @since 1.0.0\n */\n private processNode(node: ts.Node): void {\n const start = node.getStart();\n const end = node.getEnd();\n switch (node.kind) {\n case ts.SyntaxKind.TypeParameter:\n return this.addSegment(start, start + (node as ts.TypeParameterDeclaration).name.text.length, this.schema.typeColor);\n case ts.SyntaxKind.TypeReference:\n return this.addSegment(start, end, this.schema.typeColor);\n case ts.SyntaxKind.StringLiteral:\n case ts.SyntaxKind.NoSubstitutionTemplateLiteral:\n return this.addSegment(start, end, this.schema.stringColor);\n case ts.SyntaxKind.RegularExpressionLiteral:\n return this.addSegment(start, end, this.schema.regularExpressionColor);\n case ts.SyntaxKind.TemplateExpression:\n return this.processTemplateExpression(node as ts.TemplateExpression);\n case ts.SyntaxKind.Identifier:\n return this.processIdentifier(node);\n case ts.SyntaxKind.BigIntLiteral:\n case ts.SyntaxKind.NumericLiteral:\n return this.addSegment(start, end, this.schema.numericLiteralColor);\n }\n }\n}\n/**\n * Applies semantic highlighting to the provided code string using the specified color scheme.\n *\n * @param code - The source code to be highlighted\n * @param schema - An optional partial schema defining the color styles for various code elements\n *\n * @returns A string with the code elements wrapped in the appropriate color styles\n *\n * @remarks\n * If no schema is provided, the default schema will be used. The function creates a TypeScript\n * source file from the provided code and walks through its AST to apply syntax highlighting.\n *\n * @example\n * ```ts\n * const code = 'const x: number = 42;';\n * const schema = {\n * keywordColor: '\\x1b[34m', // Blue\n * numberColor: '\\x1b[31m', // Red\n * };\n * const highlightedCode = highlightCode(code, schema);\n * console.log(highlightedCode);\n * ```\n *\n * @see CodeHighlighter\n * @see HighlightSchemeInterface\n *\n * @since 1.0.0\n */\nexport function highlightCode(code: string, schema: Partial<HighlightSchemeInterface> = {}) {\n const sourceFile = ts.createSourceFile('temp.ts', code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const codeHighlighter = new CodeHighlighter(sourceFile, code, Object.assign(defaultScheme, schema));\n function walk(node: ts.Node): void {\n codeHighlighter.parseNode(node);\n for (let i = 0; i < node.getChildCount(); i++) {\n walk(node.getChildAt(i));\n }\n }\n ts.forEachChild(sourceFile, walk);\n return codeHighlighter.highlight();\n}\n"],
|
|
6
|
-
"mappings": "
|
|
4
|
+
"sourceRoot": "https://github.com/remotex-lab/xmap/tree/v3.0.3/",
|
|
5
|
+
"sourcesContent": ["/**\n * Export interfaces\n */\n\nexport type * from '@components/interfaces/highlighter-component.interface';\n\n/**\n * Import will remove at compile time\n */\n\nimport type { HighlightSchemeInterface, HighlightNodeSegmentInterface } from '@components/interfaces/highlighter-component.interface';\n\n/**\n * Imports\n */\n\nimport * as ts from 'typescript';\nimport { SyntaxKind } from 'typescript';\n\n/**\n * An enum containing ANSI escape sequences for various colors\n *\n * @remarks\n * This enum is primarily intended for terminal output and won't work directly in JavaScript for web development.\n * It defines color codes for various colors and a reset code to return to the default text color.\n *\n * @example\n * ```ts\n * console.log(`${Colors.red}This text will be red in the terminal.${Colors.reset}`);\n * ```\n *\n * @since 1.0.0\n */\n\nexport const enum Colors {\n reset = '\\x1b[0m',\n gray = '\\x1b[38;5;243m',\n darkGray = '\\x1b[38;5;238m',\n lightCoral = '\\x1b[38;5;203m',\n lightOrange = '\\x1b[38;5;215m',\n oliveGreen = '\\x1b[38;5;149m',\n burntOrange = '\\x1b[38;5;208m',\n lightGoldenrodYellow = '\\x1b[38;5;221m',\n lightYellow = '\\x1b[38;5;230m',\n canaryYellow = '\\x1b[38;5;227m',\n deepOrange = '\\x1b[38;5;166m',\n lightGray = '\\x1b[38;5;252m',\n brightPink = '\\x1b[38;5;197m'\n}\n\n/**\n * Default color scheme for semantic highlighting\n *\n * @remarks\n * This scheme defines colors for different code elements to be used for syntax highlighting.\n *\n * @example\n * ```ts\n * const scheme = defaultScheme;\n * console.log(scheme.typeColor); // Outputs: the color code for types\n * ```\n *\n * @see HighlightSchemeInterface\n * @see Colors\n *\n * @since 1.0.0\n */\n\nconst defaultScheme: HighlightSchemeInterface = {\n enumColor: Colors.burntOrange,\n typeColor: Colors.lightGoldenrodYellow,\n classColor: Colors.lightOrange,\n stringColor: Colors.oliveGreen,\n keywordColor: Colors.lightCoral,\n commentColor: Colors.darkGray,\n functionColor: Colors.lightOrange,\n variableColor: Colors.burntOrange,\n interfaceColor: Colors.lightGoldenrodYellow,\n parameterColor: Colors.deepOrange,\n getAccessorColor: Colors.lightYellow,\n numericLiteralColor: Colors.lightGray,\n methodSignatureColor: Colors.burntOrange,\n regularExpressionColor: Colors.oliveGreen,\n propertyAssignmentColor: Colors.canaryYellow,\n propertyAccessExpressionColor: Colors.lightYellow,\n expressionWithTypeArgumentsColor: Colors.lightOrange\n};\n\n/**\n * Class responsible for applying semantic highlighting to a source code string based on a given color scheme\n *\n * @remarks\n * Processes TypeScript AST nodes and applies color formatting to different code elements\n * according to the provided color scheme.\n *\n * @example\n * ```ts\n * const sourceFile = ts.createSourceFile('example.ts', code, ts.ScriptTarget.Latest);\n * const highlighter = new CodeHighlighter(sourceFile, code, customScheme);\n * highlighter.parseNode(sourceFile);\n * const highlightedCode = highlighter.highlight();\n * ```\n *\n * @since 1.0.0\n */\n\nexport class CodeHighlighter {\n\n /**\n * A Map of segments where the key is a combination of start and end positions.\n *\n * @remarks\n * This structure ensures unique segments and allows for fast lookups and updates.\n *\n * @see HighlightNodeSegmentInterface\n * @since 1.0.0\n */\n\n private segments: Map<string, HighlightNodeSegmentInterface> = new Map();\n\n /**\n * Creates an instance of the CodeHighlighter class.\n *\n * @param sourceFile - The TypeScript AST node representing the source file\n * @param code - The source code string to be highlighted\n * @param schema - The color scheme used for highlighting different elements in the code\n *\n * @since 1.0.0\n */\n\n constructor(private sourceFile: ts.Node, private code: string, private schema: HighlightSchemeInterface) {\n }\n\n /**\n * Parses a TypeScript AST node and processes its comments to identify segments that need highlighting.\n *\n * @param node - The TypeScript AST node to be parsed\n *\n * @since 1.0.0\n */\n\n parseNode(node: ts.Node): void {\n this.processComments(node);\n this.processKeywords(node);\n this.processNode(node);\n }\n\n /**\n * Generates a string with highlighted code segments based on the provided color scheme.\n *\n * @returns The highlighted code as a string, with ANSI color codes applied to the segments\n *\n * @remarks\n * This method processes the stored segments, applies the appropriate colors to each segment,\n * and returns the resulting highlighted code as a single string.\n *\n * @since 1.0.0\n */\n\n highlight(): string {\n let previousSegmentEnd = 0;\n let parent: HighlightNodeSegmentInterface | undefined;\n\n const result: Array<string> = [];\n const segments = Array.from(\n this.segments.values()\n ).sort((a, b) => a.start - b.start || a.end - b.end);\n\n segments.forEach((segment) => {\n if (parent && segment.start < parent.end) {\n const lastSegment = result.pop();\n if (!lastSegment) return;\n\n const source = this.getSegmentSource(segment.start, segment.end);\n const combinedSource = `${ segment.color }${ source }${ parent.color }`;\n result.push(lastSegment.replace(source, combinedSource));\n\n return;\n }\n\n result.push(this.getSegmentSource(previousSegmentEnd, segment.start));\n result.push(`${ segment.color }${ this.getSegmentSource(segment.start, segment.end) }${ segment.reset }`);\n previousSegmentEnd = segment.end;\n parent = segment;\n });\n\n return result.join('') + this.getSegmentSource(previousSegmentEnd);\n }\n\n /**\n * Extracts a text segment from the source code using position indices.\n *\n * @param start - The starting index position in the source text\n * @param end - The ending index position in the source text (optional)\n * @returns The substring of source text between the start and end positions\n *\n * @remarks\n * This utility method provides access to specific portions of the source code\n * based on character positions. When the end parameter is omitted, the extraction\n * will continue to the end of the source text.\n *\n * This method is typically used during the highlighting process to access the\n * actual text content that corresponds to syntax nodes or other text ranges\n * before applying formatting.\n *\n * @example\n * ```ts\n * // Extract a variable name\n * const variableName = this.getSegmentSource(10, 15);\n *\n * // Extract from a position to the end of source\n * const remaining = this.getSegmentSource(100);\n * ```\n *\n * @see addSegment\n * @see highlight\n *\n * @since 1.0.0\n */\n\n private getSegmentSource(start: number, end?: number): string {\n return this.code.slice(start, end);\n }\n\n /**\n * Registers a text segment for syntax highlighting with specified style information.\n *\n * @param start - The starting position of the segment in the source text\n * @param end - The ending position of the segment in the source text\n * @param color - The color code to apply to this segment\n * @param reset - The color reset code to apply after the segment (defaults to the standard reset code)\n *\n * @remarks\n * This method creates a unique key for each segment based on its position and stores the segment information in a map.\n * Each segment contains its position information, styling code,\n * and reset code which will later be used during the highlighting process.\n *\n * If multiple segments are added with the same positions, the later additions will\n * overwrite earlier ones due to the map's key-based storage.\n *\n * @example\n * ```ts\n * // Highlight a variable name in red\n * this.addSegment(10, 15, Colors.red);\n *\n * // Highlight a keyword with custom color and reset\n * this.addSegment(20, 26, Colors.blue, Colors.customReset);\n * ```\n *\n * @see Colors\n * @see processNode\n *\n * @since 1.0.0\n */\n\n private addSegment(start: number, end: number, color: string, reset: string = Colors.reset) {\n const key = `${ start }-${ end }`;\n this.segments.set(key, { start, end, color, reset });\n }\n\n /**\n * Processes and highlights comments associated with a TypeScript AST node.\n *\n * @param node - The TypeScript AST node whose comments are to be processed\n *\n * @remarks\n * This method identifies both leading and trailing comments associated with the given node\n * and adds them to the highlighting segments.\n * The comments are extracted from the full source text using TypeScript's utility functions\n * and are highlighted using the color specified\n * in the schema's commentColor property.\n *\n * Leading comments appear before the node, while trailing comments appear after it.\n * Both types are processed with the same highlighting style.\n *\n * @example\n * ```ts\n * // For a node that might have comments like:\n * // This is a leading comment\n * const x = 5; // This is a trailing comment\n *\n * this.processComments(someNode);\n * // Both comments will be added to segments with the comment color\n * ```\n *\n * @see addSegment\n * @see ts.getLeadingCommentRanges\n * @see ts.getTrailingCommentRanges\n *\n * @since 1.0.0\n */\n\n private processComments(node: ts.Node): void {\n const comments = [\n ...ts.getTrailingCommentRanges(this.sourceFile.getFullText(), node.getFullStart()) || [],\n ...ts.getLeadingCommentRanges(this.sourceFile.getFullText(), node.getFullStart()) || []\n ];\n\n comments.forEach(comment => this.addSegment(comment.pos, comment.end, this.schema.commentColor));\n }\n\n /**\n * Processes TypeScript keywords and primitive type references in an AST node for syntax highlighting.\n *\n * @param node - The TypeScript AST node to be processed for keywords\n *\n * @remarks\n * This method handles two categories of tokens that require special highlighting:\n *\n * 1. Primitive type references: Highlights references to built-in types like `null`,\n * `void`, `string`, `number`, `boolean`, and `undefined` using the type color.\n *\n * 2. TypeScript keywords: Identifies any node whose kind falls within the TypeScript\n * keyword range (between FirstKeyword and LastKeyword) and highlights it using\n * the keyword color.\n *\n * Each identified token is added to the segments collection with appropriate position\n * and color information.\n *\n * @example\n * ```ts\n * // Inside syntax highlighting process\n * this.processKeywords(someNode);\n * // If the node represents a keyword like 'const' or a primitive type like 'string',\n * // it will be added to the segments with the appropriate color\n * ```\n *\n * @see addSegment\n * @see ts.SyntaxKind\n *\n * @since 1.0.0\n */\n\n private processKeywords(node: ts.Node): void {\n if ([\n SyntaxKind.NullKeyword,\n SyntaxKind.VoidKeyword,\n SyntaxKind.StringKeyword,\n SyntaxKind.NumberKeyword,\n SyntaxKind.BooleanKeyword,\n SyntaxKind.UndefinedKeyword\n ].includes(node.kind)) {\n return this.addSegment(node.getStart(), node.getEnd(), this.schema.typeColor);\n }\n\n if (node && node.kind >= ts.SyntaxKind.FirstKeyword && node.kind <= ts.SyntaxKind.LastKeyword) {\n this.addSegment(node.getStart(), node.getEnd(), this.schema.keywordColor);\n }\n }\n\n /**\n * Processes identifier nodes and applies appropriate syntax highlighting based on their context.\n *\n * @param node - The TypeScript AST node representing the identifier to be processed\n *\n * @remarks\n * This method determines the appropriate color for an identifier by examining its parent node's kind.\n * Different colors are applied based on the identifier's role in the code:\n * - Enum members use enumColor\n * - Interface names use interfaceColor\n * - Class names use classColor\n * - Function and method names use functionColor\n * - Parameters use parameterColor\n * - Variables and properties use variableColor\n * - Types use typeColor\n * - And more specialized cases for other syntax kinds\n *\n * Special handling is applied to property access expressions to differentiate between\n * the object being accessed and the property being accessed.\n *\n * @example\n * ```ts\n * // Inside the CodeHighlighter class\n * const identifierNode = getIdentifierNode(); // Get some identifier node\n * this.processIdentifier(identifierNode);\n * // The identifier is now added to segments with appropriate color based on its context\n * ```\n *\n * @see addSegment\n * @see HighlightSchemeInterface\n *\n * @since 1.0.0\n */\n\n private processIdentifier(node: ts.Node): void {\n const end = node.getEnd();\n const start = node.getStart();\n\n switch (node.parent.kind) {\n case ts.SyntaxKind.EnumMember:\n return this.addSegment(start, end, this.schema.enumColor);\n case ts.SyntaxKind.CallExpression:\n case ts.SyntaxKind.EnumDeclaration:\n case ts.SyntaxKind.PropertySignature:\n case ts.SyntaxKind.ModuleDeclaration:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.InterfaceDeclaration:\n return this.addSegment(start, end, this.schema.interfaceColor);\n case ts.SyntaxKind.GetAccessor:\n return this.addSegment(start, end, this.schema.getAccessorColor);\n case ts.SyntaxKind.PropertyAssignment:\n return this.addSegment(start, end, this.schema.propertyAssignmentColor);\n case ts.SyntaxKind.MethodSignature:\n return this.addSegment(start, end, this.schema.methodSignatureColor);\n case ts.SyntaxKind.MethodDeclaration:\n case ts.SyntaxKind.FunctionDeclaration:\n return this.addSegment(start, end, this.schema.functionColor);\n case ts.SyntaxKind.ClassDeclaration:\n return this.addSegment(start, end, this.schema.classColor);\n case ts.SyntaxKind.Parameter:\n return this.addSegment(start, end, this.schema.parameterColor);\n case ts.SyntaxKind.VariableDeclaration:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.PropertyDeclaration:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.PropertyAccessExpression: {\n if (node.parent.getChildAt(0).getText() === node.getText()) {\n return this.addSegment(start, end, this.schema.variableColor);\n }\n\n return this.addSegment(start, end, this.schema.propertyAccessExpressionColor);\n }\n case ts.SyntaxKind.ExpressionWithTypeArguments:\n return this.addSegment(start, end, this.schema.expressionWithTypeArgumentsColor);\n case ts.SyntaxKind.BreakStatement:\n case ts.SyntaxKind.ShorthandPropertyAssignment:\n case ts.SyntaxKind.BindingElement:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.BinaryExpression:\n case ts.SyntaxKind.SwitchStatement:\n case ts.SyntaxKind.TemplateSpan:\n return this.addSegment(start, end, this.schema.variableColor);\n case ts.SyntaxKind.TypeReference:\n case ts.SyntaxKind.TypeAliasDeclaration:\n return this.addSegment(start, end, this.schema.typeColor);\n case ts.SyntaxKind.NewExpression:\n return this.addSegment(start, end, this.schema.variableColor);\n }\n }\n\n /**\n * Processes a TypeScript template expression and adds highlighting segments for its literal parts.\n *\n * @param templateExpression - The TypeScript template expression to be processed\n *\n * @remarks\n * This method adds color segments for both the template head and each template span's literal part.\n * All template string components are highlighted using the color defined in the schema's stringColor.\n *\n * @example\n * ```ts\n * // Given a template expression like: `Hello ${name}`\n * this.processTemplateExpression(templateNode);\n * // Both \"Hello \" and the closing part after the expression will be highlighted\n * ```\n *\n * @see addSegment\n *\n * @since 1.0.0\n */\n\n private processTemplateExpression(templateExpression: ts.TemplateExpression): void {\n const start = templateExpression.head.getStart();\n const end = templateExpression.head.getEnd();\n this.addSegment(start, end, this.schema.stringColor);\n\n templateExpression.templateSpans.forEach(span => {\n const spanStart = span.literal.getStart();\n const spanEnd = span.literal.getEnd();\n this.addSegment(spanStart, spanEnd, this.schema.stringColor);\n });\n }\n\n /**\n * Processes a TypeScript AST node and adds highlighting segments based on the node's kind.\n *\n * @param node - The TypeScript AST node to be processed\n *\n * @remarks\n * This method identifies the node's kind and applies the appropriate color for highlighting.\n * It handles various syntax kinds including literals (string, numeric, regular expressions),\n * template expressions, identifiers, and type references.\n * For complex node types like template expressions and identifiers, it delegates to specialized processing methods.\n *\n * @throws Error - When casting to TypeParameterDeclaration fails for non-compatible node kinds\n *\n * @example\n * ```ts\n * // Inside the CodeHighlighter class\n * const node = sourceFile.getChildAt(0);\n * this.processNode(node);\n * // Node is now added to the segments map with appropriate colors\n * ```\n *\n * @see processTemplateExpression\n * @see processIdentifier\n *\n * @since 1.0.0\n */\n\n private processNode(node: ts.Node): void {\n const start = node.getStart();\n const end = node.getEnd();\n\n switch (node.kind) {\n case ts.SyntaxKind.TypeParameter:\n return this.addSegment(start, start + (node as ts.TypeParameterDeclaration).name.text.length, this.schema.typeColor);\n case ts.SyntaxKind.TypeReference:\n return this.addSegment(start, end, this.schema.typeColor);\n case ts.SyntaxKind.StringLiteral:\n case ts.SyntaxKind.NoSubstitutionTemplateLiteral:\n return this.addSegment(start, end, this.schema.stringColor);\n case ts.SyntaxKind.RegularExpressionLiteral:\n return this.addSegment(start, end, this.schema.regularExpressionColor);\n case ts.SyntaxKind.TemplateExpression:\n return this.processTemplateExpression(node as ts.TemplateExpression);\n case ts.SyntaxKind.Identifier:\n return this.processIdentifier(node);\n case ts.SyntaxKind.BigIntLiteral:\n case ts.SyntaxKind.NumericLiteral:\n return this.addSegment(start, end, this.schema.numericLiteralColor);\n }\n }\n}\n\n/**\n * Applies semantic highlighting to the provided code string using the specified color scheme.\n *\n * @param code - The source code to be highlighted\n * @param schema - An optional partial schema defining the color styles for various code elements\n *\n * @returns A string with the code elements wrapped in the appropriate color styles\n *\n * @remarks\n * If no schema is provided, the default schema will be used. The function creates a TypeScript\n * source file from the provided code and walks through its AST to apply syntax highlighting.\n *\n * @example\n * ```ts\n * const code = 'const x: number = 42;';\n * const schema = {\n * keywordColor: '\\x1b[34m', // Blue\n * numberColor: '\\x1b[31m', // Red\n * };\n * const highlightedCode = highlightCode(code, schema);\n * console.log(highlightedCode);\n * ```\n *\n * @see CodeHighlighter\n * @see HighlightSchemeInterface\n *\n * @since 1.0.0\n */\n\nexport function highlightCode(code: string, schema: Partial<HighlightSchemeInterface> = {}) {\n const sourceFile = ts.createSourceFile('temp.ts', code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const codeHighlighter = new CodeHighlighter(sourceFile, code, Object.assign(defaultScheme, schema));\n\n function walk(node: ts.Node): void {\n codeHighlighter.parseNode(node);\n\n for (let i = 0; i < node.getChildCount(); i++) {\n walk(node.getChildAt(i));\n }\n } ts.forEachChild(sourceFile, walk);\n\n return codeHighlighter.highlight();\n}\n"],
|
|
6
|
+
"mappings": "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",
|
|
7
7
|
"names": ["ts", "SyntaxKind", "Colors", "defaultScheme", "CodeHighlighter", "sourceFile", "code", "schema", "node", "previousSegmentEnd", "parent", "result", "a", "b", "segment", "lastSegment", "source", "combinedSource", "start", "end", "color", "reset", "key", "comment", "templateExpression", "span", "spanStart", "spanEnd", "highlightCode", "codeHighlighter", "walk"]
|
|
8
8
|
}
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/base64.component.ts", "../../src/providers/mapping.provider.ts", "../../src/services/source.service.ts"],
|
|
4
|
-
"sourceRoot": "https://github.com/remotex-lab/xmap/tree/v3.0.
|
|
5
|
-
"sourcesContent": ["// Bitmask to extract the lower 5 bits (continuation bit removed) - 0b11111\nconst CONTINUATION_BIT_REMOVE = 0x1F;\n// Bitmask to set the continuation bit - 0b100000\nconst CONTINUATION_BIT_POSITION = 0x20;\n// Mapping of Base64 characters to their indices\nconst base64Map: {\n [key: string]: number;\n} = {};\n// Array of Base64 characters\nconst base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');\n// Populate the base64Map with characters and their corresponding indices\nbase64Chars.forEach((char, index) => {\n base64Map[char] = index;\n});\n/**\n * Encodes a given number using Variable-Length Quantity (VLQ) encoding. Negative numbers are encoded by\n * converting to a non-negative representation and the continuation bit is used to indicate if more bytes follow.\n *\n * @param value - The number to be encoded\n * @returns The VLQ encoded string represented as Base64 characters\n *\n * @throws Error - If the value cannot be properly encoded\n *\n * @remarks The encoding process shifts the value left by 1 bit to accommodate a sign bit in the least significant position.\n * Negative values have their sign bit set to 1, while positive values have it set to 0.\n *\n * @example\n * ```ts\n * // Encoding a positive number\n * const encoded = encodeVLQ(25); // Returns \"Y\"\n *\n * // Encoding a negative number\n * const encodedNegative = encodeVLQ(-25); // Returns \"Z\"\n * ```\n *\n * @see decodeVLQ - For the corresponding decode function\n *\n * @since 1.0.0\n */\nexport function encodeVLQ(value: number): string {\n const isNegative = value < 0;\n /**\n * Bit Structure Representation:\n *\n * +--------------------------+\n * | C | Value | Sign |\n * +---+---+---+---+---+------+\n * | 1 | 1 | 0 | 0 | 1 | 0 |\n * +---+---+---+---+---+------+\n */\n let encoded = '';\n let vlq = isNegative ? ((-value) << 1) + 1 : (value << 1); // Shift left by 1 bit to encode the sign bit\n do {\n const digit = vlq & CONTINUATION_BIT_REMOVE; // Extract lower 5 bits\n vlq >>>= 5; // Right shift by 5 bits to process next chunk\n encoded += base64Chars[digit | (vlq > 0 ? CONTINUATION_BIT_POSITION : 0)]; // Combine digit and continuation bit\n } while (vlq > 0);\n return encoded;\n}\n/**\n * Encodes an array of numbers using VLQ encoding by individually encoding each number and concatenating the results.\n *\n * @param values - The array of numbers to be encoded\n * @returns The concatenated VLQ encoded string\n *\n * @example\n * ```ts\n * // Encoding multiple values\n * const encoded = encodeArrayVLQ([1, 0, -5]); // Returns \"CAAK\"\n * ```\n *\n * @see encodeVLQ - The underlying function used to encode each number\n *\n * @since 1.0.0\n */\nexport function encodeArrayVLQ(values: number[]): string {\n return values.map(encodeVLQ).join('');\n}\n/**\n * Decodes a VLQ encoded string back into an array of numbers by processing Base64 characters and continuation bits.\n *\n * @param data - The VLQ encoded string\n * @returns The array of decoded numbers\n *\n * @throws Error - If the string contains invalid Base64 characters\n *\n * @remarks The decoding process examines each Base64 character,\n * checking for continuation bits and progressively building up numeric values.\n * The sign bit is extracted from the least significant position\n * to determine if the original number was negative.\n *\n * @example\n * ```ts\n * // Decoding a simple VLQ string\n * const decoded = decodeVLQ(\"Y\"); // Returns [25]\n *\n * // Decoding multiple values\n * const multiDecoded = decodeVLQ(\"CAAK\"); // Returns [1, 0, -5]\n * ```\n *\n * @see encodeVLQ - For the corresponding encode function\n *\n * @since 1.0.0\n */\nexport function decodeVLQ(data: string): number[] {\n const result = [];\n let shift = 0;\n let value = 0;\n for (let i = 0; i < data.length; i++) {\n const digit = base64Map[data[i]];\n if (digit === undefined) {\n throw new Error(`Invalid Base64 character: ${data[i]}`);\n }\n const continuation = digit & CONTINUATION_BIT_POSITION; // Check if continuation bit is set\n value += (digit & CONTINUATION_BIT_REMOVE) << shift; // Add lower 5 bits to value\n if (continuation) {\n shift += 5; // Shift left by 5 for next chunk\n }\n else {\n const isNegative = (value & 1) === 1; // Check if the number is negative\n const shifted = value >> 1; // Remove the sign bit\n result.push(isNegative ? -shifted : shifted); // Convert back to signed integer\n value = shift = 0; // Reset for next number\n }\n }\n return result;\n}\n", "/**\n * Import will remove at compile time\n */\nimport type { MapType, FrameType, SegmentInterface, SegmentOffsetInterface } from './interfaces/mapping-provider.interface';\n/**\n * Imports\n */\nimport { Bias } from './interfaces/mapping-provider.interface';\nimport { decodeVLQ, encodeArrayVLQ } from '@components/base64.component';\n/**\n * Provides functionality for encoding and decoding source map mappings.\n *\n * The MappingProvider class handles the conversion between various mapping representations:\n * - String format (VLQ-encoded mappings)\n * - Structured array format (MapType)\n * - Internal structured representation\n *\n * It also provides methods to query and retrieve source map segments based on\n * generated or original source positions.\n *\n * @example\n * ```ts\n * // Create from VLQ-encoded mapping string\n * const provider = new MappingProvider(mappingString);\n *\n * // Get a segment by generated position\n * const segment = provider.getSegment(10, 15);\n *\n * // Convert back to mapping string\n * const encoded = provider.encode();\n * ```\n *\n * @since 1.0.0\n */\nexport class MappingProvider {\n private mapping: MapType = [];\n /**\n * Creates a new MappingProvider instance.\n *\n * @param mapping - Source map mapping data in one of three formats:\n * - VLQ-encoded string\n * - Structured array (MapType)\n * - Another MappingProvider instance (copy constructor)\n * @param namesOffset - Optional offset to apply to name indices (default: 0)\n * @param sourceOffset - Optional offset to apply to source indices (default: 0)\n *\n * @remarks\n * The constructor automatically detects the mapping format and decodes it accordingly.\n * When providing offsets, these values will be added to the corresponding indices\n * in the decoded mapping data, which is useful when concatenating multiple source maps.\n *\n * @since 1.0.0\n */\n constructor(mapping: string, namesOffset?: number, sourceOffset?: number);\n constructor(mapping: MapType, namesOffset?: number, sourceOffset?: number);\n constructor(mapping: MappingProvider, namesOffset?: number, sourceOffset?: number);\n constructor(mapping: MappingProvider | MapType | string, namesOffset = 0, sourcesOffset = 0) {\n mapping = mapping instanceof MappingProvider ? mapping.mapping : mapping;\n if (Array.isArray(mapping)) {\n this.decodeMappingArray(mapping, namesOffset, sourcesOffset);\n }\n else {\n this.decodeMappingString(mapping, namesOffset, sourcesOffset);\n }\n }\n /**\n * Encodes the internal mapping representation to a VLQ-encoded mapping string.\n *\n * @returns VLQ-encoded mapping string compatible with the source map format specification\n *\n * @remarks\n * This method converts the internal structured mapping representation into a compact\n * string format using Variable Length Quantity (VLQ) encoding.\n * The resulting string follows the source map v3 format for the 'mappings' field.\n *\n * @see https://sourcemaps.info/spec.html\n *\n * @since 1.0.0\n */\n encode(): string {\n return this.encodeMappings(this.mapping);\n }\n /**\n * Decodes mapping data into the internal representation.\n *\n * @param mapping - Mapping data to decode in one of three formats:\n * - VLQ-encoded string\n * - Structured array (MapType)\n * - Another MappingProvider instance\n * @param namesOffset - Optional offset for name indices (default: 0)\n * @param sourcesOffset - Optional offset for source indices (default: 0)\n *\n * @remarks\n * This method replaces the current internal mapping data with the newly decoded mapping.\n * The format of the input mapping is automatically detected and processed accordingly.\n *\n * @see MapType\n * @see MappingProvider\n *\n * @since 1.0.0\n */\n decode(mapping: MappingProvider | MapType | string, namesOffset = 0, sourcesOffset = 0): void {\n mapping = mapping instanceof MappingProvider ? mapping.mapping : mapping;\n if (Array.isArray(mapping)) {\n this.decodeMappingArray(mapping, namesOffset, sourcesOffset);\n }\n else {\n this.decodeMappingString(mapping, namesOffset, sourcesOffset);\n }\n }\n /**\n * Retrieves a segment based on a position in the generated code.\n *\n * @param generatedLine - Line number in generated code (1-based)\n * @param generatedColumn - Column number in generated code (0-based)\n * @param bias - Controls matching behavior when exact position not found:\n * - BOUND: No preference (default)\n * - LOWER_BOUND: Prefer segment with lower column\n * - UPPER_BOUND: Prefer segment with higher column\n * @returns Matching segment or null if not found\n *\n * @remarks\n * Uses binary search to efficiently locate matching segments.\n * When no exact match is found, the bias parameter determines which nearby segment to return.\n *\n * @since 1.0.0\n */\n getSegment(generatedLine: number, generatedColumn: number, bias: Bias = Bias.BOUND): SegmentInterface | null {\n const segments = this.mapping[generatedLine - 1];\n if (!segments || segments.length === 0)\n return null;\n let low = 0;\n let high = segments.length - 1;\n let closestSegment: SegmentInterface | null = null;\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const segment = segments[mid];\n if (segment.generatedColumn < generatedColumn) {\n low = mid + 1;\n closestSegment = bias === Bias.LOWER_BOUND ? segment : closestSegment;\n }\n else if (segment.generatedColumn > generatedColumn) {\n high = mid - 1;\n closestSegment = bias === Bias.UPPER_BOUND ? segment : closestSegment;\n }\n else {\n return segment;\n }\n }\n return closestSegment;\n }\n /**\n * Retrieves a segment based on a position in the original source code.\n *\n * @param line - Line number in original source (1-based)\n * @param column - Column number in original source (0-based)\n * @param sourceIndex - Index of source file in the sources array\n * @param bias - Controls matching behavior when exact position not found:\n * - BOUND: No preference (default)\n * - LOWER_BOUND: Prefer segment with lower column\n * - UPPER_BOUND: Prefer segment with higher column\n * @returns Matching segment or null if not found\n *\n * @remarks\n * Searches across all mapping segments to find those matching the specified original source position.\n * When multiple matches are possible, the bias\n * parameter determines which segment to return.\n *\n * This operation is more expensive than getSegment as it must potentially\n * scan the entire mapping structure.\n *\n * @since 1.0.0\n */\n getOriginalSegment(line: number, column: number, sourceIndex: number, bias: Bias = Bias.BOUND): SegmentInterface | null {\n let closestSegment: SegmentInterface | null = null;\n for (const segments of this.mapping) {\n if (!segments)\n continue;\n let low = 0;\n let high = segments.length - 1;\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const midSegment = segments[mid];\n if (midSegment.sourceIndex < sourceIndex || midSegment.line < line) {\n low = mid + 1;\n }\n else if (midSegment.sourceIndex > sourceIndex || midSegment.line > line) {\n high = mid - 1;\n }\n else if (midSegment.column < column) {\n low = mid + 1;\n closestSegment = bias === Bias.LOWER_BOUND ? midSegment : closestSegment;\n }\n else if (midSegment.column > column) {\n high = mid - 1;\n closestSegment = bias === Bias.UPPER_BOUND ? midSegment : closestSegment;\n }\n else {\n return midSegment;\n }\n }\n }\n return closestSegment;\n }\n /**\n * Initializes a new segment offset object with default values.\n *\n * @param namesOffset - Initial name index offset value (default: 0)\n * @param sourceIndex - Initial source index offset value (default: 0)\n * @returns A new segment offset object with initialized position tracking values\n *\n * @remarks\n * This method creates an object that tracks position data during mapping operations.\n * All position values (line, column, generatedLine, generatedColumn) are initialized to 0,\n * while the nameIndex and sourceIndex can be initialized with custom offsets.\n *\n * @since 1.0.0\n */\n private initPositionOffsets(namesOffset: number = 0, sourceIndex: number = 0): SegmentOffsetInterface {\n return {\n line: 0,\n column: 0,\n nameIndex: namesOffset,\n sourceIndex: sourceIndex,\n generatedLine: 0,\n generatedColumn: 0\n };\n }\n /**\n * Validates the format of an encoded mapping string.\n *\n * @param encodedSourceMap - The encoded source map string to validate\n * @returns `true` if the string contains only valid VLQ mapping characters, otherwise `false`\n *\n * @remarks\n * Checks if the string contains only characters valid in source map mappings:\n * - Base64 characters (a-z, A-Z, 0-9, +, /)\n * - Separators (commas for segments, semicolons for lines)\n *\n * This is a basic format validation and doesn't verify the semantic correctness\n * of the VLQ encoding itself.\n *\n * @since 1.0.0\n */\n private validateMappingString(encodedSourceMap: string): boolean {\n // /^(;+)?([a-z0-9+/]{1,10}(,|;+)?)+$/\n return /^[a-zA-Z0-9+/,;]+$/.test(encodedSourceMap);\n }\n /**\n * Validates that a segment's properties conform to expected types.\n *\n * @param segment - The segment object to validate\n *\n * @remarks\n * Performs the following validations on the segment properties:\n * - line: Must be a finite number\n * - column: Must be a finite number\n * - nameIndex: Must be either null or a finite number\n * - sourceIndex: Must be a finite number\n * - generatedLine: Must be a finite number\n * - generatedColumn: Must be a finite number\n *\n * This validation ensures that segments can be safely used in mapping operations\n * and prevents potential issues with non-numeric or infinite values.\n *\n * @throws Error - When any property of the segment is invalid, with a message\n * indicating which property failed validation and its value\n *\n * @since 1.0.0\n */\n private validateSegment(segment: SegmentInterface): void {\n if (!Number.isFinite(segment.line)) {\n throw new Error(`Invalid segment: line must be a finite number, received ${segment.line}`);\n }\n if (!Number.isFinite(segment.column)) {\n throw new Error(`Invalid segment: column must be a finite number, received ${segment.column}`);\n }\n if (segment.nameIndex !== null && !Number.isFinite(segment.nameIndex)) {\n throw new Error(`Invalid segment: nameIndex must be a number or null, received ${segment.nameIndex}`);\n }\n if (!Number.isFinite(segment.sourceIndex)) {\n throw new Error(`Invalid segment: sourceIndex must be a finite number, received ${segment.sourceIndex}`);\n }\n if (!Number.isFinite(segment.generatedLine)) {\n throw new Error(`Invalid segment: generatedLine must be a finite number, received ${segment.generatedLine}`);\n }\n if (!Number.isFinite(segment.generatedColumn)) {\n throw new Error(`Invalid segment: generatedColumn must be a finite number, received ${segment.generatedColumn}`);\n }\n }\n /**\n * Encodes a segment into a VLQ-encoded string based on relative offsets.\n *\n * @param segmentOffset - The current segment offset tracking state\n * @param segmentObject - The segment to encode\n * @returns A VLQ-encoded string representation of the segment\n *\n * @remarks\n * The encoding process:\n * 1. Adjusts line and column values (subtracts 1 to convert from 1-based to 0-based)\n * 2. Calculates relative differences between current values and previous offsets\n * 3. Creates an array with the following components:\n * - generatedColumn difference\n * - sourceIndex difference (0 if unchanged)\n * - line difference\n * - column difference\n * - nameIndex difference (only if nameIndex is present)\n * 4. Updates the segment offset state for the next encoding\n * 5. Returns the array as a VLQ-encoded string\n *\n * This method implements the source map V3 specification's delta encoding scheme\n * where values are stored as differences from previous positions.\n *\n * @since 1.0.0\n */\n private encodeSegment(segmentOffset: SegmentOffsetInterface, segmentObject: SegmentInterface): string {\n const { line, column, generatedColumn, nameIndex, sourceIndex } = segmentObject;\n const adjustedLine = line - 1;\n const adjustedColumn = column - 1;\n const adjustedGeneratedColumn = generatedColumn - 1;\n const segment: Array<number> = [\n adjustedGeneratedColumn - segmentOffset.generatedColumn, // generatedColumn difference\n sourceIndex !== segmentOffset.sourceIndex ? sourceIndex - segmentOffset.sourceIndex : 0, // sourceIndex difference\n adjustedLine - segmentOffset.line, // line difference\n adjustedColumn - segmentOffset.column // column difference\n ];\n if (nameIndex !== null && nameIndex !== undefined) {\n segment[4] = nameIndex - segmentOffset.nameIndex; // nameIndex difference\n segmentOffset.nameIndex = nameIndex;\n }\n segmentOffset.line = adjustedLine;\n segmentOffset.column = adjustedColumn;\n segmentOffset.generatedColumn = adjustedGeneratedColumn;\n segmentOffset.sourceIndex = sourceIndex;\n return encodeArrayVLQ(segment);\n }\n /**\n * Encodes a mapping array into a VLQ-encoded mapping string following the source map V3 spec.\n *\n * @param map - The mapping array to encode, organized by generated lines and segments\n * @returns A complete VLQ-encoded mapping string with line and segment separators\n *\n * @remarks\n * The encoding process:\n * 1. Initializes position offsets to track state across the entire mapping\n * 2. Processes each frame (line) in the mapping array:\n * - Resets generated column offset to 0 at the start of each line\n * - Encodes each segment within the line using relative VLQ encoding\n * - Joins segments with commas (,)\n * 3. Joins lines with semicolons (;)\n *\n * Empty frames are preserved as empty strings in the output to maintain\n * the correct line numbering in the resulting source map.\n *\n * @since 1.0.0\n */\n private encodeMappings(map: MapType): string {\n const positionOffset = this.initPositionOffsets();\n return map.map(frame => {\n if (!frame)\n return '';\n positionOffset.generatedColumn = 0;\n const segments = frame.map(segment => this.encodeSegment(positionOffset, segment));\n return segments.join(',');\n }).join(';');\n }\n /**\n * Converts a VLQ-decoded segment array into a structured segment object.\n *\n * @param segmentOffset - The current positional state tracking offsets\n * @param decodedSegment - Array of VLQ-decoded values representing relative offsets\n * @returns A complete segment object with absolute positions\n *\n * @remarks\n * The decoding process:\n * 1. Extracts position values from the decoded array:\n * - [0]: generatedColumn delta\n * - [1]: sourceIndex delta\n * - [2]: sourceLine delta\n * - [3]: sourceColumn delta\n * - [4]: nameIndex delta (optional)\n * 2. Updates the segmentOffset state by adding each delta\n * 3. Constructs a segment object with absolute positions (adding 1 to convert\n * from 0-based to 1-based coordinates)\n * 4. Handles nameIndex appropriately (null if not present in the input)\n *\n * This method implements the inverse operation of the delta encoding scheme\n * defined in the source map V3 specification.\n *\n * @since 1.0.0\n */\n private decodedSegment(segmentOffset: SegmentOffsetInterface, decodedSegment: Array<number>): SegmentInterface {\n const [generatedColumn, sourceIndex, sourceLine, sourceColumn, nameIndex] = decodedSegment;\n segmentOffset.line += sourceLine;\n segmentOffset.column += sourceColumn;\n segmentOffset.nameIndex += nameIndex ?? 0;\n segmentOffset.sourceIndex += sourceIndex;\n segmentOffset.generatedColumn += generatedColumn;\n return {\n line: segmentOffset.line + 1,\n column: segmentOffset.column + 1,\n nameIndex: nameIndex !== undefined ? segmentOffset.nameIndex : null,\n sourceIndex: segmentOffset.sourceIndex,\n generatedLine: segmentOffset.generatedLine + 1,\n generatedColumn: segmentOffset.generatedColumn + 1\n };\n }\n /**\n * Decodes a VLQ-encoded mapping string into the internal mapping data structure.\n *\n * @param encodedMap - The VLQ-encoded mapping string from a source map\n * @param namesOffset - Base offset for name indices in the global names array\n * @param sourceOffset - Base offset for source indices in the global sources array\n *\n * @remarks\n * The decoding process:\n * 1. Validates the mapping string format before processing\n * 2. Splits the string into frames using semicolons (;) as line separators\n * 3. Initializes position offsets with the provided name and source offsets\n * 4. For each frame (line):\n * - Adds `null` to the mapping array if the frame is empty\n * - Resets the generated column offset to 0 for each new line\n * - Sets the generated line index using the offset + current index\n * - Splits segments using commas (,) and decodes each segment\n * - Transforms each decoded segment into a segment object\n * 5. Updates the internal mapping array with the decoded data\n *\n * Error handling includes validation checks and descriptive error messages\n * indicating which frame caused a decoding failure.\n *\n * @throws Error - When the mapping string format is invalid or decoding fails\n *\n * @since 1.0.0\n */\n private decodeMappingString(encodedMap: string, namesOffset: number, sourceOffset: number): void {\n if (!this.validateMappingString(encodedMap))\n throw new Error('Invalid Mappings string format: the provided string does not conform to expected VLQ format.');\n const frames = encodedMap.split(';');\n const linesOffset = this.mapping.length;\n const positionOffset = this.initPositionOffsets(namesOffset, sourceOffset);\n try {\n frames.forEach((frame, index) => {\n if (!frame) {\n this.mapping.push(null);\n return;\n }\n positionOffset.generatedColumn = 0;\n positionOffset.generatedLine = linesOffset + index;\n const segmentsArray: Array<SegmentInterface> = frame.split(',')\n .map(segment => this.decodedSegment(positionOffset, decodeVLQ(segment)));\n this.mapping.push(segmentsArray);\n });\n }\n catch (error) {\n throw new Error(`Error decoding mappings at frame index ${frames.length}: ${(<Error>error).message}`);\n }\n }\n /**\n * Decodes a structured mapping array into the internal mapping representation.\n *\n * @param encodedMap - The structured mapping array (array of frames, with each frame being an array of segments)\n * @param namesOffset - Offset to add to each segment's nameIndex (for merging multiple source maps)\n * @param sourceOffset - Offset to add to each segment's sourceIndex (for merging multiple source maps)\n *\n * @remarks\n * The decoding process:\n * 1. Validates that the input is a properly structured array\n * 2. Tracks the current line offset based on the existing mapping length\n * 3. For each frame (line) in the mapping:\n * - Preserves null frames as-is (representing empty lines)\n * - Validates that each frame is an array\n * - For each segment in a frame:\n * - Validates the segment structure\n * - Applies the name and source offsets\n * - Adjusts the generated line index by the line offset\n * - Adds the processed frame to the internal mapping array\n *\n * This method is primarily used when combining multiple source maps or\n * importing mapping data from pre-structured arrays rather than VLQ strings.\n * The offsets enable proper indexing when concatenating multiple mappings.\n *\n * @throws Error - When the input format is invalid or segments don't conform to requirements\n *\n * @since 1.0.0\n */\n private decodeMappingArray(encodedMap: MapType, namesOffset: number, sourceOffset: number): void {\n const linesOffset = this.mapping.length;\n if (!Array.isArray(encodedMap))\n throw new Error('Invalid encoded map: expected an array of frames.');\n try {\n encodedMap.forEach((frame, index) => {\n if (!frame) {\n this.mapping.push(frame);\n return;\n }\n if (!Array.isArray(frame))\n throw new Error(`Invalid Mappings array format at frame index ${index}: expected an array, received ${typeof frame}.`);\n const segments: FrameType = frame.map(segment => {\n this.validateSegment(segment);\n return {\n ...segment,\n nameIndex: (typeof segment.nameIndex === 'number') ? segment.nameIndex + namesOffset : null,\n sourceIndex: segment.sourceIndex + sourceOffset,\n generatedLine: segment.generatedLine + linesOffset\n };\n });\n this.mapping.push(segments);\n });\n }\n catch (error: unknown) {\n const errorMessage = (error instanceof Error) ? error.message : 'Unknown error';\n throw new Error(`Error decoding mappings: ${errorMessage}`);\n }\n }\n}\n", "/**\n * Import will remove at compile time\n */\nimport type { PositionInterface, SourceMapInterface, SourceOptionsInterface, PositionWithCodeInterface, PositionWithContentInterface } from '@services/interfaces/source-service.interface';\n/**\n * Imports\n */\nimport { MappingProvider } from '@providers/mapping.provider';\nimport { Bias } from '@providers/interfaces/mapping-provider.interface';\n/**\n * A service for validating and processing source maps that provides functionality for parsing,\n * position mapping, concatenation, and code snippet extraction.\n *\n * @param source - Source map data (SourceService, SourceMapInterface object, or JSON string)\n * @param file - Optional file name for the generated bundle\n * @returns A new SourceService instance\n *\n * @example\n * ```ts\n * const sourceMapJSON = '{\"version\": 3, \"file\": \"bundle.js\", \"sources\": [\"foo.ts\"], \"names\": [], \"mappings\": \"AAAA\"}';\n * const sourceService = new SourceService(sourceMapJSON);\n * console.log(sourceService.file); // 'bundle.js'\n * ```\n *\n * @since 1.0.0\n */\nexport class SourceService {\n /**\n * The name of the generated file this source map applies to.\n *\n * @since 1.0.0\n */\n readonly file: string | null;\n /**\n * Provider for accessing and manipulating the base64 VLQ-encoded mappings.\n *\n * @since 1.0.0\n */\n readonly mappings: MappingProvider;\n /**\n * The root URL for resolving relative paths in the source files.\n * @since 1.0.0\n */\n readonly sourceRoot: string | null;\n /**\n * List of symbol names referenced by the mappings.\n * @since 1.0.0\n */\n readonly names: Array<string>;\n /**\n * Array of source file paths.\n * @since 1.0.0\n */\n readonly sources: Array<string>;\n /**\n * Array of source file contents.\n * @since 1.0.0\n */\n readonly sourcesContent: Array<string>;\n /**\n * Creates a new SourceService instance.\n *\n * @param source - Source map data (SourceService, SourceMapInterface object, or JSON string)\n * @param file - Optional file name for the generated bundle\n *\n * @throws Error - When a source map has an invalid format or missing required properties\n *\n * @since 1.0.0\n */\n constructor(source: SourceService);\n constructor(source: SourceMapInterface | string, file?: string | null);\n constructor(source: SourceService | SourceMapInterface | string, file: string | null = null) {\n if (typeof source === 'string') {\n source = <SourceMapInterface>JSON.parse(source);\n }\n source = <SourceMapInterface>source;\n this.validateSourceMap(source);\n this.file = source.file ?? file;\n this.names = [...source.names ?? []];\n this.sources = [...source.sources ?? []];\n this.sourceRoot = source.sourceRoot ?? null;\n this.sourcesContent = source.sourcesContent ? [...source.sourcesContent] : [];\n ;\n this.mappings = new MappingProvider(source.mappings);\n }\n /**\n * Converts the source map data to a plain object.\n *\n * @returns A SourceMapInterface object representing the current state\n *\n * @example\n * ```ts\n * const mapObject = sourceService.getMapObject();\n * console.log(mapObject.file); // 'bundle.js'\n * ```\n *\n * @since 1.0.0\n */\n getMapObject(): SourceMapInterface {\n const sourceMap: SourceMapInterface = {\n version: 3,\n names: this.names,\n sources: this.sources,\n mappings: this.mappings.encode(),\n sourcesContent: this.sourcesContent\n };\n if (this.file)\n sourceMap.file = this.file;\n if (this.sourceRoot)\n sourceMap.sourceRoot = this.sourceRoot;\n return sourceMap;\n }\n /**\n * Concatenates additional source maps into the current instance.\n *\n * @param maps - Source maps to concatenate with the current map\n *\n * @example\n * ```ts\n * sourceService.concat(anotherSourceMap);\n * console.log(sourceService.sources); // Updated source paths\n * ```\n *\n * @throws Error - When no maps are provided\n *\n * @since 1.0.0\n */\n concat(...maps: Array<SourceMapInterface | SourceService>): void {\n if (maps.length < 1)\n throw new Error('At least one map must be provided for concatenation.');\n for (const map of (maps as Array<SourceMapInterface>)) {\n this.mappings.decode(map.mappings, this.names.length, this.sources.length);\n this.names.push(...map.names);\n this.sources.push(...map.sources);\n this.sourcesContent.push(...map.sourcesContent ?? []);\n }\n }\n /**\n * Creates a new SourceService instance with concatenated source maps.\n *\n * @param maps - Source maps to concatenate with a copy of the current map\n * @returns A new SourceService instance with the combined maps\n *\n * @example\n * ```ts\n * const newService = sourceService.concatNewMap(anotherSourceMap);\n * console.log(newService.sources); // Combined sources array\n * ```\n *\n * @throws Error - When no maps are provided\n *\n * @since 1.0.0\n */\n concatNewMap(...maps: Array<SourceMapInterface | SourceService>): SourceService {\n if (maps.length < 1)\n throw new Error('At least one map must be provided for concatenation.');\n const sourceService = new SourceService(this);\n for (const map of (maps as Array<SourceMapInterface>)) {\n sourceService.mappings.decode(map.mappings, sourceService.names.length, sourceService.sources.length);\n sourceService.names.push(...map.names);\n sourceService.sources.push(...map.sources);\n sourceService.sourcesContent.push(...map.sourcesContent ?? []);\n }\n return sourceService;\n }\n /**\n * Finds position in generated code based on original source position.\n *\n * @param line - Line number in the original source\n * @param column - Column number in the original source\n * @param sourceIndex - Index or file path of the original source\n * @param bias - Position matching strategy (default: Bias.BOUND)\n * @returns Position information or null if not found\n *\n * @example\n * ```ts\n * const position = sourceService.getPositionByOriginal(1, 10, 'foo.ts');\n * console.log(position?.generatedLine); // Line in generated code\n * ```\n *\n * @since 1.0.0\n */\n getPositionByOriginal(line: number, column: number, sourceIndex: number | string, bias: Bias = Bias.BOUND): PositionInterface | null {\n let index = <number>sourceIndex;\n if (typeof sourceIndex === 'string')\n index = this.sources.findIndex(str => str.includes(sourceIndex));\n if (index < 0)\n return null;\n const segment = this.mappings.getOriginalSegment(line, column, index, bias);\n if (!segment)\n return null;\n return {\n name: this.names[segment.nameIndex ?? -1] ?? null,\n line: segment.line,\n column: segment.column,\n source: this.sources[segment.sourceIndex],\n sourceRoot: this.sourceRoot,\n sourceIndex: segment.sourceIndex,\n generatedLine: segment.generatedLine,\n generatedColumn: segment.generatedColumn\n };\n }\n /**\n * Finds position in an original source based on generated code position.\n *\n * @param line - Line number in the generated code\n * @param column - Column number in the generated code\n * @param bias - Position matching strategy (default: Bias.BOUND)\n * @returns Position information or null if not found\n *\n * @example\n * ```ts\n * const position = sourceService.getPosition(2, 15);\n * console.log(position?.source); // Original source file\n * ```\n *\n * @since 1.0.0\n */\n getPosition(line: number, column: number, bias: Bias = Bias.BOUND): PositionInterface | null {\n const segment = this.mappings.getSegment(line, column, bias);\n if (!segment)\n return null;\n return {\n name: this.names[segment.nameIndex ?? -1] ?? null,\n line: segment.line,\n column: segment.column,\n source: this.sources[segment.sourceIndex],\n sourceRoot: this.sourceRoot,\n sourceIndex: segment.sourceIndex,\n generatedLine: segment.generatedLine,\n generatedColumn: segment.generatedColumn\n };\n }\n /**\n * Retrieves position with source content for a location in generated code.\n *\n * @param line - Line number in the generated code\n * @param column - Column number in the generated code\n * @param bias - Position matching strategy (default: Bias.BOUND)\n * @returns Position with content information or null if not found\n *\n * @example\n * ```ts\n * const posWithContent = sourceService.getPositionWithContent(3, 5);\n * console.log(posWithContent?.sourcesContent); // Original source content\n * ```\n *\n * @since 1.0.0\n */\n getPositionWithContent(line: number, column: number, bias: Bias = Bias.BOUND): PositionWithContentInterface | null {\n const position = this.getPosition(line, column, bias);\n if (!position)\n return null;\n return {\n ...position,\n sourcesContent: this.sourcesContent[position.sourceIndex]\n };\n }\n /**\n * Retrieves position with a code snippet from the original source.\n *\n * @param line - Line number in the generated code\n * @param column - Column number in the generated code\n * @param bias - Position matching strategy (default: Bias.BOUND)\n * @param options - Configuration for the amount of surrounding lines\n * @returns Position with code snippet or null if not found\n *\n * @example\n * ```ts\n * const posWithCode = sourceService.getPositionWithCode(4, 8, Bias.BOUND, {\n * linesBefore: 2,\n * linesAfter: 2\n * });\n * console.log(posWithCode?.code); // Code snippet with context\n * ```\n *\n * @since 1.0.0\n */\n getPositionWithCode(line: number, column: number, bias: Bias = Bias.BOUND, options?: SourceOptionsInterface): PositionWithCodeInterface | null {\n const position = this.getPosition(line, column, bias);\n if (!position || !this.sourcesContent[position.sourceIndex])\n return null;\n const settings = Object.assign({\n linesAfter: 4,\n linesBefore: 3\n }, options);\n const code = this.sourcesContent[position.sourceIndex].split('\\n');\n const endLine = Math.min((position.line ?? 1) + settings.linesAfter, code.length);\n const startLine = Math.max((position.line ?? 1) - settings.linesBefore, 0);\n const relevantCode = code.slice(startLine, Math.min(endLine + 1, code.length)).join('\\n');\n return {\n ...position,\n code: relevantCode,\n endLine: endLine,\n startLine: startLine\n };\n }\n /**\n * Serializes the source map to a JSON string.\n *\n * @returns JSON string representation of the source map\n *\n * @example\n * ```ts\n * const jsonString = sourceService.toString();\n * console.log(jsonString); // '{\"version\":3,\"file\":\"bundle.js\",...}'\n * ```\n *\n * @since 1.0.0\n */\n toString(): string {\n return JSON.stringify(this.getMapObject());\n }\n /**\n * Validates a source map object has all required properties.\n *\n * @param input - Source map object to validate\n *\n * @throws Error - When required properties are missing\n *\n * @since 1.0.0\n */\n private validateSourceMap(input: SourceMapInterface): void {\n const requiredKeys: (keyof SourceMapInterface)[] = ['sources', 'mappings', 'names'];\n if (!requiredKeys.every(key => key in input)) {\n throw new Error('Missing required keys in SourceMap.');\n }\n }\n}\n"],
|
|
6
|
-
"mappings": "
|
|
4
|
+
"sourceRoot": "https://github.com/remotex-lab/xmap/tree/v3.0.3/",
|
|
5
|
+
"sourcesContent": ["// Bitmask to extract the lower 5 bits (continuation bit removed) - 0b11111\nconst CONTINUATION_BIT_REMOVE = 0x1F;\n\n// Bitmask to set the continuation bit - 0b100000\nconst CONTINUATION_BIT_POSITION = 0x20;\n\n// Mapping of Base64 characters to their indices\nconst base64Map: { [key: string]: number } = {};\n\n// Array of Base64 characters\nconst base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');\n\n// Populate the base64Map with characters and their corresponding indices\nbase64Chars.forEach((char, index) => {\n base64Map[char] = index;\n});\n\n/**\n * Encodes a given number using Variable-Length Quantity (VLQ) encoding. Negative numbers are encoded by\n * converting to a non-negative representation and the continuation bit is used to indicate if more bytes follow.\n *\n * @param value - The number to be encoded\n * @returns The VLQ encoded string represented as Base64 characters\n *\n * @throws Error - If the value cannot be properly encoded\n *\n * @remarks The encoding process shifts the value left by 1 bit to accommodate a sign bit in the least significant position.\n * Negative values have their sign bit set to 1, while positive values have it set to 0.\n *\n * @example\n * ```ts\n * // Encoding a positive number\n * const encoded = encodeVLQ(25); // Returns \"Y\"\n *\n * // Encoding a negative number\n * const encodedNegative = encodeVLQ(-25); // Returns \"Z\"\n * ```\n *\n * @see decodeVLQ - For the corresponding decode function\n *\n * @since 1.0.0\n */\n\nexport function encodeVLQ(value: number): string {\n const isNegative = value < 0;\n\n /**\n * Bit Structure Representation:\n *\n * +--------------------------+\n * | C | Value | Sign |\n * +---+---+---+---+---+------+\n * | 1 | 1 | 0 | 0 | 1 | 0 |\n * +---+---+---+---+---+------+\n */\n\n let encoded = '';\n let vlq = isNegative ? ((-value) << 1) + 1 : (value << 1); // Shift left by 1 bit to encode the sign bit\n\n do {\n const digit = vlq & CONTINUATION_BIT_REMOVE; // Extract lower 5 bits\n vlq >>>= 5; // Right shift by 5 bits to process next chunk\n encoded += base64Chars[digit | (vlq > 0 ? CONTINUATION_BIT_POSITION : 0)]; // Combine digit and continuation bit\n } while (vlq > 0);\n\n return encoded;\n}\n\n/**\n * Encodes an array of numbers using VLQ encoding by individually encoding each number and concatenating the results.\n *\n * @param values - The array of numbers to be encoded\n * @returns The concatenated VLQ encoded string\n *\n * @example\n * ```ts\n * // Encoding multiple values\n * const encoded = encodeArrayVLQ([1, 0, -5]); // Returns \"CAAK\"\n * ```\n *\n * @see encodeVLQ - The underlying function used to encode each number\n *\n * @since 1.0.0\n */\n\n\nexport function encodeArrayVLQ(values: number[]): string {\n return values.map(encodeVLQ).join('');\n}\n\n/**\n * Decodes a VLQ encoded string back into an array of numbers by processing Base64 characters and continuation bits.\n *\n * @param data - The VLQ encoded string\n * @returns The array of decoded numbers\n *\n * @throws Error - If the string contains invalid Base64 characters\n *\n * @remarks The decoding process examines each Base64 character,\n * checking for continuation bits and progressively building up numeric values.\n * The sign bit is extracted from the least significant position\n * to determine if the original number was negative.\n *\n * @example\n * ```ts\n * // Decoding a simple VLQ string\n * const decoded = decodeVLQ(\"Y\"); // Returns [25]\n *\n * // Decoding multiple values\n * const multiDecoded = decodeVLQ(\"CAAK\"); // Returns [1, 0, -5]\n * ```\n *\n * @see encodeVLQ - For the corresponding encode function\n *\n * @since 1.0.0\n */\n\nexport function decodeVLQ(data: string): number[] {\n const result = [];\n let shift = 0;\n let value = 0;\n\n for (let i = 0; i < data.length; i++) {\n const digit = base64Map[data[i]];\n if (digit === undefined) {\n throw new Error(`Invalid Base64 character: ${data[i]}`);\n }\n\n const continuation = digit & CONTINUATION_BIT_POSITION; // Check if continuation bit is set\n value += (digit & CONTINUATION_BIT_REMOVE) << shift; // Add lower 5 bits to value\n if (continuation) {\n shift += 5; // Shift left by 5 for next chunk\n } else {\n const isNegative = (value & 1) === 1; // Check if the number is negative\n const shifted = value >> 1; // Remove the sign bit\n\n result.push(isNegative ? -shifted : shifted); // Convert back to signed integer\n value = shift = 0; // Reset for next number\n }\n }\n\n return result;\n}\n", "/**\n * Import will remove at compile time\n */\n\nimport type { MapType, FrameType, SegmentInterface, SegmentOffsetInterface } from './interfaces/mapping-provider.interface';\n\n/**\n * Imports\n */\n\nimport { Bias } from './interfaces/mapping-provider.interface';\nimport { decodeVLQ, encodeArrayVLQ } from '@components/base64.component';\n\n/**\n * Provides functionality for encoding and decoding source map mappings.\n *\n * The MappingProvider class handles the conversion between various mapping representations:\n * - String format (VLQ-encoded mappings)\n * - Structured array format (MapType)\n * - Internal structured representation\n *\n * It also provides methods to query and retrieve source map segments based on\n * generated or original source positions.\n *\n * @example\n * ```ts\n * // Create from VLQ-encoded mapping string\n * const provider = new MappingProvider(mappingString);\n *\n * // Get a segment by generated position\n * const segment = provider.getSegment(10, 15);\n *\n * // Convert back to mapping string\n * const encoded = provider.encode();\n * ```\n *\n * @since 1.0.0\n */\n\nexport class MappingProvider {\n\n private mapping: MapType = [];\n\n /**\n * Creates a new MappingProvider instance.\n *\n * @param mapping - Source map mapping data in one of three formats:\n * - VLQ-encoded string\n * - Structured array (MapType)\n * - Another MappingProvider instance (copy constructor)\n * @param namesOffset - Optional offset to apply to name indices (default: 0)\n * @param sourceOffset - Optional offset to apply to source indices (default: 0)\n *\n * @remarks\n * The constructor automatically detects the mapping format and decodes it accordingly.\n * When providing offsets, these values will be added to the corresponding indices\n * in the decoded mapping data, which is useful when concatenating multiple source maps.\n *\n * @since 1.0.0\n */\n\n constructor(mapping: string, namesOffset?: number, sourceOffset?: number);\n constructor(mapping: MapType, namesOffset?: number, sourceOffset?: number);\n constructor(mapping: MappingProvider, namesOffset?: number, sourceOffset?: number);\n constructor(mapping: MappingProvider| MapType | string, namesOffset = 0, sourcesOffset = 0) {\n mapping = mapping instanceof MappingProvider ? mapping.mapping : mapping;\n if (Array.isArray(mapping)) {\n this.decodeMappingArray(mapping, namesOffset, sourcesOffset);\n } else {\n this.decodeMappingString(mapping, namesOffset, sourcesOffset);\n }\n }\n\n /**\n * Encodes the internal mapping representation to a VLQ-encoded mapping string.\n *\n * @returns VLQ-encoded mapping string compatible with the source map format specification\n *\n * @remarks\n * This method converts the internal structured mapping representation into a compact\n * string format using Variable Length Quantity (VLQ) encoding.\n * The resulting string follows the source map v3 format for the 'mappings' field.\n *\n * @see https://sourcemaps.info/spec.html\n *\n * @since 1.0.0\n */\n\n encode(): string {\n return this.encodeMappings(this.mapping);\n }\n\n /**\n * Decodes mapping data into the internal representation.\n *\n * @param mapping - Mapping data to decode in one of three formats:\n * - VLQ-encoded string\n * - Structured array (MapType)\n * - Another MappingProvider instance\n * @param namesOffset - Optional offset for name indices (default: 0)\n * @param sourcesOffset - Optional offset for source indices (default: 0)\n *\n * @remarks\n * This method replaces the current internal mapping data with the newly decoded mapping.\n * The format of the input mapping is automatically detected and processed accordingly.\n *\n * @see MapType\n * @see MappingProvider\n *\n * @since 1.0.0\n */\n\n decode(mapping: MappingProvider| MapType | string, namesOffset = 0, sourcesOffset = 0): void {\n mapping = mapping instanceof MappingProvider ? mapping.mapping : mapping;\n if (Array.isArray(mapping)) {\n this.decodeMappingArray(mapping, namesOffset, sourcesOffset);\n } else {\n this.decodeMappingString(mapping, namesOffset, sourcesOffset);\n }\n }\n\n /**\n * Retrieves a segment based on a position in the generated code.\n *\n * @param generatedLine - Line number in generated code (1-based)\n * @param generatedColumn - Column number in generated code (0-based)\n * @param bias - Controls matching behavior when exact position not found:\n * - BOUND: No preference (default)\n * - LOWER_BOUND: Prefer segment with lower column\n * - UPPER_BOUND: Prefer segment with higher column\n * @returns Matching segment or null if not found\n *\n * @remarks\n * Uses binary search to efficiently locate matching segments.\n * When no exact match is found, the bias parameter determines which nearby segment to return.\n *\n * @since 1.0.0\n */\n\n getSegment(generatedLine: number, generatedColumn: number, bias: Bias = Bias.BOUND): SegmentInterface | null {\n const segments = this.mapping[generatedLine - 1];\n if (!segments || segments.length === 0)\n return null;\n\n let low = 0;\n let high = segments.length - 1;\n let closestSegment: SegmentInterface | null = null;\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const segment = segments[mid];\n\n if (segment.generatedColumn < generatedColumn) {\n low = mid + 1;\n closestSegment = bias === Bias.LOWER_BOUND ? segment : closestSegment;\n } else if (segment.generatedColumn > generatedColumn) {\n high = mid - 1;\n closestSegment = bias === Bias.UPPER_BOUND ? segment : closestSegment;\n } else {\n return segment;\n }\n }\n\n return closestSegment;\n }\n\n /**\n * Retrieves a segment based on a position in the original source code.\n *\n * @param line - Line number in original source (1-based)\n * @param column - Column number in original source (0-based)\n * @param sourceIndex - Index of source file in the sources array\n * @param bias - Controls matching behavior when exact position not found:\n * - BOUND: No preference (default)\n * - LOWER_BOUND: Prefer segment with lower column\n * - UPPER_BOUND: Prefer segment with higher column\n * @returns Matching segment or null if not found\n *\n * @remarks\n * Searches across all mapping segments to find those matching the specified original source position.\n * When multiple matches are possible, the bias\n * parameter determines which segment to return.\n *\n * This operation is more expensive than getSegment as it must potentially\n * scan the entire mapping structure.\n *\n * @since 1.0.0\n */\n\n getOriginalSegment(line: number, column: number, sourceIndex: number, bias: Bias = Bias.BOUND): SegmentInterface | null {\n let closestSegment: SegmentInterface | null = null;\n for (const segments of this.mapping) {\n if (!segments)\n continue;\n\n let low = 0;\n let high = segments.length - 1;\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const midSegment = segments[mid];\n\n if (midSegment.sourceIndex < sourceIndex || midSegment.line < line) {\n low = mid + 1;\n } else if (midSegment.sourceIndex > sourceIndex || midSegment.line > line) {\n high = mid - 1;\n } else if (midSegment.column < column) {\n low = mid + 1;\n closestSegment = bias === Bias.LOWER_BOUND ? midSegment : closestSegment;\n } else if (midSegment.column > column) {\n high = mid - 1;\n closestSegment = bias === Bias.UPPER_BOUND ? midSegment : closestSegment;\n } else {\n return midSegment;\n }\n }\n }\n\n return closestSegment;\n }\n\n /**\n * Initializes a new segment offset object with default values.\n *\n * @param namesOffset - Initial name index offset value (default: 0)\n * @param sourceIndex - Initial source index offset value (default: 0)\n * @returns A new segment offset object with initialized position tracking values\n *\n * @remarks\n * This method creates an object that tracks position data during mapping operations.\n * All position values (line, column, generatedLine, generatedColumn) are initialized to 0,\n * while the nameIndex and sourceIndex can be initialized with custom offsets.\n *\n * @since 1.0.0\n */\n\n private initPositionOffsets(namesOffset: number = 0, sourceIndex: number = 0): SegmentOffsetInterface {\n return {\n line: 0,\n column: 0,\n nameIndex: namesOffset,\n sourceIndex: sourceIndex,\n generatedLine: 0,\n generatedColumn: 0\n };\n }\n\n /**\n * Validates the format of an encoded mapping string.\n *\n * @param encodedSourceMap - The encoded source map string to validate\n * @returns `true` if the string contains only valid VLQ mapping characters, otherwise `false`\n *\n * @remarks\n * Checks if the string contains only characters valid in source map mappings:\n * - Base64 characters (a-z, A-Z, 0-9, +, /)\n * - Separators (commas for segments, semicolons for lines)\n *\n * This is a basic format validation and doesn't verify the semantic correctness\n * of the VLQ encoding itself.\n *\n * @since 1.0.0\n */\n\n private validateMappingString(encodedSourceMap: string): boolean {\n // /^(;+)?([a-z0-9+/]{1,10}(,|;+)?)+$/\n return /^[a-zA-Z0-9+/,;]+$/.test(encodedSourceMap);\n }\n\n /**\n * Validates that a segment's properties conform to expected types.\n *\n * @param segment - The segment object to validate\n *\n * @remarks\n * Performs the following validations on the segment properties:\n * - line: Must be a finite number\n * - column: Must be a finite number\n * - nameIndex: Must be either null or a finite number\n * - sourceIndex: Must be a finite number\n * - generatedLine: Must be a finite number\n * - generatedColumn: Must be a finite number\n *\n * This validation ensures that segments can be safely used in mapping operations\n * and prevents potential issues with non-numeric or infinite values.\n *\n * @throws Error - When any property of the segment is invalid, with a message\n * indicating which property failed validation and its value\n *\n * @since 1.0.0\n */\n\n private validateSegment(segment: SegmentInterface): void {\n if (!Number.isFinite(segment.line)) {\n throw new Error(`Invalid segment: line must be a finite number, received ${segment.line}`);\n }\n if (!Number.isFinite(segment.column)) {\n throw new Error(`Invalid segment: column must be a finite number, received ${segment.column}`);\n }\n if (segment.nameIndex !== null && !Number.isFinite(segment.nameIndex)) {\n throw new Error(`Invalid segment: nameIndex must be a number or null, received ${segment.nameIndex}`);\n }\n if (!Number.isFinite(segment.sourceIndex)) {\n throw new Error(`Invalid segment: sourceIndex must be a finite number, received ${segment.sourceIndex}`);\n }\n if (!Number.isFinite(segment.generatedLine)) {\n throw new Error(`Invalid segment: generatedLine must be a finite number, received ${segment.generatedLine}`);\n }\n if (!Number.isFinite(segment.generatedColumn)) {\n throw new Error(`Invalid segment: generatedColumn must be a finite number, received ${segment.generatedColumn}`);\n }\n }\n\n /**\n * Encodes a segment into a VLQ-encoded string based on relative offsets.\n *\n * @param segmentOffset - The current segment offset tracking state\n * @param segmentObject - The segment to encode\n * @returns A VLQ-encoded string representation of the segment\n *\n * @remarks\n * The encoding process:\n * 1. Adjusts line and column values (subtracts 1 to convert from 1-based to 0-based)\n * 2. Calculates relative differences between current values and previous offsets\n * 3. Creates an array with the following components:\n * - generatedColumn difference\n * - sourceIndex difference (0 if unchanged)\n * - line difference\n * - column difference\n * - nameIndex difference (only if nameIndex is present)\n * 4. Updates the segment offset state for the next encoding\n * 5. Returns the array as a VLQ-encoded string\n *\n * This method implements the source map V3 specification's delta encoding scheme\n * where values are stored as differences from previous positions.\n *\n * @since 1.0.0\n */\n\n private encodeSegment(segmentOffset: SegmentOffsetInterface, segmentObject: SegmentInterface): string {\n const { line, column, generatedColumn, nameIndex, sourceIndex } = segmentObject;\n const adjustedLine = line - 1;\n const adjustedColumn = column - 1;\n const adjustedGeneratedColumn = generatedColumn - 1;\n\n const segment: Array<number> = [\n adjustedGeneratedColumn - segmentOffset.generatedColumn, // generatedColumn difference\n sourceIndex !== segmentOffset.sourceIndex ? sourceIndex - segmentOffset.sourceIndex : 0, // sourceIndex difference\n adjustedLine - segmentOffset.line, // line difference\n adjustedColumn - segmentOffset.column // column difference\n ];\n\n if (nameIndex !== null && nameIndex !== undefined) {\n segment[4] = nameIndex - segmentOffset.nameIndex; // nameIndex difference\n segmentOffset.nameIndex = nameIndex;\n }\n\n segmentOffset.line = adjustedLine;\n segmentOffset.column = adjustedColumn;\n segmentOffset.generatedColumn = adjustedGeneratedColumn;\n segmentOffset.sourceIndex = sourceIndex;\n\n return encodeArrayVLQ(segment);\n }\n\n /**\n * Encodes a mapping array into a VLQ-encoded mapping string following the source map V3 spec.\n *\n * @param map - The mapping array to encode, organized by generated lines and segments\n * @returns A complete VLQ-encoded mapping string with line and segment separators\n *\n * @remarks\n * The encoding process:\n * 1. Initializes position offsets to track state across the entire mapping\n * 2. Processes each frame (line) in the mapping array:\n * - Resets generated column offset to 0 at the start of each line\n * - Encodes each segment within the line using relative VLQ encoding\n * - Joins segments with commas (,)\n * 3. Joins lines with semicolons (;)\n *\n * Empty frames are preserved as empty strings in the output to maintain\n * the correct line numbering in the resulting source map.\n *\n * @since 1.0.0\n */\n\n private encodeMappings(map: MapType): string {\n const positionOffset = this.initPositionOffsets();\n\n return map.map(frame => {\n if (!frame)\n return '';\n\n positionOffset.generatedColumn = 0;\n const segments = frame.map(segment => this.encodeSegment(positionOffset, segment));\n\n return segments.join(',');\n }).join(';');\n }\n\n /**\n * Converts a VLQ-decoded segment array into a structured segment object.\n *\n * @param segmentOffset - The current positional state tracking offsets\n * @param decodedSegment - Array of VLQ-decoded values representing relative offsets\n * @returns A complete segment object with absolute positions\n *\n * @remarks\n * The decoding process:\n * 1. Extracts position values from the decoded array:\n * - [0]: generatedColumn delta\n * - [1]: sourceIndex delta\n * - [2]: sourceLine delta\n * - [3]: sourceColumn delta\n * - [4]: nameIndex delta (optional)\n * 2. Updates the segmentOffset state by adding each delta\n * 3. Constructs a segment object with absolute positions (adding 1 to convert\n * from 0-based to 1-based coordinates)\n * 4. Handles nameIndex appropriately (null if not present in the input)\n *\n * This method implements the inverse operation of the delta encoding scheme\n * defined in the source map V3 specification.\n *\n * @since 1.0.0\n */\n\n private decodedSegment(segmentOffset: SegmentOffsetInterface, decodedSegment: Array<number>): SegmentInterface {\n const [ generatedColumn, sourceIndex, sourceLine, sourceColumn, nameIndex ] = decodedSegment;\n segmentOffset.line += sourceLine;\n segmentOffset.column += sourceColumn;\n segmentOffset.nameIndex += nameIndex ?? 0;\n segmentOffset.sourceIndex += sourceIndex;\n segmentOffset.generatedColumn += generatedColumn;\n\n return {\n line: segmentOffset.line + 1,\n column: segmentOffset.column + 1,\n nameIndex: nameIndex !== undefined ? segmentOffset.nameIndex : null,\n sourceIndex: segmentOffset.sourceIndex,\n generatedLine: segmentOffset.generatedLine + 1,\n generatedColumn: segmentOffset.generatedColumn + 1\n };\n }\n\n /**\n * Decodes a VLQ-encoded mapping string into the internal mapping data structure.\n *\n * @param encodedMap - The VLQ-encoded mapping string from a source map\n * @param namesOffset - Base offset for name indices in the global names array\n * @param sourceOffset - Base offset for source indices in the global sources array\n *\n * @remarks\n * The decoding process:\n * 1. Validates the mapping string format before processing\n * 2. Splits the string into frames using semicolons (;) as line separators\n * 3. Initializes position offsets with the provided name and source offsets\n * 4. For each frame (line):\n * - Adds `null` to the mapping array if the frame is empty\n * - Resets the generated column offset to 0 for each new line\n * - Sets the generated line index using the offset + current index\n * - Splits segments using commas (,) and decodes each segment\n * - Transforms each decoded segment into a segment object\n * 5. Updates the internal mapping array with the decoded data\n *\n * Error handling includes validation checks and descriptive error messages\n * indicating which frame caused a decoding failure.\n *\n * @throws Error - When the mapping string format is invalid or decoding fails\n *\n * @since 1.0.0\n */\n\n private decodeMappingString(encodedMap: string, namesOffset: number, sourceOffset: number): void {\n if (!this.validateMappingString(encodedMap))\n throw new Error('Invalid Mappings string format: the provided string does not conform to expected VLQ format.');\n\n const frames = encodedMap.split(';');\n const linesOffset = this.mapping.length;\n const positionOffset = this.initPositionOffsets(namesOffset, sourceOffset);\n try {\n frames.forEach((frame, index) => {\n if (!frame) {\n this.mapping.push(null);\n\n return;\n }\n\n positionOffset.generatedColumn = 0;\n positionOffset.generatedLine = linesOffset + index;\n const segmentsArray: Array<SegmentInterface> = frame.split(',')\n .map(segment => this.decodedSegment(positionOffset, decodeVLQ(segment)));\n\n this.mapping.push(segmentsArray);\n });\n } catch (error) {\n throw new Error(`Error decoding mappings at frame index ${frames.length}: ${(<Error>error).message}`);\n }\n }\n\n /**\n * Decodes a structured mapping array into the internal mapping representation.\n *\n * @param encodedMap - The structured mapping array (array of frames, with each frame being an array of segments)\n * @param namesOffset - Offset to add to each segment's nameIndex (for merging multiple source maps)\n * @param sourceOffset - Offset to add to each segment's sourceIndex (for merging multiple source maps)\n *\n * @remarks\n * The decoding process:\n * 1. Validates that the input is a properly structured array\n * 2. Tracks the current line offset based on the existing mapping length\n * 3. For each frame (line) in the mapping:\n * - Preserves null frames as-is (representing empty lines)\n * - Validates that each frame is an array\n * - For each segment in a frame:\n * - Validates the segment structure\n * - Applies the name and source offsets\n * - Adjusts the generated line index by the line offset\n * - Adds the processed frame to the internal mapping array\n *\n * This method is primarily used when combining multiple source maps or\n * importing mapping data from pre-structured arrays rather than VLQ strings.\n * The offsets enable proper indexing when concatenating multiple mappings.\n *\n * @throws Error - When the input format is invalid or segments don't conform to requirements\n *\n * @since 1.0.0\n */\n\n private decodeMappingArray(encodedMap: MapType, namesOffset: number, sourceOffset: number): void {\n const linesOffset = this.mapping.length;\n if (!Array.isArray(encodedMap))\n throw new Error('Invalid encoded map: expected an array of frames.');\n\n try {\n encodedMap.forEach((frame, index) => {\n if (!frame) {\n this.mapping.push(frame);\n\n return;\n }\n\n if (!Array.isArray(frame))\n throw new Error(`Invalid Mappings array format at frame index ${index}: expected an array, received ${typeof frame}.`);\n\n const segments: FrameType = frame.map(segment => {\n this.validateSegment(segment);\n\n return {\n ...segment,\n nameIndex: (typeof segment.nameIndex === 'number') ? segment.nameIndex + namesOffset : null,\n sourceIndex: segment.sourceIndex + sourceOffset,\n generatedLine: segment.generatedLine + linesOffset\n };\n });\n\n this.mapping.push(segments);\n });\n } catch (error: unknown) {\n const errorMessage = (error instanceof Error) ? error.message : 'Unknown error';\n throw new Error(`Error decoding mappings: ${errorMessage}`);\n }\n }\n}\n", "/**\n * Import will remove at compile time\n */\n\nimport type {\n PositionInterface,\n SourceMapInterface,\n SourceOptionsInterface,\n PositionWithCodeInterface,\n PositionWithContentInterface\n} from '@services/interfaces/source-service.interface';\n\n/**\n * Imports\n */\n\nimport { MappingProvider } from '@providers/mapping.provider';\nimport { Bias } from '@providers/interfaces/mapping-provider.interface';\n\n/**\n * A service for validating and processing source maps that provides functionality for parsing,\n * position mapping, concatenation, and code snippet extraction.\n *\n * @param source - Source map data (SourceService, SourceMapInterface object, or JSON string)\n * @param file - Optional file name for the generated bundle\n * @returns A new SourceService instance\n *\n * @example\n * ```ts\n * const sourceMapJSON = '{\"version\": 3, \"file\": \"bundle.js\", \"sources\": [\"foo.ts\"], \"names\": [], \"mappings\": \"AAAA\"}';\n * const sourceService = new SourceService(sourceMapJSON);\n * console.log(sourceService.file); // 'bundle.js'\n * ```\n *\n * @since 1.0.0\n */\n\nexport class SourceService {\n /**\n * The name of the generated file this source map applies to.\n *\n * @since 1.0.0\n */\n\n readonly file: string | null;\n\n /**\n * Provider for accessing and manipulating the base64 VLQ-encoded mappings.\n *\n * @since 1.0.0\n */\n\n readonly mappings: MappingProvider;\n\n /**\n * The root URL for resolving relative paths in the source files.\n * @since 1.0.0\n */\n\n readonly sourceRoot: string | null;\n\n /**\n * List of symbol names referenced by the mappings.\n * @since 1.0.0\n */\n\n readonly names: Array<string>;\n\n /**\n * Array of source file paths.\n * @since 1.0.0\n */\n\n readonly sources: Array<string>;\n\n /**\n * Array of source file contents.\n * @since 1.0.0\n */\n\n readonly sourcesContent: Array<string>;\n\n /**\n * Creates a new SourceService instance.\n *\n * @param source - Source map data (SourceService, SourceMapInterface object, or JSON string)\n * @param file - Optional file name for the generated bundle\n *\n * @throws Error - When a source map has an invalid format or missing required properties\n *\n * @since 1.0.0\n */\n\n constructor(source: SourceService);\n constructor(source: SourceMapInterface | string, file?: string | null);\n constructor(source: SourceService | SourceMapInterface | string, file: string | null = null) {\n if (typeof source === 'string') {\n source = <SourceMapInterface> JSON.parse(source);\n }\n\n source = <SourceMapInterface> source;\n this.validateSourceMap(source);\n this.file = source.file ?? file;\n this.names = [ ...source.names ?? [] ];\n this.sources = [ ...source.sources ?? [] ];\n this.sourceRoot = source.sourceRoot ?? null;\n this.sourcesContent = source.sourcesContent ? [ ...source.sourcesContent ] : [];;\n this.mappings = new MappingProvider(source.mappings);\n }\n\n /**\n * Converts the source map data to a plain object.\n *\n * @returns A SourceMapInterface object representing the current state\n *\n * @example\n * ```ts\n * const mapObject = sourceService.getMapObject();\n * console.log(mapObject.file); // 'bundle.js'\n * ```\n *\n * @since 1.0.0\n */\n\n getMapObject(): SourceMapInterface {\n const sourceMap: SourceMapInterface = {\n version: 3,\n names: this.names,\n sources: this.sources,\n mappings: this.mappings.encode(),\n sourcesContent: this.sourcesContent\n };\n\n if (this.file)\n sourceMap.file = this.file;\n\n if (this.sourceRoot)\n sourceMap.sourceRoot = this.sourceRoot;\n\n return sourceMap;\n }\n\n /**\n * Concatenates additional source maps into the current instance.\n *\n * @param maps - Source maps to concatenate with the current map\n *\n * @example\n * ```ts\n * sourceService.concat(anotherSourceMap);\n * console.log(sourceService.sources); // Updated source paths\n * ```\n *\n * @throws Error - When no maps are provided\n *\n * @since 1.0.0\n */\n\n concat(...maps: Array<SourceMapInterface | SourceService>): void {\n if (maps.length < 1)\n throw new Error('At least one map must be provided for concatenation.');\n\n for (const map of (maps as Array<SourceMapInterface>)) {\n this.mappings.decode(map.mappings, this.names.length, this.sources.length);\n this.names.push(...map.names);\n this.sources.push(...map.sources);\n this.sourcesContent.push(...map.sourcesContent ?? []);\n }\n }\n\n /**\n * Creates a new SourceService instance with concatenated source maps.\n *\n * @param maps - Source maps to concatenate with a copy of the current map\n * @returns A new SourceService instance with the combined maps\n *\n * @example\n * ```ts\n * const newService = sourceService.concatNewMap(anotherSourceMap);\n * console.log(newService.sources); // Combined sources array\n * ```\n *\n * @throws Error - When no maps are provided\n *\n * @since 1.0.0\n */\n\n concatNewMap(...maps: Array<SourceMapInterface | SourceService>): SourceService {\n if (maps.length < 1)\n throw new Error('At least one map must be provided for concatenation.');\n\n const sourceService = new SourceService(this);\n for (const map of (maps as Array<SourceMapInterface>)) {\n sourceService.mappings.decode(map.mappings, sourceService.names.length, sourceService.sources.length);\n sourceService.names.push(...map.names);\n sourceService.sources.push(...map.sources);\n sourceService.sourcesContent.push(...map.sourcesContent ?? []);\n }\n\n return sourceService;\n }\n\n /**\n * Finds position in generated code based on original source position.\n *\n * @param line - Line number in the original source\n * @param column - Column number in the original source\n * @param sourceIndex - Index or file path of the original source\n * @param bias - Position matching strategy (default: Bias.BOUND)\n * @returns Position information or null if not found\n *\n * @example\n * ```ts\n * const position = sourceService.getPositionByOriginal(1, 10, 'foo.ts');\n * console.log(position?.generatedLine); // Line in generated code\n * ```\n *\n * @since 1.0.0\n */\n\n getPositionByOriginal(line: number, column: number, sourceIndex: number | string, bias: Bias = Bias.BOUND): PositionInterface | null {\n let index = <number> sourceIndex;\n if (typeof sourceIndex === 'string')\n index = this.sources.findIndex(str => str.includes(sourceIndex));\n\n if (index < 0)\n return null;\n\n const segment = this.mappings.getOriginalSegment(line, column, index, bias);\n if (!segment)\n return null;\n\n return {\n name: this.names[segment.nameIndex ?? -1] ?? null,\n line: segment.line,\n column: segment.column,\n source: this.sources[segment.sourceIndex],\n sourceRoot: this.sourceRoot,\n sourceIndex: segment.sourceIndex,\n generatedLine: segment.generatedLine,\n generatedColumn: segment.generatedColumn\n };\n }\n\n /**\n * Finds position in an original source based on generated code position.\n *\n * @param line - Line number in the generated code\n * @param column - Column number in the generated code\n * @param bias - Position matching strategy (default: Bias.BOUND)\n * @returns Position information or null if not found\n *\n * @example\n * ```ts\n * const position = sourceService.getPosition(2, 15);\n * console.log(position?.source); // Original source file\n * ```\n *\n * @since 1.0.0\n */\n\n getPosition(line: number, column: number, bias: Bias = Bias.BOUND): PositionInterface | null {\n const segment = this.mappings.getSegment(line, column, bias);\n if (!segment)\n return null;\n\n return {\n name: this.names[segment.nameIndex ?? -1] ?? null,\n line: segment.line,\n column: segment.column,\n source: this.sources[segment.sourceIndex],\n sourceRoot: this.sourceRoot,\n sourceIndex: segment.sourceIndex,\n generatedLine: segment.generatedLine,\n generatedColumn: segment.generatedColumn\n };\n }\n\n /**\n * Retrieves position with source content for a location in generated code.\n *\n * @param line - Line number in the generated code\n * @param column - Column number in the generated code\n * @param bias - Position matching strategy (default: Bias.BOUND)\n * @returns Position with content information or null if not found\n *\n * @example\n * ```ts\n * const posWithContent = sourceService.getPositionWithContent(3, 5);\n * console.log(posWithContent?.sourcesContent); // Original source content\n * ```\n *\n * @since 1.0.0\n */\n\n getPositionWithContent(line: number, column: number, bias: Bias = Bias.BOUND): PositionWithContentInterface | null {\n const position = this.getPosition(line, column, bias);\n if (!position)\n return null;\n\n return {\n ...position,\n sourcesContent: this.sourcesContent[position.sourceIndex]\n };\n }\n\n /**\n * Retrieves position with a code snippet from the original source.\n *\n * @param line - Line number in the generated code\n * @param column - Column number in the generated code\n * @param bias - Position matching strategy (default: Bias.BOUND)\n * @param options - Configuration for the amount of surrounding lines\n * @returns Position with code snippet or null if not found\n *\n * @example\n * ```ts\n * const posWithCode = sourceService.getPositionWithCode(4, 8, Bias.BOUND, {\n * linesBefore: 2,\n * linesAfter: 2\n * });\n * console.log(posWithCode?.code); // Code snippet with context\n * ```\n *\n * @since 1.0.0\n */\n\n getPositionWithCode(line: number, column: number, bias: Bias = Bias.BOUND, options?: SourceOptionsInterface): PositionWithCodeInterface | null {\n const position = this.getPosition(line, column, bias);\n if (!position || !this.sourcesContent[position.sourceIndex])\n return null;\n\n const settings = Object.assign({\n linesAfter: 4,\n linesBefore: 3\n }, options);\n\n const code = this.sourcesContent[position.sourceIndex].split('\\n');\n const endLine = Math.min( (position.line ?? 1) + settings.linesAfter, code.length);\n const startLine = Math.max((position.line ?? 1) - settings.linesBefore, 0);\n const relevantCode = code.slice(startLine, Math.min(endLine + 1, code.length)).join('\\n');\n\n return {\n ...position,\n code: relevantCode,\n endLine: endLine,\n startLine: startLine\n };\n }\n\n /**\n * Serializes the source map to a JSON string.\n *\n * @returns JSON string representation of the source map\n *\n * @example\n * ```ts\n * const jsonString = sourceService.toString();\n * console.log(jsonString); // '{\"version\":3,\"file\":\"bundle.js\",...}'\n * ```\n *\n * @since 1.0.0\n */\n\n toString(): string {\n return JSON.stringify(this.getMapObject());\n }\n\n /**\n * Validates a source map object has all required properties.\n *\n * @param input - Source map object to validate\n *\n * @throws Error - When required properties are missing\n *\n * @since 1.0.0\n */\n\n private validateSourceMap(input: SourceMapInterface): void {\n const requiredKeys: (keyof SourceMapInterface)[] = [ 'sources', 'mappings', 'names' ];\n if (!requiredKeys.every(key => key in input)) {\n throw new Error('Missing required keys in SourceMap.');\n }\n }\n}\n"],
|
|
6
|
+
"mappings": "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",
|
|
7
7
|
"names": ["base64Map", "base64Chars", "char", "index", "encodeVLQ", "value", "isNegative", "encoded", "vlq", "digit", "encodeArrayVLQ", "values", "decodeVLQ", "data", "result", "shift", "i", "continuation", "shifted", "MappingProvider", "_MappingProvider", "mapping", "namesOffset", "sourcesOffset", "generatedLine", "generatedColumn", "bias", "segments", "low", "high", "closestSegment", "mid", "segment", "line", "column", "sourceIndex", "midSegment", "encodedSourceMap", "segmentOffset", "segmentObject", "nameIndex", "adjustedLine", "adjustedColumn", "adjustedGeneratedColumn", "encodeArrayVLQ", "map", "positionOffset", "frame", "decodedSegment", "sourceLine", "sourceColumn", "encodedMap", "sourceOffset", "frames", "linesOffset", "index", "segmentsArray", "decodeVLQ", "error", "errorMessage", "SourceService", "_SourceService", "source", "file", "MappingProvider", "sourceMap", "maps", "map", "sourceService", "line", "column", "sourceIndex", "bias", "index", "str", "segment", "position", "options", "settings", "code", "endLine", "startLine", "relevantCode", "input", "key"]
|
|
8
8
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
`).map(
|
|
1
|
+
var c={V8:{STANDARD:/at\s+(?:([^(]+?)\s+)?\(?(?:(.+?):(\d+):(\d+)|(native))\)?/,EVAL:/^at\s(.+?)\s\(eval\sat\s(.+?)\s?\((.*):(\d+):(\d+)\),\s(.+?):(\d+):(\d+)\)$/,ALIAS:/^at\s(?:new\s)?(.+?)\s\[as\s(.+?)\]\s\(?(?:(.+?):(\d+):(\d+)|(native))\)?$/},SPIDERMONKEY:{EVAL:/^(.*)@(.+?):(\d+):(\d+),\s(.+?)@(.+?):(\d+):(\d+)$/,STANDARD:/^(.*)@(.*?)(?:(\[native code\])|:(\d+):(\d+))$/},JAVASCRIPT_CORE:{STANDARD:/^(?:(global|eval)\s)?(.*)@(.*?)(?::(\d+)(?::(\d+))?)?$/}},m=(r=>(r[r.V8=0]="V8",r[r.SPIDERMONKEY=1]="SPIDERMONKEY",r[r.JAVASCRIPT_CORE=2]="JAVASCRIPT_CORE",r[r.UNKNOWN=3]="UNKNOWN",r))(m||{});function l(n){return n.startsWith(" at ")||n.startsWith("at ")?0:n.includes("@")?/(?:global|eval) code@/.test(n)?2:1:3}function s(n){return n.startsWith("file://")?n.startsWith("file:///")&&/^file:\/\/\/[A-Za-z]:/.test(n)?n.substring(8):n.substring(7):(n=n.replace(/\\/g,"/"),n)}function u(n){return{source:n,eval:!1,async:!1,native:!1,constructor:!1}}function i(n){return n&&n.trim()!==""?parseInt(n,10):void 0}function N(n){let e=u(n);n.toLowerCase().includes("new")&&(e.constructor=!0),n.toLowerCase().includes("async")&&(e.async=!0);let t=n.match(c.V8.EVAL),a=!t&&n.match(c.V8.ALIAS),r=!t&&!a&&n.match(c.V8.STANDARD);return t?(e.eval=!0,e.functionName=t[1]||void 0,e.evalOrigin={line:i(t[4])??void 0,column:i(t[5])??void 0,fileName:t[3]?s(t[3]):void 0,functionName:t[2]||"<anonymous>"},e.line=i(t[7])??void 0,e.column=i(t[8])??void 0,e.fileName=t[6]?s(t[6]):void 0):a?(e.functionName=a[1]?a[1].trim():void 0,e.functionName+=a[2]?` [as ${a[2].trim()}]`:"",a[6]==="native"?(e.native=!0,e.fileName="[native code]"):(e.line=i(a[4])??void 0,e.column=i(a[5])??void 0,e.fileName=a[3]?s(a[3]):void 0)):r&&(e.functionName=r[1]?r[1].trim():void 0,r[5]==="native"?(e.native=!0,e.fileName="[native code]"):(e.line=i(r[3])??void 0,e.column=i(r[4])??void 0,e.fileName=r[2]?s(r[2]):void 0)),e}function S(n){let e=u(n),t=n.match(c.SPIDERMONKEY.EVAL);if(t)return e.eval=!0,e.functionName=t[1]?t[1]:void 0,n.toLowerCase().includes("constructor")&&(e.constructor=!0),n.toLowerCase().includes("async")&&(e.async=!0),e.evalOrigin={line:i(t[7])??void 0,column:i(t[8])??void 0,fileName:s(t[6]),functionName:t[5]?t[5]:void 0},e.line=i(t[3])??void 0,e.column=i(t[4])??void 0,e;let a=n.match(c.SPIDERMONKEY.STANDARD);return a&&(e.functionName=a[1]?a[1]:void 0,e.fileName=s(a[2]),a[3]==="[native code]"?e.fileName="[native code]":(e.line=i(a[4])??void 0,e.column=i(a[5])??void 0)),e}function p(n){let e=u(n),t=n.match(c.JAVASCRIPT_CORE.STANDARD);return t&&(e.functionName=t[2],e.eval=t[1]==="eval"||t[3]==="eval",n.toLowerCase().includes("constructor")&&(e.constructor=!0),n.toLowerCase().includes("async")&&(e.async=!0),t[3]==="[native code]"?(e.native=!0,e.fileName="[native code]"):(e.line=i(t[4])??void 0,e.column=i(t[5])??void 0,e.fileName=s(t[3]))),e}function A(n,e){switch(e){case 1:return S(n);case 2:return p(n);case 0:default:return N(n)}}function E(n){let e=typeof n=="string"?new Error(n):n,t=e.stack||"",a=e.message||"",r=e.name||"Error",d=l(t),f=t.split(`
|
|
2
|
+
`).map(o=>o.trim()).filter(o=>o.trim()!=="").slice(1);return{name:r,message:a,stack:f.map(o=>A(o,d)),rawStack:t}}export{m as JSEngines,u as createDefaultFrame,l as detectJSEngine,s as normalizePath,E as parseErrorStack,p as parseJavaScriptCoreStackLine,S as parseSpiderMonkeyStackLine,A as parseStackLine,N as parseV8StackLine,i as safeParseInt};
|
|
3
3
|
//# sourceMappingURL=parser.component.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/parser.component.ts"],
|
|
4
|
-
"sourceRoot": "https://github.com/remotex-lab/xmap/tree/v3.0.
|
|
5
|
-
"sourcesContent": ["/**\n * Export interfaces\n */\nexport type * from '@components/interfaces/parse-component.interface';\n/**\n * Import will remove at compile time\n */\nimport type { ParsedStackTrace, StackFrame } from '@components/interfaces/parse-component.interface';\n/**\n * Regular expression patterns for different JavaScript engines' stack traces\n *\n * @since 2.1.0\n */\nconst PATTERNS = {\n V8: {\n STANDARD: /at\\s+(?:([^(]+?)\\s+)?\\(?(?:(.+?):(\\d+):(\\d+)|(native))\\)?/,\n EVAL: /^at\\s(.+?)\\s\\(eval\\sat\\s(.+?)\\s?\\((.*):(\\d+):(\\d+)\\),\\s(.+?):(\\d+):(\\d+)\\)$/\n },\n SPIDERMONKEY: {\n EVAL: /^(.*)@(.+?):(\\d+):(\\d+),\\s(.+?)@(.+?):(\\d+):(\\d+)$/,\n STANDARD: /^(.*)@(.*?)(?:(\\[native code\\])|:(\\d+):(\\d+))$/\n },\n JAVASCRIPT_CORE: {\n STANDARD: /^(?:(global|eval)\\s)?(.*)@(.*?)(?::(\\d+)(?::(\\d+))?)?$/\n }\n};\n/**\n * Enumeration of JavaScript engines that can be detected from stack traces\n *\n * @since 2.1.0\n */\nexport const enum JSEngines {\n V8,\n SPIDERMONKEY,\n JAVASCRIPT_CORE,\n UNKNOWN\n}\n/**\n * Detects the JavaScript engine based on the format of a stack trace line\n *\n * @param stack - The stack trace to analyze\n * @returns The identified JavaScript engine type\n *\n * @example\n * ```ts\n * const engine = detectJSEngine(\"at functionName (/path/to/file.js:10:15)\");\n * if (engine === JSEngines.V8) {\n * // Handle V8 specific logic\n * }\n * ```\n *\n * @since 2.1.0\n */\nexport function detectJSEngine(stack: string): JSEngines {\n if (stack.startsWith(' at ') || stack.startsWith('at '))\n return JSEngines.V8;\n if (stack.includes('@'))\n return /(?:global|eval) code@/.test(stack)\n ? JSEngines.JAVASCRIPT_CORE : JSEngines.SPIDERMONKEY;\n return JSEngines.UNKNOWN;\n}\n/**\n * Normalizes file paths from various formats to a standard format\n *\n * @param filePath - The file path to normalize, which may include protocol prefixes\n * @returns A normalized file path with consistent separators and without protocol prefixes\n *\n * @remarks\n * Handles both Windows and Unix-style paths, as well as file:// protocol URLs.\n * Converts all backslashes to forward slashes for consistency.\n *\n * @example\n * ```ts\n * // Windows file URL to a normal path\n * normalizePath(\"file:///C:/path/to/file.js\"); // \"C:/path/to/file.js\"\n *\n * // Unix file URL to a normal path\n * normalizePath(\"file:///path/to/file.js\"); // \"/path/to/file.js\"\n *\n * // Windows backslashes to forward slashes\n * normalizePath(\"C:\\\\path\\\\to\\\\file.js\"); // \"C:/path/to/file.js\"\n * ```\n *\n * @since 2.1.0\n */\nexport function normalizePath(filePath: string): string {\n // Handle file:// protocol URLs\n if (filePath.startsWith('file://')) {\n // Handle Windows file:/// format\n if (filePath.startsWith('file:///') && /^file:\\/\\/\\/[A-Za-z]:/.test(filePath)) {\n // Windows absolute path: file:///C:/path/to/file.js\n return filePath.substring(8);\n }\n // Handle *nix file:// format\n return filePath.substring(7);\n }\n // Handle Windows-style paths with backward slashes\n filePath = filePath.replace(/\\\\/g, '/');\n return filePath;\n}\n/**\n * Creates a default stack frame object with initial values\n *\n * @param source - The original source line from the stack trace\n * @returns A new StackFrame object with default null values\n *\n * @see ParsedStackTrace\n * @see StackFrame\n *\n * @since 2.1.0\n */\nexport function createDefaultFrame(source: string): StackFrame {\n return {\n source,\n eval: false,\n async: false,\n native: false,\n constructor: false\n };\n}\n/**\n * Safely parses a string value to an integer, handling undefined and null cases\n *\n * @param value - The string value to parse\n * @returns The parsed integer or null if the input is undefined/null\n *\n * @example\n * ```ts\n * safeParseInt(\"42\"); // 42\n * safeParseInt(undefined); // null\n * safeParseInt(null); // null\n * ```\n *\n * @since 2.1.0\n */\nexport function safeParseInt(value: string | undefined | null): number | undefined {\n return value && value.trim() !== '' ? parseInt(value, 10) : undefined;\n}\n/**\n * Parses a V8 JavaScript engine stack trace line into a structured StackFrame object\n *\n * @param line - The stack trace line to parse\n * @returns A StackFrame object containing the parsed information\n *\n * @remarks\n * Handles both standard V8 stack frames and eval-generated stack frames which\n * have a more complex structure with nested origin information.\n *\n * @example\n * ```ts\n * // Standard frame\n * parseV8StackLine(\"at functionName (/path/to/file.js:10:15)\");\n *\n * // Eval frame\n * parseV8StackLine(\"at eval (eval at evalFn (/source.js:5:10), <anonymous>:1:5)\");\n * ```\n *\n * @throws Error - If the line format doesn't match any known V8 pattern\n *\n * @see StackFrame\n * @see createDefaultFrame\n *\n * @since 2.1.0\n */\nexport function parseV8StackLine(line: string): StackFrame {\n const frame = createDefaultFrame(line);\n // Check for eval format first\n const evalMatch = line.match(PATTERNS.V8.EVAL);\n if (evalMatch) {\n frame.eval = true;\n frame.functionName = evalMatch[1] ? evalMatch[1] : undefined;\n // Add eval origin information\n frame.evalOrigin = {\n line: safeParseInt(evalMatch[4]) ?? undefined,\n column: safeParseInt(evalMatch[5]) ?? undefined,\n fileName: evalMatch[3] ? normalizePath(evalMatch[3]) : undefined,\n functionName: evalMatch[2] || '<anonymous>'\n };\n // Position inside evaluated code\n frame.line = safeParseInt(evalMatch[7]) ?? undefined;\n frame.column = safeParseInt(evalMatch[8]) ?? undefined;\n frame.fileName = evalMatch[6] ? normalizePath(evalMatch[6]) : undefined;\n frame.native = (frame.fileName ?? '').startsWith('node') ?? false;\n return frame;\n }\n // Standard V8 format\n const match = line.match(PATTERNS.V8.STANDARD);\n if (match) {\n frame.functionName = match[1] ? match[1].trim() : undefined;\n if (line.toLowerCase().includes('new'))\n frame.constructor = true;\n if (line.toLowerCase().includes('async'))\n frame.async = true;\n if (match[5] === 'native') {\n frame.native = true;\n frame.fileName = '[native code]';\n }\n else {\n frame.line = safeParseInt(match[3]) ?? undefined;\n frame.column = safeParseInt(match[4]) ?? undefined;\n frame.fileName = match[2] ? normalizePath(match[2]) : undefined;\n frame.native = (frame.fileName ?? '').startsWith('node') ?? false;\n }\n }\n return frame;\n}\n/**\n * Parses a SpiderMonkey JavaScript engine stack trace line into a structured StackFrame object\n *\n * @param line - The stack trace line to parse\n * @returns A StackFrame object containing the parsed information\n *\n * @remarks\n * Handles both standard SpiderMonkey stack frames and eval/Function-generated stack frames\n * which contain additional evaluation context information.\n *\n * @example\n * ```ts\n * // Standard frame\n * parseSpiderMonkeyStackLine(\"functionName@/path/to/file.js:10:15\");\n *\n * // Eval frame\n * parseSpiderMonkeyStackLine(\"evalFn@/source.js line 5 > eval:1:5\");\n * ```\n *\n * @see StackFrame\n * @see createDefaultFrame\n *\n * @since 2.1.0\n */\nexport function parseSpiderMonkeyStackLine(line: string): StackFrame {\n const frame = createDefaultFrame(line);\n // Check for eval/Function format\n const evalMatch = line.match(PATTERNS.SPIDERMONKEY.EVAL);\n if (evalMatch) {\n frame.eval = true;\n frame.functionName = evalMatch[1] ? evalMatch[1] : undefined;\n if (line.toLowerCase().includes('constructor'))\n frame.constructor = true;\n if (line.toLowerCase().includes('async'))\n frame.async = true;\n // Add eval origin information\n frame.evalOrigin = {\n line: safeParseInt(evalMatch[7]) ?? undefined,\n column: safeParseInt(evalMatch[8]) ?? undefined,\n fileName: normalizePath(evalMatch[6]),\n functionName: evalMatch[5] ? evalMatch[5] : undefined\n };\n // Position inside evaluated code\n frame.line = safeParseInt(evalMatch[3]) ?? undefined;\n frame.column = safeParseInt(evalMatch[4]) ?? undefined;\n return frame;\n }\n // Standard SpiderMonkey format\n const match = line.match(PATTERNS.SPIDERMONKEY.STANDARD);\n if (match) {\n frame.functionName = match[1] ? match[1] : undefined;\n frame.fileName = normalizePath(match[2]);\n if (match[3] === '[native code]') {\n frame.fileName = '[native code]';\n }\n else {\n frame.line = safeParseInt(match[4]) ?? undefined;\n frame.column = safeParseInt(match[5]) ?? undefined;\n }\n }\n return frame;\n}\n/**\n * Parses a JavaScriptCore engine stack trace line into a structured StackFrame object\n *\n * @param line - The stack trace line to parse\n * @returns A StackFrame object containing the parsed information\n *\n * @remarks\n * Handles both standard JavaScriptCore stack frames and eval-generated stack frames.\n * Special handling is provided for \"global code\" references and native code.\n *\n * @example\n * ```ts\n * // Standard frame\n * parseJavaScriptCoreStackLine(\"functionName@/path/to/file.js:10:15\");\n *\n * // Eval frame\n * parseJavaScriptCoreStackLine(\"eval code@\");\n * ```\n *\n * @see StackFrame\n * @see createDefaultFrame\n *\n * @since 2.1.0\n */\nexport function parseJavaScriptCoreStackLine(line: string): StackFrame {\n const frame = createDefaultFrame(line);\n // Standard JavaScriptCore format\n const match = line.match(PATTERNS.JAVASCRIPT_CORE.STANDARD);\n if (match) {\n frame.functionName = match[2];\n frame.eval = (match[1] === 'eval' || match[3] === 'eval');\n if (line.toLowerCase().includes('constructor'))\n frame.constructor = true;\n if (line.toLowerCase().includes('async'))\n frame.async = true;\n if (match[3] === '[native code]') {\n frame.native = true;\n frame.fileName = '[native code]';\n }\n else {\n frame.line = safeParseInt(match[4]) ?? undefined;\n frame.column = safeParseInt(match[5]) ?? undefined;\n frame.fileName = normalizePath(match[3]);\n }\n }\n return frame;\n}\n/**\n * Parses a stack trace line based on the detected JavaScript engine\n *\n * @param line - The stack trace line to parse\n * @param engine - The JavaScript engine type that generated the stack trace\n * @returns A StackFrame object containing the parsed information\n *\n * @remarks\n * Delegates to the appropriate parsing function based on the JavaScript engine.\n * Defaults to V8 parsing if the engine is unknown.\n *\n * @example\n * ```ts\n * const engine = detectJSEngine(stackLine);\n * const frame = parseStackLine(stackLine, engine);\n * ```\n *\n * @see JSEngines\n * @see parseV8StackLine\n * @see parseSpiderMonkeyStackLine\n * @see parseJavaScriptCoreStackLine\n *\n * @since 2.1.0\n */\nexport function parseStackLine(line: string, engine: JSEngines): StackFrame {\n switch (engine) {\n case JSEngines.SPIDERMONKEY:\n return parseSpiderMonkeyStackLine(line);\n case JSEngines.JAVASCRIPT_CORE:\n return parseJavaScriptCoreStackLine(line);\n case JSEngines.V8:\n default:\n return parseV8StackLine(line);\n }\n}\n/**\n * Parses a complete error stack trace into a structured format\n *\n * @param error - Error object or error message string to parse\n * @returns A ParsedStackTrace object containing structured stack trace information\n *\n * @remarks\n * Automatically detects the JavaScript engine from the stack format.\n * Filters out redundant information like the error name/message line.\n * Handles both Error objects and string error messages.\n *\n * @example\n * ```ts\n * try {\n * throw new Error (\"Something went wrong\");\n * } catch (error) {\n * const parsedStack = parseErrorStack(error);\n * console.log(parsedStack.name); // \"Error\"\n * console.log(parsedStack.message); // \"Something went wrong\"\n * console.log(parsedStack.stack); // Array of StackFrame objects\n * }\n * ```\n *\n * @see ParsedStackTrace\n * @see StackFrame\n * @see parseStackLine\n * @see detectJSEngine\n *\n * @since 2.1.0\n */\nexport function parseErrorStack(error: Error | string): ParsedStackTrace {\n const errorObj = typeof error === 'string' ? new Error(error) : error;\n const stack = errorObj.stack || '';\n const message = errorObj.message || '';\n const name = errorObj.name || 'Error';\n const engine = detectJSEngine(stack);\n const stackLines = stack.split('\\n')\n .map(line => line.trim())\n .filter(line => line.trim() !== '')\n .slice(1);\n return {\n name,\n message,\n stack: stackLines.map(line => parseStackLine(line, engine)),\n rawStack: stack\n };\n}\n"],
|
|
6
|
-
"mappings": "
|
|
7
|
-
"names": ["PATTERNS", "JSEngines", "detectJSEngine", "stack", "normalizePath", "filePath", "createDefaultFrame", "source", "safeParseInt", "value", "parseV8StackLine", "line", "frame", "evalMatch", "
|
|
4
|
+
"sourceRoot": "https://github.com/remotex-lab/xmap/tree/v3.0.3/",
|
|
5
|
+
"sourcesContent": ["/**\n * Export interfaces\n */\n\nexport type * from '@components/interfaces/parse-component.interface';\n\n/**\n * Import will remove at compile time\n */\n\nimport type { ParsedStackTrace, StackFrame } from '@components/interfaces/parse-component.interface';\n\n/**\n * Regular expression patterns for different JavaScript engines' stack traces\n *\n * @since 2.1.0\n */\n\nconst PATTERNS = {\n V8: {\n STANDARD: /at\\s+(?:([^(]+?)\\s+)?\\(?(?:(.+?):(\\d+):(\\d+)|(native))\\)?/,\n EVAL: /^at\\s(.+?)\\s\\(eval\\sat\\s(.+?)\\s?\\((.*):(\\d+):(\\d+)\\),\\s(.+?):(\\d+):(\\d+)\\)$/,\n ALIAS: /^at\\s(?:new\\s)?(.+?)\\s\\[as\\s(.+?)\\]\\s\\(?(?:(.+?):(\\d+):(\\d+)|(native))\\)?$/\n },\n SPIDERMONKEY: {\n EVAL: /^(.*)@(.+?):(\\d+):(\\d+),\\s(.+?)@(.+?):(\\d+):(\\d+)$/,\n STANDARD: /^(.*)@(.*?)(?:(\\[native code\\])|:(\\d+):(\\d+))$/\n },\n JAVASCRIPT_CORE: {\n STANDARD: /^(?:(global|eval)\\s)?(.*)@(.*?)(?::(\\d+)(?::(\\d+))?)?$/\n }\n};\n\n/**\n * Enumeration of JavaScript engines that can be detected from stack traces\n *\n * @since 2.1.0\n */\n\nexport const enum JSEngines {\n V8,\n SPIDERMONKEY,\n JAVASCRIPT_CORE,\n UNKNOWN\n}\n\n/**\n * Detects the JavaScript engine based on the format of a stack trace line\n *\n * @param stack - The stack trace to analyze\n * @returns The identified JavaScript engine type\n *\n * @example\n * ```ts\n * const engine = detectJSEngine(\"at functionName (/path/to/file.js:10:15)\");\n * if (engine === JSEngines.V8) {\n * // Handle V8 specific logic\n * }\n * ```\n *\n * @since 2.1.0\n */\n\nexport function detectJSEngine(stack: string): JSEngines {\n if (stack.startsWith(' at ') || stack.startsWith('at '))\n return JSEngines.V8;\n\n if (stack.includes('@'))\n return /(?:global|eval) code@/.test(stack)\n ? JSEngines.JAVASCRIPT_CORE : JSEngines.SPIDERMONKEY;\n\n return JSEngines.UNKNOWN;\n}\n\n/**\n * Normalizes file paths from various formats to a standard format\n *\n * @param filePath - The file path to normalize, which may include protocol prefixes\n * @returns A normalized file path with consistent separators and without protocol prefixes\n *\n * @remarks\n * Handles both Windows and Unix-style paths, as well as file:// protocol URLs.\n * Converts all backslashes to forward slashes for consistency.\n *\n * @example\n * ```ts\n * // Windows file URL to a normal path\n * normalizePath(\"file:///C:/path/to/file.js\"); // \"C:/path/to/file.js\"\n *\n * // Unix file URL to a normal path\n * normalizePath(\"file:///path/to/file.js\"); // \"/path/to/file.js\"\n *\n * // Windows backslashes to forward slashes\n * normalizePath(\"C:\\\\path\\\\to\\\\file.js\"); // \"C:/path/to/file.js\"\n * ```\n *\n * @since 2.1.0\n */\n\nexport function normalizePath(filePath: string): string {\n // Handle file:// protocol URLs\n if (filePath.startsWith('file://')) {\n // Handle Windows file:/// format\n if (filePath.startsWith('file:///') && /^file:\\/\\/\\/[A-Za-z]:/.test(filePath)) {\n // Windows absolute path: file:///C:/path/to/file.js\n return filePath.substring(8);\n }\n\n // Handle *nix file:// format\n return filePath.substring(7);\n }\n\n // Handle Windows-style paths with backward slashes\n filePath = filePath.replace(/\\\\/g, '/');\n\n return filePath;\n}\n\n/**\n * Creates a default stack frame object with initial values\n *\n * @param source - The original source line from the stack trace\n * @returns A new StackFrame object with default null values\n *\n * @see ParsedStackTrace\n * @see StackFrame\n *\n * @since 2.1.0\n */\n\nexport function createDefaultFrame(source: string): StackFrame {\n return {\n source,\n eval: false,\n async: false,\n native: false,\n constructor: false\n };\n}\n\n/**\n * Safely parses a string value to an integer, handling undefined and null cases\n *\n * @param value - The string value to parse\n * @returns The parsed integer or null if the input is undefined/null\n *\n * @example\n * ```ts\n * safeParseInt(\"42\"); // 42\n * safeParseInt(undefined); // null\n * safeParseInt(null); // null\n * ```\n *\n * @since 2.1.0\n */\n\nexport function safeParseInt(value: string | undefined | null): number | undefined {\n return value && value.trim() !== '' ? parseInt(value, 10) : undefined;\n}\n\n/**\n * Parses a V8 JavaScript engine stack trace line into a structured StackFrame object\n *\n * @param line - The stack trace line to parse\n * @returns A StackFrame object containing the parsed information\n *\n * @remarks\n * Handles both standard V8 stack frames and eval-generated stack frames which\n * have a more complex structure with nested origin information.\n *\n * @example\n * ```ts\n * // Standard frame\n * parseV8StackLine(\"at functionName (/path/to/file.js:10:15)\");\n *\n * // Eval frame\n * parseV8StackLine(\"at eval (eval at evalFn (/source.js:5:10), <anonymous>:1:5)\");\n * ```\n *\n * @throws Error - If the line format doesn't match any known V8 pattern\n *\n * @see StackFrame\n * @see createDefaultFrame\n *\n * @since 2.1.0\n */\n\nexport function parseV8StackLine(line: string): StackFrame {\n const frame = createDefaultFrame(line);\n\n // Common flags that apply to all formats\n if (line.toLowerCase().includes('new')) frame.constructor = true;\n if (line.toLowerCase().includes('async')) frame.async = true;\n\n // Try to match against each pattern\n const evalMatch = line.match(PATTERNS.V8.EVAL);\n const aliasMatch = !evalMatch && line.match(PATTERNS.V8.ALIAS);\n const standardMatch = !evalMatch && !aliasMatch && line.match(PATTERNS.V8.STANDARD);\n\n if (evalMatch) {\n // Handle eval format\n frame.eval = true;\n frame.functionName = evalMatch[1] || undefined;\n\n // Add eval origin information\n frame.evalOrigin = {\n line: safeParseInt(evalMatch[4]) ?? undefined,\n column: safeParseInt(evalMatch[5]) ?? undefined,\n fileName: evalMatch[3] ? normalizePath(evalMatch[3]) : undefined,\n functionName: evalMatch[2] || '<anonymous>'\n };\n\n // Position inside evaluated code\n frame.line = safeParseInt(evalMatch[7]) ?? undefined;\n frame.column = safeParseInt(evalMatch[8]) ?? undefined;\n frame.fileName = evalMatch[6] ? normalizePath(evalMatch[6]) : undefined;\n } else if (aliasMatch) {\n // Handle alias format\n frame.functionName = aliasMatch[1] ? aliasMatch[1].trim() : undefined;\n frame.functionName += aliasMatch[2] ? ` [as ${ aliasMatch[2].trim() }]` : '';\n\n if (aliasMatch[6] === 'native') {\n frame.native = true;\n frame.fileName = '[native code]';\n } else {\n frame.line = safeParseInt(aliasMatch[4]) ?? undefined;\n frame.column = safeParseInt(aliasMatch[5]) ?? undefined;\n frame.fileName = aliasMatch[3] ? normalizePath(aliasMatch[3]) : undefined;\n }\n } else if (standardMatch) {\n // Handle standard format\n frame.functionName = standardMatch[1] ? standardMatch[1].trim() : undefined;\n\n if (standardMatch[5] === 'native') {\n frame.native = true;\n frame.fileName = '[native code]';\n } else {\n frame.line = safeParseInt(standardMatch[3]) ?? undefined;\n frame.column = safeParseInt(standardMatch[4]) ?? undefined;\n frame.fileName = standardMatch[2] ? normalizePath(standardMatch[2]) : undefined;\n }\n }\n\n return frame;\n}\n\n/**\n * Parses a SpiderMonkey JavaScript engine stack trace line into a structured StackFrame object\n *\n * @param line - The stack trace line to parse\n * @returns A StackFrame object containing the parsed information\n *\n * @remarks\n * Handles both standard SpiderMonkey stack frames and eval/Function-generated stack frames\n * which contain additional evaluation context information.\n *\n * @example\n * ```ts\n * // Standard frame\n * parseSpiderMonkeyStackLine(\"functionName@/path/to/file.js:10:15\");\n *\n * // Eval frame\n * parseSpiderMonkeyStackLine(\"evalFn@/source.js line 5 > eval:1:5\");\n * ```\n *\n * @see StackFrame\n * @see createDefaultFrame\n *\n * @since 2.1.0\n */\n\nexport function parseSpiderMonkeyStackLine(line: string): StackFrame {\n const frame = createDefaultFrame(line);\n\n // Check for eval/Function format\n const evalMatch = line.match(PATTERNS.SPIDERMONKEY.EVAL);\n if (evalMatch) {\n frame.eval = true;\n frame.functionName = evalMatch[1] ? evalMatch[1] : undefined;\n\n if (line.toLowerCase().includes('constructor'))\n frame.constructor = true;\n\n if (line.toLowerCase().includes('async'))\n frame.async = true;\n\n // Add eval origin information\n frame.evalOrigin = {\n line: safeParseInt(evalMatch[7]) ?? undefined,\n column: safeParseInt(evalMatch[8]) ?? undefined,\n fileName: normalizePath(evalMatch[6]),\n functionName: evalMatch[5] ? evalMatch[5] : undefined\n };\n\n // Position inside evaluated code\n frame.line = safeParseInt(evalMatch[3]) ?? undefined;\n frame.column = safeParseInt(evalMatch[4]) ?? undefined;\n\n return frame;\n }\n\n // Standard SpiderMonkey format\n const match = line.match(PATTERNS.SPIDERMONKEY.STANDARD);\n if (match) {\n frame.functionName = match[1] ? match[1] : undefined;\n frame.fileName = normalizePath(match[2]);\n\n if (match[3] === '[native code]') {\n frame.fileName = '[native code]';\n } else {\n frame.line = safeParseInt(match[4]) ?? undefined;\n frame.column = safeParseInt(match[5]) ?? undefined;\n }\n }\n\n return frame;\n}\n\n/**\n * Parses a JavaScriptCore engine stack trace line into a structured StackFrame object\n *\n * @param line - The stack trace line to parse\n * @returns A StackFrame object containing the parsed information\n *\n * @remarks\n * Handles both standard JavaScriptCore stack frames and eval-generated stack frames.\n * Special handling is provided for \"global code\" references and native code.\n *\n * @example\n * ```ts\n * // Standard frame\n * parseJavaScriptCoreStackLine(\"functionName@/path/to/file.js:10:15\");\n *\n * // Eval frame\n * parseJavaScriptCoreStackLine(\"eval code@\");\n * ```\n *\n * @see StackFrame\n * @see createDefaultFrame\n *\n * @since 2.1.0\n */\n\nexport function parseJavaScriptCoreStackLine(line: string): StackFrame {\n const frame = createDefaultFrame(line);\n\n // Standard JavaScriptCore format\n const match = line.match(PATTERNS.JAVASCRIPT_CORE.STANDARD);\n if (match) {\n frame.functionName = match[2];\n frame.eval = (match[1] === 'eval' || match[3] === 'eval');\n\n if (line.toLowerCase().includes('constructor'))\n frame.constructor = true;\n\n if (line.toLowerCase().includes('async'))\n frame.async = true;\n\n if (match[3] === '[native code]') {\n frame.native = true;\n frame.fileName = '[native code]';\n } else {\n frame.line = safeParseInt(match[4]) ?? undefined;\n frame.column = safeParseInt(match[5]) ?? undefined;\n frame.fileName = normalizePath(match[3]);\n }\n }\n\n return frame;\n}\n\n/**\n * Parses a stack trace line based on the detected JavaScript engine\n *\n * @param line - The stack trace line to parse\n * @param engine - The JavaScript engine type that generated the stack trace\n * @returns A StackFrame object containing the parsed information\n *\n * @remarks\n * Delegates to the appropriate parsing function based on the JavaScript engine.\n * Defaults to V8 parsing if the engine is unknown.\n *\n * @example\n * ```ts\n * const engine = detectJSEngine(stackLine);\n * const frame = parseStackLine(stackLine, engine);\n * ```\n *\n * @see JSEngines\n * @see parseV8StackLine\n * @see parseSpiderMonkeyStackLine\n * @see parseJavaScriptCoreStackLine\n *\n * @since 2.1.0\n */\n\nexport function parseStackLine(line: string, engine: JSEngines): StackFrame {\n switch (engine) {\n case JSEngines.SPIDERMONKEY:\n return parseSpiderMonkeyStackLine(line);\n case JSEngines.JAVASCRIPT_CORE:\n return parseJavaScriptCoreStackLine(line);\n case JSEngines.V8:\n default:\n return parseV8StackLine(line);\n }\n}\n\n/**\n * Parses a complete error stack trace into a structured format\n *\n * @param error - Error object or error message string to parse\n * @returns A ParsedStackTrace object containing structured stack trace information\n *\n * @remarks\n * Automatically detects the JavaScript engine from the stack format.\n * Filters out redundant information like the error name/message line.\n * Handles both Error objects and string error messages.\n *\n * @example\n * ```ts\n * try {\n * throw new Error (\"Something went wrong\");\n * } catch (error) {\n * const parsedStack = parseErrorStack(error);\n * console.log(parsedStack.name); // \"Error\"\n * console.log(parsedStack.message); // \"Something went wrong\"\n * console.log(parsedStack.stack); // Array of StackFrame objects\n * }\n * ```\n *\n * @see ParsedStackTrace\n * @see StackFrame\n * @see parseStackLine\n * @see detectJSEngine\n *\n * @since 2.1.0\n */\n\nexport function parseErrorStack(error: Error | string): ParsedStackTrace {\n const errorObj = typeof error === 'string' ? new Error(error) : error;\n const stack = errorObj.stack || '';\n const message = errorObj.message || '';\n const name = errorObj.name || 'Error';\n\n const engine = detectJSEngine(stack);\n const stackLines = stack.split('\\n')\n .map(line => line.trim())\n .filter(line => line.trim() !== '')\n .slice(1);\n\n return {\n name,\n message,\n stack: stackLines.map(line => parseStackLine(line, engine)),\n rawStack: stack\n };\n}\n"],
|
|
6
|
+
"mappings": "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",
|
|
7
|
+
"names": ["PATTERNS", "JSEngines", "detectJSEngine", "stack", "normalizePath", "filePath", "createDefaultFrame", "source", "safeParseInt", "value", "parseV8StackLine", "line", "frame", "evalMatch", "aliasMatch", "standardMatch", "parseSpiderMonkeyStackLine", "match", "parseJavaScriptCoreStackLine", "parseStackLine", "engine", "parseErrorStack", "error", "errorObj", "message", "name", "stackLines"]
|
|
8
8
|
}
|