Commit 1c65c537 by Adeel

CLI: Adds source-map=directory support.

* For multi-file compilation.
* Written test.
* Usage:

  ```javascript
  node-sass --source-map source-map/dir --output css/path style/src/
  ```

Issue URL: #903.
PR URL: #964.
parent 58a85a02
...@@ -106,7 +106,7 @@ var cli = meow({ ...@@ -106,7 +106,7 @@ var cli = meow({
function isDirectory(filePath) { function isDirectory(filePath) {
var isDir = false; var isDir = false;
try { try {
var absolutePath = path.resolve(process.cwd(), filePath); var absolutePath = path.resolve(filePath);
isDir = fs.lstatSync(absolutePath).isDirectory(); isDir = fs.lstatSync(absolutePath).isDirectory();
} catch (e) { } catch (e) {
isDir = e.code === 'ENOENT'; isDir = e.code === 'ENOENT';
...@@ -173,20 +173,44 @@ function getOptions(args, options) { ...@@ -173,20 +173,44 @@ function getOptions(args, options) {
options.src = args[0]; options.src = args[0];
if (args[1]) { if (args[1]) {
options.dest = path.resolve(process.cwd(), args[1]); options.dest = path.resolve(args[1]);
} else if (options.output) { } else if (options.output) {
options.dest = path.join( options.dest = path.join(
path.resolve(process.cwd(), options.output), path.resolve(options.output),
[path.basename(options.src, path.extname(options.src)), '.css'].join('')); // replace ext. [path.basename(options.src, path.extname(options.src)), '.css'].join('')); // replace ext.
} }
if (options.directory) { if (options.directory) {
var sassDir = path.resolve(process.cwd(), options.directory); var sassDir = path.resolve(options.directory);
var file = path.relative(sassDir, args[0]); var file = path.relative(sassDir, args[0]);
var cssDir = path.resolve(process.cwd(), options.output); var cssDir = path.resolve(options.output);
options.dest = path.join(cssDir, file).replace(path.extname(file), '.css'); options.dest = path.join(cssDir, file).replace(path.extname(file), '.css');
} }
if (options.sourceMap) {
if(!options.sourceMapOriginal) {
options.sourceMapOriginal = options.sourceMap;
}
// check if sourceMap path ends with .map to avoid isDirectory false-positive
var sourceMapIsDirectory = options.sourceMapOriginal.indexOf('.map', options.sourceMapOriginal.length - 4) === -1 && isDirectory(options.sourceMapOriginal);
if (options.sourceMapOriginal === 'true') {
options.sourceMap = options.dest + '.map';
} else if (!sourceMapIsDirectory) {
options.sourceMap = path.resolve(options.sourceMapOriginal);
} else if (sourceMapIsDirectory) {
if (!options.directory) {
options.sourceMap = path.resolve(options.sourceMapOriginal, path.basename(options.dest) + '.map');
} else {
var sassDir = path.resolve(options.directory);
var file = path.relative(sassDir, args[0]);
var mapDir = path.resolve(options.sourceMapOriginal);
options.sourceMap = path.join(mapDir, file).replace(path.extname(file), '.css.map');
}
}
}
return options; return options;
} }
...@@ -201,7 +225,7 @@ function getOptions(args, options) { ...@@ -201,7 +225,7 @@ function getOptions(args, options) {
function watch(options, emitter) { function watch(options, emitter) {
var watch = []; var watch = [];
var graphOptions = {loadPaths: options.includePath}; var graphOptions = { loadPaths: options.includePath };
var graph; var graph;
if (options.directory) { if (options.directory) {
graph = grapher.parseDir(options.directory, graphOptions); graph = grapher.parseDir(options.directory, graphOptions);
...@@ -253,24 +277,15 @@ function run(options, emitter) { ...@@ -253,24 +277,15 @@ function run(options, emitter) {
} }
} }
if (options.sourceMap) { if (options.sourceMapOriginal && options.directory && !isDirectory(options.sourceMapOriginal) && options.sourceMapOriginal !== 'true') {
if (options.sourceMap === 'true') { emitter.emit('error', 'Multi-file compilation: requires sourceMap to be a directory or "true".');
if (options.dest) {
options.sourceMap = options.dest + '.map';
} else {
// replace ext.
options.sourceMap = [path.basename(options.src, path.extname(options.src)), '.css.map'].join('');
}
} else {
options.sourceMap = path.resolve(process.cwd(), options.sourceMap);
}
} }
if (options.importer) { if (options.importer) {
if ((path.resolve(options.importer) === path.normalize(options.importer).replace(/(.+)([\/|\\])$/, '$1'))) { if ((path.resolve(options.importer) === path.normalize(options.importer).replace(/(.+)([\/|\\])$/, '$1'))) {
options.importer = require(options.importer); options.importer = require(options.importer);
} else { } else {
options.importer = require(path.resolve(process.cwd(), options.importer)); options.importer = require(path.resolve(options.importer));
} }
} }
...@@ -278,7 +293,7 @@ function run(options, emitter) { ...@@ -278,7 +293,7 @@ function run(options, emitter) {
if ((path.resolve(options.functions) === path.normalize(options.functions).replace(/(.+)([\/|\\])$/, '$1'))) { if ((path.resolve(options.functions) === path.normalize(options.functions).replace(/(.+)([\/|\\])$/, '$1'))) {
options.functions = require(options.functions); options.functions = require(options.functions);
} else { } else {
options.functions = require(path.resolve(process.cwd(), options.functions)); options.functions = require(path.resolve(options.functions));
} }
} }
...@@ -315,13 +330,14 @@ function renderFile(file, options, emitter) { ...@@ -315,13 +330,14 @@ function renderFile(file, options, emitter) {
* @api private * @api private
*/ */
function renderDir(options, emitter) { function renderDir(options, emitter) {
var globPath = path.resolve(process.cwd(), options.directory, globPattern(options)); var globPath = path.resolve(options.directory, globPattern(options));
glob(globPath, {ignore: '**/_*'}, function(err, files) { glob(globPath, { ignore: '**/_*' }, function(err, files) {
if(err) { if (err) {
return emitter.emit('error', util.format('You do not have permission to access this path: %s.', err.path)); return emitter.emit('error', util.format('You do not have permission to access this path: %s.', err.path));
} else if(!files.length) { } else if (!files.length) {
return emitter.emit('error', 'No input file was found.'); return emitter.emit('error', 'No input file was found.');
} }
forEach(files, function(subject) { forEach(files, function(subject) {
emitter.once('done', this.async()); emitter.once('done', this.async());
renderFile(subject, options, emitter); renderFile(subject, options, emitter);
...@@ -359,7 +375,7 @@ if (!options.src && process.stdin.isTTY) { ...@@ -359,7 +375,7 @@ if (!options.src && process.stdin.isTTY) {
*/ */
if (options.src) { if (options.src) {
if (isDirectory(options.src)){ if (isDirectory(options.src)) {
options.directory = options.src; options.directory = options.src;
} }
run(options, emitter); run(options, emitter);
......
...@@ -81,6 +81,10 @@ module.exports = function(options, emitter) { ...@@ -81,6 +81,10 @@ module.exports = function(options, emitter) {
if (options.sourceMap) { if (options.sourceMap) {
todo++; todo++;
mkdirp(path.dirname(options.sourceMap), function(err) {
if (err) {
return emitter.emit('error', chalk.red(err));
}
fs.writeFile(options.sourceMap, result.map, function(err) { fs.writeFile(options.sourceMap, result.map, function(err) {
if (err) { if (err) {
return emitter.emit('error', chalk.red('Error' + err)); return emitter.emit('error', chalk.red('Error' + err));
...@@ -90,6 +94,7 @@ module.exports = function(options, emitter) { ...@@ -90,6 +94,7 @@ module.exports = function(options, emitter) {
emitter.emit('write-source-map', err, options.sourceMap, result.map); emitter.emit('write-source-map', err, options.sourceMap, result.map);
done(); done();
}); });
});
} }
emitter.emit('render', result.css.toString()); emitter.emit('render', result.css.toString());
......
...@@ -324,9 +324,9 @@ describe('cli', function() { ...@@ -324,9 +324,9 @@ describe('cli', function() {
'--watch', srcDir '--watch', srcDir
]); ]);
setTimeout(function () { setTimeout(function() {
fs.appendFileSync(srcFile, 'a {color:green;}\n'); fs.appendFileSync(srcFile, 'a {color:green;}\n');
setTimeout(function () { setTimeout(function() {
bin.kill(); bin.kill();
var files = fs.readdirSync(destDir); var files = fs.readdirSync(destDir);
assert.deepEqual(files, ['index.css']); assert.deepEqual(files, ['index.css']);
...@@ -420,7 +420,7 @@ describe('cli', function() { ...@@ -420,7 +420,7 @@ describe('cli', function() {
}); });
}); });
it('it should compile all files in the folder', function(done) { it('should compile all files in the folder', function(done) {
var src = fixture('input-directory/sass'); var src = fixture('input-directory/sass');
var dest = fixture('input-directory/css'); var dest = fixture('input-directory/css');
var bin = spawn(cli, [src, '--output', dest]); var bin = spawn(cli, [src, '--output', dest]);
...@@ -435,6 +435,22 @@ describe('cli', function() { ...@@ -435,6 +435,22 @@ describe('cli', function() {
}); });
}); });
it('should compile with --source-map set to directory', function(done) {
var src = fixture('input-directory/sass');
var dest = fixture('input-directory/css');
var destMap = fixture('input-directory/map');
var bin = spawn(cli, [src, '--output', dest, '--source-map', destMap]);
bin.once('close', function() {
var map = JSON.parse(read(fixture('input-directory/map/nested/three.css.map'), 'utf8'));
assert.equal(map.file, '../../css/nested/three.css');
rimraf.sync(dest);
rimraf.sync(destMap);
done();
});
});
it('should skip files with an underscore', function(done) { it('should skip files with an underscore', function(done) {
var src = fixture('input-directory/sass'); var src = fixture('input-directory/sass');
var dest = fixture('input-directory/css'); var dest = fixture('input-directory/css');
......
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