UNPKG

@adguard/agtree

Version:
74 lines (71 loc) 2.67 kB
/* * AGTree v3.4.3 (build date: Thu, 11 Dec 2025 13:43:19 GMT) * (c) 2025 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ import { LF, FF, CR } from './constants.js'; /** * @file Position provider class. */ /** * Class responsible for converting a character offset in source code into a line and column position. * This conversion is particularly needed in linters and VSCode extensions, * where line and column numbers are more human-friendly and intuitive than character offsets. * Moreover, the VSCode diagnostics API does not directly support character offsets, * it also requires line and column numbers. */ class PositionProvider { /** * Maps a character offset to a line number. */ offsetToLine; /** * Maps a line number to the starting character offset of that line. */ lineStartOffsets; /** * Constructs a new PositionProvider instance. * * @param sourceCode The source code as a string. */ constructor(sourceCode) { this.offsetToLine = []; this.lineStartOffsets = [0]; let currentLine = 0; for (let i = 0; i < sourceCode.length; i += 1) { this.offsetToLine[i] = currentLine; // Handle different types of line breaks: LF, FF, and CR if (sourceCode[i] === LF || sourceCode[i] === FF || sourceCode[i] === CR) { currentLine += 1; this.lineStartOffsets[currentLine] = (sourceCode[i] === CR && sourceCode[i + 1] === LF) ? i + 2 : i + 1; if (sourceCode[i] === CR && sourceCode[i + 1] === LF) { // Skip the '\n' in a '\r\n' sequence i += 1; } } } // Handle the case where the last offset is at the end of the source code this.offsetToLine[sourceCode.length] = currentLine; } /** * Converts a character offset to a line and column position. * * @param offset The zero-based character offset in the source code. * @returns A Position object containing the 1-based line and column number, or null if the offset is out of range. */ convertOffsetToPosition(offset) { if (offset < 0 || offset > this.offsetToLine.length - 1) { return null; } const line = this.offsetToLine[offset]; const lineStartOffset = this.lineStartOffsets[line]; return { line: line + 1, column: offset - lineStartOffset + 1, }; } } export { PositionProvider };