math_text_transform/
lib.rs

1//! Transform text from standard alphanumerical characters to itโ€™s
2//! unicode equivalents of a certain variant in the [mathematical
3//! alphanumeric symbols block][1] (code block U+1D400โ€“U+1D7FF).
4//!
5//! ```rust
6//! use math_text_transform::math_italic;
7//! use math_text_transform::MathTextTransform;
8//!
9//! assert_eq!(math_italic('f'), Some('๐‘“'));
10//! assert_eq!("Bold".to_math_bold(), "๐๐จ๐ฅ๐");
11//! ```
12//!
13//! Supported variants are:
14//!
15//! * ๐›๐จ๐ฅ๐ (bold)
16//! * ๐‘–๐‘ก๐‘Ž๐‘™๐‘–๐‘ (italic)
17//! * ๐’ƒ๐’๐’๐’… ๐’Š๐’•๐’‚๐’๐’Š๐’„ (bold italic)
18//! * ๐—Œ๐–บ๐—‡๐—Œ-๐—Œ๐–พ๐—‹๐—‚๐–ฟ (sans-serif)
19//! * ๐˜€๐—ฎ๐—ป๐˜€-๐˜€๐—ฒ๐—ฟ๐—ถ๐—ณ ๐—ฏ๐—ผ๐—น๐—ฑ (sans-serif bold)
20//! * ๐˜ด๐˜ข๐˜ฏ๐˜ด-๐˜ด๐˜ฆ๐˜ณ๐˜ช๐˜ง ๐˜ช๐˜ต๐˜ข๐˜ญ๐˜ช๐˜ค (sans-serif italic)
21//! * ๐™จ๐™–๐™ฃ๐™จ-๐™จ๐™š๐™ง๐™ž๐™› ๐™—๐™ค๐™ก๐™™ ๐™ž๐™ฉ๐™–๐™ก๐™ž๐™˜ (sans-serif bold italic)
22//! * ๐“ˆ๐’ธ๐“‡๐’พ๐“…๐“‰ (script)
23//! * ๐“ซ๐“ธ๐“ต๐“ญ ๐“ผ๐“ฌ๐“ป๐“ฒ๐“น๐“ฝ (bold script)
24//! * ๐”ฃ๐”ฏ๐”ž๐”จ๐”ฑ๐”ฒ๐”ฏ (fraktur)
25//! * ๐–‡๐–”๐–‘๐–‰ ๐–‹๐–—๐–†๐–๐–™๐–š๐–— (bold fraktur)
26//! * ๐š–๐š˜๐š—๐š˜๐šœ๐š™๐šŠ๐šŒ๐šŽ (monospace)
27//! * ๐••๐• ๐•ฆ๐•“๐•๐•–-๐•ค๐•ฅ๐•ฃ๐•ฆ๐•”๐•œ (double-struck)
28//!
29//! ### References
30//!
31//! * https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols
32//!
33//! [1]: https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols
34
35mod variants;
36pub use variants::*;
37
38macro_rules! to_math_variant {
39    ($to_math_variant:ident, $math_variant:expr) => {
40        fn $to_math_variant(&self) -> String {
41            self.chars()
42                .map(|ch|
43                     if let Some(variant) = $math_variant(ch) { variant }
44                     else { ch })
45                .collect()
46        }
47    }
48}
49
50/// Convenience trait that allows you to call the the transformation
51/// straight on a string slice. If a variant doesn't exist for a given
52/// character, it is left as is.
53///
54/// ### Examples
55///
56/// ```rust
57/// use math_text_transform::MathTextTransform;
58///
59/// assert_eq!("Italฤฑc f(ฯ€)".to_math_italic(), "๐ผ๐‘ก๐‘Ž๐‘™๐šค๐‘ ๐‘“(๐œ‹)");
60/// assert_eq!("Double-struck 123".to_math_double_struck(), "๐”ป๐• ๐•ฆ๐•“๐•๐•–-๐•ค๐•ฅ๐•ฃ๐•ฆ๐•”๐•œ ๐Ÿ™๐Ÿš๐Ÿ›");
61/// ```
62pub trait MathTextTransform<T> {
63    /// Transform to ๐›๐จ๐ฅ๐ variant.
64    fn to_math_bold(&self) -> T;
65
66    /// Transform to ๐‘–๐‘ก๐‘Ž๐‘™๐‘–๐‘ variant.
67    fn to_math_italic(&self) -> T;
68
69    /// Transform to ๐’ƒ๐’๐’๐’… ๐’Š๐’•๐’‚๐’๐’Š๐’„ variant.
70    fn to_math_bold_italic(&self) -> T;
71
72    /// Transform to ๐—Œ๐–บ๐—‡๐—Œ-๐—Œ๐–พ๐—‹๐—‚๐–ฟ variant.
73    fn to_math_sans_serif(&self) -> T;
74
75    /// Transform to ๐˜€๐—ฎ๐—ป๐˜€-๐˜€๐—ฒ๐—ฟ๐—ถ๐—ณ ๐—ฏ๐—ผ๐—น๐—ฑ variant.
76    fn to_math_sans_serif_bold(&self) -> T;
77
78    /// Transform to ๐˜ด๐˜ข๐˜ฏ๐˜ด-๐˜ด๐˜ฆ๐˜ณ๐˜ช๐˜ง ๐˜ช๐˜ต๐˜ข๐˜ญ๐˜ช๐˜ค variant.
79    fn to_math_sans_serif_italic(&self) -> T;
80
81    /// Transform to ๐™จ๐™–๐™ฃ๐™จ-๐™จ๐™š๐™ง๐™ž๐™› ๐™—๐™ค๐™ก๐™™ ๐™ž๐™ฉ๐™–๐™ก๐™ž๐™˜ variant.
82    fn to_math_sans_serif_bold_italic(&self) -> T;
83
84    /// Transform to ๐“ˆ๐’ธ๐“‡๐’พ๐“…๐“‰ variant.
85    fn to_math_script(&self) -> T;
86
87    /// Transform to ๐“ซ๐“ธ๐“ต๐“ญ ๐“ผ๐“ฌ๐“ป๐“ฒ๐“น๐“ฝ variant.
88    fn to_math_bold_script(&self) -> T;
89
90    /// Transform to ๐”ฃ๐”ฏ๐”ž๐”จ๐”ฑ๐”ฒ๐”ฏ variant.
91    fn to_math_fraktur(&self) -> T;
92
93    /// Transform to ๐–‡๐–”๐–‘๐–‰ ๐–‹๐–—๐–†๐–๐–™๐–š๐–— variant.
94    fn to_math_bold_fraktur(&self) -> T;
95
96    /// Transform to ๐š–๐š˜๐š—๐š˜๐šœ๐š™๐šŠ๐šŒ๐šŽ variant.
97    fn to_math_monospace(&self) -> T;
98
99    /// Transform to ๐••๐• ๐•ฆ๐•“๐•๐•–-๐•ค๐•ฅ๐•ฃ๐•ฆ๐•”๐•œ variant.
100    fn to_math_double_struck(&self) -> T;
101}
102
103impl MathTextTransform<String> for str {
104    to_math_variant!(to_math_bold, math_bold);
105    to_math_variant!(to_math_italic, math_italic);
106    to_math_variant!(to_math_bold_italic, math_bold_italic);
107    to_math_variant!(to_math_sans_serif, math_sans_serif);
108    to_math_variant!(to_math_sans_serif_bold, math_sans_serif_bold);
109    to_math_variant!(to_math_sans_serif_italic, math_sans_serif_italic);
110    to_math_variant!(to_math_sans_serif_bold_italic, math_sans_serif_bold_italic);
111    to_math_variant!(to_math_script, math_script);
112    to_math_variant!(to_math_bold_script, math_bold_script);
113    to_math_variant!(to_math_fraktur, math_fraktur);
114    to_math_variant!(to_math_bold_fraktur, math_bold_fraktur);
115    to_math_variant!(to_math_monospace, math_monospace);
116    to_math_variant!(to_math_double_struck, math_double_struck);
117}
118
119
120#[cfg(test)]
121mod tests {
122    use super::MathTextTransform;
123
124    #[test]
125    fn to_math_bold() {
126        assert_eq!("Bold 123".to_math_bold(), "๐๐จ๐ฅ๐ ๐Ÿ๐Ÿ๐Ÿ‘");
127        assert_eq!("ฮ’ฮฟฮปฮด".to_math_bold(), "๐šฉ๐›๐›Œ๐›…");
128    }
129
130    #[test]
131    fn to_math_italic() {
132        assert_eq!("Italฤฑc 123".to_math_italic(), "๐ผ๐‘ก๐‘Ž๐‘™๐šค๐‘ 123");
133        assert_eq!("ฮ™ฯ„ฮฑฮปฮนฮบ".to_math_italic(), "๐›ช๐œ๐›ผ๐œ†๐œ„๐œ…");
134    }
135
136    #[test]
137    fn to_math_bold_italic() {
138        assert_eq!("Bold-Italic 123".to_math_bold_italic(), "๐‘ฉ๐’๐’๐’…-๐‘ฐ๐’•๐’‚๐’๐’Š๐’„ 123");
139        assert_eq!("ฮ’ฮฟฮปฮด-ฮ™ฯ„ฮฑฮปฮนฮบ".to_math_bold_italic(), "๐œ๐„๐€๐œน-๐œค๐‰๐œถ๐€๐œพ๐œฟ");
140    }
141
142    #[test]
143    fn to_math_sans_serif() {
144        assert_eq!("Sans-Serif 123".to_math_sans_serif(), "๐–ฒ๐–บ๐—‡๐—Œ-๐–ฒ๐–พ๐—‹๐—‚๐–ฟ ๐Ÿ๐Ÿ๐Ÿ‘");
145    }
146
147    #[test]
148    fn to_math_sans_serif_bold() {
149        assert_eq!("Sans-Serif-Bold 123".to_math_sans_serif_bold(), "๐—ฆ๐—ฎ๐—ป๐˜€-๐—ฆ๐—ฒ๐—ฟ๐—ถ๐—ณ-๐—•๐—ผ๐—น๐—ฑ ๐Ÿญ๐Ÿฎ๐Ÿฏ");
150        assert_eq!("ฮฃฮฑฮฝฯƒ-ฮฃฮตฯฮนฯ†-ฮ’ฮฟฮปฮด".to_math_sans_serif_bold(), "๐จ๐ฐ๐ผ๐ž‚-๐จ๐ด๐ž€๐ธ๐ž…-๐—๐พ๐บ๐ณ");
151    }
152
153    #[test]
154    fn to_math_sans_serif_italic() {
155        assert_eq!("Sans-Serif-Italic 123".to_math_sans_serif_italic(), "๐˜š๐˜ข๐˜ฏ๐˜ด-๐˜š๐˜ฆ๐˜ณ๐˜ช๐˜ง-๐˜๐˜ต๐˜ข๐˜ญ๐˜ช๐˜ค 123");
156    }
157
158    #[test]
159    fn to_math_sans_serif_bold_italic() {
160        assert_eq!("Sans-Serif-Bold-Italic 123".to_math_sans_serif_bold_italic(), "๐™Ž๐™–๐™ฃ๐™จ-๐™Ž๐™š๐™ง๐™ž๐™›-๐˜ฝ๐™ค๐™ก๐™™-๐™„๐™ฉ๐™–๐™ก๐™ž๐™˜ 123");
161        assert_eq!("ฮฃฮฑฮฝฯƒ-ฮฃฮตฯฮนฯ†-ฮ’ฮฟฮปฮด-ฮ™ฯ„ฮฑฮปฮนฮบ".to_math_sans_serif_bold_italic(), "๐žข๐žช๐žถ๐žผ-๐žข๐žฎ๐žบ๐žฒ๐žฟ-๐ž‘๐žธ๐žด๐žญ-๐ž˜๐žฝ๐žช๐žด๐žฒ๐žณ");
162    }
163
164    #[test]
165    fn to_math_script() {
166        assert_eq!("Script 123".to_math_script(), "๐’ฎ๐’ธ๐“‡๐’พ๐“…๐“‰ 123");
167    }
168
169    #[test]
170    fn to_math_bold_script() {
171        assert_eq!("Bold-Script 123".to_math_bold_script(), "๐“‘๐“ธ๐“ต๐“ญ-๐“ข๐“ฌ๐“ป๐“ฒ๐“น๐“ฝ 123");
172    }
173
174    #[test]
175    fn to_math_fraktur() {
176        assert_eq!("Fraktur 123".to_math_fraktur(), "๐”‰๐”ฏ๐”ž๐”จ๐”ฑ๐”ฒ๐”ฏ 123");
177    }
178
179    #[test]
180    fn to_math_bold_fraktur() {
181        assert_eq!("Bold-Fraktur 123".to_math_bold_fraktur(), "๐•ญ๐–”๐–‘๐–‰-๐•ฑ๐–—๐–†๐–๐–™๐–š๐–— 123");
182    }
183
184    #[test]
185    fn to_math_monospace() {
186        assert_eq!("Monospace 123".to_math_monospace(), "๐™ผ๐š˜๐š—๐š˜๐šœ๐š™๐šŠ๐šŒ๐šŽ ๐Ÿท๐Ÿธ๐Ÿน");
187    }
188
189    #[test]
190    fn to_math_double_struck() {
191        assert_eq!("Double-Struck 123".to_math_double_struck(), "๐”ป๐• ๐•ฆ๐•“๐•๐•–-๐•Š๐•ฅ๐•ฃ๐•ฆ๐•”๐•œ ๐Ÿ™๐Ÿš๐Ÿ›");
192    }
193}