source: frontend/node_modules/underscore/modules/template.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 3.2 KB
Line 
1import defaults from './defaults.js';
2import _ from './underscore.js';
3import './templateSettings.js';
4
5// When customizing `_.templateSettings`, if you don't want to define an
6// interpolation, evaluation or escaping regex, we need one that is
7// guaranteed not to match.
8var noMatch = /(.)^/;
9
10// Certain characters need to be escaped so that they can be put into a
11// string literal.
12var escapes = {
13 "'": "'",
14 '\\': '\\',
15 '\r': 'r',
16 '\n': 'n',
17 '\u2028': 'u2028',
18 '\u2029': 'u2029'
19};
20
21var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;
22
23function escapeChar(match) {
24 return '\\' + escapes[match];
25}
26
27// In order to prevent third-party code injection through
28// `_.templateSettings.variable`, we test it against the following regular
29// expression. It is intentionally a bit more liberal than just matching valid
30// identifiers, but still prevents possible loopholes through defaults or
31// destructuring assignment.
32var bareIdentifier = /^\s*(\w|\$)+\s*$/;
33
34// JavaScript micro-templating, similar to John Resig's implementation.
35// Underscore templating handles arbitrary delimiters, preserves whitespace,
36// and correctly escapes quotes within interpolated code.
37// NB: `oldSettings` only exists for backwards compatibility.
38export default function template(text, settings, oldSettings) {
39 if (!settings && oldSettings) settings = oldSettings;
40 settings = defaults({}, settings, _.templateSettings);
41
42 // Combine delimiters into one regular expression via alternation.
43 var matcher = RegExp([
44 (settings.escape || noMatch).source,
45 (settings.interpolate || noMatch).source,
46 (settings.evaluate || noMatch).source
47 ].join('|') + '|$', 'g');
48
49 // Compile the template source, escaping string literals appropriately.
50 var index = 0;
51 var source = "__p+='";
52 text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
53 source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
54 index = offset + match.length;
55
56 if (escape) {
57 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
58 } else if (interpolate) {
59 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
60 } else if (evaluate) {
61 source += "';\n" + evaluate + "\n__p+='";
62 }
63
64 // Adobe VMs need the match returned to produce the correct offset.
65 return match;
66 });
67 source += "';\n";
68
69 var argument = settings.variable;
70 if (argument) {
71 // Insure against third-party code injection. (CVE-2021-23358)
72 if (!bareIdentifier.test(argument)) throw new Error(
73 'variable is not a bare identifier: ' + argument
74 );
75 } else {
76 // If a variable is not specified, place data values in local scope.
77 source = 'with(obj||{}){\n' + source + '}\n';
78 argument = 'obj';
79 }
80
81 source = "var __t,__p='',__j=Array.prototype.join," +
82 "print=function(){__p+=__j.call(arguments,'');};\n" +
83 source + 'return __p;\n';
84
85 var render;
86 try {
87 render = new Function(argument, '_', source);
88 } catch (e) {
89 e.source = source;
90 throw e;
91 }
92
93 var template = function(data) {
94 return render.call(this, data, _);
95 };
96
97 // Provide the compiled source as a convenience for precompilation.
98 template.source = 'function(' + argument + '){\n' + source + '}';
99
100 return template;
101}
Note: See TracBrowser for help on using the repository browser.