templates
Advanced tools
Comparing version 0.1.17 to 0.1.18
89
index.js
@@ -38,2 +38,3 @@ /*! | ||
this.options = options || {}; | ||
this.plugins = []; | ||
utils.renameKey(this); | ||
@@ -55,4 +56,2 @@ this.defaultConfig(); | ||
utils.option(this); | ||
// decorate `view` method onto instance | ||
utils.createView(this); | ||
@@ -105,2 +104,6 @@ for (var key in this.options.mixins) { | ||
initialize: function () { | ||
// expose `view` method on app instance | ||
utils.createView(this); | ||
// expose constructors on app instance | ||
this.define('Base', Base); | ||
@@ -128,3 +131,5 @@ this.define('View', this.options.View || View); | ||
/** | ||
* Run a plugin on the instance. | ||
* Run a plugin on the instance. Plugins | ||
* are invoked immediately upon creating the collection | ||
* in the order in which they were defined. | ||
* | ||
@@ -139,4 +144,4 @@ * ``` | ||
* @name .use | ||
* @param {Function} fn | ||
* @return {Object} | ||
* @param {Function} `fn` Plugin function. If the plugin returns a function it will be passed to the `use` method of each collection created on the instance. | ||
* @return {Object} Returns the instance for chaining. | ||
* @api public | ||
@@ -146,3 +151,6 @@ */ | ||
use: function (fn) { | ||
fn.call(this, this); | ||
var plugin = fn.call(this, this, this.options); | ||
if (typeof plugin === 'function') { | ||
this.plugins.push(plugin); | ||
} | ||
return this; | ||
@@ -228,8 +236,8 @@ }, | ||
if (!this.initialized) this.initialize(); | ||
var collection = null; | ||
var Views = this.get('Views'); | ||
var collection; | ||
if (opts instanceof Views) { | ||
collection = opts; | ||
opts = {}; | ||
opts = this.options; | ||
} else { | ||
@@ -240,4 +248,7 @@ opts = opts || {}; | ||
} | ||
// pass the `View` constructor from `App` to the collection | ||
return this.extendViews(collection, opts); | ||
// emit the collection | ||
this.emit('collection', collection, opts); | ||
this.extendViews(collection, opts); | ||
return collection; | ||
}, | ||
@@ -272,2 +283,6 @@ | ||
opts = opts || {}; | ||
if (!opts.views && !opts.options) { | ||
opts = utils.merge({}, this.options, opts); | ||
} | ||
var collection = this.collection(opts); | ||
@@ -305,5 +320,13 @@ | ||
// run collection plugins | ||
this.plugins.forEach(function (fn) { | ||
collection.use(fn, opts); | ||
}.bind(this)); | ||
// emit create | ||
this.emit('create', collection, opts); | ||
// add collection and view helpers | ||
helpers.plural(this, collection, opts); | ||
// helpers.single(this, this[single], opts); | ||
helpers.plural(this, this[plural], opts); | ||
helpers.single(this, this[single], opts); | ||
return collection; | ||
@@ -341,8 +364,2 @@ }, | ||
}; | ||
// support custom `extendView` function on options | ||
if (typeof opts.extendView === 'function') { | ||
opts.extendView(view); | ||
} | ||
return view; | ||
}, | ||
@@ -357,15 +374,3 @@ | ||
var app = this; | ||
var addView = collection.addView; | ||
utils.define(collection, 'addView', function () { | ||
var view = addView.apply(this, arguments); | ||
app.handleView('onLoad', view); | ||
return view; | ||
}); | ||
var extendView = collection.extendView; | ||
utils.define(collection, 'extendView', function () { | ||
var view = extendView.apply(this, arguments); | ||
return app.extendView(view, options); | ||
}); | ||
if (!collection.options.hasOwnProperty('renameKey')) { | ||
@@ -375,6 +380,8 @@ collection.option('renameKey', this.renameKey); | ||
if (opts.extendViews) { | ||
collection = opts.extendViews(collection); | ||
} | ||
return collection; | ||
collection.on('view', function (view) { | ||
utils.define(view, 'addView', collection.addView.bind(collection)); | ||
app.extendView(view, opts); | ||
app.handleView('onLoad', view); | ||
app.emit('view', view); | ||
}); | ||
}, | ||
@@ -796,3 +803,4 @@ | ||
getEngine: function(ext) { | ||
ext = utils.formatExt(ext || this.option('view engine')); | ||
if (ext === '') ext = '*'; | ||
ext = ext ? utils.formatExt(ext) : null; | ||
return this._.engines.getEngine(ext); | ||
@@ -965,2 +973,6 @@ }, | ||
if (typeof cb !== 'function') { | ||
throw this.error('render', 'callback'); | ||
} | ||
// if `view` is a function, it's probably from chaining | ||
@@ -988,8 +1000,5 @@ // a collection method | ||
if (typeof cb !== 'function') { | ||
throw this.error('render', 'callback'); | ||
if (!engine) { | ||
return cb(this.error('render', 'engine', ext)); | ||
} | ||
if (typeof engine === 'undefined') { | ||
return cb(this.error('render', 'engine', extname)); | ||
} | ||
@@ -996,0 +1005,0 @@ var isAsync = typeof cb === 'function'; |
@@ -20,4 +20,6 @@ 'use strict'; | ||
var res = Base.prototype.get.apply(this, arguments); | ||
var List; | ||
if (Array.isArray(res)) { | ||
var List = this.get('List'); | ||
List = this.get('List'); | ||
var list = new List(); | ||
@@ -29,3 +31,3 @@ list.addItems(res); | ||
if (typeof res === 'object') { | ||
var List = this.get('List'); | ||
List = this.get('List'); | ||
var keys = Object.keys(List.prototype); | ||
@@ -32,0 +34,0 @@ keys.forEach(function(key) { |
'use strict'; | ||
var path = require('path'); | ||
var glob = require('globby'); | ||
var utils = require('./utils'); | ||
@@ -6,0 +4,0 @@ |
@@ -17,32 +17,9 @@ 'use strict'; | ||
app.asyncHelper(single, function (key, locals, opts, cb) { | ||
var args = [].slice.call(arguments, 1); | ||
cb = args.pop(); | ||
app.helper(plural, function () { | ||
return app.getViews(plural); | ||
}); | ||
try { | ||
var view = app.getView(plural, key); | ||
if (!Object.keys(view).length) { | ||
view = collection[key]; | ||
} | ||
if (!view || !Object.keys(view).length) { | ||
app.emit('error', 'missing ' + single + ' `' + key + '`'); | ||
return cb(null, ''); | ||
} | ||
var locs = utils.getLocals.apply(utils.getLocals, args); | ||
locs = locs || {}; | ||
var ctx = utils.merge({}, this.context.view.locals, view.context(locs)); | ||
view.render(ctx, function (err, res) { | ||
if (err) return cb(err); | ||
return cb(null, res.content); | ||
}); | ||
} catch(err) { | ||
err.reason = 'error in helper: ' + single + ': ' + key; | ||
app.emit('error', err); | ||
cb(null, ''); | ||
} | ||
app.helper('views', function (name) { | ||
return app.getViews(name); | ||
}); | ||
}; |
@@ -26,10 +26,11 @@ 'use strict'; | ||
if (Array.isArray(options) || options instanceof List) { | ||
this.options = options.options || {}; | ||
this.addList(options.items || options); | ||
} else if (options instanceof this.Views) { | ||
this.options = {}; | ||
this.options = options.options || {}; | ||
this.addItems(options.views); | ||
} else { | ||
this.options = options; | ||
this.options = options || {}; | ||
} | ||
@@ -162,8 +163,8 @@ } | ||
/** | ||
* Paginate all list `items` with the given options, | ||
* See [paginationator][] for the full range of available features and options. | ||
* Paginate all `items` in the list with the given options, | ||
* See [paginationator][] for the full range of available | ||
* features and options. | ||
* | ||
* ```js | ||
* var list = new List(); | ||
* list.addItems(...); | ||
* var list = new List(items); | ||
* var pages = list.paginate({limit: 5}); | ||
@@ -183,3 +184,4 @@ * ``` | ||
// paginate the `items` and return the pages | ||
return fn.apply(fn, args).pages; | ||
var items = fn.apply(fn, args); | ||
return items.pages; | ||
}; | ||
@@ -192,4 +194,3 @@ | ||
* ```js | ||
* var list = new List(); | ||
* list.addItems([ | ||
* var list = new List([ | ||
* {name: 'one'}, | ||
@@ -199,24 +200,23 @@ * {name: 'two'}, | ||
* ]); | ||
* var pagination = list.pagination(); | ||
* //=> [ | ||
* //=> {idx: 0, current: 1, next: 2, item: {name: 'one'}}, | ||
* //=> {idx: 1, current: 2, next: 3, prev: 1, item: {name: 'two'}}, | ||
* //=> {idx: 2, current: 3, prev: 2, item: {name: 'three'}} | ||
* //=> ] | ||
* | ||
* var pages = list.pages; | ||
* // [ | ||
* // {idx: 0, current: 1, next: 2, item: {name: 'one'}}, | ||
* // {idx: 1, current: 2, next: 3, prev: 1, item: {name: 'two'}}, | ||
* // {idx: 2, current: 3, prev: 2, item: {name: 'three'}} | ||
* // ] | ||
* ``` | ||
* @return {Array} Returns the pagination array. | ||
* @return {Array} Returns the array of pagination pages. | ||
* @api public | ||
*/ | ||
List.prototype.pagination = function() { | ||
var Pages = utils.paginationator.Pages; | ||
var pages = new Pages(this.items.map(function (item) { | ||
return {item: item}; | ||
})); | ||
return pages.pages; | ||
}; | ||
utils.define(List.prototype, 'pagination', { | ||
get: function() { | ||
var items = this.items.map(function (view) { | ||
return { item: view }; | ||
}); | ||
utils.define(List.prototype, 'count', { | ||
get: function() { | ||
return this.items.length; | ||
var Pagination = utils.paginationator.Pages; | ||
var pagination = new Pagination(items); | ||
return pagination.pages; | ||
}, | ||
@@ -223,0 +223,0 @@ set: function () { |
@@ -425,2 +425,8 @@ 'use strict'; | ||
/** | ||
* Decorate a `view` method onto the given `app` object. | ||
* | ||
* @param {Object} app | ||
*/ | ||
utils.createView = function (app) { | ||
@@ -450,5 +456,11 @@ app.define('view', function(key, value) { | ||
view.key = this.renameKey(view.key || key); | ||
view.path = view.path || key; | ||
view.key = this.renameKey(view.key || key); | ||
return this.extendView(view); | ||
this.plugins.forEach(function (fn) { | ||
view.use(fn); | ||
}); | ||
this.emit('view', view, this); | ||
return view; | ||
}); | ||
@@ -462,3 +474,3 @@ }; | ||
utils.option = function option(app, prop) { | ||
utils.option = function option(app) { | ||
utils.define(app, 'option', function(key, value) { | ||
@@ -560,4 +572,1 @@ if (typeof key === 'string') { | ||
module.exports = lazy; | ||
@@ -10,26 +10,12 @@ 'use strict'; | ||
function View(view) { | ||
if (!view) view = {}; | ||
if (typeof view.contents === 'string') { | ||
view.contents = new Buffer(view.contents); | ||
} | ||
this.isView = true; | ||
Vinyl.call(this, view); | ||
Base.call(this, view); | ||
view = view || {}; | ||
utils.syncContents(this, view.contents || view.content); | ||
this.options = view.options || {}; | ||
this.locals = view.locals || {}; | ||
this.data = view.data || {}; | ||
for (var key in view) { | ||
var val = view[key]; | ||
if (key === 'stat' && isObject(val) && val.mode) { | ||
this.set(key, cloneStats(val)); | ||
} else if (val) { | ||
this.set(key, val); | ||
} | ||
} | ||
this.define('_contents', null); | ||
this.define('_content', null); | ||
this.define('_dest', null); | ||
this.isView = true; | ||
utils.syncContents(this, view.contents || view.content); | ||
this.define('contents', { | ||
@@ -46,5 +32,17 @@ configurable: true, | ||
Vinyl.call(this, view); | ||
Base.call(this, view); | ||
for (var key in view) { | ||
var val = view[key]; | ||
if (key === 'stat' && isObject(val) && val.mode) { | ||
this.set(key, cloneStats(val)); | ||
} else if (val) { | ||
this.set(key, val); | ||
} | ||
} | ||
this.define('_dest', null); | ||
this.define('dest', { | ||
configurable: true, | ||
enumerable: false, | ||
get: function () { | ||
@@ -57,6 +55,2 @@ return utils.destWrapper(this); | ||
}); | ||
this.options = this.options || {}; | ||
this.locals = this.locals || {}; | ||
this.data = this.data || {}; | ||
} | ||
@@ -63,0 +57,0 @@ |
247
lib/views.js
@@ -18,4 +18,7 @@ 'use strict'; | ||
this.define('View', options.View || require('./view')); | ||
this.define('loaded', false); | ||
this.isCollection = true; | ||
this.plugins = []; | ||
this.queue = []; | ||
this.views = {}; | ||
@@ -25,5 +28,7 @@ | ||
if (Array.isArray(options) || options instanceof this.List) { | ||
this.options = options.options; | ||
this.addList(options.items); | ||
} else if (options instanceof Views) { | ||
this.options = options.options; | ||
this.addViews(options.views); | ||
@@ -36,105 +41,167 @@ | ||
Base.extend(Views, { | ||
use: function(fn) { | ||
fn.call(this, this); | ||
return this; | ||
}, | ||
Base.extend(Views); | ||
/** | ||
* Returns a new view, using the `View` class | ||
* currently defined on the instance. | ||
* | ||
* ```js | ||
* var view = app.view('foo', {conetent: '...'}); | ||
* // or | ||
* var view = app.view({path: 'foo', conetent: '...'}); | ||
* ``` | ||
* @name .view | ||
* @param {String|Object} `key` View key or object | ||
* @param {Object} `value` If key is a string, value is the view object. | ||
* @return {Object} returns the `view` object | ||
* @api public | ||
*/ | ||
/** | ||
* Run a plugin on the collection instance. Plugins | ||
* are invoked immediately upon creating the collection | ||
* in the order in which they were defined. | ||
* | ||
* @param {Function} `fn` Plugin function. If the plugin returns a function it will be passed to the `use` method of each view created on the instance. | ||
* @return {Object} Returns the instance for chaining. | ||
*/ | ||
/** | ||
* Uses the `view` method to a view to the instance (collection). | ||
* | ||
* @name .addView | ||
* @param {String|Object} `key` View key or object | ||
* @param {Object} `value` If key is a string, value is the view object. | ||
* @return {Object} returns the `view` object | ||
* @api public | ||
*/ | ||
Views.prototype.use = function(fn) { | ||
var plugin = fn.call(this, this); | ||
if (typeof plugin === 'function') { | ||
this.plugins.push(plugin); | ||
} | ||
return this; | ||
}; | ||
addView: function(key, value) { | ||
// the `this.view` method is decorated onto the collection | ||
// in the constructor, using the `createView` util | ||
var view = this.view(key, value); | ||
this.emit('view', view.key, view); | ||
this.views[view.key] = view; | ||
return view; | ||
}, | ||
/** | ||
* Returns a new view, using the `View` class | ||
* currently defined on the instance. | ||
* | ||
* ```js | ||
* var view = app.view('foo', {conetent: '...'}); | ||
* // or | ||
* var view = app.view({path: 'foo', conetent: '...'}); | ||
* ``` | ||
* @name .view | ||
* @param {String|Object} `key` View key or object | ||
* @param {Object} `value` If key is a string, value is the view object. | ||
* @return {Object} returns the `view` object | ||
* @api public | ||
*/ | ||
addViews: function(views) { | ||
if (Array.isArray(views)) { | ||
return this.addList.apply(this, arguments); | ||
} | ||
if (arguments.length > 1 && utils.isView(arguments[1])) { | ||
return this.addView.apply(this, arguments); | ||
} | ||
this.visit('addView', this.loader(views)); | ||
return this; | ||
}, | ||
/** | ||
* Uses the `view` method to a view to the collection. | ||
* | ||
* @param {String|Object} `key` View key or object | ||
* @param {Object} `value` If key is a string, value is the view object. | ||
* @developer This method is decorated onto the collection in the constructor using the `createView` utility method. | ||
* @return {Object} returns the `view` instance. | ||
* @api public | ||
*/ | ||
addList: function(list) { | ||
var len = list.length, i = -1; | ||
while (++i < len) { | ||
var view = list[i]; | ||
this.addView(view.path, view); | ||
} | ||
return this; | ||
}, | ||
Views.prototype.setView = function(key, value) { | ||
var view = this.view(key, value); | ||
this.views[view.key] = view; | ||
return view; | ||
}; | ||
getView: function(key) { | ||
return this.views[key] || this.views[this.renameKey(key)]; | ||
}, | ||
/** | ||
* Adds event emitting and custom loading to `setView`. | ||
* | ||
* @param {String} key | ||
* @param {Object} value | ||
*/ | ||
extendView: function(view) { | ||
view.options = view.options || {}; | ||
view.options.plural = this.options.plural; | ||
view.options.inflection = this.options.inflection; | ||
return view; | ||
}, | ||
Views.prototype.addView = function(key, value) { | ||
var args = [].slice.call(arguments); | ||
this.emit.apply(this, ['addView'].concat(args)); | ||
extendViews: function(fn) { | ||
var viewFn = this.extendView; | ||
this.extendView = function () { | ||
var view = viewFn.apply(this, arguments); | ||
fn.call(this, view); | ||
return view; | ||
}; | ||
return this; | ||
}, | ||
var view = this.setView(key, value); | ||
while (this.queue.length) { | ||
this.setView(this.queue.shift()); | ||
} | ||
return view; | ||
}; | ||
loader: function(views) { | ||
return views; | ||
}, | ||
/** | ||
* Load multiple views onto the collection. | ||
* | ||
* ```js | ||
* collection.addViews({ | ||
* 'a.html': {content: '...'}, | ||
* 'b.html': {content: '...'}, | ||
* 'c.html': {content: '...'} | ||
* }); | ||
* ``` | ||
* @param {Object|Array} `views` | ||
* @return {Object} returns the `collection` object | ||
* @api public | ||
*/ | ||
/** | ||
* Set view types for the collection. | ||
* | ||
* @param {String} `plural` e.g. `pages` | ||
* @param {Object} `options` | ||
* @api private | ||
*/ | ||
Views.prototype.addViews = function(views) { | ||
if (Array.isArray(views)) { | ||
return this.addList.apply(this, arguments); | ||
} | ||
if (arguments.length > 1 && utils.isView(arguments[1])) { | ||
return this.addView.apply(this, arguments); | ||
} | ||
viewType: function() { | ||
this.options.viewType = utils.arrayify(this.options.viewType || []); | ||
if (this.options.viewType.length === 0) { | ||
this.options.viewType.push('renderable'); | ||
} | ||
return this.options.viewType; | ||
this.emit('addViews', views); | ||
if (this.loaded) return this; | ||
this.visit('addView', views); | ||
return this; | ||
}; | ||
/** | ||
* Load an array of views onto the collection. | ||
* | ||
* ```js | ||
* collection.addViews([ | ||
* {path: 'a.html', content: '...'}, | ||
* {path: 'b.html', content: '...'}, | ||
* {path: 'c.html', content: '...'} | ||
* ]); | ||
* ``` | ||
* @param {Object|Array} `views` | ||
* @return {Object} returns the `collection` object | ||
* @api public | ||
*/ | ||
Views.prototype.addList = function(list) { | ||
this.emit('addList', list); | ||
if (this.loaded) return this; | ||
if (!Array.isArray(list)) { | ||
throw new TypeError('expected list to be an array.'); | ||
} | ||
}); | ||
var len = list.length, i = -1; | ||
while (++i < len) { | ||
var view = list[i]; | ||
this.addView(view.path, view); | ||
} | ||
return this; | ||
}; | ||
/** | ||
* Get a view from the collection. | ||
* | ||
* ```js | ||
* collection.getView('a.html'); | ||
* ``` | ||
* @param {String} `key` Key of the view to get. | ||
* @return {Object} | ||
* @api public | ||
*/ | ||
Views.prototype.getView = function(key) { | ||
return this.views[key] || this.views[this.renameKey(key)]; | ||
}; | ||
/** | ||
* Set view types for the collection. | ||
* | ||
* @param {String} `plural` e.g. `pages` | ||
* @param {Object} `options` | ||
* @api private | ||
*/ | ||
Views.prototype.viewType = function() { | ||
this.options.viewType = utils.arrayify(this.options.viewType || []); | ||
if (this.options.viewType.length === 0) { | ||
this.options.viewType.push('renderable'); | ||
} | ||
return this.options.viewType; | ||
}; | ||
/** | ||
* Get the number of views on the instance. | ||
*/ | ||
utils.define(Views.prototype, 'count', { | ||
@@ -141,0 +208,0 @@ get: function() { |
{ | ||
"name": "templates", | ||
"description": "System for creating and managing template collections, and rendering templates with any node.js template engine. Can be used as the basis for creating a static site generator or blog framework.", | ||
"version": "0.1.17", | ||
"version": "0.1.18", | ||
"homepage": "https://github.com/jonschlinkert/templates", | ||
@@ -25,3 +25,3 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)", | ||
"array-sort": "^0.1.1", | ||
"base-methods": "^0.2.4", | ||
"base-methods": "^0.2.6", | ||
"clone": "^1.0.2", | ||
@@ -45,7 +45,7 @@ "clone-stats": "0.0.1", | ||
"lazy-cache": "^0.2.3", | ||
"load-helpers": "^0.2.3", | ||
"load-helpers": "^0.2.5", | ||
"micromatch": "^2.2.0", | ||
"mixin-deep": "^1.1.3", | ||
"object.reduce": "^0.1.7", | ||
"paginationator": "^0.1.1", | ||
"paginationator": "^0.1.2", | ||
"template-error": "^0.1.2", | ||
@@ -52,0 +52,0 @@ "vinyl": "^0.5.3" |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
110331
15
3297
Updatedbase-methods@^0.2.6
Updatedload-helpers@^0.2.5
Updatedpaginationator@^0.1.2