//! # Extended Markdown Iterator
//!
//! This crate wraps the event iterator created by [`equt_md`] to provide a more general
//! while powerful interface.
//!
//! ## Difference between those crates
//!
//! - [`equt_md`] parses the markdown into event iterator.
//! - [`equt_md_frontmatter`] parse the markdown frontmatter into Rust data structure.
//! - [`equt_md_error`] contains all errors in these crates.
//! - [`equt_md_ext`] wraps and extends the crates above for easy using.
//! - [`equt_md_html`] renders the iterator into HTML.
//!
//! [`equt_md`]: https://docs.rs/equt-md/*/equt_md
//! [`equt_md_frontmatter`]: https://docs.rs/equt-md-frontmatter/*/equt_md_frontmatter
//! [`equt_md_error`]: https://docs.rs/equt-md-error/*/equt_md_error
//! [`equt_md_ext`]: https://docs.rs/equt-md-ext/*/equt_md_ext
//! [`equt_md_html`]: https://docs.rs/equt-md-html/*/equt_md_html
mod after;
mod before;
mod parser;

pub use after::After;
pub use before::Before;
pub use equt_md::{Alignment, CodeBlockKind, CowStr, Event, LinkType, Options, Tag};
pub use equt_md_error as error;
pub use equt_md_frontmatter as frontmatter;
pub use parser::Parser;

use equt_md_frontmatter::FrontMatter;

/// An interface for extending the original Markdown event iterator.
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub trait MarkdownExt<T>: Iterator<Item = T> {
    /// Different from a normal iterator, `MarkdownExt` must own the frontmatter
    /// data.
    fn frontmatter(&mut self) -> Option<FrontMatter>;

    /// Place a custom pseudo events iterator after the first occurence of a certain event.
    fn after<P, F, S, G>(mut self, after: P, f: F) -> After<Self, S, P>
    where
        Self: Sized,
        P: Fn(&T) -> bool,
        S: Iterator<Item = T>,
        G: IntoIterator<Item = T, IntoIter = S>,
        F: FnOnce(&Option<FrontMatter>) -> G,
    {
        let frontmatter = self.frontmatter();
        let event = f(&frontmatter);
        After::new(self, frontmatter, after, event)
    }

    /// Place a custom pseudo events iterator before the first occurence of certain event.
    fn before<P, F, S, G>(mut self, before: P, f: F) -> Before<Self, S, P>
    where
        Self: Sized,
        P: Fn(&T) -> bool,
        S: Iterator<Item = T>,
        G: IntoIterator<Item = T, IntoIter = S>,
        F: FnOnce(&Option<FrontMatter>) -> G,
    {
        let frontmatter = self.frontmatter();
        let add = f(&frontmatter).into_iter();
        Before::new(self, frontmatter, before, add)
    }
}
