Commit d54aa2d9 by Kevin Martensson

Rewrite lib/index.js

parent 44aaaba4
var path = require('path');
var fs = require('fs');
var assign = require('object-assign');
var fs = require('fs'),
path = require('path');
function requireBinding() {
/**
* Get binding
*
* @api private
*/
function getBinding() {
var v8 = 'v8-' + /[0-9]+\.[0-9]+/.exec(process.versions.v8)[0];
var name = process.platform + '-' + process.arch + '-' + v8;
var candidates = [
[__dirname, '..', 'build', 'Release', 'binding.node'],
[__dirname, '..', 'build', 'Debug', 'binding.node'],
[__dirname, '..', 'bin', process.platform + '-' + process.arch + '-' + v8, 'binding.node']
path.join(__dirname, '..', 'build', 'Release', 'binding.node'),
path.join(__dirname, '..', 'build', 'Debug', 'binding.node'),
path.join(__dirname, '..', 'bin', name, 'binding.node')
];
var candidate;
for (var i = 0, l = candidates.length; i < l; i++) {
candidate = path.join.apply(path.join, candidates[i]);
var candidate = candidates.filter(fs.existsSync)[0];
if (fs.existsSync(candidate)) {
return require(candidate);
}
if (!candidate) {
throw new Error('`libsass` bindings not found. Try reinstalling `node-sass`?');
}
throw new Error('`libsass` bindings not found. Try reinstalling `node-sass`?');
return candidate;
}
var binding = requireBinding();
/**
* Get outfile
*
* @param {Object} options
* @api private
*/
var SASS_OUTPUT_STYLE = {
nested: 0,
expanded: 1,
compact: 2,
compressed: 3
};
function getOutFile(options) {
var file = options.file;
var outFile = options.outFile;
var prepareOptions = function (options) {
var success;
var error;
var stats;
var sourceComments;
var sourceMap;
if (!file || !outFile || typeof outFile !== 'string' || typeof file !== 'string') {
return false;
}
options = options || {};
success = options.success;
error = options.error;
stats = options.stats || {};
if (path.resolve(outFile) !== path.normalize(outFile).replace(new RegExp(path.sep + '$'), '')) {
return false;
}
sourceComments = options.source_comments || options.sourceComments || false;
return path.resolve(path.dirname(file), outFile);
}
if (typeof options.outFile === 'string' && typeof options.file === 'string' && path.resolve(options.outFile) === path.normalize(options.outFile).replace(new RegExp(path.sep + '$'), '' )) {
options.outFile = path.resolve(path.dirname(options.file), options.outFile);
}
/**
* Get stats
*
* @param {Object} options
* @api private
*/
function getStats(options) {
var stats = options.stats;
stats.entry = options.file || 'data';
stats.start = Date.now();
return stats;
}
/**
* End stats
*
* @param {Object} options
* @param {Object} sourceMap
* @api private
*/
function endStats(options, sourceMap) {
var stats = options.stats || {};
stats.end = Date.now();
stats.duration = stats.end - stats.start;
stats.sourceMap = sourceMap;
return stats;
}
/**
* Get style
*
* @param {Object} options
* @api private
*/
function getStyle(options) {
var style = options.output_style || options.outputStyle;
var styles = {
nested: 0,
expanded: 1,
compact: 2,
compressed: 3
};
return styles[style];
}
sourceMap = options.sourceMap;
/**
* Get source map
*
* @param {Object} options
* @api private
*/
function getSourceMap(options) {
var file = options.file;
var outFile = options.outFile;
var sourceMap = options.sourceMap;
if (sourceMap) {
if (typeof sourceMap !== 'string' || !sourceMap.trim()) {
sourceMap = options.outFile ? options.outFile + '.map' : '';
} else if (options.outFile) {
sourceMap = path.resolve(path.dirname(options.file), sourceMap);
if (typeof sourceMap !== 'string') {
sourceMap = outFile ? outFile + '.map' : '';
} else if (outFile) {
sourceMap = path.resolve(path.dirname(file), sourceMap);
}
}
prepareStats(options, stats);
return sourceMap;
}
/**
* Get options
*
* @param {Object} options
* @api private
*/
function getOptions(options) {
options = options || {};
options.comments = options.source_comments || options.sourceComments || false;
options.data = options.data || null;
options.file = options.file || null;
options.imagePath = options.image_path || options.imagePath || '';
options.outFile = getOutFile(options) || null;
options.paths = (options.include_paths || options.includePaths || []).join(path.delimiter);
options.precision = parseInt(options.precision) || 5;
options.sourceMap = getSourceMap(options);
options.stats = options.stats || {};
options.style = getStyle(options) || 0;
if (options.imagePath && typeof options.imagePath !== 'string') {
throw new Error('imagePath needs to be a string');
throw new Error('`imagePath` needs to be a string');
}
return {
file: options.file || null,
outFile: options.outFile || null,
data: options.data || null,
paths: (options.include_paths || options.includePaths || []).join(path.delimiter),
imagePath: options.image_path || options.imagePath || '',
style: SASS_OUTPUT_STYLE[options.output_style || options.outputStyle] || 0,
comments: sourceComments,
omitSourceMapUrl: options.omitSourceMapUrl,
indentedSyntax: options.indentedSyntax,
stats: stats,
sourceMap: sourceMap,
precision: parseInt(options.precision) || 5,
success: function onSuccess(css, sourceMap) {
finishStats(stats, sourceMap);
success && success(css, sourceMap);
},
error: function onError(err, errStatus) {
error && error(err, errStatus);
getStats(options);
var error = options.error;
var success = options.success;
options.error = function(err, code) {
if (error) {
error(err, code);
}
};
};
var prepareStats = function (options, stats) {
stats.entry = options.file || 'data';
stats.start = Date.now();
options.success = function(css, sourceMap) {
endStats(options, sourceMap);
return stats;
};
if (success) {
success(css, sourceMap);
}
};
var finishStats = function (stats, sourceMap) {
stats.end = Date.now();
stats.duration = stats.end - stats.start;
stats.sourceMap = sourceMap;
delete options.image_path;
delete options.include_paths;
delete options.includePaths;
delete options.source_comments;
delete options.sourceComments;
return stats;
};
return options;
}
/**
* Require binding
*/
var deprecatedRender = function(css, callback, options) {
options = prepareOptions(options);
// providing the deprecated single callback signature
options.error = callback;
var binding = require(getBinding());
/**
* Render (deprecated)
*
* @param {String} css
* @param {Function} cb
* @param {Object} options
* @api private
*/
function deprecatedRender(css, cb, options) {
options = getOptions(options);
options.data = css;
options.error = cb;
options.success = function(css) {
callback(null, css);
cb(null, css);
};
options.data = css;
binding.render(options);
};
}
/**
* Render sync (deprecated)
*
* @param {String} css
* @param {Object} options
* @api private
*/
var deprecatedRenderSync = function(css, options) {
options = prepareOptions(options);
function deprecatedRenderSync(css, options) {
options = getOptions(options);
options.data = css;
return binding.renderSync(options);
};
}
/**
* Render
*
* @param {Object} options
* @api public
*/
exports.render = function(options) {
module.exports.render = function(options) {
if (typeof arguments[0] === 'string') {
return deprecatedRender.apply(this, arguments);
}
options = assign({}, options);
options = prepareOptions(options);
options.file? binding.renderFile(options) : binding.render(options);
options = getOptions(options);
options.file ? binding.renderFile(options) : binding.render(options);
};
exports.renderSync = function(options) {
var output;
/**
* Render sync
*
* @param {Object} options
* @api public
*/
module.exports.renderSync = function(options) {
if (typeof arguments[0] === 'string') {
return deprecatedRenderSync.apply(this, arguments);
}
options = assign({}, options);
options = prepareOptions(options);
output = options.file? binding.renderFileSync(options) : binding.renderSync(options);
finishStats(options.stats, options.stats.sourceMap);
var output;
options = getOptions(options);
output = options.file ? binding.renderFileSync(options) : binding.renderSync(options);
endStats(options, options.stats.sourceMap);
return output;
};
/**
Same as `render()` but with an extra `outFile` property in `options` and writes
the CSS and sourceMap (if requested) to the filesystem.
* Render file
*
* `options.sourceMap` can be used to specify that the source map should be saved:
*
* - If falsy the source map will not be saved
* - If `options.sourceMap === true` the source map will be saved to the
* standard location of `options.file + '.map'`
* - Else `options.sourceMap` specifies the path (relative to the `outFile`)
* where the source map should be saved
*
* @param {Object} options
* @api public
*/
`options.sourceMap` can be used to specify that the source map should be saved:
module.exports.renderFile = function(options) {
options = options || {};
- If falsy the source map will not be saved
- If `options.sourceMap === true` the source map will be saved to the
standard location of `options.file + '.map'`
- Else `options.sourceMap` specifies the path (relative to the `outFile`)
where the source map should be saved
*/
exports.renderFile = function(options) {
var success;
var outFile = options.outFile;
var success = options.success;
options = assign({}, options);
success = options.success;
if (options.sourceMap === true) {
options.sourceMap = options.outFile + '.map';
}
options.success = function(css, sourceMap) {
fs.writeFile(options.outFile, css, function(err) {
var dir, sourceMapFile;
options.success = function(css, sourceMap) {
fs.writeFile(outFile, css, function(err) {
if (err) {
return options.error(err);
}
if (options.sourceMap) {
dir = path.dirname(options.outFile);
sourceMapFile = path.resolve(dir, options.sourceMap);
fs.writeFile(sourceMapFile, sourceMap, function(err) {
if (err) {
return options.error(err);
}
success(options.outFile, sourceMapFile);
});
}
else {
success(options.outFile);
if (!options.sourceMap) {
return success(options.outFile);
}
var dir = path.dirname(options.outFile);
var sourceMapFile = path.resolve(dir, options.sourceMap);
fs.writeFile(sourceMapFile, sourceMap, function(err) {
if (err) {
return options.error(err);
}
success(options.outFile, sourceMapFile);
});
});
};
exports.render(options);
module.exports.render(options);
};
exports.middleware = function() {
return new Error('The middleware has been moved to https://github.com/sass/node-sass-middleware');
/**
* Middleware
*
* @api public
*/
module.exports.middleware = function() {
return new Error([
'The middleware has been moved to',
'https://github.com/sass/node-sass-middleware'
].join(' '));
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment