dongshan2004 2017-09-26 20:37
浏览 12
已采纳

如何创建扩展来解析符号/共同标记的多行

All,

I am trying to create an extension (to extend AbstractBlockParser, I believe) which will find an opening tag, move the lines following into a block, and then stop when a closing tag is found (on its own on a last line).

While looking at the examples provided, it is extremely hard to work out how they build a block composed of multiple lines, e.g. using a code fence, and the documentation does not cover this scenario.

The list parser code seems to show ListItems being added to a ListBlock, but how does it know when to stop?

Example Markdown

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

And the output might be:

<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条回答 默认 最新

  • dryeyhe0266 2017-09-28 03:07
    关注

    The trick is that your Block should have the canContain() and matchesNextLine() methods always return true; - these will ensure that subsequent lines always get added as child blocks. (Take a look at the FencedCode and ListBlock implementations.)

    Here's some code which should work:

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

    Disclaimer: Although I am the author of this library, the particular logic (containers, tips, and block-closing) was mostly forked as-is from the JS version and I only understand about 75% of it - just enough to keep my fork working and figure out approaches that work :)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP