我在 Cursor Blinking Blog 里做了一个叫“纸上”的功能,方便我在分发内容前制作封面和海报,解决内容从完成到发布最后一公里的泥泞路。
排版工具很多,我为什么还要再做一个?答案很简单:可控、好玩。
“纸上”是一个内容驱动的排版系统:输入内容,选择版式,系统先完成大部分机械工作,人再把精力放在真正影响阅读和审美的细节上。
从结构上看,它仍然是最朴素的三段式:输入、处理、输出。
输入
“纸上”支持两种输入:直接粘贴文字,或者从博客内容库导入文章。当前实现没有让 AI 直接决定文章结构,而是通过简单规则提取标题、摘要、正文段落和媒体信息。这样,同一篇文章在同一版本中总能得到相同的基础输入。
处理
基础语义
“纸上”目前把模板分为五类:封面、海报、杂志、手账和新闻。不同分类使用不同画布,但共享同一套设计语言。封面、海报、手账更注重设计,杂志、新闻更注重内容。
从产品视角看,一个模板可以分成两层:
- 背景层,负责纸张颜色、纹理、网格或背景图片;
- 排版层,负责标题、正文、图片、辅助信息和装饰之间的空间关系。
版面的坐标系统由两层网格组成:
- 4 × 4px 是 Atomic Unit,负责保存坐标、细线、间距和精细调整;
- 16 × 16px 是 Layout Cell,负责日常拖动、缩放和大结构吸附。
一个 Layout Cell 正好由 4 × 4 个 Atomic Unit 组成。编辑时默认按 16px 粗调,需要时再切换到 4px 精调;无论使用哪一档,最终保存的仍是统一的 Atomic 坐标。这套约束看起来有些“死”,但它带来了非常简单的规则,本质上就是在 16*16px 的网格上圈出一个一个矩形。
有了规则,就可以让 AI 帮我生成模版,或者从效果图提取模版。
板块冲突
版面设计里,重叠不一定是错误。标题压在图片上可能是用户刻意的设计,但文字叠在另一段文字上面通常是问题。因此,“纸上”把重叠分成四种协议:
allow:刻意叠放,保留两个矩形和各自的层级;exclude:外接矩形可以相交,但文字需要避开视觉对象的实际占用轮廓;ignore:纯装饰关系不参与碰撞;forbid:不允许重叠,编辑器需要给出警告。
对于带透明区域的插画,还可以选中多个板块进行合并,达到文字围绕图片(不透明区域)的效果。
有了以上基础,就可以让 AI 基于内容推荐模版,或者用户手动选择模版,然后在选中模版的基础上进行内容适配。
自动排版
内容进入模板之后,往往会出现某个板块内容太长,超出板块的矩形范围,或者某个板块内容太少,看起来太空。
当前使用的不是“无限自动调整”,而是一套有优先级、失败时会明确报警的内容适配状态机。它优先处理空区块,先做轻微缩放,然后沿 16px 网格扩展区块,在扩展后的空间里再次求解字号。如果还有溢出,就报警,交由人工处理。
输出
排版之后,可以下载,也可以通过 MCP 同步到 Figma 进行更进一步的调整(如果你喜欢使用 Figma 进行调整)。模版也会记录最终应用的定格版本。之前生成或提取的模版都较粗略,经过多次使用的投影会固化出确定版本的模版。
后续
“纸上”注定是一个需要在使用中不断迭代的功能。真正让排版系统变好的,不是再增加一个“智能生成”按钮,而是不断拿真实内容去使用它,找到那些细小但持续发生的问题,再一处一处把它们擦除掉。