Fix real Biome bugs: inner declarations, dup keys, assign-in-expr, implicit any, cookie, a11y svg/keyboard, json
Local Build and Deploy / deploy (push) Successful in 51s

This commit is contained in:
openhands committed 2026-07-14 18:58:40 +02:00
1 parent 8d5c8ec96f
commit 59b63d6e70
19 files changed
+76 -44

No files matched your search

+18 -10
View File
@@ -1,14 +1,22 @@
(() => { (() => {
let theme: string | null = null;
let defaultDark = false;
let navbarColor: string | null = null;
let navbarTextColor: string | null = null;
try { try {
var s = localStorage.getItem("theme"); theme = localStorage.getItem("theme");
var dd = document.querySelector('meta[name="theme-default-dark"]'); const dd = document.querySelector('meta[name="theme-default-dark"]');
var defaultDark = dd ? dd.getAttribute("content") === "true" : false; defaultDark = dd ? dd.getAttribute("content") === "true" : false;
if (s === "dark" || (!s && defaultDark)) navbarColor = localStorage.getItem("navbarColor");
document.documentElement.classList.add("dark"); navbarTextColor = localStorage.getItem("navbarTextColor");
var nc = localStorage.getItem("navbarColor"),
nt = localStorage.getItem("navbarTextColor");
if (nc) document.documentElement.style.setProperty("--color-navbar", nc);
if (nt)
document.documentElement.style.setProperty("--color-navbar-text", nt);
} catch (_e) {} } catch (_e) {}
if (theme === "dark" || (!theme && defaultDark))
document.documentElement.classList.add("dark");
if (navbarColor)
document.documentElement.style.setProperty("--color-navbar", navbarColor);
if (navbarTextColor)
document.documentElement.style.setProperty(
"--color-navbar-text",
navbarTextColor,
);
})(); })();
+13
View File
@@ -0,0 +1,13 @@
"use server";
import { cookies } from "next/headers";
export async function setLocaleCookie(code: string): Promise<void> {
const store = await cookies();
store.set("NEXT_LOCALE", code, {
path: "/",
maxAge: 31536000,
sameSite: "strict",
secure: true,
});
}
+3 -1
View File
@@ -48,7 +48,9 @@ export default async function AdminHousekeeping({
.split(",") .split(",")
.map((i) => Number(i.trim())) .map((i) => Number(i.trim()))
.filter((i) => !Number.isNaN(i)); .filter((i) => !Number.isNaN(i));
importIds.forEach((id) => selectedIds.add(id)); importIds.forEach((id) => {
selectedIds.add(id);
});
} }
} }
+1 -1
View File
@@ -41,7 +41,7 @@ export function PollForm({ defaultValues }: PollFormProps) {
// biome-ignore lint/suspicious/noExplicitAny: explicitly chosen here, see surrounding code // biome-ignore lint/suspicious/noExplicitAny: explicitly chosen here, see surrounding code
function onSubmit(data: any) { function onSubmit(data: any) {
if (isEditing) { if (isEditing) {
run(() => updatePoll({ id: defaultValues?.id!, ...data }), { run(() => updatePoll({ id: defaultValues!.id, ...data }), {
successMessage: "Poll updated!", successMessage: "Poll updated!",
}); });
} else { } else {
+1 -1
View File
@@ -78,7 +78,7 @@ export default async function AdminRadioApiKeysPage() {
<Link href="/admin/radio/autodj">{t("autoDj")}</Link> ·{" "} <Link href="/admin/radio/autodj">{t("autoDj")}</Link> ·{" "}
<Link href="/admin/radio/embed">{t("embed")}</Link> ·{" "} <Link href="/admin/radio/embed">{t("embed")}</Link> ·{" "}
<Link href="/admin/radio/points">{t("points")}</Link> ·{" "} <Link href="/admin/radio/points">{t("points")}</Link> ·{" "}
<Link href="/admin/radio/monitoring">{t("monitoring")}</Link> <Link href="/admin/radio/monitoring">{t("monitoring.title")}</Link>
</nav> </nav>
<section className="mt-6"> <section className="mt-6">
+1 -1
View File
@@ -137,7 +137,7 @@ export default async function AdminRadioAutoDjPage() {
htmlFor="new_title" htmlFor="new_title"
style={{ display: "block", fontWeight: 700 }} style={{ display: "block", fontWeight: 700 }}
> >
{t("autoDjForm.title")} {t("autoDjForm.trackTitle")}
</label> </label>
<input <input
id="new_title" id="new_title"
+4 -2
View File
@@ -9,11 +9,13 @@ import {
captureOrder, captureOrder,
creditsPerUnit, creditsPerUnit,
isPayPalConfigured, isPayPalConfigured,
type CaptureResult,
} from "@/lib/services/paypal"; } from "@/lib/services/paypal";
import { import {
authorizeTopupCapture, authorizeTopupCapture,
claimTopupDelivery, claimTopupDelivery,
TopupCaptureError, TopupCaptureError,
type AuthorizedTopup,
} from "@/lib/services/paypal-topup"; } from "@/lib/services/paypal-topup";
import { rcon } from "@/lib/services/rcon"; import { rcon } from "@/lib/services/rcon";
import { sendCurrency } from "@/lib/services/send-currency"; import { sendCurrency } from "@/lib/services/send-currency";
@@ -72,7 +74,7 @@ export async function POST(req: Request): Promise<Response> {
// The create endpoint records ownership before returning the approval URL. // The create endpoint records ownership before returning the approval URL.
// Do not let a signed-in user submit somebody else's approved order id. // Do not let a signed-in user submit somebody else's approved order id.
let authorized; let authorized: AuthorizedTopup;
try { try {
authorized = await authorizeTopupCapture( authorized = await authorizeTopupCapture(
userId, userId,
@@ -138,7 +140,7 @@ export async function POST(req: Request): Promise<Response> {
} }
} }
let result; let result: CaptureResult;
try { try {
result = await captureOrder(orderId); result = await captureOrder(orderId);
} catch (e) { } catch (e) {
+1 -1
View File
@@ -8,7 +8,7 @@ import { useEffect } from "react";
* stays), shows a friendly card, and offers a reset. The raw error is logged to * stays), shows a friendly card, and offers a reset. The raw error is logged to
* the console, never shown to the user. * the console, never shown to the user.
*/ */
export default function Error({ export default function ErrorPage({
error, error,
reset, reset,
}: { }: {
+6 -2
View File
@@ -205,7 +205,9 @@ summary,
letter-spacing: 0.03em; letter-spacing: 0.03em;
text-transform: uppercase; text-transform: uppercase;
white-space: nowrap; white-space: nowrap;
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out; transition:
color 0.15s ease-in-out,
background-color 0.15s ease-in-out;
border-radius: 0.5rem; border-radius: 0.5rem;
} }
.nav-item:hover { .nav-item:hover {
@@ -223,7 +225,9 @@ summary,
.dropdown-item { .dropdown-item {
@apply block py-2.5 px-4 text-sm font-semibold rounded-lg mx-1; @apply block py-2.5 px-4 text-sm font-semibold rounded-lg mx-1;
color: var(--color-dropdown-text-readable, var(--color-text-readable)); color: var(--color-dropdown-text-readable, var(--color-text-readable));
transition: background-color 0.1s ease-in-out, color 0.1s ease-in-out; transition:
background-color 0.1s ease-in-out,
color 0.1s ease-in-out;
} }
.dropdown-item:hover { .dropdown-item:hover {
background-color: color-mix(in srgb, var(--color-primary) 12%, transparent); background-color: color-mix(in srgb, var(--color-primary) 12%, transparent);
+6 -5
View File
@@ -117,11 +117,12 @@ export default async function HelpCategoryPage({
/> />
) : null} ) : null}
{/* content is author-supplied HTML — sanitised server-side. */} {/* content is author-supplied HTML — sanitised server-side. */}
<div {/* biome-ignore lint/security/noDangerouslySetInnerHtml: sanitised article body */}
style={{ lineHeight: 1.7 }} <div
dangerouslySetInnerHTML={{ __html: sanitize(content) }} style={{ lineHeight: 1.7 }}
/> dangerouslySetInnerHTML={{ __html: sanitize(content) }}
/>
{hasButton ? ( {hasButton ? (
<div style={{ clear: "both", marginTop: "1rem" }}> <div style={{ clear: "both", marginTop: "1rem" }}>
+2 -2
View File
@@ -1,6 +1,6 @@
import Link from "next/link"; import Link from "next/link";
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
import type { CSSProperties } from "react"; import type { CSSProperties, ReactNode } from "react";
import { claimReferral } from "@/actions/referral"; import { claimReferral } from "@/actions/referral";
import { import {
ContentCard, ContentCard,
@@ -70,7 +70,7 @@ export default async function MePage({
const { claimed, error } = await searchParams; const { claimed, error } = await searchParams;
let content; let content: ReactNode;
try { try {
// --- Account + reward config ----------------------------------------- // --- Account + reward config -----------------------------------------
const [user, imagerBase, neededRaw, amountRaw, currencyRaw] = const [user, imagerBase, neededRaw, amountRaw, currencyRaw] =
+5 -2
View File
@@ -5,6 +5,7 @@ import Image from "next/image";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useLocale } from "next-intl"; import { useLocale } from "next-intl";
import { useEffect, useMemo, useRef, useState, useTransition } from "react"; import { useEffect, useMemo, useRef, useState, useTransition } from "react";
import { setLocaleCookie } from "@/actions/set-locale";
const LOCALES: { code: string; label: string; lang: string }[] = [ const LOCALES: { code: string; label: string; lang: string }[] = [
{ code: "nl", label: "Nederlands", lang: "nl" }, { code: "nl", label: "Nederlands", lang: "nl" },
@@ -66,8 +67,10 @@ export function LanguageSwitcher() {
function switchLocale(code: string) { function switchLocale(code: string) {
if (code === locale) return; if (code === locale) return;
document.cookie = `NEXT_LOCALE=${code};path=/;max-age=31536000;samesite=strict;secure`; startTransition(async () => {
startTransition(() => router.refresh()); await setLocaleCookie(code);
router.refresh();
});
setOpen(false); setOpen(false);
} }
+3 -5
View File
@@ -1,8 +1,7 @@
"use client"; "use client";
import { type ReactNode, useRef } from "react";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import { type ReactNode, useRef } from "react";
interface MobileNavProps { interface MobileNavProps {
children: ReactNode; children: ReactNode;
@@ -37,7 +36,7 @@ export function MobileNav({
hover:bg-[color-mix(in_srgb,var(--color-primary)_12%,transparent)] hover:bg-[color-mix(in_srgb,var(--color-primary)_12%,transparent)]
active:scale-[0.96] active:scale-[0.96]
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary-readable,var(--color-primary))] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-navbar)]" focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary-readable,var(--color-primary))] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-navbar)]"
aria-label={"Menu"} aria-label={menuLabel}
> >
<svg <svg
className="w-6 h-6 details-open:hidden" className="w-6 h-6 details-open:hidden"
@@ -97,8 +96,7 @@ export function MobileNav({
<span <span
className="text-sm font-extrabold uppercase tracking-wide" className="text-sm font-extrabold uppercase tracking-wide"
style={{ style={{
color: color: "var(--color-navbar-text-readable, var(--color-text))",
"var(--color-navbar-text-readable, var(--color-text))",
}} }}
> >
{brandLabel} {brandLabel}
+1 -1
View File
@@ -1,5 +1,5 @@
import Image from "next/image"; import Image from "next/image";
import { type ReactNode } from "react"; import type { ReactNode } from "react";
interface NavDropdownProps { interface NavDropdownProps {
label: string; label: string;
+6 -2
View File
@@ -14,7 +14,8 @@ function Currency({
amount: number; amount: number;
label: string; label: string;
}) { }) {
const textColor = "var(--color-navbar-text-readable, var(--color-navbar-text))"; const textColor =
"var(--color-navbar-text-readable, var(--color-navbar-text))";
const valueColor = const valueColor =
"var(--color-navbar-text-readable, var(--color-navbar-text, var(--color-text)))"; "var(--color-navbar-text-readable, var(--color-navbar-text, var(--color-text)))";
@@ -24,7 +25,10 @@ function Currency({
className={`h-[20px] w-[20px] sm:h-[25px] sm:w-[25px] rounded-full outline-offset-[3px] ${icon}`} className={`h-[20px] w-[20px] sm:h-[25px] sm:w-[25px] rounded-full outline-offset-[3px] ${icon}`}
/> />
<div style={{ color: textColor }}> <div style={{ color: textColor }}>
<span className="font-semibold text-xs sm:text-sm" style={{ color: valueColor }}> <span
className="font-semibold text-xs sm:text-sm"
style={{ color: valueColor }}
>
{amount.toLocaleString()} {amount.toLocaleString()}
</span>{" "} </span>{" "}
<span className="hidden sm:inline text-xs">{label}</span> <span className="hidden sm:inline text-xs">{label}</span>
+1 -1
View File
@@ -152,5 +152,5 @@ export class DbService {
} }
} }
export const db = globalForDb._db ?? (globalForDb._db = new DbService()); export const db = globalForDb._db ?? new DbService();
if (env.NODE_ENV !== "production") globalForDb._db = db; if (env.NODE_ENV !== "production") globalForDb._db = db;
+2 -3
View File
@@ -22,9 +22,8 @@ function createRedis(): Redis | null {
} }
export const redis: Redis | null = export const redis: Redis | null =
globalForRedis.redis !== undefined globalForRedis.redis !== undefined ? globalForRedis.redis : createRedis();
? globalForRedis.redis if (globalForRedis.redis === undefined) globalForRedis.redis = redis;
: (globalForRedis.redis = createRedis());
export async function withRedis<T>( export async function withRedis<T>(
fallback: () => Promise<T>, fallback: () => Promise<T>,
+1 -2
View File
@@ -1462,7 +1462,6 @@
"apiKeys": "API Keys", "apiKeys": "API Keys",
"points": "Points", "points": "Points",
"autoDj": "AutoDJ", "autoDj": "AutoDJ",
"monitoring": "Monitoring",
"user": "User", "user": "User",
"message": "Message", "message": "Message",
"posted": "Posted", "posted": "Posted",
@@ -1652,7 +1651,7 @@
"active": "Active", "active": "Active",
"inactive": "Inactive", "inactive": "Inactive",
"addTrack": "Add track", "addTrack": "Add track",
"title": "Title", "trackTitle": "Title",
"titlePlaceholder": "Track title", "titlePlaceholder": "Track title",
"artist": "Artist", "artist": "Artist",
"album": "Album", "album": "Album",
+1 -2
View File
@@ -1462,7 +1462,6 @@
"apiKeys": "API-sleutels", "apiKeys": "API-sleutels",
"points": "Punten", "points": "Punten",
"autoDj": "AutoDJ", "autoDj": "AutoDJ",
"monitoring": "Monitoring",
"user": "User", "user": "User",
"message": "Message", "message": "Message",
"posted": "Posted", "posted": "Posted",
@@ -1652,7 +1651,7 @@
"active": "Active", "active": "Active",
"inactive": "Inactive", "inactive": "Inactive",
"addTrack": "Add track", "addTrack": "Add track",
"title": "Title", "trackTitle": "Title",
"titlePlaceholder": "Track title", "titlePlaceholder": "Track title",
"artist": "Artist", "artist": "Artist",
"album": "Album", "album": "Album",