diff --git a/crates/typst/src/layout/inline/linebreak.rs b/crates/typst/src/layout/inline/linebreak.rs index 075d24b33..1f30bb732 100644 --- a/crates/typst/src/layout/inline/linebreak.rs +++ b/crates/typst/src/layout/inline/linebreak.rs @@ -655,9 +655,9 @@ fn breakpoints(p: &Preparation, mut f: impl FnMut(usize, Breakpoint)) { let (head, tail) = text.split_at(last); if head.ends_with("://") || tail.starts_with("www.") { let (link, _) = link_prefix(tail); - let end = last + link.len(); linebreak_link(link, |i| f(last + i, Breakpoint::Normal)); - while iter.peek().is_some_and(|&p| p < end) { + last += link.len(); + while iter.peek().is_some_and(|&p| p < last) { iter.next(); } } @@ -687,19 +687,17 @@ fn breakpoints(p: &Preparation, mut f: impl FnMut(usize, Breakpoint)) { }; // Hyphenate between the last and current breakpoint. - if hyphenate { - let mut offset = last; + if hyphenate && last < point { for segment in text[last..point].split_word_bounds() { if !segment.is_empty() && segment.chars().all(char::is_alphabetic) { - hyphenations(p, &lb, offset, segment, &mut f); + hyphenations(p, &lb, last, segment, &mut f); } - offset += segment.len(); + last += segment.len(); } } // Call `f` for the UAX #14 break opportunity. f(point, breakpoint); - last = point; } } diff --git a/tests/ref/issue-hyphenate-in-link.png b/tests/ref/issue-hyphenate-in-link.png new file mode 100644 index 000000000..932c23ae9 Binary files /dev/null and b/tests/ref/issue-hyphenate-in-link.png differ diff --git a/tests/suite/layout/inline/linebreak.typ b/tests/suite/layout/inline/linebreak.typ index 2fa29b6ce..7e959352b 100644 --- a/tests/suite/layout/inline/linebreak.typ +++ b/tests/suite/layout/inline/linebreak.typ @@ -107,3 +107,11 @@ For info see #link("https://myhost.tld"). #set page(width: 50pt, height: auto) #h(99%) 🏳️‍🌈 🏳️‍🌈 + +--- issue-hyphenate-in-link --- +#set par(justify: true) + +// The `linebreak()` function accidentally generated out-of-order breakpoints +// for links because it now splits on word boundaries. We avoid the link markup +// syntax because it's show rule interferes. +#"http://creativecommons.org/licenses/by-nc-sa/4.0/"