From db60dffb300be4767e261662c523d8554ee5b16c Mon Sep 17 00:00:00 2001 From: Conrad Zimmerman Date: Sat, 24 May 2014 11:33:23 -0400 Subject: [PATCH 1/2] Apply original source maps from source files --- index.js | 2 +- lib/source-map-support.js | 45 +++++++++++++++++++++++++++++++++++++++ package.json | 3 ++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 7c3dbc4..ccd4204 100644 --- a/index.js +++ b/index.js @@ -33,10 +33,10 @@ module.exports = function(node, options){ sourcemaps(compiler); var code = compiler.compile(node); + compiler.applySourceMaps(); return { code: code, map: compiler.map.toJSON() }; } var code = compiler.compile(node); return code; }; - diff --git a/lib/source-map-support.js b/lib/source-map-support.js index 1e60513..07006cd 100644 --- a/lib/source-map-support.js +++ b/lib/source-map-support.js @@ -4,6 +4,9 @@ */ var SourceMap = require('source-map').SourceMapGenerator; +var SourceMapConsumer = require('source-map').SourceMapConsumer; +var sourceMapResolve = require('source-map-resolve'); +var fs = require('fs'); /** * Expose `mixin()`. @@ -20,8 +23,10 @@ module.exports = mixin; function mixin(compiler) { var file = compiler.options.filename || 'generated.css'; + compiler._comment = compiler.comment; compiler.map = new SourceMap({ file: file }); compiler.position = { line: 1, column: 1 }; + compiler.files = {}; for (var k in exports) compiler[k] = exports[k]; } @@ -62,6 +67,7 @@ exports.emit = function(str, pos, startOnly) { column: pos.start.column - 1 } }); + this.addFile(pos); } this.updatePosition(str); @@ -78,7 +84,46 @@ exports.emit = function(str, pos, startOnly) { column: pos.end.column - 1 } }); + this.addFile(pos); } return str; }; + +/** + * Adds a file to the source map output if it has not already been added + * @param {Object} pos + */ + +exports.addFile = function(pos) { + var file = pos.source || 'source.css'; + if (this.files.hasOwnProperty(file)) return; + this.files[file] = pos.content; +}; + +/** + * Applies any original source maps to the output. + */ + +exports.applySourceMaps = function() { + for (var file in this.files) { + var originalMap = sourceMapResolve.resolveSync( + this.files[file], file, fs.readFileSync); + if (originalMap) { + originalMap = new SourceMapConsumer(originalMap.map); + this.map.applySourceMap(originalMap, file); + } + } +}; + +/** + * Process comments, drops sourceMap comments. + * @param {Object} node + */ + +exports.comment = function(node) { + if (/^# sourceMappingURL=/.test(node.comment)) + return this.emit('', node.position); + else + return this._comment(node); +}; diff --git a/package.json b/package.json index d1771a7..8803ce7 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "test": "make test" }, "dependencies": { - "source-map": "~0.1.31" + "source-map": "~0.1.31", + "source-map-resolve": "^0.1.3" } } From 5bcca096aca7c483164c6e846fe3f9d27cb6f8ce Mon Sep 17 00:00:00 2001 From: Conrad Zimmerman Date: Sat, 24 May 2014 13:13:06 -0400 Subject: [PATCH 2/2] Add tests for applying source maps and refactor --- lib/source-map-support.js | 7 ++++--- test/cases/source-map-apply.scss | 0 test/css-stringify.js | 24 ++++++++++++++++++++++++ test/source-map-apply.css | 4 ++++ test/source-map-apply.css.map | 7 +++++++ test/source-map-apply.scss | 1 + 6 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 test/cases/source-map-apply.scss create mode 100644 test/source-map-apply.css create mode 100644 test/source-map-apply.css.map create mode 100644 test/source-map-apply.scss diff --git a/lib/source-map-support.js b/lib/source-map-support.js index 07006cd..614b1b8 100644 --- a/lib/source-map-support.js +++ b/lib/source-map-support.js @@ -97,7 +97,8 @@ exports.emit = function(str, pos, startOnly) { exports.addFile = function(pos) { var file = pos.source || 'source.css'; - if (this.files.hasOwnProperty(file)) return; + if (Object.prototype.hasOwnProperty.call(this.files, file)) return; + if (typeof pos.content !== 'string') return; this.files[file] = pos.content; }; @@ -106,14 +107,14 @@ exports.addFile = function(pos) { */ exports.applySourceMaps = function() { - for (var file in this.files) { + Object.keys(this.files).forEach(function(file) { var originalMap = sourceMapResolve.resolveSync( this.files[file], file, fs.readFileSync); if (originalMap) { originalMap = new SourceMapConsumer(originalMap.map); this.map.applySourceMap(originalMap, file); } - } + }, this); }; /** diff --git a/test/cases/source-map-apply.scss b/test/cases/source-map-apply.scss new file mode 100644 index 0000000..e69de29 diff --git a/test/css-stringify.js b/test/css-stringify.js index b37ee7f..32e2474 100644 --- a/test/css-stringify.js +++ b/test/css-stringify.js @@ -67,4 +67,28 @@ describe('stringify(obj, {sourcemap: true})', function(){ map.originalPositionFor({ line: 1, column: 50 }).should.eql(locs.mediaBlock); map.originalPositionFor({ line: 1, column: 64 }).should.eql(locs.mediaOnly); }); + + it('should apply included source maps', function(){ + var file = 'test/source-map-apply.css'; + var src = read(file, 'utf8'); + var stylesheet = parse(src, { source: file, position: true }); + var result = stringify(stylesheet, { sourcemap: true }); + result.should.have.property('code'); + result.should.have.property('map'); + + var map = new SourceMapConsumer(result.map); + map.originalPositionFor({ line: 1, column: 0 }).should.eql({ + column: 0, + line: 1, + name: null, + source: 'source-map-apply.scss' + }); + + map.originalPositionFor({ line: 2, column: 2 }).should.eql({ + column: 7, + line: 1, + name: null, + source: 'source-map-apply.scss' + }); + }); }); diff --git a/test/source-map-apply.css b/test/source-map-apply.css new file mode 100644 index 0000000..5f11212 --- /dev/null +++ b/test/source-map-apply.css @@ -0,0 +1,4 @@ +tobi { + name: 'tobi'; } + +/*# sourceMappingURL=source-map-apply.css.map */ \ No newline at end of file diff --git a/test/source-map-apply.css.map b/test/source-map-apply.css.map new file mode 100644 index 0000000..066c1f5 --- /dev/null +++ b/test/source-map-apply.css.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "file": "", + "sources": ["source-map-apply.scss"], + "names": [], + "mappings": "AAAA;EAAO,MAAM" +} \ No newline at end of file diff --git a/test/source-map-apply.scss b/test/source-map-apply.scss new file mode 100644 index 0000000..7ad3ef5 --- /dev/null +++ b/test/source-map-apply.scss @@ -0,0 +1 @@ +tobi { name: 'tobi'; }