1 | ;
|
2 |
|
3 | var Base = require('base');
|
4 | var debug = require('debug')('base:templates:collection');
|
5 | var plugin = require('./plugins');
|
6 | var utils = require('./utils');
|
7 |
|
8 | /**
|
9 | * Expose `Collection`
|
10 | */
|
11 |
|
12 | module.exports = exports = Collection;
|
13 |
|
14 | /**
|
15 | * Create an instance of `Collection` with the given `options`.
|
16 | *
|
17 | * ```js
|
18 | * var collection = new Collection();
|
19 | * collection.addItem('foo', {content: 'bar'});
|
20 | * ```
|
21 | * @param {Object} `options`
|
22 | * @api public
|
23 | */
|
24 |
|
25 | function Collection(options) {
|
26 | if (!(this instanceof Collection)) {
|
27 | return new Collection(options);
|
28 | }
|
29 |
|
30 | Base.call(this, {}, options);
|
31 | this.is('Collection');
|
32 | this.items = {};
|
33 |
|
34 | this.use(utils.option());
|
35 | this.use(utils.plugin());
|
36 | this.init(options || {});
|
37 | }
|
38 |
|
39 | /**
|
40 | * Inherit `Base`
|
41 | */
|
42 |
|
43 | Base.extend(Collection);
|
44 |
|
45 | /**
|
46 | * Mixin static methods
|
47 | */
|
48 |
|
49 | plugin.is(Collection);
|
50 |
|
51 | /**
|
52 | * Initialize `Collection` defaults
|
53 | */
|
54 |
|
55 | Collection.prototype.init = function(opts) {
|
56 | debug('initializing', __filename);
|
57 |
|
58 | // add constructors to the instance
|
59 | this.define('Item', opts.Item || Collection.Item);
|
60 | this.define('View', opts.View || Collection.View);
|
61 |
|
62 | this.use(plugin.renameKey());
|
63 | this.use(plugin.item('item', 'Item', {emit: false}));
|
64 |
|
65 | // if an instance of `List` or `Collection` is passed, load it now
|
66 | if (Array.isArray(opts) || opts.isList) {
|
67 | this.options = opts.options;
|
68 | this.addList(opts.items);
|
69 |
|
70 | } else if (opts.isCollection) {
|
71 | this.options = opts.options;
|
72 | this.addItems(opts.items);
|
73 |
|
74 | } else {
|
75 | this.options = opts;
|
76 | }
|
77 | };
|
78 |
|
79 | /**
|
80 | * Add an item to the collection.
|
81 | *
|
82 | * ```js
|
83 | * collection.addItem('foo', {content: 'bar'});
|
84 | * ```
|
85 | * @emits `item` With the created `item` and `collection` instance as arguments.
|
86 | * @param {String|Object} `key` Item name or object
|
87 | * @param {Object} `val` Item object, when `key` is a string.
|
88 | * @developer The `item` method is decorated onto the collection using the `item` plugin
|
89 | * @return {Object} returns the `item` instance.
|
90 | * @api public
|
91 | */
|
92 |
|
93 | Collection.prototype.addItem = function(key, val) {
|
94 | debug('adding item "%s"');
|
95 | var item = this.item(key, val);
|
96 | if (typeof item.use === 'function') {
|
97 | this.run(item);
|
98 | }
|
99 | this.emit('item', item, this);
|
100 | this.items[item.key] = item;
|
101 | return item;
|
102 | };
|
103 |
|
104 | /**
|
105 | * Identical to `.addItem`, except the collection instance is returned instead of
|
106 | * the item, to allow chaining.
|
107 | *
|
108 | * ```js
|
109 | * collection.setItem('foo', {content: 'bar'});
|
110 | * ```
|
111 | * @emits `item` With the created `item` and `collection` instance as arguments.
|
112 | * @param {String|Object} `key` Item name or object
|
113 | * @param {Object} `val` Item object, when `key` is a string.
|
114 | * @return {Object} returns the `collection` instance.
|
115 | * @api public
|
116 | */
|
117 |
|
118 | Collection.prototype.setItem = function(/*key, value*/) {
|
119 | this.addItem.apply(this, arguments);
|
120 | return this;
|
121 | };
|
122 |
|
123 | /**
|
124 | * Get an item from `collection.items`.
|
125 | *
|
126 | * ```js
|
127 | * collection.getItem('a.html');
|
128 | * ```
|
129 | * @param {String} `key` Key of the item to get.
|
130 | * @return {Object}
|
131 | * @api public
|
132 | */
|
133 |
|
134 | Collection.prototype.getItem = function(key) {
|
135 | return this.items[key] || this.items[this.renameKey(key)];
|
136 | };
|
137 |
|
138 | /**
|
139 | * Remove an item from `collection.items`.
|
140 | *
|
141 | * ```js
|
142 | * items.deleteItem('abc');
|
143 | * ```
|
144 | * @param {String} `key`
|
145 | * @return {Object} Returns the instance for chaining
|
146 | * @api public
|
147 | */
|
148 |
|
149 | Collection.prototype.deleteItem = function(item) {
|
150 | if (typeof item === 'string') {
|
151 | item = this.getItem(item);
|
152 | }
|
153 | delete this.items[item.key];
|
154 | return this;
|
155 | };
|
156 |
|
157 | /**
|
158 | * Load multiple items onto the collection.
|
159 | *
|
160 | * ```js
|
161 | * collection.addItems({
|
162 | * 'a.html': {content: '...'},
|
163 | * 'b.html': {content: '...'},
|
164 | * 'c.html': {content: '...'}
|
165 | * });
|
166 | * ```
|
167 | * @param {Object|Array} `items`
|
168 | * @return {Object} returns the instance for chaining
|
169 | * @api public
|
170 | */
|
171 |
|
172 | Collection.prototype.addItems = function(items) {
|
173 | if (Array.isArray(items)) {
|
174 | return this.addList.apply(this, arguments);
|
175 | }
|
176 | this.visit('addItem', items);
|
177 | return this;
|
178 | };
|
179 |
|
180 | /**
|
181 | * Load an array of items onto the collection.
|
182 | *
|
183 | * ```js
|
184 | * collection.addList([
|
185 | * {path: 'a.html', content: '...'},
|
186 | * {path: 'b.html', content: '...'},
|
187 | * {path: 'c.html', content: '...'}
|
188 | * ]);
|
189 | * ```
|
190 | * @param {Array} `items` or an instance of `List`
|
191 | * @param {Function} `fn` Optional sync callback function that is called on each item.
|
192 | * @return {Object} returns the Collection instance for chaining
|
193 | * @api public
|
194 | */
|
195 |
|
196 | Collection.prototype.addList = function(list, fn) {
|
197 | if (!Array.isArray(list)) {
|
198 | throw new TypeError('expected list to be an array.');
|
199 | }
|
200 |
|
201 | if (typeof fn !== 'function') {
|
202 | fn = utils.identity;
|
203 | }
|
204 | var len = list.length;
|
205 | var idx = -1;
|
206 |
|
207 | while (++idx < len) {
|
208 | this.addItem(fn(list[idx]));
|
209 | }
|
210 | return this;
|
211 | };
|
212 |
|
213 | /**
|
214 | * Expose static properties
|
215 | */
|
216 |
|
217 | utils.define(Collection, 'Item', require('vinyl-item'));
|
218 | utils.define(Collection, 'View', require('vinyl-view'));
|