fix: 优化markdown解析器
This commit is contained in:
143
apps/desktop/docs/markdown_parser_byte_offset_fix.md
Normal file
143
apps/desktop/docs/markdown_parser_byte_offset_fix.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Markdown解析器byte_offset计算修复报告
|
||||
|
||||
## 问题描述
|
||||
|
||||
根据promptx/tauri-desktop-app-expert开发规范的要求,检查了markdown解析逻辑中byte_offset的计算是否正确。发现了以下关键问题:
|
||||
|
||||
### 1. 原始问题
|
||||
|
||||
**问题1:错误的偏移量计算方式**
|
||||
- 原代码在解析过程中手动累加`current_offset`,这种方式不准确
|
||||
- 没有正确处理pulldown-cmark解析器的事件顺序和内容映射关系
|
||||
- 对于UTF-8字符的字节长度计算不准确
|
||||
|
||||
**问题2:缺乏UTF-8支持验证**
|
||||
- 缺少针对UTF-8字符的byte_offset计算测试
|
||||
- 没有验证字符偏移和字节偏移之间的转换正确性
|
||||
|
||||
## 修复方案
|
||||
|
||||
### 1. 使用pulldown-cmark的offset_iter
|
||||
|
||||
**修复前:**
|
||||
```rust
|
||||
let parser = CmarkParser::new(text);
|
||||
let mut events = Vec::new();
|
||||
let mut current_offset = 0;
|
||||
|
||||
for event in parser {
|
||||
events.push((event.clone(), current_offset));
|
||||
// 手动计算偏移量(不准确)
|
||||
match &event {
|
||||
Event::Text(text) => current_offset += text.len(),
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**修复后:**
|
||||
```rust
|
||||
let parser = CmarkParser::new_with_broken_link_callback(
|
||||
text,
|
||||
pulldown_cmark::Options::all(),
|
||||
None
|
||||
);
|
||||
let mut events = Vec::new();
|
||||
|
||||
// 使用pulldown-cmark提供的正确偏移量信息
|
||||
for (event, range) in parser.into_offset_iter() {
|
||||
events.push((event, range.start));
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 正确的字节偏移计算
|
||||
|
||||
**修复前:**
|
||||
```rust
|
||||
// 使用不准确的字符串长度
|
||||
end: self.calculate_position(source_text, current_offset + text.len())
|
||||
```
|
||||
|
||||
**修复后:**
|
||||
```rust
|
||||
// 使用正确的字节长度
|
||||
end: self.calculate_position_from_byte_offset(source_text, *byte_offset + text.as_bytes().len())
|
||||
```
|
||||
|
||||
### 3. 增强的位置计算方法
|
||||
|
||||
添加了专门的方法来处理字节偏移和字符偏移之间的转换:
|
||||
|
||||
```rust
|
||||
/// 根据字节偏移计算位置信息
|
||||
fn calculate_position_from_byte_offset(&self, text: &str, byte_offset: usize) -> Position
|
||||
|
||||
/// 根据字符偏移计算位置信息
|
||||
fn calculate_position_from_char_offset(&self, text: &str, char_offset: usize) -> Position
|
||||
```
|
||||
|
||||
## 测试验证
|
||||
|
||||
### 1. ASCII字符测试
|
||||
```rust
|
||||
#[test]
|
||||
fn test_byte_offset_calculation_ascii() {
|
||||
let text = "Hello\nWorld";
|
||||
// 验证各个位置的字节偏移计算正确性
|
||||
}
|
||||
```
|
||||
|
||||
### 2. UTF-8字符测试
|
||||
```rust
|
||||
#[test]
|
||||
fn test_byte_offset_calculation_utf8() {
|
||||
let text = "你好\n世界"; // UTF-8字符测试
|
||||
// 验证中文字符的字节偏移计算正确性
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 字符偏移转换测试
|
||||
```rust
|
||||
#[test]
|
||||
fn test_char_offset_to_byte_offset_conversion() {
|
||||
// 验证字符偏移和字节偏移之间的双向转换
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 复杂markdown测试
|
||||
```rust
|
||||
#[test]
|
||||
fn test_complex_markdown_byte_offsets() {
|
||||
let markdown = "# 标题\n\n这是**粗体**和*斜体*文本。\n\n```rust\nfn main() {\n println!(\"你好\");\n}\n```";
|
||||
// 验证复杂markdown结构的偏移量计算
|
||||
}
|
||||
```
|
||||
|
||||
## 修复结果
|
||||
|
||||
### 测试通过情况
|
||||
- ✅ ASCII字符byte_offset计算正确
|
||||
- ✅ UTF-8字符byte_offset计算正确
|
||||
- ✅ 字符偏移与字节偏移转换正确
|
||||
- ✅ 复杂markdown结构解析正确
|
||||
- ✅ 位置一致性验证通过
|
||||
- ✅ 所有原有测试继续通过
|
||||
|
||||
### 性能影响
|
||||
- 使用pulldown-cmark的内置offset_iter,性能更优
|
||||
- 减少了手动计算的开销
|
||||
- 提高了解析准确性
|
||||
|
||||
## 符合开发规范
|
||||
|
||||
根据promptx/tauri-desktop-app-expert规范要求:
|
||||
|
||||
1. **类型安全**:✅ 使用Rust的类型系统确保偏移量计算的安全性
|
||||
2. **性能优先**:✅ 使用高效的pulldown-cmark内置方法
|
||||
3. **代码质量**:✅ 添加了全面的单元测试
|
||||
4. **错误处理**:✅ 完善的边界检查和错误处理
|
||||
5. **文档完整**:✅ 详细的代码注释和测试文档
|
||||
|
||||
## 总结
|
||||
|
||||
通过这次修复,markdown解析器的byte_offset计算现在完全正确,特别是对UTF-8字符的支持。修复遵循了Tauri开发规范,确保了代码质量、性能和可维护性。所有测试都通过,证明修复是成功的且没有破坏现有功能。
|
||||
Reference in New Issue
Block a user