rawsql-ts
Version:
High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
128 lines • 4.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TextPositionUtils = void 0;
/**
* Utility functions for text position conversion and manipulation
*
* Provides centralized functionality for converting between different
* position representations commonly used in text processing and SQL parsing.
*/
class TextPositionUtils {
/**
* Convert line/column position to character offset
*
* @param text - Source text
* @param position - Line/column position (1-based)
* @returns Character offset (0-based) or -1 if invalid
*
* @example
* ```typescript
* const text = "SELECT id\nFROM users";
* const charOffset = TextPositionUtils.lineColumnToCharOffset(text, { line: 2, column: 1 });
* console.log(charOffset); // 10 (position of 'F' in 'FROM')
* ```
*/
static lineColumnToCharOffset(text, position) {
if (position.line < 1 || position.column < 1) {
return -1;
}
const lines = text.split('\n');
if (position.line > lines.length) {
return -1;
}
const targetLine = lines[position.line - 1];
if (position.column > targetLine.length + 1) {
return -1;
}
let offset = 0;
for (let i = 0; i < position.line - 1; i++) {
offset += lines[i].length + 1; // +1 for newline
}
offset += position.column - 1;
return offset;
}
/**
* Convert character offset to line/column position
*
* @param text - Source text
* @param charOffset - Character offset (0-based)
* @returns Line/column position (1-based) or null if invalid
*
* @example
* ```typescript
* const text = "SELECT id\nFROM users";
* const position = TextPositionUtils.charOffsetToLineColumn(text, 10);
* console.log(position); // { line: 2, column: 1 }
* ```
*/
static charOffsetToLineColumn(text, charOffset) {
if (charOffset < 0 || charOffset > text.length) {
return null;
}
const lines = text.split('\n');
let currentOffset = 0;
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
const lineLength = lines[lineIndex].length;
if (charOffset < currentOffset + lineLength) {
return {
line: lineIndex + 1,
column: charOffset - currentOffset + 1
};
}
if (charOffset === currentOffset + lineLength && lineIndex < lines.length - 1) {
return {
line: lineIndex + 2,
column: 1
};
}
currentOffset += lineLength + 1; // +1 for newline
}
// Handle position at very end
if (charOffset === text.length) {
const lastLine = lines[lines.length - 1];
return {
line: lines.length,
column: lastLine.length + 1
};
}
return null;
}
/**
* Check if a position is within text bounds
*
* @param text - Source text
* @param position - Line/column position (1-based)
* @returns True if position is valid
*/
static isValidPosition(text, position) {
return this.lineColumnToCharOffset(text, position) !== -1;
}
/**
* Get the line at the specified line number
*
* @param text - Source text
* @param lineNumber - Line number (1-based)
* @returns Line content or null if invalid
*/
static getLine(text, lineNumber) {
if (lineNumber < 1) {
return null;
}
const lines = text.split('\n');
if (lineNumber > lines.length) {
return null;
}
return lines[lineNumber - 1];
}
/**
* Get the total number of lines in text
*
* @param text - Source text
* @returns Number of lines
*/
static getLineCount(text) {
return text.split('\n').length;
}
}
exports.TextPositionUtils = TextPositionUtils;
//# sourceMappingURL=TextPositionUtils.js.map