# Tree-sitter Markdown解析器使用指南

## 概述

基于Tree-sitter的Markdown解析器是一个强大的工具，能够解析Markdown文档并保留原文引用信息。它提供了语法树解析、节点查询、位置信息提取等功能。

## 特性

- **精确解析**: 基于Tree-sitter的语法树解析，比传统正则表达式更准确
- **原文引用**: 保留每个节点的精确位置信息（行号、列号、字符偏移）
- **错误恢复**: 即使在语法错误存在时也能提供有用的解析结果
- **多种查询**: 支持标题、链接、代码块等特定节点类型的查询
- **文档验证**: 检查文档结构的一致性和潜在问题
- **实时解析**: 支持实时解析和增量更新

## 快速开始

### 1. 基本解析

```typescript
import { markdownService } from '../services/markdownService';

// 解析Markdown文档
const markdown = `
# 标题

这是一个**粗体**文本和一个[链接](https://example.com)。

## 子标题

- 列表项1
- 列表项2

\`\`\`javascript
console.log('Hello, World!');
\`\`\`
`;

try {
  const result = await markdownService.parseMarkdown(markdown);
  console.log('解析结果:', result);
  console.log('统计信息:', result.statistics);
} catch (error) {
  console.error('解析失败:', error);
}
```

### 2. 使用React组件

```tsx
import React from 'react';
import MarkdownParserRenderer from '../components/MarkdownParserRenderer';

const MyComponent: React.FC = () => {
  const markdown = `
# 我的文档

这是一个示例文档。

## 功能特性

- 支持**粗体**和*斜体*
- 支持[链接](https://example.com)
- 支持代码块

\`\`\`typescript
const greeting = "Hello, World!";
console.log(greeting);
\`\`\`
  `;

  const handleNodeClick = (node) => {
    console.log('点击的节点:', node);
  };

  const handleParseComplete = (result) => {
    console.log('解析完成:', result);
  };

  return (
    <MarkdownParserRenderer
      content={markdown}
      showOutline={true}
      showLinks={true}
      showValidation={true}
      showPositionInfo={true}
      onNodeClick={handleNodeClick}
      onParseComplete={handleParseComplete}
    />
  );
};
```

## API参考

### MarkdownService

#### parseMarkdown(text: string, config?: MarkdownParserConfig)

解析Markdown文档并返回完整的解析结果。

**参数:**
- `text`: 要解析的Markdown文本
- `config`: 可选的解析器配置

**返回:** `Promise<MarkdownParseResult>`

#### extractOutline(text: string)

提取文档大纲（标题结构）。

**参数:**
- `text`: Markdown文本

**返回:** `Promise<OutlineItem[]>`

#### extractLinks(text: string)

提取文档中的所有链接和图片。

**参数:**
- `text`: Markdown文本

**返回:** `Promise<LinkInfo[]>`

#### validateMarkdown(text: string)

验证Markdown文档结构。

**参数:**
- `text`: Markdown文本

**返回:** `Promise<ValidationResult>`

#### queryNodes(text: string, queryType: QueryType | string)

查询特定类型的节点。

**参数:**
- `text`: Markdown文本
- `queryType`: 查询类型（'headings', 'links', 'code'）

**返回:** `Promise<MarkdownNode[]>`

#### findNodeAtPosition(text: string, line: number, column: number)

根据位置查找节点。

**参数:**
- `text`: Markdown文本
- `line`: 行号（从0开始）
- `column`: 列号（从0开始）

**返回:** `Promise<MarkdownNode | null>`

### MarkdownParserRenderer组件

#### 属性

- `content: string` - Markdown文本内容
- `config?: MarkdownParserConfig` - 解析器配置
- `showOutline?: boolean` - 是否显示大纲
- `showLinks?: boolean` - 是否显示链接列表
- `showValidation?: boolean` - 是否显示验证结果
- `showPositionInfo?: boolean` - 是否显示位置信息
- `enableRealTimeParsing?: boolean` - 是否启用实时解析
- `className?: string` - 自定义样式类名
- `onNodeClick?: (node: MarkdownNode) => void` - 节点点击回调
- `onParseComplete?: (result: MarkdownParseResult) => void` - 解析完成回调

## 高级用法

### 1. 自定义解析器配置

```typescript
const config: MarkdownParserConfig = {
  preserve_whitespace: true,
  parse_inline_html: false,
  max_depth: 50,
  timeout_ms: 5000,
};

const result = await markdownService.parseMarkdown(markdown, config);
```

### 2. 查询特定节点

```typescript
// 查询所有标题
const headings = await markdownService.queryHeadings(markdown);

// 查询所有链接
const links = await markdownService.queryLinkNodes(markdown);

// 查询所有代码块
const codeBlocks = await markdownService.queryCodeBlocks(markdown);
```

### 3. 位置信息处理

```typescript
const result = await markdownService.parseMarkdown(markdown);

// 遍历所有节点并打印位置信息
function printNodePositions(node: MarkdownNode, depth = 0) {
  const indent = '  '.repeat(depth);
  const position = markdownService.formatRange(node.range.start, node.range.end);
  console.log(`${indent}${node.node_type} [${position}]: ${node.content.substring(0, 50)}...`);
  
  node.children.forEach(child => printNodePositions(child, depth + 1));
}

printNodePositions(result.root);
```

### 4. 文档验证

```typescript
const validation = await markdownService.validateMarkdown(markdown);

if (!validation.is_valid) {
  console.log('文档存在问题:');
  validation.issues.forEach(issue => {
    console.log(`- ${issue.severity}: ${issue.message} (Line ${issue.range.start.line + 1})`);
  });
}
```

### 5. 实时编辑器集成

```tsx
import React, { useState } from 'react';
import MarkdownParserRenderer from '../components/MarkdownParserRenderer';

const MarkdownEditor: React.FC = () => {
  const [content, setContent] = useState('# 开始编写...');

  return (
    <div className="flex h-screen">
      <div className="w-1/2 p-4">
        <textarea
          value={content}
          onChange={(e) => setContent(e.target.value)}
          className="w-full h-full p-4 border rounded font-mono"
          placeholder="在这里输入Markdown..."
        />
      </div>
      <div className="w-1/2 p-4 border-l">
        <MarkdownParserRenderer
          content={content}
          enableRealTimeParsing={true}
          showOutline={true}
          showValidation={true}
          showPositionInfo={true}
        />
      </div>
    </div>
  );
};
```

## 错误处理

```typescript
try {
  const result = await markdownService.parseMarkdown(markdown);
  // 处理成功结果
} catch (error) {
  if (error.message.includes('timeout')) {
    console.error('解析超时，文档可能过大');
  } else if (error.message.includes('Parser not initialized')) {
    console.error('解析器初始化失败');
  } else {
    console.error('解析失败:', error.message);
  }
}
```

## 性能优化

### 1. 缓存解析结果

```typescript
const cache = new Map<string, MarkdownParseResult>();

async function cachedParse(markdown: string) {
  const hash = btoa(markdown); // 简单哈希
  
  if (cache.has(hash)) {
    return cache.get(hash)!;
  }
  
  const result = await markdownService.parseMarkdown(markdown);
  cache.set(hash, result);
  
  return result;
}
```

### 2. 防抖实时解析

```typescript
import { useMemo, useCallback } from 'react';
import { debounce } from 'lodash';

const useDebounceMarkdownParse = (content: string, delay = 300) => {
  const debouncedParse = useCallback(
    debounce(async (text: string) => {
      try {
        return await markdownService.parseMarkdown(text);
      } catch (error) {
        console.error('Parse error:', error);
        return null;
      }
    }, delay),
    [delay]
  );

  return useMemo(() => debouncedParse(content), [content, debouncedParse]);
};
```

## 最佳实践

1. **错误处理**: 始终使用try-catch包装解析调用
2. **性能**: 对于大文档，考虑使用分页或虚拟滚动
3. **缓存**: 缓存解析结果以避免重复计算
4. **防抖**: 在实时编辑场景中使用防抖
5. **验证**: 定期验证文档结构以确保质量
6. **位置信息**: 利用位置信息实现精确的错误定位和导航

## 故障排除

### 常见问题

1. **解析器初始化失败**
   - 检查Tauri后端是否正常运行
   - 确认tree-sitter-markdown依赖已正确安装

2. **解析超时**
   - 增加timeout_ms配置值
   - 考虑分块处理大文档

3. **内存使用过高**
   - 减少max_depth配置值
   - 清理不需要的解析结果缓存

4. **位置信息不准确**
   - 确保文本编码一致（UTF-8）
   - 检查换行符格式（LF vs CRLF）

### 调试技巧

```typescript
// 启用详细日志
const config: MarkdownParserConfig = {
  // ... 其他配置
};

// 检查解析统计
const result = await markdownService.parseMarkdown(markdown, config);
console.log('解析统计:', result.statistics);

// 验证文档结构
const validation = await markdownService.validateMarkdown(markdown);
console.log('验证结果:', validation);
```

## 扩展功能

### 自定义查询

虽然当前版本提供了预定义的查询类型，但可以通过修改后端代码添加自定义查询：

```rust
// 在markdown_parser.rs中添加新的查询
let custom_query = Query::new(language, r#"
    (blockquote) @quote
    (table) @table
"#)?;
queries.insert("custom".to_string(), custom_query);
```

### 插件系统

考虑实现插件系统以支持：
- 自定义节点渲染器
- 语法扩展
- 自定义验证规则
- 导出格式支持

这个解析器为Markdown文档处理提供了强大而灵活的基础，可以根据具体需求进行扩展和定制。
