575b6b533e
feat(code-runner): CodeRunner 挂载 CodeMirror 编辑器,支持双向绑定
...
兑现组件一直承诺但无人实现的「调用方挂载编辑器」契约——此前容器 div 只
输出 id,admin/runner 沙箱与文章正文 runnable 块都只能提交写死的初始源码,
作者/读者无法编辑。
- CodeRunner 在 WASM 端按自身 container_id 调 codemirror_bridge.create
挂载编辑器,onChange 回写内部 source_signal(编辑器内容 = 唯一真源)
- run_code 改读 source_signal 当前值,提交编辑后内容而非初始快照
- 主题切换经 use_resolved_theme 订阅,热切换编辑器主题
- use_drop 销毁 EditorHandle,释放 CodeMirror 实例与 closure 槽位
- source prop 外部变更(admin 切换语言重置示例)同步进 signal + 编辑器
- admin/runner 页面 overrides 解析挪进 use_memo,避免 render 体写状态
范式镜像 SQL 控制台(system.rs)与 Tiptap 编辑器(write.rs)。
2026-07-05 14:32:39 +08:00
58f1a981d3
feat(admin): SSR 层认证守卫,未登录直接跳登录页
...
此前后台鉴权完全在客户端 WASM 完成:SSR 渲染骨架屏 → 浏览器下载
/编译 WASM → hydrate → 异步 get_current_user() → 客户端 navigator.
push(Login)。整条链串行,未登录用户首屏要空白好久才跳转登录。
新增 admin_guard 中间件:/admin* 请求在进入 Dioxus SSR 渲染器之前
读 session cookie → get_user_by_token 校验 admin 角色 → 失败直接 302
到 /login。未登录用户首屏即登录页,零 SSR 渲染开销。
- 置于 app_routes layer 链最外层(CSRF/cache/SSR 之前短路)
- 复用 get_user_by_token:命中内存缓存 + session_generation 校验,
与客户端鉴权同一套语义
- DB 错误 fail-open(避免抖动把已登录管理员踢登录页),客户端
AdminLayout 仍作兜底
- /admin 与 /login 本就不进 SSR 缓存,302 不会被缓存
2026-07-04 22:53:28 +08:00
16bd644783
fix(admin): 仪表盘空数据时显示空状态占位
...
空库下 get_post_stats / list_posts 正常返回,但 list_posts 返回
Some([]) 时走有数据分支、循环 0 次,渲染出一个空表格容器,视觉
上仪表盘近期文章区域一片空白,没有空状态引导。
复用项目既有的 empty_state::EmptyState 约定(与 posts.rs / trash.rs /
comments.rs 列表页一致):Some(posts) 且 posts.is_empty() 时渲染
暂无文章插画 + 写文章CTA。空状态放在 ADMIN_TABLE_CLASS 容器
之外,避免 overflow-hidden 裁掉插画的 py-20 内边距。
2026-07-04 22:49:25 +08:00
383e6f6b43
fix(db): expand source chain for all DB error logging
...
The previous fix only covered migration errors. The same truncation
affected two more places, both because tokio_postgres::Error's Display
prints only "db error" while the real message lives in source():
- api/error.rs: AppError::{db_conn,query,tx} logged with {e}, so every
runtime DB failure showed as "Query failed: db error". The
constructors' bound is tightened from impl Display+Debug to
impl std::error::Error so the source chain can be walked; the
user-facing message stays sanitized (existing tests still pass).
- db/pool.rs: ensure_database formatted tokio_postgres::Error directly
into the String returned to main.rs' exit(1) path, collapsing to
"failed to query pg_database: db error" etc.
Adds a shared crate::db::format_with_sources helper (walks source()
with de-dup of placeholder layers) and reuses it from MigrateError's
Display, the AppError constructors, and pool.rs.
2026-07-04 21:54:54 +08:00
e9f0b032b7
fix(db): expand migration error display to walk source chain
...
tokio_postgres::Error's Display prints only the placeholder "db error"
for DB-side failures; the actual message (e.g. column already exists,
SQLSTATE, constraint name) lives in source() as DbError. Without
traversing the chain, startup logs showed the useless
"migration 001 failed: db error", making failures impossible to
diagnose.
MigrateError::Display now appends each source layer with ": " and
exposes source() so error-reporting layers that walk the chain
themselves also benefit.
2026-07-04 21:47:24 +08:00
f3eb93f320
docs(agents): document code runner and fix clippy/biome lint
...
文档:
- AGENTS.md 新增「Code Runner」架构章节(三层架构 + WASM 可见性规则 +
governor 0.8 无 per_day 的处理 + runner 镜像契约)
- Environment 段补齐 CODE_RUNNER_* 与 RATE_LIMIT_CODE_EXEC_* 环境变量
Lint 修复(clippy --all-targets --all-features -D warnings 全绿):
- runner.rs/runner.rs: use_signal 冗余闭包 → 直接传 fn
- runner_config.rs: &*RUNNER_CONFIG 去 deref;assert_eq!(...false/true) → assert!
- markdown.rs: 局部变量 /// 改 //;Option.map().flatten() → and_then
- languages.rs: 删除从未读取的 LanguageDef.name 字段(语言名即 map key)
- docker.rs: start_container if let Err → ?;timeout match → is_err();
嵌套 if 合并(修 task 2 遗留 + clippy 1.96 新 lint)
- pages/admin/posts.rs: use_signal 冗余闭包(预存 lint,顺带修绿)
- codemirror editor.ts: biome format 重排 setSchema 单行
2026-07-03 18:57:25 +08:00
bbd4553467
feat(admin): add dedicated code-runner sandbox page at /admin/runner
...
不改动 852 行的 write.rs 编辑器布局,改为独立 admin 页面(与 posts/system 同款):
- runner.rs: Runner 页面(语言切换 join 按钮 + overrides JSON 输入 + CodeRunner 沙箱)
切换语言自动填充示例源码;overrides JSON 实时校验,畸形时提示并忽略
- mod.rs: 注册 runner 模块并导出 Runner
- router.rs: 新增 #[route("/runner")] Runner {} 嵌套在 /admin 下
- admin_layout.rs: 导航新增「试运行」入口
2026-07-03 18:41:05 +08:00
0e8b5fd7b7
feat(ui): scan and mount code-runner component client-side in reader
...
采用 Dioxus vdom 友好的片段拆分(避免篡改 dangerous_inner_html 产物导致 hydration 冲突):
- post_content.rs: split_content_fragments 把 content_html 拆成 Html/Runnable 片段,
Runnable 作为 <CodeRunner> 组件穿插渲染;HTML 实体解码还原源码;6 个单测
- markdown.rs: 可运行 pre 增加 data-source(转义后的原始源码), 供阅读器无损提取
- sanitizer.rs: 放行 pre 的 data-source 属性
(任务 7 的 data-source 增量一并在此提交)
2026-07-03 18:35:57 +08:00
6b875e6ba5
feat(ui): create CodeRunner Dioxus UI component with async polling
...
- runner.rs: CodeRunner 组件(源码展示 + Run 按钮 + 阶段/输出/错误区)
spawn 提交 StartExec 后用 sleep_ms(WASM 友好) 轮询 GetExecResult,MAX_POLLS 兜底
mut 信号加 cfg_attr 放行 server 的 unused_mut(AGENTS.md 约定)
提前克隆 source/language 给 move 闭包,避免 rsx! 二次借用 (E0382)
- execute.rs: 修正双目标可见性——server fn 模块不能 cfg-gate
共享类型 use 双目标可见,server-only 辅助 use 单独 gate(对齐 posts 模块约定)
- mod.rs: execute 不再 gate,languages/progress 仍 gate
2026-07-03 18:28:52 +08:00
576803302d
refactor(editor): support dynamic languages python/javascript in codemirror
...
- editor.ts: 新增 languageCompartment + buildLanguageExtension(lang, schema)
python → lang-python, node/javascript → lang-javascript, sql/缺省 → lang-sql
新增 setLanguage(lang) 热切换; setSchema 保留当前语言不被强制切回 sql
- package.json: +@codemirror/lang-python +lang-javascript
- codemirror_bridge.rs: EditorInstance 新增 set_language wasm-bindgen extern
(产物 public/codemirror/ 被 gitignore,本地已重建)
2026-07-03 18:22:21 +08:00
a77a2e3502
feat(markdown): support rendering and sanitizing runnable pre code-blocks
...
- markdown.rs: CodeBlock 处理识别 `runnable` 标记 + 受支持语言,在 <pre> 上
挂 data-runnable/data-lang/data-overrides;overrides JSON 经 escape_html 转义
防属性注入;非可运行围栏的 language-xxx 改取纯语言 token(首个空白前)
- sanitizer.rs: clean_html 放行 <pre> 的 data-runnable/data-lang/data-overrides
- 新增 4 个 markdown 测试 + 2 个 sanitizer 测试覆盖转义/白名单/字段顺序
2026-07-03 18:19:26 +08:00
9fe128d44d
feat(api): implement StartExec and GetExecResult server functions
...
- rate_limit.rs: 新增 CODE_EXEC 双层限流(per-second burst + 每日总额)
governor 0.8 无 per_day,用 with_period(24h)+allow_burst 模拟
- execute.rs: StartExec(IP 提取/语言白名单/源码大小/入队/并发信号量/clamp/容器执行)
+ GetExecResult(轮询读取 DashMap);系统异常脱敏,日志记详情
- .env.example: RATE_LIMIT_CODE_EXEC_PER_SEC 改为整数(governor 不支持小数)
2026-07-03 18:15:59 +08:00
3f3bbf284c
feat(api): add language registry and markdown fence info parser
2026-07-03 18:11:43 +08:00
9baa9da62f
feat(api): implement in-memory task registry with gc
2026-07-03 18:10:20 +08:00
60fd6378b6
feat(api): define shared serialized structs for code runner
...
Co-authored-by: plan docs/superpowers/plans/2026-07-03-code-runner.md Task 3
2026-07-03 18:09:27 +08:00
5fdc88a48c
fix(runner): resolve task 2 container runner review findings
2026-07-03 18:02:56 +08:00
d8d30df80c
feat(infra): implement Docker execution layer using bollard client
2026-07-03 17:59:52 +08:00
b0ebba3475
fix(runner_config): remove server gate on runner_config, safeguard clamp logic, and parse allow_network case-insensitively
2026-07-03 17:52:50 +08:00
60725053e4
feat(infra): implement runner config parsing and resource limits clamping
2026-07-03 17:50:42 +08:00
2fba43dc3f
chore(infra): add bollard dependency and modular structure
2026-07-03 17:49:08 +08:00
46860f7c41
fix(ui): apply mount animation inside each page component to avoid skeleton interception
2026-07-03 17:24:38 +08:00
d361bca220
feat(ui): add smooth mount animation for route transitions
2026-07-03 17:21:04 +08:00
197c08d258
style(ui): fix inconsistent padding on post card
2026-07-03 17:13:02 +08:00
e18fe18cc3
fix(admin/layout): move scrollbar to outer card edge for all admin pages
2026-07-03 16:53:10 +08:00
52b4f91622
fix(admin/write): restore scrollability by using overflow-y-auto and min-h-full
2026-07-03 16:50:53 +08:00
acfddb3e17
style(admin/write): overhaul write page to modern minimalist layout
2026-07-03 16:44:39 +08:00
d3a50728ed
style(admin): overhaul layout to modern minimalist sidebar design
2026-07-03 15:50:59 +08:00
38ba6692d3
style(admin): redesign admin UI with soft rounded corners and Catppuccin theme
2026-07-03 15:46:18 +08:00
9f69a132fa
refactor(admin): redesign write page for industrial aesthetic
2026-07-03 15:37:41 +08:00
cad0e3d83b
fix(admin): restrict write page width to match other pages
2026-07-03 15:35:06 +08:00
d1041a84dd
feat(admin): complete redesign of backend ui with industrial minimalist aesthetic
2026-07-03 15:32:02 +08:00
45f4e9cde0
refactor(ui): 去除 Rust 中硬编码颜色,统一语义色阶
...
跟随 Catppuccin 配色迁移,清理 src/ 中绕过 paper-* 语义 token 的
硬编码 dark:[#hex] 任意值,改用 Tailwind 默认灰阶(gray-700/800),
它们随主题切换自然适配。
- post.rs 状态徽章:dark:bg-[#333 ]/dark:text-[#9b9c9d] → gray-800/gray-400/500
(同步更新测试断言)
- comments/* 与 skeletons/* 的 dark:[#2a2a2a]/[#2e2e33]/[#333 ]/[#5a5a62]
→ 对应 gray-600/700/800
- trash.rs 状态灯发光圈 rgba 由旧鼠尾草绿(92,122,94) 改 Latte green(64,160,43)
- ui.rs BTN_SECONDARY 注释更新为新 Teal 强调色值
注:src/pages/admin/posts.rs 的 clippy redundant_closure 报错为既有问题,
与本次配色迁移无关,不在范围内。
2026-07-03 14:25:40 +08:00
cb77d28a68
fix(theme): 跟随系统切换改为瞬切,放弃 VT 动画
...
诊断确认:跟随系统与手动点击的 VT 流程在 JS/CSS 层完全等价(animationName、
--tt-r、bg 翻转、clip-path 全部正确),但视觉上跟随系统场景下圆形展开动画
不显示,仅瞬切。系统偏好变化是后台事件,VT 在此上下文下动画不可靠。
改用设置语义的瞬切:JS 侧新增 applyResolvedTheme(isDark) 入口(非翻转语义,
直接 add/remove dark class),Rust effect 改调 __applyResolvedTheme 传实际
明暗值,移除圆心计算逻辑。职责清晰:
- 手动点击 → __startThemeTransition → VT 圆形展开(用户手势,动画可靠)
- 跟随系统 → __applyResolvedTheme → 瞬切(后台同步语义)
2026-07-03 13:42:17 +08:00
eb3087edf4
fix(theme): 跟随系统切换用主题按钮位置作为 VT 圆心
...
诊断发现跟随系统与手动点击的 JS 路径完全一致(__startViewTransition 全程
正常,无降级、无 reject),「看起来像淡入淡出」实为圆形展开动画在屏幕中心
圆心下的必然视觉效果:从中心向四周等距扩散,各方向同步推进,近似整体覆盖,
与手动点击(按钮在右上角,圆弧明显横扫)观感差异大。
改用 .theme-toggle 按钮的 getBoundingClientRect() 中心作为 VT 圆心,与手动
点击的动画起点一致;按钮不在 DOM 时回退到视口中心。同步更新注释说明。
2026-07-03 13:26:40 +08:00
188fc464e2
fix(theme): System 模式下系统偏好变化时同步 dark class
...
原实现存在缺口:<html> 的 dark class 运行时写入点只有「首屏预加载脚本」与
「手动点击 ThemeToggle」两处,System 模式下系统颜色偏好自动变化时无人同步——
尽管 system_dark signal 与 resolved memo 都会更新,下游(CodeMirror 等)也
能跟随,但页面配色纹丝不动,与文件头注释承诺的「实时同步 .dark class」不符。
新增 use_effect 兜底:仅 System 模式下 resolved 实际翻转时,以视口中心为圆心
复用 __startThemeTransition 触发 VT 圆形展开动画。Light/Dark 显式模式由
ThemeToggle::onclick 全权负责,effect 不介入,避免重复触发;首次挂载通过
prev_resolved 信号记录基线,自然跳过(DOM 已由 ThemePreload 设好)。
2026-07-03 11:35:10 +08:00
c79c390482
fix(ui): ADMIN_TABLE_CLASS 去掉 overflow-hidden,修复 tooltip 被裁
...
overflow-hidden 用于圆角裁剪表格,但会硬裁掉行内按钮的 tooltip
(无论朝上朝下)。去掉后:表格行 hover 背景 (bg-paper-entry) 与
容器背景同色,圆角处无视觉差异,tooltip 可正常溢出表格边界。
全局生效,所有 admin 表格的 tooltip 不再被裁。
2026-07-03 11:15:48 +08:00
64ad40ca61
fix(admin/posts): Tooltip 包裹后操作按钮恢复垂直居中
...
- Tooltip 外层 div 由块级改为 inline-flex,作为行内伸缩盒参与
flex 行对齐,不再撑高或破坏基线
- 操作列容器补 items-center,显式锁定所有子项垂直居中
2026-07-03 11:08:04 +08:00
73b9cad550
refactor(ui): 抽取 Tooltip 组件,行内重建按钮补 tooltip
...
新增可复用 Tooltip 组件(group-hover 显现,支持 top/bottom 朝向),
消除顶部重建按钮手写的内联 tooltip div 重复,并为表格行内重建
按钮补上 tooltip(朝上,避免被表格容器的 overflow-hidden 裁掉)。
2026-07-03 11:03:56 +08:00
b6fe0ae082
style(admin/posts): 删除按钮 loading 用 spinner 覆盖文字
...
- 删除改为非乐观:点击后保留行并显示 loading,服务端成功才移除行、
失败保留行并弹提示(顺带修掉原先「删除失败行却没了」的隐患)
- deleting 信号由 Option<i32> 改为 HashSet<i32>,支持并发删除
- 删除按钮 loading 样式与重建一致:文案恒为「删除」,spinner
居中覆盖、文字 opacity-40 衬底
2026-07-03 10:51:16 +08:00
1530d3a2f4
style(admin/posts): 顶部重建按钮 loading 用 spinner 覆盖文字
...
工具条「重建内容」「重建全部」按钮 loading 时由「重建中...」文案
改为 spinner 居中覆盖、文字 opacity-40 衬底,与行内重建按钮的
loading 样式统一。
2026-07-03 10:46:57 +08:00
db87d3c886
fix(admin/posts): 重建支持并发 loading,spinner 覆盖文字
...
- rebuilding 信号由 Option<i32> 改为 HashSet<i32>,连续点击多篇
文章的重建按钮可同时处于 loading 态(单值会被后点的覆盖)
- loading 样式调整:按钮文案恒为「重建」,spinner 绝对定位覆盖在
文字上方居中,文字 opacity 调至 40% 衬底,不再切换文案
2026-07-03 10:40:11 +08:00
a5c00caa80
style(admin/posts): 操作列加宽横排,重建按钮 loading 用 spinner 图标
...
- 操作列宽 w-24 → w-44,三个按钮一行排开不换行
- 重建按钮 loading 态由「重建中...」文案改为 spinner 图标 + 「重建中」
- spinner 复用 public/icons/90-ring-with-gradient.svg,作为 SPINNER_SVG
常量收入 ui.rs(修正原 SVG 损坏的孤立 ':' 选择器,重命名 id/类名
避免多处内联时冲突),用 currentColor 继承按钮文字色
2026-07-03 10:26:14 +08:00
e55f2e12bd
refactor(admin/posts): 重建按钮文案改「重建」并去掉完成弹窗
...
按钮态文案与原有一致(「重建中...」);on_rebuild 改为静默执行,
仅按行切换 rebuilding 按钮态,完成后不再弹浏览器 alert。
2026-07-03 10:16:13 +08:00
0fe0387ea3
feat(admin/posts): 文章列表操作列新增「重建内容」按钮
...
新增 rebuild_post_content_html(post_id) server function,从 DB 读取
content_md(事务内 FOR UPDATE 锁行)重新渲染 content_html/toc_html
并更新 word_count/reading_time,按影响范围精准失效列表、slug 单篇
与搜索缓存。
PostRow 操作列在「编辑」「删除」之间插入「重建内容」按钮(鼠尾草绿
文字样式),按行禁用并切换「重建中...」文案,成功/失败弹出浏览器
提示,与删除按钮的反馈模式一致。
为避免与单篇 rebuilding 信号冲突,将原批量重建工具条信号 renaming
为 batch_rebuilding。
2026-07-03 10:13:15 +08:00
edee09596c
test(api/markdown): 解耦 wrap_images_with_blur 并脱离文件系统依赖
...
把 wrap_images_with_blur 拆成两部分:
- wrap_images_with_blur_with(html, dims_fn):纯函数核心,接受 dimensions
查询闭包,不碰文件系统
- wrap_images_with_blur(html):薄包装,注入真实 get_image_dimensions
测试改用纯函数核心,注入确定性 dimensions(如 Some((800,600)) 或 None),
彻底脱离 uploads/ 真实文件依赖。此前的 aspect-ratio 测试硬编码了
/uploads/2026/06/18/...webp 真实路径——文件不存在则静默走缺省分支,
断言虽能过但实际验证内容被削弱。
新增覆盖(共 8 个 wrap 相关测试):
- --ar 缺省/有值两种路径
- rel_path 去查询的验证(用 RefCell 捕获 Fn 闭包入参)
- alt 保留(双层)/空 alt 不生成属性
- 斜杠分隔的 --ar 格式 + sanitizer 管线不破坏斜杠
2026-07-02 17:39:15 +08:00
ab05c01f76
test(api/database): 备份恢复补单测 + 修复 backup_path 路径穿越漏洞
...
backup.rs 是恢复流程的安全关键路径,此前无任何单测。本次:
提取纯函数(便于单测,无行为变更):
- is_valid_backup_filename:文件名白名单校验,替换三处内联 Regex
- parse_backup_mode:从 -- mode: 行提取模式值
- has_valid_signature:首行签名头校验
新增 15 个单测,覆盖:
- 文件名白名单(正常/路径穿越/特殊字符三类边界)
- backup_path 路径穿越纵深防御
- 签名校验(精确/前导空白/非系统文件/空内容)
- 模式解析(pg_dump/sql-fallback/缺失/空值/多次)
修复一个真实的路径穿越漏洞(测试驱动发现):
backup_path("/etc/passwd") 之前返回 /etc/passwd 而非 backups/——
因为 [BACKUP_DIR, filename].collect::<PathBuf>() 在 filename 为绝对
路径时会丢弃 BACKUP_DIR 前缀(PathBuf 语义),随后的 components 检查
在错位的路径上运行而漏判。改为先校验 filename 自身的 components
(只允许 Normal 段),从根上杜绝穿越。
注:第一道白名单 is_valid_backup_filename 已拒绝含 / 的文件名,
故该漏洞实际不可达;但纵深防御必须健壮,本修复使其名副其实。
2026-07-02 17:37:07 +08:00
533cabb0b5
test(api/database): SQL 控制台护栏补表驱动单测 + 加固
...
sql_console.rs 是 SQL 控制台的安全关键路径,此前无任何单测。本次:
测试(新增 24 个,覆盖护栏 1+2 全分支):
- check_guards: DROP SCHEMA/CREATE DATABASE 绝禁、DROP/TRUNCATE/ALTER
需确认、UPDATE/DELETE 无 WHERE 绝禁(且 confirm 不能救)、多语句短路
- is_absolutely_forbidden: 大小写不敏感、误拦检查、报错名
- statement_type_name / is_read_only: AST 变体映射
- 两条安全不变量测试(见下)
加固(测试驱动发现的两个真实缺口):
1. 字符串预检 contains() 改为 token 序列匹配 is_absolutely_forbidden()——
防多空格/制表符/换行绕过 DROP/CREATE DATABASE。
2. check_guards 补 Statement::CreateDatabase 绝禁分支——此前 sqlparser
能解析 CREATE DATABASE(可绕过字符串预检进 AST),但 AST 层无对应分支,
字符串预检是其唯一防线。现在双重拦截。
并锁定两条安全不变量,防止 sqlparser 升级时悄悄回退:
- DROP DATABASE 不可解析 → 字符串预检是唯一防线
- CREATE DATABASE 可解析 → 双重防线都生效
2026-07-02 17:33:19 +08:00
65b15509a7
chore(wasm): 清理 wasm32 target 下残留的 clippy lint
...
这些 lint 在 server build(默认 --all-features)下被 cfg 剥离故未暴露,
仅 wasm32 web-only target 触发。逐项清理:
- footer.rs: 两处 redundant closure(web_sys::window 直接传函数引用、
sync_visible 直接传闭包)+ let _ = unit 绑定(scroll_to_*)。
- hooks/event_listener.rs: 复杂类型 Rc<RefCell<Option<(Closure,T)>>>
抽 type ListenerState<T> 别名。
- system.rs: 两处单模式 match { Ok=>.., _=>{} } 改 if let。
- write.rs: split(|c| matches!(c,...)) 改 split([char; N]) 数组模式。
- codemirror_bridge.rs: let _ = instance.destroy() 删 unit 绑定,
与 tiptap_bridge.rs 同处写法对齐。
wasm32 与 server 两 target clippy -D warnings 均通过。
2026-07-02 17:15:27 +08:00
fee5b7ba94
refactor(wasm): 消除 DOM 互操作中的 js_sys::eval 字符串求值
...
对照 Dioxus "Breaking Out" 文档审查后,将 3 处 js_sys::eval 改为
类型化调用,与 tiptap_bridge/codemirror_bridge 风格统一:
- utils/time.rs sleep_ms:eval("new Promise(r=>setTimeout(r,n))")
改为 js_sys::Promise + web_sys::Window::set_timeout_*,复用项目内
system.rs::wasm_sleep 同款写法。
- theme.rs 主题切换:format!-into-eval 拼 __startThemeTransition(x,y)
改为 Reflect::get 取函数 + Function::call2,消除字符串注入面
(原坐标虽为 f64 无实际风险,但属不必要 eval)。
- post_content.rs:__initPostContent / __initLightbox 两处 eval 字面量
改为 invoke_optional_global 辅助函数(Reflect::get + Function::apply),
消除旧版 "eval 字符串粘贴" 模式;__lightboxSelectors 直接复用 JsValue
传入,省去一次回读。
2026-07-02 17:15:18 +08:00
ba5b146dfa
fix(theme): 消除 detect_initial_theme 的 unreachable_code 警告
...
wasm 分支末尾的 return Theme::System 在 wasm target 下让尾部兜底
Theme::System 不可达(unreachable_code 警告)。把尾部兜底用
#[cfg(not(target_arch = "wasm32"))] 限定,使其只在 server 分支
(cookie 未命中)或边角构建时编译,wasm target 下函数以 wasm
分支的 return 自然结束,两端都零警告。
2026-07-02 16:49:31 +08:00