1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::json::{
4 json_minifier::{keep_element, JsonMinifier},
5 read::json_read::JsonRead,
6 string::JsonMultiFilter,
7};
8use std::fmt;
9use std::io::{self, Read};
10
11mod read {
12 mod byte_to_char;
13 mod internal_buffer;
14 mod internal_reader;
15 pub mod json_read;
16}
17
18mod json_minifier;
19mod string;
20
21type 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]
40pub fn minify(json: &str) -> Minified<'_> {
41 Minified(JsonMultiFilter::new(iter:json.chars(), predicate:keep_element))
42}
43
44#[derive(Debug)]
45pub struct Minified<'a>(JsonMultiFilter<'a, JsonMethod>);
46
47impl<'a> Minified<'a> {
48 pub fn write<W: io::Write>(self, w: W) -> io::Result<()> {
49 self.0.write(w)
50 }
51}
52
53impl<'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]
76pub fn minify_from_read<R: Read>(json: R) -> JsonRead<JsonMethod, R> {
77 JsonRead::new(read:json, predicate:keep_element)
78}
79
80#[test]
81fn 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]
94fn 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]
102fn 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