erusev / parsedown

Better Markdown Parser in PHP
https://parsedown.org
MIT License
14.74k stars 1.12k forks source link

Blockquote interrupt #693

Closed whyte624 closed 5 years ago

whyte624 commented 5 years ago

Is there an easy way to interrupt blockqoute on first linebreak?

Code:

> Hi, First guy!
Hi, Second guy!

Will be rendered as:

Hi, First guy!

Hi, Second guy!

Please, note that I have $parser->setBreaksEnabled(true);

aidantwoods commented 5 years ago

At the moment setBreaksEnabled doesn't alter interruption rules, so you'd need an extension. Assuming no huge changes to #685, then in 2.0 you could swap the BlockQuote included by default with your own defined roughly like:

<?php

use Erusev\Parsedown\AST\Handler;
use Erusev\Parsedown\AST\StateRenderable;
use Erusev\Parsedown\Components\Block;
use Erusev\Parsedown\Components\Blocks\BlockQuote;
use Erusev\Parsedown\Components\ContinuableBlock;
use Erusev\Parsedown\Html\Renderables\Element;
use Erusev\Parsedown\Parsing\Context;
use Erusev\Parsedown\State;

final class CustomBlockQuote implements ContinuableBlock
{
    /** @var BlockQuote */
    private $BlockQuote;

    private function __construct(BlockQuote $BlockQuote)
    {
        $this->BlockQuote = $BlockQuote;
    }

    /**
     * @param Context $Context
     * @param State $State
     * @param Block|null $Block
     * @return static|null
     */
    public static function build(
        Context $Context,
        State $State,
        Block $Block = null
    ) {
        $BlockQuote = BlockQuote::build($Context, $State, $Block);

        if (isset($BlockQuote)) {
            return new self($BlockQuote);
        }

        return null;
    }

    /**
     * @param Context $Context
     * @param State $State
     * @return self|null
     */
    public function advance(Context $Context, State $State)
    {
        if (\preg_match('/^>[ \t]?+/', $Context->line()->text())) {
            return $this->BlockQuote->advance($Context, $State);
        }

        return null;
    }

    /**
     * @return Handler<Element>
     */
    public function stateRenderable()
    {
        return $this->BlockQuote->stateRenderable();
    }
}

which just defers to the BlockQuote in Parsedown for parsing and rendering, but when advancing to a new line it checks to assert that the > is present at the beginning of the line