代码之家  ›  专栏  ›  技术社区  ›  Elliot

如何创建扩展以解析HPLeague/commonmark的多行

  •  2
  • Elliot  · 技术社区  · 8 年前

    全部的

    我试图创建一个扩展(我相信是为了扩展AbstractBlockParser),它将找到一个开始标记,将后面的行移动到一个块中,然后在找到结束标记时停止(在最后一行上)。

    在查看所提供的示例时,很难确定它们是如何构建由多行组成的块的,例如使用代码围栏,文档中没有涵盖这种情况。

    列表解析器代码似乎显示了添加到ListBlock的ListItems,但它如何知道何时停止?

    降价示例

    {{ Object ID
    Any markdown goes here.
    Some more
      * List 1
      * List 2
    }}
    

    <div class="object">
        <span>Object ID</span>
        <p>Any markdown goes here.
        Some more</p>
        <ul>
            <li>List 1</li>
            <li>List 2</li>
        </ul>
    </div>
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Colin O'Dell    8 年前

    诀窍是你的街区应该有 canContain() matchesNextLine() 方法始终 return true; -这将确保后续行始终作为子块添加。(请看 FencedCode ListBlock

    以下是一些应该有效的代码:

    ObjectBlock。php:

    class ObjectBlock extends AbstractBlock
    {
        private $objectId;
    
        public function __construct($objectId)
        {
            $this->objectId = $objectId;
        }
    
        public function getObjectId()
        {
            return $this->objectId;
        }
    
        public function canContain(AbstractBlock $block)
        {
            return true;
        }
    
        public function acceptsLines()
        {
            return false;
        }
    
        public function isCode()
        {
            return false;
        }
    
        public function matchesNextLine(Cursor $cursor)
        {
            return true;
        }
    }
    

    ObjectParser。php:

    class ObjectParser extends AbstractBlockParser
    {
        public function parse(ContextInterface $context, Cursor $cursor)
        {
            // Look for the starting syntax
            if ($cursor->match('/^{{ /')) {
                $id = $cursor->getRemainder();
                $cursor->advanceToEnd();
    
                $context->addBlock(new ObjectBlock($id));
    
                return true;
            // Look for the ending syntax
            } elseif ($cursor->match('/^}} +$/')) {
                // TODO: I don't know if this is the best approach, but it should work
                // Basically, we're going to locate a parent ObjectBlock in the AST...
                $container = $context->getContainer();
                while ($container) {
                    if ($container instanceof ObjectBlock) {
                        $cursor->advanceToEnd();
    
                        // Found it!  Now we'll close everything up to (and including) it
                        $context->getBlockCloser()->setLastMatchedContainer($container->parent());
                        $context->getBlockCloser()->closeUnmatchedBlocks();
                        $context->setBlocksParsed(true);
    
                        return true;
                    }
    
                    $container = $container->parent();
                }
            }
    
            return false;
        }
    }
    

    ObjectRenderer:

    class ObjectRenderer implements BlockRendererInterface
    {
        public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false)
        {
            $span = sprintf('<span>%s</span>', $block->getObjectId());
            $contents = $htmlRenderer->renderBlocks($block->children());
    
            return new HtmlElement('div', ['class' => 'object'],
                $span . $contents
            );
        }
    }