1<?php 2 3/* 4 * This file is part of the league/commonmark package. 5 * 6 * (c) Colin O'Dell <colinodell@gmail.com> 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 15namespace League\CommonMark\Block\Element; 16 17use League\CommonMark\ContextInterface; 18use League\CommonMark\Cursor; 19 20/** 21 * @method children() AbstractBlock[] 22 */ 23class ListBlock extends AbstractBlock 24{ 25 const TYPE_BULLET = 'bullet'; 26 const TYPE_ORDERED = 'ordered'; 27 28 /** 29 * @deprecated This constant is deprecated in league/commonmark 1.4 and will be removed in 2.0; use TYPE_BULLET instead 30 */ 31 const TYPE_UNORDERED = self::TYPE_BULLET; 32 33 /** 34 * @var bool 35 */ 36 protected $tight = false; 37 38 /** 39 * @var ListData 40 */ 41 protected $listData; 42 43 public function __construct(ListData $listData) 44 { 45 $this->listData = $listData; 46 } 47 48 /** 49 * @return ListData 50 */ 51 public function getListData(): ListData 52 { 53 return $this->listData; 54 } 55 56 public function endsWithBlankLine(): bool 57 { 58 if ($this->lastLineBlank) { 59 return true; 60 } 61 62 if ($this->hasChildren()) { 63 return $this->lastChild() instanceof AbstractBlock && $this->lastChild()->endsWithBlankLine(); 64 } 65 66 return false; 67 } 68 69 public function canContain(AbstractBlock $block): bool 70 { 71 return $block instanceof ListItem; 72 } 73 74 public function isCode(): bool 75 { 76 return false; 77 } 78 79 public function matchesNextLine(Cursor $cursor): bool 80 { 81 return true; 82 } 83 84 public function finalize(ContextInterface $context, int $endLineNumber) 85 { 86 parent::finalize($context, $endLineNumber); 87 88 $this->tight = true; // tight by default 89 90 foreach ($this->children() as $item) { 91 if (!($item instanceof AbstractBlock)) { 92 continue; 93 } 94 95 // check for non-final list item ending with blank line: 96 if ($item->endsWithBlankLine() && $item !== $this->lastChild()) { 97 $this->tight = false; 98 break; 99 } 100 101 // Recurse into children of list item, to see if there are 102 // spaces between any of them: 103 foreach ($item->children() as $subItem) { 104 if ($subItem instanceof AbstractBlock && $subItem->endsWithBlankLine() && ($item !== $this->lastChild() || $subItem !== $item->lastChild())) { 105 $this->tight = false; 106 break; 107 } 108 } 109 } 110 } 111 112 public function isTight(): bool 113 { 114 return $this->tight; 115 } 116 117 public function setTight(bool $tight): self 118 { 119 $this->tight = $tight; 120 121 return $this; 122 } 123} 124