跳到内容

投影

投影是组件和布局的稳定文本表示。它让同一条消息既可以渲染 UI,也可以复制、存储、搜索,并继续作为后续模型上下文。

组件投影

每个组件定义都必须提供 projection.text。这是组件 spec 的规范文本表示。

下面的 spec:

ts
{
  title: 'Launch plan',
  items: [
    {
      time: 'Week 1',
      title: 'Canary',
    },
  ],
}

可以使用这样的投影模板:

ts
projection: {
  text: `### {{ title }}

{% for item in items %}
- {{ item.time }}: {{ item.title }}
{% endfor %}`,
}

渲染结果是:

md
### Launch plan

- Week 1: Canary

模板语法

投影模板使用 MFUI 受限的类 Liquid 模板语法。请把投影语法视为 MFUI 子集,而不是完整 Liquid。

MFUI 默认会在渲染前校验这个子集。模板使用不支持的 tag 或 filter 时会抛错。

功能支持的值
Tagsfor, endfor, if, endif, unless, endunless, else, elsif
Filtersdefault, join, truncate, escapeMarkdown, strip, size

编写原则

投影应该稳定:同一个 spec 应该得到同一段文本。

投影应该可读:它是给复制、搜索、审计和模型上下文使用的文本,不应该只是 JSON dump。

投影不应该推断 spec 中不存在的信息。例如图表投影可以展开数据点,但不应该额外生成趋势总结,除非趋势总结本身就是 spec 字段。

投影可以使用 Markdown 语法,但 MFUI 不要求必须使用 Markdown。

布局投影

布局不定义投影模板。内置布局会按确定性顺序组合其中的 cell。

对于 mfui.columns

cell投影规则
TextCell使用 cell 自己的 text
ComponentCell使用对应组件定义渲染出的 projection.text
多个 cell从左到右用空行拼接。

列位置是视觉结构,不会写入投影文本,因此投影不会添加“第 1 列”之类的标签。

portableText

消息级 portableText 是最终的确定性文本。它由文本 part、组件投影和布局投影拼接而成。

part 类型文本来源
Text partcontent
Component partprojection.text
Layout partprojection.text

拼接时使用空行分隔,并忽略空片段。

ts
import { messageToPortableText } from '@mfui/client';

const text = messageToPortableText(message);

MFUI 只生成这段文本。应用决定如何把它用于复制、搜索、审计日志或后续模型上下文。