mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Add ESLint + pre-commit hook and fix the issues it surfaced
This commit is contained in:
@@ -36,50 +36,54 @@ export function LivePreview() {
|
||||
if (!node) return;
|
||||
const text = draftText.trim();
|
||||
|
||||
const timer = setTimeout(async () => {
|
||||
// Empty/blank is not an error — clean, empty pane (spec §04).
|
||||
if (text === '') {
|
||||
handleRef.current?.destroy();
|
||||
handleRef.current = null;
|
||||
setError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(text);
|
||||
} catch (e) {
|
||||
setError(`Invalid JSON: ${(e as Error).message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const mine = ++generationRef.current;
|
||||
try {
|
||||
const prepared = prepareSpecForRender(parsed, { fitMode: 'default' });
|
||||
const config = chartConfigFor(uiTheme);
|
||||
handleRef.current?.destroy();
|
||||
handleRef.current = null;
|
||||
const handle = await renderSpec(node, prepared as VisualizationSpec, config);
|
||||
if (mine !== generationRef.current) {
|
||||
// TODO: a superseded render's destroy() calls node.replaceChildren(),
|
||||
// which can blank the live chart if two embeds on the same node are
|
||||
// ever in flight at once (heavy spec whose embed outlasts the 300ms
|
||||
// debounce). The debounce makes this rare in M1; when fit-mode/dataset
|
||||
// work (M2/M3) lands, serialize renders or finalize the stale view
|
||||
// without clearing the shared node.
|
||||
handle.destroy(); // a newer render superseded this one
|
||||
// The debounced body is async; wrap in a void IIFE so the timer callback
|
||||
// returns void (it handles its own errors internally — nothing awaits it).
|
||||
const timer = setTimeout(() => {
|
||||
void (async () => {
|
||||
// Empty/blank is not an error — clean, empty pane (spec §04).
|
||||
if (text === '') {
|
||||
handleRef.current?.destroy();
|
||||
handleRef.current = null;
|
||||
setError(null);
|
||||
return;
|
||||
}
|
||||
handleRef.current = handle;
|
||||
setError(null);
|
||||
} catch (e) {
|
||||
if (mine === generationRef.current) {
|
||||
setError(
|
||||
`Rendering error: ${(e as Error).message}. ` +
|
||||
`Check your JSON syntax and that the spec is valid Vega-Lite.`,
|
||||
);
|
||||
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(text);
|
||||
} catch (e) {
|
||||
setError(`Invalid JSON: ${(e as Error).message}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const mine = ++generationRef.current;
|
||||
try {
|
||||
const prepared = prepareSpecForRender(parsed, { fitMode: 'default' });
|
||||
const config = chartConfigFor(uiTheme);
|
||||
handleRef.current?.destroy();
|
||||
handleRef.current = null;
|
||||
const handle = await renderSpec(node, prepared as VisualizationSpec, config);
|
||||
if (mine !== generationRef.current) {
|
||||
// TODO: a superseded render's destroy() calls node.replaceChildren(),
|
||||
// which can blank the live chart if two embeds on the same node are
|
||||
// ever in flight at once (heavy spec whose embed outlasts the 300ms
|
||||
// debounce). The debounce makes this rare in M1; when fit-mode/dataset
|
||||
// work (M2/M3) lands, serialize renders or finalize the stale view
|
||||
// without clearing the shared node.
|
||||
handle.destroy(); // a newer render superseded this one
|
||||
return;
|
||||
}
|
||||
handleRef.current = handle;
|
||||
setError(null);
|
||||
} catch (e) {
|
||||
if (mine === generationRef.current) {
|
||||
setError(
|
||||
`Rendering error: ${(e as Error).message}. ` +
|
||||
`Check your JSON syntax and that the spec is valid Vega-Lite.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, RENDER_DEBOUNCE_MS);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
|
||||
Reference in New Issue
Block a user