Fix order of tags in text show rules matches (#5083)

This commit is contained in:
Laurenz 2024-10-01 12:44:27 +02:00 committed by GitHub
parent f0ada7ba0c
commit 63e6150ca1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 39 additions and 20 deletions

View File

@ -1115,13 +1115,22 @@ fn visit_regex_match<'a>(
elems: &[Pair<'a>],
m: RegexMatch<'a>,
) -> SourceResult<()> {
let matched = m.offset..m.offset + m.text.len();
let match_range = m.offset..m.offset + m.text.len();
let piece = TextElem::packed(m.text);
let context = Context::new(None, Some(m.styles));
let output = m.recipe.apply(s.engine, context.track(), piece)?;
let mut output = Some(output);
let mut cursor = 0;
let mut output = Some(output);
let mut visit_unconsumed_match = |s: &mut State<'a, '_, '_, '_>| -> SourceResult<()> {
if let Some(output) = output.take() {
let revocation = Style::Revocation(m.id).into();
let outer = s.arenas.bump.alloc(m.styles);
let chained = outer.chain(s.arenas.styles.alloc(revocation));
visit(s, s.store(output), chained)?;
}
Ok(())
};
for &(content, styles) in elems {
// Just forward tags.
@ -1130,48 +1139,49 @@ fn visit_regex_match<'a>(
continue;
}
// Determine the range of the element.
// At this point, we can have a `TextElem`, `SpaceElem`,
// `LinebreakElem`, or `SmartQuoteElem`. We now determine the range of
// the element.
let len = content.to_packed::<TextElem>().map_or(1, |elem| elem.text.len());
let subrange = cursor..cursor + len;
let elem_range = cursor..cursor + len;
// If the element starts before the start of match, visit it fully or
// sliced.
if subrange.start < matched.start {
if subrange.end <= matched.start {
if elem_range.start < match_range.start {
if elem_range.end <= match_range.start {
visit(s, content, styles)?;
} else {
let mut elem = content.to_packed::<TextElem>().unwrap().clone();
elem.text = elem.text[..matched.start - subrange.start].into();
elem.text = elem.text[..match_range.start - elem_range.start].into();
visit(s, s.store(elem.pack()), styles)?;
}
}
// When the match starts at or before this element ends, visit the
// match.
if matched.start <= subrange.end {
if let Some(output) = output.take() {
let revocation = Style::Revocation(m.id).into();
let outer = s.arenas.bump.alloc(m.styles);
let chained = outer.chain(s.arenas.styles.alloc(revocation));
visit(s, s.store(output), chained)?;
}
// When the match starts before this element ends, visit it.
if match_range.start < elem_range.end {
visit_unconsumed_match(s)?;
}
// If the element ends after the end of the match, visit if fully or
// sliced.
if subrange.end > matched.end {
if subrange.start >= matched.end {
if elem_range.end > match_range.end {
if elem_range.start >= match_range.end {
visit(s, content, styles)?;
} else {
let mut elem = content.to_packed::<TextElem>().unwrap().clone();
elem.text = elem.text[matched.end - subrange.start..].into();
elem.text = elem.text[match_range.end - elem_range.start..].into();
visit(s, s.store(elem.pack()), styles)?;
}
}
cursor = subrange.end;
cursor = elem_range.end;
}
// If the match wasn't consumed yet, visit it. This shouldn't really happen
// in practice (we'd need to have an empty match at the end), but it's an
// extra fail-safe.
visit_unconsumed_match(s)?;
Ok(())
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

View File

@ -199,3 +199,12 @@ $a^2 + b^2 = c^2$ is Pythagoras' theorem.
a \ #h(0pt, weak: true)
b \ #h(0pt, weak: true)
$x$ c $y$
--- issue-5014-show-text-tags ---
#{
let c = counter("c")
show "b": context c.get().first()
[a]
c.step()
[bc]
}