diff --git a/resources/views/contents/_content.blade.php b/resources/views/attachables/_content.blade.php similarity index 51% rename from resources/views/contents/_content.blade.php rename to resources/views/attachables/_content.blade.php index 3224a39..b0092e8 100644 --- a/resources/views/contents/_content.blade.php +++ b/resources/views/attachables/_content.blade.php @@ -1 +1,3 @@ +
{!! trim($content->renderTrixContentAttachment($options)) !!} +
diff --git a/resources/views/contents/_horizontal_rule.blade.php b/resources/views/contents/_horizontal_rule.blade.php deleted file mode 100644 index e123ba7..0000000 --- a/resources/views/contents/_horizontal_rule.blade.php +++ /dev/null @@ -1 +0,0 @@ -
diff --git a/src/AttachableFactory.php b/src/AttachableFactory.php index d0fde31..d81a1c5 100644 --- a/src/AttachableFactory.php +++ b/src/AttachableFactory.php @@ -32,7 +32,7 @@ public static function fromNode(DOMElement $node): Attachables\AttachableContrac return $attachable; } - return new Attachables\MissingAttachable(); + return new Attachables\MissingAttachable; } private static function attachableFromSgid(string $sgid) diff --git a/src/Attachables/ContentAttachment.php b/src/Attachables/ContentAttachment.php index 81b75c3..39270b7 100644 --- a/src/Attachables/ContentAttachment.php +++ b/src/Attachables/ContentAttachment.php @@ -3,67 +3,56 @@ namespace Tonysm\RichTextLaravel\Attachables; use DOMElement; -use Illuminate\Support\Str; +use Tonysm\RichTextLaravel\Content; class ContentAttachment implements AttachableContract { - const NAME_PATTERN = '/vnd\.richtextlaravel\.(.+)\.html/'; + private Content $contentInstance; - public static $validNames = ['horizontal-rule']; + private string $renderedHtml; public static function fromNode(DOMElement $node): ?static { - if (! $node->hasAttribute('content-type')) { + if (! $node->hasAttribute('content-type') || ! $node->hasAttribute('content')) { return null; } - if (! preg_match(static::NAME_PATTERN, $node->getAttribute('content-type'), $matches)) { - return null; - } - - $name = $matches[1]; + $contentType = $node->getAttribute('content-type'); + $content = trim($node->getAttribute('content')); - if (! $name || ! static::validName($name)) { - return null; + if (str_contains($contentType, 'html') && ! empty($content)) { + return new static($contentType, $content); } - - return new static($name); } - private static function validName(string $name): bool - { - return in_array($name, static::$validNames); - } - - public function __construct(public $name) - { - } + public function __construct( + public string $contentType, + public string $content, + ) {} public function toRichTextAttributes(array $attributes): array { return [ - 'content' => $this->renderTrixContentAttachment(), + 'contentType' => $this->contentType, + 'content' => $this->content, ]; } public function equalsToAttachable(AttachableContract $attachable): bool { return $attachable instanceof static - && $attachable->name === $this->name; + && $attachable->contentType === $this->contentType + && $attachable->content === $this->content; } public function richTextAsPlainText(): string { - if ($this->name === 'horizontal-rule') { - return ' ┄ '; - } - - return ' '; + return $this->contentInstance()->fragment->source->textContent; } public function richTextRender(array $options = []): string { - return view('rich-text-laravel::contents._content', [ + return view('rich-text-laravel::attachables._content', [ 'content' => $this, 'options' => $options, ])->render(); @@ -71,9 +60,11 @@ public function richTextRender(array $options = []): string public function renderTrixContentAttachment(array $options = []): string { - return view('rich-text-laravel::contents._'.Str::of($this->name)->studly()->snake('_'), [ - 'content' => $this, - 'options' => $options, - ])->render(); + return $this->renderedHtml ??= $this->contentInstance()->fragment->toHtml(); + } + + private function contentInstance(): Content + { + return $this->contentInstance ??= new Content($this->content); } } diff --git a/src/Attachment.php b/src/Attachment.php index 0dd62b8..5a56e12 100644 --- a/src/Attachment.php +++ b/src/Attachment.php @@ -18,7 +18,7 @@ class Attachment public static $SELECTOR = '//rich-text-attachment'; - const ATTRIBUTES = ['sgid', 'content-type', 'url', 'href', 'filename', 'filesize', 'width', 'height', 'previewable', 'presentation', 'caption']; + const ATTRIBUTES = ['sgid', 'content-type', 'url', 'href', 'filename', 'filesize', 'width', 'height', 'previewable', 'presentation', 'caption', 'content']; private $cachedAttributes; @@ -79,9 +79,7 @@ private static function processAttributes(array $attributes): array ->all(); } - public function __construct(public DOMElement $node, public AttachableContract $attachable) - { - } + public function __construct(public DOMElement $node, public AttachableContract $attachable) {} public function withFullAttributes(): static { diff --git a/src/AttachmentGallery.php b/src/AttachmentGallery.php index c00db9a..6c88b5d 100644 --- a/src/AttachmentGallery.php +++ b/src/AttachmentGallery.php @@ -34,9 +34,7 @@ public static function selector(): string ); } - public function __construct(public DOMElement $node) - { - } + public function __construct(public DOMElement $node) {} public function attachments(): Collection { diff --git a/src/Commands/InstallCommand.php b/src/Commands/InstallCommand.php index 2d86dac..151c869 100644 --- a/src/Commands/InstallCommand.php +++ b/src/Commands/InstallCommand.php @@ -237,6 +237,6 @@ protected static function updateNodePackages(callable $callback, $dev = true) private function phpBinary() { - return (new PhpExecutableFinder())->find(false) ?: 'php'; + return (new PhpExecutableFinder)->find(false) ?: 'php'; } } diff --git a/src/Fragment.php b/src/Fragment.php index 1e3efb3..9e4ff41 100644 --- a/src/Fragment.php +++ b/src/Fragment.php @@ -31,9 +31,7 @@ public static function fromHtml(?string $html = null): self return HtmlConversion::fragmentForHtml($html); } - public function __construct(public DOMDocument $source) - { - } + public function __construct(public DOMDocument $source) {} public function findAll(string $selector): Collection { diff --git a/src/TrixAttachment.php b/src/TrixAttachment.php index 40aed76..eecdfb7 100644 --- a/src/TrixAttachment.php +++ b/src/TrixAttachment.php @@ -4,6 +4,7 @@ use DOMElement; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; class TrixAttachment @@ -56,9 +57,7 @@ private static function typeCast(string $key, $value) }; } - public function __construct(public DOMElement $node) - { - } + public function __construct(public DOMElement $node) {} public function attributes(): array { @@ -93,7 +92,7 @@ private function readJsonAttribute(string $key): array $data = json_decode($value ?: '[]', true); if (json_last_error() !== JSON_ERROR_NONE) { - logger(sprintf( + Log::notice(sprintf( '[%s] Couldnt parse JSON %s from NODE %s', static::class, $value, diff --git a/tests/ContentTest.php b/tests/ContentTest.php index af4182d..1fd2825 100644 --- a/tests/ContentTest.php +++ b/tests/ContentTest.php @@ -2,6 +2,8 @@ namespace Tonysm\RichTextLaravel\Tests; +use Illuminate\Support\Facades\Log; +use Tonysm\RichTextLaravel\Attachables\ContentAttachment; use Tonysm\RichTextLaravel\Attachables\MissingAttachable; use Tonysm\RichTextLaravel\Attachables\RemoteImage; use Tonysm\RichTextLaravel\Attachment; @@ -208,6 +210,8 @@ public function converts_trix_formatetd_attachments_with_custom_tag_name() /** @test */ public function ignores_trix_formatteed_attachments_with_bad_json() { + Log::shouldReceive('notice')->once(); + $html = <<<'HTML'
HTML; @@ -505,44 +509,28 @@ public function renders_file_attachments() } /** @test */ - public function renders_horizontal_rules_as_content_attachment() + public function renders_html_content_attachment() { - $content = $this->fromHtml(<<<'HTML' -
-
-
-
-
- HTML); + $attachment = $this->attachmentFromHtml(''); + $attachable = $attachment->attachable; - $this->assertEquals(<<<'HTML' -
-
+ $this->assertInstanceOf(ContentAttachment::class, $attachable); + $this->assertEquals('text/html', $attachable->contentType); + $this->assertEquals('abc', $attachable->content); -
- HTML, $content->renderWithAttachments()); + $trixAttachment = $attachment->toTrixAttachment(); + $this->assertEquals('text/html', $trixAttachment->attributes()['contentType']); + $this->assertEquals('abc', $trixAttachment->attributes()['content']); } /** @test */ - public function renders_horizontal_rules_for_trix() + public function renders_content_attachment() { - $content = $this->fromHtml(<<<'HTML' -
-
-
-
-
- HTML); + $attachment = $this->attachmentFromHtml(''); + /** @var ContentAttachment $attachable */ + $attachable = $attachment->attachable; - $this->assertEquals(<<<'HTML' -
-
-
- HTML, $content->toTrixHtml()); + $this->assertEquals('

abc

', $attachable->renderTrixContentAttachment()); } /** @test */ @@ -584,6 +572,11 @@ private function fromHtml(string $html): Content { return tap(new Content($html), fn (Content $content) => $this->assertNotEmpty($content->toHtml())); } + + private function attachmentFromHtml(string $html): Attachment + { + return $this->fromHtml($html)->attachments()->first(); + } } class UserWithCustomRenderContent extends User diff --git a/tests/PlainTextConversionTest.php b/tests/PlainTextConversionTest.php index 44d14e2..5a52b75 100644 --- a/tests/PlainTextConversionTest.php +++ b/tests/PlainTextConversionTest.php @@ -200,14 +200,25 @@ public function handles_deeply_nested() } /** @test */ - public function converts_horizontal_rule_to_plain_text() + public function converts_html_content() { $this->assertConvertedTo( - "Hello\n\n\n ┄ \nWorld", + "Hello\n\n\n\nWorld", trim(<<<'HTML'
Hello

-
+
+
+
World
+ HTML) + ); + + $this->assertConvertedTo( + "Hello\n\n\nhello\nWorld", + trim(<<<'HTML' +
Hello
+
+

World
HTML) diff --git a/workbench/app/Html/SanitizerFactory.php b/workbench/app/Html/SanitizerFactory.php index dd6475e..d043945 100644 --- a/workbench/app/Html/SanitizerFactory.php +++ b/workbench/app/Html/SanitizerFactory.php @@ -24,14 +24,14 @@ private static function configFor($config = null): HtmlSanitizerConfig private static function defaultConfig(): HtmlSanitizerConfig { - return (new HtmlSanitizerConfig()) + return (new HtmlSanitizerConfig) ->allowSafeElements() ->allowAttribute('class', '*'); } private static function minimalConfig(): HtmlSanitizerConfig { - return (new HtmlSanitizerConfig()) + return (new HtmlSanitizerConfig) ->allowElement('br') ->allowElement('div') ->allowElement('p') diff --git a/workbench/app/Models/Opengraph/OpengraphEmbed.php b/workbench/app/Models/Opengraph/OpengraphEmbed.php index 10313db..bc47b2c 100644 --- a/workbench/app/Models/Opengraph/OpengraphEmbed.php +++ b/workbench/app/Models/Opengraph/OpengraphEmbed.php @@ -56,8 +56,7 @@ public function __construct( public $url, public $filename, public $description, - ) { - } + ) {} public function toRichTextAttributes(array $attributes): array {