use crate::error::{KrikError, KrikResult, MarkdownError, MarkdownErrorKind};
use crate::i18n::I18nManager;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::Path;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FrontMatter {
pub title: Option<String>,
pub date: Option<DateTime<Utc>>,
pub tags: Option<Vec<String>>,
pub lang: Option<String>,
pub draft: Option<bool>,
pub pdf: Option<bool>,
#[serde(flatten)]
pub extra: HashMap<String, serde_yaml::Value>,
}
#[derive(Debug, Clone, Serialize)]
pub struct Document {
pub front_matter: FrontMatter,
pub content: String,
pub file_path: String,
pub language: String,
pub base_name: String,
pub toc: Option<String>,
}
pub fn parse_markdown_with_frontmatter(content: &str) -> KrikResult<(FrontMatter, String)> {
parse_markdown_with_frontmatter_for_file(content, Path::new("<unknown>"))
}
pub fn parse_markdown_with_frontmatter_for_file(
content: &str,
file_path: &Path,
) -> KrikResult<(FrontMatter, String)> {
if let Some(stripped) = content.strip_prefix("---\n") {
if let Some(end_pos) = stripped.find("\n---\n") {
let yaml_content = &stripped[..end_pos];
let markdown_content = &stripped[end_pos + 5..];
let front_matter: FrontMatter = serde_yaml::from_str(yaml_content).map_err(|e| {
KrikError::Markdown(Box::new(MarkdownError {
kind: MarkdownErrorKind::InvalidFrontMatter(e),
file: file_path.to_path_buf(),
line: None,
column: None,
context: "Parsing YAML front matter".to_string(),
}))
})?;
return Ok((front_matter, markdown_content.to_string()));
}
}
Ok((
FrontMatter {
title: None,
date: None,
tags: None,
lang: None,
draft: None,
pdf: None,
extra: HashMap::new(),
},
content.to_string(),
))
}
pub fn extract_language_from_filename(filename: &str) -> KrikResult<(String, String)> {
if let Some(dot_pos) = filename.rfind('.') {
let base_part = &filename[..dot_pos];
let potential_lang = &filename[dot_pos + 1..];
if potential_lang.len() == 2 {
if !I18nManager::is_supported_language(potential_lang) {
return Err(KrikError::Markdown(Box::new(MarkdownError {
kind: MarkdownErrorKind::InvalidLanguage(potential_lang.to_string()),
file: Path::new(filename).to_path_buf(),
line: None,
column: None,
context: format!("Extracting language from filename: {filename}"),
})));
}
return Ok((base_part.to_string(), potential_lang.to_string()));
}
}
Ok((filename.to_string(), "en".to_string()))
}