From 7ee26852e159d35646a2ef459c9b3bad976a9dc4 Mon Sep 17 00:00:00 2001 From: Sergey Grigorjev Date: Mon, 30 Sep 2024 19:34:20 +0300 Subject: [PATCH] Allowed direct append for nodes --- src/Builder/BuilderInterface.php | 3 +- src/Builder/InlineNodeBuilder.php | 3 +- src/Builder/TextBuilder.php | 3 +- src/Node/BlockNode.php | 23 +++- src/Node/Node.php | 5 + tests/Node/Block/DirectAppendTest.php | 189 ++++++++++++++++++++++++++ 6 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 tests/Node/Block/DirectAppendTest.php diff --git a/src/Builder/BuilderInterface.php b/src/Builder/BuilderInterface.php index 73e4ce4..3ba76d1 100644 --- a/src/Builder/BuilderInterface.php +++ b/src/Builder/BuilderInterface.php @@ -4,9 +4,10 @@ namespace DH\Adf\Builder; +use DH\Adf\Node\BlockNode; use DH\Adf\Node\Node; trait BuilderInterface { - abstract protected function append(Node $node): void; + abstract public function append(Node ...$nodes): BlockNode; } diff --git a/src/Builder/InlineNodeBuilder.php b/src/Builder/InlineNodeBuilder.php index e252bfe..b222f2c 100644 --- a/src/Builder/InlineNodeBuilder.php +++ b/src/Builder/InlineNodeBuilder.php @@ -4,6 +4,7 @@ namespace DH\Adf\Builder; +use DH\Adf\Node\BlockNode; use DH\Adf\Node\Inline\Emoji; use DH\Adf\Node\Inline\Hardbreak; use DH\Adf\Node\Inline\Mention; @@ -34,5 +35,5 @@ public function break(?Node $parent = null): self return $this; } - abstract protected function append(Node $node): void; + abstract public function append(Node ...$nodes): BlockNode; } diff --git a/src/Builder/TextBuilder.php b/src/Builder/TextBuilder.php index e60dd58..8467e26 100644 --- a/src/Builder/TextBuilder.php +++ b/src/Builder/TextBuilder.php @@ -4,6 +4,7 @@ namespace DH\Adf\Builder; +use DH\Adf\Node\BlockNode; use DH\Adf\Node\Inline\Text; use DH\Adf\Node\Mark\Em; use DH\Adf\Node\Mark\Link; @@ -79,5 +80,5 @@ public function link(string $text, string $href, ?string $title = null): self return $this; } - abstract protected function append(Node $node): void; + abstract public function append(Node ...$nodes): BlockNode; } diff --git a/src/Node/BlockNode.php b/src/Node/BlockNode.php index 9dac9bc..494a86b 100644 --- a/src/Node/BlockNode.php +++ b/src/Node/BlockNode.php @@ -52,16 +52,29 @@ public function getContent(): array return $this->content; } - protected function append(Node $node): void + public function append(Node ...$nodes): BlockNode { - foreach ($this->allowedContentTypes as $type) { - if ($node instanceof $type) { + foreach ($nodes as $node) { + if ($this->isAppendAllowed($node)) { $this->content[] = $node; + } else { + throw new InvalidArgumentException( + sprintf('Invalid content type "%s" for block node "%s".', $node->getType(), $this->getType()) + ); + } + } - return; + return $this; + } + + protected function isAppendAllowed(Node $node): bool + { + foreach ($this->allowedContentTypes as $allowedContentType) { + if ($node instanceof $allowedContentType) { + return true; } } - throw new InvalidArgumentException(sprintf('Invalid content type "%s" for block node "%s".', $node->type, $this->type)); + return false; } } diff --git a/src/Node/Node.php b/src/Node/Node.php index 7374fec..277aa63 100644 --- a/src/Node/Node.php +++ b/src/Node/Node.php @@ -141,6 +141,11 @@ public static function load(array $data): self return $node; } + public function getType(): string + { + return $this->type; + } + protected function attrs(): array { return []; diff --git a/tests/Node/Block/DirectAppendTest.php b/tests/Node/Block/DirectAppendTest.php new file mode 100644 index 0000000..69e3963 --- /dev/null +++ b/tests/Node/Block/DirectAppendTest.php @@ -0,0 +1,189 @@ +append( + new Paragraph() + ) + ; + + $doc = json_encode($document); + + self::assertJsonStringEqualsJsonString($doc, json_encode([ + 'version' => 1, + 'type' => 'doc', + 'content' => [ + [ + 'type' => 'paragraph', + 'content' => [], + ], + ], + ])); + } + + public function testDocumentWithTextInParagraph(): void + { + $document = (new Document()) + ->append( + (new Paragraph()) + ->append( + new Text('Luke, ', new TextColor('red')), + new Text('may '), + new Text('the ', new Em()), + new Text('force ', new Strong()), + new Text('be '), + new Text('with ', new Underline()), + new Text('you! ', new Strike()), + new Text('Obi-Wan', new Subsup('sub')), + new Text('Kenobi', new Subsup('sup')), + new Text('Star Wars @ Wikipedia', new Link('https://wikipedia.org/wiki/Star_Wars')) + ), + ) + ; + + $doc = json_encode($document); + + self::assertJsonStringEqualsJsonString($doc, json_encode([ + 'version' => 1, + 'type' => 'doc', + 'content' => [ + [ + 'type' => 'paragraph', + 'content' => [ + [ + 'type' => 'text', + 'text' => 'Luke, ', + 'marks' => [ + [ + 'type' => 'textColor', + 'attrs' => [ + 'color' => 'red', + ], + ], + ], + ], + [ + 'type' => 'text', + 'text' => 'may ', + ], + [ + 'type' => 'text', + 'text' => 'the ', + 'marks' => [ + [ + 'type' => 'em', + ], + ], + ], + [ + 'type' => 'text', + 'text' => 'force ', + 'marks' => [ + [ + 'type' => 'strong', + ], + ], + ], + [ + 'type' => 'text', + 'text' => 'be ', + ], + [ + 'type' => 'text', + 'text' => 'with ', + 'marks' => [ + [ + 'type' => 'underline', + ], + ], + ], + [ + 'type' => 'text', + 'text' => 'you! ', + 'marks' => [ + [ + 'type' => 'strike', + ], + ], + ], + [ + 'type' => 'text', + 'text' => 'Obi-Wan', + 'marks' => [ + [ + 'type' => 'subsup', + 'attrs' => [ + 'type' => 'sub', + ], + ], + ], + ], + [ + 'type' => 'text', + 'text' => 'Kenobi', + 'marks' => [ + [ + 'type' => 'subsup', + 'attrs' => [ + 'type' => 'sup', + ], + ], + ], + ], + [ + 'type' => 'text', + 'text' => 'Star Wars @ Wikipedia', + 'marks' => [ + [ + 'type' => 'link', + 'attrs' => [ + 'href' => 'https://wikipedia.org/wiki/Star_Wars', + ], + ], + ], + ], + ], + ], + ], + ])); + } + + public function testIllegalAppend() + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid content type "panel" for block node "paragraph".'); + + (new Document()) + ->append( + (new Paragraph()) + ->append(new Panel()) + ) + ; + } +}