summaryrefslogtreecommitdiffstats
path: root/lib/pluginslist.js
blob: 10e21ac4b827d7a83d56422ebe3c7c0a759c11ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
var _ = require("lodash");
var Q = require("q");

var Plugin = require("./plugin");

var PluginsList = function(book, plugins) {
	this.book = book;
	this.log = this.book.log;

	// List of Plugin objects
	this.list = [];

	// List of names of failed plugins
	this.failed = [];

	// Namespaces
	this.namespaces = _.chain(["website", "ebook"])
		.map(function(namespace) {
			return [
				namespace,
				{
					html: {},
					resources: _.chain(Plugin.RESOURCES)
						.map(function(type) {
							return [type, []];
						})
						.object()
						.value()
				}
			];
		})
		.object()
		.value();

	// Bind methods
	_.bindAll(this);

	if (plugins) this.load(plugins);
};

// return count of plugins
PluginsList.prototype.count = function() {
	return this.list.length;
};

// Add and load a plugin
PluginsList.prototype.load = function(plugin, options) {
	var that = this;

	if (_.isArray(plugin)) {
		return _.reduce(plugin, function(prev, p) {
			return prev.then(function() {
				return that.load(p);
			});
		}, Q());
	}
	if (_.isObject(plugin) && !(plugin instanceof Plugin)) plugin = plugin.name;
	if (_.isString(plugin)) plugin = new Plugin(this.book, plugin);

	that.log.info("load plugin", plugin.name, "....");
	if (!plugin.isValid()) {
    	that.log.info.fail();
    	that.failed.push(plugin.name);
    	return Q();
    } else {
    	that.log.info.ok();

    	// Push in the list
    	that.list.push(plugin);
    }

	// Extract filters
	_.each(plugin.getFilters(), function(filterFunc, filterName) {
        that.book.template.addFilter(filterName, filterFunc);
    });

    // Extract blocks
	_.each(plugin.getBlocks(), function(block, blockName) {
        that.book.template.addBlock(blockName, block);
    });

	return _.reduce(_.keys(that.namespaces), function(prev, namespaceName) {
		return prev.then(function() {
			return plugin.getResources(namespaceName)
			.then(function(plResources) {
				var namespace = that.namespaces[namespaceName];

				// Extract js and css
				_.each(Plugin.RESOURCES, function(resourceType) {
					namespace.resources[resourceType] = (namespace.resources[resourceType] || []).concat(plResources[resourceType] || []);
				});

		        // Map of html resources by name added by each plugin
		        _.each(plResources.html || {}, function(value, tag) {
		        	// Turn into function if not one already
		           	if (!_.isFunction(value)) value = _.constant(value);

		        	namespace.html[tag] = namespace.html[tag] || [];
		        	namespace.html[tag].push(value);
		        });
			})
		});
	}, Q());
};

// Call a hook
PluginsList.prototype.hook = function(name, data) {
	return _.reduce(this.list, function(prev, plugin) {
        return prev.then(function(ret) {
            return plugin.callHook(name, ret);
        });
    }, Q(data));
};

// Return a template from a plugin
PluginsList.prototype.template = function(name) {
	var withTpl = _.find(this.list, function(plugin) {
        return (
            plugin.infos.templates &&
            plugin.infos.templates[name]
        );
    });

    if (!withTpl) return null;
    return withTpl.resolveFile(withTpl.infos.templates[name]);
};

// Return an html snippet
PluginsList.prototype.html = function(namespace, tag, context, options) {
	var htmlSnippets = this.namespaces[namespace].html[tag];
    return _.map(htmlSnippets || [], function(code) {
        return code.call(context, options);
    }).join("\n");
};

// Return a resources map for a namespace
PluginsList.prototype.resources = function(namespace) {
	return this.namespaces[namespace].resources;
};

module.exports = PluginsList;