Merge pull request #1300 from mermaid-js/sidv/errorHighlight

feat: Add error highlight
This commit is contained in:
Sidharth Vinod
2024-06-17 04:44:36 +00:00
committed by GitHub
3 changed files with 78 additions and 8 deletions
+2
View File
@@ -83,6 +83,8 @@ module.exports = {
env: true,
fn: true,
i: true,
j: true,
k: true,
param: true,
req: true,
res: true,
+47
View File
@@ -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
View File
@@ -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) {