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\Input; |
||
15 | |||
16 | use League\CommonMark\Exception\UnexpectedEncodingException; |
||
17 | |||
18 | class MarkdownInput implements MarkdownInputInterface |
||
19 | { |
||
20 | /** |
||
21 | * @var array<int, string>|null |
||
22 | * |
||
23 | * @psalm-readonly-allow-private-mutation |
||
24 | */ |
||
25 | private ?array $lines = null; |
||
26 | |||
27 | /** @psalm-readonly-allow-private-mutation */ |
||
28 | private string $content; |
||
29 | |||
30 | /** @psalm-readonly-allow-private-mutation */ |
||
31 | private ?int $lineCount = null; |
||
32 | |||
33 | /** @psalm-readonly */ |
||
34 | private int $lineOffset; |
||
35 | |||
36 | 2342 | public function __construct(string $content, int $lineOffset = 0) |
|
37 | { |
||
38 | 2342 | if (! \mb_check_encoding($content, 'UTF-8')) { |
|
39 | 8 | throw new UnexpectedEncodingException('Unexpected encoding - UTF-8 or ASCII was expected'); |
|
40 | } |
||
41 | |||
42 | // Strip any leading UTF-8 BOM |
||
43 | 2334 | if (\substr($content, 0, 3) === "\xEF\xBB\xBF") { |
|
44 | 2 | $content = \substr($content, 3); |
|
45 | } |
||
46 | |||
47 | 2334 | $this->content = $content; |
|
48 | 2334 | $this->lineOffset = $lineOffset; |
|
49 | } |
||
50 | |||
51 | 36 | public function getContent(): string |
|
52 | { |
||
53 | 36 | return $this->content; |
|
54 | } |
||
55 | |||
56 | /** |
||
57 | * {@inheritDoc} |
||
58 | */ |
||
59 | 2310 | public function getLines(): iterable |
|
60 | { |
||
61 | 2310 | $this->splitLinesIfNeeded(); |
|
62 | |||
63 | \assert($this->lines !== null); |
||
64 | |||
65 | /** @psalm-suppress PossiblyNullIterator */ |
||
66 | 2310 | foreach ($this->lines as $i => $line) { |
|
67 | 2310 | yield $this->lineOffset + $i + 1 => $line; |
|
68 | } |
||
69 | } |
||
70 | |||
71 | 2 | public function getLineCount(): int |
|
72 | { |
||
73 | 2 | $this->splitLinesIfNeeded(); |
|
74 | |||
75 | \assert($this->lineCount !== null); |
||
76 | |||
77 | 2 | return $this->lineCount; |
|
78 | } |
||
79 | |||
80 | 2312 | private function splitLinesIfNeeded(): void |
|
81 | { |
||
82 | 2312 | if ($this->lines !== null) { |
|
83 | return; |
||
84 | } |
||
85 | |||
86 | 2312 | $lines = \preg_split('/\r\n|\n|\r/', $this->content); |
|
87 | 2312 | if ($lines === false) { |
|
88 | throw new UnexpectedEncodingException('Failed to split Markdown content by line'); |
||
89 | } |
||
90 | |||
91 | 2312 | $this->lines = $lines; |
|
92 | |||
93 | // Remove any newline which appears at the very end of the string. |
||
94 | // We've already split the document by newlines, so we can simply drop |
||
95 | // any empty element which appears on the end. |
||
96 | 2312 | if (\end($this->lines) === '') { |
|
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
97 | 1806 | \array_pop($this->lines); |
|
98 | } |
||
99 | |||
100 | 2312 | $this->lineCount = \count($this->lines); |
|
101 | } |
||
102 | } |
||
103 |