Marked.js 扩展开发教程:自定义渲染器和Tokenizer实战

Marked.js 扩展开发教程:自定义渲染器和Tokenizer实战

【免费下载链接】marked 【免费下载链接】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 {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[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 【免费下载链接】marked 项目地址: https://gitcode.com/gh_mirrors/mar/marked

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值