feat(editor): 图片可选中换行、可调大小、右键链接针对图片(docs/31)
用户反馈三件:图片选不中没法在后面打字、右键不能改大小、图片的 超链接是空的。无头 Chrome 真实点击复现根因:点击能形成节点选区 但无任何视觉提示;图片选中时按 Enter 走 splitBlock,新段落插到 图片前面且选区仍停在图片上,接着打字会把图片替换掉。 - Enter 修复:捕获阶段 keydown 只接管图片选区,在图片所在文本块后 插空段落并移入光标(createParagraphNear 对行内节点无效,自己写); 选中图片加主题色描边。 - 大小:图片节点加 width 属性,带尺寸时序列化为 <img … width>、 否则标准语法;remark 插件把孤立 <img> 解析回图片节点(实体解码、 块级包段落),往返逐字一致;右键「调整图片大小…」弹窗 px/% 可调。 - 链接:右键图片的「超链接…」改为图片模式,预填包裹链接、提交对 图片节点挂/摘 link 标记([](href) 可往返)。 验证:vitest 148+2(新增 image-size/image-enter 共 12 例)、构建通过、 无头 Chrome 实测点击/Enter/打字全流程。
This commit is contained in:
71
docs/31-图片编辑体验.md
Normal file
71
docs/31-图片编辑体验.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# 31 图片编辑体验(选中 / 换行 / 大小 / 链接)
|
||||
|
||||
用户真机反馈三件事:①右键图片无法编辑大小;②右键图片点「超链接」是
|
||||
空的;③图片无法选中、没法在图片后面输入文本(按回车只能在前面换行)。
|
||||
|
||||
## ③ 选中与换行(根因)
|
||||
|
||||
无头 Chrome 实测复现(真实鼠标点击):
|
||||
|
||||
- 点击图片本身能形成 NodeSelection、点图片右侧也能把光标落在图片后——
|
||||
但选中态**没有任何视觉提示**(PM 给的 `ProseMirror-selectednode`
|
||||
类没有样式),用户感知就是「选不中」。
|
||||
- 真正的死结在 Enter:图片被选中时按 Enter,默认命令链走 splitBlock,
|
||||
空段落插到图片**前面**、选区仍停在图片上;接着打字会把图片**替换掉**。
|
||||
这就是「只能在前面的文本处换行」的由来。
|
||||
|
||||
修法(`createImageEnterPlugin`,plugins.ts):
|
||||
|
||||
- 插件 view 生命周期里给编辑器 DOM 挂**捕获阶段** keydown 监听(预置
|
||||
Enter keymap 插件排在本插件之前,props.handleKeyDown 轮不到);
|
||||
只接管「图片 NodeSelection + 无修饰 Enter」:在图片所在文本块之后
|
||||
插入空段落并把光标移进去,其余 Enter 全部放行。
|
||||
- 注意 `createParagraphNear` 用不上:它对行内节点直接返回 false
|
||||
(只处理块级选区),故插入逻辑自己写(resolve 到文本块深度、
|
||||
after(depth) 处插段落)。
|
||||
- CSS 给 `img.ProseMirror-selectednode` 加 2px 主题色描边,选中可见。
|
||||
|
||||
实测(无头 Chrome,真实点击):点击→NodeSelection+描边;Enter→新段落
|
||||
在图片之后、光标在其中;打字落在新段落、图片完好。
|
||||
|
||||
## ① 图片大小
|
||||
|
||||
Markdown 没有尺寸语法,通行写法是 HTML。方案(imageSchema.ts):
|
||||
|
||||
- 包裹 preset 的 imageSchema:节点加 `width` 属性(字符串,`300`=px、
|
||||
`50%`=百分比)。
|
||||
- 解析:remark 插件(条目形状必须是 `{ plugin, options }`,裸函数不
|
||||
生效)把孤立的 `<img …>` mdast html 节点换成 image 节点,width 存
|
||||
data;根级(块级)要包一层 paragraph,行内原地替换。属性值做一遍
|
||||
实体解码(mdast 保留源码原文,如 `"`)。
|
||||
- 序列化:有 width 时发 `<img src alt title width>` html 节点(属性
|
||||
转义),无 width 时仍发标准 ``,普通文档零影响。
|
||||
- NodeView 按 width 设置 img 的 CSS 宽度(纯数字补 px)。
|
||||
- UI:右键图片 →「调整图片大小…」弹窗(数值 + 像素/百分比分段钮,
|
||||
可恢复原始大小)。带尺寸的图片在源文件里就是 HTML 形式,弹窗里
|
||||
有明示。
|
||||
|
||||
往返实测:`<img src="b.png" alt="乙" width="300">` 解析/序列化逐字
|
||||
一致;普通图片、非 img 的 HTML 均不受影响(tests/image-size.test.ts)。
|
||||
|
||||
## ② 图片超链接
|
||||
|
||||
原「超链接」是文本链接:对选区套 link 标记,预填只有 `https://`,
|
||||
对着图片点开自然是「空的」。图片的链接在 Markdown 里是包裹式
|
||||
`[](href)`——实测这在本编辑器里可往返(link 标记挂在
|
||||
图片节点上,解析/序列化都保留)。
|
||||
|
||||
修法:右键命中图片时,「超链接…」打开图片模式的链接弹窗——预填
|
||||
图片当前的包裹链接(没有就是空),提交后用一条事务对图片节点
|
||||
addMark/removeMark(editor.ts 的 `updateImageAtElement`,与尺寸
|
||||
共用);清空即移除链接。文本选区的链接流程不变。
|
||||
|
||||
配套的编辑器接口(EditorPaneApi):`imageInfoForElement`(读
|
||||
src/alt/width/linkHref)、`updateImageForElement`(按元素定位节点
|
||||
改属性,右键菜单打开时记住元素与标签 id)。
|
||||
|
||||
## 待真机验
|
||||
|
||||
- WebView2 里点击图片的选中手感(本机为 Chromium 实测);
|
||||
- 调整大小后图片在文档中的实际观感与保存后重开的还原;
|
||||
- 图片在列表/引用/表格里时 Enter 新段落的位置是否符合预期。
|
||||
Reference in New Issue
Block a user