diff options
| author | Laurenz <laurmaedje@gmail.com> | 2024-10-02 13:51:09 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-02 11:51:09 +0000 |
| commit | fcdccc9cbae02be0ac61f5f50f7f1a256fdd2b11 (patch) | |
| tree | 671065febf3d6474c0d94f27a90c1fd927847414 | |
| parent | b791aede82cc1424ba38b74200193096390ceecd (diff) | |
Fix textual grouping (#5097)
| -rw-r--r-- | crates/typst/src/realize.rs | 51 | ||||
| -rw-r--r-- | tests/ref/show-text-in-citation.png | bin | 0 -> 795 bytes | |||
| -rw-r--r-- | tests/suite/styling/show-text.typ | 12 |
3 files changed, 38 insertions, 25 deletions
diff --git a/crates/typst/src/realize.rs b/crates/typst/src/realize.rs index f999bfd4..7c199ff1 100644 --- a/crates/typst/src/realize.rs +++ b/crates/typst/src/realize.rs @@ -873,40 +873,41 @@ const fn list_like_grouping<T: ListLike>() -> GroupingRule { /// as part of a paragraph grouping, /// - if that's not possible because another grouping is active, temporarily /// disables textual grouping and revisits the elements. -fn finish_textual(Grouped { s, start }: Grouped) -> SourceResult<()> { - // Try to find a regex match in the grouped textual elements. +fn finish_textual(Grouped { s, mut start }: Grouped) -> SourceResult<()> { + // Try to find a regex match in the grouped textual elements. Returns early + // if there is one. if visit_textual(s, start)? { return Ok(()); } - // No regex match. - match s.groupings.last() { - // Transparently apply the grouped content to an active paragraph. This - // is more efficient than revisiting everything. Checking the priority - // is a bit of a hack, but the simplest way to check which rule is - // active for now. - Some(grouping) if std::ptr::eq(grouping.rule, &PAR) => {} - - // Start a new paragraph based on this textual group. - None => s.groupings.push(Grouping { rule: &PAR, start }), - - // If a non-paragraph grouping is top-level, revisit the grouped - // content with the `TEXTUAL` rule disabled. - _ => { - let elems = s.store_slice(&s.sink[start..]); - let rules = s.rules; - s.sink.truncate(start); - s.rules = &s.rules[1..]; - for &(content, styles) in &elems { - visit(s, content, styles)?; - } - s.rules = rules; - } + // There was no regex match, so we need to collect the text into a paragraph + // grouping. To do that, we first terminate all non-paragraph groupings. + if in_non_par_grouping(s) { + let elems = s.store_slice(&s.sink[start..]); + s.sink.truncate(start); + finish_grouping_while(s, in_non_par_grouping)?; + start = s.sink.len(); + s.sink.extend(elems); + } + + // Now, there are only two options: + // 1. We are already in a paragraph group. In this case, the elements just + // transparently become part of it. + // 2. There is no group at all. In this case, we create one. + if s.groupings.is_empty() { + s.groupings.push(Grouping { start, rule: &PAR }); } Ok(()) } +/// Whether there is an active grouping, but it is not a `PAR` grouping. +fn in_non_par_grouping(s: &State) -> bool { + s.groupings + .last() + .is_some_and(|grouping| !std::ptr::eq(grouping.rule, &PAR)) +} + /// Builds the `ParElem` from inline-level elements. fn finish_par(mut grouped: Grouped) -> SourceResult<()> { // Collapse unsupported spaces in-place. diff --git a/tests/ref/show-text-in-citation.png b/tests/ref/show-text-in-citation.png Binary files differnew file mode 100644 index 00000000..392487bc --- /dev/null +++ b/tests/ref/show-text-in-citation.png diff --git a/tests/suite/styling/show-text.typ b/tests/suite/styling/show-text.typ index 4e031648..af45127c 100644 --- a/tests/suite/styling/show-text.typ +++ b/tests/suite/styling/show-text.typ @@ -162,6 +162,18 @@ hi #show bibliography: none #bibliography("/assets/bib/works.bib") +--- show-text-in-citation --- +#show "A": "B" +#show "[": "(" +#show "]": ")" +#show "[2]": set text(red) + +@netwok A \ +@arrgh B + +#show bibliography: none +#bibliography("/assets/bib/works.bib") + --- show-text-linebreak --- #show "lo\nwo": set text(red) Hello #[ ] \ |
