diff --git a/whiskers/README.md b/whiskers/README.md index 0221bae..afa55c5 100644 --- a/whiskers/README.md +++ b/whiskers/README.md @@ -178,8 +178,12 @@ These types are designed to closely match the [palette.json](https://github.com/ | `sub` | Subtract a value from a color | `red \| sub(hue=30)` => `#d30f9b` | | `mod` | Modify a color | `red \| mod(lightness=80)` => `#f8a0b3` | | `mix` | Mix two colors together | `red \| mix(color=base, amount=0.5)` => `#e08097` | -| `urlencode_lzma` | Serialize an object into a URL-safe string with LZMA compression | `red \| urlencode_lzma()` => `#ff6666` | +| `urlencode_lzma` | Serialize an object into a URL-safe string with LZMA compression | `red \| urlencode_lzma` => `#ff6666` | | `trunc` | Truncate a number to a certain number of places | `1.123456 \| trunc(places=3)` => `1.123` | +| `css_rgb` | Convert a color to an RGB CSS string | `red \| css_rgb` => `rgb(210, 15, 57)` | +| `css_rgba` | Convert a color to an RGBA CSS string | `red \| css_rgba` => `rgba(210, 15, 57, 1.00)` | +| `css_hsl` | Convert a color to an HSL CSS string | `red \| css_hsl` => `hsl(347, 87%, 44%)` | +| `css_hsla` | Convert a color to an HSLA CSS string | `red \| css_hsla` => `hsla(347, 87%, 44%, 1.00)` | > [!NOTE] > You also have access to all of Tera's own built-in filters and functions. diff --git a/whiskers/src/filters.rs b/whiskers/src/filters.rs index 4dc8ba2..025220f 100644 --- a/whiskers/src/filters.rs +++ b/whiskers/src/filters.rs @@ -132,3 +132,39 @@ pub fn trunc( )?; Ok(tera::to_value(format!("{value:.places$}"))?) } + +pub fn css_rgb( + value: &tera::Value, + _args: &HashMap, +) -> Result { + let color: Color = tera::from_value(value.clone())?; + let color: css_colors::RGB = (&color).into(); + Ok(tera::to_value(color.to_string())?) +} + +pub fn css_rgba( + value: &tera::Value, + _args: &HashMap, +) -> Result { + let color: Color = tera::from_value(value.clone())?; + let color: css_colors::RGBA = (&color).into(); + Ok(tera::to_value(color.to_string())?) +} + +pub fn css_hsl( + value: &tera::Value, + _args: &HashMap, +) -> Result { + let color: Color = tera::from_value(value.clone())?; + let color: css_colors::HSL = (&color).into(); + Ok(tera::to_value(color.to_string())?) +} + +pub fn css_hsla( + value: &tera::Value, + _args: &HashMap, +) -> Result { + let color: Color = tera::from_value(value.clone())?; + let color: css_colors::HSLA = (&color).into(); + Ok(tera::to_value(color.to_string())?) +} diff --git a/whiskers/src/markdown.rs b/whiskers/src/markdown.rs index 853d9f7..eed5935 100644 --- a/whiskers/src/markdown.rs +++ b/whiskers/src/markdown.rs @@ -104,7 +104,7 @@ fn table_format() -> String { )); } - result.push_str("### Filters\n\n"); + result.push_str("\n### Filters\n\n"); result.push_str("| Name | Description | Examples |\n"); result.push_str("|------|-------------|----------|\n"); for filter in templating::all_filters() { @@ -116,17 +116,26 @@ fn table_format() -> String { "None".to_string() } else { filter.examples.first().map_or_else(String::new, |example| { - format!( - "`{value} \\| {name}({input})` => `{output}`", - value = example.value, - name = filter.name, - input = example - .inputs - .iter() - .map(|(k, v)| format!("{k}={v}")) - .join(", "), - output = example.output - ) + if example.inputs.is_empty() { + format!( + "`{value} \\| {name}` => `{output}`", + value = example.value, + name = filter.name, + output = example.output + ) + } else { + format!( + "`{value} \\| {name}({input})` => `{output}`", + value = example.value, + name = filter.name, + input = example + .inputs + .iter() + .map(|(k, v)| format!("{k}={v}")) + .join(", "), + output = example.output + ) + } }) } )); diff --git a/whiskers/src/templating.rs b/whiskers/src/templating.rs index 418bafa..6e1df6a 100644 --- a/whiskers/src/templating.rs +++ b/whiskers/src/templating.rs @@ -50,6 +50,10 @@ pub fn make_engine() -> tera::Tera { tera.register_filter("urlencode_lzma", filters::urlencode_lzma); tera.register_filter("trunc", filters::trunc); tera.register_filter("mix", filters::mix); + tera.register_filter("css_rgb", filters::css_rgb); + tera.register_filter("css_rgba", filters::css_rgba); + tera.register_filter("css_hsl", filters::css_hsl); + tera.register_filter("css_hsla", filters::css_hsla); tera.register_function("if", functions::if_fn); tera.register_function("object", functions::object); tera.register_function("css_rgb", functions::css_rgb); @@ -148,6 +152,26 @@ pub fn all_filters() -> Vec { description: "Truncate a number to a certain number of places".to_string(), examples: vec![filter_example!(1.123456 | trunc(places=3) => "1.123")], }, + Filter { + name: "css_rgb".to_string(), + description: "Convert a color to an RGB CSS string".to_string(), + examples: vec![filter_example!(red | css_rgb => "rgb(210, 15, 57)")], + }, + Filter { + name: "css_rgba".to_string(), + description: "Convert a color to an RGBA CSS string".to_string(), + examples: vec![filter_example!(red | css_rgba => "rgba(210, 15, 57, 1.00)")], + }, + Filter { + name: "css_hsl".to_string(), + description: "Convert a color to an HSL CSS string".to_string(), + examples: vec![filter_example!(red | css_hsl => "hsl(347, 87%, 44%)")], + }, + Filter { + name: "css_hsla".to_string(), + description: "Convert a color to an HSLA CSS string".to_string(), + examples: vec![filter_example!(red | css_hsla => "hsla(347, 87%, 44%, 1.00)")], + }, ] }