FencedCodeParser   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 62
Duplicated Lines 0 %

Test Coverage

Coverage 95.83%

Importance

Changes 0
Metric Value
wmc 11
eloc 21
dl 0
loc 62
ccs 23
cts 24
cp 0.9583
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A addLine() 0 3 1
A closeBlock() 0 14 3
A tryContinue() 0 15 5
A getBlock() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the league/commonmark package.
7
 *
8
 * (c) Colin O'Dell <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace League\CommonMark\Extension\CommonMark\Parser\Block;
15
16
use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
17
use League\CommonMark\Node\Block\AbstractBlock;
18
use League\CommonMark\Parser\Block\AbstractBlockContinueParser;
19
use League\CommonMark\Parser\Block\BlockContinue;
20
use League\CommonMark\Parser\Block\BlockContinueParserInterface;
21
use League\CommonMark\Parser\Cursor;
22
use League\CommonMark\Util\ArrayCollection;
23
use League\CommonMark\Util\RegexHelper;
24
25
final class FencedCodeParser extends AbstractBlockContinueParser
26
{
27
    /**
28
     * @var FencedCode
29
     *
30
     * @psalm-readonly
31
     */
32
    private $block;
33
34
    /** @var ArrayCollection<string> */
35
    protected $strings;
36
37 108
    public function __construct(int $fenceLength, string $fenceChar, int $fenceOffset)
38
    {
39 108
        $this->block   = new FencedCode($fenceLength, $fenceChar, $fenceOffset);
40 108
        $this->strings = new ArrayCollection();
41 108
    }
42
43
    /**
44
     * @return FencedCode
45
     */
46 108
    public function getBlock(): AbstractBlock
47
    {
48 108
        return $this->block;
49
    }
50
51 102
    public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue
52
    {
53
        // Check for closing code fence
54 102
        if (! $cursor->isIndented() && $cursor->getNextNonSpaceCharacter() === $this->block->getChar()) {
55 96
            $match = RegexHelper::matchFirst('/^(?:`{3,}|~{3,})(?= *$)/', $cursor->getLine(), $cursor->getNextNonSpacePosition());
56 96
            if ($match !== null && \strlen($match[0]) >= $this->block->getLength()) {
57
                // closing fence - we're at end of line, so we can finalize now
58 90
                return BlockContinue::finished();
59
            }
60
        }
61
62
        // Skip optional spaces of fence offset
63 96
        $cursor->match('/^ {0,' . $this->block->getOffset() . '}/');
64
65 96
        return BlockContinue::at($cursor);
66
    }
67
68 108
    public function addLine(string $line): void
69
    {
70 108
        $this->strings[] = $line;
71 108
    }
72
73 108
    public function closeBlock(): void
74
    {
75
        // first line becomes info string
76 108
        $firstLine = $this->strings->first();
77 108
        if ($firstLine === false) {
78
            $firstLine = '';
79
        }
80
81 108
        $this->block->setInfo(RegexHelper::unescape(\trim($firstLine)));
82
83 108
        if ($this->strings->count() === 1) {
84 12
            $this->block->setLiteral('');
85
        } else {
86 96
            $this->block->setLiteral(\implode("\n", $this->strings->slice(1)) . "\n");
87
        }
88 108
    }
89
}
90