Completed
Push — master ( 9eb60a...7a0a03 )
by Colin
36:39 queued 35:14
created

InlineMentionParser::parse()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 32
ccs 0
cts 14
cp 0
rs 9.408
c 0
b 0
f 0
cc 4
nc 3
nop 1
crap 20
1
<?php
2
3
/*
4
 * This file is part of the league/commonmark package.
5
 *
6
 * (c) Colin O'Dell <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace League\CommonMark\Extension\Autolink;
13
14
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
15
use League\CommonMark\Parser\Inline\InlineParserInterface;
16
use League\CommonMark\Parser\InlineParserContext;
17
18
final class InlineMentionParser implements InlineParserInterface
19
{
20
    /** @var string */
21
    private $linkPattern;
22
23
    /** @var string */
24
    private $handleRegex;
25
26
    /**
27
     * @param string $linkPattern
28
     * @param string $handleRegex
29
     */
30
    public function __construct($linkPattern, $handleRegex = '/^[A-Za-z0-9_]+(?!\w)/')
31
    {
32
        $this->linkPattern = $linkPattern;
33
        $this->handleRegex = $handleRegex;
34
    }
35
36
    public function getCharacters(): array
37
    {
38
        return ['@'];
39
    }
40
41
    public function parse(InlineParserContext $inlineContext): bool
42
    {
43
        $cursor = $inlineContext->getCursor();
44
45
        // The @ symbol must not have any other characters immediately prior
46
        $previousChar = $cursor->peek(-1);
47
        if ($previousChar !== null && $previousChar !== ' ') {
48
            // peek() doesn't modify the cursor, so no need to restore state first
49
            return false;
50
        }
51
52
        // Save the cursor state in case we need to rewind and bail
53
        $previousState = $cursor->saveState();
54
55
        // Advance past the @ symbol to keep parsing simpler
56
        $cursor->advance();
57
58
        // Parse the handle
59
        $handle = $cursor->match($this->handleRegex);
60
        if (empty($handle)) {
61
            // Regex failed to match; this isn't a valid Twitter handle
62
            $cursor->restoreState($previousState);
63
64
            return false;
65
        }
66
67
        $url = \sprintf($this->linkPattern, $handle);
68
69
        $inlineContext->getContainer()->appendChild(new Link($url, '@' . $handle));
70
71
        return true;
72
    }
73
74
    public static function createTwitterHandleParser(): self
75
    {
76
        return new self('https://twitter.com/%s', '/^[A-Za-z0-9_]{1,15}(?!\w)/');
77
    }
78
79
    public static function createGithubHandleParser(): self
80
    {
81
        // RegEx adapted from https://github.com/shinnn/github-username-regex/blob/master/index.js
82
        return new self('https://www.github.com/%s', '/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)/');
83
    }
84
}
85