# t-markdown
Markdown 富文本渲染(Canvas)
t-markdown 组件介绍
t-markdown 是基于 Canvas 的高性能 Markdown 渲染组件,块级排版 + 可视区虚拟化绘制。支持标题、段落、粗体/斜体/删除线、行内代码与公式、链接、图片预览、有序/无序列表、引用、代码块(语法高亮 + 一键复制)、表格、脚注、HTML 以及多轮会话消息气泡等布局,内置触摸与 PC 鼠标惯性滚动、贴底跟随与橡皮筋回弹。
文档文本与代码高亮数据可由后端解析(如 markdown-server /render 返回的标准 ast)后整体传入 nodes,前端无需自行高亮。
t-markdown 平台兼容
| Harmony | H5 | Android | iOS | 小程序 | UTS |
|---|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
t-markdown 基础用法
基础用法参考 demo/yoga/yoga.uvue。通过 nodes 传入 markdown 块级节点数组(顶层可为各类块节点或 message 消息容器),通过 options 定制渲染样式。静态报告场景建议将 followBottom 设为 false 固定停留在顶部查看。
vue
<template>
<view class="p-15">
<t-card class="mb-15"
title="Markdown 富文本"
sub-title="Canvas高性能渲染,支持表格代码块,会话消息气泡等复杂排版"></t-card>
<view class="w-100% h-560px b-1px,s,#ebeef5 r-8 oh">
<t-markdown class="w-100% h-100%"
:options="{ pad: 15, followBottom: false }"
:nodes="nodes"></t-markdown>
</view>
</view>
</template>
<script setup>
const nodes = ref<UTSJSONObject[]>([
{
type: 'heading',
level: 2,
children: [
{ type: 'text', content: 'Canvas Markdown 渲染引擎' }
]
},
{
type: 'paragraph',
children: [
{ type: 'text', content: '支持 ' },
{ type: 'strong', children: [{ type: 'text', content: '加粗' }] },
{ type: 'text', content: '、' },
{ type: 'emphasis', children: [{ type: 'text', content: '斜体' }] },
{ type: 'text', content: '、' },
{ type: 'inlineCode', content: '行内代码' },
{ type: 'text', content: ' 与' },
{ type: 'link', href: 'https://uniapp.dcloud.net.cn', children: [{ type: 'text', content: '超链接' }] },
{ type: 'text', content: ',图片宽高未知时会等比预加载测量。' }
]
},
{
type: 'blockquote',
children: [
{ type: 'paragraph', children: [{ type: 'text', content: '引用区块:块级排版 + 可视区虚拟化绘制,数据再多也不怕。' }] }
]
},
{
type: 'code',
lang: 'ts',
content: 'const md = new TMarkdown()\nmd.render(nodes)'
},
{
type: 'list',
ordered: true,
children: [
{ type: 'listItem', children: [{ type: 'paragraph', children: [{ type: 'text', content: '代码块语法高亮 + 一键复制' }] }] },
{ type: 'listItem', children: [{ type: 'paragraph', children: [{ type: 'text', content: '支持无序/有序列表嵌套' }] }] }
]
}
])
</script>t-markdown 消息气泡会话
参考 demo/markdown/markdown.uvue。将每一轮会话包成 { type: 'message', role, children } 顶层节点即可实现多轮聊天布局:user 消息走右侧深色气泡,assistant 消息走左侧透明正文,流式追加时自动重排并贴底跟随。
vue
<template>
<view class="h-100%">
<t-markdown class="f"
:options="{ pad: 15 }"
:nodes="nodes"
@linktap="onLinkTap"></t-markdown>
</view>
</template>
<script setup>
// 会话队列:每轮渲染块数组
const messages = ref<any[]>([])
// 组装成 message 消息块序列
const nodes = computed(() : any[] => {
const out : any[] = []
const list = messages.value || []
for (const m of list) {
out.push({ type: 'message', role: m.role, children: m.render || [] })
}
return out
})
function send(text : string) : void {
const list = (messages.value || []).slice()
list.push({
role: 'user',
render: [{ type: 'paragraph', children: [{ type: 'text', content: text }] }]
})
messages.value = list
}
function onLinkTap(e : any) : void {
console.log('linktap', e.href, e.text)
}
</script>t-markdown Props
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
nodes | markdown 块级节点数组(必传)。顶层可为 message{role, children} 消息容器或各类块节点 | Array | [] |
options | 渲染配置对象,键名见下方 Options 表;均可省略,未配置时使用内置默认值 | Object | {} |
nodes 节点结构
| 节点类型 | 关键字段 | 说明 |
|---|---|---|
message | role: user/assistant,children | 多轮会话消息容器,user 右侧气泡、assistant 正文 |
heading | level,children | 标题(1~6 级) |
paragraph | children | 段落 |
text | content | 纯文本 |
strong / emphasis / delete | children | 加粗 / 斜体 / 删除线 |
inlineCode | content | 行内代码 |
link | href,children | 行内链接,点击触发 linktap |
image | src,width?,height? | 图片,宽高缺省时等比预加载测量 |
break | - | 换行 |
code | content,lang?,lines? | 代码块;lines 为逐行语法高亮 token,缺失时按纯文本绘制 |
blockquote | children | 引用块 |
list | ordered,children | 有序/无序列表,列表项 listItem |
table | align,children | 表格 |
thematicBreak | - | 分隔线 |
math / inlineMath | - | 公式块 / 行内公式 |
footnoteReference / footnoteDefinition | - | 脚注引用 / 脚注定义 |
html | - | HTML 内容 |
t-markdown Options
options 中可配置以下渲染键(均可省略,类型与默认值见下表):
内容与配色
| 配置键 | 说明 | 类型 | 默认值 |
|---|---|---|---|
pad | 内容留白 | number | 0 |
textColor | 正文色 | string | #333333 |
linkColor | 链接色 | string | #007acc |
mathColor | 公式色 | string | #555555 |
quoteBar | 引用条颜色 | string | #dfe2e5 |
hr | 分隔线颜色 | string | #eaecef |
muted | 弱化文字色(如列表符号) | string | #888888 |
footnote | 脚注色 | string | #999999 |
imgBg | 图片占位底色 | string | #f0f1f3 |
check | 任务列表选中色 | string | #2979ff |
checkboxUn | 任务列表未选色 | string | #b5bcc4 |
代码块
| 配置键 | 说明 | 类型 | 默认值 |
|---|---|---|---|
codeBg | 代码块底色 | string | #1e1e1e |
codeFg | 代码文字色 | string | #e1e4e8 |
codeInlineBg | 行内代码底色 | string | #f6f6f6 |
codeInlineColor | 行内代码文字色 | string | #e83e8c |
codeRadius | 代码块圆角 | number | 10 |
codeHeaderH | 代码顶栏高度 | number | 34 |
codeHeadGap | 顶栏左右留白 | number | 16 |
codeHead | 代码顶栏底色 | string | #2b2b2b |
codeLabel | 语言标签颜色 | string | #9aa5b1 |
copyBtn | 复制按钮底色 | string | #2979ff |
copyText | 复制按钮文字色 | string | #ffffff |
dotA / dotB / dotC | 顶栏装饰圆点颜色 | string | #ff5f57 / #febc2e / #28c840 |
表格
| 配置键 | 说明 | 类型 | 默认值 |
|---|---|---|---|
grid | 表格线颜色 | string | #eaecef |
thead | 表头底色 | string | #f2f3f5 |
zebra | 斑马纹行底色 | string | #f6f8fa |
tableRadius | 表格外框圆角 | number | 8 |
消息气泡会话
| 配置键 | 说明 | 类型 | 默认值 |
|---|---|---|---|
userBubble | 用户消息气泡底色 | string | #2979ff |
bubbleTextColor | 用户气泡内文字颜色 | string | #ffffff |
bubbleTextOffset | 气泡文字垂直居中额外下移量 | number | 4 |
bubblePad | 气泡内边距 | number | 12 |
bubbleRadius | 气泡圆角 | number | 14 |
bubbleMaxRatio | 气泡最大宽度占内容区比例 | number | 0.76 |
bubbleGapY | 消息之间垂直间距 | number | 10 |
滚动行为
| 配置键 | 说明 | 类型 | 默认值 |
|---|---|---|---|
followBottom | 是否自动贴底跟随新内容;静态内容可传 false 停顶部 | boolean | true |
releaseIdleMs | 留白静默释放延迟 | number | 700 |
t-markdown Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
linktap | 点击行内链接时触发 | { href, text } |