1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! `obsidian-parser` - Blazingly fast Rust library for parsing and analyzing [Obsidian](https://obsidian.md) vaults
//!
//! Provides idiomatic APIs for:
//! - Parsing individual Obsidian notes with frontmatter properties
//! - Analyzing entire vaults as knowledge graphs
//! - Extracting semantic relationships between notes
//!
//! ## Key Features
//! * ⚡ **High Performance**: Parses 1000+ notes in under 3ms
//! * 🧠 **Knowledge Graphs**: Built-in integration with [`petgraph`](https://docs.rs/petgraph/latest/petgraph) for advanced analysis
//! * 🧩 **Flexible API**: Supports both in-memory and on-disk note representations
//! * 🔍 **Frontmatter Parsing**: Extract YAML properties with [`serde`](https://docs.rs/serde/latest/serde) compatibility
//! * 🌐 **Link Analysis**: Identify connections between notes
//! * 👾 **WebAssembly Support**: Add `obsidian-parser` to your Obsidian plugins
//!
//! ## Usage
//! Add to `Cargo.toml`:
//! ```toml
//! [dependencies]
//! obsidian-parser = { version = "0.9", features = ["petgraph", "rayon", "digest"] }
//! ```
//!
//! ## Examples
//!
//! ### Basic Parsing
//! ```no_run
//! use obsidian_parser::prelude::*;
//! use serde::Deserialize;
//!
//! // Parse single file with `HashMap`
//! let note_hashmap = NoteInMemory::from_file_default("note.md").unwrap();
//!
//! assert!(!note_hashmap.is_todo().unwrap());
//!
//! println!("Content: {}", note_hashmap.content().unwrap());
//! println!("Properties: {:#?}", note_hashmap.properties().unwrap().unwrap());
//! println!("Tags: {:?}", note_hashmap.tags().unwrap());
//!
//! // Parse single file with custom struct
//! #[derive(Clone, Deserialize)]
//! struct NoteProperties {
//! created: String,
//! tags: Vec<String>,
//! priority: u8,
//! }
//!
//! let note_with_serde: NoteInMemory<NoteProperties> = NoteInMemory::from_file("note.md").unwrap();
//! ```
//!
//! ### Vault Analysis
//! ```no_run
//! use obsidian_parser::prelude::*;
//!
//! // Load entire vault
//! let options = VaultOptions::new("/path/to/vault");
//! let vault: VaultInMemory = VaultBuilder::new(&options)
//! .into_iter()
//! .filter_map(Result::ok)
//! .build_vault(&options);
//!
//! // Check for duplicate note names
//! if !vault.have_duplicates_notes_by_name() {
//! eprintln!("Duplicate note names detected!");
//! }
//!
//! // Access parsed notes
//! for note in vault.notes() {
//! println!("Note: {:?}", note);
//! }
//! ```
//!
//! ### Graph Analysis (requires [`petgraph`](https://docs.rs/petgraph/latest/petgraph) feature)
//! ```no_run
//! #[cfg(feature = "petgraph")]
//! {
//! use obsidian_parser::prelude::*;
//! use petgraph::dot::{Dot, Config};
//!
//! let options = VaultOptions::new("/path/to/vault");
//! let vault: VaultInMemory = VaultBuilder::new(&options)
//! .into_iter()
//! .filter_map(Result::ok)
//! .build_vault(&options);
//!
//! let graph = vault.get_digraph().unwrap();
//!
//! // Export to Graphviz format
//! println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel]));
//!
//! // Find most connected note
//! let most_connected = graph.node_indices()
//! .max_by_key(|n| graph.edges(*n).count())
//! .unwrap();
//! println!("Knowledge hub: {:?}", graph[most_connected]);
//! }
//! ```
//! ## Performance
//! Optimized for large vaults:
//! - 🚀 1000 files parsed in 2.6 ms (avg)
//! - 💾 Peak memory: 900KB per 1000 notes
//!
//! Parallel processing via Rayon (enable `rayon` feature)
pub