vendor/league/commonmark/src/Extension/CommonMark/Parser/Block/FencedCodeParser.php line 32

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of the league/commonmark package.
  5.  *
  6.  * (c) Colin O'Dell <colinodell@gmail.com>
  7.  *
  8.  * For the full copyright and license information, please view the LICENSE
  9.  * file that was distributed with this source code.
  10.  */
  11. namespace League\CommonMark\Extension\CommonMark\Parser\Block;
  12. use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
  13. use League\CommonMark\Parser\Block\AbstractBlockContinueParser;
  14. use League\CommonMark\Parser\Block\BlockContinue;
  15. use League\CommonMark\Parser\Block\BlockContinueParserInterface;
  16. use League\CommonMark\Parser\Cursor;
  17. use League\CommonMark\Util\ArrayCollection;
  18. use League\CommonMark\Util\RegexHelper;
  19. final class FencedCodeParser extends AbstractBlockContinueParser
  20. {
  21.     /** @psalm-readonly */
  22.     private FencedCode $block;
  23.     /** @var ArrayCollection<string> */
  24.     private ArrayCollection $strings;
  25.     public function __construct(int $fenceLengthstring $fenceCharint $fenceOffset)
  26.     {
  27.         $this->block   = new FencedCode($fenceLength$fenceChar$fenceOffset);
  28.         $this->strings = new ArrayCollection();
  29.     }
  30.     public function getBlock(): FencedCode
  31.     {
  32.         return $this->block;
  33.     }
  34.     public function tryContinue(Cursor $cursorBlockContinueParserInterface $activeBlockParser): ?BlockContinue
  35.     {
  36.         // Check for closing code fence
  37.         if (! $cursor->isIndented() && $cursor->getNextNonSpaceCharacter() === $this->block->getChar()) {
  38.             $match RegexHelper::matchFirst('/^(?:`{3,}|~{3,})(?= *$)/'$cursor->getLine(), $cursor->getNextNonSpacePosition());
  39.             if ($match !== null && \strlen($match[0]) >= $this->block->getLength()) {
  40.                 // closing fence - we're at end of line, so we can finalize now
  41.                 return BlockContinue::finished();
  42.             }
  43.         }
  44.         // Skip optional spaces of fence offset
  45.         // Optimization: don't attempt to match if we're at a non-space position
  46.         if ($cursor->getNextNonSpacePosition() > $cursor->getPosition()) {
  47.             $cursor->match('/^ {0,' $this->block->getOffset() . '}/');
  48.         }
  49.         return BlockContinue::at($cursor);
  50.     }
  51.     public function addLine(string $line): void
  52.     {
  53.         $this->strings[] = $line;
  54.     }
  55.     public function closeBlock(): void
  56.     {
  57.         // first line becomes info string
  58.         $firstLine $this->strings->first();
  59.         if ($firstLine === false) {
  60.             $firstLine '';
  61.         }
  62.         $this->block->setInfo(RegexHelper::unescape(\trim($firstLine)));
  63.         if ($this->strings->count() === 1) {
  64.             $this->block->setLiteral('');
  65.         } else {
  66.             $this->block->setLiteral(\implode("\n"$this->strings->slice(1)) . "\n");
  67.         }
  68.     }
  69. }