Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP tags inside strings cause incorrect rendering of template #126

Open
SeriousKen opened this issue Dec 21, 2024 · 1 comment
Open

PHP tags inside strings cause incorrect rendering of template #126

SeriousKen opened this issue Dec 21, 2024 · 1 comment

Comments

@SeriousKen
Copy link

Volt Version

1.6.1

Laravel Version

11.36,1

PHP Version

8.3.6

Database Driver & Version

No response

Description

If the PHP opening or closing tags appear in a string in the template then the template is rendered incorrectly. This stems from a naive regex in the ExtractTemplate precompiler class on line 51

$template = trim(preg_replace('/<\?php\s*(.*?)\s*\?>/s', '', $template));

Steps To Reproduce

The following simple Volt component demonstrates the issue.

<?php
use function Livewire\Volt\{state};

state(
    title: 'Exmple of ?> causing problems',
    message: 'PHP starts with <?php and ends with ?>',
);
?>
<x-layouts.app>
    @volt
        <div>
            <h1>{{ $title }}</h1>
            <p>{{ $message }}</p>
        </div>
    @endvolt
</x-layouts.app>

There is nothing special in the layout component

<!DOCTYPE html>
<html>
    <head>
        <title>Volt App</title>
    </head>
    <body>
        {{ $slot }}
    </body>
</html>

This gives the following output (note the extract of PHP code that has been rendered as part of the template)

causing problems',
    message: 'PHP starts with ',
);
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Volt App</title>
    <!-- Livewire Styles --><style >[wire\:loading][wire\:loading], [wire\:loading\.delay][wire\:loading\.delay], [wire\:loading\.inline-block][wire\:loading\.inline-block], [wire\:loading\.inline][wire\:loading\.inline], [wire\:loading\.block][wire\:loading\.block], [wire\:loading\.flex][wire\:loading\.flex], [wire\:loading\.table][wire\:loading\.table], [wire\:loading\.grid][wire\:loading\.grid], [wire\:loading\.inline-flex][wire\:loading\.inline-flex] {display: none;}[wire\:loading\.delay\.none][wire\:loading\.delay\.none], [wire\:loading\.delay\.shortest][wire\:loading\.delay\.shortest], [wire\:loading\.delay\.shorter][wire\:loading\.delay\.shorter], [wire\:loading\.delay\.short][wire\:loading\.delay\.short], [wire\:loading\.delay\.default][wire\:loading\.delay\.default], [wire\:loading\.delay\.long][wire\:loading\.delay\.long], [wire\:loading\.delay\.longer][wire\:loading\.delay\.longer], [wire\:loading\.delay\.longest][wire\:loading\.delay\.longest] {display: none;}[wire\:offline][wire\:offline] {display: none;}[wire\:dirty]:not(textarea):not(input):not(select) {display: none;}:root {--livewire-progress-bar-color: #2299dd;}[x-cloak] {display: none !important;}</style>
</head>
    <body>
        <div wire:snapshot="{&quot;data&quot;:{&quot;title&quot;:&quot;Exmple of ?&gt; causing problems&quot;,&quot;message&quot;:&quot;PHP starts with &lt;?php and ends with ?&gt;&quot;},&quot;memo&quot;:{&quot;id&quot;:&quot;oXiRLjallSrQA1IiUhzv&quot;,&quot;name&quot;:&quot;volt-anonymous-fragment-eyJuYW1lIjoidm9sdC1hbm9ueW1vdXMtZnJhZ21lbnQtNzI1NzhjZjIzMmQ5NTQwYTkxYzkwZTIxNWI3NmVlZWMiLCJwYXRoIjoicmVzb3VyY2VzXC92aWV3c1wvcGFnZXNcL2V4YW1wbGUuYmxhZGUucGhwIn0=&quot;,&quot;path&quot;:&quot;example&quot;,&quot;method&quot;:&quot;GET&quot;,&quot;children&quot;:[],&quot;scripts&quot;:[],&quot;assets&quot;:[],&quot;errors&quot;:[],&quot;locale&quot;:&quot;en&quot;},&quot;checksum&quot;:&quot;173f579b1442267838c7d014c1a23f7073d6f0133e57bf58e11e805427d1c1b8&quot;}" wire:effects="[]" wire:id="oXiRLjallSrQA1IiUhzv">
            <h1>Exmple of ?&gt; causing problems</h1>
            <p>PHP starts with &lt;?php and ends with ?&gt;</p>
        </div>
    <!-- Livewire Scripts -->
<script src="[/livewire/livewire.js?id=02b08710](https://livewire.projects.test/livewire/livewire.js?id=02b08710)"   data-csrf="80ALUp1mlTldYlewWeaiBgmmEYC2kdNE4IY5kTxx" data-update-uri="/livewire/update" data-navigate-once="true"></script>
</body>
</html>
@SeriousKen
Copy link
Author

I think using PHP's tokenizer will fix this issue. I propose the following change to the ExtractTemplate precompiler. On first look it does indeed work, but I'd need to write some tests before submitting a pull request. Any thoughts?

    /**
     * Extract the HTML from the given template.
     */
    protected function html(string $template): string
    {
        $tokens = PhpToken::tokenize($template);

        return implode('', array_filter($tokens, fn (PhpToken $token) => $token->is(T_INLINE_HTML)));
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant