Merge pull request #1300 from mermaid-js/sidv/errorHighlight
feat: Add error highlight
This commit is contained in:
@@ -83,6 +83,8 @@ module.exports = {
|
||||
env: true,
|
||||
fn: true,
|
||||
i: true,
|
||||
j: true,
|
||||
k: true,
|
||||
param: true,
|
||||
req: true,
|
||||
res: true,
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Function to find the line number with the most characters in common with the error
|
||||
export function findMostRelevantLineNumber(errorLineText: string, code: string): number {
|
||||
const codeLines = code.split('\n');
|
||||
let mostRelevantLineNumber = -1;
|
||||
let maxCommonLength = 0;
|
||||
|
||||
for (const [i, line] of codeLines.entries()) {
|
||||
let commonLength = 0;
|
||||
for (let j = 0; j <= errorLineText.length; j++) {
|
||||
for (let k = j + 1; k <= errorLineText.length; k++) {
|
||||
const sub = errorLineText.slice(j, k);
|
||||
if (line.includes(sub)) {
|
||||
commonLength = Math.max(commonLength, sub.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (commonLength > maxCommonLength) {
|
||||
maxCommonLength = commonLength;
|
||||
mostRelevantLineNumber = i + 1; // Line numbers start from 1
|
||||
}
|
||||
}
|
||||
return mostRelevantLineNumber;
|
||||
}
|
||||
|
||||
// Function to replace the incorrect line number in the error message
|
||||
export function replaceLineNumberInErrorMessage(
|
||||
errorMessage: string,
|
||||
realLineNumber: number
|
||||
): string {
|
||||
const regexParseError = /Parse error on line (\d+):/;
|
||||
const regexLexError = /Lexical error on line (\d+)/;
|
||||
return errorMessage
|
||||
.replace(regexParseError, `Parse error on line ${realLineNumber}:`)
|
||||
.replace(regexLexError, `Lexical error on line ${realLineNumber}:`);
|
||||
}
|
||||
|
||||
export function extractErrorLineText(errorMessage: string): string {
|
||||
const regex = /Error: Parse error on line \d+:\n(.+)\n+/;
|
||||
const match = errorMessage.match(regex);
|
||||
if (match) {
|
||||
return match[1].slice(3);
|
||||
}
|
||||
|
||||
const regexLex = /Error: Lexical error on line \d+. Unrecognized text.\n(.+)\n-+/;
|
||||
const matchLex = errorMessage.match(regexLex);
|
||||
return matchLex ? matchLex[1].slice(3) : '';
|
||||
}
|
||||
+29
-8
@@ -2,6 +2,11 @@ import type { ErrorHash, MarkerData, State, ValidatedState } from '$lib/types';
|
||||
import { debounce } from 'lodash-es';
|
||||
import type { MermaidConfig } from 'mermaid';
|
||||
import { derived, get, writable, type Readable } from 'svelte/store';
|
||||
import {
|
||||
extractErrorLineText,
|
||||
findMostRelevantLineNumber,
|
||||
replaceLineNumberInErrorMessage
|
||||
} from './errorHandling';
|
||||
import { parse } from './mermaid';
|
||||
import { localStorage, persist } from './persist';
|
||||
import { deserializeState, serializeState } from './serde';
|
||||
@@ -67,18 +72,34 @@ const processState = async (state: State) => {
|
||||
console.error(error);
|
||||
if ('hash' in error) {
|
||||
try {
|
||||
const {
|
||||
loc: { first_line, last_line, first_column, last_column }
|
||||
let errorString = processed.error.toString();
|
||||
const errorLineText = extractErrorLineText(errorString);
|
||||
const realLineNumber = findMostRelevantLineNumber(errorLineText, state.code);
|
||||
|
||||
let first_line: number, last_line: number, first_column: number, last_column: number;
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
} = error.hash as ErrorHash;
|
||||
({ first_line, last_line, first_column, last_column } = (error.hash as ErrorHash).loc);
|
||||
} catch {
|
||||
const lineNo = findMostRelevantLineNumber(errorString, state.code);
|
||||
first_line = lineNo;
|
||||
last_line = lineNo + 1;
|
||||
first_column = 0;
|
||||
last_column = 0;
|
||||
}
|
||||
|
||||
if (realLineNumber !== -1) {
|
||||
errorString = replaceLineNumberInErrorMessage(errorString, realLineNumber);
|
||||
}
|
||||
|
||||
processed.error = new Error(errorString);
|
||||
const marker: MarkerData = {
|
||||
severity: 8, // Error
|
||||
startLineNumber: first_line,
|
||||
startLineNumber: realLineNumber,
|
||||
startColumn: first_column,
|
||||
endLineNumber: last_line,
|
||||
endColumn: last_column + 1,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
||||
message: error.str
|
||||
endLineNumber: last_line + (realLineNumber - first_line),
|
||||
endColumn: last_column + (first_column === last_column ? 0 : 5),
|
||||
message: errorString || 'Syntax error'
|
||||
};
|
||||
processed.errorMarkers = [marker];
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user