@atlassian/aui
Version:
Atlassian User Interface Framework
132 lines (116 loc) • 3.83 kB
JavaScript
import $ from './jquery';
import escapeHtml from './escape-html';
import globalize from './internal/globalize';
/**
* Creates an object with methods for template support.
*
* See <a href="http://confluence.atlassian.com/display/AUI/AJS.template">CAC Documentation</a>.
*
* @constructor
* @class template
* @namespace AJS
*/
var template = (function ($) {
var tokenRegex = /\{([^\}]+)\}/g; // matches "{xxxxx}"
var objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g; // matches ".xxxxx" or "["xxxxx"]" to run over object properties
// internal function
// parses "{xxxxx}" and returns actual value from the given object that matches the expression
var replacer = function (all, key, obj, isHTML) {
var res = obj;
key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
name = name || quotedName;
if (res) {
if (name + ':html' in res) {
res = res[name + ':html'];
isHTML = true;
} else if (name in res) {
res = res[name];
}
if (isFunc && typeof res === 'function') {
res = res();
}
}
});
// if not found restore original value
if (res == null || res === obj) {
res = all;
}
res = String(res);
if (!isHTML) {
res = T.escape(res);
}
return res;
};
/**
* Replaces tokens in the template with corresponding values without HTML escaping
* @method fillHtml
* @param obj {Object} to populate the template with
* @return {Object} the template object
*/
var fillHtml = function (obj) {
this.template = this.template.replace(tokenRegex, function (all, key) {
return replacer(all, key, obj, true);
});
return this;
};
/**
* Replaces tokens in the template with corresponding values with HTML escaping
* @method fill
* @param obj {Object} to populate the template with
* @return {Object} the template object
*/
var fill = function (obj) {
this.template = this.template.replace(tokenRegex, function (all, key) {
return replacer(all, key, obj);
});
return this;
};
/**
* Returns the current templated string.
* @method toString
* @return {String} the current template
*/
var toString = function () {
return this.template;
};
// internal function
var T = function (s) {
function res() {
return res.template;
}
/**
* The current templated string
* @property template
*/
res.template = String(s);
res.toString = res.valueOf = toString;
res.fill = fill;
res.fillHtml = fillHtml;
return res;
};
var cache = {};
var count = [];
var findScripts = function (title) {
return $('script').filter(function () {
return this.getAttribute('title') === title;
});
};
// returns template taken form the script tag with given title. Type agnostic, but better put type="text/x-template"
T.load = function (title) {
title = String(title);
if (!cache.hasOwnProperty(title)) {
if (count.length >= 1e3) {
delete cache[count.shift()]; // enforce maximum cache size
}
count.push(title);
cache[title] = findScripts(title)[0].text;
}
return this(cache[title]);
};
// escape HTML dangerous characters
T.escape = escapeHtml;
return T;
}($));
globalize('template', template);
export default template;
;