v0.10.5 首页 H2 产品线入口 ×6:ImageBoxWidget 重构为 Elementor 忠实 DOM + slim 白名单补齐 + H2 scoped CSS(post-18 对齐,桌面/移动/hover 实测一致)

This commit is contained in:
BigCode
2026-11-01 00:15:29 +08:00
commit 5b83e71ad9
128 changed files with 20008 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
/**
* # 模块 全局请求中间件:旧链接 301/302 重定向
* 在 router 请求阶段查 redirects 表:先精确匹配(findRedirect),
* 再对 is_regex 的条目做正则匹配;命中即返回 301/302 Response。
* 正则条目内存缓存 60 秒,避免每请求全表扫描。
*/
import { createMiddleware } from "@tanstack/react-start";
import { db } from "~/db";
import { redirects } from "~/db/schema";
import { and, eq, sql } from "drizzle-orm";
import { hasPublishedSlug, resolveRedirect } from "./data";
/** # 类型 已启用的正则重定向条目(缓存行) **/
type RegexEntry = { source: string; target: string; code: number };
/** # 成员变量 正则重定向缓存 **/
let regexCache: { entries: RegexEntry[]; fetchedAt: number } | null = null;
const REGEX_CACHE_TTL = 60_000;
/** # 函数 读取启用的正则重定向条目(带缓存) */
async function getRegexEntries(): Promise<RegexEntry[]> {
if (regexCache && Date.now() - regexCache.fetchedAt < REGEX_CACHE_TTL) return regexCache.entries;
const rows = await db
.select({ source: redirects.source, target: redirects.target, code: redirects.code })
.from(redirects)
.where(and(eq(redirects.isRegex, true), eq(redirects.enabled, true)));
regexCache = { entries: rows, fetchedAt: Date.now() };
return rows;
}
/** # 函数 命中计数(fire-and-forget,不阻塞响应) */
function bumpHits(id: number) {
db.update(redirects)
.set({ hits: sql`${redirects.hits} + 1` })
.where(eq(redirects.id, id))
.catch(() => {});
}
/** # 函数 请求重定向中间件
* 仅处理 router 类型请求;路径先带斜杠再无斜杠各查一次精确匹配。
*/
export const redirectMiddleware = createMiddleware({ type: "request" }).server(async ({ request, pathname, next, handlerType }) => {
// server function RPC 与静态资源不查重定向
if (handlerType !== "router") return next();
const path = decodeURI(pathname).replace(/\/+$/, "") || "/";
// 1) 链式解析(原样/规范化/带斜杠变体依次匹配,自指规则跳过防死循环)。
// 内容优先:路径末段能命中已发布内容时直接出内容不重定向(与 sitemap 的
// canonical 一致;导入的重定向表存在 A→B 且 B→A 的矛盾规则对,内容优先可破环)
const resolved = await resolveRedirect(path);
if (resolved) {
const lastSeg = path.split("/").filter(Boolean).pop() ?? "";
if (!(await hasPublishedSlug(decodeURIComponent(lastSeg)).catch(() => false))) {
return toRedirect(request, resolved.target, resolved.code, resolved.id);
}
}
// 2) 正则匹配(目标里的 $1..$9 替换为捕获组;部分条目匹配带查询串的完整路径)
const search = new URL(request.url).search;
const full = path + search;
const entries = await getRegexEntries();
for (const entry of entries) {
try {
const re = new RegExp(entry.source);
const m = re.exec(path) ?? re.exec(pathname) ?? re.exec(full);
if (m) return toRedirect(request, entry.target, entry.code, undefined, m);
} catch {
// 非法正则跳过
}
}
return next();
});
/** # 函数 构造重定向响应(相对目标解析为绝对 URL;$n 替换捕获组) */
function toRedirect(request: Request, target: string, code: number, id?: number, match?: RegExpExecArray): Response {
let dest = target;
if (match) {
dest = target.replace(/\$(\d)/g, (_, d: string) => match[Number(d)] ?? "");
}
if (id) bumpHits(id);
const abs = new URL(dest, request.url).toString();
const headers = new Headers({ location: abs });
return new Response(null, { status: code, headers });
}