tailwindlabs / prettier-plugin-tailwindcss

A Prettier plugin for Tailwind CSS that automatically sorts classes based on our recommended class order.
MIT License
5.41k stars 127 forks source link

Not working in combination with @prettier/plugin-php #149

Closed MichaelvanLaar closed 1 year ago

MichaelvanLaar commented 1 year ago

What version of prettier-plugin-tailwindcss are you using?

v0.2.7

What version of Tailwind CSS are you using?

v3.3.1

What version of Node.js are you using?

v18.14.1

What package manager are you using?

npm

What operating system are you using?

Working remote via SSH. I guess my web hoster uses Debian.

Reproduction URL

https://github.com/MichaelvanLaar/bugreport-prettier-plugin-tailwindcss-in-combination-with-plugin-php

Describe your issue

When I try to use prettier-plugin-tailwindcss in PHP files (in this case, templates files of Kirby CMS) there seems to be a conflict with @prettier/plugin-php – despite using a .prettierrc file as described in the documentation.

As long as no PHP tags exist in a PHP file, everything works as it should. But as soon as typical PHP output is present (something like <?= $page->title() ?> or any other PHP code) each opening < of <?php resp <?= causes the following error: Unexpected character "EOF"

Without prettier-plugin-tailwindcss Prettier has no problem with the PHP files.

Tested with the file /site/templates/default.php in the reproduction repository.

johanguse commented 1 year ago

I'm facing the same issue. I am unable to make it work with PHP (WordPress). I am using this this boilerplate

reinink commented 1 year ago

Hey! Thanks for reporting this. You're right, HTML formatting in PHP files — including sorting of class names in that HTML — does not work when you have HTML with inline PHP. Let me do my best to explain why this is happening.

First, it's important to understand that the PHP Prettier plugin does not format HTML. It only formats PHP. Meaning if you have a PHP file with HTML and inline PHP, only the PHP in that file will get formatted by the PHP Prettier plugin. And even that isn't considered reliable, as noted in the README for that project:

Can this be used in production?

We're considering the plugin to be stable when pure PHP files are formatted. Formatting of files that contain mixed PHP and HTML is still considered unstable - please see open issues with the tag "inline" for details.

If you want to use the plugin in production, we recommend limiting its scope to pure PHP files.

With that in mind, to make the Tailwind Prettier plugin work with PHP files, we need to work with some type of AST so that we can sort the class attributes. Since the PHP Prettier plugin doesn't parse HTML as an AST, we need to rely on Prettier's internal HTML parsing instead. To do this we take each chunk of HTML (which is split wherever there is inline PHP), and then we use the Prettier HTML formatter to format that HTML.

For example, this...

<div>
  <h1><?php echo $title ?></h1>
</div>

...becomes this:

<div>
  <h1>
<?php echo $title ?>
  </h1>
</div>

And then we run the Prettier HTML formatter against the two HTML chunks individually, effectively ignoring the PHP code.

While this was a clever hack, this wasn't actually a good solution, since Prettier can't format invalid HTML code. If you were to inspect the Prettier output when trying to format these chunks of HTML, you'll see something like this:

["ERROR" - 10:34:34 AM] Error formatting document.
["ERROR" - 10:34:34 AM] Unexpected closing tag "h1". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags (1:1)

And when Prettier errors like this, nothing in the file gets formatted — including any chunks of PHP code.

This is ultimately why formatting doesn't work in PHP files that have a mix of HTML and inline PHP, but does work when there is just HTML in the PHP file. The only way it does work is if each chunk of HTML is itself valid HTML, which is pretty unlikely in a real PHP project where you're using inline PHP to echo out template variables.

So while we'd love to provide support for PHP files in the Tailwind Prettier plugin, our technique here unfortunately doesn't work, so we've decided to revert support for this in #152.

To properly solve this the PHP Prettier plugin would need to first properly support PHP files with HTML and inline PHP using an AST. However, until that exists, it's just not practical for us to try and effectively add HTML formatting support to PHP files when the official PHP Prettier plugin hasn't even been able to solve it.

Hope that makes sense!

MichaelvanLaar commented 1 year ago

Thank you for the explanation. I know the Prettier PHP plugin has some serious issues when using a mix of PHP and HTML. For the CMS templates I use it is basically unusable because it simply does nothing with the HTML.

My workaround at the time is: Open a new editor in VS Code, set the editor language to HTML and paste in the HTML/PHP mix and then use Prettier. This works most of the time. The PHP stuff is mostly ignored, and the HTML is formatted correctly. Then copy everything back to the original file.

Not a very good solution, but at least it works.

I guess I will do the same with the Tailwind CSS classes: Create an HTML document with minimal markup, but in the project, so that Prettier uses the sorting plugin. And then just copy the classes string I’m working on from the PHP file to the HTML file, sort it there, and copy it back to its original location.