markdown_ai_cite_remove/
lib.rs

1//! # markdown-ai-cite-remove
2//!
3//! **Remove AI-generated citations and annotations from Markdown text**
4//!
5//! High-performance Rust library for cleaning ChatGPT, Claude, Perplexity, and other AI markdown
6//! responses. Removes inline citations `[1][2]`, reference links `[1]: https://...`, and
7//! bibliography sections with 100% accuracy.
8//!
9//! ## Quick Start
10//!
11//! ```
12//! use markdown_ai_cite_remove::clean;
13//!
14//! let markdown = "AI research shows promise[1][2].\n\n[1]: https://example.com\n[2]: https://test.com";
15//! let cleaned = clean(markdown);
16//! assert_eq!(cleaned.trim(), "AI research shows promise.");
17//! ```
18//!
19//! ## Features
20//!
21//! - ✅ Remove inline numeric citations `[1][2][3]`
22//! - ✅ Remove named citations `[source:1][ref:2]`
23//! - ✅ Remove reference link lists `[1]: https://...`
24//! - ✅ Remove reference section headers `## References`
25//! - ✅ Remove bibliographic entries
26//! - ✅ Preserve markdown formatting
27//! - ✅ Whitespace normalization
28//! - ✅ Ultra-fast performance (100+ MB/s throughput)
29//!
30//! ## Custom Configuration
31//!
32//! ```
33//! use markdown_ai_cite_remove::{CitationCleaner, CleanerConfig};
34//!
35//! let config = CleanerConfig {
36//!     remove_inline_citations: true,
37//!     remove_reference_links: true,
38//!     ..Default::default()
39//! };
40//!
41//! let cleaner = CitationCleaner::with_config(config);
42//! let cleaned = cleaner.clean("Text with citations[1].");
43//! ```
44
45mod cleaner;
46mod config;
47mod error;
48mod patterns;
49
50pub use cleaner::CitationCleaner;
51pub use config::{CleanerConfig, RemovalMode};
52pub use error::{CleanerError, Result};
53
54/// Main entry point - clean markdown with default settings
55///
56/// # Examples
57///
58/// ```
59/// use markdown_ai_cite_remove::clean;
60///
61/// let input = "Recent research[1][2] shows promise[3].";
62/// let output = clean(input);
63/// assert_eq!(output, "Recent research shows promise.");
64/// ```
65pub fn clean(markdown: &str) -> String {
66    CitationCleaner::new().clean(markdown)
67}
68
69/// Clean markdown with custom configuration
70///
71/// # Examples
72///
73/// ```
74/// use markdown_ai_cite_remove::{clean_with_config, CleanerConfig};
75///
76/// let config = CleanerConfig::inline_only();
77/// let input = "Text[1] here.\n\nSome content.";
78/// let output = clean_with_config(input, config);
79/// assert_eq!(output.trim(), "Text here.\n\nSome content.");
80/// ```
81pub fn clean_with_config(markdown: &str, config: CleanerConfig) -> String {
82    CitationCleaner::with_config(config).clean(markdown)
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_clean_basic() {
91        let input = "Text[1] here[2].";
92        let expected = "Text here.";
93        assert_eq!(clean(input), expected);
94    }
95
96    #[test]
97    fn test_clean_with_references() {
98        let input = "Content here.\n\n[1]: https://example.com\n[2]: https://test.com";
99        let expected = "Content here.";
100        assert_eq!(clean(input).trim(), expected);
101    }
102
103    #[test]
104    fn test_clean_preserves_markdown() {
105        let input =
106            "# Heading\n\nSome **bold** text[1] and *italic*[2].\n\n[1]: https://example.com";
107        let expected = "# Heading\n\nSome **bold** text and *italic*.";
108        assert_eq!(clean(input).trim(), expected);
109    }
110
111    #[test]
112    fn test_empty_string() {
113        assert_eq!(clean(""), "");
114    }
115
116    #[test]
117    fn test_no_citations() {
118        let input = "Just regular markdown text.";
119        assert_eq!(clean(input), input);
120    }
121}