diff --git a/src/lib.rs b/src/lib.rs index 3649bdf..01a767e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,5 +105,6 @@ pub mod schema; pub use crate::query::parse_query; pub use crate::schema::parse_schema; +pub use crate::query::minify_query; pub use crate::position::Pos; pub use crate::format::Style; diff --git a/src/query/minify.rs b/src/query/minify.rs new file mode 100644 index 0000000..763056e --- /dev/null +++ b/src/query/minify.rs @@ -0,0 +1,84 @@ +use crate::tokenizer::{Kind, Token, TokenStream}; +use combine::StreamOnce; +use thiserror::Error; + +/// Error minifying query +#[derive(Error, Debug)] +#[error("query minify error: {}", _0)] +pub struct MinifyError(String); + +pub fn minify_query<'a>(source: String) -> Result { + let mut bits: Vec<&str> = Vec::new(); + let mut stream = TokenStream::new(source.as_str()); + let mut prev_was_punctuator = false; + + loop { + match stream.uncons() { + Ok(x) => { + let token: Token = x; + let is_non_punctuator = token.kind != Kind::Punctuator; + + if prev_was_punctuator { + if is_non_punctuator { + bits.push(" "); + } + } + + bits.push(token.value); + prev_was_punctuator = is_non_punctuator; + } + Err(ref e) if e == &combine::easy::Error::end_of_input() => break, + Err(e) => return Err(MinifyError(e.to_string())), + } + } + + Ok(bits.join("")) +} + +#[cfg(test)] +mod tests { + #[test] + fn strip_ignored_characters() { + let source = " + query SomeQuery($foo: String!, $bar: String) { + someField(foo: $foo, bar: $bar) { + a + b { + ... on B { + c + d + } + } + } + } + "; + + let minified = super::minify_query(source.to_string()).expect("minification failed"); + + assert_eq!( + &minified, + "query SomeQuery($foo:String!$bar:String){someField(foo:$foo bar:$bar){a b{...on B{c d}}}}" + ); + } + + #[test] + fn unexpected_token() { + let source = " + query foo { + bar; + } + "; + + let minified = super::minify_query(source.to_string()); + + assert_eq!( + minified.is_err(), + true + ); + + assert_eq!( + minified.unwrap_err().to_string(), + "query minify error: Unexpected `unexpected character ';'`" + ); + } +} diff --git a/src/query/mod.rs b/src/query/mod.rs index 1d21ac1..c5bbfb5 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -4,8 +4,9 @@ mod ast; mod error; mod format; mod grammar; - +mod minify; pub use self::grammar::{parse_query, consume_definition}; pub use self::error::ParseError; pub use self::ast::*; +pub use self::minify::minify_query;