UNPKG

@atlassian/aui

Version:

Atlassian User Interface Framework

132 lines (116 loc) 3.83 kB
'use strict'; 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;