437 lines
13 KiB
Markdown
437 lines
13 KiB
Markdown
# Monaco Editor 文档对比能力与限制说明
|
||
|
||
## 📖 概述
|
||
|
||
本文档详细说明 Monaco Editor 在比较两份 Word 文档时的能力和限制。Monaco Editor 是 VS Code 的核心编辑器组件,主要用于**纯文本对比**,而非格式化文档对比。
|
||
|
||
**核心结论**:Monaco Editor 只能识别和对比**纯文本内容**的差异,无法识别字号、字体、颜色、表格结构等格式化信息。
|
||
|
||
---
|
||
|
||
## ✅ Monaco Editor **能做什么**
|
||
|
||
### 1. 纯文本内容对比
|
||
|
||
- ✅ 逐行对比文字内容的增删改
|
||
- ✅ 识别文本的新增、删除、修改
|
||
- ✅ 字符级精准差异高亮(行内哪些字符被修改)
|
||
- ✅ 区分不同类型的变更(新增、删除、修改)
|
||
|
||
**示例**:
|
||
```diff
|
||
- 总金额:人民币壹佰万元整(¥1,000,000.00)
|
||
+ 总金额:人民币壹佰伍拾万元整(¥1,500,000.00)
|
||
```
|
||
|
||
### 2. 差异导航功能
|
||
|
||
- ✅ 跳转到上一处/下一处差异
|
||
- ✅ 统计差异数量(显示总共有多少处差异)
|
||
- ✅ 自动滚动到差异位置
|
||
- ✅ 差异位置高亮显示
|
||
- ✅ 显示当前查看的差异序号(如 3/15)
|
||
|
||
**功能按钮**:
|
||
- 「上一处差异」- 跳转到前一个修改位置
|
||
- 「下一处差异」- 跳转到后一个修改位置
|
||
- 差异计数器 - 显示「发现 X 处差异」
|
||
|
||
### 3. 差异可视化
|
||
|
||
#### 并排显示模式(Side-by-Side)
|
||
- 左侧:原始文档
|
||
- 右侧:修改后的文档
|
||
- 差异行用竖线连接
|
||
|
||
#### 内联显示模式(Inline)
|
||
- 上下排列显示差异
|
||
- 删除内容在上,新增内容在下
|
||
|
||
#### 颜色高亮说明
|
||
- 🔴 **红色背景**:原始版本的内容(在新版本中被删除或修改前的内容)
|
||
- 🟢 **绿色背景**:修改版本的内容(新增或修改后的内容)
|
||
- 🟡 **深色高亮**:行内具体修改的字符差异(字符级对比)
|
||
|
||
### 4. 基本文本操作
|
||
|
||
- ✅ 搜索功能(Ctrl+F)
|
||
- ✅ 自动换行(wordWrap)
|
||
- ✅ 行号显示
|
||
- ✅ 缩略图导航(Minimap)
|
||
- ✅ 鼠标滚轮缩放
|
||
- ✅ 只读模式(防止误编辑)
|
||
- ✅ 语法高亮(支持多种编程语言)
|
||
|
||
### 5. 文本提取能力(配合其他库)
|
||
|
||
项目中集成的文本提取方案:
|
||
|
||
#### Word 文档提取(使用 mammoth 库)
|
||
```typescript
|
||
import mammoth from 'mammoth';
|
||
|
||
async function extractTextFromWord(docUrl: string): Promise<string> {
|
||
const response = await fetch(docUrl);
|
||
const arrayBuffer = await response.arrayBuffer();
|
||
const textResult = await mammoth.extractRawText({ arrayBuffer });
|
||
return textResult.value; // 纯文本内容
|
||
}
|
||
```
|
||
|
||
**提取结果**:
|
||
- ✅ 提取段落文字
|
||
- ✅ 提取表格内的文字(但不保留表格结构)
|
||
- ✅ 提取列表内容(但不保留序号和缩进)
|
||
- ❌ 不提取图片
|
||
- ❌ 不提取页眉页脚
|
||
|
||
#### PDF 文档提取(使用 pdfjs 库)
|
||
```typescript
|
||
import * as pdfjs from 'pdfjs-dist';
|
||
|
||
async function extractTextFromPdf(pdfUrl: string): Promise<string> {
|
||
const pdf = await pdfjs.getDocument(pdfUrl).promise;
|
||
let fullText = '';
|
||
|
||
for (let i = 1; i <= pdf.numPages; i++) {
|
||
const page = await pdf.getPage(i);
|
||
const textContent = await page.getTextContent();
|
||
const pageText = textContent.items
|
||
.map(item => item.str)
|
||
.join(' ');
|
||
fullText += `\n========== 第 ${i} 页 ==========\n${pageText}\n`;
|
||
}
|
||
|
||
return fullText;
|
||
}
|
||
```
|
||
|
||
**提取结果**:
|
||
- ✅ 提取文本型 PDF 的文字
|
||
- ⚠️ 扫描版 PDF 提取效果差(需要 OCR)
|
||
- ❌ 不提取图片和图表
|
||
|
||
---
|
||
|
||
## ❌ Monaco Editor **不能做什么**
|
||
|
||
### 1. 格式识别(完全无法识别)
|
||
|
||
| 格式类型 | 是否支持 | 说明 |
|
||
|---------|---------|------|
|
||
| 字号大小 | ❌ | 无法识别 12pt → 14pt 的变化 |
|
||
| 字体 | ❌ | 无法识别宋体 → 黑体的变化 |
|
||
| 加粗/斜体/下划线 | ❌ | 所有文本样式都会丢失 |
|
||
| 字体颜色 | ❌ | 无法识别黑色 → 红色的变化 |
|
||
| 背景颜色/高亮 | ❌ | 无法识别文本高亮标记 |
|
||
|
||
**示例对比**:
|
||
|
||
**原始 Word 文档**:
|
||
> **第一条** 合同双方(加粗、14pt、黑体)
|
||
|
||
**Monaco 提取后**:
|
||
> 第一条 合同双方(纯文本、无格式)
|
||
|
||
### 2. 排版结构(无法识别)
|
||
|
||
| 排版元素 | 是否支持 | 说明 |
|
||
|---------|---------|------|
|
||
| 段落对齐方式 | ❌ | 左对齐/居中/右对齐/两端对齐 |
|
||
| 行间距 | ❌ | 1.5倍行距 → 2倍行距的变化 |
|
||
| 段前段后间距 | ❌ | 段落间距设置 |
|
||
| 首行缩进 | ❌ | 2字符缩进等 |
|
||
| 页边距 | ❌ | 上下左右边距 |
|
||
| 分页符 | ❌ | 强制分页 |
|
||
|
||
### 3. 复杂元素(完全丢失)
|
||
|
||
| 文档元素 | 是否支持 | Monaco 处理方式 |
|
||
|---------|---------|----------------|
|
||
| 表格 | ❌ | 只提取表格内的文字,单元格结构丢失 |
|
||
| 图片 | ❌ | 完全无法显示,跳过 |
|
||
| 图表 | ❌ | Excel 图表、SmartArt 等完全丢失 |
|
||
| 页眉/页脚 | ❌ | 不提取 |
|
||
| 脚注/尾注 | ❌ | 不提取 |
|
||
| 批注 | ❌ | Word 批注内容不提取 |
|
||
| 修订标记 | ❌ | Word 修订模式的标记丢失 |
|
||
|
||
**表格示例**:
|
||
|
||
**原始 Word 表格**:
|
||
```
|
||
┌────────┬────────┬────────┐
|
||
│ 项目 │ 数量 │ 单价 │
|
||
├────────┼────────┼────────┤
|
||
│ A产品 │ 100 │ 500 │
|
||
└────────┴────────┴────────┘
|
||
```
|
||
|
||
**Monaco 提取后**:
|
||
```
|
||
项目 数量 单价
|
||
A产品 100 500
|
||
```
|
||
|
||
### 4. 样式和主题(无法识别)
|
||
|
||
- ❌ Word 样式表(标题1、标题2、正文等)
|
||
- ❌ 主题颜色(Office 主题色)
|
||
- ❌ 模板格式
|
||
- ❌ 多级列表样式
|
||
|
||
### 5. 文档元数据(不支持)
|
||
|
||
- ❌ 作者信息
|
||
- ❌ 创建/修改时间
|
||
- ❌ 修订历史(谁在何时修改了什么)
|
||
- ❌ 文档属性(标题、主题、关键字等)
|
||
- ❌ 文档保护/密码
|
||
|
||
### 6. Office 特有功能(不支持)
|
||
|
||
| 功能 | 是否支持 | 说明 |
|
||
|-----|---------|------|
|
||
| 超链接 | ⚠️ 部分支持 | 只显示链接文字,无法点击跳转 |
|
||
| 书签 | ❌ | 不支持 |
|
||
| 目录 | ⚠️ 部分支持 | 只显示文字,无法点击导航 |
|
||
| 交叉引用 | ❌ | 不支持 |
|
||
| 域代码 | ❌ | 日期、页码等域代码不计算 |
|
||
| 宏/VBA | ❌ | 完全忽略 |
|
||
| 嵌入对象 | ❌ | Excel 表格、Visio 图等 |
|
||
|
||
---
|
||
|
||
## 📋 功能对比表
|
||
|
||
### Monaco Editor vs Word 原生比较功能
|
||
|
||
| 对比维度 | Monaco Editor | Word 原生「比较」 | 备注 |
|
||
|---------|--------------|-----------------|------|
|
||
| **文本内容** | ✅ 完全支持 | ✅ 完全支持 | Monaco 可精准识别文字差异 |
|
||
| **字号大小** | ❌ 不支持 | ✅ 支持 | Word 可显示字号变化 |
|
||
| **字体/样式** | ❌ 不支持 | ✅ 支持 | Word 可显示加粗、斜体等 |
|
||
| **颜色** | ❌ 不支持 | ✅ 支持 | Word 可显示字体颜色变化 |
|
||
| **表格结构** | ❌ 不支持 | ✅ 支持 | Word 可对比表格单元格变化 |
|
||
| **图片** | ❌ 不支持 | ✅ 支持 | Word 可显示图片增删 |
|
||
| **页眉页脚** | ❌ 不支持 | ✅ 支持 | Word 可对比页眉页脚内容 |
|
||
| **批注/修订** | ❌ 不支持 | ✅ 支持 | Word 有完整的修订模式 |
|
||
| **并排对比** | ✅ 支持 | ✅ 支持 | 两者都支持左右对比 |
|
||
| **差异导航** | ✅ 支持 | ✅ 支持 | 两者都可跳转到差异位置 |
|
||
| **在线使用** | ✅ 支持 | ❌ 需要桌面应用 | Monaco 可在浏览器中运行 |
|
||
| **跨平台** | ✅ 支持 | ⚠️ 部分支持 | Monaco 支持所有平台,Word 需要安装 |
|
||
| **性能** | ✅ 轻量快速 | ⚠️ 依赖 Office | Monaco 加载快,Word 需要完整 Office |
|
||
|
||
---
|
||
|
||
## 💡 使用建议
|
||
|
||
### ✅ 适用场景
|
||
|
||
1. **纯文本合同对比**
|
||
- 只关心条款内容变化
|
||
- 不关心格式(字体、字号、颜色)
|
||
- 适合法律条款审核
|
||
|
||
2. **代码文件对比**
|
||
- JavaScript、Python、Java 等源代码
|
||
- JSON、YAML 配置文件
|
||
- Markdown 文档
|
||
|
||
3. **法律文书文本对比**
|
||
- 合同条款修改对比
|
||
- 法规文件版本对比
|
||
- 协议文本变更追踪
|
||
|
||
4. **纯文本文档**
|
||
- TXT 文件
|
||
- CSV 文件
|
||
- 日志文件
|
||
|
||
### ❌ 不适用场景
|
||
|
||
1. **需要格式审查的文档**
|
||
- 投标文件格式审查(需要检查字号、字体)
|
||
- 公文格式审核(需要检查页边距、行距)
|
||
- 排版质量检查
|
||
|
||
2. **包含复杂元素的文档**
|
||
- 技术文档(包含大量图表)
|
||
- 设计方案(包含截图和示意图)
|
||
- 财务报表(包含 Excel 表格)
|
||
|
||
3. **需要保留完整格式的场景**
|
||
- 档案归档(需要保留原始格式)
|
||
- 打印输出(需要格式一致)
|
||
- 格式敏感的文档
|
||
|
||
---
|
||
|
||
## 🔄 替代方案
|
||
|
||
如果您需要对比格式化文档,建议使用以下方案:
|
||
|
||
### 1. Word 原生功能
|
||
**路径**:审阅 → 比较 → 比较文档
|
||
|
||
**优点**:
|
||
- ✅ 完整支持所有 Word 格式
|
||
- ✅ 显示详细的修订标记
|
||
- ✅ 可选择对比粒度(字符/单词/段落)
|
||
|
||
**缺点**:
|
||
- ❌ 需要安装 Microsoft Word
|
||
- ❌ 无法在浏览器中使用
|
||
- ❌ 不支持批量对比
|
||
|
||
### 2. Collabora Online
|
||
**说明**:开源的在线 Office 套件,支持 Word 文档预览和编辑
|
||
|
||
**优点**:
|
||
- ✅ 在线使用,无需安装
|
||
- ✅ 保留文档格式
|
||
- ✅ 支持多人协作
|
||
|
||
**缺点**:
|
||
- ❌ 对比功能不如 Word 原生强大
|
||
- ❌ 需要部署 Collabora 服务器
|
||
|
||
**项目集成参考**:见 `CLAUDE.md` 中的 Collabora 集成文档
|
||
|
||
### 3. 专业文档对比工具
|
||
|
||
| 工具名称 | 类型 | 主要功能 |
|
||
|---------|------|---------|
|
||
| **Beyond Compare** | 桌面应用 | 专业的文件/文件夹对比工具 |
|
||
| **WinMerge** | 开源工具 | 免费的文本对比工具 |
|
||
| **Araxis Merge** | 商业软件 | 支持 Word/PDF/图片对比 |
|
||
| **DiffChecker** | 在线工具 | 简单的在线文本对比 |
|
||
|
||
---
|
||
|
||
## 📚 技术实现
|
||
|
||
### 项目中的实现方式
|
||
|
||
**文件位置**:`app/routes/monaco-demo.tsx`
|
||
|
||
**关键步骤**:
|
||
|
||
1. **提取文本**(使用 mammoth 库)
|
||
```typescript
|
||
import mammoth from 'mammoth';
|
||
|
||
const response = await fetch(docUrl);
|
||
const arrayBuffer = await response.arrayBuffer();
|
||
const textResult = await mammoth.extractRawText({ arrayBuffer });
|
||
const plainText = textResult.value;
|
||
```
|
||
|
||
2. **加载到 Monaco Editor**
|
||
```typescript
|
||
import { DiffEditor } from "@monaco-editor/react";
|
||
|
||
<DiffEditor
|
||
height="90vh"
|
||
language="plaintext"
|
||
original={originalText} // 原始文档文本
|
||
modified={modifiedText} // 修改后的文档文本
|
||
options={{
|
||
readOnly: true,
|
||
renderSideBySide: true, // 并排显示
|
||
ignoreTrimWhitespace: false,
|
||
fontSize: 14,
|
||
wordWrap: 'on',
|
||
minimap: { enabled: true },
|
||
}}
|
||
/>
|
||
```
|
||
|
||
3. **差异导航**
|
||
```typescript
|
||
const handleEditorDidMount = (editor) => {
|
||
const lineChanges = editor.getLineChanges();
|
||
console.log(`发现 ${lineChanges.length} 处差异`);
|
||
};
|
||
|
||
const goToNextDiff = () => {
|
||
const modifiedEditor = diffEditorRef.current.getModifiedEditor();
|
||
modifiedEditor.revealLineInCenter(nextChange.modifiedStartLineNumber);
|
||
};
|
||
```
|
||
|
||
### 使用方法
|
||
|
||
**URL 参数加载文档**:
|
||
```
|
||
/monaco-demo?doc1=路径1&doc2=路径2
|
||
```
|
||
|
||
**示例**:
|
||
```
|
||
/monaco-demo?doc1=testWork/合同(1).docx&doc2=testWork/合同(2).docx
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
### 1. 文本提取的限制
|
||
|
||
- **表格**:表格结构会丢失,只保留单元格内的文字
|
||
- **图片**:完全忽略,不提取
|
||
- **格式**:所有格式化信息(字体、颜色、大小)全部丢失
|
||
|
||
### 2. 扫描版 PDF 的问题
|
||
|
||
- 扫描版 PDF(图片 PDF)几乎无法提取文字
|
||
- 需要 OCR(光学字符识别)才能提取文字
|
||
- 项目暂不支持 OCR
|
||
|
||
### 3. 性能考虑
|
||
|
||
- Monaco Editor 体积较大(约 5MB)
|
||
- 建议使用 CDN 加速
|
||
- 大文件(>10MB)建议分段加载
|
||
|
||
### 4. 中文编码问题
|
||
|
||
- 确保文件编码为 UTF-8
|
||
- 使用 `file.text()` 自动识别编码
|
||
- 避免使用 GBK 等编码
|
||
|
||
---
|
||
|
||
## 📖 相关文档
|
||
|
||
- [Monaco Editor 使用指南](./monaco-editor-使用指南.md)
|
||
- [Monaco Editor 官方文档](https://microsoft.github.io/monaco-editor/)
|
||
- [@monaco-editor/react 文档](https://github.com/suren-atoyan/monaco-react)
|
||
- [mammoth.js 文档](https://github.com/mwilliamson/mammoth.js)
|
||
- [PDF.js 文档](https://mozilla.github.io/pdf.js/)
|
||
|
||
---
|
||
|
||
## 🎯 结论
|
||
|
||
**Monaco Editor 适合用于**:
|
||
- ✅ 纯文本内容对比(合同条款、代码、配置文件)
|
||
- ✅ 在线文档对比(无需安装桌面软件)
|
||
- ✅ 开发者工具集成(代码审查、版本对比)
|
||
|
||
**Monaco Editor 不适合用于**:
|
||
- ❌ 格式敏感的文档对比(投标文件、公文)
|
||
- ❌ 包含图表的文档(技术文档、报告)
|
||
- ❌ 需要完整保留 Word 格式的场景
|
||
|
||
**建议**:
|
||
- 对于纯文本合同对比,Monaco Editor 是理想选择
|
||
- 对于格式敏感的文档,建议使用 Word 原生比较功能
|
||
- 对于在线协作场景,可考虑集成 Collabora Online
|
||
|
||
---
|
||
|
||
**文档版本**:v1.0
|
||
**最后更新**:2025-01-29
|
||
**作者**:中国烟草AI合同及卷宗审核系统开发团队
|