public function processDocument(Document $document)
 {
     $walker = $document->walker();
     while ($event = $walker->next()) {
         $node = $event->getNode();
         if ($event->isEntering() || !$node instanceof Attributes) {
             continue;
         }
         list($target, $direction) = $this->findTargetAndDirection($node);
         if ($target) {
             if (($parent = $target->parent()) instanceof ListItem && $parent->parent() instanceof ListBlock && $parent->parent()->isTight()) {
                 $target = $parent;
             }
             if ($direction === self::DIRECTION_SUFFIX) {
                 $attributes = AttributesUtils::merge($target, $node->getAttributes());
             } else {
                 $attributes = AttributesUtils::merge($node->getAttributes(), $target);
             }
             $target->data['attributes'] = $attributes;
         }
         if ($node instanceof AbstractBlock && $node->endsWithBlankLine() && $node->next() && $node->previous()) {
             $node->previous()->setLastLineBlank(true);
         }
         $node->detach();
     }
 }
 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;
 }
 private function applyAttributes(AbstractBlock $block)
 {
     $previous = null;
     $prepend = null;
     foreach ($block->getChildren() as $key => $child) {
         if ($child instanceof Attributes) {
             if ($child->isPrepend()) {
                 $prepend = $child;
             } elseif ($child->isAppend()) {
                 $previous->data['attributes'] = AttributesUtils::merge($previous ?: $block, $child->getAttributes());
             }
             $block->removeChild($child);
         } else {
             if (isset($prepend)) {
                 $child->data['attributes'] = AttributesUtils::merge($child, $prepend->getAttributes());
             }
             $prepend = null;
             $this->applyAttributes($child);
             $previous = $child;
         }
     }
     if (isset($prepend)) {
         $block->data['attributes'] = AttributesUtils::merge($block, $prepend->getAttributes());
     }
     return $block;
 }
 public function processInlines(ArrayCollection $inlines, DelimiterStack $delimiterStack, Delimiter $stackBottom = null)
 {
     $previous = null;
     foreach ($inlines as $key => $inline) {
         if (!$inline instanceof InlineAttributes) {
             $previous = $inline;
             continue;
         }
         $inlines->remove($key);
         if (0 === count($inline->getAttributes())) {
             continue;
         }
         $node = null;
         if ($inline->isBlock()) {
             foreach (debug_backtrace(false) as $trace) {
                 if ('League\\CommonMark\\DocParser' === $trace['class'] && 'processInlines' === $trace['function']) {
                     $node = $trace['args'][1];
                     break;
                 }
             }
             if ($node->getParent() instanceof ListItem && $node->getParent()->getParent()->isTight()) {
                 $node = $node->getParent();
             }
         } elseif ($previous) {
             $node = $previous;
         }
         if ($node) {
             $node->data['attributes'] = AttributesUtils::merge($node, $inline->getAttributes());
         }
     }
 }
 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;
 }
 public function parse(ContextInterface $context, InlineParserContext $inlineContext)
 {
     $cursor = $inlineContext->getCursor();
     if ($cursor->getFirstNonSpaceCharacter() !== '{') {
         return false;
     }
     $char = $cursor->getCharacter();
     if ('{' === $char) {
         $char = (string) $cursor->getCharacter($cursor->getPosition() - 1);
     }
     $attributes = AttributesUtils::parse($cursor);
     if (empty($attributes)) {
         return false;
     }
     $inlineContext->getInlines()->add(new InlineAttributes($attributes, ' ' === $char || '' === $char));
     return true;
 }
 public function parse(InlineParserContext $inlineContext)
 {
     $cursor = $inlineContext->getCursor();
     if ($cursor->getFirstNonSpaceCharacter() !== '{') {
         return false;
     }
     $char = $cursor->getCharacter();
     if ('{' === $char) {
         $char = (string) $cursor->getCharacter($cursor->getPosition() - 1);
     }
     $attributes = AttributesUtils::parse($cursor);
     if (empty($attributes)) {
         return false;
     }
     if ('' === $char) {
         $cursor->advanceToFirstNonSpace();
     }
     $node = new InlineAttributes($attributes, ' ' === $char || '' === $char);
     $inlineContext->getContainer()->appendChild($node);
     $inlineContext->getDelimiterStack()->push(new Delimiter('attributes', 1, $node, false, false));
     return true;
 }
 public function processInlines(DelimiterStack $delimiterStack, Delimiter $stackBottom = null)
 {
     $delimiter = $delimiterStack->getTop();
     while ($delimiter !== null) {
         $node = $delimiter->getInlineNode();
         if (!$node instanceof InlineAttributes) {
             $delimiter = $delimiter->getPrevious();
             continue;
         }
         if ($node->isBlock()) {
             $target = $node->parent();
             if (($parent = $target->parent()) instanceof ListItem && $parent->parent() instanceof ListBlock && $parent->parent()->isTight()) {
                 $target = $parent;
             }
         } else {
             $target = $node->previous();
         }
         $target->data['attributes'] = AttributesUtils::merge($node->getAttributes(), $target);
         $node->detach();
         $delimiter = $delimiter->getPrevious();
     }
 }