Skip to content

Commit

Permalink
feat: allow multiple preprocessors
Browse files Browse the repository at this point in the history
// testacular.conf.js
preprocessors = {
  '**/*.coffee': ['coffee', 'other']
};
  • Loading branch information
vojtajina committed Mar 13, 2013
1 parent 39f4f32 commit 1d17c1a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 19 deletions.
37 changes: 22 additions & 15 deletions lib/preprocessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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());
});
}

Expand Down
41 changes: 37 additions & 4 deletions test/unit/preprocessor.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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) ->
Expand All @@ -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, ->
Expand All @@ -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()


0 comments on commit 1d17c1a

Please sign in to comment.