mirror of
https://github.com/Mibew/mibew.git
synced 2024-11-15 16:44:11 +03:00
Add inheritance helpers to Handlebars.js
This commit is contained in:
parent
fa615bc2e0
commit
cb4bd3acaa
@ -219,4 +219,127 @@
|
||||
Handlebars.registerHelper('cutString', function(length, options) {
|
||||
return options.fn(this).substr(0, length);
|
||||
});
|
||||
|
||||
/**
|
||||
* Registers "block" helper.
|
||||
*
|
||||
* This helper defines default content of a block. Example of usage:
|
||||
* <code>
|
||||
* {{#block "blockName"}}
|
||||
* Default content for the block
|
||||
* {{/block}}
|
||||
* </code>
|
||||
*/
|
||||
Handlebars.registerHelper('block', function(name, options) {
|
||||
if (this._blocksStorage && this._blocksStorage.hasOwnProperty(name)) {
|
||||
return this._blocksStorage[name];
|
||||
}
|
||||
|
||||
return options.fn(this);
|
||||
});
|
||||
|
||||
/**
|
||||
* Registers "extends" helper.
|
||||
*
|
||||
* This is used for templates inheritance. Example of usage:
|
||||
* <code>
|
||||
* {{#extends "parentTemplateName"}}
|
||||
* {{#override "blockName"}}
|
||||
* Overridden first block
|
||||
* {{/override}}
|
||||
*
|
||||
* {{#override "anotherBlockName"}}
|
||||
* Overridden second block
|
||||
* {{/override}}
|
||||
* {{/extends}}
|
||||
* </code>
|
||||
*/
|
||||
Handlebars.registerHelper('extends', function(parentTemplate, options) {
|
||||
// Create a blocks storage. If the current inheritance level is not the
|
||||
// deepest one, a storage already exists. In this case we do not need
|
||||
// to override it.
|
||||
this._blocksStorage = this._blocksStorage || {};
|
||||
|
||||
// Render content inside "extends" helper to override blocks
|
||||
options.fn(this);
|
||||
|
||||
// Check if the parent template exists
|
||||
if (!Handlebars.templates.hasOwnProperty(parentTemplate)) {
|
||||
throw Error('Parent template "' + parentTemplate + '" is not defined');
|
||||
}
|
||||
|
||||
// Render the parent template. We assume that templates are stored in
|
||||
// Handlebars.templates property. It is the most common case and take
|
||||
// place when templates were compiled with node.js Handlebars CLI tool.
|
||||
return Handlebars.templates[parentTemplate](this);
|
||||
});
|
||||
|
||||
/**
|
||||
* Registers "override" helper.
|
||||
*
|
||||
* This helper overrides content of a block. Example of usage:
|
||||
* <code>
|
||||
* {{#extends "parentTemplateName"}}
|
||||
* {{#override "blockName"}}
|
||||
* Overridden first block
|
||||
* {{/override}}
|
||||
*
|
||||
* {{#override "anotherBlockName"}}
|
||||
* Overridden second block
|
||||
* {{/override}}
|
||||
* {{/extends}}
|
||||
* </code>
|
||||
*/
|
||||
Handlebars.registerHelper('override', function(name, options) {
|
||||
// We need to provide unlimited inheritence level. Rendering is started
|
||||
// from the deepest level template. If the content is in the block
|
||||
// storage it is related with the deepest level template. Thus we do not
|
||||
// need to override it.
|
||||
if (!this._blocksStorage.hasOwnProperty(name)) {
|
||||
this._blocksStorage[name] = options.fn(this);
|
||||
}
|
||||
|
||||
// An empty string is returned for consistency.
|
||||
return '';
|
||||
});
|
||||
|
||||
/**
|
||||
* Registers "ifOverridden" helper.
|
||||
*
|
||||
* This helper checks if a block is overridden or not. Example of usage:
|
||||
* <code>
|
||||
* {{#ifOverridden "blockName"}}
|
||||
* The block was overridden
|
||||
* {{else}}
|
||||
* The block was not overridden
|
||||
* {{/ifOverridden}}
|
||||
* </code>
|
||||
*/
|
||||
Handlebars.registerHelper('ifOverridden', function(name, options) {
|
||||
if (this._blocksStorage && this._blocksStorage.hasOwnProperty(name)) {
|
||||
return options.fn(this);
|
||||
} else {
|
||||
return options.inverse(this);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Registers "unlessOverridden" helper.
|
||||
*
|
||||
* This helper checks if a block is overridden or not. Example of usage:
|
||||
* <code>
|
||||
* {{#unlessOverridden "blockName"}}
|
||||
* The block was not overridden
|
||||
* {{else}}
|
||||
* The block was overridden
|
||||
* {{/unlessOverridden}}
|
||||
* </code>
|
||||
*/
|
||||
Handlebars.registerHelper('unlessOverridden', function(name, options) {
|
||||
if (this._blocksStorage && this._blocksStorage.hasOwnProperty(name)) {
|
||||
return options.inverse(this);
|
||||
} else {
|
||||
return options.fn(this);
|
||||
}
|
||||
});
|
||||
})(Mibew, Handlebars);
|
@ -217,3 +217,139 @@ test('l10n', function() {
|
||||
'Test string with placeholder'
|
||||
);
|
||||
});
|
||||
|
||||
// Test "block", "extends" and "override" Handlebars helpers.
|
||||
test('inheritance', function() {
|
||||
// Test inheritance
|
||||
Handlebars.templates = {
|
||||
parent: Handlebars.compile(
|
||||
'Test {{#block "first"}}1{{/block}} {{#block "second"}}2{{/block}}'
|
||||
),
|
||||
child: Handlebars.compile(
|
||||
'{{#extends "parent"}}{{#override "first"}}0{{/override}}{{/extends}}'
|
||||
),
|
||||
grandChild: Handlebars.compile(
|
||||
'{{#extends "child"}}{{#override "first"}}one{{/override}}{{#override "second"}}two{{/override}}{{/extends}}'
|
||||
)
|
||||
};
|
||||
|
||||
equal(
|
||||
Handlebars.templates['parent']({}),
|
||||
'Test 1 2',
|
||||
'Test default block content'
|
||||
);
|
||||
|
||||
equal(
|
||||
Handlebars.templates['child']({}),
|
||||
'Test 0 2',
|
||||
'Test inheritance'
|
||||
);
|
||||
|
||||
equal(
|
||||
Handlebars.templates['grandChild']({}),
|
||||
'Test one two',
|
||||
'Test nested inheritance'
|
||||
);
|
||||
|
||||
// Test nested blocks
|
||||
Handlebars.templates = {
|
||||
parent: Handlebars.compile(
|
||||
'Test {{#block "first"}}1 {{#block "second"}}2{{/block}}{{/block}}'
|
||||
),
|
||||
childInnerBlock: Handlebars.compile(
|
||||
'{{#extends "parent"}}{{#override "second"}}two{{/override}}{{/extends}}'
|
||||
),
|
||||
childOuterBlock: Handlebars.compile(
|
||||
'{{#extends "parent"}}{{#override "first"}}foo{{/override}}{{/extends}}'
|
||||
)
|
||||
}
|
||||
|
||||
equal(
|
||||
Handlebars.templates['childInnerBlock']({}),
|
||||
'Test 1 two',
|
||||
'Test overriding of the inner block'
|
||||
);
|
||||
|
||||
equal(
|
||||
Handlebars.templates['childOuterBlock']({}),
|
||||
'Test foo',
|
||||
'Test overriding of the outer block'
|
||||
);
|
||||
|
||||
// Clean up environment
|
||||
delete Handlebars.templates;
|
||||
});
|
||||
|
||||
// Test "ifOverridden" Handlebars helper.
|
||||
test('ifOverridden', function() {
|
||||
// Test inheritance
|
||||
Handlebars.templates = {
|
||||
parent: Handlebars.compile(
|
||||
'{{#ifOverridden "foo"}}Child{{else}}Parent{{/ifOverridden}}{{#block "foo"}}{{/block}}'
|
||||
),
|
||||
child: Handlebars.compile(
|
||||
'{{#extends "parent"}}{{/extends}}'
|
||||
),
|
||||
childOverridden: Handlebars.compile(
|
||||
'{{#extends "parent"}}{{#override "foo"}}{{/override}}{{/extends}}'
|
||||
)
|
||||
};
|
||||
|
||||
equal(
|
||||
Handlebars.templates['childOverridden']({}),
|
||||
'Child',
|
||||
'Test overridden block'
|
||||
);
|
||||
|
||||
equal(
|
||||
Handlebars.templates['child']({}),
|
||||
'Parent',
|
||||
'Test not overridden block'
|
||||
);
|
||||
|
||||
equal(
|
||||
Handlebars.templates['parent']({}),
|
||||
'Parent',
|
||||
'Test with no inheritance'
|
||||
);
|
||||
|
||||
// Clean up environment
|
||||
delete Handlebars.templates;
|
||||
});
|
||||
|
||||
// Test "unlessOverridden" Handlebars helper.
|
||||
test('unlessOverridden', function() {
|
||||
// Test inheritance
|
||||
Handlebars.templates = {
|
||||
parent: Handlebars.compile(
|
||||
'{{#unlessOverridden "foo"}}Parent{{else}}Child{{/unlessOverridden}}{{#block "foo"}}{{/block}}'
|
||||
),
|
||||
child: Handlebars.compile(
|
||||
'{{#extends "parent"}}{{/extends}}'
|
||||
),
|
||||
childOverridden: Handlebars.compile(
|
||||
'{{#extends "parent"}}{{#override "foo"}}{{/override}}{{/extends}}'
|
||||
)
|
||||
};
|
||||
|
||||
equal(
|
||||
Handlebars.templates['childOverridden']({}),
|
||||
'Child',
|
||||
'Test overridden block'
|
||||
);
|
||||
|
||||
equal(
|
||||
Handlebars.templates['child']({}),
|
||||
'Parent',
|
||||
'Test not overridden block'
|
||||
);
|
||||
|
||||
equal(
|
||||
Handlebars.templates['parent']({}),
|
||||
'Parent',
|
||||
'Test with no inheritance'
|
||||
);
|
||||
|
||||
// Clean up environment
|
||||
delete Handlebars.templates;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user