FencedCode::handleRemainingContents()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

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