UNPKG

@retailmenot/roux-sass-importer

Version:

A node-sass custom importer for Roux ecosystem ingredients.

119 lines (90 loc) 5 kB
# @retailmenot/roux-sass-importer A [node-sass custom importer][node-sass-custom-importer] for ingredients in the [Roux][Roux ecosystem]. [![Build Status](https://travis-ci.org/RetailMeNotSandbox/roux-sass-importer.svg?branch=master)](https://travis-ci.org/RetailMeNotSandbox/roux-sass-importer) [![Coverage Status](https://coveralls.io/repos/github/RetailMeNotSandbox/roux-sass-importer/badge.svg?branch=master)](https://coveralls.io/github/RetailMeNotSandbox/roux-sass-importer?branch=master) ## Installation ```sh npm install @retailmenot/roux-sass-importer ``` ## Usage This importer makes it possible to import Sass from an ingredient by specifying the pantry and ingredient name only: ```sass @import "@namespace/pantry/an-ingredient"; @import "another-pantry/another-ingredient"; ``` Create an importer and pass it to node-sass as follows: ```javascript var sass = require('node-sass'); var rouxSassImporter = require('@retailmenot/roux-sass-importer'); var importer = rouxSassImporter(sass.NULL, { pantries: { '@namespace/pantry': somePantryInstance, // This will be initialized and cached across calls to the // importer '@namespace/pantry2': '/path/to/pantry2' }, pantrySearchPaths: [ path.resolve('node_modules'), path.resolve('some/other/path') ] }); sass.render({ file: 'path/to/your/file.scss', importer: importer }, function(err, result){ console.log(result && result.css.toString()); }); ``` If passing only a path, and you have nested the pantry entry, please ensure that you have correctly noted that in your package.json, per the [roux README][pantry-root-readme]. ## Relative `@import` paths **An important note regarding how relative `@import` paths are resolved:** If the import path can be parsed by `roux.parseIngredientPath`, then the importer will try to look up the corresponding Sass entry point for that ingredient by instantiating the pantry with `roux.initialize`. If successful, the import path is resolved to the entry point, otherwise an error is returned. This means that relative file system paths which look like ingredient paths will not work. Ideally, if we couldn't find the pantry in any of the `pantrySearchPaths`, we would not return an error, but instead tell node-sass to resolve the import path in the default manner. Unfortunately, this is not possible due to a [bug][node-sass#1296] in either node-sass or libsass. The upshot of this is that *relative paths should begin with `./` or `../`*. These will never be parseable as ingredient paths, so they will be handed off to node-sass to resolve. ## CSS De-duplicating **An important note on deduping output in the CSS:** The importer will keep track of which ingredient files have already been imported. It will do so for imports matching an ingredient's entrypoint, as well as relative imports from within any sass file inside of a known pantry. Whenever an import for the same file is encountered, the importer will return empty file contents to prevent duplicate CSS from showing up in the compiled output. ## API This module exports a function that accepts an optional config object and returns a [node-sass custom importer][node-sass-custom-importer]. The importer only handles import paths matching the following patterns: - `@<namespace>/<pantry>/<ingredient>` - `<pantry>/<ingredient>` If the import path matches one of the above, the importer attempts to look up the Sass entry point for the named pantry and ingredient. If successful, an absolute path to the entry point is returned (possibly asynchronously). If the pantry is not found, an `Error` is returned. If the pantry is found but does not contain the named ingredient, an `Error` is returned. If both the pantry and ingredient are found but the ingredient does not have a Sass entry point, an `Error` is returned. The importer maintains a cache of pantries it looks up. The cache can be primed by means of the optional `config.pantries` parameter. If the named pantry is cached, the above process completes synchronously. If not cached, the pantry is looked up in the locations named by `config.pantrySearchPaths`. The first matching pantry found is cached and the above process performed. - `NODE_SASS_NULL` - The object to return when node-sass should do its thing. You should pass `require('node-sass').NULL` from your webpack config in the repo that's consuming this module. - `config` - optional config object for the importer - `config.pantries` - optional primed cache of pantries, defaults to `{}` - `config.pantrySearchPaths` - optional array of paths to search for pantries not found in the cache, defaults to `['$CWD/node_modules']` [Roux]:https://github.com/RetailMeNotSandbox/roux [node-sass-custom-importer]: https://github.com/sass/node-sass#importer--v200---experimental [node-sass#1296]: https://github.com/sass/node-sass/issues/1296 [pantry-root-readme]:https://github.com/RetailMeNotSandbox/roux#relocating-the-ingredients-base-directory