inline: parse multi-line link tags/urls
reimplement after broken by "take str per line instead of full inline iter" commit this also resolves #22
This commit is contained in:
		
					parent
					
						
							
								98f3fe5c7c
							
						
					
				
			
			
				commit
				
					
						a846477cea
					
				
			
		
					 3 changed files with 149 additions and 83 deletions
				
			
		
							
								
								
									
										190
									
								
								src/inline.rs
									
										
									
									
									
								
							
							
						
						
									
										190
									
								
								src/inline.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
use crate::attr;
 | 
			
		||||
use crate::lex;
 | 
			
		||||
use crate::CowStr;
 | 
			
		||||
use crate::Span;
 | 
			
		||||
 | 
			
		||||
use lex::Delimiter;
 | 
			
		||||
| 
						 | 
				
			
			@ -23,8 +24,8 @@ pub enum Atom {
 | 
			
		|||
    Quote { ty: QuoteType, left: bool },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 | 
			
		||||
pub enum Container {
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq)]
 | 
			
		||||
pub enum Container<'s> {
 | 
			
		||||
    Span,
 | 
			
		||||
    Subscript,
 | 
			
		||||
    Superscript,
 | 
			
		||||
| 
						 | 
				
			
			@ -38,14 +39,10 @@ pub enum Container {
 | 
			
		|||
    RawFormat,
 | 
			
		||||
    InlineMath,
 | 
			
		||||
    DisplayMath,
 | 
			
		||||
    /// Span is the reference link tag.
 | 
			
		||||
    ReferenceLink,
 | 
			
		||||
    /// Span is the reference link tag.
 | 
			
		||||
    ReferenceImage,
 | 
			
		||||
    /// Span is the URL.
 | 
			
		||||
    InlineLink,
 | 
			
		||||
    /// Span is the URL.
 | 
			
		||||
    InlineImage,
 | 
			
		||||
    ReferenceLink(CowStr<'s>),
 | 
			
		||||
    ReferenceImage(CowStr<'s>),
 | 
			
		||||
    InlineLink(CowStr<'s>),
 | 
			
		||||
    InlineImage(CowStr<'s>),
 | 
			
		||||
    /// Open delimiter span is URL, closing is '>'.
 | 
			
		||||
    Autolink,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -57,9 +54,9 @@ pub enum QuoteType {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug, PartialEq, Eq)]
 | 
			
		||||
pub enum EventKind {
 | 
			
		||||
    Enter(Container),
 | 
			
		||||
    Exit(Container),
 | 
			
		||||
pub enum EventKind<'s> {
 | 
			
		||||
    Enter(Container<'s>),
 | 
			
		||||
    Exit(Container<'s>),
 | 
			
		||||
    Atom(Atom),
 | 
			
		||||
    Str,
 | 
			
		||||
    Attributes { container: bool },
 | 
			
		||||
| 
						 | 
				
			
			@ -67,8 +64,8 @@ pub enum EventKind {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug, PartialEq, Eq)]
 | 
			
		||||
pub struct Event {
 | 
			
		||||
    pub kind: EventKind,
 | 
			
		||||
pub struct Event<'s> {
 | 
			
		||||
    pub kind: EventKind<'s>,
 | 
			
		||||
    pub span: Span,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +76,8 @@ struct Input<'s> {
 | 
			
		|||
    lexer: lex::Lexer<'s>,
 | 
			
		||||
    /// The block is complete, the final line has been provided.
 | 
			
		||||
    complete: bool,
 | 
			
		||||
    /// Span of current line.
 | 
			
		||||
    span_line: Span,
 | 
			
		||||
    /// Span of current event.
 | 
			
		||||
    span: Span,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +88,7 @@ impl<'s> Input<'s> {
 | 
			
		|||
            src,
 | 
			
		||||
            lexer: lex::Lexer::new(""),
 | 
			
		||||
            complete: false,
 | 
			
		||||
            span_line: Span::new(0, 0),
 | 
			
		||||
            span: Span::empty_at(0),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +97,7 @@ impl<'s> Input<'s> {
 | 
			
		|||
        debug_assert!(!self.complete);
 | 
			
		||||
        self.lexer = lex::Lexer::new(line.of(self.src));
 | 
			
		||||
        self.complete = last;
 | 
			
		||||
        self.span_line = line;
 | 
			
		||||
        self.span = line.empty_before();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -192,7 +193,7 @@ pub struct Parser<'s> {
 | 
			
		|||
    openers: Vec<(Opener, usize)>,
 | 
			
		||||
    /// Buffer queue for next events. Events are buffered until no modifications due to future
 | 
			
		||||
    /// characters are needed.
 | 
			
		||||
    events: std::collections::VecDeque<Event>,
 | 
			
		||||
    events: std::collections::VecDeque<Event<'s>>,
 | 
			
		||||
    /// State if inside a verbatim container.
 | 
			
		||||
    verbatim: Option<VerbatimState>,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -219,12 +220,12 @@ impl<'s> Parser<'s> {
 | 
			
		|||
        debug_assert!(self.verbatim.is_none());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn push_sp(&mut self, kind: EventKind, span: Span) -> Option<()> {
 | 
			
		||||
    fn push_sp(&mut self, kind: EventKind<'s>, span: Span) -> Option<()> {
 | 
			
		||||
        self.events.push_back(Event { kind, span });
 | 
			
		||||
        Some(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn push(&mut self, kind: EventKind) -> Option<()> {
 | 
			
		||||
    fn push(&mut self, kind: EventKind<'s>) -> Option<()> {
 | 
			
		||||
        self.push_sp(kind, self.input.span)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -274,12 +275,12 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                    }
 | 
			
		||||
                    self.input.span = span_attr;
 | 
			
		||||
                };
 | 
			
		||||
                let ty_opener = if let EventKind::Enter(ty) = self.events[event_opener].kind {
 | 
			
		||||
                let ty_opener = if let EventKind::Enter(ty) = &self.events[event_opener].kind {
 | 
			
		||||
                    debug_assert!(matches!(
 | 
			
		||||
                        ty,
 | 
			
		||||
                        Verbatim | RawFormat | InlineMath | DisplayMath
 | 
			
		||||
                    ));
 | 
			
		||||
                    ty
 | 
			
		||||
                    ty.clone()
 | 
			
		||||
                } else {
 | 
			
		||||
                    panic!()
 | 
			
		||||
                };
 | 
			
		||||
| 
						 | 
				
			
			@ -504,7 +505,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                self.openers.drain(o..);
 | 
			
		||||
                let mut closed = match DelimEventKind::from(opener) {
 | 
			
		||||
                    DelimEventKind::Container(cont) => {
 | 
			
		||||
                        self.events[e_opener].kind = EventKind::Enter(cont);
 | 
			
		||||
                        self.events[e_opener].kind = EventKind::Enter(cont.clone());
 | 
			
		||||
                        self.push(EventKind::Exit(cont))
 | 
			
		||||
                    }
 | 
			
		||||
                    DelimEventKind::Quote(ty) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -536,26 +537,79 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                        image,
 | 
			
		||||
                    } => {
 | 
			
		||||
                        let span_spec = self.events[e_opener].span.between(self.input.span);
 | 
			
		||||
                        let span_spec = if !inline && span_spec.is_empty() {
 | 
			
		||||
                            self.events[event_span]
 | 
			
		||||
                        let multiline =
 | 
			
		||||
                            self.events[e_opener].span.start() < self.input.span_line.start();
 | 
			
		||||
 | 
			
		||||
                        let spec: CowStr = if span_spec.is_empty() && !inline {
 | 
			
		||||
                            let span_spec = self.events[event_span]
 | 
			
		||||
                                .span
 | 
			
		||||
                                .between(self.events[e_opener - 1].span)
 | 
			
		||||
                                .between(self.events[e_opener - 1].span);
 | 
			
		||||
                            let events_text = self
 | 
			
		||||
                                .events
 | 
			
		||||
                                .iter()
 | 
			
		||||
                                .skip(event_span + 1)
 | 
			
		||||
                                .take(e_opener - event_span - 2);
 | 
			
		||||
 | 
			
		||||
                            if multiline
 | 
			
		||||
                                || events_text.clone().any(|ev| {
 | 
			
		||||
                                    !matches!(ev.kind, EventKind::Str | EventKind::Atom(..))
 | 
			
		||||
                                })
 | 
			
		||||
                            {
 | 
			
		||||
                                events_text
 | 
			
		||||
                                    .filter(|ev| {
 | 
			
		||||
                                        matches!(ev.kind, EventKind::Str | EventKind::Atom(..))
 | 
			
		||||
                                    })
 | 
			
		||||
                                    .map(|ev| ev.span.of(self.input.src))
 | 
			
		||||
                                    .collect::<String>()
 | 
			
		||||
                                    .into()
 | 
			
		||||
                            } else {
 | 
			
		||||
                            span_spec
 | 
			
		||||
                                span_spec.of(self.input.src).into()
 | 
			
		||||
                            }
 | 
			
		||||
                        } else if multiline {
 | 
			
		||||
                            let mut spec = String::new();
 | 
			
		||||
                            let mut first_part = true;
 | 
			
		||||
                            let mut span = self.events[e_opener].span.empty_after();
 | 
			
		||||
 | 
			
		||||
                            let mut append = |span: Span| {
 | 
			
		||||
                                span.of(self.input.src).split('\n').for_each(|s| {
 | 
			
		||||
                                    if !s.is_empty() {
 | 
			
		||||
                                        if !inline && !first_part {
 | 
			
		||||
                                            spec.push(' ');
 | 
			
		||||
                                        }
 | 
			
		||||
                                        spec.push_str(s);
 | 
			
		||||
                                        first_part = false;
 | 
			
		||||
                                    }
 | 
			
		||||
                                })
 | 
			
		||||
                            };
 | 
			
		||||
 | 
			
		||||
                            for ev in self.events.iter().skip(e_opener + 1) {
 | 
			
		||||
                                if span.end() == ev.span.start() {
 | 
			
		||||
                                    span = Span::new(span.start(), ev.span.end());
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    append(span);
 | 
			
		||||
                                    span = ev.span;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            append(span);
 | 
			
		||||
 | 
			
		||||
                            spec.into()
 | 
			
		||||
                        } else {
 | 
			
		||||
                            span_spec.of(self.input.src).into()
 | 
			
		||||
                        };
 | 
			
		||||
 | 
			
		||||
                        let container = match (image, inline) {
 | 
			
		||||
                            (false, false) => ReferenceLink,
 | 
			
		||||
                            (false, true) => InlineLink,
 | 
			
		||||
                            (true, false) => ReferenceImage,
 | 
			
		||||
                            (true, true) => InlineImage,
 | 
			
		||||
                        };
 | 
			
		||||
                        self.events[event_span] = Event {
 | 
			
		||||
                            kind: EventKind::Enter(container),
 | 
			
		||||
                            span: span_spec,
 | 
			
		||||
                            (false, false) => ReferenceLink(spec.into()),
 | 
			
		||||
                            (false, true) => InlineLink(spec.into()),
 | 
			
		||||
                            (true, false) => ReferenceImage(spec.into()),
 | 
			
		||||
                            (true, true) => InlineImage(spec.into()),
 | 
			
		||||
                        };
 | 
			
		||||
                        self.events[event_span].kind = EventKind::Enter(container.clone());
 | 
			
		||||
                        self.events[e_opener - 1] = Event {
 | 
			
		||||
                            kind: EventKind::Exit(container),
 | 
			
		||||
                            span: span_spec,
 | 
			
		||||
                            span: Span::new(
 | 
			
		||||
                                self.events[e_opener - 1].span.start(),
 | 
			
		||||
                                span_spec.end() + 1,
 | 
			
		||||
                            ),
 | 
			
		||||
                        };
 | 
			
		||||
                        self.events.drain(e_opener..);
 | 
			
		||||
                        Some(())
 | 
			
		||||
| 
						 | 
				
			
			@ -687,7 +741,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
        self.push(EventKind::Atom(atom))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn merge_str_events(&mut self, span_str: Span) -> Event {
 | 
			
		||||
    fn merge_str_events(&mut self, span_str: Span) -> Event<'s> {
 | 
			
		||||
        let mut span = span_str;
 | 
			
		||||
        let should_merge = |e: &Event, span: Span| {
 | 
			
		||||
            matches!(e.kind, EventKind::Str | EventKind::Placeholder)
 | 
			
		||||
| 
						 | 
				
			
			@ -711,7 +765,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn apply_word_attributes(&mut self, span_str: Span) -> Event {
 | 
			
		||||
    fn apply_word_attributes(&mut self, span_str: Span) -> Event<'s> {
 | 
			
		||||
        if let Some(i) = span_str
 | 
			
		||||
            .of(self.input.src)
 | 
			
		||||
            .bytes()
 | 
			
		||||
| 
						 | 
				
			
			@ -848,8 +902,8 @@ impl Opener {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum DelimEventKind {
 | 
			
		||||
    Container(Container),
 | 
			
		||||
enum DelimEventKind<'s> {
 | 
			
		||||
    Container(Container<'s>),
 | 
			
		||||
    Span(SpanType),
 | 
			
		||||
    Quote(QuoteType),
 | 
			
		||||
    Link {
 | 
			
		||||
| 
						 | 
				
			
			@ -859,7 +913,7 @@ enum DelimEventKind {
 | 
			
		|||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<Opener> for DelimEventKind {
 | 
			
		||||
impl<'s> From<Opener> for DelimEventKind<'s> {
 | 
			
		||||
    fn from(d: Opener) -> Self {
 | 
			
		||||
        match d {
 | 
			
		||||
            Opener::Span(ty) => Self::Span(ty),
 | 
			
		||||
| 
						 | 
				
			
			@ -886,7 +940,7 @@ impl From<Opener> for DelimEventKind {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
impl<'s> Iterator for Parser<'s> {
 | 
			
		||||
    type Item = Event;
 | 
			
		||||
    type Item = Event<'s>;
 | 
			
		||||
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        while self.events.is_empty()
 | 
			
		||||
| 
						 | 
				
			
			@ -908,12 +962,12 @@ impl<'s> Iterator for Parser<'s> {
 | 
			
		|||
 | 
			
		||||
        // automatically close unclosed verbatim
 | 
			
		||||
        if let Some(VerbatimState { event_opener, .. }) = self.verbatim.take() {
 | 
			
		||||
            let ty_opener = if let EventKind::Enter(ty) = self.events[event_opener].kind {
 | 
			
		||||
            let ty_opener = if let EventKind::Enter(ty) = &self.events[event_opener].kind {
 | 
			
		||||
                debug_assert!(matches!(
 | 
			
		||||
                    ty,
 | 
			
		||||
                    Verbatim | RawFormat | InlineMath | DisplayMath
 | 
			
		||||
                ));
 | 
			
		||||
                ty
 | 
			
		||||
                ty.clone()
 | 
			
		||||
            } else {
 | 
			
		||||
                panic!()
 | 
			
		||||
            };
 | 
			
		||||
| 
						 | 
				
			
			@ -1109,31 +1163,31 @@ mod test {
 | 
			
		|||
    fn span_tag() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "[text][tag]",
 | 
			
		||||
            (Enter(ReferenceLink), "tag"),
 | 
			
		||||
            (Enter(ReferenceLink("tag".into())), "["),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(ReferenceLink), "tag"),
 | 
			
		||||
            (Exit(ReferenceLink("tag".into())), "][tag]"),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "![text][tag]",
 | 
			
		||||
            (Enter(ReferenceImage), "tag"),
 | 
			
		||||
            (Enter(ReferenceImage("tag".into())), "!["),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(ReferenceImage), "tag"),
 | 
			
		||||
            (Exit(ReferenceImage("tag".into())), "][tag]"),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "before [text][tag] after",
 | 
			
		||||
            (Str, "before "),
 | 
			
		||||
            (Enter(ReferenceLink), "tag"),
 | 
			
		||||
            (Enter(ReferenceLink("tag".into())), "["),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(ReferenceLink), "tag"),
 | 
			
		||||
            (Exit(ReferenceLink("tag".into())), "][tag]"),
 | 
			
		||||
            (Str, " after"),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "[[inner][i]][o]",
 | 
			
		||||
            (Enter(ReferenceLink), "o"),
 | 
			
		||||
            (Enter(ReferenceLink), "i"),
 | 
			
		||||
            (Enter(ReferenceLink("o".into())), "["),
 | 
			
		||||
            (Enter(ReferenceLink("i".into())), "["),
 | 
			
		||||
            (Str, "inner"),
 | 
			
		||||
            (Exit(ReferenceLink), "i"),
 | 
			
		||||
            (Exit(ReferenceLink), "o"),
 | 
			
		||||
            (Exit(ReferenceLink("i".into())), "][i]"),
 | 
			
		||||
            (Exit(ReferenceLink("o".into())), "][o]"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1141,15 +1195,15 @@ mod test {
 | 
			
		|||
    fn span_tag_empty() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "[text][]",
 | 
			
		||||
            (Enter(ReferenceLink), "text"),
 | 
			
		||||
            (Enter(ReferenceLink("text".into())), "["),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(ReferenceLink), "text"),
 | 
			
		||||
            (Exit(ReferenceLink("text".into())), "][]"),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "![text][]",
 | 
			
		||||
            (Enter(ReferenceImage), "text"),
 | 
			
		||||
            (Enter(ReferenceImage("text".into())), "!["),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(ReferenceImage), "text"),
 | 
			
		||||
            (Exit(ReferenceImage("text".into())), "][]"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1158,12 +1212,12 @@ mod test {
 | 
			
		|||
        // TODO strip non str from tag?
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "[some _text_][]",
 | 
			
		||||
            (Enter(ReferenceLink), "some _text_"),
 | 
			
		||||
            (Enter(ReferenceLink("some text".into())), "["),
 | 
			
		||||
            (Str, "some "),
 | 
			
		||||
            (Enter(Emphasis), "_"),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(Emphasis), "_"),
 | 
			
		||||
            (Exit(ReferenceLink), "some _text_"),
 | 
			
		||||
            (Exit(ReferenceLink("some text".into())), "][]"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1172,19 +1226,19 @@ mod test {
 | 
			
		|||
        test_parse!(
 | 
			
		||||
            "before [text](url) after",
 | 
			
		||||
            (Str, "before "),
 | 
			
		||||
            (Enter(InlineLink), "url"),
 | 
			
		||||
            (Enter(InlineLink("url".into())), "["),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(InlineLink), "url"),
 | 
			
		||||
            (Exit(InlineLink("url".into())), "](url)"),
 | 
			
		||||
            (Str, " after"),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "[outer [inner](i)](o)",
 | 
			
		||||
            (Enter(InlineLink), "o"),
 | 
			
		||||
            (Enter(InlineLink("o".into())), "["),
 | 
			
		||||
            (Str, "outer "),
 | 
			
		||||
            (Enter(InlineLink), "i"),
 | 
			
		||||
            (Enter(InlineLink("i".into())), "["),
 | 
			
		||||
            (Str, "inner"),
 | 
			
		||||
            (Exit(InlineLink), "i"),
 | 
			
		||||
            (Exit(InlineLink), "o"),
 | 
			
		||||
            (Exit(InlineLink("i".into())), "](i)"),
 | 
			
		||||
            (Exit(InlineLink("o".into())), "](o)"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1203,9 +1257,9 @@ mod test {
 | 
			
		|||
    fn span_url_attr_closed() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "[text]({.cls})",
 | 
			
		||||
            (Enter(InlineLink), "{.cls}"),
 | 
			
		||||
            (Enter(InlineLink("{.cls}".into())), "["),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(InlineLink), "{.cls}"),
 | 
			
		||||
            (Exit(InlineLink("{.cls}".into())), "]({.cls})"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1214,9 +1268,9 @@ mod test {
 | 
			
		|||
        test_parse!(
 | 
			
		||||
            "before [text]() after",
 | 
			
		||||
            (Str, "before "),
 | 
			
		||||
            (Enter(InlineLink), ""),
 | 
			
		||||
            (Enter(InlineLink("".into())), "["),
 | 
			
		||||
            (Str, "text"),
 | 
			
		||||
            (Exit(InlineLink), ""),
 | 
			
		||||
            (Exit(InlineLink("".into())), "]()"),
 | 
			
		||||
            (Str, " after"),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										41
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								src/lib.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -830,16 +830,14 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                        inline::Container::Emphasis => Container::Emphasis,
 | 
			
		||||
                        inline::Container::Strong => Container::Strong,
 | 
			
		||||
                        inline::Container::Mark => Container::Mark,
 | 
			
		||||
                        inline::Container::InlineLink => Container::Link(
 | 
			
		||||
                            inline.span.of(self.src).replace('\n', "").into(),
 | 
			
		||||
                            LinkType::Span(SpanLinkType::Inline),
 | 
			
		||||
                        ),
 | 
			
		||||
                        inline::Container::InlineImage => Container::Image(
 | 
			
		||||
                            inline.span.of(self.src).replace('\n', "").into(),
 | 
			
		||||
                            SpanLinkType::Inline,
 | 
			
		||||
                        ),
 | 
			
		||||
                        inline::Container::ReferenceLink | inline::Container::ReferenceImage => {
 | 
			
		||||
                            let tag = inline.span.of(self.src).replace('\n', " ");
 | 
			
		||||
                        inline::Container::InlineLink(url) => {
 | 
			
		||||
                            Container::Link(url, LinkType::Span(SpanLinkType::Inline))
 | 
			
		||||
                        }
 | 
			
		||||
                        inline::Container::InlineImage(url) => {
 | 
			
		||||
                            Container::Image(url, SpanLinkType::Inline)
 | 
			
		||||
                        }
 | 
			
		||||
                        inline::Container::ReferenceLink(ref tag)
 | 
			
		||||
                        | inline::Container::ReferenceImage(ref tag) => {
 | 
			
		||||
                            let link_def = self
 | 
			
		||||
                                .pre_pass
 | 
			
		||||
                                .link_definitions
 | 
			
		||||
| 
						 | 
				
			
			@ -851,12 +849,12 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                                (url, SpanLinkType::Reference)
 | 
			
		||||
                            } else {
 | 
			
		||||
                                self.pre_pass.heading_id_by_tag(tag.as_ref()).map_or_else(
 | 
			
		||||
                                    || (tag.into(), SpanLinkType::Unresolved),
 | 
			
		||||
                                    || (tag.clone(), SpanLinkType::Unresolved),
 | 
			
		||||
                                    |id| (format!("#{}", id).into(), SpanLinkType::Reference),
 | 
			
		||||
                                )
 | 
			
		||||
                            };
 | 
			
		||||
 | 
			
		||||
                            if matches!(c, inline::Container::ReferenceLink) {
 | 
			
		||||
                            if matches!(c, inline::Container::ReferenceLink(..)) {
 | 
			
		||||
                                Container::Link(url_or_tag, LinkType::Span(ty))
 | 
			
		||||
                            } else {
 | 
			
		||||
                                Container::Image(url_or_tag, ty)
 | 
			
		||||
| 
						 | 
				
			
			@ -1359,7 +1357,6 @@ mod test {
 | 
			
		|||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[ignore = "broken"]
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn link_inline_multi_line() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
| 
						 | 
				
			
			@ -1378,6 +1375,23 @@ mod test {
 | 
			
		|||
            End(Paragraph),
 | 
			
		||||
            End(Blockquote),
 | 
			
		||||
        );
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            concat!(
 | 
			
		||||
                "> [text](a\n", //
 | 
			
		||||
                "> bc\n",       //
 | 
			
		||||
                "> def)\n",     //
 | 
			
		||||
            ),
 | 
			
		||||
            Start(Blockquote, Attributes::new()),
 | 
			
		||||
            Start(Paragraph, Attributes::new()),
 | 
			
		||||
            Start(
 | 
			
		||||
                Link("abcdef".into(), LinkType::Span(SpanLinkType::Inline)),
 | 
			
		||||
                Attributes::new()
 | 
			
		||||
            ),
 | 
			
		||||
            Str("text".into()),
 | 
			
		||||
            End(Link("abcdef".into(), LinkType::Span(SpanLinkType::Inline))),
 | 
			
		||||
            End(Paragraph),
 | 
			
		||||
            End(Blockquote),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
| 
						 | 
				
			
			@ -1442,7 +1456,6 @@ mod test {
 | 
			
		|||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[ignore = "multiline links broken"]
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn link_reference_multiline() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,6 @@ ae6fc15:bugged left/right quote
 | 
			
		|||
e1f5b5e:untrimmed whitespace before linebreak
 | 
			
		||||
07888f3:div close within raw block
 | 
			
		||||
8423412:heading id conflict with existing id
 | 
			
		||||
00a46ed:clear inline formatting from link tags
 | 
			
		||||
c0a3dec:escape in url
 | 
			
		||||
61876cf:roman alpha ambiguity
 | 
			
		||||
f31b357:roman alpha ambiguity
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue