Completed
Push — spec-next ( cc96f3...6d269d )
by Colin
02:39
created

LinkParserHelper::parseLinkTitle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 4
cts 4
cp 1
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 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 399
    public static function parseLinkDestination(Cursor $cursor): ?string
29
    {
30 399
        if ($res = $cursor->match(RegexHelper::REGEX_LINK_DESTINATION_BRACES)) {
31
            // Chop off surrounding <..>:
32 18
            return UrlEncoder::unescapeAndEncode(
33 18
                RegexHelper::unescape(\substr($res, 1, -1))
34
            );
35
        }
36
37 381
        if ($cursor->getCharacter() === '<') {
38 6
            return null;
39
        }
40
41 375
        $oldState = $cursor->saveState();
42 375
        $openParens = 0;
43 375
        while (($c = $cursor->getCharacter()) !== null) {
44 372
            if ($c === '\\' && RegexHelper::isEscapable($cursor->peek())) {
45 18
                $cursor->advanceBy(2);
46 372
            } elseif ($c === '(') {
47 18
                $cursor->advance();
48 18
                $openParens++;
49 372
            } elseif ($c === ')') {
50 120
                if ($openParens < 1) {
51 117
                    break;
52
                }
53
54 18
                $cursor->advance();
55 18
                $openParens--;
56 369
            } elseif (\preg_match(RegexHelper::REGEX_WHITESPACE_CHAR, $c)) {
57 171
                break;
58
            } else {
59 369
                $cursor->advance();
60
            }
61
        }
62
63 375
        $newPos = $cursor->getPosition();
64 375
        $cursor->restoreState($oldState);
65
66 375
        $cursor->advanceBy($newPos - $cursor->getPosition());
67
68 375
        $res = $cursor->getPreviousText();
69
70 375
        return UrlEncoder::unescapeAndEncode(
71 375
            RegexHelper::unescape($res)
72
        );
73
    }
74
75
    /**
76
     * @param Cursor $cursor
77
     *
78
     * @return int
79
     */
80 405
    public static function parseLinkLabel(Cursor $cursor): int
81
    {
82 405
        $match = $cursor->match('/^\[(?:[^\\\\\[\]]|\\\\.){0,1000}\]/');
83 405
        if ($match === null) {
84 210
            return 0;
85
        }
86
87 378
        $length = \mb_strlen($match, 'utf-8');
88
89 378
        if ($length > 1001) {
90
            return 0;
91
        }
92
93 378
        return $length;
94
    }
95
96
    /**
97
     * Attempt to parse link title (sans quotes)
98
     *
99
     * @param Cursor $cursor
100
     *
101
     * @return null|string The string, or null if no match
102
     */
103 174
    public static function parseLinkTitle(Cursor $cursor): ?string
104
    {
105 174
        if ($title = $cursor->match('/' . RegexHelper::PARTIAL_LINK_TITLE . '/')) {
106
            // Chop off quotes from title and unescape
107 138
            return RegexHelper::unescape(substr($title, 1, -1));
108
        }
109
110 36
        return null;
111
    }
112
}
113