Skip to main content

sofie_values/
slug_character.rs

1use std::ops::RangeInclusive;
2
3use unicode_normalization::char::is_combining_mark;
4
5/// Decomposed accents, which a slug drops as it spells Latin letters in ASCII.
6pub const LATIN_COMBINING_ACCENTS: RangeInclusive<char> = '\u{300}'..='\u{36f}';
7
8/// A letter, digit or nonspacing or spacing mark (L*, N*, Mn, Mc) that lowercasing leaves as it
9/// is; anything else parts a slug's words, unassigned, private-use and format characters too.
10#[must_use]
11pub fn is_slug_character(character: char) -> bool {
12    character.to_lowercase().eq([character])
13        && (character.is_alphanumeric() || is_word_mark(character))
14        && !LATIN_COMBINING_ACCENTS.contains(&character)
15        && !sofie_core::misleads_display(character)
16}
17
18/// The enclosing marks (Me) draw a circle or a sign around what comes before them.
19fn is_word_mark(character: char) -> bool {
20    is_combining_mark(character)
21        && !matches!(
22            character,
23            '\u{488}'..='\u{489}'
24                | '\u{1abe}'
25                | '\u{20dd}'..='\u{20e0}'
26                | '\u{20e2}'..='\u{20e4}'
27                | '\u{a670}'..='\u{a672}'
28        )
29}