Completed
Push — master ( db24e4...a24032 )
by Colin
02:01
created

QuoteParser   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 97.44%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 13
c 1
b 0
f 1
lcom 1
cbo 7
dl 0
loc 71
ccs 38
cts 39
cp 0.9744
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A getCharacters() 0 4 1
D parse() 0 52 12
1
<?php
2
3
/*
4
 * This file is part of the league/commonmark-extras package.
5
 *
6
 * (c) Colin O'Dell <[email protected]>
7
 *
8
 * Original code based on the CommonMark JS reference parser (http://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\Extras\SmartPunct;
16
17
use League\CommonMark\Delimiter\Delimiter;
18
use League\CommonMark\Inline\Element\Text;
19
use League\CommonMark\Inline\Parser\AbstractInlineParser;
20
use League\CommonMark\InlineParserContext;
21
use League\CommonMark\Util\RegexHelper;
22
23
class QuoteParser extends AbstractInlineParser
24
{
25
    protected $double = ['"', '“', '”'];
26
    protected $single = ["'", '‘', '’'];
27
28
    /**
29
     * @return string[]
30
     */
31 45
    public function getCharacters()
32
    {
33 45
        return array_merge($this->double, $this->single);
34
    }
35
36
    /**
37
     * @param InlineParserContext $inlineContext
38
     *
39
     * @return bool
40
     */
41 27
    public function parse(InlineParserContext $inlineContext)
42
    {
43 27
        $character = $inlineContext->getCursor()->getCharacter();
44 27
        if (in_array($character, $this->double)) {
45 12
            $character = '“';
46 27
        } elseif (in_array($character, $this->single)) {
47 24
            $character = '’';
48 24
        } else {
49
            return false;
50
        }
51
52 27
        $cursor = $inlineContext->getCursor();
53 27
        $charBefore = $cursor->peek(-1);
54 27
        if ($charBefore === null) {
55 21
            $charBefore = "\n";
56 21
        }
57
58 27
        $cursor->advance();
59
60 27
        $charAfter = $cursor->getCharacter();
61 27
        if ($charAfter === null) {
62 15
            $charAfter = "\n";
63 15
        }
64
65 27
        $afterIsWhitespace = preg_match('/\pZ|\s/u', $charAfter);
66 27
        $afterIsPunctuation = preg_match(RegexHelper::REGEX_PUNCTUATION, $charAfter);
67 27
        $beforeIsWhitespace = preg_match('/\pZ|\s/u', $charBefore);
68 27
        $beforeIsPunctuation = preg_match(RegexHelper::REGEX_PUNCTUATION, $charBefore);
69
70 27
        $leftFlanking = !$afterIsWhitespace &&
71 27
            !($afterIsPunctuation &&
72 27
                !$beforeIsWhitespace &&
73 27
                !$beforeIsPunctuation);
74
75 27
        $rightFlanking = !$beforeIsWhitespace &&
76 27
            !($beforeIsPunctuation &&
77 27
                !$afterIsWhitespace &&
78 27
                !$afterIsPunctuation);
79
80 27
        $canOpen = $leftFlanking && !$rightFlanking;
81 27
        $canClose = $rightFlanking;
82
83 27
        $node = new Text($character, ['delim' => true]);
84 27
        $inlineContext->getContainer()->appendChild(
85
            $node
86 27
        );
87
88
        // Add entry to stack to this opener
89 27
        $inlineContext->getDelimiterStack()->push(new Delimiter($character, 1, $node, $canOpen, $canClose));
90
91 27
        return true;
92
    }
93
}
94