Socket
Socket
Sign inDemoInstall

sass-loader

Package Overview
Dependencies
Maintainers
3
Versions
107
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sass-loader - npm Package Compare versions

Comparing version 0.5.0 to 1.0.0

CHANGELOG.md

206

index.js

@@ -6,12 +6,128 @@ 'use strict';

var path = require('path');
var sassGraph = require('sass-graph');
var os = require('os');
var fs = require('fs');
// A typical sass error looks like this
var SassError = {
message: 'invalid property name',
column: 14,
line: 1,
file: 'stdin',
status: 1
};
/**
* The sass-loader makes node-sass available to webpack modules.
*
* @param {String} content
* @returns {*}
*/
module.exports = function (content) {
this.cacheable();
var callback = this.async();
var isSync = typeof callback !== 'function';
var self = this;
var resourcePath = this.resourcePath;
var fileExt;
var opt;
var opt = utils.parseQuery(this.query);
/**
* Enhances the sass error with additional information about what actually went wrong.
*
* @param {SassError} err
*/
function formatSassError(err) {
var msg = err.message;
if (err.file === 'stdin') {
err.file = resourcePath;
}
// The 'Current dir' hint of node-sass does not help us, we're providing
// additional information by reading the err.file property
msg = msg.replace(/\s*Current dir:\s*/, '');
err.message = getFileExcerptIfPossible(err) +
msg.charAt(0).toUpperCase() + msg.slice(1) + os.EOL +
' in ' + err.file + ' (line ' + err.line + ', column ' + err.column + ')';
// Instruct webpack to hide the JS stack from the console
// Usually you're only interested in the SASS stack in this case.
err.hideStack = true;
}
/**
* Returns an importer that uses webpack's resolving algorithm.
*
* It's important that the returned function has the correct number of arguments
* (based on whether the call is sync or async) because otherwise node-sass doesn't exit.
*
* @returns {Function}
*/
function getWebpackImporter() {
if (isSync) {
return function syncWebpackImporter(url, context) {
var filename;
url = urlToRequest(url);
context = normalizeContext(context);
try {
filename = self.resolveSync(context, url);
self.dependency && self.dependency(filename);
} catch (err) {
// Unfortunately we can't return an error inside a custom importer yet
// @see https://github.com/sass/node-sass/issues/651#issuecomment-73317319
filename = url;
}
return {
file: filename
};
};
}
return function asyncWebpackImporter(url, context, done) {
url = urlToRequest(url);
context = normalizeContext(context);
self.resolve(context, url, function onWebpackResolve(err, filename) {
if (err) {
// Unfortunately we can't return an error inside a custom importer yet
// @see https://github.com/sass/node-sass/issues/651#issuecomment-73317319
filename = url;
} else {
self.dependency && self.dependency(filename);
}
// Use self.loadModule() before calling done() to make imported files available to
// other webpack tools like postLoaders etc.?
done({
file: filename
});
});
};
}
function urlToRequest(url) {
// Add file extension if it's not present already
if (url.slice(-fileExt.length) !== fileExt) {
url = url + fileExt;
}
return utils.urlToRequest(url, opt.root);
}
function normalizeContext(context) {
// The first file is 'stdin' when we're using the data option
if (context === 'stdin') {
context = resourcePath;
}
return path.dirname(context);
}
this.cacheable();
opt = utils.parseQuery(this.query);
opt.data = content;
// skip empty files, otherwise it will stop webpack, see issue #21
// Skip empty files, otherwise it will stop webpack, see issue #21
if (opt.data.trim() === '') {

@@ -21,10 +137,3 @@ return callback(null, content);

// set include path to fix imports
opt.includePaths = opt.includePaths || [];
opt.includePaths.push(path.dirname(this.resourcePath));
if (this.options.resolve && this.options.resolve.root) {
var root = [].concat(this.options.resolve.root);
opt.includePaths = opt.includePaths.concat(root);
}
// opt.outputStyle
if (!opt.outputStyle && this.minimize) {

@@ -34,3 +143,4 @@ opt.outputStyle = 'compressed';

// not using the `this.sourceMap` flag because css source maps are different
// opt.sourceMap
// Not using the `this.sourceMap` flag because css source maps are different
// @see https://github.com/webpack/css-loader/pull/40

@@ -44,29 +154,32 @@ if (opt.sourceMap) {

var loadPaths = opt.includePaths;
var markDependencies = function () {
// indentedSyntax is a boolean flag
opt.indentedSyntax = Boolean(opt.indentedSyntax);
fileExt = '.' + (opt.indentedSyntax? 'sass' : 'scss');
// opt.importer
opt.importer = getWebpackImporter();
// start the actual rendering
if (isSync) {
try {
var graph = sassGraph.parseFile(this.resourcePath, {loadPaths: loadPaths});
graph.visitDescendents(this.resourcePath, function (imp) {
this.addDependency(imp);
}.bind(this));
return sass.renderSync(opt).css.toString();
} catch (err) {
this.emitError(err);
formatSassError(err);
throw err;
}
}.bind(this);
sass.render(opt, function(err, result) {
if(err) {
markDependencies();
callback({message: err.message + ' (' + err.line + ':' + err.column + ')'});
}
sass.render(opt, function onRender(err, result) {
if (err) {
formatSassError(err);
callback(err);
return;
}
markDependencies();
if (result.map && result.map !== '{}') {
result.map = JSON.parse(result.map);
result.map.file = utils.getCurrentRequest(this);
// the first source is 'stdin' according to libsass because we've used the data input
// now let's override that value with the correct relative path
result.map.sources[0] = path.relative(this.options.output.path, utils.getRemainingRequest(this));
result.map.file = resourcePath;
// The first source is 'stdin' according to libsass because we've used the data input
// Now let's override that value with the correct relative path
result.map.sources[0] = path.relative(self.options.output.path, resourcePath);
} else {

@@ -76,4 +189,29 @@ result.map = null;

callback(null, result.css, result.map);
}.bind(this));
callback(null, result.css.toString(), result.map);
});
};
/**
* Tries to get an excerpt of the file where the error happened.
* Uses err.line and err.column.
*
* Returns an empty string if the excerpt could not be retrieved.
*
* @param {SassError} err
* @returns {string}
*/
function getFileExcerptIfPossible(err) {
var content;
try {
content = fs.readFileSync(err.file, 'utf8');
return os.EOL +
content.split(os.EOL)[err.line - 1] + os.EOL +
new Array(err.column - 1).join(' ') + '^' + os.EOL +
' ';
} catch (err) {
// If anything goes wrong here, we don't want any errors to be reported to the user
return '';
}
}

22

package.json
{
"name": "sass-loader",
"version": "0.5.0",
"description": "SASS loader for Webpack",
"version": "1.0.0",
"description": "Sass loader for webpack",
"main": "index.js",

@@ -9,6 +9,9 @@ "scripts": {

"test": "mocha -R spec",
"test-source-map": "webpack --config test/sourceMap/webpack.config.js && open ./test/sourceMap/index.html"
"test-source-map": "webpack-dev-server --config test/sourceMap/webpack.config.js --content-base ./test/sourceMap",
"test-watch": "webpack --config test/watch/webpack.config.js",
"test-hmr": "webpack-dev-server --config test/hmr/webpack.config.js --content-base ./test/hmr --hot --inline"
},
"keywords": [
"sass",
"libsass",
"webpack",

@@ -23,15 +26,20 @@ "loader"

"license": "MIT",
"peerDependencies": {
"node-sass": "^3.0.0-alpha.0"
},
"dependencies": {
"loader-utils": "^0.2.5",
"node-sass": "^3.0.0-pre",
"sass-graph": "^1.0.3"
"loader-utils": "^0.2.5"
},
"devDependencies": {
"css-loader": "^0.9.1",
"enhanced-require": "^0.5.0-beta6",
"extract-text-webpack-plugin": "^0.3.8",
"mocha": "^2.0.1",
"node-sass": "^3.0.0-alpha.0",
"raw-loader": "^0.5.1",
"should": "^5.0.1",
"webpack": "^1.4.0"
"style-loader": "^0.8.3",
"webpack": "^1.4.0",
"webpack-dev-server": "^1.7.0"
}
}

@@ -1,2 +0,2 @@

# sass loader for [webpack](http://webpack.github.io/)
# Sass loader for [webpack](http://webpack.github.io/)

@@ -7,2 +7,4 @@ ## Install

Starting with `1.0.0`, the sass-loader requires [node-sass](https://github.com/sass/node-sass) as [`peerDependency`](https://docs.npmjs.com/files/package.json#peerdependencies). Thus you are able to specify the required version accurately.
## Usage

@@ -44,5 +46,5 @@

### SASS options
### Sass options
You can pass any SASS specific configuration options through to the render function via [query parameters](http://webpack.github.io/docs/using-loaders.html#query-parameters).
You can pass any Sass specific configuration options through to the render function via [query parameters](http://webpack.github.io/docs/using-loaders.html#query-parameters).

@@ -68,5 +70,15 @@ ``` javascript

### Imports
webpack provides an [advanced mechanism to resolve files](http://webpack.github.io/docs/resolving.html). The sass-loader uses node-sass' custom importer feature to pass all queries to the webpack resolving engine. Thus you can import your sass-modules from `node_modules`. Just prepend them with a `~` which tells webpack to look-up the [`modulesDirectories`](http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories)
```css
@import "~bootstrap/less/bootstrap";
```
It's important to only prepend it with `~`, because `~/` resolves to the home-directory. webpack needs to distinguish between `bootstrap` and `~bootstrap` because CSS- and Sass-files have no special syntax for importing relative files. Writing `@import "file"` is the same as `@import "./file";`
### .sass files
For requiring `.sass` files, add `indentedSyntax=sass` as a loader option:
For requiring `.sass` files, add `indentedSyntax` as a loader option:

@@ -80,3 +92,3 @@ ``` javascript

// Passing indentedSyntax query param to node-sass
loader: "style!css!sass?indentedSyntax=sass"
loader: "style!css!sass?indentedSyntax"
}

@@ -90,3 +102,3 @@ ]

Because of browser limitations, source maps are only available in conjunction with the [extract-text-webpack-plugin](https://github.com/webpack/extract-text-webpack-plugin). Use that plugin to extract the CSS code from the generated JS bundle into a separate file (which even improves the perceived performance because JS and CSS are loaded in parallel).
Because of browser limitations, source maps are only available in conjunction with the [extract-text-webpack-plugin](https://github.com/webpack/extract-text-webpack-plugin). Use that plugin to extract the CSS code from the generated JS bundle into a separate file (which even improves the perceived performance because JS and CSS are downloaded in parallel).

@@ -121,11 +133,6 @@ Then your `webpack.config.js` should look like this:

If you want to view the original SASS files inside Chrome and even edit it, [there's a good blog post](https://medium.com/@toolmantim/getting-started-with-css-sourcemaps-and-in-browser-sass-editing-b4daab987fb0). Checkout [test/sourceMap](https://github.com/jtangelder/sass-loader/tree/master/test) for a running example. Make sure to serve the content with an HTTP server.
If you want to view the original Sass files inside Chrome and even edit it, [there's a good blog post](https://medium.com/@toolmantim/getting-started-with-css-sourcemaps-and-in-browser-sass-editing-b4daab987fb0). Checkout [test/sourceMap](https://github.com/jtangelder/sass-loader/tree/master/test) for a running example. Make sure to serve the content with an HTTP server.
## Caveats
Currently the sass-loader does not follow all of the webpack loader guidelines. The general problem is that the entry scss-file is passed to [node-sass](https://github.com/sass/node-sass) which does pretty much the rest. Thus `@import` statements inside your scss-files cannot be resolved by webpack's resolver. However, there is an [issue for that missing feature in libsass](https://github.com/sass/libsass/issues/21).
## License
MIT (http://www.opensource.org/licenses/mit-license.php)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc