1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use crate::json::{ |
4 | json_minifier::{keep_element, JsonMinifier}, |
5 | read::json_read::JsonRead, |
6 | string::JsonMultiFilter, |
7 | }; |
8 | use std::fmt; |
9 | use std::io::{self, Read}; |
10 | |
11 | mod read { |
12 | mod byte_to_char; |
13 | mod internal_buffer; |
14 | mod internal_reader; |
15 | pub mod json_read; |
16 | } |
17 | |
18 | mod json_minifier; |
19 | mod string; |
20 | |
21 | type JsonMethod = fn(&mut JsonMinifier, &char, Option<&char>) -> bool; |
22 | |
23 | /// Minifies a given String by JSON minification rules |
24 | /// |
25 | /// # Example |
26 | /// |
27 | /// ```rust |
28 | /// use minifier::json::minify; |
29 | /// |
30 | /// let json = r#" |
31 | /// { |
32 | /// "test": "test", |
33 | /// "test2": 2 |
34 | /// } |
35 | /// "# .into(); |
36 | /// let json_minified = minify(json); |
37 | /// assert_eq!(&json_minified.to_string(), r#"{"test":"test","test2":2}"# ); |
38 | /// ``` |
39 | #[inline ] |
40 | pub fn minify(json: &str) -> Minified<'_> { |
41 | Minified(JsonMultiFilter::new(iter:json.chars(), predicate:keep_element)) |
42 | } |
43 | |
44 | #[derive (Debug)] |
45 | pub struct Minified<'a>(JsonMultiFilter<'a, JsonMethod>); |
46 | |
47 | impl<'a> Minified<'a> { |
48 | pub fn write<W: io::Write>(self, w: W) -> io::Result<()> { |
49 | self.0.write(w) |
50 | } |
51 | } |
52 | |
53 | impl<'a> fmt::Display for Minified<'a> { |
54 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
55 | self.0.fmt(f) |
56 | } |
57 | } |
58 | |
59 | /// Minifies a given Read by JSON minification rules |
60 | /// |
61 | /// # Example |
62 | /// |
63 | /// ```rust |
64 | /// extern crate minifier; |
65 | /// use std::fs::File; |
66 | /// use std::io::Read; |
67 | /// use minifier::json::minify_from_read; |
68 | /// |
69 | /// fn main() { |
70 | /// let mut html_minified = String::new(); |
71 | /// let mut file = File::open("tests/files/test.json" ).expect("file not found" ); |
72 | /// minify_from_read(file).read_to_string(&mut html_minified); |
73 | /// } |
74 | /// ``` |
75 | #[inline ] |
76 | pub fn minify_from_read<R: Read>(json: R) -> JsonRead<JsonMethod, R> { |
77 | JsonRead::new(read:json, predicate:keep_element) |
78 | } |
79 | |
80 | #[test ] |
81 | fn removal_from_read() { |
82 | use std::fs::File; |
83 | |
84 | let input: File = File::open("tests/files/test.json" ).expect(msg:"file not found" ); |
85 | let expected: String = "{ \"test \": \"\\\" test2 \", \"test2 \": \"\", \"test3 \": \" \"}" .into(); |
86 | let mut actual: String = String::new(); |
87 | minify_from_read(input) |
88 | .read_to_string(&mut actual) |
89 | .expect(msg:"error at read" ); |
90 | assert_eq!(actual, expected); |
91 | } |
92 | |
93 | #[test ] |
94 | fn removal_of_control_characters() { |
95 | let input: &str = " \n" .into(); |
96 | let expected: String = "" .into(); |
97 | let actual: Minified<'_> = minify(json:input); |
98 | assert_eq!(actual.to_string(), expected); |
99 | } |
100 | |
101 | #[test ] |
102 | fn removal_of_whitespace_outside_of_tags() { |
103 | let input: &str = r#" &str |
104 | { &str |
105 | "test": "\" test2", &str |
106 | "test2": "", &str |
107 | "test3": " " &str |
108 | } &str |
109 | "# &str |
110 | .into(); |
111 | let expected: String = "{ \"test \": \"\\\" test2 \", \"test2 \": \"\", \"test3 \": \" \"}" .into(); |
112 | let actual: Minified<'_> = minify(json:input); |
113 | assert_eq!(actual.to_string(), expected); |
114 | } |
115 | |