commit a72dc06a541ecb087811abe251c975704d9504bd
Author: kirbylife <kirbylife@protonmail.com>
Date:   Wed Aug 30 00:34:26 2023 -0600

    Initial commit

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..869df07
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/target
+Cargo.lock
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..4a97761
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "tera_thousands"
+version = "0.1.0"
+authors = ["kirbylife <hola@kirbylife.dev>"]
+license = "MIT"
+readme = "README.md"
+homepage = "https://git.kirbylife.dev/kirbylife/tera_thousands"
+repository = "https://git.kirbylife.dev/kirbylife/tera_thousands"
+documentation = "https://docs.rs/tera_thousands"
+description = "Simple filter for tera to split the numbers by thousands"
+keywords = ["tera", "template", "formatting", "separators", "numbers"]
+categories = ["template-engine"]
+edition = "2021"
+
+[dependencies]
+thousands = "0.2.0"
+tera = { version = "1.19.0", default-features = false }
\ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..3c63e44
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,19 @@
+Copyright (c) 2023 Kirbylife <hola@kirbylife.dev>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..caa66ea
--- /dev/null
+++ b/README.md
@@ -0,0 +1,59 @@
+# tera_thousands
+
+## Simple filter for tera to split the numbers by thousands
+
+### dependencies:
+- [tera](https://crates.io/crates/tera)
+- [thousands](https://crates.io/crates/thousands)
+
+### Usage
+The usage is simple:
+
+First add this crate to the `Cargo.toml` file:
+```Toml
+tera_thousands = "0.1.0"
+```
+
+Now add the filter to your Tera instance:
+```Rust
+let mut tera = Tera::default();
+tera.register_filter("separate_with_commas", tera_thousands::separate_with_commas);
+```
+
+You can now divide the numbers in your tera template with commas:
+```Rust
+let mut context = Context::new();
+context.insert("number", &123456);
+
+let output = tera
+    .render_str("{{ number | separate_with_commas }}", &context)
+    .expect("Expected a number");
+assert_eq!(output, "123,456");
+```
+
+Also, you can use it with Rocket or any framework compatible with Tera.
+For example, this is how it would be used with Rocket:
+```
+use rocket_dyn_templates::Template;
+use tera_thousands::separate_with_commas;
+
+#[launch]
+fn rocket() -> _ {
+    rocket::build()
+        .attach(Template::custom(|engines| {
+            engines.tera.register_filter("separate_with_commas", separate_with_commas)
+        }))
+        .mount(...)
+}
+```
+
+The possible options are:
+- `separate_with_commas`
+- `separate_with_dots`
+- `separate_with_spaces`
+- `separate_with_underscores`
+
+### TO-DO
+- [ ] An addition customizable filter from the template
+
+Contributors are welcome :).
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..41afc98
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,174 @@
+use std::{collections::HashMap, hash::BuildHasher};
+use tera::{to_value, Error, Value};
+use thousands::Separable;
+
+pub fn separate_with_commas<S: BuildHasher>(
+    value: &Value,
+    _: &HashMap<String, Value, S>,
+) -> tera::Result<Value> {
+    if value.is_f64() {
+        Ok(to_value(value.as_f64().unwrap().separate_with_commas()).unwrap())
+    } else if value.is_i64() {
+        Ok(to_value(value.as_i64().unwrap().separate_with_commas()).unwrap())
+    } else if value.is_u64() {
+        Ok(to_value(value.as_u64().unwrap().separate_with_commas()).unwrap())
+    } else {
+        Err(Error::msg("Expected a number"))
+    }
+}
+
+pub fn separate_with_spaces<S: BuildHasher>(
+    value: &Value,
+    _: &HashMap<String, Value, S>,
+) -> tera::Result<Value> {
+    if value.is_f64() {
+        Ok(to_value(value.as_f64().unwrap().separate_with_spaces()).unwrap())
+    } else if value.is_i64() {
+        Ok(to_value(value.as_i64().unwrap().separate_with_spaces()).unwrap())
+    } else if value.is_u64() {
+        Ok(to_value(value.as_u64().unwrap().separate_with_spaces()).unwrap())
+    } else {
+        Err(Error::msg("Expected a number"))
+    }
+}
+
+pub fn separate_with_dots<S: BuildHasher>(
+    value: &Value,
+    _: &HashMap<String, Value, S>,
+) -> tera::Result<Value> {
+    if value.is_f64() {
+        Ok(to_value(value.as_f64().unwrap().separate_with_dots()).unwrap())
+    } else if value.is_i64() {
+        Ok(to_value(value.as_i64().unwrap().separate_with_dots()).unwrap())
+    } else if value.is_u64() {
+        Ok(to_value(value.as_u64().unwrap().separate_with_dots()).unwrap())
+    } else {
+        Err(Error::msg("Expected a number"))
+    }
+}
+
+pub fn separate_with_underscores<S: BuildHasher>(
+    value: &Value,
+    _: &HashMap<String, Value, S>,
+) -> tera::Result<Value> {
+    if value.is_f64() {
+        Ok(to_value(value.as_f64().unwrap().separate_with_underscores()).unwrap())
+    } else if value.is_i64() {
+        Ok(to_value(value.as_i64().unwrap().separate_with_underscores()).unwrap())
+    } else if value.is_u64() {
+        Ok(to_value(value.as_u64().unwrap().separate_with_underscores()).unwrap())
+    } else {
+        Err(Error::msg("Expected a number"))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{
+        separate_with_commas, separate_with_dots, separate_with_spaces, separate_with_underscores,
+    };
+    use tera::{Context, Tera};
+
+    #[test]
+    fn separate_with_commas_test() {
+        let mut context = Context::new();
+        context.insert("integer_number", &10000);
+        context.insert("negative_number", &-69420);
+        context.insert("float_number", &1234.567);
+
+        let mut tera = Tera::default();
+        tera.register_filter("separate_with_commas", separate_with_commas);
+
+        let s_int = tera
+            .render_str("{{ integer_number | separate_with_commas }}", &context)
+            .expect("Expected a number");
+        let s_neg = tera
+            .render_str("{{ negative_number | separate_with_commas }}", &context)
+            .expect("Expected a number");
+        let s_flt = tera
+            .render_str("{{ float_number | separate_with_commas }}", &context)
+            .expect("Expected a number");
+
+        assert_eq!(s_int, "10,000");
+        assert_eq!(s_neg, "-69,420");
+        assert_eq!(s_flt, "1,234.567");
+    }
+
+    #[test]
+    fn separate_with_dots_test() {
+        let mut context = Context::new();
+        context.insert("integer_number", &10000);
+        context.insert("negative_number", &-69420);
+        context.insert("float_number", &1234.567);
+
+        let mut tera = Tera::default();
+        tera.register_filter("separate_with_dots", separate_with_dots);
+
+        let s_int = tera
+            .render_str("{{ integer_number | separate_with_dots }}", &context)
+            .expect("Expected a number");
+        let s_neg = tera
+            .render_str("{{ negative_number | separate_with_dots }}", &context)
+            .expect("Expected a number");
+        let s_flt = tera
+            .render_str("{{ float_number | separate_with_dots }}", &context)
+            .expect("Expected a number");
+
+        assert_eq!(s_int, "10.000");
+        assert_eq!(s_neg, "-69.420");
+        assert_eq!(s_flt, "1.234.567");
+    }
+
+    #[test]
+    fn separate_with_spaces_test() {
+        let mut context = Context::new();
+        context.insert("integer_number", &10000);
+        context.insert("negative_number", &-69420);
+        context.insert("float_number", &1234.567);
+
+        let mut tera = Tera::default();
+        tera.register_filter("separate_with_spaces", separate_with_spaces);
+
+        let s_int = tera
+            .render_str("{{ integer_number | separate_with_spaces }}", &context)
+            .expect("Expected a number");
+        let s_neg = tera
+            .render_str("{{ negative_number | separate_with_spaces }}", &context)
+            .expect("Expected a number");
+        let s_flt = tera
+            .render_str("{{ float_number | separate_with_spaces }}", &context)
+            .expect("Expected a number");
+
+        assert_eq!(s_int, "10 000");
+        assert_eq!(s_neg, "-69 420");
+        assert_eq!(s_flt, "1 234.567");
+    }
+
+    #[test]
+    fn separate_with_underscores_test() {
+        let mut context = Context::new();
+        context.insert("integer_number", &10000);
+        context.insert("negative_number", &-69420);
+        context.insert("float_number", &1234.567);
+
+        let mut tera = Tera::default();
+        tera.register_filter("separate_with_underscores", separate_with_underscores);
+
+        let s_int = tera
+            .render_str("{{ integer_number | separate_with_underscores }}", &context)
+            .expect("Expected a number");
+        let s_neg = tera
+            .render_str(
+                "{{ negative_number | separate_with_underscores }}",
+                &context,
+            )
+            .expect("Expected a number");
+        let s_flt = tera
+            .render_str("{{ float_number | separate_with_underscores }}", &context)
+            .expect("Expected a number");
+
+        assert_eq!(s_int, "10_000");
+        assert_eq!(s_neg, "-69_420");
+        assert_eq!(s_flt, "1_234.567");
+    }
+}