feat: 书库导入导出/图片变体/书籍搜索/小组件运行时等

新增:
- 书库导入导出(library_import/library_export)及测试
- 图片变体生成(image_variants)与响应式图片(responsiveImage)
- 书籍搜索(bookSearch)+ BookSearch/LibrarySearchGrid 组件
- 小组件运行时(widgetRuntime)与静态检查(widgetLint)
- 上传缓存中间件(upload_cache)与字体 CSS 提取脚本

其它:
- 后端 handlers/services 全量调整
- 前端页面、组件、库函数与配置更新
This commit is contained in:
2026-10-01 03:06:05 +08:00
parent 7fbd6ba699
commit ff2ab286fb
141 changed files with 7527 additions and 1407 deletions

View File

@@ -1,5 +1,5 @@
import { absoluteCanonical, resolveSiteOrigin, type QueryBag } from "./siteUrl.ts";
import { postPath, userPath, type UrlStyle } from "./urlStyle.ts";
import { postPath, userPath, commentAnchor, type UrlStyle } from "./urlStyle.ts";
/** 防止用户正文里的 </script> 提前闭合 JSON-LD 脚本 */
export function serializeJsonLd(data: unknown): string {
@@ -88,13 +88,17 @@ export function listingJsonLd(input: {
export type JsonLdVisibleComment = {
id: number;
/** 帖内相对楼层号;评论 URL 锚点使用它而非全局评论 ID */
floor: number;
/** 楼中楼回复需 -r{id} 精确锚定;楼层评论可缺省(默认 true) */
is_root?: boolean;
content: string;
created_at: string;
author?: JsonLdPerson;
};
function commentUrl(entityUrl: string, id: number): string {
return `${entityUrl}#comment-${id}`;
function commentUrl(entityUrl: string, c: JsonLdVisibleComment): string {
return `${entityUrl}${commentAnchor(c.floor, c.is_root ?? true, c.id)}`;
}
/** 问答帖:一问多答。只收录当前页可见楼层,不把折叠回复或未展示评论写进去。 */
@@ -124,7 +128,7 @@ export function questionJsonLd(input: {
"@type": "Answer" as const,
text: a.content,
dateCreated: a.created_at,
url: commentUrl(entityUrl, a.id),
url: commentUrl(entityUrl, a),
...(a.author ? { author: personNode(a.author, urlStyle) } : {}),
});
return {
@@ -208,7 +212,7 @@ export function discussionJsonLd(input: {
"@type": "Comment",
text: c.content,
dateCreated: c.created_at,
url: commentUrl(entityUrl, c.id),
url: commentUrl(entityUrl, c),
...(c.author ? { author: personNode(c.author, urlStyle) } : {}),
})),
}