1 | use std::fmt; |
2 | |
3 | use crate::{lowercase, transform}; |
4 | |
5 | /// This trait defines a kebab case conversion. |
6 | /// |
7 | /// In kebab-case, word boundaries are indicated by hyphens. |
8 | /// |
9 | /// ## Example: |
10 | /// |
11 | /// ```rust |
12 | /// use heck::ToKebabCase; |
13 | /// |
14 | /// let sentence = "We are going to inherit the earth." ; |
15 | /// assert_eq!(sentence.to_kebab_case(), "we-are-going-to-inherit-the-earth" ); |
16 | /// ``` |
17 | pub trait ToKebabCase: ToOwned { |
18 | /// Convert this type to kebab case. |
19 | fn to_kebab_case(&self) -> Self::Owned; |
20 | } |
21 | |
22 | impl ToKebabCase for str { |
23 | fn to_kebab_case(&self) -> Self::Owned { |
24 | AsKebabCase(self).to_string() |
25 | } |
26 | } |
27 | |
28 | /// This wrapper performs a kebab case conversion in [`fmt::Display`]. |
29 | /// |
30 | /// ## Example: |
31 | /// |
32 | /// ``` |
33 | /// use heck::AsKebabCase; |
34 | /// |
35 | /// let sentence = "We are going to inherit the earth." ; |
36 | /// assert_eq!(format!("{}" , AsKebabCase(sentence)), "we-are-going-to-inherit-the-earth" ); |
37 | /// ``` |
38 | pub struct AsKebabCase<T: AsRef<str>>(pub T); |
39 | |
40 | impl<T: AsRef<str>> fmt::Display for AsKebabCase<T> { |
41 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
42 | transform(self.0.as_ref(), with_word:lowercase, |f: &mut Formatter<'_>| write!(f, "-" ), f) |
43 | } |
44 | } |
45 | |
46 | #[cfg (test)] |
47 | mod tests { |
48 | use super::ToKebabCase; |
49 | |
50 | macro_rules! t { |
51 | ($t:ident : $s1:expr => $s2:expr) => { |
52 | #[test] |
53 | fn $t() { |
54 | assert_eq!($s1.to_kebab_case(), $s2) |
55 | } |
56 | }; |
57 | } |
58 | |
59 | t!(test1: "CamelCase" => "camel-case" ); |
60 | t!(test2: "This is Human case." => "this-is-human-case" ); |
61 | t!(test3: "MixedUP CamelCase, with some Spaces" => "mixed-up-camel-case-with-some-spaces" ); |
62 | t!(test4: "mixed_up_ snake_case with some _spaces" => "mixed-up-snake-case-with-some-spaces" ); |
63 | t!(test5: "kebab-case" => "kebab-case" ); |
64 | t!(test6: "SHOUTY_SNAKE_CASE" => "shouty-snake-case" ); |
65 | t!(test7: "snake_case" => "snake-case" ); |
66 | t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "this-contains-all-kinds-of-word-boundaries" ); |
67 | #[cfg (feature = "unicode" )] |
68 | t!(test9: "XΣXΣ baffle" => "xσxς-baffle" ); |
69 | t!(test10: "XMLHttpRequest" => "xml-http-request" ); |
70 | } |
71 | |