Marked.js 扩展开发教程:自定义渲染器和Tokenizer实战
【免费下载链接】marked 项目地址: https://gitcode.com/gh_mirrors/mar/marked
Marked.js 是一个高速的 Markdown 解析器和编译器,支持自定义扩展功能。本文将详细介绍如何通过自定义渲染器和 Tokenizer 来扩展 Marked.js 的功能,实现个性化的 Markdown 渲染效果。
🎯 为什么要扩展 Marked.js?
Marked.js 默认提供了标准的 Markdown 解析功能,但实际项目中我们经常需要:
- 添加自定义的 HTML 标签和样式
- 支持特殊的语法扩展
- 集成第三方组件和库
- 优化移动端显示效果
通过自定义渲染器和 Tokenizer,你可以完全控制 Markdown 的解析和渲染过程。
🛠️ 环境准备和项目设置
首先安装 Marked.js:
npm install marked
或者直接通过 CDN 引入:
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
🔧 自定义渲染器实战
渲染器负责将解析后的 Token 转换为 HTML。让我们创建一个自定义渲染器来添加特殊功能:
import { marked } from 'marked';
class CustomRenderer extends marked.Renderer {
// 重写标题渲染方法
heading({ text, depth }) {
return `<h${depth} class="custom-heading" data-depth="${depth}">
${text}
</h${depth}>`;
}
// 自定义代码块渲染
code({ text, lang }) {
const escapedText = text.replace(/[&<>"']/g, function(c) {
return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c];
});
return `<pre class="custom-code-block"><code class="language-${lang}">
${escapedText}
</code></pre>`;
}
// 添加自定义警告框支持
paragraph({ text }) {
if (text.startsWith('⚠️ ')) {
return `<div class="warning-box">${text.substring(2)}</div>`;
}
return `<p>${text}</p>`;
}
}
// 使用自定义渲染器
marked.setOptions({
renderer: new CustomRenderer()
});
🔍 自定义 Tokenizer 深度解析
Tokenizer 负责将原始文本解析为 Token。让我们创建一个支持特殊语法的 Tokenizer:
class CustomTokenizer extends marked.Tokenizer {
// 解析自定义的提示框语法
customAlert(src) {
const match = src.match(/^\!(NOTE|WARNING|TIP)\/);
if (match) {
return {
type: 'customAlert',
raw: match[0],
alertType: match[1],
text: match[2].trim()
};
}
}
// 解析emoji短代码
emoji(src) {
const match = src.match(/^:([a-zA-Z0-9_+-]+):/);
if (match) {
return {
type: 'emoji',
raw: match[0],
name: match[1]
};
}
}
}
// 注册自定义 Tokenizer
marked.use({
tokenizer: new CustomTokenizer()
});
🎨 完整示例:创建主题化的 Markdown 处理器
让我们结合渲染器和 Tokenizer 创建一个完整的主题化处理器:
class ThemeRenderer extends marked.Renderer {
heading({ text, depth, tokens }) {
const icon = depth === 1 ? '🏷️' : depth === 2 ? '📌' : '🔹';
return `<h${depth} class="theme-heading">
<span class="heading-icon">${icon}</span>
${this.parser.parseInline(tokens)}
</h${depth}>`;
}
link({ href, title, text, tokens }) {
return `<a href="${href}" title="${title || ''}"
class="theme-link" target="_blank" rel="noopener">
🔗 ${this.parser.parseInline(tokens)}
</a>`;
}
// 渲染自定义警告框
customAlert({ alertType, text }) {
const icons = {
NOTE: '📝',
WARNING: '⚠️',
TIP: '💡'
};
return `<div class="alert alert-${alertType.toLowerCase()}">
<div class="alert-icon">${icons[alertType]}</div>
<div class="alert-content">${text}</div>
</div>`;
}
}
// 使用配置
marked.setOptions({
renderer: new ThemeRenderer(),
highlight: function(code, lang) {
// 集成代码高亮功能
return require('highlight.js').highlightAuto(code).value;
},
breaks: true,
gfm: true
});
🚀 高级技巧和最佳实践
1. 性能优化
对于大型文档,使用缓存机制:
const renderCache = new Map();
function cachedMarkdownRender(markdown) {
if (renderCache.has(markdown)) {
return renderCache.get(markdown);
}
const result = marked.parse(markdown);
renderCache.set(markdown, result);
return result;
}
2. 安全性考虑
始终对用户输入进行消毒处理:
import DOMPurify from 'dompurify';
function safeMarkdownRender(markdown) {
const rawHtml = marked.parse(markdown);
return DOMPurify.sanitize(rawHtml);
}
3. 异步渲染支持
对于需要异步操作的复杂渲染:
class AsyncRenderer extends marked.Renderer {
async image({ href, title, text }) {
// 异步加载图片信息
const imageInfo = await fetchImageInfo(href);
return `<img src="${href}" alt="${text}"
title="${title || imageInfo.title}"
loading="lazy">`;
}
}
📊 扩展功能对比表
| 功能 | 默认实现 | 自定义实现 | 优势 |
|---|---|---|---|
| 标题渲染 | 简单标签 | 带图标和样式 | 更好的视觉效果 |
| 链接处理 | 基本链接 | 带图标和新标签页 | 改善用户体验 |
| 代码高亮 | 无 | 语法高亮 | 代码可读性提升 |
| 自定义组件 | 不支持 | 完全支持 | 无限扩展可能 |
🔮 总结
通过自定义渲染器和 Tokenizer,Marked.js 提供了强大的扩展能力。你可以:
- ✅ 完全控制 HTML 输出结构
- ✅ 添加自定义语法支持
- ✅ 集成第三方库和组件
- ✅ 优化移动端和SEO表现
- ✅ 实现主题化和个性化功能
记住始终考虑性能优化和安全性,特别是在处理用户生成内容时。Happy coding! 🎉
【免费下载链接】marked 项目地址: https://gitcode.com/gh_mirrors/mar/marked
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



