Skip to content

Commit

Permalink
Support alternate preprocessors for assets
Browse files Browse the repository at this point in the history
  • Loading branch information
joefiorini committed Apr 3, 2014
1 parent f255c42 commit 59ddbdf
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 100 deletions.
58 changes: 38 additions & 20 deletions lib/preprocessors.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,55 @@

var pkg = require(process.cwd() + '/package');
var deps = pkg['devDependencies'];
var path = require('path');
var Registry = require('./preprocessors/registry');
var requireLocal = require('./utilities/require-local');

function preprocessorType(preprocessor) {
var types = Object.keys(preprocessor.supportedPlugins);
var registry = new Registry(deps);

return types.reduce(function(final, type) {
var plugin = preprocessor.supportedPlugins[type];
registry.add('css', 'broccoli-sass', 'scss');
registry.add('css', 'broccoli-ruby-sass', 'scss');
registry.add('css', 'broccoli-less-single', 'less');
registry.add('css', 'broccoli-stylus-single', 'styl');

if(deps[plugin]) {
return type;
}
registry.add('js', 'broccoli-coffee', 'coffee');
registry.add('js', 'broccoli-sweetjs', 'js');

return final;
}, preprocessor.fallback);
}
registry.add('template', 'broccoli-template', ['hbs', 'handlebars']);
registry.add('template', 'broccoli-emblem-compiler', ['embl', 'emblem']);

var js = require('./preprocessors/javascript');
var css = require('./preprocessors/css');
var templates = require('./preprocessors/templates');
module.exports.registerPlugin = registry.add.bind(registry);

module.exports.preprocessCss = function(trees, inputPath, outputPath, options) {
var type = preprocessorType(css);
return css[type].call(null, trees, inputPath, outputPath, options);
var plugin = registry.load('css');

if(!plugin) { return trees; }

var input = path.join(inputPath, 'app.' + plugin.ext);
var output = path.join(outputPath, 'app.css');
return requireLocal(plugin.name).call(null, trees, input, output, options);

This comment has been minimized.

Copy link
@MajorBreakfast

MajorBreakfast Apr 3, 2014

Contributor

why .call()?

};

module.exports.preprocessTemplates = function(tree) {
var type = preprocessorType(templates);
return templates[type].call(null, tree);
var plugin = registry.load('template');

return requireLocal(plugin.name).call(null, tree, {

This comment has been minimized.

Copy link
@MajorBreakfast

MajorBreakfast Apr 3, 2014

Contributor

why .call()?

extensions: plugin.ext,
compileFunction: 'Ember.Handlebars.compile'
});

This comment has been minimized.

Copy link
@MajorBreakfast

MajorBreakfast Apr 3, 2014

Contributor

Why do you use .call()?

};

module.exports.preprocessJs = function(tree, inputPath, outputPath, options) {
var type = preprocessorType(js);
if(!type) { return tree; }
return js[type].call(null, tree, inputPath, outputPath, options);
var plugin = registry.load('js');

if(!plugin) { return tree; }

if(plugin.name.indexOf('coffee') !== -1) {
options = options || {};
options.bare = true;
options.srcDir = inputPath;
options.destDir = outputPath;
}

return requireLocal(plugin.name).call(null, tree, options);

This comment has been minimized.

Copy link
@MajorBreakfast

MajorBreakfast Apr 3, 2014

Contributor

why .call()?

This comment has been minimized.

Copy link
@joefiorini

joefiorini Apr 3, 2014

Author Contributor

why not .call()?

};
36 changes: 0 additions & 36 deletions lib/preprocessors/css.js

This file was deleted.

23 changes: 0 additions & 23 deletions lib/preprocessors/javascript.js

This file was deleted.

36 changes: 36 additions & 0 deletions lib/preprocessors/registry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

var isArray = require('lodash-node/compat/objects/isArray');

This comment has been minimized.

Copy link
@MajorBreakfast

MajorBreakfast Apr 3, 2014

Contributor

I think you should use Array.isArray instead. We're on node, not IE8. isArray came with ES5.

This comment has been minimized.

Copy link
@joefiorini

joefiorini Apr 3, 2014

Author Contributor

Good point, didn't realize that was ES5, thanks!


function Plugin(name, ext) {
this.name = name;
this.ext = ext;
}

function Registry(plugins) {
this.registry = {};
this.availablePlugins = plugins;
}

module.exports = Registry;

Registry.prototype.load = function(type) {
return this.registry[type].reduce(function(actual, plugin) {
if(this.availablePlugins.hasOwnProperty(plugin.name)) {
return plugin;
} else {
return actual;
}
}.bind(this), null);
};


Registry.prototype.add = function(type, name, extension) {
var registered = this.registry[type];

if(isArray(registered)) {
registered.push(new Plugin(name, extension));
} else {
this.registry[type] = [new Plugin(name, extension)];
}
};
21 changes: 0 additions & 21 deletions lib/preprocessors/templates.js

This file was deleted.

44 changes: 44 additions & 0 deletions tests/unit/preprocessors/registry-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';

var assert = require('../../helpers/assert');
var PluginRegistry = require('../../../lib/preprocessors/registry');

var pkg, registry;

This comment has been minimized.

Copy link
@MajorBreakfast

MajorBreakfast Apr 3, 2014

Contributor

belong into the function, I think


describe('Plugin Loader', function() {

beforeEach(function() {
pkg = {
devDependencies: {
'broccoli-sass': 'latest',
'broccoli-coffee': 'latest'
}
};
registry = new PluginRegistry(pkg.devDependencies);
registry.add('css', 'broccoli-sass');
registry.add('css', 'broccoli-ruby-sass');
});

it('returns first plugin when only one', function() {
var plugin = registry.load('css');
assert.equal(plugin.name, 'broccoli-sass');
});

it('returns the correct plugin when there are more than one', function() {
registry.availablePlugins = { 'broccoli-ruby-sass': 'latest' };
var plugin = registry.load('css');
assert.equal(plugin.name, 'broccoli-ruby-sass');
});

it('returns plugin of the correct type', function() {
registry.add('js', 'broccoli-coffee');
var plugin = registry.load('js');
assert.equal(plugin.name, 'broccoli-coffee');
});

it('returns null when no plugin available for type', function() {
registry.add('blah', 'not-available');
var plugin = registry.load('blah');
assert.notOk(plugin, 'loaded a plugin that wasn\'t in dependencies');
});
});

3 comments on commit 59ddbdf

@twokul
Copy link
Contributor

@twokul twokul commented on 59ddbdf Apr 3, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joefiorini mind submitting a PR next time? It will help the "hive mind" to digest the change and make sure that everyone is aware of the direction ember-cli is moving to.

@joefiorini
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@twokul Ordinarily I would have, this was something that was discussed on a previous commit (eaf0e76) and a huge blocker to being able to release the proxy feature. It's just a quick implementation that will involve a bigger change down the road that I'll discuss in an issue first.

@stefanpenner
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is great, this will be a great API entry point for ember-cli addons :)

Please sign in to comment.