g-plane / markup_fmt

Configurable HTML, Vue, Svelte, Astro, Angular, Jinja, Twig, Nunjucks and Vento formatter with dprint integration.
https://dprint.dev/plugins/markup_fmt/
MIT License
91 stars 4 forks source link

Avoid multiline opening tag for single attribute #42

Open UnknownPlatypus opened 1 month ago

UnknownPlatypus commented 1 month ago

Opening tags with a single attribute exceeding line width are wrapping but it's not really helping readability and adds a lot of vertical space (especially when nested). I added a bunch of test cases to showcase the formatting causing some churn on my work codebase (see the first commit).

-<div class="my_very_long_class_name_because_bem_or_tailwind_that_should_not_wrap_pls grey_color">
-    <div class="my_very_long_class_name_because_bem_or_tailwind_that_should_not_wrap_pls">
-        <div class="my_very_long_class_name_because_bem_or_tailwind_that_should_not_wrap_pls">
-            Deeply nested string
-        </div>
-    </div>
-</div>  
+<div
+  class="my_very_long_class_name_because_bem_or_tailwind_that_should_not_wrap_pls grey_color"
+>
+  <div
+    class="my_very_long_class_name_because_bem_or_tailwind_that_should_not_wrap_pls"
+  >
+    <div
+      class="my_very_long_class_name_because_bem_or_tailwind_that_should_not_wrap_pls"
+    >
+      Deeply nested string
+    </div>
+  </div>
+</div>

This patch try to keep an opening HTML tag with a single attribute on a single line when applicable. This was really successful for me on my work codebase (~2k html files, 250k LOC, using mostly BEM classes or tailwind classes) with over 300 files fixed with clear readability wins!

Prettier suffer from the same issue (see https://github.com/prettier/prettier/issues/10918#issuecomment-971629374) and because of that, the tailwind team (and others) are using some crazy printwidth to workaround this behavior.

It could maybe be behind a configuration flag like keepSingleAttrOnSingleLine or any other better naming you find. Let me know if I should add such flag.

g-plane commented 1 month ago

This must be behind a configuration option, but I'm not sure its naming.

UnknownPlatypus commented 1 month ago

This must be behind a configuration option, but I'm not sure its naming.

Maybe preferSingleLineOpeningTag /preferSingleLineTag because the same type of behavior could be nice for tags with no attributes at all. The flag could cover both cases.

For example, markup_fmt currently wrap tags for the following snippet with small print width and I'd like to do a followup PR to avoid that and keep the snippet unchanged.

-<html>
-  <body>
-  </body>
-</html>
+<html
+>
+  <body
+  >
+  </body
+  >
+</html
+>
UnknownPlatypus commented 1 month ago

I added a configuration option and updated the tests accordingly. I went for preferSingleLineOpeningTag for now, let me know if you want something else when you find a good naming for such option. I'll update the PR.

I set the default value to the current behavior, we could eventually do the opposite if you want to promote the new behavior.