|
| 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 | +} |
0 commit comments