60bfee7f36
feat(build): inject git/rustc/build-time info and print on startup
...
新增 build.rs 在编译期采集构建元信息(version / git describe / commit
hash / 提交时间 / rustc 版本 / 编译时刻),通过 cargo:rustc-env 注入,
由 src/build_info.rs 用 env! 宏在编译期内联读取,零运行时开销。
启动时(main() tracing 初始化之后)调用 log_build_info() 分 4 行打印
这些字段,方便定位线上跑的是哪个二进制。
设计取舍:
- 只用 std,不引 vergen/git2 等 build-dependencies(git 不可用时降级为
"unknown",不 fail the build)。
- build.rs 存 Unix 秒,运行时用已有的 chrono 解析回 RFC3339。
- 声明 rerun-if-changed=.git/HEAD,确保切换提交后重新采集。
2026-07-09 11:50:39 +08:00
0ab3340133
fix(code-runner): allow exec on /tmp tmpfs for compiled languages
...
Docker tmpfs 挂载默认带 noexec,编译型语言(go/rust)把编译产物
落在 /tmp 后再 exec 会报 permission denied:
- rust: /tmp/main (run-rust.sh 的 rustc 输出)
- go: /tmp/go-build*/b001/exe/main (GOTMPDIR=/tmp 的链接器输出)
解释型语言(python/node)执行根文件系统里的解释器,不在 tmpfs 上,不受影响。
给 /tmp tmpfs 显式加 exec 选项。这是容器执行的固有需求——只要
沙箱支持任何编译型语言,/tmp 就必须可执行。安全模型由只读根文件系统 +
cap_drop=ALL + no-new-privileges + pids/memory/cpu 限制兜底,/tmp 可执行
不引入额外攻击面(容器内本就允许执行自身进程)。
2026-07-09 11:04:27 +08:00
2f6f8e549d
refactor(code-runner): default CODE_RUNNER_LANGUAGES to all-open
...
CODE_RUNNER_LANGUAGES 未设置时,白名单不再默认为 python,node,
而是放行 LANGUAGES 注册表里的全部语言。该环境变量变为「可选的收窄开关」:
新增语言到注册表即可默认启用,无需再同步运维白名单(避免两边脱节,
如本次 go/rust 就因 .env 未同步白名单导致 is_supported_lang 拒绝)。
- RunnerConfig.languages: Vec<String> → Option<Vec<String>>,
None 表示不限制
- is_supported_lang: Option 为 None 时直接放行注册表语言
- 测试 is_supported_lang_default_whitelist → is_supported_lang_default_all_open,
断言 go/rust 在默认(未设白名单)下可用
2026-07-09 11:02:04 +08:00
75767661ac
feat(admin): surface Go and Rust on the runner page
...
SUPPORTED_LANGS 追加 go / rust,并为两者补 default_source 示例源码,
使新增语言在 /admin/runner 试运行沙箱的语言切换按钮中可见、可用。
前端语言集合此前是注册表的手动镜像副本(注释已声明需对齐),
本次保持该约定;runner.rs:15 的注释依然准确。
2026-07-09 10:52:03 +08:00
e48e992ca1
fix(system): add key to tab content div to fix skeleton delay
...
Without a key, Dioxus 0.7 VDOM diffing may reuse hook slots from
the previous tab component on tab switch. This caused DelayedSkeleton's
visible signal to retain the old true value, bypassing the 200ms delay.
Adding key based on active_tab forces full unmount/remount on tab switch.
2026-07-09 10:22:29 +08:00
c624997c04
feat(code-runner): add Go and Rust language support
...
为 Code Runner 新增 Go 和 Rust 两种编译型语言,沿用现有 base 镜像分层结构。
Go:
- run_cmd 直接用 go run(单条命令,内部编译+运行)
- 镜像把 GOCACHE/GOTMPDIR/GOPATH 重定向到 /tmp tmpfs
(只读根文件系统下 /Users/issuser/.cache 不可写)
- default_limits: 1 核 / 256MB / 10s(编译冷启动比解释型慢)
Rust:
- rustc 编译 + 运行是两步,但 docker.rs 注入脚本用 exec 执行 run_cmd,
exec 替换 shell 进程后 'A && B' 后半段不执行,
因此镜像内置 /usr/local/bin/run-rust.sh wrapper 封装两步
- default_limits: 1 核 / 512MB / 15s(rustc 内存大、编译慢)
新增镜像与白名单后,默认 CODE_RUNNER_LANGUAGES=python,node,go,rust。
2026-07-09 09:40:32 +08:00
d690910efa
fix(admin): 消除骨架屏→认证→正常页面的布局闪烁
...
合并 (true, None) 和 (false, _) 两个分支为统一的 fallback 骨架屏。
旧 (true, None) 分支渲染无侧边栏的全屏居中文字「正在验证身份...」,
与骨架屏 / 正常页面的侧边栏+卡片布局完全不同,在 checked.set(true)
同步触发 re-render 时产生明显的布局跳变。统一后三个状态的布局结构
一致,过渡平滑无闪烁。
2026-07-08 18:23:08 +08:00
53de550d7c
fix(admin): 修复后台骨架屏不可见问题
...
- admin_layout: 移除 (false, _) 分支中的 DelayedSkeleton 包裹,直接渲染
骨架屏并附加 animate-pulse。DelayedSkeleton 依赖 use_effect 延迟 200ms
置 visible=true,但 SSR 不执行 effect,导致服务端 HTML 输出空节点;
hydration 后 checked 又会立即置 true 退出该分支,骨架屏窗口趋近于零。
去掉后 SSR HTML 直接包含骨架屏,用户在 WASM 加载 + 身份校验期间可见。
- comments: loading 初始值从 false 改为 true,与 use_paginated hook 保持
一致。旧值导致首帧 loading()=false,骨架屏条件永远不满足。
2026-07-08 18:20:25 +08:00
3eaf330673
fix(admin): use flex split layout for write page to fix sticky footer jump
...
The sticky footer with -mt-12 negative margin caused a jump when
scrolling to bottom: sticky bottom-0 positions against the scroll
container's padding box, but the negative margin pulls the element up
by 48px, so at scroll-end the footer shifts up and clips the editor.
Replace sticky+neg-margin with a proper flex split layout:
- AdminLayout: write route now gets overflow-hidden on the card and a
padding-free, non-scrolling flex main; other admin pages unchanged.
- write.rs: root becomes flex-col; content area is flex-1 overflow-y-auto
with the px-10 py-12 padding moved here; footer is a flex-shrink-0
sibling that sits at the card bottom permanently, never scrolls, never
jumps.
min-h-0 added on flex children so overflow can shrink below content
height (required for flex + overflow to work).
2026-07-08 18:14:23 +08:00
7c98eee285
fix(admin): remove redundant pt-8 on write page top spacing
...
After the shell unification, main already provides py-12 (48px) top
padding via the shared admin shell. The write page's own pt-8 (32px)
was a leftover from when it had no outer card, so it stacked to 80px —
much larger than other admin pages. Remove it to match.
2026-07-08 17:46:50 +08:00
25c3172b7c
fix(admin): unify write page shell with other admin pages + sticky footer
...
The write route had a separate shell in AdminLayout (main element acted
as its own rounded card + scroll container), while all other admin pages
used a dedicated rounded-card div wrapping a centered main. This caused
visible margin/spacing differences.
Changes:
- AdminLayout: remove is_write_route shell branching; all admin pages now
share the same rounded-card div + centered main shell.
- write.rs: drop redundant max-w-7xl mx-auto on root div (main already
provides it); make bottom action bar sticky bottom-0 with negative
margins to bleed to card edges and a translucent backdrop so scrolling
content doesn't bleed through.
2026-07-08 17:42:25 +08:00
5c37b17cb8
fix(admin): align runner page width with other admin pages
...
runner.rs was the only admin page using max-w-5xl (1024px) while all
others (system/comments/dashboard/posts/posts_trash/write) use
max-w-7xl (1280px). The page's own comment claimed to align with
dashboard/posts/system but the width class contradicted that.
2026-07-08 17:25:39 +08:00
d72495c002
refactor(admin): merge trash into /admin/posts as a URL-driven tab
...
回收站从独立路由 /admin/trash 合并为 /admin/posts 下的一个 tab,
消除「回收站」导航项,让文章管理(列表 + 回收站 + 自动清理配置)集中在
同一页面,符合「相关功能就近聚合」的组织原则。
路由(router.rs)
- 删除 Route::Trash / Route::TrashPage
- 新增 Route::PostsTrash (/posts/trash) 与 PostsTrashPage (/posts/trash/:page)
- 静态段声明在 :page 之前::page 为 i32 类型,天然排斥 'trash' 文本,
路由匹配安全且遵循文件内 static-first 约定
导航(admin_layout.rs)
- 移除「回收站」导航项
- 「管理文章」高亮覆盖其下所有子路由(列表/分页/回收站 tab),
顺带修掉原 PostsPage 分页不高亮的小 bug
页面(posts.rs / posts_trash.rs)
- 新增 PostsTabs:URL 驱动的 tab 栏(Link 切换路由,非本地 signal),
回收站 tab 带 get_post_stats().trash 数量角标,>0 用主题强调色提醒
- trash.rs → posts_trash.rs:TrashPage 重命名为 PostsTrashPage,
分页路由改指向 PostsTrash/PostsTrashPage,内容(列表/批量操作/
清空回收站/AutoPurgeSettings)原样迁移;include_str 测试同步更新
- posts.rs 的 PostsPage 渲染 PostsTabs,列表逻辑不变
无后端契约变更:所有 server function(list/delete/restore/purge/
batch/empty_trash/get_trash_settings)签名不变,Pagination 组件
接收具体 Route 变体,给 trash tab 传 PostsTrash 即可,无需改组件。
2026-07-08 16:52:02 +08:00
9c3f2242ba
feat(stats): add trash count to PostStats for posts page badge
...
为合并回收站到 /admin/posts 的 tab 设计铺路:PostStats 新增 trash 字段,
统计 deleted_at IS NOT NULL 的文章数,供文章列表页「回收站」tab 角标使用。
- stats.rs: 条件聚合查询增加 trash 列,server/非 server 构造同步补字段
- models/post.rs: PostStats 加 pub trash: i64
- cache.rs: post_stats_cache_roundtrip 测试 fixture 补 trash 字段
2026-07-08 16:40:32 +08:00
ebeec2a295
fix(comments): resolve reactivity dependency tracking in CommentSection hooks
2026-07-08 15:42:44 +08:00
a72a167a5f
fix(comment): resolve potential SSR hydration mismatch in CommentSection
2026-07-08 15:38:29 +08:00
74a74e77a8
feat(comment): render form and header persistently to eliminate layout shift
2026-07-08 15:32:24 +08:00
42548d5c3a
style(comment): redesign comment list skeleton to match real list layout
2026-07-08 15:30:32 +08:00
9e70fd9893
feat(runner): set Vim mode default to enabled in CodeRunner
2026-07-08 14:43:57 +08:00
cda5a92230
feat(runner): enable Vim mode toggle for CodeRunner sandbox
2026-07-08 14:37:52 +08:00
3bb67f6673
style(runner): optimize CodeMirror editor height auto-scaling and scrolling limit
2026-07-08 14:32:04 +08:00
f60bc4beaa
fix(runner): fix CodeMirror editing reversion feedback loop
2026-07-08 14:28:45 +08:00
61c64841f9
refactor(skeletons): 统一骨架屏延迟机制,200ms 内加载不显示
...
- DelayedSkeleton 从「延迟 pulse 动画」改为「延迟渲染」:
前 200ms 完全不渲染,超时后才显示并带 pulse 动画
- admin_layout 从 use_delayed_loading hook 改为 DelayedSkeleton 包裹
- CommentListSkeleton 的两处裸用(section.rs / post_detail.rs)
补上 DelayedSkeleton 包裹
- 移除不再使用的 use_delayed_loading hook 模块
2026-07-08 14:18:08 +08:00
5b9e65bf72
fix(editor): 修复文章页折叠行被撑高 & 折叠图标垂直不居中
...
文章页 CodeRunner 嵌在 .md-content 内,CodeMirror 折叠后插入的
<img class="cm-widgetBuffer">(width:0、height:1em 的占位符,用于对齐折叠
widget 基线)被 .md-content img 的 margin:1rem 0 命中,上下各 16px margin
把折叠那行 .cm-line 撑到 47.5px(试运行页不在 .md-content 内,正常 19.6px)。
对比两页 .cm-line 的 children 锁定:文章页含 cm-widgetBuffer,试运行页没有。
input.css:.md-content img 选择器加 :where(:not(.cm-widgetBuffer)) 排除占位 img,
用 :where() 压低特异性避免影响其它规则。
themes.ts:core 对折叠列 .cm-foldGutter .cm-gutterElement 完全没设样式,格子
高度 ≈ font-size(14px) 比正文行(line-height ≈19.6px)矮,图标偏离中央。给格子
flex 居中 + line-height:1.4(复刻 CM 的字号×1.4 行高算法),图标落在正文行中央。
2026-07-08 14:03:14 +08:00
20540358c2
docs: remove Playwright from agents
2026-07-08 13:44:17 +08:00
533f12e851
fix(editor): 修复 CodeMirror 折叠图标垂直不居中
...
折叠三角 (▾/▸) 在每行行框里偏低,根因有二:
1. 图标字符本身基线不稳。codemirror 包的 basicSetup 调 foldGutter() 用默认
openText "⌄" (U+2304「下花括号」),这是个基线/字形表现不稳定的符号字符,
在多数 mono 字体里墨迹落在字符框底部,三角明显偏低。本地内联一份 basicSetup
(CodeMirror 官方推荐的定制方式),改用几何形状块字符 ▾ (U+25BE) /
▸ (U+25B8),字形本身在字符框内居中;同时把 foldGutter() 展开后丢弃的
@codemirror/{lint,search} 显式声明为依赖。
2. core 没给图标 <span> 设 vertical-align/display。baseTheme 只给
.cm-foldGutter span 设了 padding/cursor,图标默认按基线贴在格子底部。
themes.ts 加一条 flex 居中规则,把 .cm-foldGutter .cm-gutterElement 变成
flex 容器,三角稳稳落在行框中央。
文章页 CodeRunner 与后台 SQL 控制台共用同一份 editor.js,一处修复两处生效。
2026-07-08 13:19:59 +08:00
7d0922c0f9
feat(editor): 可运行代码块在 CodeMirror 挂载前显示骨架屏
...
SSR 渲染时 CodeMirror 容器为空(JS 编辑器不在服务端拉起),hydration
完成前用户看到一块空白区域。新增 editor_ready signal(声明在 cfg 块外,
SSR/客户端双目标可见),CodeMirror 挂载后置 true、卸载时复位。
容器改为 relative,未就绪时叠加一层绝对定位覆盖骨架屏——5 行宽度递减
(90/70/55/85/40%) 的脉冲占位条,模拟代码缩进语境,配色沿用
paper-code-block / paper-tertiary 语义 token。容器本身始终在 DOM
(不与 CodeMirror 的 getElementById 挂载冲突),editor_ready 置 true
后骨架屏 if 分支消失即从 DOM 移除。
Playwright(release)验证:SSR 即渲染骨架屏(5 占位条,无闪烁),
hydration 后骨架屏消失、CodeMirror 可见。
2026-07-08 11:22:06 +08:00
b95777e58d
fix(editor): 修复 SSR 直接访问时可运行代码块不挂载 CodeMirror
...
CodeRunner 原用 use_hook(|| format!("code-runner-{}", now_pseudo_unique()))
生成容器 id,后缀依赖 now_millis() 时间戳。Dioxus hydration 不传递
use_hook 状态——SSR 渲染与客户端 hydration 各执行一次 use_hook,时间戳
(以及顺带验证过的 ScopeId)两端不同,导致 CodeMirror create() 在 hydration
时用新 id 去 getElementById,找不到 SSR 渲染的容器(id 是旧值),返回 null
不挂载。路由跳转是纯客户端渲染,use_hook 只跑一次 id 一致,故正常。
改为由父组件传入确定性的 instance_id(PostContent 的片段索引 i,来自纯函数
split_content_fragments 对同一 content_html 的解析,SSR 与 hydration 一致),
container_id 直接派生自该 prop,不进 use_hook。admin 试运行页单实例固定 0。
Playwright(release 构建)验证:SSR 直接访问与路由跳转 .cm-editor 均为 1。
2026-07-08 11:04:40 +08:00
8f6c864f22
chore(tiptap): 移除未使用的 RunCodeOptsJs 重导出
...
RunCodeOptsJs 只在 mod wasm 内部用作 Closure 类型参数,无外部消费者,
从 pub use 重导出列表移除以消除 unused_imports warning。
2026-07-07 18:34:17 +08:00
a37b0ee811
docs: 修复 cargo doc 的两处 broken intra-doc links
...
- runner.rs: 把含函数调用表达式的 rustdoc 链接 `[crate::codemirror_bridge::get_module().create]`
改为普通代码片段;get_module 是 WASM 专属符号,server target rustdoc 解析不到
- sql_result_table.rs: 模块级 doc 里裸用 `[SqlResult]` 但该类型来自 server-gated
模块不在作用域,改为纯代码片段并补全路径
2026-07-07 18:29:54 +08:00
82315853a2
fix(tiptap): slash 命令创建可运行代码块时模态框被立即关闭
...
斜杠菜单中按 Enter 选择「可运行代码块」时,openRunnableModal 在
同一个 keydown 事件处理中同步调用。模态框的 document keydown 监听
立即注册后,该 Enter 事件继续冒泡到 document 触发模态框的 Enter
处理——insert() → close(),模态框在同一 tick 内创建又销毁,用户
看不到配置弹框。
将 document.addEventListener("keydown", ...) 延迟到 setTimeout(0)
注册,确保触发事件完成传播后才开始监听。
2026-07-07 17:51:06 +08:00
1fa1984703
feat(editor): 点语言标签编辑可运行代码块的语言与配置
...
openRunnableModal 新增编辑模式(editPos + currentInfo):
- 回填当前块的 lang + overrides(解析 info string)
- 标题改「编辑」、按钮改「保存」
- 确认用 setNodeMarkup 原地更新 language 属性(保留块内代码)
CodeBlockNodeView 的语言标签在 runnable 块上可点击(绿字 hover 提示),
点击触发编辑模式(getPos 传 NodeView)。update() 在 language 变化时同步
刷新 <code> 的 class,让高亮按新语言重算。
补 4 个编辑模式用例(回填/标题/保存走 setNodeMarkup/改语言写入)。
Playwright 验证:python→node 编辑后 lang 标签与 code class 同步更新。
2026-07-07 16:12:11 +08:00
9c8ab791d9
fix(editor): codeBlock 内 Backspace 在 lowlight decoration 重建后失效
...
根因:CodeBlockLowlight 的 lowlight 插件在 codeBlock 内容变化后重新高亮,
重建 <code> 内 text node(包成 <span class=hljs-...>)。重建过程导致 DOM
selection 错位到 <pre>(contentDOM 父元素)而非 <code> 内文本,后续 Backspace
删不掉剩余字符,块删空后也无法删除整个 codeBlock。
文档层 ProseMirror selection($anchor)始终正确,只是 DOM 层不同步。用独立
Extension + handleKeyDown plugin prop 接管 codeBlock 内的 Backspace:基于
文档 pos 直接删除字符(不依赖 DOM selection),或在块空时 setNodeMarkup
转段落。handleKeyDown 优先级高于 keymap,能覆盖父类 CodeBlock 的同名 shortcut
(在 CodeBlockLowlight.extend 里 addKeyboardShortcuts 无法覆盖父类,故独立扩展)。
经 Playwright 真实浏览器逐键验证:输入 ab → 删 b → 删 a(此前失败) → 删块,
全链路正常。与 NodeView 无关(禁用 NodeView 同样复现,根因在 lowlight decoration)。
2026-07-07 14:05:53 +08:00
2a3a48af4e
docs(agents): 记录 Tiptap 交互 bug 用 Playwright 调试的方法论
...
happy-dom 测不出 ProseMirror 真实交互 bug(键盘/selection/NodeView/
Suggestion range)。记录 Playwright 反馈环的标准搭建与诊断模式:
逐字符输入、调试写 DOM、二分定位 NodeView。附 /code 文本残留案例。
这类 bug 不进 git:repro.mjs/package.json/node_modules 用完即删。
2026-07-07 12:01:55 +08:00
df8f7397b2
fix(editor): 斜杠命令文本残留进新节点(/code 带入 codeBlock)
...
Suggestion 传给 command 的 range 在某些输入路径下过时——停在首次
输入 '/' 的位置 {from:1,to:2},不随后续字符更新。deleteRange 只删 '/',
命令文本(如 'code')残留,被 toggleCodeBlock 包进新节点。
该 bug 同时导致衍生症状:残留文本让 codeBlock 非空,Backspace 的
clearNodes 条件(!textContent.length)不成立,空块退格看似无效。
修复:command 转发处防御性重算 range——基于当前 selection 在同一段落
内往前找触发字符 '/',删到光标位置。对所有命令统一生效。
经 Playwright 真实浏览器复现验证(happy-dom 无法复现此 bug):
- /code 回车:codeBlock 现为空(原残留 'code' 文本)
- 空 codeBlock 退格:正常删除变段落(原无反应)
2026-07-07 11:59:26 +08:00
7fbaae7622
feat(editor): 斜杠命令空状态显示「无匹配命令」
...
搜索无结果时浮层显示居中提示(非空白卡片)。同步修两个空列表 bug:
- ArrowUp/Down 对 % 0 产生 NaN(除零)
- Enter 被吞(preventDefault 后无项可选,用户回车无反应)
空列表时方向键/回车放行(return false),仅 Escape 拦截关闭。
导出 createPopup 补 6 个 happy-dom 用例。
2026-07-07 10:24:54 +08:00
9a90514470
feat(editor): 斜杠命令支持英文别名搜索(中英文互通)
...
每条命令补 keywords 字段(空格分隔英文/常见词),搜索时 title/description/
keywords 任一命中即匹配。/code 现在能命中「代码块」,/link 命中「链接」。
提取 matchCommand 纯函数(原 inline filter),补 30 个用例覆盖中英文命中、
大小写不敏感、keywords 缺省回退、不命中场景。
2026-07-07 10:15:44 +08:00
d8036c6e70
fix(editor): 代码块内 Backspace 删整块(ignoreMutation 误忽略 contentDOM 编辑)
...
CodeBlockNodeView.ignoreMutation 无条件返回 true,导致 contentDOM(<code>)
内的 characterData/childList mutation 被忽略,ProseMirror 文档状态与 DOM
失同步——输入文字它不知道,Backspace 时基于错误状态重建,表现为删整块。
改为对齐 ProseMirror/Tiptap 默认 NodeView 逻辑:
- contentDOM 内的 mutation(characterData/childList)→ false(交给 PM)
- selection → false
- contentDOM 自身 attributes(高亮改 class)→ true(忽略)
- 工具栏/结果区装饰元素 → true(忽略)
补 2 个回归用例覆盖 contentDOM 内/外分支。参数类型改 ViewMutationRecord
(含 selection,ProseMirror 扩展类型)。
2026-07-07 10:03:36 +08:00
c8b2248066
fix(editor): runnable 块 classList.add 抛 InvalidCharacterError
...
CodeBlockNodeView 构造时把完整 info string 原样拼进 class
(`language-python runnable {...}`),classList.add 拒绝含空格 token,
导致编辑模式回填含 runnable 块的文章时崩溃(setMarkdown → addNode)。
改用 extractLang 只挂纯语言名 class。高亮靠 CodeBlockLowlight decoration,
本就不依赖此 class。补回归测试。
2026-07-07 09:41:05 +08:00
05460f1257
Merge branch 'feat/editor-runnable-codeblock'
...
编辑器三大增强:
- 斜杠命令插入可运行代码块(模态框配置语言+overrides)
- CodeBlockLowlight 语法高亮(Catppuccin Latte/Mocha,对齐读者侧)
- CodeBlockNodeView:语言标签 + 运行按钮(仅 runnable) + 内联运行结果
运行经 onRunCode 回调桥接到 Rust(start_exec + 轮询 get_exec_result)。
markdown 往返保真(language 承载完整 info string)。
2026-07-06 18:34:54 +08:00
763edc300d
feat(editor): NodeView 适配 onRunCode 协议(extractLang + overridesJson 提取)
...
runCode 改传纯语言名(extractLang) + overrides JSON 字符串(extractOverridesJson),
对齐 Task 4 Rust 桥接 RunCodeOptsJs(language/source/overrides_json):
- highlight.ts: 新增 extractOverridesJson,对齐后端 parse_fence_info 取以 { 开头的 token
- code-block-view.ts: RunCodeOpts 加 overridesJson 字段,runCode 改传 extractLang/extractOverridesJson 提取结果
- index.ts: EditorOptions.onRunCode 类型同步加 overridesJson
- 测试: extractOverridesJson 6 例 + code-block-view 点击断言更新(纯语言名 + overridesJson)
2026-07-06 18:17:33 +08:00
0c1e8b7640
feat(bridge): 新增 make_run_code_closure 桥接编辑器内运行代码
...
tiptap_bridge.rs:
- EditorOptions extern 追加 set_on_run_code setter (js_name=onRunCode)
- 新增 RunCodeOptsJs 映射(language/source/overridesJson getter)
- 新增 format_run_result + make_run_code_closure
· start_exec + 500ms 轮询 get_exec_result,30s 上限
· overridesJson 空串视为 None,畸形 JSON 静默降级
· 不依赖 server-only 的 languages 模块(前端 extractLang 已提取纯语言名)
- EditorHandle 加 _on_run_code 字段 + new 参数
- pub use 导出 make_run_code_closure + RunCodeOptsJs
write.rs: 跟进 EditorHandle::new 新签名(构造 on_run_code + set_on_run_code)。
2026-07-06 18:11:28 +08:00
6bdc48e84c
feat(editor): CodeBlock NodeView 工具栏与结果区样式
...
语言标签 + 运行按钮 + 结果区,亮/暗双套 Catppuccin 配色。
runnable 绿条移到 .tiptap-codeblock 容器(替换旧 pre 绿条规则)。
2026-07-06 18:02:32 +08:00
6e5ff72a29
feat(editor): 挂载 CodeBlockNodeView + editor.storage 注入 onRunCode
...
CodeBlockLowlight.extend({ addNodeView }) 接入自定义 NodeView。
EditorOptions 新增 onRunCode 字段;编辑器初始化时挂到 editor.storage,
NodeView 经 storage key 读取(仿 upload-coordinator 范式)。
2026-07-06 18:00:15 +08:00
82280e3d4f
feat(editor): CodeBlockNodeView 显示语言标签与运行按钮
...
自定义 NodeView 包裹 <pre><code>,顶部工具栏显示语言(extractLang 提取),
runnable 块额外显示运行按钮。contentDOM 指向 <code>,保证 CodeBlockLowlight
decoration(高亮)正常生效。运行走 editor.storage.__onRunCode 回调。
2026-07-06 17:59:01 +08:00
0adc6d8382
fix(editor): 暗色 type 色值修正 + extractLang 小写化
...
- .dark .hljs-type/.hljs-title.class_ 由 #8839ef(紫) 改为 #f9e2af(黄),
与 spec 表、官方 @catppuccin/highlightjs、读者侧 highlight.css 三处对齐
- extractLang 加 toLowerCase,与后端 parse_fence_info(languages.rs:85)对齐,
避免大写语言名触发 lowlight Unknown language 抛错
2026-07-06 16:13:08 +08:00
4de48cd16c
style(editor): biome 修正 import 排序(highlight/index)
...
TDD 阶段子代理未跑 biome check --write,补齐 import 字母序以过 make lint。
2026-07-06 15:53:16 +08:00
8493e4c4c4
feat(editor): 代码块语法高亮配色(Catppuccin Latte/Mocha)
...
色值取自 @catppuccin/highlightjs@1.0.1,与读者侧 highlight.css 同一 palette。
亮/暗双套,.dark 前缀切换,scope 到 .tiptap-editor 避免污染全站。
2026-07-06 15:50:35 +08:00
e86fe0767d
feat(editor): 用 CodeBlockLowlight 替换 StarterKit 自带 CodeBlock
...
禁用 StarterKit codeBlock,引入 CodeBlockLowlight + lowlight 实例。
代码块现在有实时语法高亮(ProseMirror decoration),language 属性
仍承载完整 info string(markdown 往返不变)。
2026-07-06 15:48:02 +08:00
e79e0d9ee2
feat(editor): 新增 lowlight 实例与 extractLang 语言提取
...
common 集(~35 种语言)注册到 lowlight;extractLang 从完整 info string
(如 'python runnable {...}')提取首 token,使 runnable 块按正确语言高亮。
2026-07-06 15:45:42 +08:00