Skip to main content

pullup/
lib.rs

1pub mod assert;
2pub mod filter;
3
4#[cfg(feature = "markdown")]
5pub mod markdown;
6#[cfg(feature = "mdbook")]
7pub mod mdbook;
8#[cfg(feature = "typst")]
9pub mod typst;
10
11/// Represents all the types of markup events this crate can operate on.
12///
13/// Markup adapters:
14/// * Convert format-specific iterators to [`ParserEvent`] iterators for further
15///   processing.
16/// * Convert [`ParserEvent`] iterators to format-specific iterators for output.
17#[derive(Debug, Clone, PartialEq)]
18pub enum ParserEvent<'a> {
19    #[cfg(feature = "markdown")]
20    Markdown(markdown::Event<'a>),
21    #[cfg(feature = "mdbook")]
22    Mdbook(mdbook::Event<'a>),
23    #[cfg(feature = "typst")]
24    Typst(typst::Event<'a>),
25    #[cfg(not(any(feature = "markdown", feature = "mdbook", feature = "typst")))]
26    NoFeaturesEnabled(core::marker::PhantomData<&'a ()>),
27}
28
29#[macro_export]
30/// Convert between markup events without a buffer or lookahead.
31macro_rules! converter {
32    (
33        $(#[$attr:meta])*
34        $struct_name:ident,
35        $in:ty => $out:ty,
36        $body:expr
37    ) => {
38        // Define the struct with the given name
39        #[derive(Debug, Clone)]
40        $(#[$attr])*
41        pub struct $struct_name<'a, I> {
42            iter: I,
43            p: core::marker::PhantomData<&'a ()>,
44        }
45
46        // Define an implementation for the struct
47        impl<'a, I> $struct_name<'a, I>
48        where
49            I: Iterator<Item = ParserEvent<'a>>,
50        {
51            #[allow(dead_code)]
52            pub fn new(iter: I) -> Self {
53                Self {
54                    iter,
55                    p: core::marker::PhantomData,
56                }
57            }
58        }
59
60        impl<'a, I> Iterator for $struct_name<'a, I>
61        where
62            I: Iterator<Item = $in>,
63        {
64            type Item = $out;
65
66            fn next(&mut self) -> Option<Self::Item> {
67                #[cfg(feature = "tracing")]
68                let span = tracing::span!(tracing::Level::TRACE, &"next");
69                #[cfg(feature = "tracing")]
70                let _enter = span.enter();
71                #[allow(clippy::redundant_closure_call)]
72                $body(self)
73            }
74        }
75    };
76}