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) {
|
Handlebars.registerHelper('cutString', function(length, options) {
|
||||||
return options.fn(this).substr(0, length);
|
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);
|
})(Mibew, Handlebars);
|
@ -217,3 +217,139 @@ test('l10n', function() {
|
|||||||
'Test string with placeholder'
|
'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