SpecReader::read()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 18
nc 3
nop 1
dl 0
loc 25
ccs 0
cts 19
cp 0
crap 12
rs 9.6666
c 1
b 0
f 0
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\Util;
15
16
use League\CommonMark\Exception\IOException;
17
18
/**
19
 * Reads in a CommonMark spec document and extracts the input/output examples for testing against them
20
 */
21
final class SpecReader
22
{
23
    private function __construct()
24
    {
25
    }
26
27
    /**
28
     * @return iterable<string, array{input: string, output: string, type: string, section: string, number: int}>
29
     */
30
    public static function read(string $data): iterable
31
    {
32
        // Normalize newlines for platform independence
33
        $data = \preg_replace('/\r\n?/', "\n", $data);
34
        \assert($data !== null);
35
        $data = \preg_replace('/<!-- END TESTS -->.*$/', '', $data);
36
        \assert($data !== null);
37
        \preg_match_all('/^`{32} (example ?\w*)\n([\s\S]*?)^\.\n([\s\S]*?)^`{32}$|^#{1,6} *(.*)$/m', $data, $matches, PREG_SET_ORDER);
38
39
        $currentSection = 'Example';
40
        $exampleNumber  = 0;
41
42
        foreach ($matches as $match) {
43
            \assert(isset($match[1], $match[2], $match[3]));
44
            if (isset($match[4])) {
45
                $currentSection = $match[4];
46
                continue;
47
            }
48
49
            yield \trim($currentSection . ' #' . $exampleNumber) => [
50
                'input'   => \str_replace('→', "\t", $match[2]),
51
                'output'  => \str_replace('→', "\t", $match[3]),
52
                'type'    => $match[1],
53
                'section' => $currentSection,
54
                'number'  => $exampleNumber++,
55
            ];
56
        }
57
    }
58
59
    /**
60
     * @return iterable<string, array{input: string, output: string, type: string, section: string, number: int}>
61
     *
62
     * @throws IOException if the file cannot be loaded
63
     */
64
    public static function readFile(string $filename): iterable
65
    {
66
        if (($data = \file_get_contents($filename)) === false) {
67
            throw new IOException(\sprintf('Failed to load spec from %s', $filename));
68
        }
69
70
        return self::read($data);
71
    }
72
}
73