/*! * Copyright (c) Squirrel Chat et al., All rights reserved. * SPDX-License-Identifier: BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ type TomlErrorOptions = ErrorOptions & { toml: string ptr: number } function getLineColFromPtr(string: string, ptr: number): [number, number] { let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g) return [lines.length, lines.pop()!.length + 1] } function makeCodeBlock(string: string, line: number, column: number) { let lines = string.split(/\r\n|\n|\r/g) let codeblock = '' let numberLen = (Math.log10(line + 1) | 0) + 1 for (let i = line - 1; i <= line + 1; i++) { let l = lines[i - 1] if (!l) continue codeblock += i.toString().padEnd(numberLen, ' ') codeblock += ': ' codeblock += l codeblock += '\n' if (i === line) { codeblock += ' '.repeat(numberLen + column + 2) codeblock += '^\n' } } return codeblock } export class TomlError extends Error { line: number column: number codeblock: string constructor(message: string, options: TomlErrorOptions) { const [line, column] = getLineColFromPtr(options.toml, options.ptr) const codeblock = makeCodeBlock(options.toml, line, column) super(`Invalid TOML document: ${message}\n\n${codeblock}`, options) this.line = line this.column = column this.codeblock = codeblock } }