mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-08 19:42:12 +00:00
CP6.13: craft-libs#487 review — a trailing combining mark stays on its word; Italian and Portuguese look a hyphenated word up whole before its parts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
This commit is contained in:
1 parent
be52680c9c
commit
64bd43db1d
3 files changed
+32
-3
No files matched your search
@@ -95,8 +95,9 @@ fn check(d: &AffixDict, word: &str, opts: &crate::Options) -> bool {
|
||||
if TRUNCATIONS.contains(&lower.as_str()) || left_to_grammar(&lower) {
|
||||
return true;
|
||||
}
|
||||
// The whole word first, as Hunspell does: a hyphenated entry or user word.
|
||||
if w.contains('-') {
|
||||
return w.split('-').all(|p| p.chars().count() <= 1 || known(d, p));
|
||||
return known(d, w) || w.split('-').all(|p| p.chars().count() <= 1 || known(d, p));
|
||||
}
|
||||
if let Some((head, tail)) = w.split_once(['\'', '’'])
|
||||
&& PROCLITICS.contains(&head.to_lowercase().as_str())
|
||||
@@ -139,6 +140,14 @@ mod tests {
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// craft-libs#487 review: a hyphenated dictionary entry is a word even when its parts aren't.
|
||||
#[test]
|
||||
fn a_hyphenated_entry_is_looked_up_whole() {
|
||||
let d = AffixDict::from_hunspell("SET UTF-8\n", "1\ntic-tac\n", &[]).unwrap();
|
||||
assert!(is_correct_with(&d, "tic-tac"));
|
||||
assert!(!is_correct_with(&d, "tic-tacc"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn without_a_dictionary_nothing_is_flagged() {
|
||||
let none = AffixDict::default();
|
||||
|
||||
@@ -71,8 +71,9 @@ fn check(d: &AffixDict, word: &str, opts: &crate::Options) -> bool {
|
||||
let Some(w) = crate::spelling::word_to_check(d, word, opts) else {
|
||||
return true;
|
||||
};
|
||||
// The whole word first, as Hunspell does: a hyphenated entry or user word.
|
||||
if w.contains('-') {
|
||||
return w.split('-').all(|p| p.chars().count() <= 1 || known(d, p));
|
||||
return known(d, w) || w.split('-').all(|p| p.chars().count() <= 1 || known(d, p));
|
||||
}
|
||||
known(d, w)
|
||||
}
|
||||
@@ -96,6 +97,14 @@ mod tests {
|
||||
assert!(!d.rep().is_empty() && !d.map().is_empty() && !d.try_chars().is_empty());
|
||||
}
|
||||
|
||||
/// craft-libs#487 review: a hyphenated dictionary entry is a word even when its parts aren't.
|
||||
#[test]
|
||||
fn a_hyphenated_entry_is_looked_up_whole() {
|
||||
let d = AffixDict::from_hunspell("SET UTF-8\n", "1\ntic-tac\n", &[]).unwrap();
|
||||
assert!(is_correct_with(&d, "tic-tac"));
|
||||
assert!(!is_correct_with(&d, "tic-tacc"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn without_a_dictionary_nothing_is_flagged() {
|
||||
let none = AffixDict::default();
|
||||
|
||||
@@ -24,7 +24,9 @@ pub(crate) fn word_to_check_in<'a>(d: &AffixDict, word: &'a str, opts: &Options)
|
||||
if d.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’');
|
||||
// A trailing combining mark with no precomposed form (`x\u{338}`) is part of the word.
|
||||
let edge = |c: char| !c.is_alphanumeric() && c != '\'' && c != '’';
|
||||
let w = word.trim_start_matches(edge).trim_end_matches(|c| edge(c) && !unicode_normalization::char::is_combining_mark(c));
|
||||
let w = w.trim_matches(['\'', '’']);
|
||||
let n = w.chars().count();
|
||||
if n <= 1 || (opts.ignore_numbers && w.chars().any(|c| c.is_ascii_digit())) || !w.chars().any(char::is_alphabetic) {
|
||||
@@ -56,4 +58,13 @@ mod tests {
|
||||
assert_eq!(word_to_check(&d, "B2B", &strict), Some("B2B"));
|
||||
assert_eq!(word_to_check(&d, "PRZEDSIĘBIORSTWO", &defaults), Some("PRZEDSIĘBIORSTWO"), "only short capitals are acronyms");
|
||||
}
|
||||
|
||||
/// craft-libs#487 review: a trailing combining mark stays on the word it marks.
|
||||
#[test]
|
||||
fn trailing_combining_marks_are_kept() {
|
||||
let d = AffixDict::from_hunspell("", "1\nkot\n", &[]).unwrap();
|
||||
let defaults = Options::default();
|
||||
assert_eq!(word_to_check(&d, "kox\u{338}", &defaults), Some("kox\u{338}"));
|
||||
assert_eq!(word_to_check(&d, "(kox\u{338}).", &defaults), Some("kox\u{338}"));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user