diff --git a/.gitignore b/.gitignore index 58b9f2d..7631fb5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ # never commit compiled code -javascripts/compiled/* stylesheets/* -images/compass-sprites # Temporary Sass files .sass-cache/ @@ -9,4 +7,3 @@ images/compass-sprites # Compiled source for deployment dist/ tests/**/*input.css -scss/bourbon diff --git a/.scss-lint.yml b/.scss-lint.yml index 2ef3208..1621da3 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -2,7 +2,7 @@ exclude: - "scss/vendor/_reset.scss" - "scss/vendor/_normalize.scss" - - "scss/_tests/*" + - "tests/*" linters: Comment: @@ -13,3 +13,13 @@ linters: enabled: false StringQuotes: enabled: false + ImportantRule: + enabled: false + SelectorFormat: + enabled: false + ColorVariable: + enabled: false + QualifyingElement: + enabled: false + DeclarationOrder: + enabled: false diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a02b18c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: ruby +rvm: + - 2.2.3 +script: rake test diff --git a/CHANGELOG.md b/CHANGELOG.md index c9ce9f0..be956db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +### 2.0.0 (Oct 8, 2015) + +* Replace media-query() mixin with media() mixin. +* Remove support for IE6/7. +* Remove dependency on Compass. +* Move island, lists and media partials into UI folder. +* Update to Normalize.css 3.0.3. +* Documentation! + + ### 1.0.1 (Aug 11, 2015) * Add table helper classes. diff --git a/Gemfile b/Gemfile index 74d50b6..d9b1294 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,5 @@ source "https://rubygems.org" gem "rake" -gem "scss-lint", "0.25.1" +gem "scss_lint", "0.38.0", require: false +gem "sassunit" diff --git a/Gemfile.lock b/Gemfile.lock index 688b016..090070d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,19 +1,28 @@ GEM remote: https://rubygems.org/ specs: + commander (4.3.5) + highline (~> 1.7.2) + highline (1.7.7) + minitest (5.8.1) rainbow (2.0.0) rake (10.4.2) - sass (3.3.14) - scss-lint (0.25.1) + sass (3.4.18) + sassunit (1.0.0) + commander + minitest + sass + scss_lint (0.38.0) rainbow (~> 2.0) - sass (~> 3.3.0) + sass (~> 3.4.1) PLATFORMS ruby DEPENDENCIES rake - scss-lint (= 0.25.1) + sassunit + scss_lint (= 0.38.0) BUNDLED WITH - 1.10.5 + 1.10.6 diff --git a/README.md b/README.md index 1b349a7..74ba3f2 100644 --- a/README.md +++ b/README.md @@ -5,29 +5,45 @@ spaceBase Many CSS frameworks are meant to be included and left alone. But spaceBase is a boilerplate layer that can be built upon and tailored for your needs. It combines best practices for today’s responsive web with the core components we use on every project. Consider it the launch pad for your adventures into cyberspace. -spaceBase is meant to be copied into your project for further modifications. The SCSS files in `scss/base/` are usually not modified much, but the files in `scss/ui/` are meant to be completely tailored to your project. +spaceBase is the front-end starter files for any new web project. It sets up your Sass architecture and normalizes your CSS and native HTML elements. It provides the structural groundwork for your application. -**Coming Soon** +[![Build Status](https://img.shields.io/travis/space150/spaceBase.svg?style=flat-square)](https://travis-ci.org/space150/spaceBase) -Documentation is currently in orbit. In the meantime, feel free to explore! +### Highlights -### Getting Started +* Object-oriented CSS +* Optimized for light speed +* Common UI components (buttons, lists, media object) +* Helper classes and mixins +* Cross-browser form controls +* Built on REMs, with px fallback +* Supports modern browsers including IE8+ -After you download the spaceBase ZIP from the repo, unzip it and copy its contents into your own project. +### Customizable Features -spaceBase is built with Sass, so you'll need a a way to compile it. +* Compatible with any Sass 3.3 compiler +* Start with Normalize (default) or CSS Reset +* Scalable, mobile-first grid - choose how robust you want it +* Base font size for mobile vs desktop +* Global variables for breakpoints, colors, fonts and more -Setting up Sass compilation is outside the scope of this document. +**Coming Soon** -Your editor should be setup with an EditorConfig plugin, so that certain basic code style standards are enforced automatically. See http://editorconfig.org/#download and install the plugin for your editor of choice. +Detailed documentation is currently in orbit. In the meantime, feel free to explore! -You can remove: -- `tests/` -- `scss/README.md` -- `Gemfile` -- `Gemfile.lock` +## Getting Started + +1. `$ bower install spacebase` or download the ZIP and copy its contents into your project folder. +2. Use your favorite Sass 3.3 compiler to watch changes and compile the files. (Setting up Sass is outside the scope of this document.) +3. Open scss/_vars.scss to make changes to your global variables. +4. Start building out your HTML. We've included index.html as a starting point. +5. scss/base/ is the core of spaceBase. Build your UI layer in scss/ui/ -### The spaceBase structure +Your editor can be setup with EditorConfig so that code style standards are enforced automatically. See http://editorconfig.org/#download and install the plugin for your editor of choice. + +## The spaceBase structure + +Read the [CSS Architecture Overview](scss/README.md) for details on the SCSS files. ``` fonts/ @@ -36,24 +52,31 @@ scss/ ... ui/ ... + vendor/ + ... _manifest.scss _vars.scss application-ie.scss application.scss styleguide.scss +stylesheets/ ``` -Read the [CSS Architecture Overview](scss/README.md) for details on these files. +You can remove: +- `tests/` +- `Gemfile` +- `Gemfile.lock` -### Credits +## Credits * [Harry Robert’s Inuit.css](https://github.com/csswizardry/inuit.css) +* [Sass MQ](https://github.com/sass-mq/sass-mq) * [Bootstrap](http://getbootstrap.com) * [HTML5 Boilerplate](http://html5boilerplate.com) * [Normalize.css](http://necolas.github.io/normalize.css) * [Eric Meyer’s CSS Reset](http://meyerweb.com/eric/tools/css/reset) -### License +## License spaceBase is free to use under the [MIT License](LICENSE.md). diff --git a/Rakefile b/Rakefile index 9408316..658fb25 100644 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,5 @@ end desc "Run tests" task :test do - Dir.chdir "./tests" - require_relative "./tests/test" + puts `bundle exec sassunit` end diff --git a/scss/README.md b/scss/README.md index ad96760..efcd76b 100755 --- a/scss/README.md +++ b/scss/README.md @@ -1,21 +1,21 @@ -# CSS Architecture Overview +# SCSS Architecture Overview -## Philosophy +## File Structure -Mobile first. Fallback for legacy IE. +The `scss/` directory contains three folders: Base, UI and Vendor. +- **Base** contains the "building block" abstractions, namely the grid framework, mixins and helpers. These are core to spaceBase and should not be edited. +- **UI** contains all project-specific styles shared across the application. These files are meant to be completely tailored to your project. To start, it includes typography, form elements, generic print styles, buttons and other common UI components. Add more partials and organize them however the project demands. +- **Vendor** contains Normalize and CSS reset. You can add other vendor files here. -## Directories -The `scss/` directory contains two folders: Base and UI. +## Compilation -- **Base** [avoid editing] contains things like normalize/CSS reset, mixins, helpers, and the "building block" abstractions. Most of the layout and basic visual styles can be achieved with these classes. The grid, widths, lists, blocks, and basic spacing content objects are in here. -- **UI** [customize this] contains all design-specific styles shared across the application. This folder is free to organize however the project demands. To start, it includes layout, fonts, typography, buttons, and generic print styles. +All partials are imported into the `_manifest.scss`. This is also where you can choose to import either Normalize (default) or CSS Reset. When you add new partials to your project, add them to this import list. `_manifest.scss` is then imported into the two main stylesheets, `application.scss` and `application-ie.scss`. Set up your Sass compilation to generate these in the `stylesheets/` directory. Because of the amount of comments, please use minified CSS in production. +### Legacy IE Support -## Legacy IE Support - -All partials are compiled into two CSS files in the main `stylesheets/` directory, `application.css` and `application-ie.css`. These should be loaded into the site via conditional comments. +After compilation you will have two stylesheets, `application.css` and `application-ie.css`. The only difference between these files lies in the `$legacy-ie` variable. When set to true, the `media()` mixin will only render the content inside appropriate media query breakpoints. Taking advantage of CSS inheritance, the site will render the desktop layout in legacy browsers that don't support media queries (IE8 and below). Therefore, these should be loaded into the site via conditional comments. Example: ~~~html @@ -28,21 +28,27 @@ Example: ~~~ -The only difference between these files is the `$legacy-ie` variable. When set to true, the `media-query()` mixin will only render the content inside the media query breakpoints. The site will thereby display the desktop layout in legacy IE browsers. +### Styleguide + +There is a third stylesheet, `styleguide.css`, used only in `styleguide.html`. This file is the start for your project style guide, including grid examples, color swatches, typography, UI and form elements. [What is a style guide?](http://alistapart.com/article/creating-style-guides) + + +## Global Variables +Customizable variables are stored in the `_vars.scss` partial. This includes things like font styles, colors, breakpoints and base sizing measurements. Use these variables throughout the rest of the project, and add more as you see fit. `_vars.scss` also contains switches to include or exclude features as you need them. -## Variables +### Vertical Rhythm and the `$base-sizing-unit` -Global variables are kept in the `_vars.scss` partial. This includes things like base font styles, colors, breakpoints, and some misc. sizing measurements. All of these variables are used throughout most of the partials. There are a few spots where having some "local" variables are helpful for math and reuse in that particular section. These variables have been prefixed with an underscore so you know that those variables aren't used outside that partial. +As a means for consistency and good vertical rhythm, many measurements are based off the `$base-spacing-unit`, which is equal to the base `$line-height-ratio`. This way if the `$base-font-size` or `$base-line-height` is adjusted down the road, white space proportions are preserved. For example, unless you opt for using CSS Reset, most block-level elements (headings, lists, paragraphs, etc.) will have a bottom margin equal to `$base-spacing-unit`. ## The Grid -The grid structure comes almost directly from [inuit.css](https://github.com/csswizardry/inuit.css) with some minor modifications. It works on proportional sizes, not "columns" and "rows". +The grid structure comes from version 4 of [inuit.css](https://github.com/csswizardry/inuit.css) with some modifications. It uses proportionally-sized floats with human readable classnames (i.e. one-half, two-thirds, three-quarters, etc). By default, grid gutters (the space between grid elements) are equal to the `$base-sizing-unit` but can be changed in `_vars.scss`. Each set of grid elements must be wrapped in a `grid-wrapper`. Floats can be reversed by adding `grid-wrapper--rev`, and gutters can be removed by adding `grid-wrapper--full`. Example: ~~~html -
+
... @@ -57,25 +63,38 @@ Example: ### The `$responsive` Variable -If $responsive is set to false, the grid will collapse to 100% on mobile and use the same proportions for all wider breakpoints. +If `$responsive` is set to false, the grid will collapse to 100% wide on mobile and only use the proportional-width classes for breakpoint `lap` and above. This is ideal for a simple site layout. -If $responsive is set to true, the grid proportions will change at different breakpoints with the addition of classes prefixed with the breakpoint. +If `$responsive` is set to true, the base grid proportions remain constant across all breakpoints. But by adding classes prefixed with the breakpoint namespace, grid elements can change width at different breakpoints, thereby creating a truly dynamic site layout. Example: ~~~html
-
+
...
-
+
+~~~ + +This would create a `div` that at the smallest sizes fills the full width of the horizontal space, takes up half of that space at `hand` sizes, a third of that space at `lap` sizes, and a quarter at `desk` sizes. + +### Push and Pull + +Push classes move grid items over to the right, creating white space on the left. Pull classes move grid items over to the left, creating white space on the right. Push and pull styles follow the same logic of the `$responsive` variable. If `$responsive` is false, they only apply to the `lap` breakpoint and above. If `$responsive` is true, you have access to push and pull classes prefixed with the breakpoint namespace. + +Example: +~~~html +
+ +
...
~~~ -### The `$base-sizing-unit` Variable +To exclude the push/pull styles from the compiled stylesheet, change their variables to `false` in `_vars.scss`. Because of the weight they add to the file size, it is advisable to do this if you aren't using them. -As a means for consistency and good vertical rhythm as many "measurements" are based off the base-spacing-unit, which is equal to the base line-height. This way if we need to adjust down the road, all proportions are preserved. +See the [style guide](../styleguide.html) for more grid examples. diff --git a/scss/_manifest.scss b/scss/_manifest.scss index 6f70da4..032821f 100644 --- a/scss/_manifest.scss +++ b/scss/_manifest.scss @@ -1,6 +1,6 @@ @import "vars"; -// Choose either Reset or Normalize: +// Choose either Normalize or Reset: @import "vendor/normalize"; $normalize: true; // @import "vendor/reset"; $reset: true; @@ -10,9 +10,6 @@ @import "base/widths"; @import "base/push"; @import "base/pull"; -@import "base/island"; -@import "base/lists"; -@import "base/media"; @import "base/shared"; @import "base/helpers"; @@ -20,6 +17,9 @@ @import "ui/typography"; @import "ui/forms"; @import "ui/buttons"; +@import "ui/island"; +@import "ui/lists"; +@import "ui/media"; @import "ui/layout"; @import "ui/print"; diff --git a/scss/_vars.scss b/scss/_vars.scss index 7a42e22..6ed48d9 100644 --- a/scss/_vars.scss +++ b/scss/_vars.scss @@ -3,15 +3,15 @@ //------------------------------------// /* - spaceBase version: 1.0.1 + spaceBase version: 2.0.0 http://spacebase.space150.com */ $legacy-ie: false !default; -// To select Reset or Normalize, see _manifest.scss. -$reset: false !default; +// To select Normalize or Reset, see _manifest.scss $normalize: false !default; +$reset: false !default; // Include push/pull styles? $push: true; @@ -36,15 +36,26 @@ $half-spacing-unit: $base-spacing-unit / 2; $gutter: $base-spacing-unit; // Layout -$site-min-width: 320px; -$site-wrapper-max-width: 1440px; +$site-min-width: 320px; +$site-wrapper-max-width: 1440px; // Breakpoints -// Set to false to exclude breakpoints -$hand-start: 480px; -$lap-start: 768px; -$desk-start: 1024px; -$wall-start: 1200px; +$media-breakpoints: ( + hand: 480px, + lap: 768px, + desk: 1024px, + wall: 1200px +); + +$legacy-media-breakpoint: desk; + +// Media query expressions +$media-features: ( + portrait: '(orientation: portrait)', + landscape: '(orientation: landscape)', + at2x: '(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)', + at3x: '(-webkit-min-device-pixel-ratio: 3), (min-resolution: 350dpi)' +); // Colors $black: #000; @@ -60,13 +71,13 @@ $quaternary: #c46e35; // dark orange // quinary, senary, septenary, octonary, nonary, denary // Form validation colors -$state-success: #468847; -$state-error: #b94a48; +$state-success: #468847; +$state-error: #b94a48; // Fonts $font-body: Arial, Helvetica, sans-serif; $font-head: $font-body; -// Examples for custom @font-face (see _fonts.scss for declaration) -//$font-body: "Source Sans Pro", Arial, Helvetica, sans-serif; -//$font-head: "Fontatica4F", Arial, Helvetica, sans-serif; +// Example font stacks using @font-face (see _fonts.scss for declaration) +// $font-body: "Source Sans Pro", Arial, Helvetica, sans-serif; +// $font-head: "Fontatica4F", Arial, Helvetica, sans-serif; diff --git a/scss/base/_functions.scss b/scss/base/_functions.scss index a8c3aa0..bb7b4a2 100644 --- a/scss/base/_functions.scss +++ b/scss/base/_functions.scss @@ -21,3 +21,23 @@ @return $a; } } + +// get-breakpoint-width +// Get a breakpoint's width from the map. +@function get-breakpoint-width($name, $breakpoints: $media-breakpoints) { + @if map-has-key($breakpoints, $name) { + @return map-get($breakpoints, $name); + } @else { + @error "Breakpoint #{$name} wasn't found in $media-breakpoints."; + } +} + +// get-feature +// Get a media feature's definition from the map. +@function get-feature($name, $features: $media-features) { + @if map-has-key($features, $name) { + @return map-get($features, $name); + } @else { + @return false; + } +} diff --git a/scss/base/_grids.scss b/scss/base/_grids.scss index 60240d9..0e3c5c2 100644 --- a/scss/base/_grids.scss +++ b/scss/base/_grids.scss @@ -2,48 +2,43 @@ // $GRIDS //------------------------------------// -@mixin grid { - - // Grid wrapper - .gw, - .grid-wrapper { - list-style: none; - margin-bottom: 0; - @include rem(margin-left, -$gutter, $base-font-size--mobile); - @include clearfix; - } +// Grid wrapper +.gw, +.grid-wrapper { + list-style: none; + margin-bottom: 0; + @include rem(margin-left, -$gutter, $base-font-size--mobile); + @include clearfix; +} - // Reverse grid - .gw--rev > .g, - .grid-wrapper--rev > .grid { float: right; } +// Reverse grid +.gw--rev > .g, +.grid-wrapper--rev > .grid { float: right; } - // Gutterless grid - .gw--full, - .grid-wrapper--full { - margin-left: 0; +// Gutterless grid +.gw--full, +.grid-wrapper--full { + margin-left: 0; - > .g, - > .grid { - padding-left: 0; - } + > .g, + > .grid { + padding-left: 0; } +} - // Very infrequently occuring grid wrappers as children of grid wrappers - .gw > .gw, - .grid-wrapper > .grid-wrapper { margin-left: 0; } +// Very infrequently occuring grid wrappers as children of grid wrappers +.gw > .gw, +.grid-wrapper > .grid-wrapper { margin-left: 0; } - // Grid - .g, - .grid { - float: left; - width: 100%; - @include rem(padding-left, $gutter, $base-font-size--mobile); - transition: width .15s ease; - } +// Grid +.g, +.grid { + float: left; + width: 100%; + @include rem(padding-left, $gutter, $base-font-size--mobile); + transition: width .15s ease; } - -@include grid; diff --git a/scss/base/_helpers.scss b/scss/base/_helpers.scss index c3fb67b..28624cd 100644 --- a/scss/base/_helpers.scss +++ b/scss/base/_helpers.scss @@ -42,28 +42,14 @@ // Responsive visibility helpers -@include media-query(below-hand) { - .hidden-below-hand { display: none; } -} - -@include media-query(hand-and-up) { - .hidden-hand-and-up { display: none; } -} - -@include media-query(below-lap) { - .hidden-below-lap { display: none; } -} - -@include media-query(lap-and-up) { - .hidden-lap-and-up { display: none; } -} - -@include media-query(below-desk) { - .hidden-below-desk { display: none; } -} - -@include media-query(desk-and-up) { - .hidden-desk-and-up { display: none; } +@each $breakpoint, $_ in $media-breakpoints { + @include media($upto: $breakpoint) { + .hidden-below-#{$breakpoint} { display: none; } + } + + @include media($from: $breakpoint) { + .hidden-#{$breakpoint}-and-up { display: none; } + } } @@ -82,6 +68,7 @@ display: table; width: 100%; } + .display-row { display: table-row; } .display-cell { display: table-cell; diff --git a/scss/base/_mixins.scss b/scss/base/_mixins.scss index 9214960..fc9e6c8 100644 --- a/scss/base/_mixins.scss +++ b/scss/base/_mixins.scss @@ -2,17 +2,13 @@ // $MIXINS //------------------------------------// -// Micro clearfix, as per: nicolasgallagher.com/micro-clearfix-hack +// Micro clearfix @mixin clearfix { - *zoom: 1; - - &:before, &:after { display: table; content: ""; + clear: both; } - - &:after { clear: both; } } // Clear grid floats @@ -21,6 +17,7 @@ clear: left; } } + // Clear grid float clears @mixin clear-n-up($number) { &:nth-of-type(#{$number}n + 1) { @@ -28,12 +25,6 @@ } } -@mixin inline-block { - display: inline-block; - *display: inline; - zoom: 1; -} - // Image replacement @mixin hide-text { border: 0; @@ -52,6 +43,7 @@ // WebKit-style focus @mixin tab-focus { + // scss-lint:disable DuplicateProperty outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; @@ -59,6 +51,7 @@ // Placeholder text @mixin placeholder { + // scss-lint:disable VendorPrefix &:-moz-placeholder { @content; } // Firefox 4-18 &::-moz-placeholder { opacity: 1; @content; } // Firefox 19+ &:-ms-input-placeholder { @content; } // Internet Explorer 10+ @@ -146,103 +139,107 @@ // *************************************************************************** // Media query mixin // -// All styles w/o a media-query are assumed to be base, mobile-first styles. -// All styling "up" from that should be done in media queries. +// When using spaceBase, styles should be written mobile-first. +// The media mixin can override these base styles in a variety of ways: +// - starting at a breakpoint ($from: x) +// - up to a breakpoint ($upto: y) +// - between two breakpoints ($from: x, $upto: y) +// - for specific media features (e.g. retina, orientation) +// - for different media types ($type: print) +// +// You can use breakpoint aliases set in $media-breakpoints (in _vars.scss), +// or custom widths like 480px or 20em. // -// Our options are: +// Commonly-used media features are defined in $media-features (in _vars.scss). +// You can define additional feature aliases or use custom one-off expressions. // -// hand-and-up - bigger-than-phone and up -// lap-and-up - laptops and up -// desk-and-up - desktops and up -// wall-and-up - widescreen desktops and up -// below-lap - smaller than laptops -// below-hand - isolates phones +// It's important to note that $upto is exclusive. +// This means that `@include media($upto: 780px)` will set a max-width of 779px. // -// Without one of these parameters the mixin will accept a custom media query. +// USAGE: +// +// @include media($from: hand) { ... } +// @include media($upto: desk) { ... } +// @include media($from: lap, $upto: desk) { ... } +// @include media($from: 800px, $upto: 900px) { ... } +// @include media(landscape, $upto: desk) { ... } +// @include media($type: print) { ... } +// @include media('(device-radius: 50%)') { ... } +// +// OUTPUT: +// +// @media screen and (min-width: 480px) { ... } +// @media screen and (max-width: 1023px) { ... } +// @media screen and (min-width: 768px) and (max-width: 1023px) { ... } +// @media screen and (min-width: 800px) and (max-width: 900px) { ... } +// @media screen and (max-width: 1023px) and (orientation: landscape) { ... } +// @media print { ... } +// @media screen and (device-radius: 50%) { ... } +// +// OUTPUT TO LEGACY CSS: +// +// Only the content needed to render the $legacy-media-breakpoint layout. // // *************************************************************************** -@mixin media-query($media-query) { - - @if $legacy-ie == true { - // render styles without media queries - - @if $media-query == "hand-and-up" { @content; } - - @else if $media-query == "lap-and-up" { @content; } - - @else if $media-query == "desk-and-up" { @content; } - - @else if $media-query == "wall-and-up" {} - - @else if $media-query == "below-desk" {} - - @else if $media-query == "below-lap" {} - - @else if $media-query == "below-hand" {} - - // include custom breakpoints - @else { - @content; - } - - // Not legacy-ie - } @else { - // render styles without media queries if those breakpoints are false - - @if $media-query == "hand-and-up" { - @if $hand-start != false { - @media only screen and (min-width:$hand-start) { @content; } - } - @else { @content; } - } - - @else if $media-query == "lap-and-up" { - @if $lap-start != false { - @media only screen and (min-width:$lap-start) { @content; } - } - @else { @content; } - } - - @else if $media-query == "desk-and-up" { - @if $desk-start != false { - @media only screen and (min-width:$desk-start) { @content; } - } - @else { @content; } +@mixin media($feature:false, $from:false, $upto:false, $type:screen) { + $min-width: 0; + $max-width: 0; + $media-query: ''; + + // From: this breakpoint (inclusive) + @if $from { + @if type-of($from) == number { + $min-width: $from; + } @else if get-breakpoint-width($from) { + $min-width: get-breakpoint-width($from); } + } - @else if $media-query == "wall-and-up" { - @if $wall-start != false { - @media only screen and (min-width:$wall-start) { @content; } - } - @else { @content; } + // Upto: that breakpoint (exclusive) + @if $upto { + @if type-of($upto) == number { + $max-width: $upto; + } @else if get-breakpoint-width($upto) { + $max-width: get-breakpoint-width($upto) - 1px; } + } - @else if $media-query == "below-desk" { - @if $desk-start != false { - @media only screen and (max-width: ($desk-start - 1px)) { @content; } - } - @else {} + // Render styles without media queries + @if $legacy-ie == true { + $legacy-breakpoint-width: get-breakpoint-width($legacy-media-breakpoint); + // Output only rules that start at or span our legacy media width + @if ( + $min-width <= $legacy-breakpoint-width + and ( + $upto == false or $max-width >= $legacy-breakpoint-width + ) + ) { + @content; } - @else if $media-query == "below-lap" { - @if $lap-start != false { - @media only screen and (max-width: ($lap-start - 1px)) { @content; } + } @else { + @if $min-width != 0 { $media-query: '#{$media-query} and (min-width: #{$min-width})'; } + @if $max-width != 0 { $media-query: '#{$media-query} and (max-width: #{$max-width})'; } + @if $feature { + // Pass through custom expression or get defined expression + $original-feature: $feature; + $feature: get-feature($feature); + @if $feature { + $media-query: '#{$media-query} and #{$feature}'; + } @else { + $media-query: '#{$media-query} and (#{$original-feature})'; } - @else {} } - @else if $media-query == "below-hand" { - @if $hand-start != false { - @media only screen and (max-width: ($hand-start - 1px)) { @content; } - } - @else {} + // Remove unnecessary media query prefix 'all and ' + @if ($type == 'all' and $media-query != '') { + $type: ''; + $media-query: str-slice(unquote($media-query), 6); } - // custom breakpoints - @else { - @media only screen and ($media-query) { @content; } + @media #{$type + $media-query} { + @content; } } } - diff --git a/scss/base/_pull.scss b/scss/base/_pull.scss index 6bbad8e..f26fbb0 100644 --- a/scss/base/_pull.scss +++ b/scss/base/_pull.scss @@ -7,33 +7,18 @@ } @if $pull { - [class*="pull--"] { position: relative; } @if $responsive { - @include pull-setup; @if $responsive-push-pull { - - @if $hand-start { - @include media-query(hand-and-up) { @include pull-setup("hand-"); } - } - - @if $lap-start { - @include media-query(lap-and-up) { @include pull-setup("lap-"); } - } - - @if $desk-start { - @include media-query(desk-and-up) { @include pull-setup("desk-"); } - } - - @if $wall-start { - @include media-query(wall-and-up) { @include pull-setup("wall-"); } + @each $breakpoint, $_ in $media-breakpoints { + @include media($from: $breakpoint) { @include pull-setup("#{$breakpoint}-"); } } } } @else { - @include media-query(lap-and-up) { @include pull-setup; } + @include media($from: lap) { @include pull-setup; } } } diff --git a/scss/base/_push.scss b/scss/base/_push.scss index 8f3a1ef..569acbd 100644 --- a/scss/base/_push.scss +++ b/scss/base/_push.scss @@ -7,33 +7,18 @@ } @if $push { - [class*="push--"] { position: relative; } @if $responsive { - @include push-setup; @if $responsive-push-pull { - - @if $hand-start { - @include media-query(hand-and-up) { @include push-setup("hand-"); } - } - - @if $lap-start { - @include media-query(lap-and-up) { @include push-setup("lap-"); } - } - - @if $desk-start { - @include media-query(desk-and-up) { @include push-setup("desk-"); } - } - - @if $wall-start { - @include media-query(wall-and-up) { @include push-setup("wall-"); } + @each $breakpoint, $_ in $media-breakpoints { + @include media($from: $breakpoint) { @include push-setup("#{$breakpoint}-"); } } } } @else { - @include media-query(lap-and-up) { @include push-setup; } + @include media($from: lap) { @include push-setup; } } } diff --git a/scss/base/_widths.scss b/scss/base/_widths.scss index aeb2164..ccbf39b 100644 --- a/scss/base/_widths.scss +++ b/scss/base/_widths.scss @@ -93,22 +93,10 @@ $grid-widths: ( @if $responsive { @include grid-setup; - @if $hand-start { - @include media-query(hand-and-up) { @include grid-setup("hand-"); } - } - - @if $lap-start { - @include media-query(lap-and-up) { @include grid-setup("lap-"); } - } - - @if $desk-start { - @include media-query(desk-and-up) { @include grid-setup("desk-"); } - } - - @if $wall-start { - @include media-query(wall-and-up) { @include grid-setup("wall-"); } + @each $breakpoint, $_ in $media-breakpoints { + @include media($from: $breakpoint) { @include grid-setup("#{$breakpoint}-"); } } } @else { // Not responsive // Initializes widths w/o namespace - @include media-query(lap-and-up) { @include grid-setup; } + @include media($from: lap) { @include grid-setup; } } diff --git a/scss/ui/_buttons.scss b/scss/ui/_buttons.scss index 9744f40..c07eb3b 100644 --- a/scss/ui/_buttons.scss +++ b/scss/ui/_buttons.scss @@ -3,17 +3,17 @@ //------------------------------------// .btn { + display: inline-block; margin: 0; padding: .4em 1em; + @include rem(font-size, 1); line-height: 1.6em; text-align: center; vertical-align: middle; white-space: nowrap; border: 1px solid $gray; - cursor: pointer; - @include inline-block; - @include rem(font-size, 1); border-radius: 0; + cursor: pointer; &, &:hover, @@ -22,6 +22,6 @@ &.disabled, &[disabled] { cursor: not-allowed; - opacity: 0.65; + opacity: .65; } } diff --git a/scss/ui/_forms.scss b/scss/ui/_forms.scss index 804ce12..4380f02 100644 --- a/scss/ui/_forms.scss +++ b/scss/ui/_forms.scss @@ -115,6 +115,7 @@ input[type="checkbox"]:focus { @include tab-focus; } background-color: $gray-light; opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655 } + &[disabled], fieldset[disabled] & { cursor: not-allowed; @@ -129,6 +130,7 @@ textarea.form-control { // Remove inner shadow on webkit, see http://zomigi.com/blog/bug-fixes-for-removing-the-inner-shadow-on-ios-inputs input.form-control, textarea.form-control { + // scss-lint:disable VendorPrefix background-image: -webkit-linear-gradient(hsla(0, 0%, 100%, 0), hsla(0, 0%, 100%, 0)); } @@ -158,6 +160,7 @@ textarea.form-control { margin-left: -20px; margin-top: 4px \9; } + // Move up sibling radios or checkboxes for tighter spacing .radio + .radio, .checkbox + .checkbox { margin-top: -5px; } diff --git a/scss/base/_island.scss b/scss/ui/_island.scss similarity index 100% rename from scss/base/_island.scss rename to scss/ui/_island.scss diff --git a/scss/base/_lists.scss b/scss/ui/_lists.scss similarity index 97% rename from scss/base/_lists.scss rename to scss/ui/_lists.scss index ade0264..cf746d2 100644 --- a/scss/base/_lists.scss +++ b/scss/ui/_lists.scss @@ -23,7 +23,7 @@ > li { float: none; - @include inline-block; + display: inline-block; @include rem(margin, 0 $half-spacing-unit, $base-font-size--mobile); &:last-child { diff --git a/scss/base/_media.scss b/scss/ui/_media.scss similarity index 76% rename from scss/base/_media.scss rename to scss/ui/_media.scss index 483a9e6..57ee3a5 100644 --- a/scss/base/_media.scss +++ b/scss/ui/_media.scss @@ -7,7 +7,7 @@ .media__item { float: left; - margin-right: 1em; + @include rem(margin-right, $half-spacing-unit, $base-font-size--mobile); img, video, @@ -26,8 +26,8 @@ // FLIP .media--flip > .media__item { float: right; - margin-left: $base-spacing-unit; margin-right: 0; + @include rem(margin-left, $half-spacing-unit, $base-font-size--mobile); } // NOWRAP @@ -46,7 +46,7 @@ } .media__item { - padding-right: $base-spacing-unit; + @include rem(padding-right, $half-spacing-unit, $base-font-size--mobile); img { width: auto !important; diff --git a/scss/ui/_print.scss b/scss/ui/_print.scss index 9cae0ae..71b486c 100644 --- a/scss/ui/_print.scss +++ b/scss/ui/_print.scss @@ -6,6 +6,7 @@ @media print { * { + // scss-lint:disable ColorVariable background: transparent !important; color: #000 !important; box-shadow: none !important; diff --git a/scss/ui/_typography.scss b/scss/ui/_typography.scss index 52890eb..e7c9b42 100644 --- a/scss/ui/_typography.scss +++ b/scss/ui/_typography.scss @@ -3,7 +3,7 @@ //------------------------------------// html { - font: #{($base-font-size/16px)*1em}/#{$line-height-ratio} $font-body; + font: #{($base-font-size--mobile/16px)*1em}/#{$line-height-ratio} $font-body; color: $black; background: $white; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); @@ -47,7 +47,7 @@ h4, .h4 { @include rem(font-size, .875); } -@include media-query(lap-and-up) { +@include media($from: lap) { h1, .h1 { @include rem(font-size, 3.6); } h2, .h2 { @include rem(font-size, 2.4); } diff --git a/scss/vendor/_normalize.scss b/scss/vendor/_normalize.scss index 458eea1..5e5e3c8 100644 --- a/scss/vendor/_normalize.scss +++ b/scss/vendor/_normalize.scss @@ -1,9 +1,9 @@ -/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ /** * 1. Set default font family to sans-serif. - * 2. Prevent iOS text size adjust after orientation change, without disabling - * user zoom. + * 2. Prevent iOS and IE text size adjust after device orientation change, + * without disabling user zoom. */ html { @@ -71,7 +71,7 @@ audio:not([controls]) { /** * Address `[hidden]` styling not present in IE 8/9/10. - * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. */ [hidden], @@ -91,7 +91,8 @@ a { } /** - * Improve readability when focused and also mouse hovered in all browsers. + * Improve readability of focused elements when they are also in an + * active/hover state. */ a:active, @@ -209,7 +210,6 @@ figure { */ hr { - -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } @@ -350,15 +350,12 @@ input[type="number"]::-webkit-outer-spin-button { /** * 1. Address `appearance` set to `searchfield` in Safari and Chrome. - * 2. Address `box-sizing` set to `border-box` in Safari and Chrome - * (include `-moz` to future-proof). + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome. */ input[type="search"] { -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; + box-sizing: content-box; /* 2 */ } /** diff --git a/styleguide.html b/styleguide.html index 0f303ac..d4e94d6 100644 --- a/styleguide.html +++ b/styleguide.html @@ -8,7 +8,7 @@ - spaceBase + spaceBase Style Guide @@ -22,7 +22,7 @@
-

spaceBase

+

spaceBase Style Guide

View on GitHub

diff --git a/test/_test_helper.css b/test/_test_helper.css new file mode 100644 index 0000000..e69de29 diff --git a/test/_test_helper.scss b/test/_test_helper.scss new file mode 100644 index 0000000..5f6fef1 --- /dev/null +++ b/test/_test_helper.scss @@ -0,0 +1,3 @@ +@import "../scss/vars"; +@import "../scss/base/functions"; +@import "../scss/base/mixins"; diff --git a/test/media/basic.css b/test/media/basic.css new file mode 100644 index 0000000..f2d0c45 --- /dev/null +++ b/test/media/basic.css @@ -0,0 +1,30 @@ +@media screen and (min-width: 480px) { + div { display: none; } +} +@media screen and (max-width: 479px) { + div { display: none; } +} + + +@media screen and (min-width: 768px) { + div { display: none; } +} +@media screen and (max-width: 767px) { + div { display: none; } +} + + +@media screen and (min-width: 1024px) { + div { display: none; } +} +@media screen and (max-width: 1023px) { + div { display: none; } +} + + +@media screen and (min-width: 1200px) { + div { display: none; } +} +@media screen and (max-width: 1199px) { + div { display: none; } +} diff --git a/test/media/basic.scss b/test/media/basic.scss new file mode 100644 index 0000000..1d4f0ea --- /dev/null +++ b/test/media/basic.scss @@ -0,0 +1,61 @@ +@import "../test_helper"; + +@each $breakpoint, $_ in $media-breakpoints { + @include media($from: $breakpoint) { + div { display: none; } + } + @include media($upto: $breakpoint) { + div { display: none; } + } +} + +// // LEGACY-IE +// $legacy-ie: true; + +// @include media($from: lap) { +// div { display: none; } +// } +// @include media($from: hand) { +// div { display: none; } +// } +// @include media($from: desk) { +// div { display: none; } +// } +// @include media($from: wall) { +// div { display: none; } +// } +// @include media($upto: desk) { +// div { display: none; } +// } +// @include media($upto: hand) { +// div { display: none; } +// } +// @include media($upto: lap) { +// div { display: none; } +// } + +// // BREAKPOINTS REMOVED +// // $legacy-ie: false; +// // $media-breakpoints: (); + +// // @include media($from: lap) { +// // div { display: none; } +// // } +// // @include media($from: hand) { +// // div { display: none; } +// // } +// // @include media($from: desk) { +// // div { display: none; } +// // } +// // @include media($from: wall) { +// // div { display: none; } +// // } +// // @include media($upto: desk) { +// // div { display: none; } +// // } +// // @include media($upto: hand) { +// // div { display: none; } +// // } +// // @include media($upto: lap) { +// // div { display: none; } +// // } diff --git a/test/media/legacy.css b/test/media/legacy.css new file mode 100644 index 0000000..366642b --- /dev/null +++ b/test/media/legacy.css @@ -0,0 +1,4 @@ +div { display: none; } +div { display: none; } +div { display: none; } +div { display: none; } diff --git a/test/media/legacy.scss b/test/media/legacy.scss new file mode 100644 index 0000000..ce71eb4 --- /dev/null +++ b/test/media/legacy.scss @@ -0,0 +1,13 @@ +@import "../test_helper"; + +$legacy-ie: true; + +@each $breakpoint, $_ in $media-breakpoints { + @include media($from: $breakpoint) { + div { display: none; } + } + @include media($upto: $breakpoint) { + div { display: none; } + } +} + diff --git a/tests/rem-mixin/expected.css b/test/rem-mixin/rem-mixin.css similarity index 68% rename from tests/rem-mixin/expected.css rename to test/rem-mixin/rem-mixin.css index 523fc77..851e08a 100644 --- a/tests/rem-mixin/expected.css +++ b/test/rem-mixin/rem-mixin.css @@ -5,11 +5,11 @@ div { margin-left: 4rem; padding: 4rem 0rem 2rem 1rem; - font-size: 30px; + font-size: 32px; font-size: 2rem; } span { - padding: 60px 0px 30px 15px; - font-size: 30px; + padding: 64px 0px 32px 16px; + font-size: 32px; } diff --git a/tests/rem-mixin/input.scss b/test/rem-mixin/rem-mixin.scss similarity index 79% rename from tests/rem-mixin/input.scss rename to test/rem-mixin/rem-mixin.scss index 8902c5d..fcc1926 100644 --- a/tests/rem-mixin/input.scss +++ b/test/rem-mixin/rem-mixin.scss @@ -1,6 +1,4 @@ -@import "vars"; -@import "base/functions"; -@import "base/mixins"; +@import "../test_helper"; div { @include rem(margin-left, 4); diff --git a/tests/media-queries/expected.css b/tests/media-queries/expected.css deleted file mode 100644 index 6ee39ee..0000000 --- a/tests/media-queries/expected.css +++ /dev/null @@ -1,51 +0,0 @@ -/* -Error: File to import not found or unreadable: vars. - on line 1 of media-queries/input.scss - -1: @import "vars"; -2: @import "base/mixins"; -3: -4: @include media-query(lap-and-up) { -5: div { display: none; } -6: } - -Backtrace: -media-queries/input.scss:1 -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/import_node.rb:67:in `rescue in import' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/import_node.rb:45:in `import' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/import_node.rb:28:in `imported_file' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/import_node.rb:37:in `css_import?' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:311:in `visit_import' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/base.rb:36:in `visit' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:158:in `block in visit' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/stack.rb:79:in `block in with_base' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/stack.rb:115:in `with_frame' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/stack.rb:79:in `with_base' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:158:in `visit' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/base.rb:52:in `block in visit_children' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/base.rb:52:in `map' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/base.rb:52:in `visit_children' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:167:in `block in visit_children' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:179:in `with_environment' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:166:in `visit_children' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/base.rb:36:in `block in visit' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:186:in `visit_root' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/base.rb:36:in `visit' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:157:in `visit' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/visitors/perform.rb:8:in `visit' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/root_node.rb:36:in `css_tree' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/tree/root_node.rb:29:in `render_with_sourcemap' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/engine.rb:368:in `_render_with_sourcemap' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/engine.rb:285:in `render_with_sourcemap' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/exec/sass_scss.rb:407:in `run' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/exec/sass_scss.rb:63:in `process_result' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/exec/base.rb:52:in `parse' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/lib/sass/exec/base.rb:19:in `parse!' -/Users/mike/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/sass-3.4.14/bin/sass:13:in `' -/Users/mike/.rbenv/versions/2.2.2/bin/sass:23:in `load' -/Users/mike/.rbenv/versions/2.2.2/bin/sass:23:in `
' -*/ -body:before { - white-space: pre; - font-family: monospace; - content: "Error: File to import not found or unreadable: vars.\A on line 1 of media-queries/input.scss\A \A 1: @import \"vars\";\A 2: @import \"base/mixins\";\A 3: \A 4: @include media-query(lap-and-up) {\A 5: div { display: none; }\A 6: }"; } diff --git a/tests/media-queries/input.scss b/tests/media-queries/input.scss deleted file mode 100644 index 8e30379..0000000 --- a/tests/media-queries/input.scss +++ /dev/null @@ -1,78 +0,0 @@ -@import "vars"; -@import "base/mixins"; - -@include media-query(lap-and-up) { - div { display: none; } -} -@include media-query(hand-and-up) { - div { display: none; } -} -@include media-query(desk-and-up) { - div { display: none; } -} -@include media-query(wall-and-up) { - div { display: none; } -} -@include media-query(below-desk) { - div { display: none; } -} -@include media-query(below-hand) { - div { display: none; } -} -@include media-query(below-lap) { - div { display: none; } -} - -// LEGACY-IE -$legacy-ie: true; - -@include media-query(lap-and-up) { - div { display: none; } -} -@include media-query(hand-and-up) { - div { display: none; } -} -@include media-query(desk-and-up) { - div { display: none; } -} -@include media-query(wall-and-up) { - div { display: none; } -} -@include media-query(below-desk) { - div { display: none; } -} -@include media-query(below-hand) { - div { display: none; } -} -@include media-query(below-lap) { - div { display: none; } -} - -// BREAKPOINTS SET TO FALSE -$legacy-ie: false; -$hand-start: false; -$lap-start: false; -$desk-start: false; -$wall-start: false; - -@include media-query(lap-and-up) { - div { display: none; } -} -@include media-query(hand-and-up) { - div { display: none; } -} -@include media-query(desk-and-up) { - div { display: none; } -} -@include media-query(wall-and-up) { - div { display: none; } -} -@include media-query(below-desk) { - div { display: none; } -} -@include media-query(below-hand) { - div { display: none; } -} -@include media-query(below-lap) { - div { display: none; } -} diff --git a/tests/test.rb b/tests/test.rb deleted file mode 100644 index 0201d6d..0000000 --- a/tests/test.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "pathname" - -puts "Building test files..." -puts `compass compile` - -puts "\nRunning..." -test_dirs = `find ./ -type d`.split("\n").map do |dir| - Pathname.new(dir).realpath.to_s -end - -# Don't stare directly at the Sass cache. -test_dirs.reject! do |dir| - dir =~ /sass-cache/ -end - -# Get rid of current dir. -test_dirs.shift - -test_dirs.each do |dir| - Dir.chdir(dir) - css = Dir["*.css"] - - # If there's no expected output, copy the actual output for next time. - expected = Dir["expected.css"] - if expected.length == 0 - puts "No expected output for #{dir}!" - puts "Copying actual output to expected.css, just this time." - `cp input.css expected.css` - # There's no point in diffing. - next - end - - diff = `diff #{css.join(" ")} 2>/dev/null` - if !diff.empty? - puts "FAILED: " + dir - puts `diff -y #{css.join(" ")}` - puts "\n" - else - # Everything went okay. - puts dir + " ✓" - end - - # Clean up. - `rm -f input.css` -end