(allowPrimary: boolean, depth: number)
| 761 | |
| 762 | // parse `(a/b//outlet_name:c/d)` |
| 763 | private parseParens(allowPrimary: boolean, depth: number): {[outlet: string]: UrlSegmentGroup} { |
| 764 | const segments: {[key: string]: UrlSegmentGroup} = {}; |
| 765 | this.capture('('); |
| 766 | |
| 767 | while (!this.consumeOptional(')') && this.remaining.length > 0) { |
| 768 | const path = matchSegments(this.remaining); |
| 769 | |
| 770 | const next = this.remaining[path.length]; |
| 771 | |
| 772 | // if is is not one of these characters, then the segment was unescaped |
| 773 | // or the group was not closed |
| 774 | if (next !== '/' && next !== ')' && next !== ';') { |
| 775 | throw new RuntimeError( |
| 776 | RuntimeErrorCode.UNPARSABLE_URL, |
| 777 | (typeof ngDevMode === 'undefined' || ngDevMode) && `Cannot parse url '${this.url}'`, |
| 778 | ); |
| 779 | } |
| 780 | |
| 781 | let outletName: string | undefined; |
| 782 | if (path.indexOf(':') > -1) { |
| 783 | outletName = path.slice(0, path.indexOf(':')); |
| 784 | this.capture(outletName); |
| 785 | this.capture(':'); |
| 786 | } else if (allowPrimary) { |
| 787 | outletName = PRIMARY_OUTLET; |
| 788 | } |
| 789 | |
| 790 | const children = this.parseChildren(depth + 1); |
| 791 | segments[outletName ?? PRIMARY_OUTLET] = |
| 792 | Object.keys(children).length === 1 && children[PRIMARY_OUTLET] |
| 793 | ? children[PRIMARY_OUTLET] |
| 794 | : new UrlSegmentGroup([], children); |
| 795 | this.consumeOptional('//'); |
| 796 | } |
| 797 | |
| 798 | return segments; |
| 799 | } |
| 800 | |
| 801 | private peekStartsWith(str: string): boolean { |
| 802 | return this.remaining.startsWith(str); |
no test coverage detected