You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					104 lines
				
				3.4 KiB
			
		
		
			
		
	
	
					104 lines
				
				3.4 KiB
			| 
											3 years ago
										 | define(['./defaults', './underscore', './templateSettings'], function (defaults, underscore, templateSettings) { | ||
|  | 
 | ||
|  |   // When customizing `_.templateSettings`, if you don't want to define an
 | ||
|  |   // interpolation, evaluation or escaping regex, we need one that is
 | ||
|  |   // guaranteed not to match.
 | ||
|  |   var noMatch = /(.)^/; | ||
|  | 
 | ||
|  |   // Certain characters need to be escaped so that they can be put into a
 | ||
|  |   // string literal.
 | ||
|  |   var escapes = { | ||
|  |     "'": "'", | ||
|  |     '\\': '\\', | ||
|  |     '\r': 'r', | ||
|  |     '\n': 'n', | ||
|  |     '\u2028': 'u2028', | ||
|  |     '\u2029': 'u2029' | ||
|  |   }; | ||
|  | 
 | ||
|  |   var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g; | ||
|  | 
 | ||
|  |   function escapeChar(match) { | ||
|  |     return '\\' + escapes[match]; | ||
|  |   } | ||
|  | 
 | ||
|  |   // In order to prevent third-party code injection through
 | ||
|  |   // `_.templateSettings.variable`, we test it against the following regular
 | ||
|  |   // expression. It is intentionally a bit more liberal than just matching valid
 | ||
|  |   // identifiers, but still prevents possible loopholes through defaults or
 | ||
|  |   // destructuring assignment.
 | ||
|  |   var bareIdentifier = /^\s*(\w|\$)+\s*$/; | ||
|  | 
 | ||
|  |   // JavaScript micro-templating, similar to John Resig's implementation.
 | ||
|  |   // Underscore templating handles arbitrary delimiters, preserves whitespace,
 | ||
|  |   // and correctly escapes quotes within interpolated code.
 | ||
|  |   // NB: `oldSettings` only exists for backwards compatibility.
 | ||
|  |   function template(text, settings, oldSettings) { | ||
|  |     if (!settings && oldSettings) settings = oldSettings; | ||
|  |     settings = defaults({}, settings, underscore.templateSettings); | ||
|  | 
 | ||
|  |     // Combine delimiters into one regular expression via alternation.
 | ||
|  |     var matcher = RegExp([ | ||
|  |       (settings.escape || noMatch).source, | ||
|  |       (settings.interpolate || noMatch).source, | ||
|  |       (settings.evaluate || noMatch).source | ||
|  |     ].join('|') + '|$', 'g'); | ||
|  | 
 | ||
|  |     // Compile the template source, escaping string literals appropriately.
 | ||
|  |     var index = 0; | ||
|  |     var source = "__p+='"; | ||
|  |     text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { | ||
|  |       source += text.slice(index, offset).replace(escapeRegExp, escapeChar); | ||
|  |       index = offset + match.length; | ||
|  | 
 | ||
|  |       if (escape) { | ||
|  |         source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; | ||
|  |       } else if (interpolate) { | ||
|  |         source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; | ||
|  |       } else if (evaluate) { | ||
|  |         source += "';\n" + evaluate + "\n__p+='"; | ||
|  |       } | ||
|  | 
 | ||
|  |       // Adobe VMs need the match returned to produce the correct offset.
 | ||
|  |       return match; | ||
|  |     }); | ||
|  |     source += "';\n"; | ||
|  | 
 | ||
|  |     var argument = settings.variable; | ||
|  |     if (argument) { | ||
|  |       // Insure against third-party code injection. (CVE-2021-23358)
 | ||
|  |       if (!bareIdentifier.test(argument)) throw new Error( | ||
|  |         'variable is not a bare identifier: ' + argument | ||
|  |       ); | ||
|  |     } else { | ||
|  |       // If a variable is not specified, place data values in local scope.
 | ||
|  |       source = 'with(obj||{}){\n' + source + '}\n'; | ||
|  |       argument = 'obj'; | ||
|  |     } | ||
|  | 
 | ||
|  |     source = "var __t,__p='',__j=Array.prototype.join," + | ||
|  |       "print=function(){__p+=__j.call(arguments,'');};\n" + | ||
|  |       source + 'return __p;\n'; | ||
|  | 
 | ||
|  |     var render; | ||
|  |     try { | ||
|  |       render = new Function(argument, '_', source); | ||
|  |     } catch (e) { | ||
|  |       e.source = source; | ||
|  |       throw e; | ||
|  |     } | ||
|  | 
 | ||
|  |     var template = function(data) { | ||
|  |       return render.call(this, data, underscore); | ||
|  |     }; | ||
|  | 
 | ||
|  |     // Provide the compiled source as a convenience for precompilation.
 | ||
|  |     template.source = 'function(' + argument + '){\n' + source + '}'; | ||
|  | 
 | ||
|  |     return template; | ||
|  |   } | ||
|  | 
 | ||
|  |   return template; | ||
|  | 
 | ||
|  | }); |