Completed
Push — master ( a7c107...4e4170 )
by Colin
01:04
created

FencedCode::finalize()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.009

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 9
cts 10
cp 0.9
rs 9.6666
c 0
b 0
f 0
cc 3
nc 4
nop 2
crap 3.009
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 96
    public function getLength(): int
97
    {
98 96
        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 3
    public function canContain(AbstractBlock $block): bool
134
    {
135 3
        return false;
136
    }
137
138 102
    public function isCode(): bool
139
    {
140 102
        return true;
141
    }
142
143 99
    public function matchesNextLine(Cursor $cursor): bool
144
    {
145 99
        if ($this->length === -1) {
146 15
            if ($cursor->isBlank()) {
147 9
                $this->lastLineBlank = true;
148
            }
149
150 15
            return false;
151
        }
152
153
        // Skip optional spaces of fence offset
154 99
        $cursor->match('/^ {0,' . $this->offset . '}/');
155
156 99
        return true;
157
    }
158
159 114
    public function finalize(ContextInterface $context, int $endLineNumber)
160
    {
161 114
        parent::finalize($context, $endLineNumber);
162
163
        // first line becomes info string
164 114
        $firstLine = $this->strings->first();
165 114
        if ($firstLine === false) {
166
            $firstLine = '';
167
        }
168
169 114
        $this->info = RegexHelper::unescape(\trim($firstLine));
170
171 114
        if ($this->strings->count() === 1) {
172 12
            $this->finalStringContents = '';
173
        } else {
174 102
            $this->finalStringContents = \implode("\n", $this->strings->slice(1)) . "\n";
175
        }
176 114
    }
177
178 105
    public function handleRemainingContents(ContextInterface $context, Cursor $cursor)
179
    {
180
        /** @var self $container */
181 105
        $container = $context->getContainer();
182
183
        // check for closing code fence
184 105
        if ($cursor->getIndent() <= 3 && $cursor->getNextNonSpaceCharacter() === $container->getChar()) {
185 93
            $match = RegexHelper::matchAll('/^(?:`{3,}|~{3,})(?= *$)/', $cursor->getLine(), $cursor->getNextNonSpacePosition());
186 93
            if ($match !== null && \strlen($match[0]) >= $container->getLength()) {
187
                // don't add closing fence to container; instead, close it:
188 87
                $this->setLength(-1); // -1 means we've passed closer
189
190 87
                return;
191
            }
192
        }
193
194 105
        $container->addLine($cursor->getRemainder());
195 105
    }
196
197 105
    public function shouldLastLineBeBlank(Cursor $cursor, int $currentLineNumber): bool
198
    {
199 105
        return false;
200
    }
201
}
202