You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中实现渲染后Markdown文本差异对比的方案咨询

渲染后Markdown差异对比的React实现方案

你需要对比**渲染后的Markdown(即HTML内容)**差异而非原始文本,下面提供几种可行的React实现方案:

方案一:改造react-diff-viewer,渲染Markdown内容

react-diff-viewer支持自定义内容渲染,我们可以利用renderContent属性,将每个diff块的原始Markdown文本先渲染成HTML,再结合diff的高亮样式展示。

步骤:

  1. 安装依赖:
npm install react-markdown
  1. 修改组件代码:
import ReactDiffViewer from 'react-diff-viewer';
import ReactMarkdown from 'react-markdown';

const TextComparer = ({ oldText, newText }) => {
  // 自定义渲染函数:将diff文本转为渲染后的Markdown
  const renderDiffContent = (content) => {
    return <ReactMarkdown>{content}</ReactMarkdown>;
  };

  return (
    <ReactDiffViewer
      oldValue={oldText}
      newValue={newText}
      splitView
      renderContent={renderDiffContent}
      // 可选:自定义diff高亮样式
      styles={{
        insert: { backgroundColor: '#e6ffed', color: '#22863a' },
        delete: { backgroundColor: '#ffeef0', color: '#cb2431' },
      }}
    />
  );
};

注意:这种方式是将diff拆分的文本块分别渲染为Markdown,diff的高亮样式会作用于整个文本块。如果需要更精细的文本级高亮,参考方案二。

方案二:基于文本diff算法,在渲染时插入高亮标记

使用diff-match-patch库对比原始Markdown的文本差异,然后在渲染Markdown时,给差异文本包裹高亮样式的标签,实现渲染后内容的精准高亮。

步骤:

  1. 安装依赖:
npm install diff-match-patch react-markdown
  1. 实现组件:
import React from 'react';
import ReactMarkdown from 'react-markdown';
import DiffMatchPatch from 'diff-match-patch';

const dmp = new DiffMatchPatch();

const MarkdownDiff = ({ oldMarkdown, newMarkdown }) => {
  // 计算文本差异并优化结果
  const diffs = dmp.diff_main(oldMarkdown, newMarkdown);
  dmp.diff_cleanupSemantic(diffs);

  // 构建带高亮标记的内容
  const buildDiffContent = () => {
    return diffs.map(([diffType, text], index) => {
      let highlightClass = '';
      switch (diffType) {
        case 1: // 新增内容
          highlightClass = 'bg-green-100 text-green-800 px-1 rounded';
          break;
        case -1: // 删除内容(旧版本展示,新版本可隐藏)
          highlightClass = 'bg-red-100 text-red-800 px-1 rounded line-through';
          break;
        default: // 无差异内容
          break;
      }
      return <span key={index} className={highlightClass}>{text}</span>;
    });
  };

  return (
    <div className="flex gap-8 p-4">
      <div className="flex-1">
        <h3 className="font-bold mb-2">旧版本</h3>
        <ReactMarkdown>{oldMarkdown}</ReactMarkdown>
      </div>
      <div className="flex-1">
        <h3 className="font-bold mb-2">新版本</h3>
        {/* 将带高亮标记的内容传入ReactMarkdown渲染 */}
        <ReactMarkdown children={buildDiffContent()} />
      </div>
    </div>
  );
};

export default MarkdownDiff;

这种方式可以实现渲染后文本的精准高亮,差异样式直接作用于修改的文字片段,符合你的预期效果。

方案三:AST级差异对比(进阶)

如果需要对Markdown的结构化内容(比如标题、列表、段落)进行差异对比,可以通过解析Markdown为AST(抽象语法树),对比AST节点的差异后再渲染高亮。

步骤:

  1. 安装依赖:
npm install react-markdown remark-parse unist-util-diff
  1. 简化实现示例:
import React from 'react';
import ReactMarkdown from 'react-markdown';
import { parse } from 'remark-parse';
import { diff } from 'unist-util-diff';

const MarkdownAstDiff = ({ oldMarkdown, newMarkdown }) => {
  // 解析Markdown为AST
  const oldAst = parse(oldMarkdown);
  const newAst = parse(newMarkdown);
  // 获取AST差异
  const astDiff = diff(oldAst, newAst);

  // 自定义渲染节点,根据差异添加高亮样式
  const renderCustomNode = ({ node, ...props }) => {
    // 判断当前节点是否为新增/修改的节点
    const isModified = astDiff.some(diffNode => diffNode.node === node);
    const highlightClass = isModified ? 'bg-yellow-100 p-1 rounded' : '';
    return <div className={highlightClass} {...props} />;
  };

  return (
    <div className="flex gap-8 p-4">
      <div className="flex-1">
        <h3 className="font-bold mb-2">旧版本</h3>
        <ReactMarkdown>{oldMarkdown}</ReactMarkdown>
      </div>
      <div className="flex-1">
        <h3 className="font-bold mb-2">新版本</h3>
        <ReactMarkdown components={{ root: renderCustomNode }}>{newMarkdown}</ReactMarkdown>
      </div>
    </div>
  );
};

export default MarkdownAstDiff;

这种方式适合需要结构化对比的场景,比如识别新增的标题、修改的列表项等。

内容的提问来源于stack exchange,提问作者Mani DS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 07:44:56