Add "title" to default `:inline_matcher` `HTMLFormatter` config

LiveView 1.1 ships with a new :inline_matcher HTMLFormatter config that defaults to ["link", "button"].

It’s a great addition that makes it much easier to tell the formatter about elements and components that should be treated as “inline” for the sake of not changing inter-element whitespace.

My proposal is to include "title" in the default list, because, having extra whitespace in the document title can have unintended side-effects. The MDN docs state that the permitted content for the title tag is “Text that is not inter-element whitespace.”

Even though browsers will handle it, some will not. For example, I just ran into a case where Discord rendered the title of a LiveView-powered website in two lines (as the preview below a message that included a link to said website).

I remember reading this thread last year Asserting `Phoenix.Component.live_title/1`, which relates to the additional whitespace affecting the document title and assertions having to work around the formatter. If this proposal would be accepted, we could write <.live_title default="My App" suffix=" · My App">{assigns[:page_title]}</.live_title> in a single line and have the formatter preserve it in a single line.

The same would apply to the non-LV <title>My App</title>.

If accepted, I am willing to contribute the a patch to both the default config and the installer templates to start off new projects with titles on a single line.

1 Like

Yeah, titles are treated as plain text. I actually only found out about this recently when I noticed that a unit test I wrote was failing to un-escape special characters (&lt; &gt;) in the title (I was parsing with Floki or something). And only after a bunch of debugging did I realize that characters in the title don’t have to be escaped and Floki was doing the right thing.

In fact, you can even do this:

<title><b>Foo bar</b><div>baz</div></title>

And it will come out literally! I have no idea how I went so long without realizing that. HTML is so weird.

1 Like

Please send a PR :slight_smile:

2 Likes

While testing changes to contribute upstream I discovered my suggestion doesn’t work as I intended:

A block element will go to the next line, while inline elements will be kept in the current line as long as they fit within the configured line length.

But

<.live_title default="My App" suffix=" · My App">{assigns[:page_title]}</.live_title>

for many values I’d like to set as default/suffix, causes the line to be longer than the default max length, thus causing the formatter to reformat into 3 lines, introducing white space in the title.

My previous version was:

<.live_title default="My App" suffix={" · My App"} phx-no-format>{assigns[:page_title]}</.live_title>

which is longer for having phx-no-format, but works as intended.

Any suggestions?

1 Like

I also tried

    <.live_title
      default="My App"
      suffix={" · My App"}
    >{assigns[:page_title]}</.live_title>

to keep all lines short, but it gets reformatted to

    <.live_title
      default="My App"
      suffix={" · My App"}
    >
      {assigns[:page_title]}
    </.live_title>

For comparison, if the full tag fits in a single line, then the formatter doesn’t introduce white space:

  <.live_title>{assigns[:page_title]}</.live_title>

It feels like phx-no-format would still be necessary to cover the usage of live_title assigns/attributes.

I wonder if the current behavior is problematic for links, buttons, and other “inline” tags?

A project I’m working on is indeed full of <.link> components that are formatted with extra inner white space just like the second code block above. In many contexts (e.g. with flexbox) the extra space is not visible, but sometimes it breaks the page design (e.g. links within longer prose) – in which case I do use phx-no-format.

1 Like