summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-10-01 12:44:27 +0200
committerGitHub <noreply@github.com>2024-10-01 10:44:27 +0000
commit63e6150ca1cd793d5c2a994e892d862b45bdaa42 (patch)
treec8ff4b8179e9b19f12fa459ef21273525e1b81cb
parentf0ada7ba0c9009c113e34960bc8e7b3f3124476e (diff)
Fix order of tags in text show rules matches (#5083)
-rw-r--r--crates/typst/src/realize.rs50
-rw-r--r--tests/ref/issue-5014-show-text-tags.pngbin0 -> 184 bytes
-rw-r--r--tests/suite/styling/show-text.typ9
3 files changed, 39 insertions, 20 deletions
diff --git a/crates/typst/src/realize.rs b/crates/typst/src/realize.rs
index 97c53ace..f999bfd4 100644
--- a/crates/typst/src/realize.rs
+++ b/crates/typst/src/realize.rs
@@ -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(())
}
diff --git a/tests/ref/issue-5014-show-text-tags.png b/tests/ref/issue-5014-show-text-tags.png
new file mode 100644
index 00000000..4cefe9d3
--- /dev/null
+++ b/tests/ref/issue-5014-show-text-tags.png
Binary files differ
diff --git a/tests/suite/styling/show-text.typ b/tests/suite/styling/show-text.typ
index 66ae6580..4e031648 100644
--- a/tests/suite/styling/show-text.typ
+++ b/tests/suite/styling/show-text.typ
@@ -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]
+}