style(frontend): Prettier config + one-time repo-wide format pass
Prettier 3 (pinned), printWidth 100, double quotes — chosen to match the existing hand-formatting and minimise reflow. This commit is ONLY the mechanical format pass (`prettier --write`) plus the config/ignore/scripts, isolated so it never pollutes a feature diff. Verified behaviour-neutral: typecheck, eslint (0 errors), and vitest all green before and after. See .git-blame-ignore-revs — `git blame` skips this sha.
This commit is contained in:
@@ -14,9 +14,7 @@ const INLINE_RE =
|
||||
|
||||
function tsToSeconds(ts: string): number {
|
||||
const parts = ts.split(":").map((n) => parseInt(n, 10));
|
||||
return parts.length === 3
|
||||
? parts[0] * 3600 + parts[1] * 60 + parts[2]
|
||||
: parts[0] * 60 + parts[1];
|
||||
return parts.length === 3 ? parts[0] * 3600 + parts[1] * 60 + parts[2] : parts[0] * 60 + parts[1];
|
||||
}
|
||||
|
||||
// Parse a YouTube `t`/`start` param: "90", "90s", or "1h2m3s".
|
||||
@@ -26,9 +24,7 @@ function parseStart(t: string | null): number | null {
|
||||
const m = t.match(/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/);
|
||||
if (!m) return null;
|
||||
const total =
|
||||
parseInt(m[1] || "0", 10) * 3600 +
|
||||
parseInt(m[2] || "0", 10) * 60 +
|
||||
parseInt(m[3] || "0", 10);
|
||||
parseInt(m[1] || "0", 10) * 3600 + parseInt(m[2] || "0", 10) * 60 + parseInt(m[3] || "0", 10);
|
||||
return total || null;
|
||||
}
|
||||
|
||||
@@ -62,7 +58,7 @@ export function renderDescription(
|
||||
onSeek: (seconds: number) => void;
|
||||
onLoadVideo: (id: string, start: number | null) => void;
|
||||
t: TFunction;
|
||||
}
|
||||
},
|
||||
): ReactNode[] {
|
||||
const { t } = opts;
|
||||
const out: ReactNode[] = [];
|
||||
@@ -70,7 +66,10 @@ export function renderDescription(
|
||||
const linkCls = "text-accent hover:underline break-all";
|
||||
// Tidy YouTube descriptions: drop trailing spaces and remove blank lines entirely
|
||||
// (they're just noise in the popover), keeping single line breaks.
|
||||
const clean = text.replace(/[ \t]+\n/g, "\n").replace(/\n{2,}/g, "\n").trim();
|
||||
const clean = text
|
||||
.replace(/[ \t]+\n/g, "\n")
|
||||
.replace(/\n{2,}/g, "\n")
|
||||
.trim();
|
||||
for (const chunk of clean.split(URL_RE)) {
|
||||
if (/^https?:\/\//.test(chunk)) {
|
||||
const href = chunk.replace(/[.,;:!?)\]]+$/, "");
|
||||
@@ -87,13 +86,13 @@ export function renderDescription(
|
||||
title={sameVideo ? t("player.jumpToTime") : t("player.playInApp")}
|
||||
>
|
||||
{href}
|
||||
</button>
|
||||
</button>,
|
||||
);
|
||||
} else {
|
||||
out.push(
|
||||
<a key={key++} href={href} target="_blank" rel="noreferrer" className={linkCls}>
|
||||
{href}
|
||||
</a>
|
||||
</a>,
|
||||
);
|
||||
}
|
||||
continue;
|
||||
@@ -110,9 +109,10 @@ export function renderDescription(
|
||||
out.push(
|
||||
<a key={key++} href={`mailto:${email}`} className={linkCls}>
|
||||
{email}
|
||||
</a>
|
||||
</a>,
|
||||
);
|
||||
if (m[1].length > email.length) out.push(<span key={key++}>{m[1].slice(email.length)}</span>);
|
||||
if (m[1].length > email.length)
|
||||
out.push(<span key={key++}>{m[1].slice(email.length)}</span>);
|
||||
} else if (m[2]) {
|
||||
// Hashtag → YouTube's hashtag feed (mirrors native YouTube behavior).
|
||||
const tag = m[2].slice(1);
|
||||
@@ -125,7 +125,7 @@ export function renderDescription(
|
||||
className={linkCls}
|
||||
>
|
||||
{m[2]}
|
||||
</a>
|
||||
</a>,
|
||||
);
|
||||
} else {
|
||||
const ts = m[3];
|
||||
@@ -136,7 +136,7 @@ export function renderDescription(
|
||||
className="text-accent hover:underline"
|
||||
>
|
||||
{ts}
|
||||
</button>
|
||||
</button>,
|
||||
);
|
||||
}
|
||||
last = m.index + m[0].length;
|
||||
|
||||
Reference in New Issue
Block a user