diff --git a/lib/preprocessor.js b/lib/preprocessor.js index e47d0d268..72582352d 100644 --- a/lib/preprocessor.js +++ b/lib/preprocessor.js @@ -16,33 +16,40 @@ var createPreprocessor = function(config, basePath, injector) { var patterns = Object.keys(config); return function(file, done) { - // TODO(vojta): chain multiple pre-processors for a single file - var processor; + var preprocessors = []; + var nextPreprocessor = function(content) { + if (!preprocessors.length) { + return fs.writeFile(file.contentPath, content, function() { + done(); + }); + } + + preprocessors.shift()(content, file, nextPreprocessor); + }; + // collects matching preprocessors + // TODO(vojta): should we cache this ? for (var i = 0; i < patterns.length; i++) { if (mm(file.originalPath, patterns[i])) { - try { - processor = injector.get('preprocessor:' + config[patterns[i]]); - break; - } catch (e) { - // TODO(vojta): log warning only once per each preprocessor - log.warn('Pre-processor "%s" is not registered!', config[patterns[i]]); - } + config[patterns[i]].forEach(function(preprocessorName) { + try { + preprocessors.push(injector.get('preprocessor:' + preprocessorName)); + } catch (e) { + // TODO(vojta): log warning only once per each preprocessor + log.warn('Pre-processor "%s" is not registered!', preprocessorName); + } + }); } } - if (processor) { + if (preprocessors.length) { return fs.readFile(file.originalPath, function(err, buffer) { // TODO(vojta): extract get/create temp dir somewhere else (use the same for launchers etc) var env = process.env; var tmp = env.TMPDIR || env.TMP || env.TEMP || '/tmp'; file.contentPath = tmp + '/' + sha1(file.originalPath) + '.js'; - processor(buffer.toString(), file, function(processed) { - fs.writeFile(file.contentPath, processed, function() { - done(); - }); - }); + nextPreprocessor(buffer.toString()); }); } diff --git a/test/unit/preprocessor.spec.coffee b/test/unit/preprocessor.spec.coffee index 26992ceb3..763419380 100644 --- a/test/unit/preprocessor.spec.coffee +++ b/test/unit/preprocessor.spec.coffee @@ -5,20 +5,18 @@ describe 'preprocessor', -> mocks = require 'mocks' di = require 'di' - m = pp = mockFs = fakePreprocessor = null + m = pp = mockFs = null beforeEach -> mockFs = mocks.fs.create some: - 'a.js': mocks.fs.file 0, 'originalContent' - injector = new di.Injector [{'preprocessor:fake': ['factory', -> fakePreprocessor]}] + 'a.js': mocks.fs.file 0, 'content' mocks_ = fs: mockFs minimatch: require 'minimatch' m = mocks.loadFile __dirname + '/../../lib/preprocessor.js', mocks_ - pp = m.createPreprocessor {'**/*.js': 'fake'}, null, injector it 'should preprocess matching file', (done) -> @@ -27,6 +25,9 @@ describe 'preprocessor', -> file.contentPath = '/some/new.js' done 'new-content' + injector = new di.Injector [{'preprocessor:fake': ['factory', -> fakePreprocessor]}] + pp = m.createPreprocessor {'**/*.js': ['fake']}, null, injector + file = {originalPath: '/some/a.js', path: 'path'} pp file, -> @@ -40,8 +41,40 @@ describe 'preprocessor', -> fakePreprocessor = sinon.spy (content, file, done) -> done '' + injector = new di.Injector [{'preprocessor:fake': ['factory', -> fakePreprocessor]}] + pp = m.createPreprocessor {'**/*.js': ['fake']}, null, injector + file = {originalPath: '/some/a.txt', path: 'path'} pp file, -> expect(fakePreprocessor).to.not.have.been.called done() + + + it 'should apply all preprocessors', (done) -> + fakePreprocessor1 = sinon.spy (content, file, done) -> + file.contentPath = '/some/new.js' + file.path = file.path + '-p1' + done content + '-c1' + + fakePreprocessor2 = sinon.spy (content, file, done) -> + file.path = file.path + '-p2' + done content + '-c2' + + injector = new di.Injector [{ + 'preprocessor:fake1': ['factory', -> fakePreprocessor1] + 'preprocessor:fake2': ['factory', -> fakePreprocessor2] + }] + + pp = m.createPreprocessor {'**/*.js': ['fake1', 'fake2']}, null, injector + + file = {originalPath: '/some/a.js', path: 'path'} + + pp file, -> + expect(fakePreprocessor1).to.have.been.calledOnce + expect(fakePreprocessor2).to.have.been.calledOnce + expect(file.path).to.equal 'path-p1-p2' + expect(mockFs.readFileSync('/some/new.js').toString()).to.equal 'content-c1-c2' + done() + +