Repository: typst/typst
File: crates/typst-layout/src/inline/linebreak.rs (Rust)

Code before:

        // Find out whether the last break was mandatory by checking against
        // rules LB4 and LB5, special-casing the end of text according to LB3.
        // See also: https://docs.rs/icu_segmenter/latest/icu_segmenter/struct.LineSegmenter.html
        let breakpoint = if point == text.len() {
            Breakpoint::Mandatory
        } else {
            const OBJ_REPLACE: char = '\u{FFFC}';
            match lb.get(c) {
                LineBreak::MandatoryBreak
                | LineBreak::CarriageReturn
                | LineBreak::LineFeed
                | LineBreak::NextLine => Breakpoint::Mandatory,

                // https://github.com/typst/typst/issues/5489
                //
                // OBJECT-REPLACEMENT-CHARACTERs provide Contingent Break
                // opportunities before and after by default. This behaviour
                // is however tailorable, see:
                // https://www.unicode.org/reports/tr14/#CB
                // https://www.unicode.org/reports/tr14/#TailorableBreakingRules
                // https://www.unicode.org/reports/tr14/#LB20
                //
                // Don't provide a line breaking opportunity between a LTR-
                // ISOLATE (or any other Combining Mark) and an OBJECT-
                // REPLACEMENT-CHARACTER representing and inline item, if the
                // LTR-ISOLATE could end up as the only character on the
                // previous line.
                LineBreak::CombiningMark
                    if text[point..].starts_with(OBJ_REPLACE)
                        && last == (point - c.len_utf8()) =>
                {
                    continue;
                }

                _ => Breakpoint::Normal,
            }
        };

        // Hyphenate between the last and current breakpoint.
        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, last, segment, &mut f);
                }
                last += segment.len();
            }
        }

        // Call `f` for the UAX #14 break opportunity.
        f(point, breakpoint);

Review comment (suggestion):
```suggestion
                // REPLACEMENT-CHARACTER representing an inline item, if the
```

Code after:

        // Find out whether the last break was mandatory by checking against
        // rules LB4 and LB5, special-casing the end of text according to LB3.
        // See also: https://docs.rs/icu_segmenter/latest/icu_segmenter/struct.LineSegmenter.html
        let breakpoint = if point == text.len() {
            Breakpoint::Mandatory
        } else {
            const OBJ_REPLACE: char = '\u{FFFC}';
            match lb.get(c) {
                LineBreak::MandatoryBreak
                | LineBreak::CarriageReturn
                | LineBreak::LineFeed
                | LineBreak::NextLine => Breakpoint::Mandatory,

                // https://github.com/typst/typst/issues/5489
                //
                // OBJECT-REPLACEMENT-CHARACTERs provide Contingent Break
                // opportunities before and after by default. This behaviour
                // is however tailorable, see:
                // https://www.unicode.org/reports/tr14/#CB
                // https://www.unicode.org/reports/tr14/#TailorableBreakingRules
                // https://www.unicode.org/reports/tr14/#LB20
                //
                // Don't provide a line breaking opportunity between a LTR-
                // ISOLATE (or any other Combining Mark) and an OBJECT-
                // REPLACEMENT-CHARACTER representing an inline item, if the
                // LTR-ISOLATE could end up as the only character on the
                // previous line.
                LineBreak::CombiningMark
                    if text[point..].starts_with(OBJ_REPLACE)
                        && last + c.len_utf8() == point =>
                {
                    continue;
                }

                _ => Breakpoint::Normal,
            }
        };

        // Hyphenate between the last and current breakpoint.
        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, last, segment, &mut f);
                }
                last += segment.len();
            }
        }

        // Call `f` for the UAX #14 break opportunity.
        f(point, breakpoint);