2

全部,

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

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

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

示例降价

{{ 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>
4

1 回答 1

1

诀窍是您的 Block 应该始终具有canContain()and matchesNextLine()方法return true;- 这些将确保后续行始终作为子块添加。(看看FencedCodeListBlock实现。)

这是一些应该可以工作的代码:

对象块.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;
    }
}

对象解析器.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;
    }
}

对象渲染器:

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
        );
    }
}

免责声明:虽然我是这个库的作者,但特定的逻辑(容器、提示和块关闭)大多是从 JS 版本中按原样分叉的,我只了解其中的 75% - 足以保留我的分叉工作并找出可行的方法:)

于 2017-09-28T03:07:24.577 回答