Commit 703c2e4f by Andrew Nesbitt

Merge pull request #500 from kevva/rewrite-index

Rewrite lib/index.js
parents e3804709 d54aa2d9
var path = require('path'); var fs = require('fs'),
var fs = require('fs'); path = require('path');
var assign = require('object-assign');
function requireBinding() { /**
* Get binding
*
* @api private
*/
function getBinding() {
var v8 = 'v8-' + /[0-9]+\.[0-9]+/.exec(process.versions.v8)[0]; var v8 = 'v8-' + /[0-9]+\.[0-9]+/.exec(process.versions.v8)[0];
var name = process.platform + '-' + process.arch + '-' + v8;
var candidates = [ var candidates = [
[__dirname, '..', 'build', 'Release', 'binding.node'], path.join(__dirname, '..', 'build', 'Release', 'binding.node'),
[__dirname, '..', 'build', 'Debug', 'binding.node'], path.join(__dirname, '..', 'build', 'Debug', 'binding.node'),
[__dirname, '..', 'bin', process.platform + '-' + process.arch + '-' + v8, 'binding.node'] path.join(__dirname, '..', 'bin', name, 'binding.node')
]; ];
var candidate;
for (var i = 0, l = candidates.length; i < l; i++) { var candidate = candidates.filter(fs.existsSync)[0];
candidate = path.join.apply(path.join, candidates[i]);
if (!candidate) {
throw new Error('`libsass` bindings not found. Try reinstalling `node-sass`?');
}
return candidate;
}
/**
* Get outfile
*
* @param {Object} options
* @api private
*/
if (fs.existsSync(candidate)) { function getOutFile(options) {
return require(candidate); var file = options.file;
var outFile = options.outFile;
if (!file || !outFile || typeof outFile !== 'string' || typeof file !== 'string') {
return false;
} }
if (path.resolve(outFile) !== path.normalize(outFile).replace(new RegExp(path.sep + '$'), '')) {
return false;
} }
throw new Error('`libsass` bindings not found. Try reinstalling `node-sass`?'); return path.resolve(path.dirname(file), outFile);
} }
var binding = requireBinding(); /**
* 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;
}
var SASS_OUTPUT_STYLE = { /**
* 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, nested: 0,
expanded: 1, expanded: 1,
compact: 2, compact: 2,
compressed: 3 compressed: 3
}; };
var prepareOptions = function (options) {
var success;
var error;
var stats;
var sourceComments;
var sourceMap;
options = options || {};
success = options.success;
error = options.error;
stats = options.stats || {};
sourceComments = options.source_comments || options.sourceComments || false; return styles[style];
}
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 source map
} *
* @param {Object} options
* @api private
*/
sourceMap = options.sourceMap; function getSourceMap(options) {
var file = options.file;
var outFile = options.outFile;
var sourceMap = options.sourceMap;
if (sourceMap) { if (sourceMap) {
if (typeof sourceMap !== 'string' || !sourceMap.trim()) { if (typeof sourceMap !== 'string') {
sourceMap = options.outFile ? options.outFile + '.map' : ''; sourceMap = outFile ? outFile + '.map' : '';
} else if (options.outFile) { } else if (outFile) {
sourceMap = path.resolve(path.dirname(options.file), sourceMap); 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') { 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 { getStats(options);
file: options.file || null,
outFile: options.outFile || null, var error = options.error;
data: options.data || null, var success = options.success;
paths: (options.include_paths || options.includePaths || []).join(path.delimiter),
imagePath: options.image_path || options.imagePath || '', options.error = function(err, code) {
style: SASS_OUTPUT_STYLE[options.output_style || options.outputStyle] || 0, if (error) {
comments: sourceComments, error(err, code);
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);
} }
}; };
};
var prepareStats = function (options, stats) { options.success = function(css, sourceMap) {
stats.entry = options.file || 'data'; endStats(options, sourceMap);
stats.start = Date.now();
return stats; if (success) {
}; success(css, sourceMap);
}
};
var finishStats = function (stats, sourceMap) { delete options.image_path;
stats.end = Date.now(); delete options.include_paths;
stats.duration = stats.end - stats.start; delete options.includePaths;
stats.sourceMap = sourceMap; delete options.source_comments;
delete options.sourceComments;
return stats; return options;
}; }
/**
* Require binding
*/
var deprecatedRender = function(css, callback, options) { var binding = require(getBinding());
options = prepareOptions(options);
// providing the deprecated single callback signature /**
options.error = callback; * 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) { options.success = function(css) {
callback(null, css); cb(null, css);
}; };
options.data = css;
binding.render(options); binding.render(options);
}; }
/**
* Render sync (deprecated)
*
* @param {String} css
* @param {Object} options
* @api private
*/
var deprecatedRenderSync = function(css, options) { function deprecatedRenderSync(css, options) {
options = prepareOptions(options); options = getOptions(options);
options.data = css; options.data = css;
return binding.renderSync(options); return binding.renderSync(options);
}; }
exports.render = function(options) { /**
* Render
*
* @param {Object} options
* @api public
*/
module.exports.render = function(options) {
if (typeof arguments[0] === 'string') { if (typeof arguments[0] === 'string') {
return deprecatedRender.apply(this, arguments); return deprecatedRender.apply(this, arguments);
} }
options = assign({}, options); options = getOptions(options);
options = prepareOptions(options); options.file ? binding.renderFile(options) : binding.render(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') { if (typeof arguments[0] === 'string') {
return deprecatedRenderSync.apply(this, arguments); return deprecatedRenderSync.apply(this, arguments);
} }
options = assign({}, options); var output;
options = prepareOptions(options);
output = options.file? binding.renderFileSync(options) : binding.renderSync(options); options = getOptions(options);
finishStats(options.stats, options.stats.sourceMap); output = options.file ? binding.renderFileSync(options) : binding.renderSync(options);
endStats(options, options.stats.sourceMap);
return output; return output;
}; };
/** /**
Same as `render()` but with an extra `outFile` property in `options` and writes * Render file
the CSS and sourceMap (if requested) to the filesystem. *
* `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 var outFile = options.outFile;
- If `options.sourceMap === true` the source map will be saved to the var success = options.success;
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;
options = assign({}, options);
success = options.success;
if (options.sourceMap === true) { if (options.sourceMap === true) {
options.sourceMap = options.outFile + '.map'; 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) { if (err) {
return options.error(err); return options.error(err);
} }
if (options.sourceMap) {
dir = path.dirname(options.outFile); if (!options.sourceMap) {
sourceMapFile = path.resolve(dir, 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) { fs.writeFile(sourceMapFile, sourceMap, function(err) {
if (err) { if (err) {
return options.error(err); return options.error(err);
} }
success(options.outFile, sourceMapFile); success(options.outFile, sourceMapFile);
}); });
}
else {
success(options.outFile);
}
}); });
}; };
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