Skip to content

Commit

Permalink
feat(pipes): add ReplacePipe for string manipulation
Browse files Browse the repository at this point in the history
add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.

feat(pipes): add ReplacePipe for string manipulation

add commonly used pipe that is missing  from framework.
  • Loading branch information
RobiFerentz authored and vsavkin committed Feb 25, 2016
1 parent 38cb526 commit 6ef2121
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 2 deletions.
5 changes: 4 additions & 1 deletion modules/angular2/src/common/pipes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {JsonPipe} from './pipes/json_pipe';
import {SlicePipe} from './pipes/slice_pipe';
import {DatePipe} from './pipes/date_pipe';
import {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
import {ReplacePipe} from './pipes/replace_pipe';
import {CONST_EXPR} from 'angular2/src/facade/lang';

export {AsyncPipe} from './pipes/async_pipe';
Expand All @@ -19,6 +20,7 @@ export {SlicePipe} from './pipes/slice_pipe';
export {LowerCasePipe} from './pipes/lowercase_pipe';
export {NumberPipe, DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
export {UpperCasePipe} from './pipes/uppercase_pipe';
export {ReplacePipe} from './pipes/replace_pipe';

/**
* A collection of Angular core pipes that are likely to be used in each and every
Expand All @@ -36,5 +38,6 @@ export const COMMON_PIPES = CONST_EXPR([
DecimalPipe,
PercentPipe,
CurrencyPipe,
DatePipe
DatePipe,
ReplacePipe
]);
4 changes: 3 additions & 1 deletion modules/angular2/src/common/pipes/common_pipes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {JsonPipe} from './json_pipe';
import {SlicePipe} from './slice_pipe';
import {DatePipe} from './date_pipe';
import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe';
import {ReplacePipe} from './replace_pipe';
import {CONST_EXPR} from 'angular2/src/facade/lang';

/**
Expand All @@ -28,5 +29,6 @@ export const COMMON_PIPES = CONST_EXPR([
DecimalPipe,
PercentPipe,
CurrencyPipe,
DatePipe
DatePipe,
ReplacePipe
]);
91 changes: 91 additions & 0 deletions modules/angular2/src/common/pipes/replace_pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {
isBlank,
isString,
isNumber,
isFunction,
RegExpWrapper,
StringWrapper
} from 'angular2/src/facade/lang';
import {BaseException} from 'angular2/src/facade/exceptions';
import {Injectable, PipeTransform, Pipe} from 'angular2/core';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';

/**
* Creates a new String with some or all of the matches of a pattern replaced by
* a replacement.
*
* The pattern to be matched is specified by the 'pattern' parameter.
*
* The replacement to be set is specified by the 'replacement' parameter.
*
* An optional 'flags' parameter can be set.
*
* ### Usage
*
* expression | replace:pattern:replacement
*
* All behavior is based on the expected behavior of the JavaScript API
* String.prototype.replace() function.
*
* Where the input expression is a [String] or [Number] (to be treated as a string),
* the `pattern` is a [String] or [RegExp],
* the 'replacement' is a [String] or [Function].
*
* --Note--: The 'pattern' parameter will be converted to a RegExp instance. Make sure to escape the

This comment has been minimized.

Copy link
@gkalpak

gkalpak Mar 8, 2016

Member

Isn't this only true when replacement is a function ?

* string properly if you are matching for regular expression special characters like parenthesis,
* brackets etc.
*/

@Pipe({name: 'replace'})
@Injectable()
export class ReplacePipe implements PipeTransform {
transform(value: any, args: any[]): any {
if (isBlank(args) || args.length !== 2) {
throw new BaseException('ReplacePipe requires two arguments');
}

if (isBlank(value)) {
return value;
}

if (!this._supportedInput(value)) {
throw new InvalidPipeArgumentException(ReplacePipe, value);
}

var input = value.toString();
var pattern = args[0];
var replacement = args[1];


if (!this._supportedPattern(pattern)) {
throw new InvalidPipeArgumentException(ReplacePipe, pattern);
}
if (!this._supportedReplacement(replacement)) {
throw new InvalidPipeArgumentException(ReplacePipe, replacement);
}
// template fails with literal RegExp e.g /pattern/igm
// var rgx = pattern instanceof RegExp ? pattern : RegExpWrapper.create(pattern);

if (isFunction(replacement)) {
var rgxPattern = isString(pattern) ? RegExpWrapper.create(pattern) : pattern;

return StringWrapper.replaceAllMapped(input, rgxPattern, replacement);
}
if (pattern instanceof RegExp) {
// use the replaceAll variant
return StringWrapper.replaceAll(input, pattern, replacement);
}

return StringWrapper.replace(input, pattern, replacement);
}

private _supportedInput(input: any): boolean { return isString(input) || isNumber(input); }

private _supportedPattern(pattern: any): boolean {
return isString(pattern) || pattern instanceof RegExp;
}

private _supportedReplacement(replacement: any): boolean {
return isString(replacement) || isFunction(replacement);
}
}
73 changes: 73 additions & 0 deletions modules/angular2/test/common/pipes/replace_pipe_spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
browserDetection,
inject,
TestComponentBuilder,
AsyncTestCompleter
} from 'angular2/testing_internal';

import {ReplacePipe} from 'angular2/common';
import {RegExpWrapper, StringJoiner} from 'angular2/src/facade/lang';

export function main() {
describe("ReplacePipe", () => {
var someNumber: number;
var str;
var pipe;

beforeEach(() => {
someNumber = 42;
str = 'Douglas Adams';
pipe = new ReplacePipe();
});

describe("transform", () => {

it("should not support input other than strings and numbers", () => {
expect(() => pipe.transform({}, ["Douglas", "Hugh"])).toThrow();
expect(() => pipe.transform([1, 2, 3], ["Douglas", "Hugh"])).toThrow();
});

it("should not support patterns other than strings and regular expressions", () => {
expect(() => pipe.transform(str, [{}, "Hugh"])).toThrow();
expect(() => pipe.transform(str, [null, "Hugh"])).toThrow();
expect(() => pipe.transform(str, [123, "Hugh"])).toThrow();
});

it("should not support replacements other than strings and functions", () => {
expect(() => pipe.transform(str, ["Douglas", {}])).toThrow();
expect(() => pipe.transform(str, ["Douglas", null])).toThrow();
expect(() => pipe.transform(str, ["Douglas", 123])).toThrow();
});

it("should return a new string with the pattern replaced", () => {
var result1 = pipe.transform(str, ["Douglas", "Hugh"]);

var result2 = pipe.transform(str, [RegExpWrapper.create("a"), "_"]);

var result3 = pipe.transform(str, [RegExpWrapper.create("a", "i"), "_"]);

var f = (x => { return "Adams!"; });

var result4 = pipe.transform(str, ["Adams", f]);

var result5 = pipe.transform(someNumber, ["2", "4"]);

expect(result1).toEqual("Hugh Adams");
expect(result2).toEqual("Dougl_s Ad_ms");
expect(result3).toEqual("Dougl_s _d_ms");
expect(result4).toEqual("Douglas Adams!");
expect(result5).toEqual("44");
});

});

});
}
2 changes: 2 additions & 0 deletions modules/angular2/test/public_api_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ var NG_COMMON = [
'PatternValidator.validate()',
'PercentPipe',
'PercentPipe.transform()',
'ReplacePipe',
'ReplacePipe.transform()',
'RequiredValidator',
'SelectControlValueAccessor',
'SelectControlValueAccessor.onChange',
Expand Down
2 changes: 2 additions & 0 deletions tools/public_api_guard/public_api_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,8 @@ const COMMON = [
'PatternValidator.validate(c:Control):{[key:string]:any}',
'PercentPipe',
'PercentPipe.transform(value:any, args:any[]):string',
'ReplacePipe',
'ReplacePipe.transform(value:any, args:any[]):any',
'RequiredValidator',
'SelectControlValueAccessor',
'SelectControlValueAccessor.constructor(_renderer:Renderer, _elementRef:ElementRef, query:QueryList<NgSelectOption>)',
Expand Down

0 comments on commit 6ef2121

Please sign in to comment.