sass-module-importer
Advanced tools
Comparing version 1.0.2 to 1.1.0
114
lib/index.js
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var fs = _interopDefault(require('fs')); | ||
var path = _interopDefault(require('path')); | ||
var Map = _interopDefault(require('es6-map')); | ||
var assign = _interopDefault(require('object-assign')); | ||
var npmResolve = _interopDefault(require('resolve')); | ||
var bowerResolve = _interopDefault(require('resolve-bower')); | ||
var _es6Map = require('es6-map'); | ||
var options = void 0; | ||
var _es6Map2 = _interopRequireDefault(_es6Map); | ||
/** | ||
* Check for the "main" field to see if it contains any css/scss/sass | ||
* If not, try to use the "style" field from package.json - and if that fails | ||
* too, defaults to "index.css" | ||
*/ | ||
var filter = function filter(pkg) { | ||
if (!pkg.main || pkg.main && !pkg.main.match(/\.s?[c|a]ss$/g)) { | ||
pkg.main = pkg.style || 'index.css'; | ||
} | ||
return pkg; | ||
}; | ||
var _resolve = require('resolve'); | ||
var _resolve2 = _interopRequireDefault(_resolve); | ||
var _resolveBower = require('resolve-bower'); | ||
var _resolveBower2 = _interopRequireDefault(_resolveBower); | ||
function find(resolver, file) { | ||
/** | ||
* Simple Promise wrapper to resolve the npm/bower modules | ||
*/ | ||
var find = function find(resolver, _ref) { | ||
var url = _ref.url; | ||
var prev = _ref.prev; | ||
var resolved = _ref.resolved; | ||
return new Promise(function (resolve) { | ||
resolver(file, function (err, res) { | ||
return resolve(err ? file : res); | ||
}); | ||
if (resolved) { | ||
resolve({ url: url, prev: prev, resolved: resolved }); | ||
} else { | ||
resolver(url, options, function (err, res) { | ||
resolve({ url: err ? url : res, prev: prev, resolved: !err }); | ||
}); | ||
} | ||
}); | ||
} | ||
}; | ||
find.npm = function (file) { | ||
var npm = function npm(file) { | ||
return find(npmResolve, file); | ||
}; | ||
return find(_resolve2['default'], file); | ||
var bower = function bower(file) { | ||
return find(bowerResolve, file); | ||
}; | ||
find.bower = function (file) { | ||
return find(_resolveBower2['default'], file); | ||
/** | ||
* Read file's content | ||
*/ | ||
var read = function read(_ref2) { | ||
var url = _ref2.url; | ||
var prev = _ref2.prev; | ||
var resolved = _ref2.resolved; | ||
return new Promise(function (resolve, reject) { | ||
if (url.match(/\.s[c|a]ss/g) || !resolved) { | ||
var resolvedURL = url; | ||
if (prev && prev !== 'stdin' && !path.isAbsolute(url)) { | ||
resolvedURL = path.resolve(path.dirname(prev), url); | ||
} | ||
resolve({ file: resolvedURL }); | ||
} else { | ||
fs.readFile(url, 'utf8', function (err, contents) { | ||
return err ? reject(err) : resolve({ contents: contents }); | ||
}); | ||
} | ||
}); | ||
}; | ||
@@ -43,24 +76,23 @@ | ||
* Look for Sass files installed through npm | ||
* @param opts {Object} Options to be passed to the resolver module | ||
* | ||
* @return {Function} Function to be used by node-sass importer | ||
*/ | ||
function index (opts) { | ||
options = assign({}, { packageFilter: filter }, opts); | ||
exports['default'] = function () { | ||
var aliases = new Map(); | ||
var aliases = new _es6Map2['default'](); | ||
return function (url, _, done) { | ||
return function (url, prev, done) { | ||
if (aliases.has(url)) { | ||
return done({ file: aliases.get(url) }); | ||
done(aliases.get(url)); | ||
} else { | ||
npm({ url: url, prev: prev }).then(bower).then(read).then(function (res) { | ||
aliases.set(url, res); | ||
done(res); | ||
}); | ||
} | ||
find.npm(url).then(find.bower).then(function (file) { | ||
aliases.set(url, file); | ||
done({ file: file }); | ||
}); | ||
}; | ||
}; | ||
} | ||
module.exports = exports['default']; | ||
module.exports = index; |
{ | ||
"name": "sass-module-importer", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"main": "lib/index.js", | ||
"jsnext:main": "src/index.js", | ||
"description": "Import Sass files from NPM and Bower Modules", | ||
@@ -24,28 +25,32 @@ "author": "Lucas Motta <mail@lucasmotta.com> (lucasmotta.com)", | ||
], | ||
"engines": { | ||
"node": ">=0.10.0" | ||
}, | ||
"scripts": { | ||
"test": "mocha --compilers js:babel/register", | ||
"compile": "babel -d lib/ src/", | ||
"pretest": "eslint src/index.js test.js", | ||
"prebuild": "npm test", | ||
"build": "rollup -c", | ||
"lint": "eslint src/index.js test.js", | ||
"pretest": "npm run lint", | ||
"test": "BABEL_ENV=test mocha --compilers js:babel-register", | ||
"prepublish": "npm run build", | ||
"preversion": "npm test", | ||
"prepublish": "npm test && npm run compile", | ||
"postpublish": "git push" | ||
"version": "npm run build", | ||
"postversion": "git push && git push --tags" | ||
}, | ||
"devDependencies": { | ||
"babel": "^5.8.3", | ||
"babel-eslint": "^3.1.20", | ||
"chai": "^3.0.0", | ||
"eslint": "^0.24.1", | ||
"eslint-config-mcsaatchi": "^1.0.2", | ||
"mocha": "^2.2.5", | ||
"node-sass": "^3.2.0", | ||
"sass-easing": "^1.0.3" | ||
"babel-preset-es2015": "^6.6.0", | ||
"babel-preset-es2015-rollup": "^1.1.1", | ||
"babel-register": "^6.6.5", | ||
"chai": "^3.5.0", | ||
"eslint": "^2.3.0", | ||
"eslint-config-airbnb": "^6.1.0", | ||
"mocha": "^2.4.5", | ||
"node-sass": "^3.4.2", | ||
"rollup": "^0.25.4", | ||
"rollup-plugin-babel": "^2.4.0", | ||
"rollup-plugin-commonjs": "^2.2.1" | ||
}, | ||
"dependencies": { | ||
"es6-map": "^0.1.1", | ||
"resolve": "^1.1.6", | ||
"es6-map": "0.1.3", | ||
"object-assign": "4.0.1", | ||
"resolve": "1.1.7", | ||
"resolve-bower": "0.0.1" | ||
} | ||
} |
@@ -0,1 +1,3 @@ | ||
[![Build Status](https://travis-ci.org/lucasmotta/sass-module-importer.svg?branch=master)](https://travis-ci.org/lucasmotta/sass-module-importer) | ||
# sass-module-importer | ||
@@ -34,2 +36,10 @@ | ||
Assuming that the external library you are installing fits under one of those categories: | ||
1. Set a SCSS/Sass/CSS file on the "main" field of their package.json/bower.json | ||
2. Set a SCSS/Sass/CSS file on the "style" field of their package.json/bower.json | ||
3. Have a `index.css` file on the root of their module | ||
This tool it will also inline CSS files for you, since Sass [cannot import plain CSS files yet](https://github.com/sass/sass/issues/556). So if the dependency you are using exports a CSS file, it will work too. | ||
## How-to | ||
@@ -69,2 +79,8 @@ | ||
## Options | ||
You can pass any option supported by [node-resolve](https://github.com/substack/node-resolve#resolveid-opts-cb) directly, like this: | ||
```js | ||
moduleImporter({ basedir: path.join(__dirname, 'another-folder') }); | ||
``` | ||
## Tests | ||
@@ -71,0 +87,0 @@ Use `npm test` to run the tests. |
145
test.js
@@ -1,6 +0,4 @@ | ||
/*eslint no-unused-expressions: 0, no-var: 0 */ | ||
/*eslint-env node, mocha */ | ||
/* eslint max-len: 0 */ | ||
import { expect } from 'chai'; | ||
import path from 'path'; | ||
import sass from 'node-sass'; | ||
@@ -10,14 +8,13 @@ import moduleImporter from './src'; | ||
function getCSS(file) { | ||
function getCSS(file, data) { | ||
return new Promise((resolve, reject) => { | ||
sass.render({ | ||
file: `./fixtures/${file}`, | ||
data, | ||
file: file ? `./fixtures/${file}` : null, | ||
outputStyle: 'compressed', | ||
importer: moduleImporter() | ||
importer: moduleImporter({ | ||
basedir: path.join(__dirname, 'fixtures'), | ||
}), | ||
}, (err, res) => err ? reject(err) : resolve(res.css.toString())); | ||
}); | ||
} | ||
@@ -27,69 +24,111 @@ | ||
describe('sass-module-importer', () => { | ||
it('should import npm module', (done) => { | ||
getCSS('npm-module.scss').then((css) => { | ||
expect(css).to.exist | ||
.and.equal('body{transition-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1)}\n'); | ||
it('should import a local file', (done) => { | ||
getCSS(null, '@import "fixtures/dummy";').then((css) => { | ||
const expected = 'body{content:"local"}\n'; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
it('should import bower module', (done) => { | ||
getCSS('bower-module.scss').then((css) => { | ||
expect(css).to.exist | ||
.and.equal('body{background-color:#e51c23}\n'); | ||
it('should import nested files and dependencies', (done) => { | ||
getCSS(null, '@import "test-npm-nested";').then((css) => { | ||
const expected = `*,*:after,*:before{box-sizing:border-box}html,body{margin:0;padding:0}.test{content:"SCSS from 'npm' and from 'style' field."}.child{content:'I am being imported by another file'}.test{content:"SCSS from 'npm' and from 'main' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
it('should import a local file', (done) => { | ||
getCSS('local-file.scss').then((css) => { | ||
expect(css).to.exist.and.equal('body{content:"local"}\n'); | ||
it('should fail to import non-existing module', (done) => { | ||
getCSS(null, '@import "unicorn";').catch((err) => { | ||
const expected = { | ||
message: 'File to import not found or unreadable: unicorn\nParent style sheet: stdin', | ||
}; | ||
expect(err.message).to.exist.and.equal(expected.message); | ||
done(); | ||
}); | ||
}); | ||
describe('npm', () => { | ||
it('should import contents of CSS from npm module using the "main" field', (done) => { | ||
getCSS(null, '@import "test-npm-main-css";').then((css) => { | ||
const expected = `.test{content:"CSS from 'npm' and from 'main' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
it('should import npm, bower and local file', (done) => { | ||
it('should import SCSS from npm module using the "main" field', (done) => { | ||
getCSS(null, '@import "test-npm-main-scss";').then((css) => { | ||
const expected = `.test{content:"SCSS from 'npm' and from 'main' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
getCSS('all.scss').then((css) => { | ||
it('should import contents of CSS from npm module using the "style" field', (done) => { | ||
getCSS(null, '@import "test-npm-style-css";').then((css) => { | ||
const expected = `.test{content:"CSS from 'npm' and from 'style' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
expect(css).to.exist.and.equal('body{content:"local"}body{transition-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1);background-color:#e51c23}\n'); | ||
it('should import SCSS from npm module using the "style" field', (done) => { | ||
getCSS(null, '@import "test-npm-style-scss";').then((css) => { | ||
const expected = `.test{content:"SCSS from 'npm' and from 'style' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
done(); | ||
it('should import "index.css" if the "main" and "style" are undefined', (done) => { | ||
getCSS(null, '@import "test-npm-index-css";').then((css) => { | ||
const expected = `.test{content:"CSS from 'npm' as index.css fallback."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('bower', () => { | ||
it('should import contents of CSS from bower module using the "main" field', (done) => { | ||
getCSS(null, '@import "test-bower-main-css";').then((css) => { | ||
const expected = `.test{content:"CSS from 'bower' and from 'main' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
it('should throw error when importing inexistent module', (done) => { | ||
it('should import SCSS from bower module using the "main" field', (done) => { | ||
getCSS(null, '@import "test-bower-main-scss";').then((css) => { | ||
const expected = `.test{content:"SCSS from 'bower' and from 'main' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
getCSS('no-module.scss').catch((err) => { | ||
it('should import contents of CSS from bower module using the "style" field', (done) => { | ||
getCSS(null, '@import "test-bower-style-css";').then((css) => { | ||
const expected = `.test{content:"CSS from 'bower' and from 'style' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
expect(err).to.be.instanceof(Error); | ||
it('should import SCSS from bower module using the "style" field', (done) => { | ||
getCSS(null, '@import "test-bower-style-scss";').then((css) => { | ||
const expected = `.test{content:"SCSS from 'bower' and from 'style' field."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
done(); | ||
it('should import "index.css" if the "main" and "style" are undefined', (done) => { | ||
getCSS(null, '@import "test-bower-index-css";').then((css) => { | ||
const expected = `.test{content:"CSS from 'bower' as index.css fallback."}\n`; | ||
expect(css).to.exist.and.equal(expected); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
39
252
93
15573
4
11
1
1
+ Addedobject-assign@4.0.1
+ Addedd@0.1.1(transitive)
+ Addedes6-map@0.1.3(transitive)
+ Addedes6-symbol@3.0.2(transitive)
+ Addedobject-assign@4.0.1(transitive)
+ Addedresolve@1.1.7(transitive)
- Removedes6-map@0.1.5(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedhasown@2.0.2(transitive)
- Removedis-core-module@2.15.1(transitive)
- Removedpath-parse@1.0.7(transitive)
- Removedresolve@1.22.8(transitive)
- Removedsupports-preserve-symlinks-flag@1.0.0(transitive)
Updatedes6-map@0.1.3
Updatedresolve@1.1.7