Home

Awesome

Sassport

Sassport logo

PluginsQuick StartUsageAssetsCustom ModulesLoadersExamples

JavaScript modules for Sass (node-sass). Easily share assets, and JavaScript functions and values in your Sass projects.

Available Plugins

Available Modules

Quick Start

  1. npm install sassport --save-dev
  2. Use sassport just like you would use Node-Sass (see example below)
  3. Use require() in your Sass (SCSS) stylesheets to import JS values (see example below)
  4. node index.js

EXAMPLE:

// index.js
var sassport = require('sassport');

sassport().render({
  file: 'path/to/stylesheet.scss'
}, function(err, result) {
  console.log(result.css.toString());
  // ... or whatever you want to do with the result
});
// path/to/my-colors.js
module.exports = {
  primary: '#C0FF33',
  secondary: '#B4D455'
};
// path/to/stylesheet.scss
$colors: require('path/to/my-colors'); // Just like Node require()!

.foo {
  color: map-get($colors, primary);
  
  &:hover {
    // Sassport uses inferred Sass values, not strings!
    color: lighten(map-get($colors, primary), 10%);
}

Result:

.foo {
  color: #C0FF33;
}

.foo:hover {
  color: #D0FF66;
}

Inspiration

Sassport was created to solve a few problems related to creating and maintaining Sass projects:

The last question is especially important - it means that you can communicate with JavaScript from Sass to do complex tasks such as creating sprite sheets and receive useful information from the completed task's return value, such as image dimensions or sprite locations. With sassport.wrap(), it's possible to wrap entire JavaScript libraries for use inside your Sass project.

Is this similar to Sass Eyeglass? Yes, and no. Both projects achieve similar goals, with different philosophies. Eyeglass is based on convention - 3rd-party Eyeglass modules must be configured to be discoverable by Eyeglass via NPM. With Sassport, you explicity state which Sassport plugins (modules) you're going to use, which can come from anywhere - NPM, Bower, or even your own project. This is very similar to how PostCSS works.

Sassport is also agnostic and simple with assets - its only job is to copy assets from the source folder to your project's assets folder (inside the sassport-assets subdirectory). With this, you can wrap any plugin to transform your assets (see examples below). Sassport is not meant to be another asset management tool - Gulp, Grunt, Broccoli, etc. already exist for that.

Using Sassport modules

Sassport modules can provide extra functionality and give you access to module-specific stylesheets. The syntax for including Sassport modules is very similar to PostCSS' syntax:

EXAMPLE:

var sassport = require('sassport');

sassport([
  require('sassport-foo'), // example foo module
  require('sassport-bar')  // example bar module
]).render({
  file: 'path/to/stylesheet.scss'
}, function(err, result) { /* ... */ });
// path/to/stylesheet.scss
@import 'sassport-foo'; // imports default export(s)
                        // from sassport-foo module
@import 'sassport-bar'; 

@import 'sassport-bar/images'; // imports specific images export(s) 
                               // from sassport-bar module

When a Sassport module is included:

Managing Assets

To specify where your assets are, configure the asset paths by using the .assets(localAssetPath, remoteAssetPath) method. Then, you can use the Sass helper function resolve-url($source, $module: null) to generate the remote URL path. The $source is relative to the provided localAssetPath.

EXAMPLE:

var sassport = require('sassport');

sassport([ /* modules */ ])
  .assets(__dirname + '/assets', 'public/assets')
  .render(/* ... */);
.my-image {
  // Renders as:
  // background-image: url(public/assets/images/my-image.png);
  background-image: resolve-url('images/my-image.png');
}

When you @import assets (files or directories) from a Sassport module, those get copied into the sassport-assets/ subdirectory inside the provided localAssetPath. These assets can then be referenced in resolve-url() by specifying the $module that it came from.

EXAMPLE:

@import 'foo-module/images';

.their-image {
  // Renders as:
  // background-image: url(public/assets/sassport-assets/images/their-image.png);
  background-image: resolve-url('images/their-image.png', 'foo-module');
}

Creating Sassport Modules

A Sassport module is created with sassport.module(name). From there, you can use the below methods to configure your Sassport module:

EXAMPLE:

var sassport = require('sassport');
var sass = require('node-sass');

module.exports = sassport.module('test')
  .functions({
    'greet($val)': function(val) {
      return sass.types.String('Hello, ' + val.getValue());
    },
    'greet-simple($value)': sassport.wrap(function(val) {
      return 'Hey, ' + val;
    })
  })
  .variables({
    '$a-number': 42,
    '$a-string': 'Sassport rocks!',
    '$a-list': [1, 2, 3, 4, 5],
    '$a-map': {a: 1, b: 2, c: 3}
  })
  .exports({
    'default': __dirname + '/stylesheets/main.scss', // @import 'test';
    'images': __dirname + '/images', // @import 'test/images';
  });
.greeting {
  test: greet('David'); // Hello, David
  test: greet-simple('David'); // Hey, David
}

With the sassport.wrap(fn, options) utility function, normal JS functions can be wrapped to automatically have arguments converted to JS values, and to automatically have the JS return value converted to Sass values using this conversion:

Also, sassport.utils provides Chris Eppstein's excellent node-sass-utils library.

Custom Loaders

You can now specify custom loaders for @import files by separating them with an ! after the import path. Here's an example that uses the Sassport reference module to load SCSS files by reference:

var sassport = require('sassport');

// The Sassport reference module provides:
// - a !reference loader
// - a reference() Sass function
var referenceModule = require('sassport/modules/reference');

sassport([ referenceModule ])
  .render({ file: 'main.scss' }, /* ... */);
// In path/to/_foo.scss:
@for $i from 1 through 10 {
  .col-#{$i} {
    display: block;
    width: percentage($i / 10);
  }
}

// In main.scss:
@import 'path/to/foo !reference';

.my-thing {
  @extend #{reference('.col-4')};
}

// Result CSS:
// Notice how the other column selectors never get output.
.my-thing {
  display: block;
  width: 40%;
}

Value Inference

By default, Sassport automatically infers Sass values from JavaScript strings. This means that you can seamlessly share CSS-like or (Sass-like) values as strings between JS and Sass, and Sassport will hand them over to sass as their inferred values, not as strings. For example:

To turn this option off, set infer to false as an option: sassport([...], { infer: false }).render(...). If you do this, you can selectively use inference in custom wrapped functions: sassport.wrap(fn, { infer: true });, or as a param in the Sass require() function as $infer: true.

Examples

Getting image dimensions

TERMINAL

npm install sassport image-size --save-dev

JAVASCRIPT

// index.js
var sassport = require('sassport');
var sizeOf = require('image-size');

sassport()
  .functions({
    'size-of($path)': sassport.wrap(function(path) {
      return sizeOf(path);
    }, { unit: 'px' })
  })
  .assets('./assets', 'public/assets')
  .render({
    file: 'stylesheet.scss'
  }, function(err, res) {
    console.log(res.css.toString());
  });

SCSS

// stylesheet.scss
$image-path: 'sassport-sm.png';
$image-size: size-of(resolve-path($image-path));

.my-image {
  background-image: resolve-url($image-path);
  width: map-get($image-size, 'width');
  height: map-get($image-size, 'height');
}

RESULT (CSS)

.my-image {
  background-image: url(public/assets/sassport-sm.png);
  width: 145px;
  height: 175px;
}