Completed
Push — master ( bfe104...7d2154 )
by Colin
7s
created

ListParser::calculateListMarkerPadding()   B

Complexity

Conditions 6
Paths 6

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 23
Code Lines 13

Code Coverage

Tests 14
CRAP Score 6

Importance

Changes 3
Bugs 2 Features 0
Metric Value
c 3
b 2
f 0
dl 0
loc 23
ccs 14
cts 14
cp 1
rs 8.5906
cc 6
eloc 13
nc 6
nop 2
crap 6
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\Parser;
16
17
use League\CommonMark\Block\Element\ListBlock;
18
use League\CommonMark\Block\Element\ListData;
19
use League\CommonMark\Block\Element\ListItem;
20
use League\CommonMark\ContextInterface;
21
use League\CommonMark\Cursor;
22
use League\CommonMark\Util\RegexHelper;
23
24
class ListParser extends AbstractBlockParser
25
{
26
    /**
27
     * @param ContextInterface $context
28
     * @param Cursor           $cursor
29
     *
30
     * @return bool
31
     */
32 1641
    public function parse(ContextInterface $context, Cursor $cursor)
33
    {
34 1641
        if ($cursor->isIndented() && !($context->getContainer() instanceof ListBlock)) {
35 174
            return false;
36
        }
37
38 1578
        $tmpCursor = clone $cursor;
39 1578
        $tmpCursor->advanceToFirstNonSpace();
40 1578
        $rest = $tmpCursor->getRemainder();
41
42 1578
        $data = new ListData();
43 1578
        $data->markerOffset = $cursor->getIndent();
44
45 1578
        if ($matches = RegexHelper::matchAll('/^[*+-]/', $rest)) {
46 402
            $data->type = ListBlock::TYPE_UNORDERED;
47 402
            $data->delimiter = null;
48 402
            $data->bulletChar = $matches[0][0];
49 1578
        } elseif ($matches = RegexHelper::matchAll('/^(\d{1,9})([.)])/', $rest)) {
50 81
            $data->type = ListBlock::TYPE_ORDERED;
51 81
            $data->start = intval($matches[1]);
52 81
            $data->delimiter = $matches[2];
53 81
            $data->bulletChar = null;
54 81
        } else {
55 1392
            return false;
56
        }
57
58 465
        $markerLength = strlen($matches[0]);
59
60
        // Make sure we have spaces after
61 465
        $nextChar = $tmpCursor->peek($markerLength);
62 465
        if (!($nextChar === null || $nextChar === "\t" || $nextChar === ' ')) {
63 228
            return false;
64
        }
65
66
        // We've got a match! Advance offset and calculate padding
67 240
        $cursor->advanceToFirstNonSpace(); // to start of marker
68 240
        $cursor->advanceBy($markerLength, true); // to end of marker
69 240
        $data->padding = $this->calculateListMarkerPadding($cursor, $markerLength);
70
71
        // add the list if needed
72 240
        $container = $context->getContainer();
73 240
        if (!$container || !($context->getContainer() instanceof ListBlock) || !$data->equals($container->getListData())) {
74 240
            $context->addBlock(new ListBlock($data));
75 240
        }
76
77
        // add the list item
78 240
        $context->addBlock(new ListItem($data));
79
80 240
        return true;
81
    }
82
83
    /**
84
     * @param Cursor $cursor
85
     * @param int    $markerLength
86
     *
87
     * @return int
88
     */
89 240
    private function calculateListMarkerPadding(Cursor $cursor, $markerLength)
90
    {
91 240
        $start = $cursor->saveState();
92 240
        $spacesStartCol = $cursor->getColumn();
93
94 240
        while ($cursor->getColumn() - $spacesStartCol < 5) {
95 240
            if (!$cursor->advanceBySpaceOrTab()) {
96 231
                break;
97
            }
98 228
        }
99
100 240
        $blankItem = $cursor->peek() === null;
101 240
        $spacesAfterMarker = $cursor->getColumn() - $spacesStartCol;
102
103 240
        if ($spacesAfterMarker >= 5 || $spacesAfterMarker < 1 || $blankItem) {
104 72
            $cursor->restoreState($start);
105 72
            $cursor->advanceBySpaceOrTab();
106
107 72
            return $markerLength + 1;
108
        }
109
110 183
        return $markerLength + $spacesAfterMarker;
111
    }
112
}
113