From c773305bc143610efd4e9c8f679adf676999f446 Mon Sep 17 00:00:00 2001 From: Aidan Woods Date: Tue, 12 Oct 2021 00:06:51 +0100 Subject: [PATCH] Add RenderStack This is a special configurable that can be used to alter the Renderable[] AST before output. --- src/Configurables/RenderStack.php | 41 ++++++++++++++++++ src/Parsedown.php | 14 ++++++- tests/src/Configurables/RenderStackTest.php | 46 +++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/Configurables/RenderStack.php create mode 100644 tests/src/Configurables/RenderStackTest.php diff --git a/src/Configurables/RenderStack.php b/src/Configurables/RenderStack.php new file mode 100644 index 0000000..fe0930d --- /dev/null +++ b/src/Configurables/RenderStack.php @@ -0,0 +1,41 @@ + */ + 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; + } +} diff --git a/src/Parsedown.php b/src/Parsedown.php index bfb5bdf..cda8a85 100644 --- a/src/Parsedown.php +++ b/src/Parsedown.php @@ -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); diff --git a/tests/src/Configurables/RenderStackTest.php b/tests/src/Configurables/RenderStackTest.php new file mode 100644 index 0000000..8755304 --- /dev/null +++ b/tests/src/Configurables/RenderStackTest.php @@ -0,0 +1,46 @@ +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( + "

foo

\nbar\nbaz", + (new Parsedown($State))->toHtml('foo') + ); + } +}