style: biome formatting wave + clear web lint (selector order, safe list keys)

This commit is contained in:
noelorin 2026-09-27 12:57:49 +08:00
parent e3c275befa
commit 95962b4aa4
6 changed files with 54 additions and 46 deletions

View File

@ -730,10 +730,10 @@ function WatchInner(props: { locale: Locale; mediaItemId: string }) {
const active =
Math.abs(c.time - currentTime) < 0.5 ||
(c.time <= currentTime &&
(i === listComments.length - 1 ||
listComments[i + 1]!.time > currentTime));
(listComments[i + 1]?.time ??
Number.POSITIVE_INFINITY) > currentTime);
return (
<li key={`${c.time}-${c.rowId}-${i}`}>
<li key={`${c.time}-${c.rowId}`}>
<button
type="button"
className={cn(
@ -955,29 +955,33 @@ function WatchInner(props: { locale: Locale; mediaItemId: string }) {
)}
{sourceAnimeId == null &&
(sourceSearch.data?.animes.length ?? 0) > 0 && (
<ul className="space-y-1.5">
{(sourceSearch.data?.animes ?? []).map((a) => (
<li key={a.animeId}>
<button
type="button"
className="w-full rounded-md border border-border px-3 py-2 text-left text-sm hover:border-primary/60 hover:bg-primary/5"
onClick={() => setSourceAnimeId(a.animeId)}
>
<span className="font-medium">
{a.animeTitle ?? `#${a.animeId}`}
</span>
<span className="ml-2 text-xs text-muted-foreground">
{a.typeDescription ?? ""}
{a.episodeCount > 0 &&
` · ${t(locale, "watch.episodeCount", {
count: a.episodeCount,
})}`}
</span>
</button>
</li>
))}
</ul>
)}
<ul className="space-y-1.5">
{(sourceSearch.data?.animes ?? []).map((a) => (
<li key={a.animeId}>
<button
type="button"
className="w-full rounded-md border border-border px-3 py-2 text-left text-sm hover:border-primary/60 hover:bg-primary/5"
onClick={() => setSourceAnimeId(a.animeId)}
>
<span className="font-medium">
{a.animeTitle ?? `#${a.animeId}`}
</span>
<span className="ml-2 text-xs text-muted-foreground">
{a.typeDescription ?? ""}
{a.episodeCount > 0 &&
` · ${t(
locale,
"watch.episodeCount",
{
count: a.episodeCount,
},
)}`}
</span>
</button>
</li>
))}
</ul>
)}
{sourceAnimeId != null && (
<div className="space-y-2">

View File

@ -186,6 +186,17 @@ select {
font-variant-numeric: tabular-nums;
}
/* 组件内 u-mono 调整:置于 .u-linelink:hover 等更高特异性规则之前 */
.u-hud-strip .u-mono {
flex-shrink: 0;
}
.side-rail__link .u-mono {
font-size: 10px;
letter-spacing: 0.14em;
color: var(--ink-3);
}
.u-label {
font-family: var(--font-mono);
font-size: 10px;
@ -246,7 +257,9 @@ html.has-reveal .u-reveal.is-in {
opacity: 1;
transform: none;
}
/* island 内部不依赖 JS 加类:入场后直接显示,避免 hydration 冲突 */
/* island 内部不依赖 JS 加类:入场后直接显示,避免 hydration 冲突。
两条规则需按源序覆盖上一条的初始隐藏态,故不做特异性排序。 */
/* biome-ignore lint/style/noDescendingSpecificity: 源序覆盖是刻意的级联依赖 */
astro-island .u-reveal,
html.has-reveal astro-island .u-reveal {
opacity: 1;
@ -500,9 +513,6 @@ html.has-reveal astro-island .u-reveal {
font-size: 10px;
letter-spacing: 0.18em;
}
.u-hud-strip .u-mono {
flex-shrink: 0;
}
/* —— 左侧固定竖栏 —— */
.side-rail {
@ -572,11 +582,6 @@ html.has-reveal astro-island .u-reveal {
color 0.2s ease,
border-color 0.2s ease;
}
.side-rail__link .u-mono {
font-size: 10px;
letter-spacing: 0.14em;
color: var(--ink-3);
}
.side-rail__link:hover,
.side-rail__link:focus-visible {
background: color-mix(in srgb, var(--edge) 8%, transparent);

View File

@ -164,7 +164,9 @@ function parseAnime(a: RawAnime): OpenAnimeBrief | null {
type: a.type ?? null,
typeDescription: a.typeDescription ?? null,
imageUrl: a.imageUrl ?? null,
episodes: (a.episodes ?? []).map(parseEpisode).filter((x): x is OpenEpisodeBrief => x != null),
episodes: (a.episodes ?? [])
.map(parseEpisode)
.filter((x): x is OpenEpisodeBrief => x != null),
};
}

View File

@ -17,5 +17,9 @@ export { danmakuPrefs } from "./danmaku-prefs.js";
export type { DanmakuPrefsRow, NewDanmakuPrefsRow } from "./danmaku-prefs.js";
export { danmakuDocs } from "./danmaku-docs.js";
export type { DanmakuDocRow, NewDanmakuDocRow } from "./danmaku-docs.js";
export { appSettings, APP_SETTING_OPEN_DANMAKU_APP_ID, APP_SETTING_OPEN_DANMAKU_APP_SECRET } from "./app-settings.js";
export {
appSettings,
APP_SETTING_OPEN_DANMAKU_APP_ID,
APP_SETTING_OPEN_DANMAKU_APP_SECRET,
} from "./app-settings.js";
export type { AppSettingRow, NewAppSettingRow } from "./app-settings.js";

View File

@ -7,11 +7,7 @@ import {
openMatch,
rankCandidates,
} from "@app/danmaku";
import {
parseEpisodeFromFilename,
type BatchResult,
type DanmakuMatchOutput,
} from "@app/types";
import { parseEpisodeFromFilename, type BatchResult, type DanmakuMatchOutput } from "@app/types";
import { remoteFileHash } from "./danmaku.service.js";
/** 集数解析统一走 @app/types(前后端共用同一套正则);此处再导出保持旧入口可用 */

View File

@ -1,7 +1,4 @@
import {
APP_SETTING_OPEN_DANMAKU_APP_ID,
APP_SETTING_OPEN_DANMAKU_APP_SECRET,
} from "@app/models";
import { APP_SETTING_OPEN_DANMAKU_APP_ID, APP_SETTING_OPEN_DANMAKU_APP_SECRET } from "@app/models";
import { appSettingsDao } from "@app/dao";
import type { OpenNetworkSettingsOutput, SaveOpenNetworkSettingsInput } from "@app/types";
import { setOpenCredentials, type OpenCredentials } from "@app/danmaku";