Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
/*
6
 * This is part of the league/commonmark package.
7
 *
8
 * (c) Martin Hasoň <martin.hason@gmail.com>
9
 * (c) Webuni s.r.o. <info@webuni.cz>
10
 * (c) Colin O'Dell <colinodell@gmail.com>
11
 *
12
 * For the full copyright and license information, please view the LICENSE
13
 * file that was distributed with this source code.
14
 */
15
 
16
namespace League\CommonMark\Extension\Table;
17
 
18
use League\CommonMark\Parser\Block\BlockStart;
19
use League\CommonMark\Parser\Block\BlockStartParserInterface;
20
use League\CommonMark\Parser\Block\ParagraphParser;
21
use League\CommonMark\Parser\Cursor;
22
use League\CommonMark\Parser\MarkdownParserStateInterface;
23
 
24
final class TableStartParser implements BlockStartParserInterface
25
{
26
    public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart
27
    {
28
        $paragraph = $parserState->getParagraphContent();
29
        if ($paragraph === null || \strpos($paragraph, '|') === false) {
30
            return BlockStart::none();
31
        }
32
 
33
        $columns = self::parseSeparator($cursor);
34
        if (\count($columns) === 0) {
35
            return BlockStart::none();
36
        }
37
 
38
        $lines    = \explode("\n", $paragraph);
39
        $lastLine = \array_pop($lines);
40
 
41
        $headerCells = TableParser::split($lastLine);
42
        if (\count($headerCells) > \count($columns)) {
43
            return BlockStart::none();
44
        }
45
 
46
        $cursor->advanceToEnd();
47
 
48
        $parsers = [];
49
 
50
        if (\count($lines) > 0) {
51
            $p = new ParagraphParser();
52
            $p->addLine(\implode("\n", $lines));
53
            $parsers[] = $p;
54
        }
55
 
56
        $parsers[] = new TableParser($columns, $headerCells);
57
 
58
        return BlockStart::of(...$parsers)
59
            ->at($cursor)
60
            ->replaceActiveBlockParser();
61
    }
62
 
63
    /**
64
     * @return array<int, string|null>
65
     *
66
     * @psalm-return array<int, TableCell::ALIGN_*|null>
67
     *
68
     * @phpstan-return array<int, TableCell::ALIGN_*|null>
69
     */
70
    private static function parseSeparator(Cursor $cursor): array
71
    {
72
        $columns = [];
73
        $pipes   = 0;
74
        $valid   = false;
75
 
76
        while (! $cursor->isAtEnd()) {
77
            switch ($c = $cursor->getCurrentCharacter()) {
78
                case '|':
79
                    $cursor->advanceBy(1);
80
                    $pipes++;
81
                    if ($pipes > 1) {
82
                        // More than one adjacent pipe not allowed
83
                        return [];
84
                    }
85
 
86
                    // Need at least one pipe, even for a one-column table
87
                    $valid = true;
88
                    break;
89
                case '-':
90
                case ':':
91
                    if ($pipes === 0 && \count($columns) > 0) {
92
                        // Need a pipe after the first column (first column doesn't need to start with one)
93
                        return [];
94
                    }
95
 
96
                    $left  = false;
97
                    $right = false;
98
                    if ($c === ':') {
99
                        $left = true;
100
                        $cursor->advanceBy(1);
101
                    }
102
 
103
                    if ($cursor->match('/^-+/') === null) {
104
                        // Need at least one dash
105
                        return [];
106
                    }
107
 
108
                    if ($cursor->getCurrentCharacter() === ':') {
109
                        $right = true;
110
                        $cursor->advanceBy(1);
111
                    }
112
 
113
                    $columns[] = self::getAlignment($left, $right);
114
                    // Next, need another pipe
115
                    $pipes = 0;
116
                    break;
117
                case ' ':
118
                case "\t":
119
                    // White space is allowed between pipes and columns
120
                    $cursor->advanceToNextNonSpaceOrTab();
121
                    break;
122
                default:
123
                    // Any other character is invalid
124
                    return [];
125
            }
126
        }
127
 
128
        if (! $valid) {
129
            return [];
130
        }
131
 
132
        return $columns;
133
    }
134
 
135
    /**
136
     * @psalm-return TableCell::ALIGN_*|null
137
     *
138
     * @phpstan-return TableCell::ALIGN_*|null
139
     *
140
     * @psalm-pure
141
     */
142
    private static function getAlignment(bool $left, bool $right): ?string
143
    {
144
        if ($left && $right) {
145
            return TableCell::ALIGN_CENTER;
146
        }
147
 
148
        if ($left) {
149
            return TableCell::ALIGN_LEFT;
150
        }
151
 
152
        if ($right) {
153
            return TableCell::ALIGN_RIGHT;
154
        }
155
 
156
        return null;
157
    }
158
}