()
| 581 | } |
| 582 | |
| 583 | private consumeUrlToken(): StringValueToken | Token { |
| 584 | const value = []; |
| 585 | this.consumeWhiteSpace(); |
| 586 | |
| 587 | if (this.peekCodePoint(0) === EOF) { |
| 588 | return {type: TokenType.URL_TOKEN, value: ''}; |
| 589 | } |
| 590 | |
| 591 | const next = this.peekCodePoint(0); |
| 592 | if (next === APOSTROPHE || next === QUOTATION_MARK) { |
| 593 | const stringToken = this.consumeStringToken(this.consumeCodePoint()); |
| 594 | if (stringToken.type === TokenType.STRING_TOKEN) { |
| 595 | this.consumeWhiteSpace(); |
| 596 | |
| 597 | if (this.peekCodePoint(0) === EOF || this.peekCodePoint(0) === RIGHT_PARENTHESIS) { |
| 598 | this.consumeCodePoint(); |
| 599 | return {type: TokenType.URL_TOKEN, value: stringToken.value}; |
| 600 | } |
| 601 | } |
| 602 | |
| 603 | this.consumeBadUrlRemnants(); |
| 604 | return BAD_URL_TOKEN; |
| 605 | } |
| 606 | |
| 607 | while (true) { |
| 608 | const codePoint = this.consumeCodePoint(); |
| 609 | if (codePoint === EOF || codePoint === RIGHT_PARENTHESIS) { |
| 610 | return {type: TokenType.URL_TOKEN, value: fromCodePoint(...value)}; |
| 611 | } else if (isWhiteSpace(codePoint)) { |
| 612 | this.consumeWhiteSpace(); |
| 613 | if (this.peekCodePoint(0) === EOF || this.peekCodePoint(0) === RIGHT_PARENTHESIS) { |
| 614 | this.consumeCodePoint(); |
| 615 | return {type: TokenType.URL_TOKEN, value: fromCodePoint(...value)}; |
| 616 | } |
| 617 | this.consumeBadUrlRemnants(); |
| 618 | return BAD_URL_TOKEN; |
| 619 | } else if ( |
| 620 | codePoint === QUOTATION_MARK || |
| 621 | codePoint === APOSTROPHE || |
| 622 | codePoint === LEFT_PARENTHESIS || |
| 623 | isNonPrintableCodePoint(codePoint) |
| 624 | ) { |
| 625 | this.consumeBadUrlRemnants(); |
| 626 | return BAD_URL_TOKEN; |
| 627 | } else if (codePoint === REVERSE_SOLIDUS) { |
| 628 | if (isValidEscape(codePoint, this.peekCodePoint(0))) { |
| 629 | value.push(this.consumeEscapedCodePoint()); |
| 630 | } else { |
| 631 | this.consumeBadUrlRemnants(); |
| 632 | return BAD_URL_TOKEN; |
| 633 | } |
| 634 | } else { |
| 635 | value.push(codePoint); |
| 636 | } |
| 637 | } |
| 638 | } |
| 639 | |
| 640 | private consumeWhiteSpace(): void { |
no test coverage detected