use miette::Result;
use mq_markdown::Markdown;
use crate::document::{FileType, LineMap};
#[derive(Debug, Clone)]
pub enum DocumentType {
Markdown {
ast: Markdown,
line_map: LineMap,
},
Code {
language: String,
},
PlainText,
}
impl DocumentType {
pub fn new_markdown(content: &str) -> Result<Self> {
let ast = Markdown::from_markdown_str(content)
.map_err(|e| miette::miette!("Failed to parse markdown: {}", e))?;
let line_map = LineMap::from_markdown(&ast);
Ok(Self::Markdown { ast, line_map })
}
pub fn new_code(language: String) -> Self {
Self::Code { language }
}
pub fn new_plain_text() -> Self {
Self::PlainText
}
pub fn file_type(&self) -> FileType {
match self {
Self::Markdown { .. } => FileType::Markdown,
Self::Code { language } => FileType::Code(language.clone()),
Self::PlainText => FileType::PlainText,
}
}
pub fn markdown_ast(&self) -> Option<&Markdown> {
match self {
Self::Markdown { ast, .. } => Some(ast),
_ => None,
}
}
pub fn line_map(&self) -> Option<&LineMap> {
match self {
Self::Markdown { line_map, .. } => Some(line_map),
_ => None,
}
}
pub fn language(&self) -> Option<&str> {
match self {
Self::Code { language } => Some(language.as_str()),
_ => None,
}
}
pub fn rebuild(&mut self, content: &str) -> Result<()> {
match self {
Self::Markdown { ast, line_map } => {
let new_ast = Markdown::from_markdown_str(content)
.map_err(|e| miette::miette!("Failed to reparse markdown: {}", e))?;
*ast = new_ast;
*line_map = LineMap::from_markdown(ast);
Ok(())
}
Self::Code { .. } | Self::PlainText => {
Ok(())
}
}
}
pub fn has_ast(&self) -> bool {
matches!(self, Self::Markdown { .. })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_markdown_document_creation() {
let doc = DocumentType::new_markdown("# Hello World").unwrap();
assert!(doc.has_ast());
assert!(doc.markdown_ast().is_some());
assert!(doc.line_map().is_some());
assert_eq!(doc.file_type(), FileType::Markdown);
}
#[test]
fn test_code_document_creation() {
let doc = DocumentType::new_code("rust".to_string());
assert!(!doc.has_ast());
assert_eq!(doc.language(), Some("rust"));
assert_eq!(doc.file_type(), FileType::Code("rust".to_string()));
}
#[test]
fn test_plain_text_document_creation() {
let doc = DocumentType::new_plain_text();
assert!(!doc.has_ast());
assert_eq!(doc.file_type(), FileType::PlainText);
}
#[test]
fn test_markdown_rebuild() {
let mut doc = DocumentType::new_markdown("# Title").unwrap();
doc.rebuild("## Subtitle").unwrap();
assert!(doc.markdown_ast().is_some());
}
}