diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..8a21474 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,91 @@ +name: CI +on: + push: + branches: + - master + pull_request: + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@master + + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - name: version info + run: rustc --version; cargo --version; + + - name: Run all tests + run: cargo test + + fmt: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@master + + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + clippy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@master + + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - uses: actions-rs/cargo@v1 + with: + command: clippy + args: -- -D warnings + + + sass-spec: + continue-on-error: true + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@master + + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - name: version info + run: rustc --version; cargo --version; + + - name: Build binary + run: cargo b --release + + - name: Get sass-spec + run: git submodule init && git submodule update + + - name: Install whatever Ruby needs + run: | + sudo apt-get install libncurses5-dev libncursesw5-dev + sudo gem install bundler + cd sass-spec && bundler install + + - name: Run Sass spec + run: ./sass-spec/sass-spec.rb -c './target/release/grass' diff --git a/.gitignore b/.gitignore index c08fa70..2089ed5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ Cargo.lock coverage pkg +.idea/ +!input.scss \ No newline at end of file diff --git a/input.scss b/input.scss new file mode 100644 index 0000000..80afe79 --- /dev/null +++ b/input.scss @@ -0,0 +1,3 @@ +body { + background: red; +} \ No newline at end of file diff --git a/src/args.rs b/src/args.rs index 0ae0583..7cf5e38 100644 --- a/src/args.rs +++ b/src/args.rs @@ -5,7 +5,6 @@ use codemap::{Span, Spanned}; use peekmore::PeekMoreIterator; -use crate::Cow; use crate::common::Identifier; use crate::error::SassResult; use crate::scope::Scope; @@ -15,6 +14,7 @@ use crate::utils::{ read_until_closing_paren, read_until_closing_quote, read_until_closing_square_brace, }; use crate::value::Value; +use crate::Cow; use crate::Token; #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/src/atrule/media.rs b/src/atrule/media.rs index 70dd2d1..99e3f10 100644 --- a/src/atrule/media.rs +++ b/src/atrule/media.rs @@ -64,9 +64,7 @@ impl Media { } } - if super_selector.is_empty() { - body.append(&mut rules); - } else { + if !super_selector.is_empty() { body = vec![Spanned { node: Stmt::RuleSet(RuleSet { selector: super_selector.clone(), @@ -75,8 +73,8 @@ impl Media { }), span: kind_span, }]; - body.append(&mut rules); } + body.append(&mut rules); Ok(Media { super_selector: Selector::new(), diff --git a/src/utils/strings.rs b/src/utils/strings.rs index 4573941..9eda2e5 100644 --- a/src/utils/strings.rs +++ b/src/utils/strings.rs @@ -1,5 +1,5 @@ -use std::iter::Iterator; use std::borrow::Borrow; +use std::iter::Iterator; use codemap::{Span, Spanned}; diff --git a/src/value/ops.rs b/src/value/ops.rs index 5d63d97..0c0e0c8 100644 --- a/src/value/ops.rs +++ b/src/value/ops.rs @@ -324,7 +324,9 @@ impl Value { format!("{}{}", self.to_css_string(span)?, s), QuoteKind::Quoted, ), - Self::Null => Value::String(self.to_css_string(span)?.into_owned(), QuoteKind::None), + Self::Null => { + Value::String(self.to_css_string(span)?.into_owned(), QuoteKind::None) + } _ => Value::String( format!( "{}{}", diff --git a/src/value/parse.rs b/src/value/parse.rs index 7c49e53..5e818fe 100644 --- a/src/value/parse.rs +++ b/src/value/parse.rs @@ -431,6 +431,12 @@ fn single_value>( }) } +fn parse_i64(s: String) -> i64 { + s.as_bytes() + .iter() + .fold(0, |total, this| total * 10 + i64::from(this - b'0')) +} + impl Value { pub fn from_tokens>( toks: &mut PeekMoreIterator, @@ -735,7 +741,7 @@ impl Value { let n = if val.dec_len == 0 { if val.num.len() <= 18 && val.times_ten.is_empty() { - let n = Rational64::new_raw(val.num.parse::().unwrap(), 1); + let n = Rational64::new_raw(parse_i64(val.num), 1); return Some(Ok(IntermediateValue::Value(Value::Dimension( Number::new_machine(n), unit, @@ -745,8 +751,7 @@ impl Value { BigRational::new_raw(val.num.parse::().unwrap(), BigInt::one()) } else { if val.num.len() <= 18 && val.times_ten.is_empty() { - let n = - Rational64::new(val.num.parse::().unwrap(), pow(10, val.dec_len)); + let n = Rational64::new(parse_i64(val.num), pow(10, val.dec_len)); return Some(Ok(IntermediateValue::Value(Value::Dimension( Number::new_machine(n), unit,