Files
mixvideo-v2/apps/desktop/src-tauri/src/presentation/commands/markdown_commands.rs
2025-07-22 15:04:37 +08:00

424 lines
12 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use crate::infrastructure::markdown_parser::{
MarkdownParser, MarkdownParserConfig, MarkdownParseResult,
OutlineItem, LinkInfo, ValidationResult, MarkdownNode, Range, Position
};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::sync::Mutex;
use tauri::{command, State};
use tracing::{error, info};
/// Markdown解析器状态
pub struct MarkdownParserState {
parser: Mutex<Option<MarkdownParser>>,
}
impl MarkdownParserState {
pub fn new() -> Self {
Self {
parser: Mutex::new(None),
}
}
/// 获取或创建解析器实例
pub fn get_or_create_parser(&self, config: Option<MarkdownParserConfig>) -> Result<()> {
let mut parser_guard = self.parser.lock().unwrap();
if parser_guard.is_none() {
let parser = MarkdownParser::new(config)?;
*parser_guard = Some(parser);
}
Ok(())
}
/// 执行解析操作
pub fn with_parser<F, R>(&self, f: F) -> Result<R>
where
F: FnOnce(&mut MarkdownParser) -> Result<R>,
{
let mut parser_guard = self.parser.lock().unwrap();
if let Some(ref mut parser) = *parser_guard {
f(parser)
} else {
Err(anyhow::anyhow!("Parser not initialized"))
}
}
}
/// 解析Markdown请求
#[derive(Debug, Deserialize)]
pub struct ParseMarkdownRequest {
/// 要解析的Markdown文本
pub text: String,
/// 解析器配置
pub config: Option<MarkdownParserConfigDto>,
}
/// 解析器配置DTO
#[derive(Debug, Deserialize)]
pub struct MarkdownParserConfigDto {
/// 是否保留空白节点
pub preserve_whitespace: Option<bool>,
/// 是否解析内联HTML
pub parse_inline_html: Option<bool>,
/// 最大解析深度
pub max_depth: Option<usize>,
/// 超时时间(毫秒)
pub timeout_ms: Option<u64>,
}
impl From<MarkdownParserConfigDto> for MarkdownParserConfig {
fn from(dto: MarkdownParserConfigDto) -> Self {
let default = MarkdownParserConfig::default();
Self {
preserve_whitespace: dto.preserve_whitespace.unwrap_or(default.preserve_whitespace),
parse_inline_html: dto.parse_inline_html.unwrap_or(default.parse_inline_html),
max_depth: dto.max_depth.unwrap_or(default.max_depth),
timeout_ms: dto.timeout_ms.unwrap_or(default.timeout_ms),
}
}
}
/// 解析Markdown响应
#[derive(Debug, Serialize)]
pub struct ParseMarkdownResponse {
/// 是否成功
pub success: bool,
/// 解析结果
pub result: Option<MarkdownParseResult>,
/// 错误信息
pub error: Option<String>,
}
/// 查询节点请求
#[derive(Debug, Deserialize)]
pub struct QueryNodesRequest {
/// Markdown文本
pub text: String,
/// 查询名称
pub query_name: String,
}
/// 查询节点响应
#[derive(Debug, Serialize)]
pub struct QueryNodesResponse {
/// 是否成功
pub success: bool,
/// 查询结果
pub nodes: Option<Vec<MarkdownNode>>,
/// 错误信息
pub error: Option<String>,
}
/// 位置查询请求
#[derive(Debug, Deserialize)]
pub struct FindNodeAtPositionRequest {
/// Markdown文本
pub text: String,
/// 行号从0开始
pub line: usize,
/// 列号从0开始
pub column: usize,
}
/// 位置查询响应
#[derive(Debug, Serialize)]
pub struct FindNodeAtPositionResponse {
/// 是否成功
pub success: bool,
/// 找到的节点
pub node: Option<MarkdownNode>,
/// 错误信息
pub error: Option<String>,
}
/// 大纲提取请求
#[derive(Debug, Deserialize)]
pub struct ExtractOutlineRequest {
/// Markdown文本
pub text: String,
}
/// 大纲提取响应
#[derive(Debug, Serialize)]
pub struct ExtractOutlineResponse {
/// 是否成功
pub success: bool,
/// 大纲项目
pub outline: Option<Vec<OutlineItem>>,
/// 错误信息
pub error: Option<String>,
}
/// 链接提取请求
#[derive(Debug, Deserialize)]
pub struct ExtractLinksRequest {
/// Markdown文本
pub text: String,
}
/// 链接提取响应
#[derive(Debug, Serialize)]
pub struct ExtractLinksResponse {
/// 是否成功
pub success: bool,
/// 链接信息
pub links: Option<Vec<LinkInfo>>,
/// 错误信息
pub error: Option<String>,
}
/// 验证请求
#[derive(Debug, Deserialize)]
pub struct ValidateMarkdownRequest {
/// Markdown文本
pub text: String,
}
/// 验证响应
#[derive(Debug, Serialize)]
pub struct ValidateMarkdownResponse {
/// 是否成功
pub success: bool,
/// 验证结果
pub validation: Option<ValidationResult>,
/// 错误信息
pub error: Option<String>,
}
/// 解析Markdown文档
#[command]
pub async fn parse_markdown(
request: ParseMarkdownRequest,
state: State<'_, MarkdownParserState>,
) -> Result<ParseMarkdownResponse, String> {
info!("Received Markdown parse request, text length: {}", request.text.len());
// 转换配置
let parser_config = request.config.map(|c| c.into());
// 确保解析器已初始化
if let Err(e) = state.get_or_create_parser(parser_config) {
error!("Failed to initialize Markdown parser: {}", e);
return Ok(ParseMarkdownResponse {
success: false,
result: None,
error: Some(format!("Parser initialization failed: {}", e)),
});
}
// 执行解析
match state.with_parser(|parser| parser.parse(&request.text)) {
Ok(result) => {
info!("Markdown parsing completed successfully");
Ok(ParseMarkdownResponse {
success: true,
result: Some(result),
error: None,
})
}
Err(e) => {
error!("Markdown parsing failed: {}", e);
Ok(ParseMarkdownResponse {
success: false,
result: None,
error: Some(e.to_string()),
})
}
}
}
/// 查询特定类型的节点
#[command]
pub async fn query_markdown_nodes(
request: QueryNodesRequest,
state: State<'_, MarkdownParserState>,
) -> Result<QueryNodesResponse, String> {
info!("Received query nodes request: {}", request.query_name);
// 确保解析器已初始化
if let Err(e) = state.get_or_create_parser(None) {
error!("Failed to initialize Markdown parser: {}", e);
return Ok(QueryNodesResponse {
success: false,
nodes: None,
error: Some(format!("Parser initialization failed: {}", e)),
});
}
// 执行查询
match state.with_parser(|parser| parser.query_nodes(&request.text, &request.query_name)) {
Ok(nodes) => {
info!("Query completed successfully, found {} nodes", nodes.len());
Ok(QueryNodesResponse {
success: true,
nodes: Some(nodes),
error: None,
})
}
Err(e) => {
error!("Query failed: {}", e);
Ok(QueryNodesResponse {
success: false,
nodes: None,
error: Some(e.to_string()),
})
}
}
}
/// 根据位置查找节点
#[command]
pub async fn find_markdown_node_at_position(
request: FindNodeAtPositionRequest,
state: State<'_, MarkdownParserState>,
) -> Result<FindNodeAtPositionResponse, String> {
info!("Received find node at position request: {}:{}", request.line, request.column);
// 确保解析器已初始化
if let Err(e) = state.get_or_create_parser(None) {
error!("Failed to initialize Markdown parser: {}", e);
return Ok(FindNodeAtPositionResponse {
success: false,
node: None,
error: Some(format!("Parser initialization failed: {}", e)),
});
}
// 执行查找
match state.with_parser(|parser| parser.find_node_at_position(&request.text, request.line, request.column)) {
Ok(node) => {
info!("Find node at position completed successfully");
Ok(FindNodeAtPositionResponse {
success: true,
node,
error: None,
})
}
Err(e) => {
error!("Find node at position failed: {}", e);
Ok(FindNodeAtPositionResponse {
success: false,
node: None,
error: Some(e.to_string()),
})
}
}
}
/// 提取文档大纲
#[command]
pub async fn extract_markdown_outline(
request: ExtractOutlineRequest,
state: State<'_, MarkdownParserState>,
) -> Result<ExtractOutlineResponse, String> {
info!("Received extract outline request");
// 确保解析器已初始化
if let Err(e) = state.get_or_create_parser(None) {
error!("Failed to initialize Markdown parser: {}", e);
return Ok(ExtractOutlineResponse {
success: false,
outline: None,
error: Some(format!("Parser initialization failed: {}", e)),
});
}
// 执行大纲提取
match state.with_parser(|parser| parser.extract_outline(&request.text)) {
Ok(outline) => {
info!("Extract outline completed successfully, found {} items", outline.len());
Ok(ExtractOutlineResponse {
success: true,
outline: Some(outline),
error: None,
})
}
Err(e) => {
error!("Extract outline failed: {}", e);
Ok(ExtractOutlineResponse {
success: false,
outline: None,
error: Some(e.to_string()),
})
}
}
}
/// 提取所有链接
#[command]
pub async fn extract_markdown_links(
request: ExtractLinksRequest,
state: State<'_, MarkdownParserState>,
) -> Result<ExtractLinksResponse, String> {
info!("Received extract links request");
// 确保解析器已初始化
if let Err(e) = state.get_or_create_parser(None) {
error!("Failed to initialize Markdown parser: {}", e);
return Ok(ExtractLinksResponse {
success: false,
links: None,
error: Some(format!("Parser initialization failed: {}", e)),
});
}
// 执行链接提取
match state.with_parser(|parser| parser.extract_links(&request.text)) {
Ok(links) => {
info!("Extract links completed successfully, found {} links", links.len());
Ok(ExtractLinksResponse {
success: true,
links: Some(links),
error: None,
})
}
Err(e) => {
error!("Extract links failed: {}", e);
Ok(ExtractLinksResponse {
success: false,
links: None,
error: Some(e.to_string()),
})
}
}
}
/// 验证Markdown文档结构
#[command]
pub async fn validate_markdown(
request: ValidateMarkdownRequest,
state: State<'_, MarkdownParserState>,
) -> Result<ValidateMarkdownResponse, String> {
info!("Received validate markdown request");
// 确保解析器已初始化
if let Err(e) = state.get_or_create_parser(None) {
error!("Failed to initialize Markdown parser: {}", e);
return Ok(ValidateMarkdownResponse {
success: false,
validation: None,
error: Some(format!("Parser initialization failed: {}", e)),
});
}
// 执行验证
match state.with_parser(|parser| parser.validate_structure(&request.text)) {
Ok(validation) => {
info!("Validate markdown completed successfully, found {} issues", validation.issues.len());
Ok(ValidateMarkdownResponse {
success: true,
validation: Some(validation),
error: None,
})
}
Err(e) => {
error!("Validate markdown failed: {}", e);
Ok(ValidateMarkdownResponse {
success: false,
validation: None,
error: Some(e.to_string()),
})
}
}
}