inline: apply word attribute when flushing event buf
fixes issue with e.g `[text]({.cls})` where attributes get immediately
applied to `[text](` where link should have priority.
	
	
This commit is contained in:
		
					parent
					
						
							
								08ef15655b
							
						
					
				
			
			
				commit
				
					
						9454a2e393
					
				
			
		
					 2 changed files with 59 additions and 31 deletions
				
			
		| 
						 | 
				
			
			@ -63,7 +63,7 @@ pub enum EventKind {
 | 
			
		|||
    Atom(Atom),
 | 
			
		||||
    Str,
 | 
			
		||||
    Whitespace,
 | 
			
		||||
    Attributes,
 | 
			
		||||
    Attributes { container: bool },
 | 
			
		||||
    Placeholder,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -273,7 +273,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                    if non_empty {
 | 
			
		||||
                        let e_attr = event_opener - 1;
 | 
			
		||||
                        self.events[e_attr] = Event {
 | 
			
		||||
                            kind: EventKind::Attributes,
 | 
			
		||||
                            kind: EventKind::Attributes { container: true },
 | 
			
		||||
                            span: span_attr,
 | 
			
		||||
                        };
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -360,20 +360,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                        .map_or(false, |e| e.kind == EventKind::Str);
 | 
			
		||||
 | 
			
		||||
                if set_attr {
 | 
			
		||||
                    let i = self
 | 
			
		||||
                        .events
 | 
			
		||||
                        .iter()
 | 
			
		||||
                        .rposition(|e| e.kind != EventKind::Str)
 | 
			
		||||
                        .map_or(0, |i| i + 1);
 | 
			
		||||
                    let span_str = self.events[i]
 | 
			
		||||
                        .span
 | 
			
		||||
                        .union(self.events[self.events.len() - 1].span);
 | 
			
		||||
                    self.events.drain(i..);
 | 
			
		||||
 | 
			
		||||
                    self.push(EventKind::Attributes);
 | 
			
		||||
                    self.push_sp(EventKind::Enter(Span), span_str.empty_before());
 | 
			
		||||
                    self.push_sp(EventKind::Str, span_str);
 | 
			
		||||
                    self.push_sp(EventKind::Exit(Span), span_str.empty_after());
 | 
			
		||||
                    self.push(EventKind::Attributes { container: false });
 | 
			
		||||
                } else {
 | 
			
		||||
                    self.push_sp(EventKind::Placeholder, self.input.span.empty_before());
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -573,7 +560,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                if let Some((non_empty, span)) = self.input.ahead_attributes() {
 | 
			
		||||
                    if non_empty {
 | 
			
		||||
                        self.events[e_attr] = Event {
 | 
			
		||||
                            kind: EventKind::Attributes,
 | 
			
		||||
                            kind: EventKind::Attributes { container: true },
 | 
			
		||||
                            span,
 | 
			
		||||
                        };
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -697,9 +684,51 @@ impl<'s> Parser<'s> {
 | 
			
		|||
            let ev = self.events.pop_front().unwrap();
 | 
			
		||||
            span = span.union(ev.span);
 | 
			
		||||
        }
 | 
			
		||||
        Event {
 | 
			
		||||
            kind: EventKind::Str,
 | 
			
		||||
            span,
 | 
			
		||||
 | 
			
		||||
        if matches!(
 | 
			
		||||
            self.events.front().map(|ev| &ev.kind),
 | 
			
		||||
            Some(EventKind::Attributes { container: false })
 | 
			
		||||
        ) {
 | 
			
		||||
            self.apply_word_attributes(span)
 | 
			
		||||
        } else {
 | 
			
		||||
            Event {
 | 
			
		||||
                kind: EventKind::Str,
 | 
			
		||||
                span,
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn apply_word_attributes(&mut self, span_str: Span) -> Event {
 | 
			
		||||
        if let Some(i) = span_str
 | 
			
		||||
            .of(self.input.src)
 | 
			
		||||
            .bytes()
 | 
			
		||||
            .rposition(|c| c.is_ascii_whitespace())
 | 
			
		||||
        {
 | 
			
		||||
            let before = span_str.with_len(i + 1);
 | 
			
		||||
            let word = span_str.skip(i + 1);
 | 
			
		||||
            self.events.push_front(Event {
 | 
			
		||||
                kind: EventKind::Str,
 | 
			
		||||
                span: word,
 | 
			
		||||
            });
 | 
			
		||||
            Event {
 | 
			
		||||
                kind: EventKind::Str,
 | 
			
		||||
                span: before,
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            let attr = self.events.pop_front().unwrap();
 | 
			
		||||
            self.events.push_front(Event {
 | 
			
		||||
                kind: EventKind::Exit(Span),
 | 
			
		||||
                span: span_str.empty_after(),
 | 
			
		||||
            });
 | 
			
		||||
            self.events.push_front(Event {
 | 
			
		||||
                kind: EventKind::Str,
 | 
			
		||||
                span: span_str,
 | 
			
		||||
            });
 | 
			
		||||
            self.events.push_front(Event {
 | 
			
		||||
                kind: EventKind::Enter(Span),
 | 
			
		||||
                span: span_str.empty_before(),
 | 
			
		||||
            });
 | 
			
		||||
            attr
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -883,7 +912,7 @@ impl<'s> Iterator for Parser<'s> {
 | 
			
		|||
        self.events.pop_front().and_then(|e| match e.kind {
 | 
			
		||||
            EventKind::Str if e.span.is_empty() => self.next(),
 | 
			
		||||
            EventKind::Str | EventKind::Whitespace => Some(self.merge_str_events(e.span)),
 | 
			
		||||
            EventKind::Placeholder => self.next(),
 | 
			
		||||
            EventKind::Placeholder | EventKind::Attributes { container: false } => self.next(),
 | 
			
		||||
            _ => Some(e),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -967,7 +996,7 @@ mod test {
 | 
			
		|||
        test_parse!(
 | 
			
		||||
            "pre `raw`{#id} post",
 | 
			
		||||
            (Str, "pre "),
 | 
			
		||||
            (Attributes, "{#id}"),
 | 
			
		||||
            (Attributes { container: true }, "{#id}"),
 | 
			
		||||
            (Enter(Verbatim), "`"),
 | 
			
		||||
            (Str, "raw"),
 | 
			
		||||
            (Exit(Verbatim), "`"),
 | 
			
		||||
| 
						 | 
				
			
			@ -1152,14 +1181,13 @@ mod test {
 | 
			
		|||
    fn span_url_attr_unclosed() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "[text]({.cls}",
 | 
			
		||||
            (Attributes, "{.cls}"),
 | 
			
		||||
            (Attributes { container: false }, "{.cls}"),
 | 
			
		||||
            (Enter(Span), ""),
 | 
			
		||||
            (Str, "[text]("),
 | 
			
		||||
            (Exit(Span), ""),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[ignore = "broken"]
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn span_url_attr_closed() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
| 
						 | 
				
			
			@ -1196,7 +1224,7 @@ mod test {
 | 
			
		|||
    fn span_attr() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "[abc]{.def}",
 | 
			
		||||
            (Attributes, "{.def}"),
 | 
			
		||||
            (Attributes { container: true }, "{.def}"),
 | 
			
		||||
            (Enter(Span), "["),
 | 
			
		||||
            (Str, "abc"),
 | 
			
		||||
            (Exit(Span), "]"),
 | 
			
		||||
| 
						 | 
				
			
			@ -1301,7 +1329,7 @@ mod test {
 | 
			
		|||
    fn container_attr() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "_abc def_{.attr}",
 | 
			
		||||
            (Attributes, "{.attr}"),
 | 
			
		||||
            (Attributes { container: true }, "{.attr}"),
 | 
			
		||||
            (Enter(Emphasis), "_"),
 | 
			
		||||
            (Str, "abc def"),
 | 
			
		||||
            (Exit(Emphasis), "_"),
 | 
			
		||||
| 
						 | 
				
			
			@ -1329,7 +1357,7 @@ mod test {
 | 
			
		|||
    fn container_attr_multiple() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "_abc def_{.a}{.b}{.c} {.d}",
 | 
			
		||||
            (Attributes, "{.a}{.b}{.c}"),
 | 
			
		||||
            (Attributes { container: true }, "{.a}{.b}{.c}"),
 | 
			
		||||
            (Enter(Emphasis), "_"),
 | 
			
		||||
            (Str, "abc def"),
 | 
			
		||||
            (Exit(Emphasis), "_"),
 | 
			
		||||
| 
						 | 
				
			
			@ -1341,7 +1369,7 @@ mod test {
 | 
			
		|||
    fn attr() {
 | 
			
		||||
        test_parse!(
 | 
			
		||||
            "word{a=b}",
 | 
			
		||||
            (Attributes, "{a=b}"),
 | 
			
		||||
            (Attributes { container: false }, "{a=b}"),
 | 
			
		||||
            (Enter(Span), ""),
 | 
			
		||||
            (Str, "word"),
 | 
			
		||||
            (Exit(Span), ""),
 | 
			
		||||
| 
						 | 
				
			
			@ -1349,7 +1377,7 @@ mod test {
 | 
			
		|||
        test_parse!(
 | 
			
		||||
            "some word{.a}{.b} with attrs",
 | 
			
		||||
            (Str, "some "),
 | 
			
		||||
            (Attributes, "{.a}{.b}"),
 | 
			
		||||
            (Attributes { container: false }, "{.a}{.b}"),
 | 
			
		||||
            (Enter(Span), ""),
 | 
			
		||||
            (Str, "word"),
 | 
			
		||||
            (Exit(Span), ""),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -799,7 +799,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
 | 
			
		||||
        let mut first_is_attr = false;
 | 
			
		||||
        let mut attributes = inline.as_ref().map_or_else(Attributes::new, |inl| {
 | 
			
		||||
            if let inline::EventKind::Attributes = inl.kind {
 | 
			
		||||
            if let inline::EventKind::Attributes { .. } = inl.kind {
 | 
			
		||||
                first_is_attr = true;
 | 
			
		||||
                attr::parse(inl.span.of(self.src))
 | 
			
		||||
            } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -911,7 +911,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                },
 | 
			
		||||
                inline::EventKind::Str => Event::Str(inline.span.of(self.src).into()),
 | 
			
		||||
                inline::EventKind::Whitespace
 | 
			
		||||
                | inline::EventKind::Attributes
 | 
			
		||||
                | inline::EventKind::Attributes { .. }
 | 
			
		||||
                | inline::EventKind::Placeholder => {
 | 
			
		||||
                    panic!("{:?}", inline)
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue