123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- /* eslint-disable no-shadow */
- define([
- 'jquery',
- 'underscore',
- 'mage/utils/objects',
- 'mage/utils/strings'
- ], function ($, _, utils, stringUtils) {
- 'use strict';
- var tmplSettings = _.templateSettings,
- interpolate = /\$\{([\s\S]+?)\}/g,
- opener = '${',
- template,
- hasStringTmpls;
- /**
- * Identifies whether ES6 templates are supported.
- */
- hasStringTmpls = (function () {
- var testString = 'var foo = "bar"; return `${ foo }` === foo';
- try {
- return Function(testString)();
- } catch (e) {
- return false;
- }
- })();
- if (hasStringTmpls) {
- /*eslint-disable no-unused-vars, no-eval*/
- /**
- * Evaluates template string using ES6 templates.
- *
- * @param {String} tmpl - Template string.
- * @param {Object} $ - Data object used in a template.
- * @returns {String} Compiled template.
- */
- template = function (tmpl, $) {
- return eval('`' + tmpl + '`');
- };
- /*eslint-enable no-unused-vars, no-eval*/
- } else {
- /**
- * Fallback function used when ES6 templates are not supported.
- * Uses underscore templates renderer.
- *
- * @param {String} tmpl - Template string.
- * @param {Object} data - Data object used in a template.
- * @returns {String} Compiled template.
- */
- template = function (tmpl, data) {
- var cached = tmplSettings.interpolate;
- tmplSettings.interpolate = interpolate;
- tmpl = _.template(tmpl, {
- variable: '$'
- })(data);
- tmplSettings.interpolate = cached;
- return tmpl;
- };
- }
- /**
- * Checks if provided value contains template syntax.
- *
- * @param {*} value - Value to be checked.
- * @returns {Boolean}
- */
- function isTemplate(value) {
- return typeof value === 'string' &&
- value.indexOf(opener) !== -1 &&
- // the below pattern almost always indicates an accident which should not cause template evaluation
- // refuse to evaluate
- value.indexOf('${{') === -1;
- }
- /**
- * Iteratively processes provided string
- * until no templates syntax will be found.
- *
- * @param {String} tmpl - Template string.
- * @param {Object} data - Data object used in a template.
- * @param {Boolean} [castString=false] - Flag that indicates whether template
- * should be casted after evaluation to a value of another type or
- * that it should be leaved as a string.
- * @returns {*} Compiled template.
- */
- function render(tmpl, data, castString) {
- var last = tmpl;
- while (~tmpl.indexOf(opener)) {
- tmpl = template(tmpl, data);
- if (tmpl === last) {
- break;
- }
- last = tmpl;
- }
- return castString ?
- stringUtils.castString(tmpl) :
- tmpl;
- }
- return {
- /**
- * Applies provided data to the template.
- *
- * @param {Object|String} tmpl
- * @param {Object} [data] - Data object to match with template.
- * @param {Boolean} [castString=false] - Flag that indicates whether template
- * should be casted after evaluation to a value of another type or
- * that it should be leaved as a string.
- * @returns {*}
- *
- * @example Template defined as a string.
- * var source = { foo: 'Random Stuff', bar: 'Some' };
- *
- * utils.template('${ $.bar } ${ $.foo }', source);
- * => 'Some Random Stuff';
- *
- * @example Template defined as an object.
- * var tmpl = {
- * key: {'${ $.$data.bar }': '${ $.$data.foo }'},
- * foo: 'bar',
- * x1: 2, x2: 5,
- * delta: '${ $.x2 - $.x1 }',
- * baz: 'Upper ${ $.foo.toUpperCase() }'
- * };
- *
- * utils.template(tmpl, source);
- * => {
- * key: {'Some': 'Random Stuff'},
- * foo: 'bar',
- * x1: 2, x2: 5,
- * delta: 3,
- * baz: 'Upper BAR'
- * };
- */
- template: function (tmpl, data, castString, dontClone) {
- if (typeof tmpl === 'string') {
- return render(tmpl, data, castString);
- }
- if (!dontClone) {
- tmpl = utils.copy(tmpl);
- }
- tmpl.$data = data || {};
- /**
- * Template iterator function.
- */
- _.each(tmpl, function iterate(value, key, list) {
- if (key === '$data') {
- return;
- }
- if (isTemplate(key)) {
- delete list[key];
- key = render(key, tmpl);
- list[key] = value;
- }
- if (isTemplate(value)) {
- list[key] = render(value, tmpl, castString);
- } else if ($.isPlainObject(value) || Array.isArray(value)) {
- _.each(value, iterate);
- }
- });
- delete tmpl.$data;
- return tmpl;
- }
- };
- });
|