From ebac9a2305998ea545489941ac418664b692dfaf Mon Sep 17 00:00:00 2001 From: Carlos Correa Date: Sat, 4 Apr 2015 18:55:23 -0700 Subject: [PATCH] feature: use node-sass's importer hook to help tools track dependencies. --- lib/index.js | 12 ++++++++ package.json | 7 +++-- test/fixtures/_settings.scss | 1 + test/fixtures/_settings.scss.new | 1 + test/fixtures/main.scss | 1 + test/fixtures/something.scss | 5 ++++ test/importer.js | 50 ++++++++++++++++++++++++++++++++ 7 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/_settings.scss create mode 100644 test/fixtures/_settings.scss.new create mode 100644 test/fixtures/main.scss create mode 100644 test/fixtures/something.scss create mode 100644 test/importer.js diff --git a/lib/index.js b/lib/index.js index 900ea71..a75011d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -9,6 +9,7 @@ module.exports = tools.makeStringTransform('sassify', { includeExtensions: ['.css', '.sass', '.scss'], evaluateArguments: true }, function(content, opts, done) { + var self = this; var inject = (typeof opts.config !== 'undefined' && typeof opts.config['auto-inject'] !== 'undefined') ? opts.config['auto-inject'] : false; var file = opts.file; @@ -24,6 +25,17 @@ module.exports = tools.makeStringTransform('sassify', { options.outFile = opts.file; options.sourceMapEmbed = true; options.sourceMapContents = true; + options.importer = function(url, prev) { + var importAbsolutePath = path.resolve(path.dirname(prev), url); + var underscoredImportAbsolutePath = path.join(path.dirname(importAbsolutePath), '_' + path.basename(importAbsolutePath)); + self.emit('file', importAbsolutePath); + self.emit('file', importAbsolutePath + '.scss'); + self.emit('file', underscoredImportAbsolutePath); + self.emit('file', underscoredImportAbsolutePath + '.scss'); + return { + file: url + }; + }; options.success = function (css) { var exp; if (inject) { diff --git a/package.json b/package.json index 4c3705c..2ec6cde 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Browserify middleware for adding required styles to the page.", "main": "index.js", "scripts": { - "test": "browserify -t . -r ./index.js:sassify test/*.js -o test_pack.js && cat test_pack.js | tape-run -b firefox | tap-spec && cat test_pack.js | tape-run -b phantom | tap-spec" + "test": "browserify -t . -r ./index.js:sassify test/*.js -o test_pack.js && cat test_pack.js | tape-run -b firefox | tap-spec && cat test_pack.js | tape-run -b phantom | tap-spec", + "test-importer": "node_modules/.bin/mocha test/importer.js" }, "repository": { "type": "git", @@ -57,9 +58,11 @@ }, "devDependencies": { "browserify": "^9.0.3", + "mocha": "^2.2.1", "tap-spec": "^2.2.2", "tape": "^3.5.0", - "tape-run": "^0.3.0" + "tape-run": "^0.3.0", + "watchify": "^2.6.0" }, "bugs": { "url": "https://github.com/davidguttman/sassify/issues" diff --git a/test/fixtures/_settings.scss b/test/fixtures/_settings.scss new file mode 100644 index 0000000..c55638e --- /dev/null +++ b/test/fixtures/_settings.scss @@ -0,0 +1 @@ +$bg: red; diff --git a/test/fixtures/_settings.scss.new b/test/fixtures/_settings.scss.new new file mode 100644 index 0000000..3222ed0 --- /dev/null +++ b/test/fixtures/_settings.scss.new @@ -0,0 +1 @@ +$bg: blue; diff --git a/test/fixtures/main.scss b/test/fixtures/main.scss new file mode 100644 index 0000000..e5eb1c8 --- /dev/null +++ b/test/fixtures/main.scss @@ -0,0 +1 @@ +@import './something'; diff --git a/test/fixtures/something.scss b/test/fixtures/something.scss new file mode 100644 index 0000000..ea3f1cf --- /dev/null +++ b/test/fixtures/something.scss @@ -0,0 +1,5 @@ +@import './settings'; + +body { + background-color: $bg; +} diff --git a/test/importer.js b/test/importer.js new file mode 100644 index 0000000..0476e0a --- /dev/null +++ b/test/importer.js @@ -0,0 +1,50 @@ +var assert = require("assert"); +var browserify = require("browserify"); +var watchify = require("watchify"); +var fs = require("fs"); +var path = require("path"); +var sassify = require(".."); + +function fixturePath(filename) { + return path.join(__dirname, 'fixtures', filename); +} + +function copySync(src, dest) { + fs.writeFileSync(dest, fs.readFileSync(src)); +} + +var settingsContent = fs.readFileSync(fixturePath('_settings.scss')); + +describe("the sass importer", function() { + before(function() { + this.b = browserify(); + this.b.transform(sassify.configure({ + 'auto-inject': false + })) + .add(fixturePath('main.scss')); + this.w = watchify(this.b); + }); + + after(function() { + fs.writeFileSync(fixturePath('_settings.scss'), settingsContent); + if (this.w) { + this.w.close(); + } + }); + + it("should update when an imported file changes", function(done) { + this.w.bundle(function(err, bundle) { + assert(bundle.toString().match(/background-color:\s*red/)); + + this.w.once('update', function() { + this.w.bundle(function(err, bundle) { + assert(bundle.toString().match(/background-color:\s*blue/)); + done(); + }.bind(this)); + }.bind(this)); + + // This will trigger the watcher to update. + copySync(fixturePath('_settings.scss.new'), fixturePath('_settings.scss')); + }.bind(this)); + }); +});