import ngModule from '../module'; import {ng} from '../vendor'; function stringify(value) { if (value === null) { // null || undefined return ''; } switch (typeof value) { case 'string': break; case 'number': value = String(value); break; default: value = angular.toJson(value); } return value; } var $interpolateMinErr = ng.$interpolateMinErr = ng.$$minErr('$interpolate'); $interpolateMinErr.throwNoconcat = function(text) { throw $interpolateMinErr('noconcat', 'Error while interpolating: {0}\nStrict Contextual Escaping disallows ' + 'interpolations that concatenate multiple expressions when a trusted value is ' + 'required. See http://docs.angularjs.org/api/ng.$sce', text); }; $interpolateMinErr.interr = function(text, err) { return $interpolateMinErr('interr', 'Can\'t interpolate: {0}\n{1}', text, err.toString()); }; function $get($parse, $exceptionHandler, $sce) { let startSymbolLength = this._startSymbol.length; let endSymbolLength = this._endSymbol.length; let escapedStartRegexp = new RegExp(this._startSymbol.replace(/./g, escape), 'g'); let escapedEndRegexp = new RegExp(this._endSymbol.replace(/./g, escape), 'g'); let self = this; function escape(ch) { return '\\\\\\' + ch; } function unescapeText(text) { return text.replace(escapedStartRegexp, self._startSymbol) .replace(escapedEndRegexp, self._endSymbol); } // TODO: this is the same as the constantWatchDelegate in parse.js function constantWatchDelegate(scope, listener, objectEquality, constantInterp) { var unwatch = scope.$watch(function constantInterpolateWatch(scope) { unwatch(); return constantInterp(scope); }, listener, objectEquality); return unwatch; } function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { // Provide a quick exit and simplified result function for text with no interpolation if (!text.length || text.indexOf(self._startSymbol) === -1) { var constantInterp; if (!mustHaveExpression) { var unescapedText = unescapeText(text); constantInterp = valueFn(unescapedText); constantInterp.exp = text; constantInterp.expressions = []; constantInterp.$$watchDelegate = constantWatchDelegate; } return constantInterp; } allOrNothing = Boolean(allOrNothing); let startIndex; let endIndex; let index = 0; let expressions = []; let parseFns = []; let textLength = text.length; let exp; let concat = []; let expressionPositions = []; while (index < textLength) { if (((startIndex = text.indexOf(self._startSymbol, index)) !== -1) && ((endIndex = text.indexOf(self._endSymbol, startIndex + startSymbolLength)) !== -1)) { if (index !== startIndex) concat.push(unescapeText(text.substring(index, startIndex))); exp = text.substring(startIndex + startSymbolLength, endIndex); expressions.push(exp); parseFns.push($parse(exp, parseStringifyInterceptor)); index = endIndex + endSymbolLength; expressionPositions.push(concat.length); concat.push(''); } else { // we did not find an interpolation, so we have to add the remainder to the separators array if (index !== textLength) concat.push(unescapeText(text.substring(index))); break; } } if (trustedContext && concat.length > 1) { $interpolateMinErr.throwNoconcat(text); } var getValue = function(value) { return trustedContext ? $sce.getTrusted(trustedContext, value) : $sce.valueOf(value); }; if (!mustHaveExpression || expressions.length) { var compute = function(values) { for (var i = 0, ii = expressions.length; i < ii; i++) { if (allOrNothing && isUndefined(values[i])) return; concat[expressionPositions[i]] = values[i]; } return concat.join(''); }; return angular.extend(function interpolationFn(context) { var i = 0; var ii = expressions.length; var values = new Array(ii); try { for (; i < ii; i++) { values[i] = parseFns[i](context); } return compute(values); } catch (err) { $exceptionHandler($interpolateMinErr.interr(text, err)); } }, { // all of these properties are undocumented for now exp: text, // just for compatibility with regular watchers created via $watch expressions: expressions }); } function parseStringifyInterceptor(value) { try { value = getValue(value); return allOrNothing && !isDefined(value) ? value : stringify(value); } catch (err) { $exceptionHandler($interpolateMinErr.interr(text, err)); } } } $interpolate.startSymbol = function() { return startSymbol; }; $interpolate.endSymbol = function() { return endSymbol; }; return $interpolate; } $get.$inject = ['$parse', '$exceptionHandler', '$sce']; export class Interpolate { constructor() { this._startSymbol = '*['; this._endSymbol = ']*'; } set startSymbol(value) { if (value) { this._startSymbol = value; return this; } return this._startSymbol; } set endSymbol(value) { if (value) { this._endSymbol = value; return this; } return this._endSymbol; } } Interpolate.prototype.$get = $get; var interpolate = new Interpolate(); ngModule.provider('vnInterpolate', () => interpolate);