|
|
6ce8915e6c
|
fix(editor): 修复 focus() 把源码视图滚动到底部
切换到源码模式时 sourceTextarea.focus() 会触发浏览器将光标
所在行滚动进可视区域,光标默认在内容末尾,导致 textarea 被
拉到底部覆盖已设的滚动位置。改为 focus 后立即恢复 scrollTop。
同时移除调试日志。
|
2026-06-16 16:13:46 +08:00 |
|
|
|
ae6d80c9cc
|
fix(editor): 修复滚动比例同步失效导致切换到底部
原 syncScrollRatio 封装在 display:'none' 之后重复读取源容器
scrollTop,此时浏览器已将其归零,导致比例计算为 0。改为提前
读取比例并直接应用,移除二次封装与调试日志。
|
2026-06-16 15:58:50 +08:00 |
|
|
|
914f168551
|
fix(editor): 切换视图时按滚动比例同步位置
修复切回富文本时编辑器滚动到底部的问题:移除 commands.focus()
(会强制滚动到光标位置),改用滚动比例跨模式同步,富文本与源码
视图按相同比例定位,保持视觉位置一致。
|
2026-06-16 15:53:28 +08:00 |
|
|
|
480aa92bb4
|
feat(editor): 新增 Markdown 源码视图切换
在 Tiptap 编辑器右上角增加 </> 悬浮按钮,支持在富文本与
Markdown 源码视图间双向切换,内容自动同步。getMarkdown() 在
源码模式下返回 textarea 内容,使 Rust 端提交逻辑无需改动。
|
2026-06-16 15:50:09 +08:00 |
|
|
|
c6d27f0ae0
|
feat(highlight): 新增 JSX 与 TSX 语法高亮
新建 syntaxes/JSX.sublime-syntax(纯 JS + JSX)与
syntaxes/TSX.sublime-syntax(TypeScript + JSX),两者共享同一套
JSX 规则:标签名(区分大写组件/小写 HTML 标签)、属性名、属性值
(字符串与 {expr} 表达式)、自闭合 />、闭合标签、嵌套子标签与
JSX 片段 <>...</>。
从 TypeScript.sublime-syntax 移除 tsx 扩展名:此前 tsx 命中的是
没有 JSX 支持的 TS 语法,遮蔽了新建的 TSX 语法。
新增回归测试覆盖 jsx/tsx 的标签名与属性名识别。
|
2026-06-16 15:45:38 +08:00 |
|
|
|
d549f4a476
|
feat(highlight): 新增 TypeScript 语法高亮
新增 syntaxes/TypeScript.sublime-syntax,覆盖声明/控制流关键字、
interface/type/enum 类型声明、函数声明与箭头函数、装饰器、原始类型
与标准库类型、访问修饰符、模板字符串(含 ${} 插值)、各类数字字面量。
同时修复别名表:移除旧的 ts/typescript/tsx -> js 降级映射。这些别名
在没有 TS 语法时是临时降级方案,但 find_syntax 按扩展名->名字->别名
顺序匹配,别名会抢先于扩展名命中内置 JS,导致新增的 TS 语法被永久
遮蔽(诊断输出为 source js 而非 source ts)。改为映射 typescript -> ts
扩展名,使其正确走自定义 TypeScript 语法。
新增两个回归测试覆盖关键字/类型高亮与别名解析。
|
2026-06-16 15:35:44 +08:00 |
|
|
|
61a001c03b
|
feat(highlight): 新增 Zig 语法高亮
新增 syntaxes/Zig.sublime-syntax,覆盖声明/控制流关键字、函数声明、
内建函数(@import 等)、整数/浮点类型(含任意位宽 i0..i65535)、
标准库类型、字符串(含 {d} 格式化插值与多行字符串)、十六进制/八进制/
二进制数字、注释与文档注释、标签等。
新增两个回归测试覆盖关键字/函数/类型/字符串/数字高亮。
|
2026-06-16 15:25:11 +08:00 |
|
|
|
a9f0e8d16b
|
docs(development): 补充代码高亮开发文档
- DEVELOPMENT.md 增加代码高亮系统的详细开发指南,
涵盖添加/修复语法、刷新文章、调试流程等
- admin/posts.rs 重构重建逻辑:提取 do_rebuild 闭包消除重复,
新增「重建全部」按钮用于批量刷新已有文章渲染缓存
|
2026-06-16 15:19:45 +08:00 |
|
|
|
e8be1967db
|
fix(highlight): 语法加载改用编译期绝对路径并增加诊断日志
add_from_folder 之前用相对路径 syntaxes/,依赖运行时工作目录,
在 dx serve 启动的 server 子进程下可能解析失败导致自定义语法
(含 Swift)静默不加载。
改用 CARGO_MANIFEST_DIR 在编译期固化为绝对路径,消除工作目录
依赖;并在 LazyLock 初始化时输出加载路径、语法总数与 Swift 是否
命中,便于排查加载问题。
|
2026-06-16 14:49:44 +08:00 |
|
|
|
603a7f68cb
|
refactor(ui): 提取共享 UI 组件,消除跨页面重复
新增 src/components/ui.rs 作为通用 UI 原子层,封装:
组件:
- <Pagination variant="admin"|"frontend">:合并 posts/comments/trash/home
四个重复的分页实现,用 variant 区分配色(admin 灰黑 / 前台主题绿)
- <StatusBadge>:统一文章状态、评论状态、回收站剩余天数的徽章外层
- <EmptyState variant="default"|"error">:统一列表空态与加载失败占位
类名常量:
- ADMIN_CARD_CLASS / ADMIN_TABLE_CLASS / ADMIN_ROW_HOVER / CHECKBOX_CLASS
- BTN_SOLID_{GREEN,AMBER,RED}:批量操作实心按钮
- BTN_TEXT_{GREEN,AMBER,RED,ACCENT}:行内文字按钮
清理:
- 删除 input.css 中零引用的 .btn-primary 死代码(22 行)
- 删除 4 个重复的分页组件函数
注意:
- 前台空状态(home/search/archives/tags)保持 text-paper-secondary 配色,
未强行统一到 admin 的灰色 token,避免改变视觉
- 回收站分页计数单位从"条"修正为"篇"(回收站里是文章)
|
2026-06-16 14:20:05 +08:00 |
|
|
|
188e607ec2
|
fix(highlight): 补全 Swift 语法高亮
Swift.sublime-syntax 之前是残缺定义,expression 上下文仅包含
空白/字符串/数字,导致关键字、类型、函数等全部无法高亮。
补全声明关键字(import/func/class/let 等)、控制流(if/return/
async/await)、标准库类型(Int/String/Array)、函数声明与调用、
属性(@objc)等上下文,并调整 include 顺序使函数声明名优先于
函数调用识别。
新增两个回归测试覆盖关键字/函数/类型/字符串高亮。
|
2026-06-16 14:17:17 +08:00 |
|
|
|
6986a62bb5
|
style(ui): 重新设计回收站自动清理设置界面
- 合并为单一折叠卡片,顶部摘要条始终显示当前清理状态
- 用主题绿 toggle 开关取代原生 checkbox
- 保留天数改为数字步进器(−/输入框/+)
- 保存按钮改用鼠尾草绿强调色,与项目设计系统一致
- 新增 dirty/已保存 草稿状态反馈
- 补齐 hover/active/focus-visible 交互细节
|
2026-06-16 13:38:57 +08:00 |
|
|
|
63e352d471
|
feat: 文章回收站与自动清理
|
2026-06-16 12:42:11 +08:00 |
|
|
|
55bef35d1f
|
refactor: 清理 clippy 提示(unwrap_or 与宏 deprecated 放行)
|
2026-06-16 12:40:43 +08:00 |
|
|
|
4ba4fedb23
|
feat(ui): 新增 /admin/trash 回收站管理页面与导航
|
2026-06-16 12:38:41 +08:00 |
|
|
|
0ba8f9f835
|
feat(tasks): 新增回收站自动清理后台任务
|
2026-06-16 12:34:28 +08:00 |
|
|
|
f5e19def1a
|
feat(api): 新增回收站配置读写接口
|
2026-06-16 12:34:28 +08:00 |
|
|
|
b6de75ee97
|
feat(api): 新增 list_deleted_posts 回收站列表接口
|
2026-06-16 12:34:28 +08:00 |
|
|
|
c4c27a34c5
|
feat(model): 新增 TrashSettings 配置模型与 clamp 测试
|
2026-06-16 12:32:37 +08:00 |
|
|
|
65e090da27
|
feat(api): 新增回收站恢复/彻底删除/批量/清空接口
|
2026-06-16 12:31:55 +08:00 |
|
|
|
054d7450f7
|
feat(model): Post 新增 deleted_at 字段并用 try_get 兼容现有查询
|
2026-06-16 12:29:37 +08:00 |
|
|
|
959cc1fb0e
|
feat(db): 新增 settings 键值表与回收站默认配置
|
2026-06-16 12:28:29 +08:00 |
|
|
|
863ec5ea52
|
fix(posts): get_post_by_slug 的 SELECT 补上 toc_html 列
row_to_post_full 用 row.get("toc_html") 读取该列,但 get_post_by_slug
的 SQL 漏选了 p.toc_html,导致访问公开文章详情时 panic(invalid column
toc_html)。补上列即可。
|
2026-06-16 11:34:12 +08:00 |
|
|
|
c60e4e08d7
|
fix(build): 用 cfg gate 消除 WASM 构建的 27 个假阳性 warning
CI / check (push) Failing after 5m17s
CI / build (push) Has been skipped
Dioxus fullstack 在 WASM 构建中会剥离 #[server] 函数体,导致仅在
函数体内使用的导入/函数/常量被误报为 unused / dead_code。
- 仅在服务端使用的导入加 #[cfg(feature="server")]:get_conn、
PostStatus/PostStats/Tag、password/session、User/UserRole、
slug.rs 的 dioxus::prelude(保留 ServerFnError 给 server-gated
的 ensure_unique_slug)
- 仅在服务端使用的项加 cfg gate:clamp_pagination 及其常量、
rebuild 常量、format_relative_time、compute_content_hash、
CommentStatus::from_str
- CommentCountResponse/PendingCommentsResponse 出现在 #[server]
签名中(WASM 保留),无法 gate,改用 #[allow(dead_code)],
与现有 CreateCommentRequest 处理一致
make build 零 warning,cargo test 299 passed。
|
2026-06-16 11:29:18 +08:00 |
|
|
|
b37e33dbf4
|
fix(build): 修复 Tailwind v4 与 Tiptap 编辑器构建
Tailwind v4 将 CLI 拆为独立包 @tailwindcss/cli,核心包 tailwindcss
不再带 bin,npx tailwindcss 会因找不到可执行入口而失败;即便改用
@tailwindcss/cli,npx 装到全局缓存,@import "tailwindcss" 仍解析不到
./node_modules/tailwindcss。回到直接调用 PATH 上的 tailwindcss 二进制
(brew 安装或 CI 的 npm i -g @tailwindcss/cli),这也是 v4 升级时的
原始设计。
build-editor 中 npm ci 受全局 --omit=dev 影响会跳过 vite,npx vite
退而拉取 latest(v8,不兼容)。改用 npm ci --include=dev 确保装上
lock 钉死的 vite@5.4.21,并以 npm run build 走本地 .bin/vite,避免
npx 版本漂移。
|
2026-06-16 10:53:37 +08:00 |
|
|
|
1cc4bc5aeb
|
style(list): 简化多行表达式为单行
CI / check (push) Failing after 13m53s
CI / build (push) Has been skipped
|
2026-06-15 14:15:11 +08:00 |
|
|
|
94319d3411
|
ci: 回退 composite action,仅保留 Tailwind CLI 包名修复
CI / check (push) Failing after 18m26s
CI / build (push) Has been skipped
Gitea act_runner 对本地 composite action(uses: ./...)支持不稳定,
报 'failed to read action.yml ... file does not exist'。回退为内联
步骤,仅保留 @tailwindcss/cli 包名修正(v4 将 CLI 拆为独立包)。
|
2026-06-15 13:22:29 +08:00 |
|
|
|
76ad4ec8fb
|
ci: 修正 Tailwind CLI 包名并收敛重复的环境准备步骤
CI / check (push) Failing after 2s
CI / build (push) Has been skipped
Tailwind v4 将 CLI 拆为独立包 @tailwindcss/cli,核心包 tailwindcss
不再注册 bin,导致 npx tailwindcss 报 "could not determine executable
to run"。CI 改为安装 @tailwindcss/cli。
同时将 check 与 build 两个 job 重复的 checkout、镜像、Rust/Node/dx/
tailwind 安装步骤抽到 .gitea/actions/setup 复合 action,顶层 env
统一管理 Rust 镜像配置。AGENTS.md 同步说明 v4 拆包这一坑。
|
2026-06-15 11:47:54 +08:00 |
|
|
|
a2ccc3da1a
|
Merge branch 'fix-dos-and-toc-xss'
安全修复:
- 钳制公开分页接口 per_page 与 page 上限,消除 DoS 与缓存键扇出
- 修正 TOC 标题在属性上下文的转义,防止属性注入(XSS)
经 code review 后追加:
- 复用既有 escape_html,删除重复转义实现
- 增加 page 上限作为纵深防御
|
2026-06-15 11:40:01 +08:00 |
|
|
|
a3d6c2f19e
|
refactor(markdown): 复用既有 escape_html,删除重复的转义实现
hooks::comment_storage::escape_html 已实现完整 OWASP 转义(& < > " '),
且无 server feature 门控,全平台可用。escape_heading_text 改为委托给它,
避免在仓库内维护第二份行为略有差异(缺 >)的转义函数。补充 < 转义测试。
|
2026-06-15 11:38:24 +08:00 |
|
|
|
eaa7118e09
|
fix(posts): 钳制 page 上限,防止无界 OFFSET 与缓存键扇出
clamp_pagination 原先仅限制 per_page,page 无上限。攻击者可用海量不同
page 值撑大缓存键空间(缓存污染)并触发无意义的超大 OFFSET 扫描。新增
MAX_PAGE=10_000,对任何实际博客都足够宽裕(配合 MAX_PER_PAGE 最多覆盖
50 万篇文章),同时把缓存键空间限制在有限范围。
|
2026-06-15 11:38:24 +08:00 |
|
|
|
928fc1a0de
|
Merge branch 'improve-tests-and-comments'
完善单元测试与代码注释。测试 254 → 290(净增 36 个有价值测试),
顺带修复 highlight.rs 中大写语言标识无法走别名映射的 bug。
- theme.rs: 2 → 8(主题切换对合性、预加载脚本契约)
- highlight.rs: 7 → 15(别名映射、大小写回退,修复 'RUST' 回退纯文本 bug)
- webp.rs: 6 → 16(编解码错误处理、像素格式转换路径、Display 格式)
- sanitizer.rs: 8 → 17(is_safe_url 安全敏感分支直接测试)
- error.rs: 5 → 8(AppError 各变体消息转换)
|
2026-06-15 11:27:33 +08:00 |
|
|
|
6d32664020
|
fix(markdown): 转义 TOC 标题文本,防止属性上下文注入
generate_toc_html 原先用 clean_html 处理标题后拼进 aria-label="..." 与
<a> 正文,但 clean_html 只做正文 HTML 消毒、不转义双引号。标题形如
" onmouseover="alert(1) 会越出属性边界。新增 escape_html_attr(),对
标题文本统一做属性上下文转义(& " <),正文与属性两处一致使用。
内容由 admin 写入、严重度中低,但属真实消毒逻辑缺口,TOC 会展示给所有读者。
|
2026-06-15 11:27:32 +08:00 |
|
|
|
cfa4975813
|
fix(posts): 钳制分页参数 per_page 上限,消除公开接口 DoS
list_published_posts 为无需认证的公开接口,原先 per_page 直接透传给
SQL LIMIT,攻击者可传入巨大值迫使数据库扫描并实例化超大 Vec,造成
内存放大与拒绝服务。新增 MAX_PER_PAGE=50 与 clamp_pagination(),在
list_published_posts 与 list_posts 入口钳制 page/per_page;钳制值同时
用于缓存键与查询,避免同一逻辑页落入不同缓存条目。
|
2026-06-15 11:27:25 +08:00 |
|
|
|
19ffcada4a
|
test: 移除脆弱断言与凑数测试(review 修正)
对本次新增测试自审后的清理:
1. webp: encode_lower_quality_produces_smaller_or_equal_bytes
原断言“低质量体积 <= 高质量体积”是 WebP 的统计趋势而非
确定性不变量,依赖底层 libwebp 量化策略,纯色图上高低差异
接近 0,未来库升级易变为 flaky。改为验证两个质量档位都能
成功编码并产生可被本模块解码的合法 WebP。
2. theme: theme_is_copy
Copy 语义由编译器在编译期保证,运行期断言永真,不测任何
运行逻辑,属凑数。
3. webp: webp_config_default_quality_and_method
构造 struct 再断言字段等于构造时填入的值,是同义反复。
净减 2 个测试(292 → 290),全部通过。
|
2026-06-15 11:26:24 +08:00 |
|
|
|
263208b930
|
style: 修正新测试的格式以符合 rustfmt 宽度限制
cargo fmt 自动调整了 highlight.rs 与 error.rs 中新增测试的
assert! / assert_eq! 长行折行。
|
2026-06-15 11:22:35 +08:00 |
|
|
|
9fc626232c
|
test(error): 补全 AppError 各变体的消息转换测试
原仅覆盖 Unauthorized/Forbidden/NotFound/DbConn/Query 五个变体,
补充:
- Internal 变体的消息透传
- Transaction 变体的 SQL 细节隐藏(与 Query 行为一致)
- 三类数据库错误统一返回中文通用提示的聚合断言
共 8 个测试,全部通过。
|
2026-06-15 11:20:33 +08:00 |
|
|
|
28f0117f06
|
test(sanitizer): 补充 is_safe_url 分支测试
is_safe_url 是 HTML 消毒器的安全核心,原仅通过 clean_html 间接覆盖。
新增 9 个直接单元测试,锁定各分支契约:
- https/http 白名单通过
- javascript / vbscript scheme 拒绝(含大小写混淆)
- data URI 按 allow_data_uri 标志决定(文章正文 vs 评论)
- 相对路径与锚点片段通过
- 空字符串/纯空白视为安全
- mailto / tel / ftp 等其它白名单 scheme 通过
- 含空白的 scheme 名(混淆手法)被拒绝
共 17 个测试,全部通过。
|
2026-06-15 11:19:46 +08:00 |
|
|
|
a9cde41de8
|
test(webp): 扩充 WebP 编解码测试覆盖
原仅 6 个测试,补充后覆盖:
- WebpError 的 Display 格式与 std::error::Error trait 约束
- encode 对非快速路径像素格式(Luma8 / LumaA8)的 RGBA 转换
- encode 质量参数对体积的单调性(低质量 <= 高质量)
- decode 对非法字节流与空输入的错误处理(不 panic)
- decode 错误信息带 'WebP decode error' 前缀便于排查
- 编解码往返保持图像尺寸不变
共 17 个测试,全部通过。
|
2026-06-15 11:18:55 +08:00 |
|
|
|
e9aac7d6b4
|
fix(highlight): 修复大写语言标识无法走别名映射的问题
别名表此前用 lang == from 做严格相等比较,导致 'RUST' 这类
大写标识无法命中 ('rust' → 'rs') 这类别名,最终回退到纯文本。
改用 eq_ignore_ascii_case 比较,使别名解析与扩展名/名称的小写
回退路径保持一致。
test(highlight): 补充 find_syntax 分支覆盖
新增 8 个测试覆盖此前未测的路径:
- 大写语言标识的小写回退(同时验证了上述修复)
- 别名表:golang/bash/yml 等映射
- 未知语言与空字符串的纯文本回退
- 代码首尾空白被 trim
- 多行代码逐行高亮
通过等价性断言(而非脆弱的 span class 字面量)校验别名解析,
避免 syntect 内部 class 命名变化导致测试漂移。
共 15 个测试,全部通过。
|
2026-06-15 11:17:53 +08:00 |
|
|
|
4e89412cde
|
test(theme): 扩充主题模块测试覆盖
原仅 2 个 toggle 测试,补充后覆盖:
- toggle 的对合性(连续切换两次回到原值)
- Theme 的 PartialEq / Copy trait 行为
- 首屏预加载脚本的关键行为契约:读取 localStorage、
回退 prefers-color-scheme、添加 dark class、
包裹 try/catch 防止禁用 localStorage 时抛错
共 9 个测试,全部通过。
|
2026-06-15 10:57:51 +08:00 |
|
|
|
81ee60a77d
|
chore: ignore .worktrees directory
Add .worktrees/ to .gitignore so isolated git worktrees created for
parallel development work are not accidentally tracked.
|
2026-06-15 10:50:48 +08:00 |
|
|
|
e12e59461b
|
docs: 整理表格格式并添加 CI 链接
CI / check (push) Successful in 12m26s
CI / build (push) Failing after 13m0s
|
2026-06-15 10:41:03 +08:00 |
|
|
|
f7288cc390
|
style: 格式化测试代码以符合 clippy 宽度限制
|
2026-06-15 10:40:00 +08:00 |
|
|
|
0242534274
|
style(tags): 修复文档注释列表缩进以消除 clippy 警告
CI / check (push) Failing after 4m52s
CI / build (push) Has been skipped
|
2026-06-12 19:48:10 +08:00 |
|
|
|
194611bb7e
|
docs(bin): 补充中文注释
|
2026-06-12 19:45:59 +08:00 |
|
|
|
c43da3676f
|
docs(components): 补充中文注释
|
2026-06-12 19:42:42 +08:00 |
|
|
|
c5d1eb117c
|
docs(auth-pages, router, main): 补充中文注释
|
2026-06-12 19:31:21 +08:00 |
|
|
|
18500c9496
|
docs(pages-admin): 补充中文注释
|
2026-06-12 19:24:22 +08:00 |
|
|
|
abfab19839
|
docs(pages-frontend): 补充中文注释
|
2026-06-12 19:16:59 +08:00 |
|