diff --git a/webview/src/components/MetaschemaStackTrace.tsx b/webview/src/components/MetaschemaStackTrace.tsx
new file mode 100644
index 0000000..0973001
--- /dev/null
+++ b/webview/src/components/MetaschemaStackTrace.tsx
@@ -0,0 +1,122 @@
+import { useState } from "react";
+import type { MetaschemaError,Position } from "../../../protocol/cli";
+import { goToPosition } from "../message";
+
+interface Props {
+ errors: MetaschemaError[];
+}
+
+function ErrorBox({
+ error,
+ size,
+ indent
+}: {
+ error: MetaschemaError;
+ size?: 'primary' | 'stack';
+ indent: number;
+}) {
+ const clickable = Boolean(error.instancePosition);
+
+ return (
+
+ clickable && goToPosition(error.instancePosition as Position)
+ }
+ >
+
+ {size === 'stack' && (
+
↳
+ )}
+
+
+ {error.error}
+
+ {error.instanceLocation && (
+
+ {error.instanceLocation || "(root)"}
+
+ )}
+
+
+
+ );
+}
+
+
+export function MetaschemaStackTrace({errors}:Props){
+ const [expanded,setExpanded]= useState(false);
+
+ if(errors.length===0) return null;
+
+ const [primary, ...stack] = errors;
+
+ if (!primary) return null;
+
+ return (
+
+ {/* Top level error */}
+
+
+ {stack.length > 0 && (
+
+ )}
+
+ {/* Stack trace */}
+
+
+
+ {
+ stack.map((err,ind)=>{
+ const STACK_INDENT = 16;
+ return (
+
+ ↳
+
+
+ )
+ })
+ }
+
+
+
+
+ )
+}
+
+
diff --git a/webview/src/components/MetaschemaTab.tsx b/webview/src/components/MetaschemaTab.tsx
index 224c075..c40e75a 100644
--- a/webview/src/components/MetaschemaTab.tsx
+++ b/webview/src/components/MetaschemaTab.tsx
@@ -2,6 +2,7 @@ import type { MetaschemaResult, MetaschemaError, Position } from '../../../proto
import { goToPosition } from '../message';
import { RawOutput } from './RawOutput';
import { CheckCircle, AlertTriangle, FileQuestion } from 'lucide-react';
+import { MetaschemaStackTrace } from './MetaschemaStackTrace';
export interface MetaschemaTabProps {
metaschemaResult: MetaschemaResult;
@@ -55,55 +56,7 @@ export function MetaschemaTab({ metaschemaResult, noFileSelected }: MetaschemaTa
return (
- {metaschemaErrors.map((error, index) => (
-
error.instancePosition && handleGoToPosition(error.instancePosition)}
- >
-
-
- {error.instancePosition && (
-
-
- Location:
-
-
- Line {error.instancePosition[0]}, Col {error.instancePosition[1]}
-
-
- )}
- {error.instanceLocation && (
-
-
- Path:
-
-
- {error.instanceLocation || '(root)'}
-
-
- )}
- {error.keywordLocation && (
-
-
- Schema:
-
-
- {error.keywordLocation}
-
-
- )}
-
-
- ))}
+
@@ -128,12 +81,12 @@ export function MetaschemaTab({ metaschemaResult, noFileSelected }: MetaschemaTa
error && 'instancePosition' in error && error.instancePosition
? error.instancePosition
: null;
-
+
return (
<>
- (
+ items: T[],
+ containerWidth: number,
+ itemWidth: number,
+ gap: number
+): T[][] {
+ const itemsPerRow = Math.max(
+ 1,
+ Math.floor((containerWidth + gap) / (itemWidth + gap))
+ );
+
+ const rows: T[][] = [];
+ for (let i = 0; i < items.length; i += itemsPerRow) {
+ rows.push(items.slice(i, i + itemsPerRow));
+ }
+ return rows;
+}
+