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), |     Atom(Atom), | ||||||
|     Str, |     Str, | ||||||
|     Whitespace, |     Whitespace, | ||||||
|     Attributes, |     Attributes { container: bool }, | ||||||
|     Placeholder, |     Placeholder, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -273,7 +273,7 @@ impl<'s> Parser<'s> { | ||||||
|                     if non_empty { |                     if non_empty { | ||||||
|                         let e_attr = event_opener - 1; |                         let e_attr = event_opener - 1; | ||||||
|                         self.events[e_attr] = Event { |                         self.events[e_attr] = Event { | ||||||
|                             kind: EventKind::Attributes, |                             kind: EventKind::Attributes { container: true }, | ||||||
|                             span: span_attr, |                             span: span_attr, | ||||||
|                         }; |                         }; | ||||||
|                     } |                     } | ||||||
|  | @ -360,20 +360,7 @@ impl<'s> Parser<'s> { | ||||||
|                         .map_or(false, |e| e.kind == EventKind::Str); |                         .map_or(false, |e| e.kind == EventKind::Str); | ||||||
| 
 | 
 | ||||||
|                 if set_attr { |                 if set_attr { | ||||||
|                     let i = self |                     self.push(EventKind::Attributes { container: false }); | ||||||
|                         .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()); |  | ||||||
|                 } else { |                 } else { | ||||||
|                     self.push_sp(EventKind::Placeholder, self.input.span.empty_before()); |                     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 let Some((non_empty, span)) = self.input.ahead_attributes() { | ||||||
|                     if non_empty { |                     if non_empty { | ||||||
|                         self.events[e_attr] = Event { |                         self.events[e_attr] = Event { | ||||||
|                             kind: EventKind::Attributes, |                             kind: EventKind::Attributes { container: true }, | ||||||
|                             span, |                             span, | ||||||
|                         }; |                         }; | ||||||
|                     } |                     } | ||||||
|  | @ -697,6 +684,13 @@ impl<'s> Parser<'s> { | ||||||
|             let ev = self.events.pop_front().unwrap(); |             let ev = self.events.pop_front().unwrap(); | ||||||
|             span = span.union(ev.span); |             span = span.union(ev.span); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         if matches!( | ||||||
|  |             self.events.front().map(|ev| &ev.kind), | ||||||
|  |             Some(EventKind::Attributes { container: false }) | ||||||
|  |         ) { | ||||||
|  |             self.apply_word_attributes(span) | ||||||
|  |         } else { | ||||||
|             Event { |             Event { | ||||||
|                 kind: EventKind::Str, |                 kind: EventKind::Str, | ||||||
|                 span, |                 span, | ||||||
|  | @ -704,6 +698,41 @@ impl<'s> Parser<'s> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     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 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||||||
| enum Directionality { | enum Directionality { | ||||||
|     Uni, |     Uni, | ||||||
|  | @ -883,7 +912,7 @@ impl<'s> Iterator for Parser<'s> { | ||||||
|         self.events.pop_front().and_then(|e| match e.kind { |         self.events.pop_front().and_then(|e| match e.kind { | ||||||
|             EventKind::Str if e.span.is_empty() => self.next(), |             EventKind::Str if e.span.is_empty() => self.next(), | ||||||
|             EventKind::Str | EventKind::Whitespace => Some(self.merge_str_events(e.span)), |             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), |             _ => Some(e), | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  | @ -967,7 +996,7 @@ mod test { | ||||||
|         test_parse!( |         test_parse!( | ||||||
|             "pre `raw`{#id} post", |             "pre `raw`{#id} post", | ||||||
|             (Str, "pre "), |             (Str, "pre "), | ||||||
|             (Attributes, "{#id}"), |             (Attributes { container: true }, "{#id}"), | ||||||
|             (Enter(Verbatim), "`"), |             (Enter(Verbatim), "`"), | ||||||
|             (Str, "raw"), |             (Str, "raw"), | ||||||
|             (Exit(Verbatim), "`"), |             (Exit(Verbatim), "`"), | ||||||
|  | @ -1152,14 +1181,13 @@ mod test { | ||||||
|     fn span_url_attr_unclosed() { |     fn span_url_attr_unclosed() { | ||||||
|         test_parse!( |         test_parse!( | ||||||
|             "[text]({.cls}", |             "[text]({.cls}", | ||||||
|             (Attributes, "{.cls}"), |             (Attributes { container: false }, "{.cls}"), | ||||||
|             (Enter(Span), ""), |             (Enter(Span), ""), | ||||||
|             (Str, "[text]("), |             (Str, "[text]("), | ||||||
|             (Exit(Span), ""), |             (Exit(Span), ""), | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[ignore = "broken"] |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn span_url_attr_closed() { |     fn span_url_attr_closed() { | ||||||
|         test_parse!( |         test_parse!( | ||||||
|  | @ -1196,7 +1224,7 @@ mod test { | ||||||
|     fn span_attr() { |     fn span_attr() { | ||||||
|         test_parse!( |         test_parse!( | ||||||
|             "[abc]{.def}", |             "[abc]{.def}", | ||||||
|             (Attributes, "{.def}"), |             (Attributes { container: true }, "{.def}"), | ||||||
|             (Enter(Span), "["), |             (Enter(Span), "["), | ||||||
|             (Str, "abc"), |             (Str, "abc"), | ||||||
|             (Exit(Span), "]"), |             (Exit(Span), "]"), | ||||||
|  | @ -1301,7 +1329,7 @@ mod test { | ||||||
|     fn container_attr() { |     fn container_attr() { | ||||||
|         test_parse!( |         test_parse!( | ||||||
|             "_abc def_{.attr}", |             "_abc def_{.attr}", | ||||||
|             (Attributes, "{.attr}"), |             (Attributes { container: true }, "{.attr}"), | ||||||
|             (Enter(Emphasis), "_"), |             (Enter(Emphasis), "_"), | ||||||
|             (Str, "abc def"), |             (Str, "abc def"), | ||||||
|             (Exit(Emphasis), "_"), |             (Exit(Emphasis), "_"), | ||||||
|  | @ -1329,7 +1357,7 @@ mod test { | ||||||
|     fn container_attr_multiple() { |     fn container_attr_multiple() { | ||||||
|         test_parse!( |         test_parse!( | ||||||
|             "_abc def_{.a}{.b}{.c} {.d}", |             "_abc def_{.a}{.b}{.c} {.d}", | ||||||
|             (Attributes, "{.a}{.b}{.c}"), |             (Attributes { container: true }, "{.a}{.b}{.c}"), | ||||||
|             (Enter(Emphasis), "_"), |             (Enter(Emphasis), "_"), | ||||||
|             (Str, "abc def"), |             (Str, "abc def"), | ||||||
|             (Exit(Emphasis), "_"), |             (Exit(Emphasis), "_"), | ||||||
|  | @ -1341,7 +1369,7 @@ mod test { | ||||||
|     fn attr() { |     fn attr() { | ||||||
|         test_parse!( |         test_parse!( | ||||||
|             "word{a=b}", |             "word{a=b}", | ||||||
|             (Attributes, "{a=b}"), |             (Attributes { container: false }, "{a=b}"), | ||||||
|             (Enter(Span), ""), |             (Enter(Span), ""), | ||||||
|             (Str, "word"), |             (Str, "word"), | ||||||
|             (Exit(Span), ""), |             (Exit(Span), ""), | ||||||
|  | @ -1349,7 +1377,7 @@ mod test { | ||||||
|         test_parse!( |         test_parse!( | ||||||
|             "some word{.a}{.b} with attrs", |             "some word{.a}{.b} with attrs", | ||||||
|             (Str, "some "), |             (Str, "some "), | ||||||
|             (Attributes, "{.a}{.b}"), |             (Attributes { container: false }, "{.a}{.b}"), | ||||||
|             (Enter(Span), ""), |             (Enter(Span), ""), | ||||||
|             (Str, "word"), |             (Str, "word"), | ||||||
|             (Exit(Span), ""), |             (Exit(Span), ""), | ||||||
|  |  | ||||||
|  | @ -799,7 +799,7 @@ impl<'s> Parser<'s> { | ||||||
| 
 | 
 | ||||||
|         let mut first_is_attr = false; |         let mut first_is_attr = false; | ||||||
|         let mut attributes = inline.as_ref().map_or_else(Attributes::new, |inl| { |         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; |                 first_is_attr = true; | ||||||
|                 attr::parse(inl.span.of(self.src)) |                 attr::parse(inl.span.of(self.src)) | ||||||
|             } else { |             } else { | ||||||
|  | @ -911,7 +911,7 @@ impl<'s> Parser<'s> { | ||||||
|                 }, |                 }, | ||||||
|                 inline::EventKind::Str => Event::Str(inline.span.of(self.src).into()), |                 inline::EventKind::Str => Event::Str(inline.span.of(self.src).into()), | ||||||
|                 inline::EventKind::Whitespace |                 inline::EventKind::Whitespace | ||||||
|                 | inline::EventKind::Attributes |                 | inline::EventKind::Attributes { .. } | ||||||
|                 | inline::EventKind::Placeholder => { |                 | inline::EventKind::Placeholder => { | ||||||
|                     panic!("{:?}", inline) |                     panic!("{:?}", inline) | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue