Add RenderStack

This is a special configurable that can be used to alter the
Renderable[] AST before output.
This commit is contained in:
Aidan Woods 2021-10-12 00:06:51 +01:00
parent 7c2681be19
commit c773305bc1
No known key found for this signature in database
GPG Key ID: 9A6A8EFAA512BBB9
3 changed files with 100 additions and 1 deletions

View File

@ -0,0 +1,41 @@
<?php
namespace Erusev\Parsedown\Configurables;
use Erusev\Parsedown\Configurable;
use Erusev\Parsedown\Html\Renderable;
final class RenderStack implements Configurable
{
/** @var list<\Closure(Renderable[]):Renderable[]> */
private $stack;
/**
* @param list<\Closure(Renderable[]):Renderable[]> $stack
*/
private function __construct($stack = [])
{
$this->stack = $stack;
}
/** @return self */
public static function initial()
{
return new self;
}
/**
* @param \Closure(Renderable[]):Renderable[] $RenderMap
* @return self
*/
public function push(\Closure $RenderMap): self
{
return new self(\array_merge($this->stack, [$RenderMap]));
}
/** @return list<\Closure(Renderable[]):Renderable[]> */
public function getStack(): array
{
return $this->stack;
}
}

View File

@ -14,6 +14,7 @@ use Erusev\Parsedown\Components\StateUpdatingBlock;
use Erusev\Parsedown\Configurables\BlockTypes;
use Erusev\Parsedown\Configurables\InlineTypes;
use Erusev\Parsedown\Configurables\RecursionLimiter;
use Erusev\Parsedown\Configurables\RenderStack;
use Erusev\Parsedown\Html\Renderable;
use Erusev\Parsedown\Parsing\Excerpt;
use Erusev\Parsedown\Parsing\Line;
@ -44,7 +45,18 @@ final class Parsedown
$this->State->isolatedCopy()
);
$Renderables = $State->applyTo($StateRenderables);
$Renderables = \array_reduce(
\array_reverse($State->get(RenderStack::class)->getStack()),
/**
* @param Renderable[] $Renderables
* @param \Closure(Renderable[]):Renderable[] $RenderMap
* @return Renderable[]
*/
function (array $Renderables, \Closure $RenderMap): array {
return $RenderMap($Renderables);
},
$State->applyTo($StateRenderables)
);
$html = self::render($Renderables);

View File

@ -0,0 +1,46 @@
<?php
namespace Erusev\Parsedown\Tests\Configurables;
use Erusev\Parsedown\Configurables\RenderStack;
use Erusev\Parsedown\Html\Renderable;
use Erusev\Parsedown\Html\Renderables\Text;
use Erusev\Parsedown\Parsedown;
use Erusev\Parsedown\State;
use PHPUnit\Framework\TestCase;
final class RenderStackTest extends TestCase
{
/**
* @return void
* @throws \PHPUnit\Framework\ExpectationFailedException
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function testRenderStack()
{
$State = new State;
$RenderStack = $State->get(RenderStack::class)
->push(
/**
* @param Renderable[] $Rs
* return Renderable[]
*/
function ($Rs) { return \array_merge($Rs, [new Text('baz')]); }
)
->push(
/**
* @param Renderable[] $Rs
* return Renderable[]
*/
function ($Rs) { return \array_merge($Rs, [new Text('bar')]); }
)
;
$State = $State->setting($RenderStack);
$this->assertSame(
"<p>foo</p>\nbar\nbaz",
(new Parsedown($State))->toHtml('foo')
);
}
}