Comparing version 0.1.1 to 0.2.0
75
index.js
@@ -39,6 +39,6 @@ /*! | ||
this.cache = Object.create(opts.cache || null); | ||
this.cache = opts.cache || {}; | ||
this.extend = opts.extend || _.extend; | ||
this.defaultTag = this.makeTag(opts); | ||
this.regex = this.makeRegex(opts); | ||
this.defaultTag = this.makeTag(opts) | ||
this.options = opts; | ||
}; | ||
@@ -59,3 +59,3 @@ | ||
Layouts.prototype.makeTag = function (options) { | ||
var opts = _.extend({}, options); | ||
var opts = _.defaults({}, options, this.options); | ||
return [ | ||
@@ -81,4 +81,5 @@ opts.delims[0], | ||
Layouts.prototype.makeRegex = function (options) { | ||
var opts = _.extend({sep: '\\s*'}, options); | ||
return new RegExp(this.makeTag(opts), opts.flags); | ||
var opts = _.extend({sep: '\\s*'}, this.options, options); | ||
var tag = this.makeTag(opts).replace(/[\]()[{|}]/g, '\\$&'); | ||
return new RegExp(tag, opts.flags || 'g'); | ||
}; | ||
@@ -111,6 +112,9 @@ | ||
} | ||
// if (arguments.length === 2 ) { | ||
// } | ||
this.cache[name] = { | ||
layout: (data && data.layout) ? data.layout : data, | ||
content: content, | ||
content: (data && data.content) ? data.content : content, | ||
data: data | ||
@@ -158,7 +162,6 @@ }; | ||
Layouts.prototype.extendData = function (obj, data) { | ||
if (typeof obj.data === 'object') { | ||
this.extend(data, obj.data); | ||
} | ||
delete data.layout; | ||
return data; | ||
this.extend(data, obj, obj.data); | ||
// Remove special properties | ||
return _.omit(data, ['content', 'layout', 'data']); | ||
}; | ||
@@ -227,12 +230,19 @@ | ||
Layouts.prototype.stack = function (name) { | ||
Layouts.prototype.stack = function (name, options) { | ||
var stack = this.createStack(name); | ||
var opts = _.extend(this.options, options); | ||
var data = {}; | ||
var tag = this.makeTag(opts) || this.defaultTag; | ||
this.regex = this.makeRegex(opts); | ||
return _.reduce(stack, function (acc, layout) { | ||
var content = acc.content || tag; | ||
var tmpl = this.cache[layout]; | ||
var content = acc.content || this.defaultTag; | ||
return { | ||
data: this.extendData(tmpl, data), | ||
content: content.replace(this.regex, tmpl.content) | ||
content: content.replace(this.regex, tmpl.content), | ||
regex: this.regex, | ||
tag: tag | ||
}; | ||
@@ -244,5 +254,29 @@ }.bind(this), {}); | ||
/** | ||
* ## .replaceTag | ||
* | ||
* Replace a `{{body}}` tag (or equivalent if custom delims are used) in `content` | ||
* with the given `str`. | ||
* | ||
* **Example:** | ||
* | ||
* ```js | ||
* console.log(layouts.replaceTag('ABC', 'Before {{body}} After')); | ||
* //=> 'Before ABC After' | ||
* ``` | ||
* | ||
* @param {String} `str` The string to use as a replacement value. | ||
* @param {String} `content` A string with a `{{body}}` tag where the `str` should be injected. | ||
* @return {String} Resulting flattened content. | ||
* @api public | ||
*/ | ||
Layouts.prototype.replaceTag = function (str, content, options) { | ||
return content.replace(this.makeRegex(options), str); | ||
}; | ||
/** | ||
* ## .inject | ||
* | ||
* Flatten nested layouts. | ||
* Inject content into a layout stack. | ||
* | ||
@@ -256,9 +290,10 @@ * **Example:** | ||
* | ||
* @param {String} `str` The content to inject into the layout. | ||
* @param {String} `name` The layout to start with. | ||
* @return {String} Resulting flattened layout. | ||
* @api private | ||
* @api public | ||
*/ | ||
Layouts.prototype.inject = function (str, name) { | ||
var layout = this.stack(name); | ||
Layouts.prototype.inject = function (str, name, options) { | ||
var layout = this.stack(name, options); | ||
if (layout.content) { | ||
@@ -268,2 +303,2 @@ str = layout.content.replace(this.regex, str); | ||
return {data: layout.data, content: str}; | ||
}; | ||
}; |
{ | ||
"name": "layouts", | ||
"description": "Wrap templates with layouts. Layouts can use/refer to other layouts, allowing them to be nested.", | ||
"version": "0.1.1", | ||
"description": "Wrap templates with layouts. Layouts can be nested and optionally use other layouts.", | ||
"version": "0.2.0", | ||
"homepage": "https://github.com/jonschlinkert/layouts", | ||
@@ -47,2 +47,4 @@ "author": { | ||
"mustache", | ||
"nest", | ||
"nested", | ||
"nunjucks", | ||
@@ -52,2 +54,4 @@ "page", | ||
"ractive", | ||
"stack", | ||
"stacked", | ||
"swig", | ||
@@ -62,3 +66,4 @@ "template", | ||
"walrus", | ||
"whiskers" | ||
"whiskers", | ||
"wrap" | ||
], | ||
@@ -81,5 +86,6 @@ "main": "index.js", | ||
"dependencies": { | ||
"debug": "^1.0.4", | ||
"falsey": "^0.1.0", | ||
"lodash": "^2.4.1" | ||
} | ||
} | ||
} |
@@ -13,53 +13,34 @@ /*! | ||
var layouts = new Layouts({ | ||
cache: { | ||
a: { layout: 'b', content: 'A above\n{{body}}\nA below' }, | ||
b: { layout: 'c', content: 'B above\n{{body}}\nB below' }, | ||
c: { layout: 'd', content: 'C above\n{{body}}\nC below' }, | ||
d: { layout: 'e', content: 'D above\n{{body}}\nD below' }, | ||
base: { layout: undefined, content: 'base!\n{{body}}\nbase!' }, | ||
e: { layout: 'f', content: 'E above\n{{body}}\nE below' }, | ||
f: { layout: 'base', content: 'F above\n{{body}}\nF below' }, | ||
foo: { layout: 'a', content: 'I\'m a <%= title %>' }, | ||
simple: { layout: 'base', content: 'I\'m a simple page.' }, | ||
} | ||
}); | ||
describe('layouts cache', function () { | ||
describe('.cache()', function () { | ||
it('should recursively inject content from each file into its layout.', function () { | ||
// Define the name of the cached template to start with | ||
var actual = layouts.stack('simple'); | ||
var expected = [ | ||
'base!', | ||
'I\'m a simple page.', | ||
'base!' | ||
].join('\n'); | ||
actual.content.should.eql(expected); | ||
it('should add layouts to the cache when passed to `new Layouts`.', function () { | ||
var layouts = new Layouts({ | ||
cache: { | ||
first: { layout: 'a', content: 'I\'m a <%= title %>' }, | ||
a: { layout: 'b', content: 'A above\n{{body}}\nA below' }, | ||
b: { layout: 'c', content: 'B above\n{{body}}\nB below' }, | ||
c: { layout: 'd', content: 'C above\n{{body}}\nC below' }, | ||
d: { layout: 'e', content: 'D above\n{{body}}\nD below' }, | ||
e: { layout: 'f', content: 'E above\n{{body}}\nE below' }, | ||
f: { layout: 'last', content: 'F above\n{{body}}\nF below' }, | ||
last: { layout: undefined, content: 'last!\n{{body}}\nlast!' } | ||
} | ||
}); | ||
Object.keys(layouts.cache).length.should.eql(8); | ||
}); | ||
it('should extend the `cache`.', function () { | ||
var actual = layouts.stack('foo'); | ||
var expected = [ | ||
'base!', | ||
'F above', | ||
'E above', | ||
'D above', | ||
'C above', | ||
'B above', | ||
'A above', | ||
'I\'m a <%= title %>', // should not be compiled | ||
'A below', | ||
'B below', | ||
'C below', | ||
'D below', | ||
'E below', | ||
'F below', | ||
'base!' | ||
].join('\n'); | ||
it('should add layouts to the cache when using `.set()`.', function () { | ||
var layouts = new Layouts(); | ||
actual.content.should.eql(expected); | ||
}); | ||
layouts.set('first', 'a', 'I\'m a <%= title %>'); | ||
layouts.set('a', 'b', 'A above\n{{body}}\nA below'); | ||
layouts.set('b', 'c', 'B above\n{{body}}\nB below'); | ||
layouts.set('c', 'd', 'C above\n{{body}}\nC below'); | ||
layouts.set('d', 'e', 'D above\n{{body}}\nD below'); | ||
layouts.set('e', 'f', 'E above\n{{body}}\nE below'); | ||
layouts.set('f', 'last', 'F above\n{{body}}\nF below'); | ||
layouts.set('last', undefined, 'last!\n{{body}}\nlast!'); | ||
Object.keys(layouts.cache).length.should.eql(8); | ||
}); | ||
}); |
@@ -14,3 +14,4 @@ /*! | ||
describe('layouts data', function () { | ||
describe('.data()', function () { | ||
layouts.set('first', 'a', '{{body}}'); | ||
layouts.set('a', {layout: 'b', xyz: 'aaa', one: 'two'}, 'A above\n{{body}}\nA below'); | ||
@@ -20,11 +21,10 @@ layouts.set('b', {layout: 'c', xyz: 'bbb', three: 'four'}, 'B above\n{{body}}\nB below'); | ||
layouts.set('d', 'e', 'D above\n{{body}}\nD below'); | ||
layouts.set('base', {xyz: 'zzz'}, 'base!\n{{body}}\nbase!'); | ||
layouts.set('e', 'f', 'E above\n{{body}}\nE below'); | ||
layouts.set('f', 'base', 'F above\n{{body}}\nF below'); | ||
layouts.set('foo', 'a', 'I\'m a <%= title %>'); | ||
layouts.set('f', 'last', 'F above\n{{body}}\nF below'); | ||
layouts.set('last', {xyz: 'zzz'}, 'last!\n{{body}}\nlast!'); | ||
it('should return an extended data object from the flattened layouts.', function () { | ||
var actual = layouts.stack('foo'); | ||
var actual = layouts.stack('first'); | ||
var expected = [ | ||
'base!', | ||
'last!', | ||
'F above', | ||
@@ -36,3 +36,3 @@ 'E above', | ||
'A above', | ||
'I\'m a <%= title %>', // should not be compiled | ||
'{{body}}', // should not be compiled | ||
'A below', | ||
@@ -44,3 +44,3 @@ 'B below', | ||
'F below', | ||
'base!' | ||
'last!' | ||
].join('\n'); | ||
@@ -47,0 +47,0 @@ actual.content.should.eql(expected); |
@@ -17,17 +17,17 @@ /*! | ||
var layouts = new Layouts(); | ||
layouts.set('first', 'a', '{{body}}'); | ||
layouts.set('a', {layout: 'b', xyz: 'aaa', one: 'two'}, 'A above\n{{body}}\nA below'); | ||
layouts.set('b', {layout: 'base', xyz: 'bbb', three: 'four'}, 'B above\n{{body}}\nB below'); | ||
layouts.set('base', {xyz: 'zzz'}, 'base!\n{{body}}\nbase!'); | ||
layouts.set('foo', 'a', 'I\'m a <%= title %>'); | ||
layouts.set('b', {layout: 'last', xyz: 'bbb', three: 'four'}, 'B above\n{{body}}\nB below'); | ||
layouts.set('last', {xyz: 'zzz'}, 'last!\n{{body}}\nlast!'); | ||
it('should merge the context so that the inner-most templates context wins.', function () { | ||
var actual = layouts.stack('foo'); | ||
var actual = layouts.stack('first'); | ||
var expected = [ | ||
'base!', | ||
'last!', | ||
'B above', | ||
'A above', | ||
'I\'m a <%= title %>', | ||
'{{body}}', | ||
'A below', | ||
'B below', | ||
'base!' | ||
'last!' | ||
].join('\n'); | ||
@@ -42,16 +42,16 @@ actual.content.should.eql(expected); | ||
layouts.set('a', {layout: 'b', xyz: 'aaa', one: 'two'}, 'A above\n{{body}}\nA below'); | ||
layouts.set('b', {layout: 'base', xyz: 'bbb', three: 'four'}, 'B above\n{{body}}\nB below'); | ||
layouts.set('base', {xyz: 'zzz'}, 'base!\n{{body}}\nbase!'); | ||
layouts.set('foo', 'a', 'I\'m a <%= title %>'); | ||
layouts.set('b', {layout: 'last', xyz: 'bbb', three: 'four'}, 'B above\n{{body}}\nB below'); | ||
layouts.set('last', {xyz: 'zzz'}, 'last!\n{{body}}\nlast!'); | ||
layouts.set('first', 'a', '{{body}}'); | ||
it('should change the order in which the context is merged.', function () { | ||
var actual = layouts.stack('foo'); | ||
var actual = layouts.stack('first'); | ||
var expected = [ | ||
'base!', | ||
'last!', | ||
'B above', | ||
'A above', | ||
'I\'m a <%= title %>', | ||
'{{body}}', | ||
'A below', | ||
'B below', | ||
'base!' | ||
'last!' | ||
].join('\n'); | ||
@@ -58,0 +58,0 @@ actual.content.should.eql(expected); |
@@ -19,11 +19,11 @@ /*! | ||
layouts.set({d: { layout: 'e', content: 'D above\n{{body}}\nD below' }}); | ||
layouts.set({base: { layout: undefined, content: 'base!\n{{body}}\nbase!' }}); | ||
layouts.set({last: { layout: undefined, content: 'last!\n{{body}}\nlast!' }}); | ||
layouts.set({e: { layout: 'f', content: 'E above\n{{body}}\nE below' }}); | ||
layouts.set({f: { layout: 'base', content: 'F above\n{{body}}\nF below' }}); | ||
layouts.set({foo: { layout: 'a', content: 'I\'m a <%= title %>' }}); | ||
layouts.set({f: { layout: 'last', content: 'F above\n{{body}}\nF below' }}); | ||
layouts.set({first: { layout: 'a', content: 'I\'m a <%= title %>' }}); | ||
it('should extend the `cache`.', function () { | ||
var actual = layouts.stack('foo'); | ||
var actual = layouts.stack('first'); | ||
var expected = [ | ||
'base!', | ||
'last!', | ||
'F above', | ||
@@ -42,3 +42,3 @@ 'E above', | ||
'F below', | ||
'base!' | ||
'last!' | ||
].join('\n'); | ||
@@ -50,2 +50,3 @@ actual.content.should.eql(expected); | ||
describe('when layouts are defined with string values:', function () { | ||
layouts.set('first', 'a', 'I\'m a <%= title %>'); | ||
layouts.set('a', 'b', 'A above\n{{body}}\nA below'); | ||
@@ -55,11 +56,10 @@ layouts.set('b', 'c', 'B above\n{{body}}\nB below'); | ||
layouts.set('d', 'e', 'D above\n{{body}}\nD below'); | ||
layouts.set('base', undefined, 'base!\n{{body}}\nbase!'); | ||
layouts.set('e', 'f', 'E above\n{{body}}\nE below'); | ||
layouts.set('f', 'base', 'F above\n{{body}}\nF below'); | ||
layouts.set('foo', 'a', 'I\'m a <%= title %>'); | ||
layouts.set('f', 'last', 'F above\n{{body}}\nF below'); | ||
layouts.set('last', undefined, 'last!\n{{body}}\nlast!'); | ||
it('should extend the `cache`.', function () { | ||
var actual = layouts.stack('foo'); | ||
var actual = layouts.stack('first'); | ||
var expected = [ | ||
'base!', | ||
'last!', | ||
'F above', | ||
@@ -78,3 +78,3 @@ 'E above', | ||
'F below', | ||
'base!' | ||
'last!' | ||
].join('\n'); | ||
@@ -84,2 +84,70 @@ actual.content.should.eql(expected); | ||
}); | ||
describe('when an object is passed as the second parameter:', function () { | ||
describe('when a `layout` propery is defined:', function () { | ||
layouts.set('first', {layout: 'a'}, 'I\'m a <%= title %>'); | ||
layouts.set('a', {layout: 'b'}, 'A above\n{{body}}\nA below'); | ||
layouts.set('b', {layout: 'c'}, 'B above\n{{body}}\nB below'); | ||
layouts.set('c', {layout: 'd'}, 'C above\n{{body}}\nC below'); | ||
layouts.set('d', {layout: 'e'}, 'D above\n{{body}}\nD below'); | ||
layouts.set('e', {layout: 'f'}, 'E above\n{{body}}\nE below'); | ||
layouts.set('f', {layout: 'last'}, 'F above\n{{body}}\nF below'); | ||
layouts.set('last', {layout: undefined}, 'last!\n{{body}}\nlast!'); | ||
it('should extend the `cache` with the layout', function () { | ||
var actual = layouts.stack('first'); | ||
var expected = [ | ||
'last!', | ||
'F above', | ||
'E above', | ||
'D above', | ||
'C above', | ||
'B above', | ||
'A above', | ||
'I\'m a <%= title %>', // should not be compiled | ||
'A below', | ||
'B below', | ||
'C below', | ||
'D below', | ||
'E below', | ||
'F below', | ||
'last!' | ||
].join('\n'); | ||
actual.content.should.eql(expected); | ||
}); | ||
}); | ||
describe('when a `content` propery is defined:', function () { | ||
layouts.set('first', {layout: 'a', content: 'I\'m a <%= title %>'}); | ||
layouts.set('a', {layout: 'b', content: 'A above\n{{body}}\nA below'}); | ||
layouts.set('b', {layout: 'c', content: 'B above\n{{body}}\nB below'}); | ||
layouts.set('c', {layout: 'd', content: 'C above\n{{body}}\nC below'}); | ||
layouts.set('d', {layout: 'e', content: 'D above\n{{body}}\nD below'}); | ||
layouts.set('e', {layout: 'f', content: 'E above\n{{body}}\nE below'}); | ||
layouts.set('f', {layout: 'last', content: 'F above\n{{body}}\nF below'}); | ||
layouts.set('last', {layout: undefined, content: 'last!\n{{body}}\nlast!'}); | ||
it('should extend the `cache` with the layout', function () { | ||
var actual = layouts.stack('first'); | ||
var expected = [ | ||
'last!', | ||
'F above', | ||
'E above', | ||
'D above', | ||
'C above', | ||
'B above', | ||
'A above', | ||
'I\'m a <%= title %>', // should not be compiled | ||
'A below', | ||
'B below', | ||
'C below', | ||
'D below', | ||
'E below', | ||
'F below', | ||
'last!' | ||
].join('\n'); | ||
actual.content.should.eql(expected); | ||
}); | ||
}); | ||
}); | ||
}); |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
33668
28
806
0
3
+ Addeddebug@^1.0.4
+ Addeddebug@1.0.5(transitive)
+ Addedms@2.0.0(transitive)