From 4494642b05a8135911ced5b032ab32e29c9dfeb6 Mon Sep 17 00:00:00 2001 From: bflatastic Date: Mon, 9 Nov 2026 18:20:36 +0700 Subject: [PATCH] Search reads ligatures through the page text's ligature_letters --- crates/render/src/text/search.rs | 39 ++------------------------------ 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/crates/render/src/text/search.rs b/crates/render/src/text/search.rs index 5718975849..42df5c0a83 100644 --- a/crates/render/src/text/search.rs +++ b/crates/render/src/text/search.rs @@ -11,6 +11,7 @@ //! hit in any reading counts; where hits from different readings overlap, the one that starts //! first is kept (the longer on a tie). A soft hyphen needs no second reading: it draws nothing, //! and a line that ends in one always runs on. +use super::device::ligature_letters; use super::{PageText, fold_case}; use std::ops::Range; @@ -25,31 +26,6 @@ enum Hyphen { Kept, } -/// The letters of a Latin compatibility ligature (U+FB00–U+FB06), their compatibility decomposition. -fn ligature(c: char) -> Option<&'static str> { - match c { - '\u{FB00}' => Some("ff"), - '\u{FB01}' => Some("fi"), - '\u{FB02}' => Some("fl"), - '\u{FB03}' => Some("ffi"), - '\u{FB04}' => Some("ffl"), - '\u{FB05}' | '\u{FB06}' => Some("st"), - _ => None, - } -} - -/// `s` with each Latin compatibility ligature written as its letters. Nothing else is normalised. -fn letters(s: &str) -> String { - let mut out = String::with_capacity(s.len()); - for c in s.chars() { - match ligature(c) { - Some(l) => out.push_str(l), - None => out.push(c), - } - } - out -} - /// A visible hyphen that can divide a word at a line end: HYPHEN-MINUS and HYPHEN. A SOFT HYPHEN /// (ISO 32000-2 §14.8.2.3) is invisible instead: find skips it, and a line that ends in one runs on. fn is_hyphen(c: char) -> bool { @@ -65,7 +41,7 @@ pub(super) fn find(page: &PageText, query: &str, sensitive: bool, whole_words: b if limit == 0 { return Vec::new(); } - let fold = |s: &str| if sensitive { letters(s) } else { fold_case(&letters(s)) }; + let fold = |s: &str| if sensitive { ligature_letters(s.to_owned()) } else { fold_case(&ligature_letters(s.to_owned())) }; let query: String = fold(query).chars().filter(|&c| !is_invisible(c)).collect(); let needle: Vec = query.split_whitespace().collect::>().join(" ").chars().collect(); if needle.is_empty() { @@ -378,14 +354,3 @@ fn unspaced_script(c: char) -> bool { | 0x20000..=0x3FFFF ) } - -#[cfg(test)] -mod tests { - use super::letters; - - #[test] - fn ligatures_read_as_their_letters() { - assert_eq!(letters("o\u{FB03}ce \u{FB00}\u{FB01}\u{FB02}\u{FB04}\u{FB05}\u{FB06}"), "office fffiflfflstst"); - assert_eq!(letters("\u{FB13}é\u{FF21}\u{2460}"), "\u{FB13}é\u{FF21}\u{2460}", "nothing else is normalised"); - } -}