2017-09-26 68 views
2

所有多線,如何創建一個擴展解析爲thephpleague/commonmark

我想創建一個擴展(擴大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> 
+0

你能提供一個你想要解析的Markdown的例子,以及生成的HTML應該是什麼? –

+0

@ ColinO'Dell - 完成! – Kurucu

回答

1

訣竅是,你的格擋應該始終return true;canContain()matchesNextLine()方法 - 這些將確保後續行總是添加爲子塊。 (看看的FencedCodeListBlock實現。)

下面是一些代碼,應該工作:

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

Objec tRenderer:

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它的% - 只是足以讓我的叉子工作,並找出可行的方法:)

+0

這個工作,我需要給它一個適當的嘗試,然後我會提供一些反饋。非常感謝你。 – Kurucu

+0

很高興能幫到你! –