mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Fix order of tags in text show rules matches (#5083)
This commit is contained in:
parent
f0ada7ba0c
commit
63e6150ca1
@ -1115,13 +1115,22 @@ fn visit_regex_match<'a>(
|
|||||||
elems: &[Pair<'a>],
|
elems: &[Pair<'a>],
|
||||||
m: RegexMatch<'a>,
|
m: RegexMatch<'a>,
|
||||||
) -> SourceResult<()> {
|
) -> 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 piece = TextElem::packed(m.text);
|
||||||
let context = Context::new(None, Some(m.styles));
|
let context = Context::new(None, Some(m.styles));
|
||||||
let output = m.recipe.apply(s.engine, context.track(), piece)?;
|
let output = m.recipe.apply(s.engine, context.track(), piece)?;
|
||||||
|
|
||||||
let mut output = Some(output);
|
|
||||||
let mut cursor = 0;
|
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 {
|
for &(content, styles) in elems {
|
||||||
// Just forward tags.
|
// Just forward tags.
|
||||||
@ -1130,48 +1139,49 @@ fn visit_regex_match<'a>(
|
|||||||
continue;
|
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 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
|
// If the element starts before the start of match, visit it fully or
|
||||||
// sliced.
|
// sliced.
|
||||||
if subrange.start < matched.start {
|
if elem_range.start < match_range.start {
|
||||||
if subrange.end <= matched.start {
|
if elem_range.end <= match_range.start {
|
||||||
visit(s, content, styles)?;
|
visit(s, content, styles)?;
|
||||||
} else {
|
} else {
|
||||||
let mut elem = content.to_packed::<TextElem>().unwrap().clone();
|
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)?;
|
visit(s, s.store(elem.pack()), styles)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the match starts at or before this element ends, visit the
|
// When the match starts before this element ends, visit it.
|
||||||
// match.
|
if match_range.start < elem_range.end {
|
||||||
if matched.start <= subrange.end {
|
visit_unconsumed_match(s)?;
|
||||||
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)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the element ends after the end of the match, visit if fully or
|
// If the element ends after the end of the match, visit if fully or
|
||||||
// sliced.
|
// sliced.
|
||||||
if subrange.end > matched.end {
|
if elem_range.end > match_range.end {
|
||||||
if subrange.start >= matched.end {
|
if elem_range.start >= match_range.end {
|
||||||
visit(s, content, styles)?;
|
visit(s, content, styles)?;
|
||||||
} else {
|
} else {
|
||||||
let mut elem = content.to_packed::<TextElem>().unwrap().clone();
|
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)?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
tests/ref/issue-5014-show-text-tags.png
Normal file
BIN
tests/ref/issue-5014-show-text-tags.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 184 B |
@ -199,3 +199,12 @@ $a^2 + b^2 = c^2$ is Pythagoras' theorem.
|
|||||||
a \ #h(0pt, weak: true)
|
a \ #h(0pt, weak: true)
|
||||||
b \ #h(0pt, weak: true)
|
b \ #h(0pt, weak: true)
|
||||||
$x$ c $y$
|
$x$ c $y$
|
||||||
|
|
||||||
|
--- issue-5014-show-text-tags ---
|
||||||
|
#{
|
||||||
|
let c = counter("c")
|
||||||
|
show "b": context c.get().first()
|
||||||
|
[a]
|
||||||
|
c.step()
|
||||||
|
[bc]
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user