Skip to content

API 参考

导出总览

@huiol/stream-uisrc/index.ts 导出:

ts
export { StreamContains } from './StreamContains'
export * from './component'      // Think, Text, StreamBase, defineStreamBase, MdSupport, LatexSupport, ...
export * from './core/stream-form-data'
export * from './types'          // StreamBlockData, StreamBlockComponentProps, streamBlockProps, ...

类型定义

全部在 src/types/stream-ui.ts 中定义。

ts
type RenderMode = 'fast' | 'accurate'
type StreamBlockCategory = 'component' | 'fallback' | 'text'
type StreamBlockAttrs = Record<string, string | boolean>

interface StreamBlockData {
  id: string
  tagName: string
  attrs?: StreamBlockAttrs
  content: string
  isClosed: boolean
  category: StreamBlockCategory
  payload?: unknown
}

// 组件标签存在字符串 id 属性时,会优先作为稳定区块 ID。
type StreamBlockReporter = (payload: unknown) => void

interface StreamContainsProps {
  modelValue: string
  mode: RenderMode
  data?: StreamBlockData[]
  components?: ComponentMap
  baseComponent?: Component | null
  literalTags?: string[]
}

interface StreamBlockBaseProps {
  block: StreamBlockData
  tagName: string
  attrs?: StreamBlockAttrs
  content: string
  isClosed: boolean
  reportData: StreamBlockReporter
}

interface StreamBlockComponentProps {
  block?: StreamBlockData
  attrs?: StreamBlockAttrs
  content?: string
  isClosed?: boolean
  reportData?: StreamBlockReporter
}

interface StreamFormField {
  id: string
  name: string
  tagName: string
  label?: string
  value?: unknown
  required?: boolean
  valid?: boolean
  error?: string
  attrs?: StreamBlockAttrs
  payload?: unknown
}

interface StreamFormAction {
  id: string
  action: string
  label?: string
  clicked: boolean
  at?: number
  attrs?: StreamBlockAttrs
  payload?: unknown
}

interface StreamFormData {
  values: Record<string, unknown>
  fields: Record<string, StreamFormField>
  actions: StreamFormAction[]
  valid: boolean
  errors: Record<string, string>
  submitted: boolean
  lastAction?: StreamFormAction
  blocks: StreamBlockData[]
}

streamBlockProps 是对应的运行时 props 对象,适合在 defineComponent 写法中复用:

ts
import { defineComponent } from 'vue'
import { streamBlockProps } from '@huiol/stream-ui'

export default defineComponent({
  name: 'MyBlock',
  props: streamBlockProps
})

表单数据辅助函数

collectStreamFormData

v-model:data 得到的 StreamBlockData[] 整理成表单视图:

ts
import { collectStreamFormData } from '@huiol/stream-ui'

const form = collectStreamFormData(blocks.value)
console.log(form.values.email)

input-blockselect-block 会进入 fields / valuesbutton-block 会进入 actions。字段键优先使用 payload.name,其次使用 attrs.name,最后回退到区块 id

required 字段为空或字段 payload 上报 valid: false 时,form.valid 会变为 false,错误信息会进入 form.errors。点击 action="submit" 的按钮后,form.submitted 会变为 true,最近一次点击动作可通过 form.lastAction 读取。

useStreamFormData

Vue 组件中可以直接传入 ref、getter 或普通数组:

ts
import { ref } from 'vue'
import { useStreamFormData, type StreamBlockData } from '@huiol/stream-ui'

const blocks = ref<StreamBlockData[]>([])
const form = useStreamFormData(blocks)

if (form.value.submitted && form.value.valid) {
  submit(form.value.values)
}

组件

StreamContains

核心容器组件。详见组件文档

Think

内置的 <think> 标签拦截组件,可折叠推理面板。详见组件文档

Text

内置的 <text> 标签拦截组件,内联 <span> 包装器。

DefaultTag

未注册标签的降级渲染组件。详见组件文档

StreamBase

Base 组件工厂,支持插件式扩展。

ts
const BaseComponent = StreamBase.with([MdSupport, LatexSupport])

defineStreamBase

StreamBase.with() 的底层函数,接收 DefineStreamBaseOptions

ts
interface DefineStreamBaseOptions {
  supports?: StreamBaseSupport[]
  className?: string
}

内核函数(底层,一般不直接调用)

ts
// 在 src/core/stream-contains-core.ts 中

function normalizeTagName(value: string): string
function toKebabCase(value: string): string
function parseTagAttrs(tagSource: string): StreamBlockAttrs
function getOpeningTagSource(tagSource: string): string
function buildComponentMap(defaultSlots: unknown[], explicitComponents?: ComponentMap): { componentMap: ComponentMap; rawTagNames: Set<string> }
function parseAccurateStream(rawText: string, options: ParserOptions): { root: StackNode; currentWarnings: string[] }
function createStreamContainsRender(props: StreamContainsProps, slots: Slots, options: StreamContainsRenderOptions): () => VNode

StreamContainsRenderOptions

ts
interface StreamContainsRenderOptions {
  DefaultTag: Component
  emit?: {
    (event: 'update:data', value: StreamBlockData[]): void
    (event: 'parse-warning', value: string): void
  }
  emptyClassName?: string                          // 默认: 'stream-content'
  fastContainerClassName?: string                   // 默认: 'stream-ui-container mode-fast'
  accurateContainerClassName?: string               // 默认: 'stream-ui-container mode-accurate'
  getUndefinedTagWarning?: (tagName: string) => string
  getCrossedTagWarning?: (tagName: string, closedTags: string[]) => string
  getIsolatedClosingTagWarning?: (tagName: string) => string
  getParserWarningsTitle?: (count: number) => string
}

StackNode

ts
interface StackNode {
  tagName: string
  attrs?: StreamBlockAttrs
  children: (StackNode | string)[]
  isClosed: boolean
}

ComponentMap

ts
type ComponentMap = Record<string, Component>

正则(源码中定义,仅供参考)

ts
// Fast 模式:单次匹配完整标签结构
const FAST_MODE_TAG_REGEX = /<([A-Za-z][\w-]*)(?:\s+[^>]*)?(?:(/>)|(?:>)([\s\S]*?)(?:<\/\1>|$))/gi

// Accurate 模式:分段匹配开/闭标签
const ACCURATE_MODE_TAG_REGEX = /<\/([A-Za-z][\w-]*(?:\s+[^>]*)?>|<([A-Za-z][\w-]*)(?:\s+[^>]*)?>/g

// 属性匹配
const ATTR_REGEX = /([^\s=\/>]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g

Released under the MIT License.