/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { $tmpCursor = clone $cursor; $indent = $tmpCursor->advanceWhileMatches(' ', 3); $rest = $tmpCursor->getRemainder(); $data = new ListData(); if ($matches = RegexHelper::matchAll('/^[*+-]( +|$)/', $rest)) { $spacesAfterMarker = strlen($matches[1]); $data->type = ListBlock::TYPE_UNORDERED; $data->delimiter = null; $data->bulletChar = $matches[0][0]; } elseif ($matches = RegexHelper::matchAll('/^(\\d+)([.)])( +|$)/', $rest)) { $spacesAfterMarker = strlen($matches[3]); $data->type = ListBlock::TYPE_ORDERED; $data->start = intval($matches[1]); $data->delimiter = $matches[2]; $data->bulletChar = null; } else { return false; } $data->padding = $this->calculateListMarkerPadding($matches[0], $spacesAfterMarker, $rest); $cursor->advanceToFirstNonSpace(); $cursor->advanceBy($data->padding); // list item $data->markerOffset = $indent; // add the list if needed $container = $context->getContainer(); if (!$container || !$context->getContainer() instanceof ListBlock || !$data->equals($container->getListData())) { $context->addBlock(new ListBlock($data)); } // add the list item $context->addBlock(new ListItem($data)); return true; }
public function parse(ContextInterface $context, Cursor $cursor) { $document = $context->getDocument(); $tip = $context->getTip(); if (!$document->getLastChild() instanceof AttributesDocument) { $attributesDocument = new AttributesDocument(); foreach ($document->getChildren() as $child) { $document->removeChild($child); $attributesDocument->addChild($child); } $document->addChild($attributesDocument); if ($tip instanceof Document) { $context->setTip($attributesDocument); } } $state = $cursor->saveState(); $attributes = AttributesUtils::parse($cursor); if (empty($attributes)) { return false; } if (null !== $cursor->getFirstNonSpaceCharacter()) { $cursor->restoreState($state); return false; } $prepend = $tip instanceof Document || !$tip->getParent() instanceof Document && $context->getBlockCloser()->areAllClosed(); $context->addBlock(new Attributes($attributes, $prepend ? Attributes::PREPEND : Attributes::APPEND)); $context->setBlocksParsed(true); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { if ($cursor->isIndented() && !$context->getContainer() instanceof ListBlock) { return false; } $tmpCursor = clone $cursor; $tmpCursor->advanceToFirstNonSpace(); $rest = $tmpCursor->getRemainder(); $data = new ListData(); $data->markerOffset = $cursor->getIndent(); if ($matches = RegexHelper::matchAll('/^[*+-]/', $rest)) { $data->type = ListBlock::TYPE_UNORDERED; $data->delimiter = null; $data->bulletChar = $matches[0][0]; } elseif (($matches = RegexHelper::matchAll('/^(\\d{1,9})([.)])/', $rest)) && (!$context->getContainer() instanceof Paragraph || $matches[1] === '1')) { $data->type = ListBlock::TYPE_ORDERED; $data->start = intval($matches[1]); $data->delimiter = $matches[2]; $data->bulletChar = null; } else { return false; } $markerLength = strlen($matches[0]); // Make sure we have spaces after $nextChar = $tmpCursor->peek($markerLength); if (!($nextChar === null || $nextChar === "\t" || $nextChar === ' ')) { return false; } // If it interrupts paragraph, make sure first line isn't blank if ($context->getContainer() instanceof Paragraph && !RegexHelper::matchAt(RegexHelper::REGEX_NON_SPACE, $rest, $markerLength)) { return false; } // We've got a match! Advance offset and calculate padding $cursor->advanceToFirstNonSpace(); // to start of marker $cursor->advanceBy($markerLength, true); // to end of marker $data->padding = $this->calculateListMarkerPadding($cursor, $markerLength); // add the list if needed $container = $context->getContainer(); if (!$container || !$context->getContainer() instanceof ListBlock || !$data->equals($container->getListData())) { $context->addBlock(new ListBlock($data)); } // add the list item $context->addBlock(new ListItem($data)); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor */ public function handleRemainingContents(ContextInterface $context, Cursor $cursor) { if ($cursor->isBlank()) { return; } $context->addBlock(new Paragraph()); $cursor->advanceToFirstNonSpace(); $context->getTip()->addLine($cursor->getRemainder()); }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { $match = RegexHelper::matchAt(RegexHelper::getInstance()->getHtmlBlockOpenRegex(), $cursor->getLine(), $cursor->getFirstNonSpacePosition()); if ($match === null) { return false; } $context->addBlock(new HtmlBlock()); $context->setBlocksParsed(true); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { if ($cursor->getFirstNonSpaceCharacter() !== '>') { return false; } $cursor->advanceToFirstNonSpace(); $cursor->advance(); if ($cursor->getCharacter() === ' ') { $cursor->advance(); } $context->addBlock(new BlockQuote()); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { $previousState = $cursor->saveState(); $indent = $cursor->advanceToFirstNonSpace(); $fence = $cursor->match('/^`{3,}(?!.*`)|^~{3,}(?!.*~)/'); if (!$fence) { $cursor->restoreState($previousState); return false; } // fenced code block $fenceLength = strlen($fence); $context->addBlock(new FencedCode($fenceLength, $fence[0], $indent)); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { if ($cursor->isIndented()) { return false; } $match = RegexHelper::matchAt(RegexHelper::getInstance()->getThematicBreakRegex(), $cursor->getLine(), $cursor->getFirstNonSpacePosition()); if ($match === null) { return false; } // Advance to the end of the string, consuming the entire line (of the thematic break) $cursor->advanceBy(mb_strlen($cursor->getRemainder())); $context->addBlock(new ThematicBreak()); $context->setBlocksParsed(true); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { if (!$cursor->isIndented()) { return false; } if ($context->getTip() instanceof Paragraph) { return false; } if ($cursor->isBlank()) { return false; } $cursor->advanceBy(Cursor::INDENT_LEVEL, true); $context->addBlock(new IndentedCode()); return true; }
public function parse(ContextInterface $context, Cursor $cursor) { $state = $cursor->saveState(); $attributes = AttributesUtils::parse($cursor); if (empty($attributes)) { return false; } if (null !== $cursor->getFirstNonSpaceCharacter()) { $cursor->restoreState($state); return false; } $context->addBlock(new Attributes($attributes)); $context->setBlocksParsed(true); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { if ($cursor->isIndented()) { return false; } $previousState = $cursor->saveState(); $cursor->advanceToFirstNonSpace(); $fence = $cursor->match('/^\\[TOC\\]/'); if (is_null($fence)) { $cursor->restoreState($previousState); return false; } $context->addBlock(new TableOfContents()); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { if ($cursor->getFirstNonSpaceCharacter() !== 'A' || $cursor->getCharacter($cursor->getFirstNonSpacePosition() + 1) !== '>') { return false; } $cursor->advanceToFirstNonSpace(); if ($cursor->peek() === '>') { $cursor->advanceBy(2); if ($cursor->getCharacter() === ' ') { $cursor->advance(); } } $context->addBlock(new Aside()); return true; }
/** * @param \League\CommonMark\ContextInterface $context * @param \League\CommonMark\Cursor $cursor * * @return bool */ public function parse(\League\CommonMark\ContextInterface $context, \League\CommonMark\Cursor $cursor) { $line = $cursor->getLine(); //either a line starting with 'example:' (expected to have a set of links) //or a line starting with [example] (a single link) //remove potential markdown formatting (except what we need) $check = preg_replace('#[^a-z:\\[\\]]#', '', strtolower($line)); if (substr($check, 0, 8) != 'example:' and substr($check, 0, 9) != '[example]') { return false; } $context->addBlock(new ExampleElement($cursor->getLine(), $this->path)); $cursor->advanceBy(strlen($line)); $context->setBlocksParsed(true); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { $match = RegexHelper::matchAll('/^#{1,6}(?: +|$)/', $cursor->getLine(), $cursor->getFirstNonSpacePosition()); if (!$match) { return false; } $cursor->advanceToFirstNonSpace(); $cursor->advanceBy(strlen($match[0])); $level = strlen(trim($match[0])); $str = $cursor->getRemainder(); $str = preg_replace('/^ *#+ *$/', '', $str); $str = preg_replace('/ +#+ *$/', '', $str); $context->addBlock(new Header($level, $str)); $context->setBlocksParsed(true); return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { if (!in_array($cursor->getFirstNonSpaceCharacter(), IconBlock::getIconBlockTypes()) || $cursor->getCharacter($cursor->getFirstNonSpacePosition() + 1) !== '>') { return false; } $type = $cursor->getFirstNonSpaceCharacter(); $cursor->advanceToFirstNonSpace(); if ($cursor->peek() === '>') { $cursor->advanceBy(2); if ($cursor->getCharacter() === ' ') { $cursor->advance(); } } $context->addBlock(new IconBlock($type)); return true; }
public function parse(ContextInterface $context, Cursor $cursor) { $container = $context->getContainer(); if (!$container instanceof Paragraph) { return false; } $lines = $container->getStrings(); if (count($lines) < 1) { return false; } $match = RegexHelper::matchAll(self::REGEXP_DEFINITION, $cursor->getLine(), $cursor->getFirstNonSpacePosition()); if (null === $match) { return false; } $columns = $this->parseColumns($match); $head = $this->parseRow(trim(array_pop($lines)), $columns, TableCell::TYPE_HEAD); if (null === $head) { return false; } $table = new Table(function (Cursor $cursor) use(&$table, $columns) { $row = $this->parseRow($cursor->getLine(), $columns); if (null === $row) { if (null !== $table->getCaption()) { return false; } if (null !== ($caption = $this->parseCaption($cursor->getLine()))) { $table->setCaption($caption); return true; } return false; } $table->getBody()->appendChild($row); return true; }); $table->getHead()->appendChild($head); if (count($lines) >= 1) { $paragraph = new Paragraph(); foreach ($lines as $line) { $paragraph->addLine($line); } $context->replaceContainerBlock($paragraph); $context->addBlock($table); } else { $context->replaceContainerBlock($table); } return true; }
/** * @param ContextInterface $context * @param Cursor $cursor * * @return bool */ public function parse(ContextInterface $context, Cursor $cursor) { if ($cursor->isIndented()) { return false; } if ($cursor->getFirstNonSpaceCharacter() !== '<') { return false; } $savedState = $cursor->saveState(); $cursor->advanceToFirstNonSpace(); $line = $cursor->getRemainder(); for ($blockType = 1; $blockType <= 7; $blockType++) { $match = RegexHelper::matchAt(RegexHelper::getHtmlBlockOpenRegex($blockType), $line); if ($match !== null && ($blockType < 7 || !$context->getContainer() instanceof Paragraph)) { $cursor->restoreState($savedState); $context->addBlock(new HtmlBlock($blockType)); $context->setBlocksParsed(true); return true; } } $cursor->restoreState($savedState); return false; }
/** * @param ContextInterface $context * @param Cursor $cursor */ public function handleRemainingContents(ContextInterface $context, Cursor $cursor) { // create paragraph container for line $context->addBlock(new Paragraph()); $cursor->advanceToFirstNonSpace(); $context->getTip()->addLine($cursor->getRemainder()); }