Completed
Push — spec-next ( 67e4cc...9c0970 )
by Colin
05:39 queued 04:10
created

LinkParserHelper   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Test Coverage

Coverage 97.67%

Importance

Changes 0
Metric Value
wmc 17
lcom 0
cbo 3
dl 0
loc 99
ccs 42
cts 43
cp 0.9767
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
C parseLinkDestination() 0 51 12
A parseLinkLabel() 0 15 3
A parseLinkTitle() 0 9 2
1
<?php
2
3
/*
4
 * This file is part of the league/commonmark package.
5
 *
6
 * (c) Colin O'Dell <[email protected]>
7
 *
8
 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
9
 *  - (c) John MacFarlane
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace League\CommonMark\Util;
16
17
use League\CommonMark\Cursor;
18
19
final class LinkParserHelper
20
{
21
    /**
22
     * Attempt to parse link destination
23
     *
24
     * @param Cursor $cursor
25
     *
26
     * @return null|string The string, or null if no match
27
     */
28 423
    public static function parseLinkDestination(Cursor $cursor): ?string
29
    {
30 423
        if ($res = $cursor->match(RegexHelper::REGEX_LINK_DESTINATION_BRACES)) {
31
            // Chop off surrounding <..>:
32 30
            return UrlEncoder::unescapeAndEncode(
33 30
                RegexHelper::unescape(\substr($res, 1, -1))
34
            );
35
        }
36
37 396
        if ($cursor->getCharacter() === '<') {
38 9
            return null;
39
        }
40
41 387
        $oldPosition = $cursor->getPosition();
42 387
        $oldState = $cursor->saveState();
43 387
        $openParens = 0;
44 387
        while (($c = $cursor->getCharacter()) !== null) {
45 384
            if ($c === '\\' && RegexHelper::isEscapable($cursor->peek())) {
46 18
                $cursor->advanceBy(2);
47 384
            } elseif ($c === '(') {
48 18
                $cursor->advance();
49 18
                $openParens++;
50 384
            } elseif ($c === ')') {
51 120
                if ($openParens < 1) {
52 117
                    break;
53
                }
54
55 18
                $cursor->advance();
56 18
                $openParens--;
57 381
            } elseif (\preg_match(RegexHelper::REGEX_WHITESPACE_CHAR, $c)) {
58 177
                break;
59
            } else {
60 381
                $cursor->advance();
61
            }
62
        }
63
64 387
        if ($cursor->getPosition() === $oldPosition && $c !== ')') {
65 3
            return null;
66
        }
67
68 384
        $newPos = $cursor->getPosition();
69 384
        $cursor->restoreState($oldState);
70
71 384
        $cursor->advanceBy($newPos - $cursor->getPosition());
72
73 384
        $res = $cursor->getPreviousText();
74
75 384
        return UrlEncoder::unescapeAndEncode(
76 384
            RegexHelper::unescape($res)
77
        );
78
    }
79
80
    /**
81
     * @param Cursor $cursor
82
     *
83
     * @return int
84
     */
85 429
    public static function parseLinkLabel(Cursor $cursor): int
86
    {
87 429
        $match = $cursor->match('/^\[(?:[^\\\\\[\]]|\\\\.){0,1000}\]/');
88 429
        if ($match === null) {
89 228
            return 0;
90
        }
91
92 402
        $length = \mb_strlen($match, 'utf-8');
93
94 402
        if ($length > 1001) {
95
            return 0;
96
        }
97
98 402
        return $length;
99
    }
100
101
    /**
102
     * Attempt to parse link title (sans quotes)
103
     *
104
     * @param Cursor $cursor
105
     *
106
     * @return null|string The string, or null if no match
107
     */
108 183
    public static function parseLinkTitle(Cursor $cursor): ?string
109
    {
110 183
        if ($title = $cursor->match('/' . RegexHelper::PARTIAL_LINK_TITLE . '/')) {
111
            // Chop off quotes from title and unescape
112 138
            return RegexHelper::unescape(\substr($title, 1, -1));
113
        }
114
115 45
        return null;
116
    }
117
}
118