☰
OpenPencil JSX 渲染器:用代码声明式构建设计并导出为 JSX/Tailwind
2026/10/9 2:36:29 网站建设 项目流程
  • 前端
  • 桌面应用
  • AI 应用
  • MCP 服务

【免费下载链接】open-pencil

AI-native design editor. Open-source Figma alternative.

项目地址:https://gitcode.com/gh_mirrors/op/open-pencil
点击查看免费下载

本文围绕 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)可以概括为五步:

  1. 编译:buildComponent用 sucrase 把 JSX 字符串编译为函数;编译时自动注入别名(Frame、Text、View、Rect、Component、Instance、Icon、svg及各 Reka 元素命名空间)和辅助函数(solid、gradient、dropShadow、layerBlur、designVar等),因此 JSX 字符串中可直接使用这些名字;同时剥离 HTML 注释。
  2. 解析:resolveToTree把编译产物解析为TreeNode(递归函数组件最多 100 层,片段<>…</>会被内联展开,见 packages/design-jsx/src/tree.ts)。
  3. 校验:对每个节点检查属性名,不支持的属性收集为 warnings(如Unsupported prop "xxx" on <frame> is ignored.)并随渲染结果返回。
  4. 建树: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 语义标签写设计。
  5. 布局:所有根节点渲染完成后调用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为别名)
fillbg的别名
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.

项目地址:https://gitcode.com/gh_mirrors/op/open-pencil
点击查看免费下载

相关推荐

上一篇:arduino-esp32 Deep Sleep 完全指南:ExternalWakeUp 外部唤醒与 TimerWakeUp 定时器唤醒实战
下一篇:iii 引擎生产部署实战:Docker 化打包与 Caddy/Nginx 反向代理配置指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询