X Tutup
Skip to content

Commit 6ef2121

Browse files
RobiFerentzvsavkin
authored andcommitted
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. feat(pipes): add ReplacePipe for string manipulation add commonly used pipe that is missing from framework.
1 parent 38cb526 commit 6ef2121

File tree

6 files changed

+175
-2
lines changed

6 files changed

+175
-2
lines changed

modules/angular2/src/common/pipes.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {JsonPipe} from './pipes/json_pipe';
1010
import {SlicePipe} from './pipes/slice_pipe';
1111
import {DatePipe} from './pipes/date_pipe';
1212
import {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
13+
import {ReplacePipe} from './pipes/replace_pipe';
1314
import {CONST_EXPR} from 'angular2/src/facade/lang';
1415

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

2325
/**
2426
* A collection of Angular core pipes that are likely to be used in each and every
@@ -36,5 +38,6 @@ export const COMMON_PIPES = CONST_EXPR([
3638
DecimalPipe,
3739
PercentPipe,
3840
CurrencyPipe,
39-
DatePipe
41+
DatePipe,
42+
ReplacePipe
4043
]);

modules/angular2/src/common/pipes/common_pipes.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {JsonPipe} from './json_pipe';
1010
import {SlicePipe} from './slice_pipe';
1111
import {DatePipe} from './date_pipe';
1212
import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe';
13+
import {ReplacePipe} from './replace_pipe';
1314
import {CONST_EXPR} from 'angular2/src/facade/lang';
1415

1516
/**
@@ -28,5 +29,6 @@ export const COMMON_PIPES = CONST_EXPR([
2829
DecimalPipe,
2930
PercentPipe,
3031
CurrencyPipe,
31-
DatePipe
32+
DatePipe,
33+
ReplacePipe
3234
]);
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import {
2+
isBlank,
3+
isString,
4+
isNumber,
5+
isFunction,
6+
RegExpWrapper,
7+
StringWrapper
8+
} from 'angular2/src/facade/lang';
9+
import {BaseException} from 'angular2/src/facade/exceptions';
10+
import {Injectable, PipeTransform, Pipe} from 'angular2/core';
11+
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
12+
13+
/**
14+
* Creates a new String with some or all of the matches of a pattern replaced by
15+
* a replacement.
16+
*
17+
* The pattern to be matched is specified by the 'pattern' parameter.
18+
*
19+
* The replacement to be set is specified by the 'replacement' parameter.
20+
*
21+
* An optional 'flags' parameter can be set.
22+
*
23+
* ### Usage
24+
*
25+
* expression | replace:pattern:replacement
26+
*
27+
* All behavior is based on the expected behavior of the JavaScript API
28+
* String.prototype.replace() function.
29+
*
30+
* Where the input expression is a [String] or [Number] (to be treated as a string),
31+
* the `pattern` is a [String] or [RegExp],
32+
* the 'replacement' is a [String] or [Function].
33+
*
34+
* --Note--: The 'pattern' parameter will be converted to a RegExp instance. Make sure to escape the
35+
* string properly if you are matching for regular expression special characters like parenthesis,
36+
* brackets etc.
37+
*/
38+
39+
@Pipe({name: 'replace'})
40+
@Injectable()
41+
export class ReplacePipe implements PipeTransform {
42+
transform(value: any, args: any[]): any {
43+
if (isBlank(args) || args.length !== 2) {
44+
throw new BaseException('ReplacePipe requires two arguments');
45+
}
46+
47+
if (isBlank(value)) {
48+
return value;
49+
}
50+
51+
if (!this._supportedInput(value)) {
52+
throw new InvalidPipeArgumentException(ReplacePipe, value);
53+
}
54+
55+
var input = value.toString();
56+
var pattern = args[0];
57+
var replacement = args[1];
58+
59+
60+
if (!this._supportedPattern(pattern)) {
61+
throw new InvalidPipeArgumentException(ReplacePipe, pattern);
62+
}
63+
if (!this._supportedReplacement(replacement)) {
64+
throw new InvalidPipeArgumentException(ReplacePipe, replacement);
65+
}
66+
// template fails with literal RegExp e.g /pattern/igm
67+
// var rgx = pattern instanceof RegExp ? pattern : RegExpWrapper.create(pattern);
68+
69+
if (isFunction(replacement)) {
70+
var rgxPattern = isString(pattern) ? RegExpWrapper.create(pattern) : pattern;
71+
72+
return StringWrapper.replaceAllMapped(input, rgxPattern, replacement);
73+
}
74+
if (pattern instanceof RegExp) {
75+
// use the replaceAll variant
76+
return StringWrapper.replaceAll(input, pattern, replacement);
77+
}
78+
79+
return StringWrapper.replace(input, pattern, replacement);
80+
}
81+
82+
private _supportedInput(input: any): boolean { return isString(input) || isNumber(input); }
83+
84+
private _supportedPattern(pattern: any): boolean {
85+
return isString(pattern) || pattern instanceof RegExp;
86+
}
87+
88+
private _supportedReplacement(replacement: any): boolean {
89+
return isString(replacement) || isFunction(replacement);
90+
}
91+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {
2+
ddescribe,
3+
describe,
4+
it,
5+
iit,
6+
xit,
7+
expect,
8+
beforeEach,
9+
afterEach,
10+
browserDetection,
11+
inject,
12+
TestComponentBuilder,
13+
AsyncTestCompleter
14+
} from 'angular2/testing_internal';
15+
16+
import {ReplacePipe} from 'angular2/common';
17+
import {RegExpWrapper, StringJoiner} from 'angular2/src/facade/lang';
18+
19+
export function main() {
20+
describe("ReplacePipe", () => {
21+
var someNumber: number;
22+
var str;
23+
var pipe;
24+
25+
beforeEach(() => {
26+
someNumber = 42;
27+
str = 'Douglas Adams';
28+
pipe = new ReplacePipe();
29+
});
30+
31+
describe("transform", () => {
32+
33+
it("should not support input other than strings and numbers", () => {
34+
expect(() => pipe.transform({}, ["Douglas", "Hugh"])).toThrow();
35+
expect(() => pipe.transform([1, 2, 3], ["Douglas", "Hugh"])).toThrow();
36+
});
37+
38+
it("should not support patterns other than strings and regular expressions", () => {
39+
expect(() => pipe.transform(str, [{}, "Hugh"])).toThrow();
40+
expect(() => pipe.transform(str, [null, "Hugh"])).toThrow();
41+
expect(() => pipe.transform(str, [123, "Hugh"])).toThrow();
42+
});
43+
44+
it("should not support replacements other than strings and functions", () => {
45+
expect(() => pipe.transform(str, ["Douglas", {}])).toThrow();
46+
expect(() => pipe.transform(str, ["Douglas", null])).toThrow();
47+
expect(() => pipe.transform(str, ["Douglas", 123])).toThrow();
48+
});
49+
50+
it("should return a new string with the pattern replaced", () => {
51+
var result1 = pipe.transform(str, ["Douglas", "Hugh"]);
52+
53+
var result2 = pipe.transform(str, [RegExpWrapper.create("a"), "_"]);
54+
55+
var result3 = pipe.transform(str, [RegExpWrapper.create("a", "i"), "_"]);
56+
57+
var f = (x => { return "Adams!"; });
58+
59+
var result4 = pipe.transform(str, ["Adams", f]);
60+
61+
var result5 = pipe.transform(someNumber, ["2", "4"]);
62+
63+
expect(result1).toEqual("Hugh Adams");
64+
expect(result2).toEqual("Dougl_s Ad_ms");
65+
expect(result3).toEqual("Dougl_s _d_ms");
66+
expect(result4).toEqual("Douglas Adams!");
67+
expect(result5).toEqual("44");
68+
});
69+
70+
});
71+
72+
});
73+
}

modules/angular2/test/public_api_spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,8 @@ var NG_COMMON = [
431431
'PatternValidator.validate()',
432432
'PercentPipe',
433433
'PercentPipe.transform()',
434+
'ReplacePipe',
435+
'ReplacePipe.transform()',
434436
'RequiredValidator',
435437
'SelectControlValueAccessor',
436438
'SelectControlValueAccessor.onChange',

tools/public_api_guard/public_api_spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,8 @@ const COMMON = [
777777
'PatternValidator.validate(c:Control):{[key:string]:any}',
778778
'PercentPipe',
779779
'PercentPipe.transform(value:any, args:any[]):string',
780+
'ReplacePipe',
781+
'ReplacePipe.transform(value:any, args:any[]):any',
780782
'RequiredValidator',
781783
'SelectControlValueAccessor',
782784
'SelectControlValueAccessor.constructor(_renderer:Renderer, _elementRef:ElementRef, query:QueryList<NgSelectOption>)',

0 commit comments

Comments
 (0)
X Tutup