These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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\Block\Element\Paragraph; |
||
21 | use League\CommonMark\ContextInterface; |
||
22 | use League\CommonMark\Cursor; |
||
23 | use League\CommonMark\Util\RegexHelper; |
||
24 | |||
25 | class ListParser extends AbstractBlockParser |
||
26 | { |
||
27 | /** |
||
28 | * @param ContextInterface $context |
||
29 | * @param Cursor $cursor |
||
30 | * |
||
31 | * @return bool |
||
32 | */ |
||
33 | 1716 | public function parse(ContextInterface $context, Cursor $cursor) |
|
34 | { |
||
35 | 1716 | if ($cursor->isIndented() && !($context->getContainer() instanceof ListBlock)) { |
|
36 | 168 | return false; |
|
37 | } |
||
38 | |||
39 | 1653 | $tmpCursor = clone $cursor; |
|
40 | 1653 | $tmpCursor->advanceToNextNonSpaceOrTab(); |
|
41 | 1653 | $rest = $tmpCursor->getRemainder(); |
|
42 | |||
43 | 1653 | $data = new ListData(); |
|
44 | 1653 | $data->markerOffset = $cursor->getIndent(); |
|
45 | |||
46 | 1653 | if (preg_match('/^[*+-]/', $rest) === 1) { |
|
47 | 405 | $data->type = ListBlock::TYPE_UNORDERED; |
|
48 | 405 | $data->delimiter = null; |
|
49 | 405 | $data->bulletChar = $rest[0]; |
|
50 | 405 | $markerLength = 1; |
|
51 | 1527 | } elseif (($matches = RegexHelper::matchAll('/^(\d{1,9})([.)])/', $rest)) && (!($context->getContainer() instanceof Paragraph) || $matches[1] === '1')) { |
|
52 | 84 | $data->type = ListBlock::TYPE_ORDERED; |
|
53 | 84 | $data->start = (int) $matches[1]; |
|
54 | 84 | $data->delimiter = $matches[2]; |
|
55 | 84 | $data->bulletChar = null; |
|
56 | 84 | $markerLength = strlen($matches[0]); |
|
57 | 28 | } else { |
|
58 | 1464 | return false; |
|
59 | } |
||
60 | |||
61 | // Make sure we have spaces after |
||
62 | 468 | $nextChar = $tmpCursor->peek($markerLength); |
|
63 | 468 | if (!($nextChar === null || $nextChar === "\t" || $nextChar === ' ')) { |
|
64 | 228 | return false; |
|
65 | } |
||
66 | |||
67 | // If it interrupts paragraph, make sure first line isn't blank |
||
68 | 243 | $container = $context->getContainer(); |
|
69 | 243 | if ($container instanceof Paragraph && !RegexHelper::matchAt(RegexHelper::REGEX_NON_SPACE, $rest, $markerLength)) { |
|
0 ignored issues
–
show
|
|||
70 | 6 | return false; |
|
71 | } |
||
72 | |||
73 | // We've got a match! Advance offset and calculate padding |
||
74 | 237 | $cursor->advanceToNextNonSpaceOrTab(); // to start of marker |
|
75 | 237 | $cursor->advanceBy($markerLength, true); // to end of marker |
|
76 | 237 | $data->padding = $this->calculateListMarkerPadding($cursor, $markerLength); |
|
77 | |||
78 | // add the list if needed |
||
79 | 237 | if (!$container || !($container instanceof ListBlock) || !$data->equals($container->getListData())) { |
|
80 | 237 | $context->addBlock(new ListBlock($data)); |
|
81 | 79 | } |
|
82 | |||
83 | // add the list item |
||
84 | 237 | $context->addBlock(new ListItem($data)); |
|
85 | |||
86 | 237 | return true; |
|
87 | } |
||
88 | |||
89 | /** |
||
90 | * @param Cursor $cursor |
||
91 | * @param int $markerLength |
||
92 | * |
||
93 | * @return int |
||
94 | */ |
||
95 | 237 | private function calculateListMarkerPadding(Cursor $cursor, $markerLength) |
|
96 | { |
||
97 | 237 | $start = $cursor->saveState(); |
|
98 | 237 | $spacesStartCol = $cursor->getColumn(); |
|
99 | |||
100 | 237 | while ($cursor->getColumn() - $spacesStartCol < 5) { |
|
101 | 237 | if (!$cursor->advanceBySpaceOrTab()) { |
|
102 | 228 | break; |
|
103 | } |
||
104 | 76 | } |
|
105 | |||
106 | 237 | $blankItem = $cursor->peek() === null; |
|
107 | 237 | $spacesAfterMarker = $cursor->getColumn() - $spacesStartCol; |
|
108 | |||
109 | 237 | if ($spacesAfterMarker >= 5 || $spacesAfterMarker < 1 || $blankItem) { |
|
110 | 72 | $cursor->restoreState($start); |
|
111 | 72 | $cursor->advanceBySpaceOrTab(); |
|
112 | |||
113 | 72 | return $markerLength + 1; |
|
114 | } |
||
115 | |||
116 | 180 | return $markerLength + $spacesAfterMarker; |
|
117 | } |
||
118 | } |
||
119 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
integer
values, zero is a special case, in particular the following results might be unexpected: