diff --git a/src/Illuminate/Mail/Markdown.php b/src/Illuminate/Mail/Markdown.php index e8ec2defc4c4..54c9c2ece372 100644 --- a/src/Illuminate/Mail/Markdown.php +++ b/src/Illuminate/Mail/Markdown.php @@ -69,9 +69,25 @@ public function render($view, array $data = [], $inliner = null) $contents = $bladeCompiler->usingEchoFormat( 'new \Illuminate\Support\EncodedHtmlString(%s)', function () use ($view, $data) { - return $this->view->replaceNamespace( - 'mail', $this->htmlComponentPaths() - )->make($view, $data)->render(); + EncodedHtmlString::encodeUsing(function ($value) { + $replacements = [ + '[' => '\[', + '<' => '<', + '>' => '>', + ]; + + return str_replace(array_keys($replacements), array_values($replacements), $value); + }); + + try { + $contents = $this->view->replaceNamespace( + 'mail', $this->htmlComponentPaths() + )->make($view, $data)->render(); + } finally { + EncodedHtmlString::flushState(); + } + + return $contents; } ); @@ -84,7 +100,7 @@ function () use ($view, $data) { } return new HtmlString(($inliner ?: new CssToInlineStyles)->convert( - $contents, $this->view->make($theme, $data)->render() + str_replace('\[', '[', $contents), $this->view->make($theme, $data)->render() )); } @@ -112,10 +128,15 @@ public function renderText($view, array $data = []) * Parse the given Markdown text into HTML. * * @param string $text + * @param bool $encoded * @return \Illuminate\Support\HtmlString */ - public static function parse($text) + public static function parse($text, bool $encoded = false) { + if ($encoded === false) { + return new HtmlString(static::converter()->convert($text)->getContent()); + } + EncodedHtmlString::encodeUsing(function ($value) { $replacements = [ '[' => '\[', diff --git a/src/Illuminate/Mail/resources/views/html/button.blade.php b/src/Illuminate/Mail/resources/views/html/button.blade.php index 4a9bf7d00495..050e969d2130 100644 --- a/src/Illuminate/Mail/resources/views/html/button.blade.php +++ b/src/Illuminate/Mail/resources/views/html/button.blade.php @@ -12,7 +12,7 @@
-{{ $slot }} +{!! $slot !!}
diff --git a/src/Illuminate/Mail/resources/views/html/header.blade.php b/src/Illuminate/Mail/resources/views/html/header.blade.php index 56197f8d23f3..c47a260c56b2 100644 --- a/src/Illuminate/Mail/resources/views/html/header.blade.php +++ b/src/Illuminate/Mail/resources/views/html/header.blade.php @@ -5,7 +5,7 @@ @if (trim($slot) === 'Laravel') @else -{{ $slot }} +{!! $slot !!} @endif diff --git a/src/Illuminate/Mail/resources/views/html/layout.blade.php b/src/Illuminate/Mail/resources/views/html/layout.blade.php index d31a01de8630..0fa6b82f72b2 100644 --- a/src/Illuminate/Mail/resources/views/html/layout.blade.php +++ b/src/Illuminate/Mail/resources/views/html/layout.blade.php @@ -23,7 +23,7 @@ } } -{{ $head ?? '' }} +{!! $head ?? '' !!} @@ -31,7 +31,7 @@ -{{ $header ?? '' }} +{!! $header ?? '' !!} @@ -40,16 +40,16 @@ -{{ $footer ?? '' }} +{!! $footer ?? '' !!} diff --git a/src/Illuminate/Mail/resources/views/html/message.blade.php b/src/Illuminate/Mail/resources/views/html/message.blade.php index 1a874fc26de5..f1e815f32a41 100644 --- a/src/Illuminate/Mail/resources/views/html/message.blade.php +++ b/src/Illuminate/Mail/resources/views/html/message.blade.php @@ -7,13 +7,13 @@ {{-- Body --}} -{{ $slot }} +{!! $slot !!} {{-- Subcopy --}} @isset($subcopy) -{{ $subcopy }} +{!! $subcopy !!}} @endisset diff --git a/src/Illuminate/Mail/resources/views/html/panel.blade.php b/src/Illuminate/Mail/resources/views/html/panel.blade.php index 2975a60a021e..812db7c08e77 100644 --- a/src/Illuminate/Mail/resources/views/html/panel.blade.php +++ b/src/Illuminate/Mail/resources/views/html/panel.blade.php @@ -4,7 +4,7 @@
-{{ Illuminate\Mail\Markdown::parse($slot) }} +{!! Illuminate\Mail\Markdown::parse($slot) !!}
diff --git a/tests/Integration/Mail/Fixtures/message-with-template.blade.php b/tests/Integration/Mail/Fixtures/message-with-template.blade.php new file mode 100644 index 000000000000..9c53cef7e1bb --- /dev/null +++ b/tests/Integration/Mail/Fixtures/message-with-template.blade.php @@ -0,0 +1,4 @@ +@component('mail::message') +*Hi* {{ $user->name }} + +@endcomponent diff --git a/tests/Integration/Mail/MailableTest.php b/tests/Integration/Mail/MailableTest.php index 339ebb2422d7..4ff0f539b6ad 100644 --- a/tests/Integration/Mail/MailableTest.php +++ b/tests/Integration/Mail/MailableTest.php @@ -2,14 +2,20 @@ namespace Illuminate\Tests\Integration\Mail; +use Illuminate\Foundation\Auth\User; +use Illuminate\Foundation\Testing\LazilyRefreshDatabase; use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; +use Orchestra\Testbench\Attributes\WithMigration; +use Orchestra\Testbench\Factories\UserFactory; use Orchestra\Testbench\TestCase; use PHPUnit\Framework\Attributes\DataProvider; class MailableTest extends TestCase { + use LazilyRefreshDatabase; + /** {@inheritdoc} */ #[\Override] protected function defineEnvironment($app) @@ -69,4 +75,55 @@ public static function markdownEncodedDataProvider() 'My message is: Visit <span>https://laravel.com/docs</span> to browse the documentation', ]; } + + #[WithMigration] + #[DataProvider('markdownEncodedTemplateDataProvider')] + public function testItCanAssertMarkdownEncodedStringUsingTemplate($given, $expected) + { + $user = UserFactory::new()->create([ + 'name' => $given, + ]); + + $mailable = new class($user) extends Mailable + { + public $theme = 'taylor'; + + public function __construct(public User $user) + { + // + } + + public function build() + { + return $this->markdown('message-with-template'); + } + }; + + $mailable->assertSeeInHtml($expected, false); + } + + public static function markdownEncodedTemplateDataProvider() + { + yield ['[Laravel](https://laravel.com)', 'Hi [Laravel](https://laravel.com)']; + + yield [ + '![Welcome to Laravel](https://laravel.com/assets/img/welcome/background.svg)', + 'Hi ![Welcome to Laravel](https://laravel.com/assets/img/welcome/background.svg)', + ]; + + yield [ + 'Visit https://laravel.com/docs to browse the documentation', + 'Hi Visit https://laravel.com/docs to browse the documentation', + ]; + + yield [ + 'Visit to browse the documentation', + 'Hi Visit <https://laravel.com/docs> to browse the documentation', + ]; + + yield [ + 'Visit https://laravel.com/docs to browse the documentation', + 'Hi Visit <span>https://laravel.com/docs</span> to browse the documentation', + ]; + } } diff --git a/tests/Integration/Mail/MarkdownParserTest.php b/tests/Integration/Mail/MarkdownParserTest.php index d21602c9ad00..6669fe038ba3 100644 --- a/tests/Integration/Mail/MarkdownParserTest.php +++ b/tests/Integration/Mail/MarkdownParserTest.php @@ -24,7 +24,7 @@ public function testItCanParseMarkdownString($given, $expected) #[DataProvider('markdownEncodedDataProvider')] public function testItCanParseMarkdownEncodedString($given, $expected) { - tap(Markdown::parse($given), function ($html) use ($expected) { + tap(Markdown::parse($given, encoded: true), function ($html) use ($expected) { $this->assertInstanceOf(HtmlString::class, $html); $this->assertStringEqualsStringIgnoringLineEndings($expected.PHP_EOL, (string) $html);