mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-01-15 03:44:31 +08:00
vite plugin checker seems to happily spawn a new linting process per file save, causing issues. This vibe coded solution kills the previously running process. It also splits linting into two steps to get some fast fail behavior. I (AI) tried to merge it into one file but the overlay refused to show that way. !nuf --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
126 lines
3.2 KiB
TypeScript
126 lines
3.2 KiB
TypeScript
// Oxlint overlay client-side code
|
|
let overlay: HTMLDivElement | null = null;
|
|
let hideTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
function createOverlay(): HTMLDivElement {
|
|
if (overlay) return overlay;
|
|
|
|
overlay = document.createElement("div");
|
|
overlay.id = "oxlint-error-overlay";
|
|
overlay.style.cssText = `
|
|
position: fixed;
|
|
bottom: 20px;
|
|
left: 20px;
|
|
background: #323437;
|
|
color: #e4dec8ff;
|
|
padding: 12px 16px;
|
|
border-radius: 8px;
|
|
font-family: 'Roboto Mono', monospace;
|
|
font-size: 14px;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
z-index: 10000;
|
|
display: none;
|
|
align-items: center;
|
|
gap: 8px;
|
|
cursor: pointer;
|
|
transition: opacity 0.2s ease;
|
|
`;
|
|
|
|
overlay.addEventListener("mouseenter", () => {
|
|
if (overlay) overlay.style.opacity = "0.5";
|
|
});
|
|
|
|
overlay.addEventListener("mouseleave", () => {
|
|
if (overlay) overlay.style.opacity = "1";
|
|
});
|
|
|
|
overlay.addEventListener("click", () => {
|
|
if (overlay) overlay.style.display = "none";
|
|
});
|
|
|
|
document.body.appendChild(overlay);
|
|
return overlay;
|
|
}
|
|
|
|
function updateOverlay(data: {
|
|
errorCount?: number;
|
|
warningCount?: number;
|
|
running?: boolean;
|
|
hadIssues?: boolean;
|
|
typeAware?: boolean;
|
|
}): void {
|
|
const overlayEl = createOverlay();
|
|
|
|
// Clear any pending hide timeout
|
|
if (hideTimeout !== null) {
|
|
clearTimeout(hideTimeout);
|
|
hideTimeout = null;
|
|
}
|
|
|
|
// Show running icon if linting is running and there were issues before
|
|
if (data.running) {
|
|
if (data.hadIssues) {
|
|
const message = data.typeAware ? "checking type aware..." : "checking...";
|
|
overlayEl.innerHTML = `
|
|
<span style="font-size: 18px;">⏳</span>
|
|
<span>oxlint: ${message}</span>
|
|
`;
|
|
overlayEl.style.display = "flex";
|
|
overlayEl.style.color = "#e4dec8ff";
|
|
} else {
|
|
overlayEl.style.display = "none";
|
|
}
|
|
return;
|
|
}
|
|
|
|
const { errorCount = 0, warningCount = 0, hadIssues = false } = data;
|
|
const total = errorCount + warningCount;
|
|
|
|
if (total > 0) {
|
|
overlayEl.innerHTML = `
|
|
<span style="font-size: 18px;">🚨</span>
|
|
<span>oxlint: ${errorCount} error${errorCount !== 1 ? "s" : ""}, ${warningCount} warning${warningCount !== 1 ? "s" : ""}</span>
|
|
`;
|
|
overlayEl.style.display = "flex";
|
|
|
|
if (errorCount > 0) {
|
|
overlayEl.style.color = "#e4dec8ff";
|
|
}
|
|
} else {
|
|
// Only show success if the previous lint had issues
|
|
if (hadIssues) {
|
|
overlayEl.innerHTML = `
|
|
<span style="font-size: 18px;">✅</span>
|
|
<span>oxlint: ok</span>
|
|
`;
|
|
overlayEl.style.display = "flex";
|
|
overlayEl.style.color = "#e4dec8ff";
|
|
|
|
// Hide after 3 seconds
|
|
hideTimeout = setTimeout(() => {
|
|
overlayEl.style.display = "none";
|
|
hideTimeout = null;
|
|
}, 3000);
|
|
} else {
|
|
// Two good lints in a row - don't show anything
|
|
overlayEl.style.display = "none";
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize overlay on load
|
|
createOverlay();
|
|
|
|
if (import.meta.hot) {
|
|
import.meta.hot.on(
|
|
"vite-plugin-oxlint",
|
|
(data: {
|
|
errorCount?: number;
|
|
warningCount?: number;
|
|
running?: boolean;
|
|
hadIssues?: boolean;
|
|
}) => {
|
|
updateOverlay(data);
|
|
},
|
|
);
|
|
}
|