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,6 +684,13 @@ impl<'s> Parser<'s> {
|
|||
let ev = self.events.pop_front().unwrap();
|
||||
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 {
|
||||
kind: EventKind::Str,
|
||||
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)]
|
||||
enum Directionality {
|
||||
Uni,
|
||||
|
@ -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…
Reference in a new issue