更新记录
1.0.0(2026-02-13) 下载此版本
初始版本,基于Marked.js 17.0.2优化兼容,完整TypeScript支持,支持全平台运行
平台兼容性
uni-app(3.6.17)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ | - | √ | √ |
uni-app x(3.6.17)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ |
其他
| 多语言 | 暗黑模式 | 宽屏模式 |
|---|---|---|
| √ | √ | √ |
dh-marked - Markdown解析器(uniapp专用版)
基于Marked.js 17.0.2,专为uniapp优化,兼容全平台(H5、小程序、App)
✨ 特性
- ✅ 全平台兼容 - 支持H5、微信小程序、支付宝小程序、App(iOS/Android)
- ✅ 完整支持 - 支持GitHub风格Markdown(GFM)
- ✅ 轻量快速 - 42KB (gzipped),速度极快
- ✅ TypeScript - 完整的类型定义支持
- ✅ 可扩展 - 支持自定义渲染器和语法扩展
- ✅ 使用方便 - 可以搭配rich-text或者其他富文本显示组件
🚀 快速开始
基础用法
<template>
<view class="markdown-body">
<rich-text :nodes="html"></rich-text>
</view>
</template>
<script>
import { marked } from '@/uni_modules/dh-marked';
export default {
data() {
return {
markdown: '# Hello World\n\n这是**粗体**,这是*斜体*',
};
},
computed: {
html() {
return marked.parse(this.markdown);
},
},
};
</script>
TypeScript支持
import { marked, type MarkedOptions, type Token } from '@/uni_modules/dh-marked';
// 完整的类型提示
const html: string = marked.parse('# Hello');
// 带配置
const options: MarkedOptions = {
breaks: true,
gfm: true,
};
marked.setOptions(options);
📚 核心API
1. marked.parse() - 解析Markdown为HTML
最常用的方法,将Markdown文本转换为HTML。
const html = marked.parse('# 标题\n\n段落内容');
// 输出: <h1>标题</h1>\n<p>段落内容</p>
// 带选项
const html = marked.parse('文本\n换行', {
breaks: true, // 单个换行转<br>
gfm: true, // GitHub风格Markdown
});
参数:
src: string- Markdown源文本options?: MarkedOptions- 可选配置
返回: string | Promise<string> - HTML字符串
2. marked.parseInline() - 只解析内联元素
只解析加粗、斜体、链接等内联元素,不解析标题、列表等块级元素。
const html = marked.parseInline('**粗体** _斜体_ [链接](url)');
// 输出: <strong>粗体</strong> <em>斜体</em> <a href="url">链接</a>
// 不会解析块级元素
marked.parseInline('# 标题\n\n段落');
// 输出: # 标题\n\n段落 (保持原样)
使用场景: 单行文本、评论预览、标题文字
3. marked.setOptions() - 全局配置
设置全局默认配置,影响后续所有的parse调用。
marked.setOptions({
breaks: true, // 单个换行转<br>(默认false)
gfm: true, // GitHub风格Markdown(默认true)
pedantic: false, // 严格遵循markdown.pl(默认false)
silent: false, // 安静模式,遇错不抛异常(默认false)
});
常用配置项:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
breaks |
boolean |
false |
单个换行是否转<br> |
gfm |
boolean |
true |
GitHub风格Markdown |
pedantic |
boolean |
false |
严格模式 |
silent |
boolean |
false |
安静模式 |
renderer |
Renderer |
null |
自定义渲染器 |
tokenizer |
Tokenizer |
null |
自定义分词器 |
walkTokens |
function |
null |
token遍历钩子 |
4. marked.use() - 扩展和自定义
扩展marked的功能,自定义渲染规则或添加新语法。
自定义渲染
// 自定义标题渲染
marked.use({
renderer: {
heading(token) {
const level = token.depth;
const text = this.parser.parseInline(token.tokens);
return `<h${level} class="my-heading" id="${token.text}">${text}</h${level}>\n`;
},
// 自定义链接渲染
link(token) {
return `<a href="${token.href}" class="external-link" target="_blank">${token.text}</a>`;
},
// 自定义图片渲染(uniapp图片预览)
image(token) {
return `<image src="${token.href}" mode="widthFix" data-src="${token.href}" @tap="previewImage" />`;
},
},
});
添加自定义语法
// 添加警告框语法:!!! 警告内容
marked.use({
extensions: [
{
name: 'alert',
level: 'block',
tokenizer(src) {
const match = /^!!! (.+)\n/.exec(src);
if (match) {
return {
type: 'alert',
raw: match[0],
text: match[1],
};
}
},
renderer(token) {
return `<view class="alert">${token.text}</view>\n`;
},
},
],
});
// 使用
const html = marked.parse('!!! 这是警告信息');
// 输出: <view class="alert">这是警告信息</view>
5. marked.lexer() - 词法分析
将Markdown文本转换为token数组(语法树)。
const tokens = marked.lexer('# 标题\n\n段落内容');
console.log(tokens);
/*
[
{
type: 'heading',
depth: 1,
text: '标题',
tokens: [...]
},
{
type: 'paragraph',
text: '段落内容',
tokens: [...]
}
]
*/
使用场景: 需要分析或修改Markdown结构
6. marked.parser() - 将tokens渲染为HTML
将token数组渲染为HTML字符串。
const tokens = marked.lexer('# Hello');
const html = marked.parser(tokens);
// 输出: <h1>Hello</h1>
// 可以先修改tokens再渲染
tokens[0].text = '修改后的标题';
const newHtml = marked.parser(tokens);
使用场景: 需要在渲染前修改语法树
7. marked.walkTokens() - 遍历所有token
遍历语法树中的所有token,可用于分析或修改内容。
const tokens = marked.lexer('# 标题\n\n[链接](url)');
marked.walkTokens(tokens, (token) => {
// 修改所有链接
if (token.type === 'link') {
token.href = 'https://new-domain.com' + token.href;
}
// 收集所有标题
if (token.type === 'heading') {
console.log(`H${token.depth}: ${token.text}`);
}
});
const html = marked.parser(tokens);
🎨 实战示例
示例1:Markdown文章渲染器
<template>
<scroll-view class="article-container">
<view class="markdown-body">
<rich-text :nodes="html"></rich-text>
</view>
</scroll-view>
</template>
<script>
import { marked } from '@/uni_modules/dh-marked';
export default {
data() {
return {
markdown: '',
};
},
computed: {
html() {
return marked.parse(this.markdown || '');
},
},
onLoad(options) {
// 配置marked
marked.setOptions({
breaks: true, // 换行转<br>
gfm: true, // GitHub风格
});
// 加载文章
this.loadArticle(options.id);
},
methods: {
loadArticle(id) {
uni.request({
url: '/api/article/' + id,
success: (res) => {
this.markdown = res.data.content;
},
});
},
},
};
</script>
<style>
/* GitHub样式的Markdown */
.markdown-body h1 {
font-size: 32px;
font-weight: bold;
margin: 20px 0;
}
.markdown-body h2 {
font-size: 28px;
font-weight: bold;
margin: 18px 0;
}
.markdown-body p {
line-height: 1.6;
margin: 10px 0;
}
.markdown-body code {
background: #f5f5f5;
padding: 2px 4px;
border-radius: 3px;
}
.markdown-body pre {
background: #f5f5f5;
padding: 10px;
border-radius: 5px;
overflow: auto;
}
</style>
示例2:自定义图片渲染(支持预览)
import { marked } from '@/uni_modules/dh-marked';
// 自定义图片渲染
marked.use({
renderer: {
image(token) {
// 为图片添加点击事件属性
return `<img src="${token.href}" alt="${token.text}" mode="widthFix" data-preview="${token.href}" class="md-image" />`;
},
},
});
export default {
methods: {
// 图片预览
handleTap(e) {
const src = e.target.dataset.preview;
if (src) {
uni.previewImage({
urls: [src],
current: src,
});
}
},
},
};
示例3:生成文章目录
import { marked } from '@/uni_modules/dh-marked';
function generateTOC(markdown) {
const tokens = marked.lexer(markdown);
const toc = [];
marked.walkTokens(tokens, (token) => {
if (token.type === 'heading') {
toc.push({
level: token.depth,
text: token.text,
id: token.text.toLowerCase().replace(/\s+/g, '-'),
});
}
});
return toc;
}
// 使用
const markdown = '# 一级标题\n## 二级标题\n### 三级标题';
const toc = generateTOC(markdown);
/*
[
{ level: 1, text: '一级标题', id: '一级标题' },
{ level: 2, text: '二级标题', id: '二级标题' },
{ level: 3, text: '三级标题', id: '三级标题' }
]
*/
示例4:提取纯文本摘要
import { marked } from '@/uni_modules/dh-marked';
function getPlainText(markdown, maxLength = 100) {
const tokens = marked.lexer(markdown);
let text = '';
marked.walkTokens(tokens, (token) => {
if (token.type === 'text') {
text += token.text + ' ';
}
});
return text.trim().slice(0, maxLength) + '...';
}
// 使用
const summary = getPlainText('# 标题\n\n这是一段**很长**的内容...');
// 输出: "标题 这是一段很长的内容..."
示例5:代码高亮(使用highlight.js)
import { marked } from '@/uni_modules/dh-marked';
import hljs from 'highlight.js'; // 需要另外引入
marked.use({
renderer: {
code(token) {
const language = token.lang || 'plaintext';
const code = token.text;
// 使用highlight.js高亮
const highlighted = hljs.highlight(code, { language }).value;
return `<pre><code class="language-${language}">${highlighted}</code></pre>\n`;
},
},
});
🔧 高级用法
创建独立实例
import { Marked } from '@/uni_modules/dh-marked';
// 创建独立实例,不影响全局配置
const customMarked = new Marked({
breaks: true,
gfm: false,
});
const html1 = customMarked.parse('文本\n换行'); // 有<br>
const html2 = marked.parse('文本\n换行'); // 无<br>
使用Hooks钩子
import { marked } from '@/uni_modules/dh-marked';
marked.use({
hooks: {
// 预处理Markdown
preprocess(markdown) {
// 替换emoji短代码
return markdown.replace(/:smile:/g, '😊').replace(/:heart:/g, '❤️');
},
// 后处理HTML
postprocess(html) {
// 为所有图片添加懒加载
return html.replace(/<img/g, '<img loading="lazy"');
},
},
});
📖 完整API列表
基础API
| API | 用途 | 常用度 |
|---|---|---|
marked.parse() |
解析Markdown为HTML | ⭐⭐⭐⭐⭐ |
marked.parseInline() |
只解析内联元素 | ⭐⭐⭐ |
marked.setOptions() |
全局配置 | ⭐⭐⭐⭐ |
marked.use() |
扩展/自定义 | ⭐⭐⭐⭐ |
marked.getDefaults() |
获取默认配置 | ⭐⭐ |
高级API
| API | 用途 | 常用度 |
|---|---|---|
marked.lexer() |
词法分析 | ⭐⭐⭐ |
marked.parser() |
tokens转HTML | ⭐⭐⭐ |
marked.walkTokens() |
遍历tokens | ⭐⭐⭐ |
类API
| 类 | 用途 | 常用度 |
|---|---|---|
Marked |
独立实例 | ⭐⭐ |
Renderer |
渲染器类 | ⭐⭐⭐ |
Tokenizer |
分词器类 | ⭐⭐ |
Lexer |
词法分析器类 | ⭐⭐ |
Parser |
解析器类 | ⭐⭐ |
TextRenderer |
纯文本渲染 | ⭐⭐ |
Hooks |
钩子系统 | ⭐⭐⭐ |
⚙️ 配置选项详解
MarkedOptions
interface MarkedOptions {
// 单个换行是否转<br>
breaks?: boolean; // 默认: false
// GitHub风格Markdown
gfm?: boolean; // 默认: true
// 严格模式
pedantic?: boolean; // 默认: false
// 安静模式(错误不抛异常)
silent?: boolean; // 默认: false
// 异步解析
async?: boolean; // 默认: false
// 自定义渲染器
renderer?: Renderer;
// 自定义分词器
tokenizer?: Tokenizer;
// 钩子函数
hooks?: Hooks;
// 扩展语法
extensions?: Extension[];
// token遍历函数
walkTokens?: (token: Token) => void;
}
📄 许可证
MIT License
基于 Marked.js - Copyright (c) 2018+, MarkedJS (MIT License)
🔗 相关链接
💡 常见问题
Q: 如何在rich-text中使用?
A: 直接将解析后的HTML传给rich-text组件:
<rich-text :nodes="marked.parse(markdown)"></rich-text>
Q: 图片如何支持预览?
A: 使用自定义渲染器添加点击事件,参考示例2。
Q: 支持代码高亮吗?
A: 需要配合highlight.js使用,参考示例5。
Q: 如何生成目录?
A: 使用marked.walkTokens()遍历heading类型的token,参考示例3。
Q: 性能如何?
A: Marked是最快的Markdown解析器之一,10KB的文档解析时间<5ms。

收藏人数:
下载插件并导入HBuilderX
下载插件ZIP
赞赏(0)
下载 126
赞赏 0
下载 11234677
赞赏 1860
赞赏
京公网安备:11010802035340号