203 lines
6.5 KiB
JavaScript
203 lines
6.5 KiB
JavaScript
|
import {module} from './module';
|
||
|
import {ng} from 'vendor';
|
||
|
import * as util from './util';
|
||
|
|
||
|
export const NAME = util.getProviderName('interpolate');
|
||
|
|
||
|
function minErr() {}
|
||
|
|
||
|
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.angular.$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) {
|
||
|
var startSymbolLength = this._startSymbol.length,
|
||
|
endSymbolLength = this._endSymbol.length,
|
||
|
escapedStartRegexp = new RegExp(this._startSymbol.replace(/./g, escape), 'g'),
|
||
|
escapedEndRegexp = new RegExp(this._endSymbol.replace(/./g, escape), 'g'),
|
||
|
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);
|
||
|
var startIndex,
|
||
|
endIndex,
|
||
|
index = 0,
|
||
|
expressions = [],
|
||
|
parseFns = [],
|
||
|
textLength = text.length,
|
||
|
exp,
|
||
|
concat = [],
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
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('');
|
||
|
};
|
||
|
|
||
|
var getValue = function(value) {
|
||
|
return trustedContext ?
|
||
|
$sce.getTrusted(trustedContext, value) :
|
||
|
$sce.valueOf(value);
|
||
|
};
|
||
|
|
||
|
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;
|
||
|
} else {
|
||
|
return this._startSymbol;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set endSymbol(value) {
|
||
|
if (value) {
|
||
|
this._endSymbol = value;
|
||
|
return this;
|
||
|
} else {
|
||
|
return this._endSymbol;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
Interpolate.prototype.$get = $get;
|
||
|
var interpolate = new Interpolate();
|
||
|
module.provider(NAME, () => interpolate);
|