Commit 51435f44 by Kevin Martensson

Fix stdin

parent 0b1df747
...@@ -53,9 +53,11 @@ var yargs = require('yargs') ...@@ -53,9 +53,11 @@ var yargs = require('yargs')
type: 'string', type: 'string',
alias: 'help' alias: 'help'
}) })
.check(function(argv){ .check(function(argv) {
if (!argv.stdout && argv.o === undefined && argv._.length === 0) { return false; }
if (argv.help) { return true; } if (argv.help) { return true; }
if (!argv._.length && (process.stdin.isTTY || process.env.isTTY)) {
return false;
}
}); });
// throttle function, used so when multiple files change at the same time // throttle function, used so when multiple files change at the same time
...@@ -63,6 +65,7 @@ var yargs = require('yargs') ...@@ -63,6 +65,7 @@ var yargs = require('yargs')
function throttle(fn) { function throttle(fn) {
var timer; var timer;
var args = Array.prototype.slice.call(arguments, 1); var args = Array.prototype.slice.call(arguments, 1);
return function() { return function() {
var self = this; var self = this;
clearTimeout(timer); clearTimeout(timer);
...@@ -76,110 +79,106 @@ function isSassFile(file) { ...@@ -76,110 +79,106 @@ function isSassFile(file) {
return file.match(/\.(sass|scss)/); return file.match(/\.(sass|scss)/);
} }
exports = module.exports = function(args) { function run(options, emitter) {
var argv = yargs.parse(args);
if (argv.help) {
yargs.showHelp();
process.exit(0);
return;
}
var emitter = new Emitter();
emitter.on('error', function(err){
console.error(err);
process.exit(1);
});
var options = {
stdout: argv.stdout,
omitSourceMapUrl: argv['omit-source-map-url']
};
var inFile = options.inFile = argv._[0];
var outFile = options.outFile = argv.o || argv._[1];
if (!outFile) {
var suffix = '.css';
if (/\.css$/.test(inFile)) {
suffix = '';
}
outFile = options.outFile = path.join(cwd, path.basename(inFile, '.scss') + suffix);
}
// make sure it's an array.
options.includePaths = argv['include-path'];
if (!Array.isArray(options.includePaths)) { if (!Array.isArray(options.includePaths)) {
options.includePaths = [options.includePaths]; options.includePaths = [options.includePaths];
} }
// include the image path.
options.imagePath = argv['image-path'];
// if it's an array, make it a string
options.outputStyle = argv['output-style'];
if (Array.isArray(options.outputStyle)) { if (Array.isArray(options.outputStyle)) {
options.outputStyle = options.outputStyle[0]; options.outputStyle = options.outputStyle[0];
} }
// if it's an array, make it a string
options.sourceComments = argv['source-comments'];
if (Array.isArray(options.sourceComments)) { if (Array.isArray(options.sourceComments)) {
options.sourceComments = options.sourceComments[0]; options.sourceComments = options.sourceComments[0];
} }
// Set the sourceMap path if the sourceComment was 'map', but set source-map was missing if (options.sourceComments === 'map' && !options.sourceMap) {
if (options.sourceComments === 'map' && !argv['source-map']) { options.sourceMap = true;
argv['source-map'] = true;
} }
// set source map file and set sourceComments to 'map' if (options.sourceMap) {
if (argv['source-map']) {
options.sourceComments = 'map'; options.sourceComments = 'map';
if (argv['source-map'] === true) {
options.sourceMap = outFile + '.map'; if (options.sourceMap === true) {
options.sourceMap = options.dest + '.map';
} else { } else {
options.sourceMap = path.resolve(cwd, argv['source-map']); options.sourceMap = path.resolve(cwd, options.sourceMap);
} }
} }
options.precision = argv.precision; if (options.watch) {
var throttledRender = throttle(render, options, emitter);
if (argv.w) { var watchDir = options.watch;
var watchDir = argv.w;
if (watchDir === true) { if (watchDir === true) {
watchDir = []; watchDir = [];
} else if (!Array.isArray(watchDir)) { } else if (!Array.isArray(watchDir)) {
watchDir = [watchDir]; watchDir = [watchDir];
} }
watchDir.push(inFile);
var throttledRender = throttle(render, options, emitter); watchDir.push(options.src);
watch(watchDir, function(file){ watch(watchDir, function(file) {
emitter.emit('warn', '=> changed: '.grey + file.blue); emitter.emit('warn', '=> changed: '.grey + file.blue);
if (isSassFile(file)) { if (isSassFile(file)) {
throttledRender(); throttledRender();
} }
}); });
throttledRender(); throttledRender();
} else { } else {
if (inFile === undefined && args.length > 0) { render(options, emitter);
stdin(function(data){ }
options.data = data.toString().trim(); }
render(options, emitter);
}); module.exports = function(args) {
} else { var argv = yargs.parse(args);
render(options, emitter); var emitter = new Emitter();
var options = {
imagePath: argv['image-path'],
includePaths: argv['include-path'],
omitSourceMapUrl: argv['omit-source-map-url'],
outputStyle: argv['output-style'],
precision: argv.precision,
sourceComments: argv['source-comments'],
sourceMap: argv['source-map'],
stdout: argv.stdout,
watch: argv.w
};
if (argv.help) {
yargs.showHelp();
process.exit();
return;
}
emitter.on('error', function(err) {
console.error(err);
process.exit(1);
});
options.src = argv._[0];
options.dest = argv.o || argv._[1];
if (!options.dest) {
var suffix = '.css';
if (/\.css$/.test(options.src)) {
suffix = '';
} }
options.dest = path.join(cwd, path.basename(options.src, '.scss') + suffix);
}
if (process.stdin.isTTY || process.env.isTTY) {
run(options, emitter);
} else {
stdin(function(data) {
options.data = data;
run(options, emitter);
});
} }
return emitter; return emitter;
}; };
exports.yargs = yargs; module.exports.yargs = yargs;
...@@ -3,59 +3,63 @@ var sass = require('../sass'), ...@@ -3,59 +3,63 @@ var sass = require('../sass'),
fs = require('fs'); fs = require('fs');
function render(options, emitter) { function render(options, emitter) {
var renderOptions = {
sass.render({
file: options.inFile,
data: options.data,
includePaths: options.includePaths,
imagePath: options.imagePath, imagePath: options.imagePath,
includePaths: options.includePaths,
omitSourceMapUrl: options.omitSourceMapUrl,
outFile: options.outFile,
outputStyle: options.outputStyle, outputStyle: options.outputStyle,
sourceComments: options.sourceComments,
sourceMap: options.sourceMap,
precision: options.precision, precision: options.precision,
outFile: options.outFile, sourceComments: options.sourceComments,
omitSourceMapUrl: options.omitSourceMapUrl, sourceMap: options.sourceMap
success: function(css, sourceMap) { };
var todo = 1; if (options.src) {
var done = function() { renderOptions.file = options.src;
if (--todo <= 0) { } else if (options.data) {
emitter.emit('done'); renderOptions.data = options.data;
} }
};
renderOptions.success = function(css, sourceMap) {
// Write to stdout var todo = 1;
if (options.stdout) { var done = function() {
emitter.emit('log', css); if (--todo <= 0) {
return done(); emitter.emit('done');
} }
};
if (options.stdout || (!process.stdout.isTTY && !process.env.isTTY)) {
emitter.emit('log', css);
return done();
}
emitter.emit('warn', chalk.green('Rendering Complete, saving .css file...'));
// Write to disk fs.writeFile(options.dest, css, function(err) {
emitter.emit('warn', chalk.green('Rendering Complete, saving .css file...')); if (err) { return emitter.emit('error', chalk.red('Error: ' + err)); }
emitter.emit('warn', chalk.green('Wrote CSS to ' + options.dest));
emitter.emit('write', err, options.dest, css);
done();
});
fs.writeFile(options.outFile, css, function(err) { if (options.sourceMap) {
if (err) { return emitter.emit('error', chalk.red('Error: ' + err)); } todo++;
emitter.emit('warn', chalk.green('Wrote CSS to ' + options.outFile)); fs.writeFile(options.sourceMap, sourceMap, function(err) {
emitter.emit('write', err, options.outFile, css); if (err) {return emitter.emit('error', chalk.red('Error' + err)); }
emitter.emit('warn', chalk.green('Wrote Source Map to ' + options.sourceMap));
emitter.emit('write-source-map', err, options.sourceMap, sourceMap);
done(); done();
}); });
}
if (options.sourceMap) { emitter.emit('render', css);
todo++; };
fs.writeFile(options.sourceMap, sourceMap, function(err) {
if (err) {return emitter.emit('error', chalk.red('Error' + err)); }
emitter.emit('warn', chalk.green('Wrote Source Map to ' + options.sourceMap));
emitter.emit('write-source-map', err, options.sourceMap, sourceMap);
done();
});
}
emitter.emit('render', css); renderOptions.error = function(error) {
}, emitter.emit('error', chalk.red(error));
error: function(error) { };
emitter.emit('error', chalk.red(error));
} sass.render(renderOptions);
});
} }
module.exports = render; module.exports = render;
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
"coveralls": "^2.11.1", "coveralls": "^2.11.1",
"jscoverage": "^0.5.6", "jscoverage": "^0.5.6",
"jshint": "^2.5.5", "jshint": "^2.5.5",
"mocha-lcov-reporter": "^0.0.1" "mocha-lcov-reporter": "^0.0.1",
"object-assign": "^0.3.1"
} }
} }
...@@ -2,8 +2,8 @@ var path = require('path'), ...@@ -2,8 +2,8 @@ var path = require('path'),
assert = require('assert'), assert = require('assert'),
fs = require('fs'), fs = require('fs'),
exec = require('child_process').exec, exec = require('child_process').exec,
assign = require('object-assign'),
cli = process.env.NODESASS_COVERAGE ? require('../lib-coverage/cli') : require('../lib/cli'), cli = process.env.NODESASS_COVERAGE ? require('../lib-coverage/cli') : require('../lib/cli'),
cliPath = path.resolve(__dirname, '../bin/node-sass'), cliPath = path.resolve(__dirname, '../bin/node-sass'),
sampleFilename = path.resolve(__dirname, 'sample.scss'); sampleFilename = path.resolve(__dirname, 'sample.scss');
...@@ -33,16 +33,21 @@ var sampleCssMapOutputPath = path.join(__dirname, '../sample.css.map'); ...@@ -33,16 +33,21 @@ var sampleCssMapOutputPath = path.join(__dirname, '../sample.css.map');
describe('cli', function() { describe('cli', function() {
it('should print help when run with no arguments', function(done) { it('should print help when run with no arguments', function(done) {
exec('node ' + cliPath, function(err, stdout, stderr) { var env = assign(process.env, { isTTY: true });
exec('node ' + cliPath, {
env: env
}, function(err, stdout, stderr) {
done(assert(stderr.trim().indexOf('Compile .scss files with node-sass') === 0)); done(assert(stderr.trim().indexOf('Compile .scss files with node-sass') === 0));
}); });
}); });
it('should compile sample.scss as sample.css', function(done) { it('should compile sample.scss as sample.css', function(done) {
var env = assign(process.env, { isTTY: true });
var resultPath = path.join(__dirname, 'sample.css'); var resultPath = path.join(__dirname, 'sample.css');
exec('node ' + cliPath + ' ' + sampleFilename, { exec('node ' + cliPath + ' ' + sampleFilename, {
cwd: __dirname cwd: __dirname,
env: env
}, function(err) { }, function(err) {
assert.equal(err, null); assert.equal(err, null);
...@@ -54,10 +59,12 @@ describe('cli', function() { ...@@ -54,10 +59,12 @@ describe('cli', function() {
}); });
it('should compile sample.scss to ../out.css', function(done) { it('should compile sample.scss to ../out.css', function(done) {
var env = assign(process.env, { isTTY: true });
var resultPath = path.resolve(__dirname, '../out.css'); var resultPath = path.resolve(__dirname, '../out.css');
exec('node ' + cliPath + ' ' + sampleFilename + ' ../out.css', { exec('node ' + cliPath + ' ' + sampleFilename + ' ../out.css', {
cwd: __dirname cwd: __dirname,
env: env
}, function(err) { }, function(err) {
assert.equal(err, null); assert.equal(err, null);
...@@ -68,51 +75,51 @@ describe('cli', function() { ...@@ -68,51 +75,51 @@ describe('cli', function() {
}); });
}); });
it('should compile with --include-path option', function(done){ it('should compile with --include-path option', function(done) {
var emitter = cli([ var emitter = cli([
'--include-path', path.join(__dirname, 'lib'), '--include-path', path.join(__dirname, 'lib'),
'--include-path', path.join(__dirname, 'functions'), '--include-path', path.join(__dirname, 'functions'),
path.join(__dirname, 'include_path.scss') path.join(__dirname, 'include_path.scss')
]); ]);
emitter.on('error', done); emitter.on('error', done);
emitter.on('write', function(err, file, css){ emitter.on('write', function(err, file, css) {
assert.equal(css.trim(), 'body {\n background: red;\n color: #0000fe; }'); assert.equal(css.trim(), 'body {\n background: red;\n color: #0000fe; }');
fs.unlink(file, done); fs.unlink(file, done);
}); });
}); });
it('should compile with the --output-style', function(done){ it('should compile with the --output-style', function(done) {
var emitter = cli(['--output-style', 'compressed', sampleScssPath]); var emitter = cli(['--output-style', 'compressed', sampleScssPath]);
emitter.on('error', done); emitter.on('error', done);
emitter.on('write', function(err, file, css){ emitter.on('write', function(err, file, css) {
assert.equal(css, expectedSampleCompressed); assert.equal(css, expectedSampleCompressed);
fs.unlink(file, done); fs.unlink(file, done);
}); });
}); });
it('should compile with the --source-comments option', function(done){ it('should compile with the --source-comments option', function(done) {
var emitter = cli(['--source-comments', 'none', sampleScssPath]); var emitter = cli(['--source-comments', 'none', sampleScssPath]);
emitter.on('error', done); emitter.on('error', done);
emitter.on('write', function(err, file, css){ emitter.on('write', function(err, file, css) {
assert.equal(css, expectedSampleNoComments); assert.equal(css, expectedSampleNoComments);
fs.unlink(file, done); fs.unlink(file, done);
}); });
}); });
it('should compile with the --image-path option', function(done){ it('should compile with the --image-path option', function(done) {
var emitter = cli(['--image-path', '/path/to/images', path.join(__dirname, 'image_path.scss')]); var emitter = cli(['--image-path', '/path/to/images', path.join(__dirname, 'image_path.scss')]);
emitter.on('error', done); emitter.on('error', done);
emitter.on('write', function(err, file, css){ emitter.on('write', function(err, file, css) {
assert.equal(css, expectedSampleCustomImagePath); assert.equal(css, expectedSampleCustomImagePath);
fs.unlink(file, done); fs.unlink(file, done);
}); });
}); });
it('should write the output to the file specified with the --output option', function(done){ it('should write the output to the file specified with the --output option', function(done) {
var resultPath = path.join(__dirname, '../output.css'); var resultPath = path.join(__dirname, '../output.css');
var emitter = cli(['--output', resultPath, sampleScssPath]); var emitter = cli(['--output', resultPath, sampleScssPath]);
emitter.on('error', done); emitter.on('error', done);
emitter.on('write', function(){ emitter.on('write', function() {
fs.exists(resultPath, function(exists) { fs.exists(resultPath, function(exists) {
assert(exists); assert(exists);
fs.unlink(resultPath, done); fs.unlink(resultPath, done);
...@@ -120,19 +127,19 @@ describe('cli', function() { ...@@ -120,19 +127,19 @@ describe('cli', function() {
}); });
}); });
it('should write to stdout with the --stdout option', function(done){ it('should write to stdout with the --stdout option', function(done) {
var emitter = cli(['--stdout', sampleScssPath]); var emitter = cli(['--stdout', sampleScssPath]);
emitter.on('error', done); emitter.on('error', done);
emitter.on('log', function(css){ emitter.on('log', function(css) {
assert.equal(css, expectedSampleNoComments); assert.equal(css, expectedSampleNoComments);
done(); done();
}); });
}); });
it('should not write to disk with the --stdout option', function(done){ it('should not write to disk with the --stdout option', function(done) {
var emitter = cli(['--stdout', sampleScssPath]); var emitter = cli(['--stdout', sampleScssPath]);
emitter.on('error', done); emitter.on('error', done);
emitter.on('done', function(){ emitter.on('done', function() {
fs.exists(sampleCssOutputPath, function(exists) { fs.exists(sampleCssOutputPath, function(exists) {
assert(!exists); assert(!exists);
if (exists) {fs.unlinkSync(sampleCssOutputPath);} if (exists) {fs.unlinkSync(sampleCssOutputPath);}
...@@ -141,9 +148,12 @@ describe('cli', function() { ...@@ -141,9 +148,12 @@ describe('cli', function() {
}); });
}); });
it('should not exit with the --watch option', function(done){ it('should not exit with the --watch option', function(done) {
var command = cliPath + ' --watch ' + sampleScssPath; var command = cliPath + ' --watch ' + sampleScssPath;
var child = exec('node ' + command); var env = assign(process.env, { isTTY: true });
var child = exec('node ' + command, {
env: env
});
var exited = false; var exited = false;
child.on('exit', function() { child.on('exit', function() {
...@@ -160,7 +170,7 @@ describe('cli', function() { ...@@ -160,7 +170,7 @@ describe('cli', function() {
}, 100); }, 100);
}); });
it('should compile with the --source-map option', function(done){ it('should compile with the --source-map option', function(done) {
var emitter = cli([sampleScssPath, '--source-map']); var emitter = cli([sampleScssPath, '--source-map']);
emitter.on('error', done); emitter.on('error', done);
emitter.on('write-source-map', function(err, file) { emitter.on('write-source-map', function(err, file) {
...@@ -197,7 +207,7 @@ describe('cli', function() { ...@@ -197,7 +207,7 @@ describe('cli', function() {
}); });
}); });
it('should compile a sourceMap if --source-comments="map", but the --source-map option is excluded', function(done){ it('should compile a sourceMap if --source-comments="map", but the --source-map option is excluded', function(done) {
var emitter = cli([sampleScssPath, '--source-comments', 'map']); var emitter = cli([sampleScssPath, '--source-comments', 'map']);
emitter.on('error', done); emitter.on('error', done);
emitter.on('write-source-map', function(err, file) { emitter.on('write-source-map', function(err, file) {
...@@ -214,15 +224,4 @@ describe('cli', function() { ...@@ -214,15 +224,4 @@ describe('cli', function() {
}); });
}); });
}); });
it('should compile with input from stdin', function(done){
var emitter = cli(['--stdout']);
emitter.on('error', done);
emitter.on('log', function(css){
done(assert.equal(css, '#navbar ul {\n list-style-type: none; }\n'));
});
process.stdin.emit('data', '#navbar ul{list-style-type:none;}');
process.stdin.emit('end');
});
}); });
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