diff --git a/src/Elements/BodyComponents/MjRaw.php b/src/Elements/BodyComponents/MjRaw.php new file mode 100644 index 0000000..d854cdb --- /dev/null +++ b/src/Elements/BodyComponents/MjRaw.php @@ -0,0 +1,66 @@ +> + */ + protected array $allowedAttributes = []; + + protected array $defaultAttributes = []; + + /** + * Override getContent to preserve raw content without trimming + */ + protected function getContent(): string + { + return $this->content; + } + + public function render(): string + { + // Return content as-is without any processing + return $this->getContent(); + } + + /** + * @return array> + */ + public function getStyles(): array + { + // No styles needed for raw HTML passthrough + return []; + } +} diff --git a/tests/Unit/Elements/BodyComponents/MjRawTest.php b/tests/Unit/Elements/BodyComponents/MjRawTest.php new file mode 100644 index 0000000..ff946ec --- /dev/null +++ b/tests/Unit/Elements/BodyComponents/MjRawTest.php @@ -0,0 +1,162 @@ +element = new MjRaw(); +}); + +it('is ending tag', function () { + expect($this->element->isEndingTag())->toBe(true); +}); + +it('returns the correct component name', function () { + expect($this->element->getTagName())->toBe('mj-raw'); +}); + +it('has no default attributes', function () { + // mj-raw has no attributes, so we just verify it doesn't error + expect($this->element)->toBeInstanceOf(MjRaw::class); +}); + +it('will correctly render raw HTML', function () { + $rawNode = new MjmlNode( + 'mj-raw', + null, + '
Raw HTML Content
', + true, + null + ); + + $factory = new ElementFactory(); + $mjRawElement = $factory->create($rawNode); + + expect($mjRawElement)->toBeInstanceOf(MjRaw::class); + + $out = $mjRawElement->render(); + + expect($out)->toBe('
Raw HTML Content
'); + expect($out)->not->toBeEmpty(); +}); + +it('will pass through complex HTML unchanged', function () { + $complexHtml = '
Link
'; + + $rawNode = new MjmlNode( + 'mj-raw', + null, + $complexHtml, + true, + null + ); + + $factory = new ElementFactory(); + $mjRawElement = $factory->create($rawNode); + + $out = $mjRawElement->render(); + + expect($out)->toBe($complexHtml); +}); + +it('will preserve whitespace and formatting', function () { + $htmlWithWhitespace = "
\n

Paragraph

\n
"; + + $rawNode = new MjmlNode( + 'mj-raw', + null, + $htmlWithWhitespace, + true, + null + ); + + $factory = new ElementFactory(); + $mjRawElement = $factory->create($rawNode); + + $out = $mjRawElement->render(); + + expect($out)->toBe($htmlWithWhitespace); +}); + +it('will pass through empty content', function () { + $rawNode = new MjmlNode( + 'mj-raw', + null, + '', + true, + null + ); + + $factory = new ElementFactory(); + $mjRawElement = $factory->create($rawNode); + + $out = $mjRawElement->render(); + + expect($out)->toBe(''); +}); + +it('will pass through HTML comments', function () { + $htmlWithComments = '
Content
'; + + $rawNode = new MjmlNode( + 'mj-raw', + null, + $htmlWithComments, + true, + null + ); + + $factory = new ElementFactory(); + $mjRawElement = $factory->create($rawNode); + + $out = $mjRawElement->render(); + + expect($out)->toBe($htmlWithComments); +}); + +it('will pass through scripts and styles', function () { + $htmlWithScript = ''; + + $rawNode = new MjmlNode( + 'mj-raw', + null, + $htmlWithScript, + true, + null + ); + + $factory = new ElementFactory(); + $mjRawElement = $factory->create($rawNode); + + $out = $mjRawElement->render(); + + expect($out)->toBe($htmlWithScript); +}); + +it('will pass through special characters', function () { + $htmlWithSpecialChars = '
 ©™<>&"\'
'; + + $rawNode = new MjmlNode( + 'mj-raw', + null, + $htmlWithSpecialChars, + true, + null + ); + + $factory = new ElementFactory(); + $mjRawElement = $factory->create($rawNode); + + $out = $mjRawElement->render(); + + expect($out)->toBe($htmlWithSpecialChars); +}); + +it('returns empty styles array', function () { + $styles = $this->element->getStyles(); + expect($styles)->toBeArray(); + expect($styles)->toBeEmpty(); +});