Completed
Push — master ( 0b0b24...54ff37 )
by Colin
02:37
created

FencedCode::canContain()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
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\Extension\CommonMark\Node\Block;
16
17
use League\CommonMark\Node\Block\AbstractBlock;
18
use League\CommonMark\Node\Block\AbstractStringContainerBlock;
19
use League\CommonMark\Parser\ContextInterface;
20
use League\CommonMark\Parser\Cursor;
21
use League\CommonMark\Util\RegexHelper;
22
23
class FencedCode extends AbstractStringContainerBlock
24
{
25
    /**
26
     * @var string
27
     */
28
    protected $info;
29
30
    /**
31
     * @var int
32
     */
33
    protected $length;
34
35
    /**
36
     * @var string
37
     */
38
    protected $char;
39
40
    /**
41
     * @var int
42
     */
43
    protected $offset;
44
45
    /**
46
     * @param int    $length
47
     * @param string $char
48
     * @param int    $offset
49
     */
50 132
    public function __construct(int $length, string $char, int $offset)
51
    {
52 132
        parent::__construct();
53
54 132
        $this->length = $length;
55 132
        $this->char = $char;
56 132
        $this->offset = $offset;
57 132
    }
58
59
    /**
60
     * @return string
61
     */
62 3
    public function getInfo(): string
63
    {
64 3
        return $this->info;
65
    }
66
67
    /**
68
     * @return string[]
69
     */
70 114
    public function getInfoWords(): array
71
    {
72 114
        return \preg_split('/\s+/', $this->info) ?: [];
73
    }
74
75
    /**
76
     * @return string
77
     */
78 111
    public function getChar(): string
79
    {
80 111
        return $this->char;
81
    }
82
83
    /**
84
     * @param string $char
85
     *
86
     * @return $this
87
     */
88 3
    public function setChar(string $char): self
89
    {
90 3
        $this->char = $char;
91
92 3
        return $this;
93
    }
94
95
    /**
96
     * @return int
97
     */
98 96
    public function getLength(): int
99
    {
100 96
        return $this->length;
101
    }
102
103
    /**
104
     * @param int $length
105
     *
106
     * @return $this
107
     */
108 90
    public function setLength(int $length): self
109
    {
110 90
        $this->length = $length;
111
112 90
        return $this;
113
    }
114
115
    /**
116
     * @return int
117
     */
118 6
    public function getOffset(): int
119
    {
120 6
        return $this->offset;
121
    }
122
123
    /**
124
     * @param int $offset
125
     *
126
     * @return $this
127
     */
128 3
    public function setOffset(int $offset): self
129
    {
130 3
        $this->offset = $offset;
131
132 3
        return $this;
133
    }
134
135 3
    public function canContain(AbstractBlock $block): bool
136
    {
137 3
        return false;
138
    }
139
140 102
    public function isCode(): bool
141
    {
142 102
        return true;
143
    }
144
145 99
    public function matchesNextLine(Cursor $cursor): bool
146
    {
147 99
        if ($this->length === -1) {
148 15
            if ($cursor->isBlank()) {
149 9
                $this->lastLineBlank = true;
150
            }
151
152 15
            return false;
153
        }
154
155
        // Skip optional spaces of fence offset
156 99
        $cursor->match('/^ {0,' . $this->offset . '}/');
157
158 99
        return true;
159
    }
160
161 114
    public function finalize(ContextInterface $context, int $endLineNumber): void
162
    {
163 114
        parent::finalize($context, $endLineNumber);
164
165
        // first line becomes info string
166 114
        $firstLine = $this->strings->first();
167 114
        if ($firstLine === false) {
168
            $firstLine = '';
169
        }
170
171 114
        $this->info = RegexHelper::unescape(\trim($firstLine));
172
173 114
        if ($this->strings->count() === 1) {
174 12
            $this->finalStringContents = '';
175
        } else {
176 102
            $this->finalStringContents = \implode("\n", $this->strings->slice(1)) . "\n";
177
        }
178 114
    }
179
180 105
    public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void
181
    {
182
        /** @var self $container */
183 105
        $container = $context->getContainer();
184
185
        // check for closing code fence
186 105
        if ($cursor->getIndent() <= 3 && $cursor->getNextNonSpaceCharacter() === $container->getChar()) {
187 93
            $match = RegexHelper::matchAll('/^(?:`{3,}|~{3,})(?= *$)/', $cursor->getLine(), $cursor->getNextNonSpacePosition());
188 93
            if ($match !== null && \strlen($match[0]) >= $container->getLength()) {
189
                // don't add closing fence to container; instead, close it:
190 87
                $this->setLength(-1); // -1 means we've passed closer
191
192 87
                return;
193
            }
194
        }
195
196 105
        $container->addLine($cursor->getRemainder());
197 105
    }
198
199 105
    public function shouldLastLineBeBlank(Cursor $cursor, int $currentLineNumber): bool
200
    {
201 105
        return false;
202
    }
203
}
204