|
|
246d8a6d67
|
feat(libs): add xterm-terminal IIFE library (xterm.js 6.0)
New pnpm workspace package @yggdrasil/xterm-terminal, output to
public/xterm/. Output-only terminal (disableStdin) for streaming
container stdout/stderr via SSE.
- @xterm/xterm@^6.0.0 + @xterm/addon-fit@^0.11.0 (released same day,
2025-12-22; 0.10.0's peerDependency is ^5.0.0 and incompatible)
- convertEol: containers emit \n, xterm needs \r\n
- stderr wrapped in ANSI red for visual distinction
- Catppuccin Latte/Mocha themes matching project highlight.css
- Mirrors codemirror-editor IIFE pattern: object literal default export,
XtermOptions as class (survives TS erasure for wasm-bindgen)
- css.d.ts declares *.css module for tsc side-effect import
|
2026-07-10 11:37:04 +08:00 |
|
|
|
81682eb70e
|
fix(post): 修复 hash 锚点跳转失效
内容异步加载(use_server_future)导致骨架屏阶段标题 DOM 缺失,浏览器原生
fragment-scroll 找不到目标留在顶部;刷新页面也因 SSR 出的是骨架屏而失效。
- 新增 __scrollToHash 全局入口(yggdrasil-core):内容挂载后解码
location.hash(CJK 百分号编码 → 原始字符)并 scrollIntoView
- PostContent use_effect 末尾复用 invoke_optional_global 调用,标题
DOM 已就绪时补一次滚动
- 标题加 scroll-margin-top: 6rem,避开 80px sticky header
点击 TOC/标题 hashtag 由原生 anchor + scroll-margin-top 覆盖,无需 JS。
|
2026-07-10 00:21:08 +08:00 |
|
|
|
1584e01425
|
chore(deps): update all cargo and pnpm dependencies to latest versions
|
2026-07-09 18:12:54 +08:00 |
|
|
|
1521414cad
|
fix(code-runner): 修复编辑器内运行结果不换行
resultArea 挂在 ProseMirror 可编辑文档树内部,浏览器对 contenteditable
子树强制 white-space 折叠(computed 为 collapse),CSS 的 white-space:
pre-wrap 被覆盖,导致 textContent 里的 \n 与行首空格被吞、多行输出挤成一行。
改用 <br> 显式渲染换行、\u00A0 替换空格/制表符以保留对齐——二者均不依赖
white-space。createTextNode 避免 stdout 含 HTML 标签时的注入。
|
2026-07-09 13:25:59 +08:00 |
|
|
|
cda5a92230
|
feat(runner): enable Vim mode toggle for CodeRunner sandbox
|
2026-07-08 14:37:52 +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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
0b4346ecd4
|
fix(editor): 语言下拉展开时 Enter 不误触发插入
<select> 展开时 Enter 用于确认选项,不应提交整个弹框。
HTMLSelectElement.open 浏览器存在但 TS lib.dom 未声明,用交叉类型断言。
|
2026-07-06 14:15:25 +08:00 |
|
|
|
9b4c0ea36e
|
style(editor): biome 格式化 runnable 模态框代码
biome check --write 修正 import 排序 + 格式化 openRunnableModal 链式调用
(TDD 阶段子代理未跑 make fix,此处补齐以过 make lint)。
|
2026-07-06 14:08:06 +08:00 |
|
|
|
01ceef2694
|
feat(editor): 可运行代码块模态框样式 + runnable 块绿色边框
模态框复用 Catppuccin Latte/Mocha 配色;编辑器内含 runnable 标记的
代码块加左侧绿色边框(与 Code Runner 运行按钮主色一致)。
|
2026-07-06 14:04:52 +08:00 |
|
|
|
d6fc98d253
|
feat(editor): 斜杠菜单新增「可运行代码块」条目
触发 openRunnableModal,配置后插入标准 CodeBlock(language 承载
'python runnable {...}' info string)。
|
2026-07-06 14:02:12 +08:00 |
|
|
|
5929ab68b4
|
feat(editor): 新增 openRunnableModal 模态框配置可运行代码块
原生 DOM 模态框(遮罩+卡片),语言 select + 超时/内存/网络 3 项 overrides
+ 实时预览。确认插入 setCodeBlock({language: 'python runnable {...}'}),
Esc/遮罩/取消关闭不插入。
|
2026-07-06 13:58:51 +08:00 |
|
|
|
84b3da9db6
|
feat(editor): 新增 buildRunnableInfo 构造 runnable fence info string
纯函数,把语言+overrides 配置转成 'python runnable {...}' 形态。
dirty=false 省略 JSON,dirty=true 写 timeout/memory/network 三项,
字段顺序固定。
|
2026-07-06 13:45:11 +08:00 |
|
|
|
89bab26b90
|
fix(lint): themes.ts import 排序(type import 前置)
Biome organizeImports 要求 import type 排在普通 import 之前,
交换 @codemirror/view 与 @codemirror/state 顺序。make lint 全绿。
|
2026-07-06 11:45:14 +08:00 |
|
|
|
d3c2e41fd8
|
fix(codemirror): 编辑器塌缩导致上下背景割裂(height:100% 失效)
上一提交(3c10f72)用 `& { height: 100% }` 让 .cm-editor 撑满容器,
但实测无效——headless chromium 抓取 computed style 显示:
容器#ed: h=280px (min-height)
.cm-editor: h=63px ← 塌缩!只有内容高度
.cm-gutters: h=63px
.cm-content: h=63px
根因:CSS 百分比高度要求父元素有「明确 height」(不是 min-height)。
容器只有 min-height: 280px,没有 height,`.cm-editor { height: 100% }`
解析为 auto,塌缩到内容高度(3 行 ≈ 63px)。剩余 217px 透出容器背景
(paper-entry/mantle),与 .cm-editor 的 base 色形成上下割裂。
修复:改用 flexbox 而非百分比高度——
- themes.ts:`& { flex: 1 1 0; minHeight: 0 }`(替换 height:100%)
- 容器(system.rs / runner.rs):`display: flex; flex-direction: column`
flex 子项的 `flex: 1` 不依赖父元素 height,能真正填满 min-height 撑开
的空间。headless 验证:.cm-editor 现为 280px,与容器一致,割裂消失。
诊断方法:构建自包含测试 HTML(内联 editor.js),chromium --headless
--dump-dom 抓 getComputedStyle。这是应有的反馈循环,避免了前几轮
凭代码猜测导致的反复误诊。
|
2026-07-06 00:20:55 +08:00 |
|
|
|
3c10f72444
|
fix(codemirror): 编辑器未撑满容器导致上下背景割裂
现象:编辑器「有行号的上半部分」与「空白下半部分」背景色不一致。
根因:CodeMirror core 的 base theme 给 `.cm-editor`(&)只设了
position: relative + display: flex,没有 height。编辑器默认只占
内容高度(几行 ≈ 60px),不填满父容器。容器 div 设了 min-height:
280px,但 .cm-editor 不会自动撑到 280px——剩余空间透出容器的
paper-entry(mantle #e6e9ef) 背景,与 .cm-editor 的 base(#eff1f5)
形成「上半 base / 下半 mantle」的上下色差。
修复:themes.ts 的覆盖里加 `& { height: 100% }`,让 .cm-editor
撑满父容器。配合容器已有的 min-height: 280px,编辑器完整填充,
背景统一为 base 色,上下割裂消失。
|
2026-07-06 00:06:00 +08:00 |
|
|
|
64907401a0
|
fix(codemirror): 行号区背景与代码区割裂(core base theme 覆盖 catppuccin)
现象:行号列(gutter)背景是 #f5f5f5 浅灰,代码区(content)是 catppuccin
base #eff1f5 浅蓝灰,两者不一致,有明显割裂。
误诊修正:上一提交(e1b312e)以为是容器背景与 CodeMirror 层次扁平,
改了容器为 code-block(crust)。但 CodeMirror 内部 .cm-editor 和
.cm-gutters 都有不透明背景,容器色根本透不出来——所以「没效果」。
本次回退该容器改动。
真因:CodeMirror core 的内置 base theme(@codemirror/view dist index.js:6916)
给 `&light .cm-gutters` 设了 backgroundColor: "#f5f5f5" / dark "#333338",
特异性为 .cm-editor.cm-light .cm-gutters,高于 @catppuccin/codemirror
的 .cm-gutters 覆盖,catppuccin 的 base 背景被 core 默认灰压制。
修复:themes.ts 在 catppuccin extension 之后追加一个 EditorView.theme,
用 backgroundColor: transparent !important 强制 .cm-gutters 透明,
继承 .cm-editor 的 base 色,行号区与代码区完全融合。light/dark 同理。
|
2026-07-05 23:58:18 +08:00 |
|
|
|
4239602f3d
|
feat(codemirror): 支持 Ctrl/Cmd+Enter 运行快捷键
按钮一直写着「执行 (Ctrl+Enter)」但快捷键从未接线——basicSetup 不含
自定义 keymap。从底层往上打通 Mod-Enter 运行通道:
editor.ts:
- EditorOptions 加 onRunShortcut 可选回调
- constructor 条件注入 keymap.of([{ key: "Mod-Enter", ... }])
- 用 Prec.highest 包裹:@replit/codemirror-vim 的 vimPlugin 在
ViewPlugin 层拦截按键,普通 keymap 会被吞;vim 自己也用
Prec.highest,跟随此惯例保证 Mod-Enter 在 vim 之前命中
- 放在 vimCompartment 之前,满足「vim 必须在 keymap 最前」约束
- Prec 从 @codemirror/state 引入(不在 @codemirror/view)
codemirror_bridge.rs:
- EditorOptions extern 加 set_on_run_shortcut
- EditorHandle 加 _on_run_shortcut 字段保生命周期,new() 签名增加
该参数(Drop 随实例释放)
调用点适配:
- CodeRunner(runner.rs)传 no-op 闭包(不用该功能但签名要满足)
- SQL 控制台的接线在后续 system.rs 改动中完成
|
2026-07-05 21:31:03 +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 |
|
|
|
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 |
|
|
|
90fc6977b0
|
feat(editor): Tiptap 编辑器配色迁移到 Catppuccin(Latte/Mocha)
编辑器 CSS 此前用硬编码 GitHub 风格色(#0366d6/#d73a49/#24292e 等),
独立于 paper-* 语义 token。逐元素重映射到 Catppuccin 调色板:
亮色 Latte:正文 text、标题 text、placeholder overlay0、
行内 code surface0/red、pre crust、blockquote surface1/subtext0、
hr surface1、链接 blue、selection surface0、表格 surface1/crust、
slash 弹层 mantle/surface0、checkbox/选中态 green(主强调)
暗色 Mocha:对应角色映射(text/cdd6f4 等)
上传遮罩的 rgba(255,255,255,*) 白字与 rgba(239,68,68,*) 红删除按钮
属中性覆盖层,保留不动。
|
2026-07-03 14:18:03 +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 |
|
|
|
a47e1e6027
|
refactor(build): workspace 根迁移至 libs/,Makefile 整合 lint/fix
将 pnpm workspace 根从项目根移到 libs/,项目根保持纯 Rust,JS 工作区自治:
- package.json/pnpm-workspace.yaml/pnpm-lock.yaml/biome.json 迁入 libs/
- pnpm-workspace.yaml glob 从 'libs/*' 改为 '*'(已在 libs/ 内)
- biome.json 关闭 vcs.useIgnoreFile(libs/ 无独立 .gitignore,
files.includes 已显式排除 node_modules/dist)
- Makefile 所有 pnpm/biome 调用加 'cd libs &&' 前缀
Makefile 同步整合 lint/fix(替代独立 clippy/fix target):
- make lint = biome check (libs) + cargo clippy
- make fix = biome format --write (libs) + cargo fix
- 删除 8 个 build-*-incremental/build-* target,改为 build-libs 聚合 +
build-<name> 用 pnpm --filter 单库便利 target
修复 biome 格式化回归:tiptap-editor/src/index.ts:83 的 sourceTextarea!.value
被 biome 误转为可选链 ?.,导致 TS2345(string | undefined 不匹配 string),
已还原为非空断言。
|
2026-07-02 18:02:52 +08:00 |
|
|
|
b1b1c88a74
|
chore(biome): 引入 Biome v2.5 monorepo 配置并格式化全量源码
新增根 biome.json(v2.5,v2 起原生支持 monorepo,子包自动向上查找):
- formatter: 2 空格缩进、单引号、行宽 100、LF、尾逗号、箭头函数括号
(匹配现有代码风格)
- linter: recommended preset + 项目化裁剪
- useTemplate/useTemplate off(geometry.ts 故意保留字符串拼接,
且测试用精确浮点断言锁定行为)
- noNonNullAssertion off(测试与 DOM 访问里的 ! 是惯用写法)
- noConsole off(4 个 lib 用 console.error/warn 做错误上报)
- CSS 关闭 noDescendingSpecificity/noDuplicateProperties
(手写 CSS 的 fallback 模式)
- useImportType/useNodejsImportProtocol/noUnusedVariables warn
- vcs.useIgnoreFile 自动读 .gitignore;排除 public/target/node_modules/
dist/.dioxus/static + Tailwind 入口 input.css(含 @theme 等 Biome 无法
解析的 at-rules)
首次格式化覆盖 29 个源文件:import 排序、node: 协议、引号/缩进统一,
并修复 index.ts 两处 forEach 回调隐式返回值(useIterableCallbackReturn)。
90 个 vitest 用例全绿,确认无语义改动。
|
2026-07-02 17:54:46 +08:00 |
|
|
|
79ceb307ad
|
chore(workspace): 建立 pnpm workspace 与共享 tsconfig
将 libs/ 下 4 个独立 pnpm 项目整合为 workspace:
- 新增根 package.json/pnpm-workspace.yaml,4 份重复的 devDeps
(happy-dom/typescript/vite/vitest,版本零分歧)上提到根,各 lib 只留运行时依赖
- 新增 libs/tsconfig.base.json,4 份逐字节相同的 tsconfig.json 改为 extends
- per-lib pnpm-lock.yaml 合并为根 lockfile;冗余的 libs/{lightbox,yggdrasil-core}/.gitignore 删除
(根 .gitignore 的 **/**/node_modules 已覆盖)
收益:依赖共享安装(node_modules 去重)、构建/测试可用 pnpm -r 统一调度,
单库仍可 pnpm --filter @yggdrasil/<name> 独立操作。构建与测试均验证通过(90 个 vitest 用例全绿)。
|
2026-07-02 17:50:52 +08:00 |
|
|
|
0772951867
|
fix(editor): 修复升级后空项 Enter 不退出列表(根因:畸形文档)
bug 表现:- [ ] 123 升级成任务列表后,空项按 Enter 不退出,而是继续新建空项。
根因有两处,都在 appendTransaction 构造新节点时:
1. stripPrefix 作用域错误:原代码 cut 作用在 listItem.content(把段落节点
当原子),cut(N) 会切进段落的标签边界,产生畸形文档——段落文本前缀残留
(如' 未完成'多出空格)、nodeSize 与实际不符。修正为作用在段落内部的
content 上(用 para.type.create 重建段落),并用 Fragment.replaceChild
替换 listItem 的第一个子节点。
2. 光标位置少算一层:+1 进 taskList 内容,+offset 到命中 taskItem,+1 进
taskItem 内容(段落节点位置),还需 +1 进段落内容(文本),原代码漏了
这最后一个 +1,导致光标落在文本中间而非末尾,splitListItem 在错误位置
分裂(把'123'拆成'12'+'3')。
畸形文档 + 光标错位 → splitListItem 在错误位置分裂,产生的'空'taskItem
实际不空,二次 Enter 走分裂路径而非退出路径。
新增回归测试:段落文本无残留 + 完整 Enter 链路(升级→Enter 空项→Enter 退出)。
|
2026-07-02 15:27:37 +08:00 |
|
|
|
53b53d3169
|
fix(editor): appendTransaction 加重入防护 + Enter 行为测试
用户反馈:升级成 taskList 后,空项按 Enter 未退出列表(与斜杠命令创建的
行为不一致)。
单测用 splitListItem 命令验证:升级后的 taskList,有内容项 Enter 分裂出空
taskItem,空项 Enter 正确退出列表(doc 末尾产生 paragraph)。行为与斜杠
命令创建的一致。说明 appendTransaction 产生的节点结构合法。
追加防护:给 appendTransaction 返回的 transaction 打 pluginKey 标记,
重入时跳过,避免 Enter 等操作的文档变化被本插件二次干扰。
happy-dom 无法可靠模拟真实 keydown 链路(派发 KeyboardEvent 时光标映射
不准),Enter 的 bug 需真实浏览器复现。
|
2026-07-02 14:59:53 +08:00 |
|
|
|
873ccb1a80
|
fix(editor): task list label 内 checkbox 居中
label 默认是 inline 元素,内部 checkbox(inline-block)受父级行高影响会产生
基线间距,导致 checkbox 在 label 盒子内偏上,即便 li 用了 align-items: center
也只对齐了 label 盒子而非 checkbox 本身。
给 label 加 display: flex + align-items: center + line-height: 0,消除行高
撑出的基线空间,让 checkbox 严格居于 label 盒子中心。
|
2026-07-02 14:42:52 +08:00 |
|
|
|
4e96243407
|
style(editor): 任务列表 checkbox 与文本垂直中线对齐
与前台 input.css 同步,编辑器内 task list 同样改为 align-items: center。
- li: flex-start → center,实现真正的中线对齐
- label: 去掉 margin-top: 0.3em(center 已处理)
- 新增 li > div > p { margin: 0 }:task list 项内段落清掉默认 .6em 0
上下 margin,否则 margin 撑高 div 导致 checkbox 与文本错位、项间距过大
|
2026-07-02 14:38:59 +08:00 |
|
|
|
250fe653c1
|
fix(editor): 修复任务列表升级后光标被甩到下一行
appendTransaction 用 replaceWith 整段替换 bulletList→taskList,ProseMirror 的
选区映射无法把原 listItem 内的光标正确映射到新 taskItem 内,默认落到替换
区域之后(下一行)。
显式用 TextSelection.near 把光标设到命中的 taskItem 段落文本末尾:
按命中项在 newItems 中的索引 + 段落文本长度算出目标 pos。
新增光标位置断言(selection.from === 3,即 doc>taskList>taskItem>paragraph 内)。
|
2026-07-02 14:25:57 +08:00 |
|
|
|
4a27236859
|
fix(editor): TaskInputRule 改用 appendTransaction(逐字符输入才生效)
input rule 方案对逐字符输入无效:BulletList 在用户打 - (第2字符)时就抢先
触发,把行变成 bulletList>listItem,之后 [ ] 在 listItem 内无法被任何
input rule 升级。提高 priority 也无济于事——BulletList 在更短文本上抢先。
改用 appendTransaction 监听文档变化:BulletList 触发后,用户在 listItem 里
打出 [ ] / [x] 前缀时,把该 bulletList 整体替换成 taskList,对应 listItem
转成带 checked 的 taskItem 并删除已识别的文本前缀。
- 测试模拟逐字符时序:先 - (applyInputRules 触发 BulletList),再 [ ]
(appendTransaction 升级),5 个用例覆盖未勾选/已勾选/大写/不误判/星号
- * + - 三种 marker 的 bulletList 都会升级(BulletList 对三者创建同种节点)
|
2026-07-02 14:16:34 +08:00 |
|
|
|
4a76397af8
|
feat(editor): 支持 - [ ] 手动输入创建任务列表
Tiptap 官方 TaskItem 的 input rule 只匹配 [ ] 不含 marker,且 StarterKit
的 BulletList input rule /^\s*([-+*])\s$/ 在用户打 - 时就抢先触发,把这行
变成无序列表;后续的 [ ] 沦为字面文本,getMarkdown 序列化时转义成 \[ \],
前台无法渲染成 checkbox。
- 新增 TaskInputRule 扩展,priority 1000 抢在 BulletList(默认 100)之前,
正则 /^(\s*-\s)\[( |x|X)\]\s$/ 匹配 - [ ] / - [x],
wrappingInputRule 包裹成 taskList > taskItem(findWrapping 自动补齐两层)
- 仅识别减号 marker(* + 仍走 BulletList),Enter 续行复用 TaskItem 内置
splitListItem,不重复实现
- 新增 task-input-rule 测试(真实 Editor + happy-dom):覆盖未勾选/已勾选/
大写 X/不误判普通列表/星号 marker
|
2026-07-02 13:56:11 +08:00 |
|
|
|
c74e59485d
|
feat(editor): add codemirror-editor subproject + Rust bridge
新建 libs/codemirror-editor(pnpm/Vite IIFE/@catppuccin/codemirror Catppuccin
Latte+Mocha 主题/@codemirror/lang-sql schema 补全/@replit/codemirror-vim),
输出 public/codemirror/。Rust 桥接 codemirror_bridge.rs 镜像 tiptap_bridge.rs
(Reflect::get 取对象字面量 + EditorHandle 持有闭包 + Drop→destroy)。
接入 Makefile/Dioxus.toml/.gitignore。
注意:thememirror 不含 catppuccin 主题,改用官方 @catppuccin/codemirror@1.0.3
(导出 catppuccinLatte/catppuccinMocha)。
|
2026-06-29 18:24:38 +08:00 |
|