markmark206

markmark206

HEEX formatter (Phoenix.LiveView.HTMLFormatter / mix format) seems to introduce an unexpected line break in the generated html. User error? A bug? ; )

This looks super-related to Formatter adds space/newline to inline elements · Issue #2237 · phoenixframework/phoenix_live_view · GitHub, but, AFAICT, the fix got merged in LiveView 0.18.2, and I am seeing the problem in 0.18.3.

Details:

Here is my repro (happy to provide a more streamline repro gist, if useful):

I want to add a comma after some text

        <%= link to: ... do %>
          <%= @item.content %><% end %>,

and this works great. Here is the web page (loaded in Safari, on a Mac):
image

Running mix format, moves the <% end %> element (and, therefore, the comma that follows) to its own line:

        <%= link to: ... do %>
          <%= @item.content %>
        <% end %>,

which introduces a space before the comma:
image

I am not expecting a code formatter to change what the code does, only what the code looks like. Am I doing something obviously silly here, or does this look like a bug? ; )

Thank you!

PS A bit more data:

$ cat .formatter.exs
[
  line_length: 120,
  import_deps: [:ecto, :phoenix],
  plugins: [Phoenix.LiveView.HTMLFormatter],
  inputs: ["*.{heex,ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{heex,ex,exs}"],
  subdirectories: ["priv/*/migrations"]
]
$ cat mix.exs | grep phoenix
      {:phoenix, "~> 1.6"},
      {:phoenix_ecto, "~> 4.4"},
      {:phoenix_html, "~> 3.2"},
      {:phoenix_live_dashboard, "~> 0.7"},
      {:phoenix_live_reload, "~> 1.4", only: :dev},
      {:phoenix_live_view, "~> 0.18.3"},
$ elixir --version
Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]

Elixir 1.14.1 (compiled with Erlang/OTP 25)

Showing Posts 1 to 9

BartOtten

BartOtten

I guess this has to do with how how HTML is specced. Browsers condense multiple whitespace characters (including newlines) to a single space for most scripts (Latin for example).

Can you show us the generated HTML source? Won’t be surprised when it looks like

<a href=“http://foo.com”>content</a>
,

or

<a href=“http://foo.com”>
   content
</a>
,

W3C about whitespace

However…as this is code and not HTML I guess the formatter should recognize such and this is a bug.

zachallaun

zachallaun

In the meantime, you could do:

<%= link to: ... do %>
  <%= "#{@item.content}," %>
<% end %>
markmark206

markmark206 OP

Sure, here is what the html looks like in both cases:

$ elixir heexformat.exs
next_line: "<a href=\"/i\">\n  next line\n</a>,\n" <<<<< notice \n just before the closing </a> and ","
same_line: "<a href=\"/i\">\n  same line</a>,\n"

, where heexformat.exs is

Mix.install(
  [
    {:jason, "~> 1.4"},
    {:phoenix, "~> 1.6"},
    {:phoenix_live_view, "~> 0.18.3"}
  ],
  config: [
    phoenix: [json_library: Jason]
  ]
)

defmodule HeexFormatTest do
  use Phoenix.HTML
  import Phoenix.Component, only: [sigil_H: 2]

  def to_text(h) do
    h
    |> Phoenix.HTML.Safe.to_iodata()
    |> List.to_string()
  end

  def generate_html_next_line() do
    assigns = %{}

    ~H"""
    <%= link to: "/i", method: :get do %>
      <%= "next line" %>
    <% end %>,
    """
  end

  def generate_html_same_line() do
    assigns = %{}

    ~H"""
    <%= link to: "/i", method: :get do %>
      <%= "same line" %><% end %>,
    """
  end
end

HeexFormatTest.generate_html_next_line() |> HeexFormatTest.to_text() |> IO.inspect(label: :next_line)
HeexFormatTest.generate_html_same_line() |> HeexFormatTest.to_text() |> IO.inspect(label: :same_line)
adamu

adamu

Does anyone know how to deal with this?

For example, if I write

<a href="/foo">Foo</a>

Formatting it can result in

<a href="/foo">Foo </a>

Adding a space and changing the appearance.

This happens whether I use <a> or <.link>.

LostKobrakai

LostKobrakai

Your example formats just fine for me. But you can also use this: Phoenix.LiveView.HTMLFormatter — Phoenix LiveView v1.0.9

adamu

adamu

Sorry, I simplied it. I’ll check out the LiveView formatter, thanks.

Here’s a reproducible example:

<div>
  <div>
    <div>
      <div>
        <div>
          <div>
            <div>
              <a
                class="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                href="/foo"
              >Foo</a>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

frankdugan3

frankdugan3

Did you look at the link he posted? The documentation describes a phx-no-format attribute you can add to any element to disable formatting for that element. So in your case:

<a
  phx-no-format
  class="..."
adamu

adamu

Yes I did, and that avoids the problem. But I agree with @markmark206 - it’s surprising that the formatter adds whitespace to visible text where there was previously none. So it’s really a workaround, rather than a solution.

Out of curiosity, I checked what Prettier does, and it formats it as the following, which preserves the visible whitespace.

<a
  class="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  href="/foo"
  >Foo</a
>
— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
marciol
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
durvia
Anyone running long-lived stateful processes on BEAM? We’re building an AI agent runtime and would love to compare notes. We’re a small ...
New

Other Trending Topics Top

marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews