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\Parser; 16 17use League\CommonMark\Block\Element\Heading; 18use League\CommonMark\Block\Element\Paragraph; 19use League\CommonMark\ContextInterface; 20use League\CommonMark\Cursor; 21use League\CommonMark\Reference\ReferenceParser; 22use League\CommonMark\Util\RegexHelper; 23 24final class SetExtHeadingParser implements BlockParserInterface 25{ 26 public function parse(ContextInterface $context, Cursor $cursor): bool 27 { 28 if ($cursor->isIndented()) { 29 return false; 30 } 31 32 if (!($context->getContainer() instanceof Paragraph)) { 33 return false; 34 } 35 36 $match = RegexHelper::matchFirst('/^(?:=+|-+)[ \t]*$/', $cursor->getLine(), $cursor->getNextNonSpacePosition()); 37 if ($match === null) { 38 return false; 39 } 40 41 $level = $match[0][0] === '=' ? 1 : 2; 42 $strings = $context->getContainer()->getStrings(); 43 44 $strings = $this->resolveReferenceLinkDefinitions($strings, $context->getReferenceParser()); 45 if (empty($strings)) { 46 return false; 47 } 48 49 $context->replaceContainerBlock(new Heading($level, $strings)); 50 51 return true; 52 } 53 54 /** 55 * Resolve reference link definition 56 * 57 * @see https://github.com/commonmark/commonmark.js/commit/993bbe335931af847460effa99b2411eb643577d 58 * 59 * @param string[] $strings 60 * @param ReferenceParser $referenceParser 61 * 62 * @return string[] 63 */ 64 private function resolveReferenceLinkDefinitions(array $strings, ReferenceParser $referenceParser): array 65 { 66 foreach ($strings as &$string) { 67 $cursor = new Cursor($string); 68 while ($cursor->getCharacter() === '[' && $referenceParser->parse($cursor)) { 69 $string = $cursor->getRemainder(); 70 } 71 72 if ($string !== '') { 73 break; 74 } 75 } 76 77 return \array_filter($strings, function ($s) { 78 return $s !== ''; 79 }); 80 } 81} 82