- 前端
- 桌面应用
- AI 应用
- MCP 服务
【免费下载链接】open-pencil
AI-native design editor. Open-source Figma alternative.
本文围绕 OpenPencil(开源 Figma 替代方案、AI 原生设计编辑器)的 JSX 渲染器展开,系统讲解如何把 JSX 作为声明式设计语言:在 AI 聊天、MCP 工具与evalCLI 中通过render传入 JSX 字符串创建设计,在无界面代码或库中通过renderJSX/renderTree把 JSX 渲染进场景图,以及用export命令把既有设计反向导出为可读、可 diff、可复用的 JSX 或 Tailwind 代码。读完本文,你将掌握 OpenPencil JSX 的完整元素与样式属性体系、底层渲染管线(sucrase 编译 → 树解析 → 场景图节点创建 → 自动布局),以及用代码评审(Code Review)与版本管理承载设计变更的工程化工作流。
JSX 作为声明式设计语言
OpenPencil 把 JSX 用作设计创作的声明式语言:一段 JSX 即描述一个设计树,适合 AI Agent、脚本与可复现的界面构建。同时 JSX 也是既有设计的可读表示——设计变更表现为普通的代码 diff,便于人工审查、存入版本控制系统,甚至放到 CI 中自动分析。
其核心思路与前端组件化完全一致:用Frame(容器)和Text(文本)等元素声明层级与样式,再交给渲染器转换为真正的场景图节点。相比在画布上手工拖拽,JSX 方式的优势在于可复现、可审查、可自动化。
一段最小设计示例
<Frame name="Card" w={320} h="hug" flex="col" gap={16} p={24} bg="#FFF" rounded={16}> <Text size={18} weight="bold">Card Title</Text> <Text size={14} color="#666">Description text</Text> </Frame>这里<Frame>声明了一个宽 320、高度自适应(hug)、纵向 flex 布局(flex="col")、子元素间距 16、内边距 24、白色背景、圆角 16 的卡片容器;两个<Text>作为其子节点声明标题与描述文本。这段 JSX 可直接在 AI 聊天、MCP 的render工具或evalCLI 中执行,渲染出一个真实的图层树。
使用render渲染 JSX 的三种途径
render工具同时存在于以下三个入口,均接收 JSX 字符串:
| 入口 | 使用方式 |
|---|---|
| AI 聊天(Chat) | 直接向 AI 会话中的render工具传入 JSX 字符串 |
| MCP 服务器 | 通过 MCP 工具调用render,传入 JSX 字符串 |
evalCLI | 在命令行执行包含 JSX 的代码(见openpencil eval,底层通过 RPC 调用eval执行并渲染) |
三种入口共享同一套 JSX 语法与渲染语义,因此同一个设计代码段可以在不同场景间无缝迁移。
在无界面代码中渲染:@open-pencil/design-jsx与@open-pencil/core/design-jsx
在不经过聊天/MCP/CLI、而是从应用代码或库中直接创建设计时,需要引入两组包:
@open-pencil/design-jsx:提供Frame、Text等元素函数(组件工厂),用于在 TypeScript 中直接拼装设计树。其导出内容见 packages/design-jsx/src/index.ts,包括Frame、Text、Rectangle、Ellipse、Line、Star、Polygon、Vector、Group、Section、Component、ComponentSet、Instance及其别名View(=Frame)、Rect(=Rectangle)、Page(=Frame)。@open-pencil/core/design-jsx:提供renderJSX与renderTree两个渲染函数,负责把 JSX 字符串/设计树真正渲染进场景图。它们来自 packages/core/src/design-jsx/index.ts,底层由 packages/core/src/design-jsx/renderer.ts 通过createDesignJSXRenderer绑定引擎服务实现。
@open-pencil/core/design-jsx的渲染器绑定的是 OpenPencil 引擎提供的三类服务(见 packages/core/src/design-jsx/renderer.ts#L39-L48):
- 图标(
icon):按名称与尺寸拉取 Iconify 图标数据; - SVG 转换(
svg):把内联<svg>标记提取路径并按 viewBox 缩放,走与图标相同的管线; - 布局(
layout):渲染完成后调用computeAllLayouts计算自动布局。
因此renderJSX/renderTree天然具备图标、内联 SVG 与自动布局能力,这就是原文档所说"它们添加图标、SVG 转换与布局"的底层来源。
两个函数的签名差异:renderJSX(graph, jsxString, options)接收 JSX 字符串(内部用 sucrase 编译),renderTree(graph, tree, options)接收已用元素函数构建好的TreeNode树;两者共享RenderOptions(见 packages/design-jsx/src/types.ts):x/y设置根节点位置、parentId指定父节点(默认第一页)、onNode在每创建一个图层时回调(可用来建立源码到图层的映射)。
在 TSX 中书写设计树
若想在.tsx源文件中直接用 JSX 语法书写设计树,需要在tsconfig.json中配置:
{ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "@open-pencil/design-jsx" } }或只在单个文件顶部添加编译指令注释:
/** @jsxImportSource @open-pencil/design-jsx */这样@open-pencil/design-jsx的 JSX 运行时(见 packages/design-jsx/src/jsx-runtime.ts)会接管jsx/jsxs/jsxDEV与Fragment:字符串标签(如frame、text)映射为node(type, props),函数组件则直接调用返回TreeNode。该文件同时声明了JSX.IntrinsicElements接口(frame、text、rectangle、ellipse、line、star、polygon、vector、group、section、component、component-set、instance),为 TSX 提供类型提示。
渲染管线:从字符串到场景图
renderJSX的完整链路(见 packages/design-jsx/src/render.ts 与 packages/design-jsx/src/renderer.ts)可以概括为五步:
- 编译:
buildComponent用 sucrase 把 JSX 字符串编译为函数;编译时自动注入别名(Frame、Text、View、Rect、Component、Instance、Icon、svg及各 Reka 元素命名空间)和辅助函数(solid、gradient、dropShadow、layerBlur、designVar等),因此 JSX 字符串中可直接使用这些名字;同时剥离 HTML 注释。 - 解析:
resolveToTree把编译产物解析为TreeNode(递归函数组件最多 100 层,片段<>…</>会被内联展开,见 packages/design-jsx/src/tree.ts)。 - 校验:对每个节点检查属性名,不支持的属性收集为 warnings(如
Unsupported prop "xxx" on <frame> is ignored.)并随渲染结果返回。 - 建树:
renderNode按TYPE_MAP把元素类型映射为场景图节点类型(frame→FRAME、text→TEXT、group→GROUP等),通过propsToOverrides把 JSX 属性转换为节点字段,再递归渲染子节点。值得注意的映射:div/main/header/footer/nav/article/aside映射为FRAME,span/p/h1~h6映射为TEXT——即可以直接用 HTML 语义标签写设计。 - 布局:所有根节点渲染完成后调用
services.layout(graph)统一计算自动布局,随后返回每个根节点的RenderResult(id、name、type、childIds,可能带warnings)。
若 JSX 未返回任何 Figma 元素,会抛出明确错误:JSX must return a Figma element (Frame, Text, etc)。
元素清单
下表为 OpenPencil JSX 支持的元素(与 packages/design-jsx/src/schema.ts#L35-L53 的DESIGN_JSX_ELEMENTS定义一致):
| 元素 | 创建的节点 | 别名 |
|---|---|---|
<Frame> | 带自动布局的帧容器 | <View>、<Page> |
<Rectangle> | 矩形 | <Rect> |
<Ellipse> | 椭圆或圆 | |
<Text> | 文本对象;子元素内容即文本内容 | |
<Line> | 直线 | |
<Star> | 星形(可用points、innerRadius控制) | |
<Polygon> | 多边形(可用pointCount控制) | |
<Vector> | 矢量路径 | |
<Group> | 编组 | |
<Section> | 画布分区 |
除上表外,schema 还注册了<Component>、<ComponentSet>、<Instance>(组件/组件集/实例)以及<Icon>(Iconify 图标,要求name属性,如name="lucide:heart",默认尺寸 24,见 packages/design-jsx/src/renderer.ts#L231-L245)。<Instance>通过component/componentId/of属性按 ID、名称或组件集变体解析组件,并支持overrides(形如{ "label:text": "…" })按子节点名覆盖实例内容。<ComponentSet>渲染后会依据变体命名(如State=Hover)自动推断变体属性定义(inferComponentSetProperties)。
样式属性体系
属性命名刻意贴近 Tailwind 以保持简洁,且绝大多数支持多别名。从源码 packages/design-jsx/src/schema.ts#L193-L210 的DESIGN_JSX_PROPERTY_ALIASES可以看到完整别名表:w/width、h/height、bg/fill/background/backgroundColor、stroke/border/borderColor、rounded/cornerRadius/borderRadius、rotate/rotation、p/padding、justify/justifyContent、items/align/alignItems、size/fontSize、font/fontFamily、weight/fontWeight、textAlign/textAlignHorizontal/textHorizontalAlignment。渲染器按别名顺序读取第一个已设置的值。
此外还支持style={{ … }}对象形式:DESIGN_JSX_STYLE_KEYS把 CSS 风格键映射回 JSX 属性(如background→bg、fontSize→size、borderWidth→strokeWidth、width/height等),px字符串如'320px'会被解析为数字;直接属性优先于style(见 packages/design-jsx/src/props-overrides.ts#L74-L86)。
布局
| 属性 | 作用 |
|---|---|
flex | "row"或"col",开启自动布局("column"等同"col") |
gap | 子元素间距 |
wrap | 子元素换行 |
rowGap | 换行时行间距 |
justify | "start"、"end"、"center"或"between"(主轴线对齐) |
items | "start"、"end"、"center"或"stretch"(交叉轴对齐) |
p、px、py、pt、pr、pb、pl | 内边距(p 为四边统一,px/py 为水平/垂直,其余为单边) |
实现细节(见 packages/design-jsx/src/props-overrides.ts#L317-L397):flex决定layoutMode(col/column→VERTICAL,row→HORIZONTAL),默认主轴/交叉轴均为HUG;给w/h传数字会将该轴改为FIXED,传"hug"保持HUG,传"fill"则映射为layoutGrow/layoutAlignSelf(在 flex 容器中子元素按方向选择 grow 或 stretch,grid 容器按行语义处理)。只要出现flex或任意内边距/对齐属性就会自动启用自动布局(shouldEnableAutoLayout)。网格布局由grid、columns、rows、colStart、rowStart、colSpan、rowSpan属性驱动(columns/rows支持数字或 CSS 轨道字符串,如"1fr 2fr")。
尺寸与位置
| 属性 | 作用 |
|---|---|
w、h | 宽高:数字、"fill"或"hug" |
minW、maxW、minH、maxH | 尺寸约束 |
x、y | 位置(top/left为别名) |
在自动布局容器内,显式给出x/y(或top/left)会自动把该节点标记为绝对定位(layoutPositioning = 'ABSOLUTE');position="absolute"也可直接声明。
外观
| 属性 | 作用 |
|---|---|
bg | 十六进制背景填充色(fill/background/backgroundColor为别名) |
fill | bg的别名 |
stroke | 描边颜色(border/borderColor为别名) |
strokeWidth | 描边粗细,默认 1 |
rounded | 圆角半径;独立圆角:roundedTL、roundedTR、roundedBL、roundedBR |
cornerSmoothing | 圆角平滑度 0~1 |
opacity | 不透明度 0~1 |
shadow | 投影,如"0 4 8 #00000040"(x 偏移、y 偏移、模糊半径、颜色) |
blur | 图层模糊半径 |
rotate | 旋转角度(度) |
blendMode | 混合模式 |
overflow | "hidden"或"visible"(hidden会设置clipsContent) |
外观属性通过applyVisualOverrides(见 packages/design-jsx/src/props-overrides.ts#L204-L215)写入节点:rounded为数字时设置cornerRadius,四个独立圆角属性任一出现时启用independentCorners;fills数组可用于声明多层填充,每个成员可以是颜色字符串、Color对象或Fill对象。更丰富的填充(渐变、多重效果)可通过solid、gradient、linearGradient、radialGradient、angularGradient、diamondGradient、dropShadow、innerShadow、layerBlur、backgroundBlur、foregroundBlur等辅助函数表达(DESIGN_JSX_HELPERS,见 packages/design-jsx/src/schema.ts#L254-L268)。
排版
| 属性 | 作用 |
|---|---|
size/fontSize | 字号 |
font/fontFamily | 字族 |
weight/fontWeight | "bold"、"medium"、"normal"或数字(映射为 700/500/400) |
color | 文本颜色 |
textAlign | "left"、"center"、"right"或"justified" |
排版族还支持lineHeight、letterSpacing、italic、textDecoration、textCase、maxLines、truncate、textAlignVertical("top"/"center"/"bottom")、textAutoResize("none"/"width"/"height")等属性。文本自动尺寸有专门逻辑(见 packages/design-jsx/src/props-overrides.ts#L448-L469):显式宽度或位于自动布局且fill时用HEIGHT,否则默认WIDTH_AND_HEIGHT——源码注释特别提醒该默认值依赖 headless 布局的 fallback 估算器,改动会破坏所有 JSX 渲染。
设计变量绑定
JSX 支持把属性绑定到设计变量:designVar与defineVars辅助函数创建变量引用,bind属性或直接传变量对象到bg/color/stroke/size/gap等属性时,渲染器会解析变量 ID 并调用graph.bindVariable建立绑定,同时保留回退值(见 packages/design-jsx/src/renderer.ts#L132-L218)。这让代码生成的设计与设计系统 token 保持一致。
导出设计为 JSX
反向流程由export命令完成。JSX 导出支持两种风格:
openpencil export design.fig -f jsx # OpenPencil 原生 JSX 格式 openpencil export design.fig -f jsx --style tailwind # Tailwind 工具类-f jsx(或-f tailwind-jsx)以 OpenPencil 原生 JSX 格式输出,可直接再渲染;--style tailwind输出带 Tailwind 工具类的代码,例如:
<div className="flex flex-col gap-4 p-6 bg-white rounded-xl"> <p className="text-2xl font-bold text-[#1D1B20]">Card Title</p> <p className="text-sm text-[#49454F]">Description text</p> </div>导出的设计可以当作代码修改后再重新渲染。导出会完整记录隐藏与锁定图层、约束、尺寸约束、多层/渐变/图片填充、描边、效果、蒙版与变量绑定——这些信息在重新渲染时都能复现,diff_jsx可以显示其中任何一项的变化。目前尚未导出的内容包括:混合样式的富文本、矢量路径、布局网格、共享样式与组件属性定义。实例(Instance)会导出为带自身内容的 Frame,因此导出的 JSX 是自包含的,不依赖外部组件库。
导出的完整命令集合见 packages/docs/programmable/cli/exporting.md:openpencil export design.fig -f tailwind-jsx与-f jsx --style tailwind等价;导出还支持png、jpg、webp、svg、pdf、pptx、fig、html、storybook等格式与-s(缩放)、-q(质量)、--page、--node等选项。另外openpencil tokens design.fig可以把文档变量导出为 CSS 自定义属性(--format tailwind输出 Tailwind v4 的@theme块,供bg-primary这类类名使用),与 JSX/HTML 导出的 token 化输出配套使用。
设计变更的代码级对比
由于 JSX 是可读的文本表示,设计变更自然呈现为普通代码 diff:
<Frame name="Card" w={320} flex="col" gap={16} p={24} bg="#FFF"> - <Text size={18} weight="bold">Old Title</Text> + <Text size={24} weight="bold" color="#1D1B20">New Title</Text> <Text size={14} color="#666">Description</Text> </Frame>这样的 diff 可以在 Pull Request 中进行人工审查,提交进版本控制系统,并放到 CI 里自动分析(配合diff_jsx检查任意属性的变化)。对团队而言,这意味着设计评审与代码评审可以共用同一套流程:AI 或设计师修改 JSX,审查者只看 diff 即可判断改动意图,无需打开设计文件逐一比对。
与相关工具链的衔接
evalCLI:openpencil eval执行代码片段,内部通过 RPC 的eval通道运行(见 packages/cli/src/commands/eval.ts 与 packages/cli/src/index.ts),--write可把结果保存为文档,是脚本化构建设计的主入口。- MCP / AI 聊天:
render工具面向 AI Agent 暴露同一 JSX 语法,使模型可以直接"写代码生图"。 @open-pencil/design-jsx测试:仓库内配套测试覆盖属性、网格、流式解析、reconcile 等行为(见 packages/design-jsx/tests),例如attributes.test.ts、grid.test.ts、props-overrides.test.ts、streaming.test.ts,可作为 JSX 语法行为的可运行参考。- JSX 导出实现:
selectionToJSX、sceneNodeToJSX等导出函数位于 packages/design-jsx/src/export/index.ts,剪辑板 JSX 导出亦复用selectionToJSX(见 packages/core/src/editor/clipboard/export.ts),说明"选中图层复制为 JSX"与文件导出走同一套序列化逻辑。
小结
OpenPencil 的 JSX 渲染器把"写界面"变成了"写代码":render(聊天/MCP/evalCLI)负责解释执行 JSX,renderJSX/renderTree(@open-pencil/core/design-jsx)在代码侧构建设计树,export命令则把既有设计序列化为可读、自包含、可再渲染的 JSX/Tailwind。元素、布局、外观、排版与变量绑定构成的完整属性体系(全部支持别名与style对象形式),加上底层 sucrase 编译 → 树解析 → 场景图建树 → 自动布局的渲染管线,让设计既可以由 AI 与脚本生成,也可以像源码一样被审查、diff、入库与 CI 校验——这是 OpenPencil 作为 AI 原生设计编辑器的核心工程能力之一。
- 前端
- 桌面应用
- AI 应用
- MCP 服务
【免费下载链接】open-pencil
AI-native design editor. Open-source Figma alternative.
相关推荐
OpenPencil JSX 渲染器:用声明式 JSX 创建与导出可编辑设计
OpenPencil JSX 渲染器:用声明式 JSX 创建与导出可编辑设计 OpenPencil(开源 Figma 替代品)将 JSX 作为设计创作的声明式语
前端桌面应用AI 应用MCP 服务OpenPencil JSX 渲染引擎:用声明式 JSX 构建可编辑设计树与 Tailwind 导出实战
OpenPencil JSX 渲染引擎:用声明式 JSX 构建可编辑设计树与 Tailwind 导出实战 OpenPencil 提供了一套独立的"设计 JSX"
前端桌面应用AI 应用MCP 服务OpenPencil JSX 渲染器(Motore JSX)完全指南:从声明式 JSX 到可编辑设计树
OpenPencil JSX 渲染器(Motore JSX)完全指南:从声明式 JSX 到可编辑设计树 导读 OpenPencil(开源 Figma 替代品)的
前端桌面应用AI 应用MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考