Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Y.Template and Y.Template.Micro - Generic template API and simple ERB/Underscore-style JavaScript templates #230

Closed
wants to merge 10 commits into from
9 changes: 6 additions & 3 deletions src/handlebars/js/yui-handlebars-base-after.js
Expand Up @@ -33,9 +33,6 @@ Y.Handlebars = Handlebars;

Handlebars.VERSION += '-yui';

// The rest of this file is just API docs for methods defined in Handlebars
// itself.

/**
Registers a helper function that will be made available to all templates.

Expand Down Expand Up @@ -113,3 +110,9 @@ Converts a precompiled template into a renderable template function.
@param {Function} template Precompiled Handlebars template function.
@return {Function} Compiled template function.
*/

// Alias for Y.Handlebars.template(), used by Y.Template.
Handlebars.revive = Handlebars.template;

// Make Y.Template.Handlebars an alias for Y.Handlebars.
Y.namespace('Template').Handlebars = Handlebars;
7 changes: 7 additions & 0 deletions src/template/HISTORY.md
@@ -0,0 +1,7 @@
Template Change History
=======================

3.8.0
-----

* Initial release.
5 changes: 5 additions & 0 deletions src/template/README.md
@@ -0,0 +1,5 @@
Template
========

Provides a generic API for using template engines such as Handlebars and
`Y.Template.Micro`.
17 changes: 17 additions & 0 deletions src/template/build.json
@@ -0,0 +1,17 @@
{
"name": "template",

"builds": {
"template-base": {
"jsfiles": [
"template-base.js"
]
},

"template-micro": {
"jsfiles": [
"template-micro.js"
]
}
}
}
13 changes: 13 additions & 0 deletions src/template/docs/component.json
@@ -0,0 +1,13 @@
{
"name" : "template",
"displayName": "Template",
"description": "Provides a generic template engine API and a micro-templating language similar to ERB and Underscore templates.",
"author" : ["rgrove", "ericf"],

"tags": [
"utility", "beta", "template", "templating", "micro", "handlebars",
"erb", "underscore", "view"
],

"use": ["template"]
}
69 changes: 69 additions & 0 deletions src/template/docs/index.mustache
@@ -0,0 +1,69 @@
<div class="intro">
<p>
The Template component provides `Y.Template`, a generic template engine API, and `Y.Template.Micro`, a string-based micro-templating language similar to <a href="http://ruby-doc.org/stdlib-1.9.3/libdoc/erb/rdoc/ERB.html">ERB</a> and <a href="http://underscorejs.org/#template">Underscore</a> templates.
</p>
</div>

{{>getting-started}}

<h2>Using `Template`</h2>

<h3>Quick Start</h3>

<p>
A template engine takes a template&mdash;usually in the form of a string&mdash;and some data, and renders the data into the template to produce an HTML or text string. Using templates to keep markup and structure separate from content encourages reuse and can make code easier to read and maintain, and in many cases faster.
</p>

<p>
`Y.Template` provides a common API that can be used to compile and render templates with a variety of template engines. The two template engines included in YUI are <a href="../handlebars/">Handlebars</a> and [[#Using Template.Micro|Template.Micro]].
</p>

<p>[example of rendering a Template.Micro template]</p>

<p>[example of rendering a Handlebars template]</p>

<h3>Generic Template API</h3>

<p>[overview of the purpose of Y.Template's generic API -- a widget's default templates can be Handlebars templates, but you can override with Micro templates, etc.]</p>

<h3>Instantiating a Template Engine</h3>

<h3>Compiling and Rendering Templates</h3>

<h3>Precompiling and Reviving Templates</h3>

<h3>Creating a Custom Template Engine</h3>

<p>[how to create a template engine that conforms to the `Y.Template` API interface]</p>

<h2>Using `Template.Micro`</h2>

<p>[Overview of what Template.Micro is and what kinds of use cases it's suited for -- when you'd use it vs. Handlebars, etc.]</p>

<h3>Template Syntax</h3>

<h4>Basic Expressions</h4>

<h4>HTML Escaping</h4>

<h4>Inline Code &amp; Code Blocks</h4>

<h3>Compiling and Rendering Templates</h3>

<p>[may be redundant; possibly just refer to the Y.Template section above?]</p>

<h3>Precompiling and Reviving Templates</h3>

<p>[may be redundant; possibly just refer to the Y.Template section above?]</p>

<h3>Customizing Template Syntax</h3>

<p>[describe how to override Y.Template.Micro's regexes to customize the template syntax if desired]</p>

<h2>Using Templates in Custom Components</h2>

<p>[guidelines for bundling templates with custom views, widgets, etc. -- how to build, compile, and make them available on a namespace]</p>

<h2>Best Practices</h2>

<p>[recommended best practices for templates -- don't embed too much logic, don't embed huge template strings in JS, compile once; render often, etc.]</p>
132 changes: 132 additions & 0 deletions src/template/js/template-base.js
@@ -0,0 +1,132 @@
/**
Virtual rollup of the `template-base` and `template-micro` modules.

@module template
@main template
@since 3.8.0
**/

/**
Provides a generic API for using template engines such as Handlebars and
`Y.Template.Micro`.

@module template
@submodule template-base
@since 3.8.0
**/

/**
Provides a generic API for using template engines such as Handlebars and
`Y.Template.Micro`.

### Examples

Using with `Y.Template.Micro` (the default template engine):

YUI().use('template', function (Y) {
var micro = new Y.Template(),
html = micro.render('<%= data.message %>', {message: 'hello!'});

// ...
});

Using with Handlebars:

YUI().use('template-base', 'handlebars', function (Y) {
var handlebars = new Y.Template(Y.Handlebars),
html = handlebars.render('{{message}}', {message: 'hello!'});

// ...
});

@class Template
@param {Mixed} [engine=Y.Template.Micro] Template engine to use, such as
`Y.Template.Micro` or `Y.Handlebars`. Defaults to `Y.Template.Micro` if not
specified.
@constructor
@since 3.8.0
**/

function Template(engine) {
/**
Template engine class.

@property {Mixed} engine
**/
this.engine = engine || Y.Template.Micro;

if (!this.engine) {
Y.error('No template engine loaded.');
}
}

Template.prototype = {
/**
Compiles a template with the current template engine and returns a compiled
template function.

@method compile
@param {String} text Template text to compile.
@param {Object} [options] Options to pass along to the template engine. See
template engine docs for options supported by each engine.
@return {Function} Compiled template function.
**/
compile: function (text, options) {
return this.engine.compile(text, options);
},

/**
Precompiles a template with the current template engine and returns a string
containing JavaScript source code for the precompiled template.

@method precompile
@param {String} text Template text to compile.
@param {Object} [options] Options to pass along to the template engine. See
template engine docs for options supported by each engine.
@return {String} Source code for the precompiled template.
**/
precompile: function (text, options) {
return this.engine.precompile(text, options);
},

/**
Compiles and renders a template with the current template engine in a single
step, and returns the rendered result.

@method render
@param {String} text Template text to render.
@param {Object} data Data object to provide when rendering the template.
@param {Object} [options] Options to pass along to the template engine. See
template engine docs for options supported by each engine.
@return {String} Rendered result.
**/
render: function (text, data, options) {
if (this.engine.render) {
return this.engine.render(text, data, options);
}

return this.engine.compile(text, options)(data, options);
},

/**
Revives a precompiled template function into an executable template function
using the current template engine. The precompiled code must already have
been evaluated; this method won't evaluate it for you.

@method revive
@param {Function} precompiled Precompiled template function.
@param {Object} [options] Options to pass along to the template engine. See
template engine docs for options supported by each engine.
@return {Function} Compiled template function.
**/
revive: function (precompiled, options) {
return this.engine.revive ? this.engine.revive(precompiled, options) :
precompiled;
}
};

// Copy existing namespaced properties from Y.Template to the Template function
// if Y.Template already exists, then make the function the new Y.Template.
// This ensures that other modules can safely add stuff to the Y.Template
// namespace even if they're loaded before this one.
Y.Template = Y.Template ? Y.mix(Template, Y.Template) : Template;