Update validateMetricYaml.tsx

This commit is contained in:
Nate Kelley 2025-04-04 11:57:07 -06:00
parent 675379c00b
commit 16c6ea1d26
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
1 changed files with 60 additions and 24 deletions

View File

@ -2,8 +2,7 @@ import React, { useRef } from 'react';
import * as yaml from 'js-yaml'; import * as yaml from 'js-yaml';
import * as monaco from 'monaco-editor'; import * as monaco from 'monaco-editor';
import { type editor } from 'monaco-editor/esm/vs/editor/editor.api'; import { type editor } from 'monaco-editor/esm/vs/editor/editor.api';
import { useEffect } from 'react'; import MonacoEditor from '@monaco-editor/react';
import MonacoEditor, { OnMount } from '@monaco-editor/react';
type IMarkerData = editor.IMarkerData; type IMarkerData = editor.IMarkerData;
@ -15,8 +14,22 @@ Siblings:
Jane: 25 Jane: 25
Jim: 28`; Jim: 28`;
// Helper function to find line number for a specific key in YAML content
const findLineNumberForKey = (content: string, key: string): number => {
const lines = content.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i].trim().startsWith(`${key}:`)) {
return i + 1; // Line numbers are 1-based
}
}
return 1; // Default to line 1 if not found
};
// Linting function that validates YAML content // Linting function that validates YAML content
export const validateMetricYaml = (content: string, monaco: any): IMarkerData[] => { export const validateMetricYaml = (
content: string,
monaco: typeof import('monaco-editor')
): IMarkerData[] => {
const markers: IMarkerData[] = []; const markers: IMarkerData[] = [];
let parsed: any; let parsed: any;
@ -24,12 +37,19 @@ export const validateMetricYaml = (content: string, monaco: any): IMarkerData[]
try { try {
parsed = yaml.load(content); parsed = yaml.load(content);
} catch (error: any) { } catch (error: any) {
// For parse errors, try to extract line information from the error message
let lineNumber = 1;
const lineMatch = error.message.match(/line (\d+)/i);
if (lineMatch && lineMatch[1]) {
lineNumber = parseInt(lineMatch[1], 10);
}
markers.push({ markers.push({
severity: monaco.MarkerSeverity.Error, severity: monaco.MarkerSeverity.Error,
message: 'Invalid YAML 🤣: ' + error.message, message: 'Invalid YAML 🤣: ' + error.message,
startLineNumber: 1, startLineNumber: lineNumber,
startColumn: 1, startColumn: 1,
endLineNumber: 1, endLineNumber: lineNumber,
endColumn: 1 endColumn: 1
}); });
return markers; return markers;
@ -55,13 +75,14 @@ export const validateMetricYaml = (content: string, monaco: any): IMarkerData[]
// Check for any unexpected keys // Check for any unexpected keys
keys.forEach((key) => { keys.forEach((key) => {
if (!allowedKeys.includes(key)) { if (!allowedKeys.includes(key)) {
const lineNumber = findLineNumberForKey(content, key);
markers.push({ markers.push({
severity: monaco.MarkerSeverity.Error, severity: monaco.MarkerSeverity.Error,
message: `Unexpected key "${key}". Only ${allowedKeys.join(', ')} are allowed.`, message: `Unexpected key "${key}". Only ${allowedKeys.join(', ')} are allowed.`,
startLineNumber: 1, startLineNumber: lineNumber,
startColumn: 1, startColumn: 1,
endLineNumber: 1, endLineNumber: lineNumber,
endColumn: 1 endColumn: content.split('\n')[lineNumber - 1]?.length || 1
}); });
} }
}); });
@ -82,39 +103,44 @@ export const validateMetricYaml = (content: string, monaco: any): IMarkerData[]
// Validate types for each field // Validate types for each field
if ('Person' in parsed && typeof parsed.Person !== 'string') { if ('Person' in parsed && typeof parsed.Person !== 'string') {
const lineNumber = findLineNumberForKey(content, 'Person');
markers.push({ markers.push({
severity: monaco.MarkerSeverity.Error, severity: monaco.MarkerSeverity.Error,
message: 'The "Person" field must be a string.', message: 'The "Person" field must be a string.',
startLineNumber: 1, startLineNumber: lineNumber,
startColumn: 1, startColumn: 1,
endLineNumber: 1, endLineNumber: lineNumber,
endColumn: 1 endColumn: content.split('\n')[lineNumber - 1]?.length || 1
}); });
} }
if ('Place' in parsed && typeof parsed.Place !== 'string') { if ('Place' in parsed && typeof parsed.Place !== 'string') {
const lineNumber = findLineNumberForKey(content, 'Place');
markers.push({ markers.push({
severity: monaco.MarkerSeverity.Error, severity: monaco.MarkerSeverity.Error,
message: 'The "Place" field must be a string.', message: 'The "Place" field must be a string.',
startLineNumber: 1, startLineNumber: lineNumber,
startColumn: 1, startColumn: 1,
endLineNumber: 1, endLineNumber: lineNumber,
endColumn: 1 endColumn: content.split('\n')[lineNumber - 1]?.length || 1
}); });
} }
if ('Age' in parsed && typeof parsed.Age !== 'number') { if ('Age' in parsed && typeof parsed.Age !== 'number') {
const lineNumber = findLineNumberForKey(content, 'Age');
markers.push({ markers.push({
severity: monaco.MarkerSeverity.Error, severity: monaco.MarkerSeverity.Error,
message: 'The "Age" field must be a number.', message: 'The "Age" field must be a number.',
startLineNumber: 1, startLineNumber: lineNumber,
startColumn: 1, startColumn: 1,
endLineNumber: 1, endLineNumber: lineNumber,
endColumn: 1 endColumn: content.split('\n')[lineNumber - 1]?.length || 1
}); });
} }
if ('Siblings' in parsed) { if ('Siblings' in parsed) {
const siblingsLineNumber = findLineNumberForKey(content, 'Siblings');
if ( if (
typeof parsed.Siblings !== 'object' || typeof parsed.Siblings !== 'object' ||
Array.isArray(parsed.Siblings) || Array.isArray(parsed.Siblings) ||
@ -123,22 +149,32 @@ export const validateMetricYaml = (content: string, monaco: any): IMarkerData[]
markers.push({ markers.push({
severity: monaco.MarkerSeverity.Error, severity: monaco.MarkerSeverity.Error,
message: 'The "Siblings" field must be an object with sibling name-age pairs.', message: 'The "Siblings" field must be an object with sibling name-age pairs.',
startLineNumber: 1, startLineNumber: siblingsLineNumber,
startColumn: 1, startColumn: 1,
endLineNumber: 1, endLineNumber: siblingsLineNumber,
endColumn: 1 endColumn: content.split('\n')[siblingsLineNumber - 1]?.length || 1
}); });
} else { } else {
// Validate that each siblings age is a number // Validate that each sibling's age is a number
const lines = content.split('\n');
Object.entries(parsed.Siblings).forEach(([siblingName, siblingAge]) => { Object.entries(parsed.Siblings).forEach(([siblingName, siblingAge]) => {
if (typeof siblingAge !== 'number') { if (typeof siblingAge !== 'number') {
// Look for the sibling in the content
let siblingLineNumber = siblingsLineNumber + 1; // Start after Siblings:
for (let i = siblingsLineNumber; i < lines.length; i++) {
if (lines[i].trim().startsWith(`${siblingName}:`)) {
siblingLineNumber = i + 1;
break;
}
}
markers.push({ markers.push({
severity: monaco.MarkerSeverity.Error, severity: monaco.MarkerSeverity.Error,
message: `The age for sibling "${siblingName}" must be a number.`, message: `The age for sibling "${siblingName}" must be a number.`,
startLineNumber: 1, startLineNumber: siblingLineNumber,
startColumn: 1, startColumn: 1,
endLineNumber: 1, endLineNumber: siblingLineNumber,
endColumn: 1 endColumn: lines[siblingLineNumber - 1]?.length || 1
}); });
} }
}); });