Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Commit

Permalink
feat(): add option to html escape all values
Browse files Browse the repository at this point in the history
Apply an additional functionaly to an interpolator being responsible for escaping interpolated params or using a sanitation service when working with them.

For the default interpolation service, the usage will be:

```javascript
// config
translationProvider.useSanitizedValues(true);
// scope
$scope.user = {link: '/user', name: '<h1>Big User</h1>'};
```

and

```html
<a href="{user.link}">{user.name}</a>
```

will results into the html

```html
<a href="/user">&lt;h1&gt;Big User&lt;/h1&gt;</a>
```
  • Loading branch information
knalli committed Oct 13, 2013
1 parent 0d448b7 commit fe94c1f
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 1 deletion.
21 changes: 20 additions & 1 deletion src/service/default-interpolation.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,18 @@ angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation

var $translateInterpolator = {},
$locale,
$identifier = 'default';
$identifier = 'default',
$useSanitizedValues = false;

var sanitizeParams = function (params) {
var result = {};
for (var key in params) {
if (params.hasOwnProperty(key)) {
result[key] = angular.element('<div></div>').text(params[key]).html();
}
}
return result;
};

/**
* @ngdoc function
Expand Down Expand Up @@ -42,6 +53,11 @@ angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation
return $identifier;
};

$translateInterpolator.useSanitizedValues = function (value) {
$useSanitizedValues = (value === true);
return this;
};

/**
* @ngdoc function
* @name pascalprecht.translate.$translateDefaultInterpolation#interpolate
Expand All @@ -54,6 +70,9 @@ angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation
* @returns {string} interpolated string.
*/
$translateInterpolator.interpolate = function (string, interpolateParams) {
if ($useSanitizedValues) {
interpolateParams = sanitizeParams(interpolateParams);
}
return $interpolate(string)(interpolateParams);
};

Expand Down
15 changes: 15 additions & 0 deletions src/service/translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
$missingTranslationHandlerFactory,
$interpolationFactory,
$interpolatorFactories = [],
$interpolationSanitization = false,
$loaderFactory,
$loaderOptions,
$notFoundIndicatorLeft,
Expand Down Expand Up @@ -168,6 +169,11 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
return this;
};

this.useSanitizedValues = function (value) {
$interpolationSanitization = value;
return this;
};

/**
* @ngdoc function
* @name pascalprecht.translate.$translateProvider#preferredLanguage
Expand Down Expand Up @@ -559,6 +565,11 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
}
}

// apply additional settings
if (typeof defaultInterpolator.useSanitizedValues === 'function') {
defaultInterpolator.useSanitizedValues($interpolationSanitization);
}

// if we have additional interpolations that were added via
// $translateProvider.addInterpolation(), we have to map'em
if ($interpolatorFactories.length > 0) {
Expand All @@ -568,6 +579,10 @@ angular.module('pascalprecht.translate').provider('$translate', ['$STORAGE_KEY',
var interpolator = $injector.get(interpolatorFactory);
// setting initial locale for each interpolation service
interpolator.setLocale($preferredLanguage || $uses);
// apply additional settings
if (typeof interpolator.useSanitizedValues === 'function') {
interpolator.useSanitizedValues($interpolationSanitization);
}
// make'em recognizable through id
interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator;
});
Expand Down
55 changes: 55 additions & 0 deletions test/unit/directive/translate.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,4 +410,59 @@ describe('pascalprecht.translate', function () {
expect(element.text()).toEqual('custom interpolation');
});
});

describe('translate sanitization', function () {

var $rootScope, $compile;

beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide) {

$translateProvider.translations('en', {
'hacking': '{{v}}'
});

$translateProvider.preferredLanguage('en');
}));

beforeEach(inject(function (_$rootScope_, _$compile_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
}));

it('should be disabled at default', function () {
element = $compile('<p translate="hacking" translate-values="{v: \'<u>test</u>\'}"></p>')($rootScope);
$rootScope.$digest();
// Verify content is not escaped.
expect(element.text()).toEqual('test');
expect(element.html()).toEqual('<u>test</u>');
});
});

describe('translate sanitization (escaping)', function () {

var $rootScope, $compile;

beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide) {

$translateProvider.translations('en', {
'hacking': '{{v}}'
});

$translateProvider.preferredLanguage('en');
$translateProvider.useSanitizedValues(true);
}));

beforeEach(inject(function (_$rootScope_, _$compile_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
}));

it('should be enabled via useSanitizedValues(true)', function () {
element = $compile('<p translate="hacking" translate-values="{v: \'<u>test</u>\'}"></p>')($rootScope);
$rootScope.$digest();
// Verify content is escaped.
expect(element.text()).toEqual('<u>test</u>'); // possible because text
expect(element.html()).toEqual('&lt;u&gt;test&lt;/u&gt;');
});
});
});

0 comments on commit fe94c1f

Please sign in to comment.