markdown-ai-cite-remove 0.2.2

High-performance removal of AI-generated citations and annotations from Markdown text
Documentation

markdown-ai-banner-primary

Rust Crate: Markdown AI Citation Removal

Crates.io Documentation License Tests

"Five years of AI evolution and flirting with AGI. Zero libraries to remove [1][2][3] from markdown ๐Ÿ™„. Remember me well when they take over."

Remove AI-generated citations and annotations from Markdown text at the speed of Rust

High-performance Rust library for removing citations from ChatGPT, Claude, Perplexity, and other AI markdown responses. Removes inline citations [1][2], reference links [1]: https://..., and bibliography sections with 100% accuracy.

๐Ÿ“š CLI Guide โ€ข Benchmarking Guide โ€ข FAQ โ€ข Documentation Index


โšก Performance-First

  • 100+ MB/s throughput on typical documents
  • Zero-copy processing where possible
  • Regex-optimized with lazy compilation
  • Thread-safe stateless design

๐ŸŽฏ Use Cases

Real-World Applications

1. Blog Publishing Pipeline

// Remove citations from AI-generated blog posts before publishing
use markdown_ai_cite_remove::clean;

let ai_draft = fetch_from_chatgpt();
let clean_post = remove_citations(&ai_draft);
publish_to_cms(clean_post);

2. Documentation Generation

// Remove citations from AI-generated documentation
let docs = generate_docs_with_ai();
let clean_docs = remove_citations(&docs);
write_to_file("README.md", clean_docs);

3. Content Aggregation

// Remove citations from multiple AI responses
use markdown_ai_cite_remove::CitationRemover;

let cleaner = CitationRemover::new();
let responses = vec![chatgpt_response, claude_response, perplexity_response];

let cleaned: Vec<String> = responses
    .iter()
    .map(|r| cleaner.remove_citations(r))
    .collect();

4. Streaming API Processing

// Remove citations from AI responses in real-time
async fn process_stream(stream: impl Stream<Item = String>) {
    let cleaner = CitationRemover::new();

    stream
        .map(|chunk| cleaner.remove_citations(&chunk))
        .for_each(|cleaned| {
            send_to_client(cleaned).await;
        })
        .await;
}

5. Batch File Processing (CLI)

# Remove citations from all markdown files in a directory
find ./ai_output -name "*.md" -exec md-cite-remove {} -o ./cleaned/{} \;

Common Scenarios

  • โœ… Remove citations from AI chatbot responses (ChatGPT, Claude, Perplexity, Gemini)
  • โœ… Prepare markdown for blog posts and articles
  • โœ… Remove citations before website publishing
  • โœ… Process streaming API responses in real-time
  • โœ… Batch document cleaning for content pipelines
  • โœ… Remove citations from documentation generated by AI tools
  • โœ… Prepare content for CMS ingestion
  • โœ… Remove annotations from research summaries

๐Ÿ“ฆ Installation

Prerequisites

Minimum Requirements:

  • Rust 1.70 or later
  • Cargo (comes with Rust)

Optional (for enhanced benchmarking):

  • Gnuplot (for benchmark visualization)
    • macOS: brew install gnuplot
    • Ubuntu/Debian: sudo apt-get install gnuplot
    • Windows: Download from http://www.gnuplot.info/

Library Installation

Add to your Cargo.toml:

[dependencies]
markdown-ai-cite-remove = "0.1"

CLI Installation

Install the command-line tool globally:

# Install from crates.io (when published)
cargo install markdown-ai-cite-remove --features cli

# Or install from local source
cargo install --path . --features cli

Verify installation:

md-cite-remove --version

๐Ÿš€ Quick Start

Quick Reference

Task Command
Remove citations from from stdin echo "Text[1]" | md-cite-remove
Remove citations from a file md-cite-remove input.md
Save to file md-cite-remove input.md -o output.md
Verbose output md-cite-remove input.md -o output.md --verbose
Run tests cargo test
Run benchmarks cargo bench
View docs cargo doc --open

Library Usage

use markdown_ai_cite_remove::clean;

let markdown = "AI research shows promise[1][2].\n\n[1]: https://example.com\n[2]: https://test.com";
let result = remove_citations(markdown);
assert_eq!(cleaned.trim(), "AI research shows promise.");

CLI Usage

Basic Examples

1. Process from stdin to stdout (pipe mode):

echo "Text[1] here." | md-cite-remove
# Output: Text here.

2. Remove citations from a file and print to stdout:

md-cite-remove document.md

3. Remove citations from a file and save to another file:

md-cite-remove input.md -o output.md

4. Remove citations from with verbose output (shows processing details):

md-cite-remove input.md -o output.md --verbose
# Output:
# Reading from file: input.md
# Cleaning markdown (input size: 1234 bytes)...
# Cleaned markdown (output size: 1100 bytes)
# Writing to file: output.md
# Done!

Advanced CLI Usage

Process multiple files:

# Using a loop
for file in *.md; do
  md-cite-remove "$file" -o "cleaned_${file}"
done

Integration with other tools:

# Remove citations from AI output from curl
curl https://api.example.com/ai-response | md-cite-remove

# Remove citations from and preview
md-cite-remove document.md | less

# Remove citations from and count words
md-cite-remove document.md | wc -w

# Chain with other markdown processors
md-cite-remove input.md | pandoc -f markdown -t html -o output.html

Using in scripts:

#!/bin/bash
# clean_ai_docs.sh - Remove citations from all AI-generated markdown files

INPUT_DIR="./ai_output"
OUTPUT_DIR="./cleaned"

mkdir -p "$OUTPUT_DIR"

for file in "$INPUT_DIR"/*.md; do
  filename=$(basename "$file")
  md-cite-remove "$file" -o "$OUTPUT_DIR/$filename" --verbose
done

echo "Cleaned $(ls -1 "$INPUT_DIR"/*.md | wc -l) files"

๐Ÿ”ง Features

  • โœ… Remove inline numeric citations [1][2][3]
  • โœ… Remove named citations [source:1][ref:2][cite:3][note:4]
  • โœ… Remove reference link lists [1]: https://...
  • โœ… Remove reference section headers ## References, # Citations, ### Sources
  • โœ… Remove bibliographic entries [1] Author (2024). Title...
  • โœ… Preserve markdown formatting (bold, italic, links, lists, etc.)
  • โœ… Whitespace normalization
  • โœ… Configurable cleaning options

๐Ÿ“– Documentation


๐Ÿ“š Advanced Usage

Custom Configuration

use markdown_ai_cite_remove::{CitationRemover, RemoverConfig};

// Remove only inline citations, keep reference sections
let config = RemoverConfig::inline_only();
let cleaner = CitationRemover::with_config(config);
let result = cleaner.remove_citations("Text[1] here.\n\n[1]: https://example.com");

// Remove only reference sections, keep inline citations
let config = RemoverConfig::references_only();
let result = cleaner.remove_citations("Text[1] here.\n\n[1]: https://example.com");

// Full custom configuration
let config = RemoverConfig {
    remove_inline_citations: true,
    remove_reference_links: true,
    remove_reference_headers: true,
    remove_reference_entries: true,
    normalize_whitespace: true,
    remove_blank_lines: true,
    trim_lines: true,
};

Reusable Cleaner Instance

use markdown_ai_cite_remove::CitationRemover;

let cleaner = CitationRemover::new();

// Reuse for multiple documents
let doc1 = cleaner.remove_citations("First document[1].");
let doc2 = cleaner.remove_citations("Second document[2][3].");
let doc3 = cleaner.remove_citations("Third document[source:1].");

๐Ÿงช Examples

See the examples/ directory for more:

Run examples:

cargo run --example basic_usage
cargo run --example custom_config

๐ŸŽ๏ธ Performance

Running Benchmarks

# Run all benchmarks
cargo bench

# Run specific benchmark
cargo bench chatgpt_format

# Save baseline for comparison
cargo bench -- --save-baseline main

# Compare against baseline
cargo bench -- --baseline main

# View results (after running benchmarks)
open target/criterion/report/index.html  # macOS
xdg-open target/criterion/report/index.html  # Linux
start target/criterion/report/index.html  # Windows

Note about benchmark output:

  • Tests shown as "ignored" during cargo bench is normal behavior - regular tests are skipped during benchmarking to avoid interference
  • Outliers (3-13% of measurements) are normal due to OS scheduling and CPU frequency scaling
  • "Gnuplot not found" warning is harmless - Criterion uses an alternative plotting backend
  • With Gnuplot installed: Interactive HTML reports with charts are generated in target/criterion/report/

Performance Characteristics

Typical performance on modern hardware (Apple Silicon M-series):

Benchmark Time Throughput Notes
Simple inline citations ~580 ns 91 MiB/s Single sentence
Complex document ~2.5 ฮผs 287 MiB/s Multiple sections
Real ChatGPT output ~18 ฮผs 645 MiB/s 11.8 KB document
Real Perplexity output ~245 ฮผs 224 MiB/s 54.9 KB document
Batch (5 documents) ~2.2 ฮผs 43 MiB/s Total for all 5
No citations (passthrough) ~320 ns 393 MiB/s Fastest path

Key Insights:

  • Throughput: 100-650 MB/s depending on document complexity
  • Latency: Sub-microsecond to ~250 ฮผs for large documents
  • Scalability: Linear with document size
  • Memory: ~200-300 bytes per operation

๐Ÿงช Testing

This library has 100%+ test coverage with comprehensive edge case testing.

Running Tests

# Run all tests (unit + integration + doc tests)
cargo test

# Run with output visible
cargo test -- --nocapture

# Run specific test
cargo test test_real_world_chatgpt

# Run only unit tests
cargo test --lib

# Run only integration tests
cargo test --test integration_tests

# Run tests with all features enabled
cargo test --all-features

Test Coverage

  • 58 total tests covering all functionality
  • 18 unit tests - Core logic, patterns, configuration
  • 36 integration tests - Real-world scenarios, edge cases
  • 4 doc tests - Documentation examples

What's tested:

  • โœ… All citation formats (numeric, named, reference links)
  • โœ… Real AI outputs (ChatGPT, Perplexity)
  • โœ… Edge cases (empty strings, no citations, only citations)
  • โœ… Unicode and emoji support
  • โœ… Large documents (1000+ citations)
  • โœ… Configuration variations
  • โœ… Markdown preservation (formatting, links, images)

Understanding Test Output

When running cargo bench, you'll see tests marked as "ignored" - this is normal. Rust automatically skips regular tests during benchmarking to avoid timing interference. All tests pass when running cargo test.


๐Ÿ”ง Troubleshooting

Common Issues

Q: Why do tests show as "ignored" when running cargo bench?

A: This is normal Rust behavior. When running benchmarks, regular tests are automatically skipped to avoid interfering with timing measurements. All tests pass when you run cargo test. See BENCHMARKING.md for details.

Q: What does "Gnuplot not found, using plotters backend" mean?

A: This is just an informational message. Criterion (the benchmarking library) can use Gnuplot for visualization, but falls back to an alternative plotting backend if it's not installed. Benchmarks still run correctly. To install Gnuplot:

  • macOS: brew install gnuplot
  • Ubuntu/Debian: sudo apt-get install gnuplot
  • Windows: Download from http://www.gnuplot.info/

Q: Why are there performance outliers in benchmarks?

A: Outliers (typically 3-13% of measurements) are normal due to:

  • Operating system scheduling
  • CPU frequency scaling
  • Background processes
  • Cache effects

This is expected and doesn't indicate a problem. Criterion automatically detects and reports outliers.

Q: The CLI tool isn't found after installation

A: Make sure Cargo's bin directory is in your PATH:

# Add to ~/.bashrc, ~/.zshrc, or equivalent
export PATH="$HOME/.cargo/bin:$PATH"

# Then reload your shell
source ~/.bashrc  # or source ~/.zshrc

Q: How do I know if citations were actually removed?

A: Use the --verbose flag to see before/after sizes:

md-cite-remove input.md -o output.md --verbose

Getting Help

  • Issues: Report bugs or request features on GitHub
  • Documentation: Run cargo doc --open for full API docs
  • Examples: Check the examples/ directory for working code

๐Ÿค Contributing

Built by OpenSite AI for the developer community.

Contributions welcome! Please feel free to submit a Pull Request.

Development Setup

# Clone the repository
git clone https://github.com/opensite-ai/markdown-ai-cite-remove.git
cd markdown-ai-cite-remove

# Run tests
cargo test

# Run benchmarks
cargo bench

# Build documentation
cargo doc --open

# Format code
cargo fmt

# Run linter
cargo clippy

๐Ÿ“„ License

Licensed under either of:

at your option.