@@ -60,6 +60,12 @@ defmodule Phoenix.LiveView.HTMLFormatter do
6060 ]
6161 ```
6262
63+ * `:inline_matcher` - a list of regular expressions to determine if a component
64+ should be treated as inline.
65+ Defaults to `[~r/link/, ~r/button/]`, which treats any component with `link
66+ or `button` in its name as inline.
67+ Can be disabled by setting it to an empty list.
68+
6369 ## Formatting
6470
6571 This formatter tries to be as consistent as possible with the Elixir formatter.
@@ -214,10 +220,6 @@ defmodule Phoenix.LiveView.HTMLFormatter do
214220 mark meter noscript object output picture progress q ruby s samp select slot
215221 small span strong sub sup svg template textarea time u tt var video wbr)
216222
217- @ inline_components ~w( .link)
218-
219- @ inline_elements @ inline_tags ++ @ inline_components
220-
221223 # Default line length to be used in case nothing is specified in the `.formatter.exs` options.
222224 @ default_line_length 98
223225
@@ -235,6 +237,7 @@ defmodule Phoenix.LiveView.HTMLFormatter do
235237 else
236238 line_length = opts [ :heex_line_length ] || opts [ :line_length ] || @ default_line_length
237239 newlines = :binary . matches ( source , [ "\r \n " , "\n " ] )
240+ inline_matcher = opts [ :inline_matcher ] || [ ~r/ link/ , ~r/ button/ ]
238241
239242 opts =
240243 Keyword . update ( opts , :attribute_formatters , % { } , fn formatters ->
@@ -251,7 +254,11 @@ defmodule Phoenix.LiveView.HTMLFormatter do
251254 formatted =
252255 source
253256 |> tokenize ( )
254- |> to_tree ( [ ] , [ ] , { source , newlines } )
257+ |> to_tree ( [ ] , [ ] , % {
258+ source: { source , newlines } ,
259+ inline_elements: @ inline_tags ,
260+ inline_matcher: inline_matcher
261+ } )
255262 |> case do
256263 { :ok , nodes } ->
257264 nodes
@@ -413,88 +420,88 @@ defmodule Phoenix.LiveView.HTMLFormatter do
413420 # ]}
414421 # ]
415422 # ```
416- defp to_tree ( [ ] , buffer , [ ] , _source ) do
423+ defp to_tree ( [ ] , buffer , [ ] , _opts ) do
417424 { :ok , Enum . reverse ( buffer ) }
418425 end
419426
420- defp to_tree ( [ ] , _buffer , [ { name , _ , % { line: line , column: column } , _ } | _ ] , _source ) do
427+ defp to_tree ( [ ] , _buffer , [ { name , _ , % { line: line , column: column } , _ } | _ ] , _opts ) do
421428 message = "end of template reached without closing tag for <#{ name } >"
422429 { :error , line , column , message }
423430 end
424431
425- defp to_tree ( [ { :text , text , % { context: [ :comment_start ] } } | tokens ] , buffer , stack , source ) do
426- to_tree ( tokens , [ ] , [ { :comment , text , buffer } | stack ] , source )
432+ defp to_tree ( [ { :text , text , % { context: [ :comment_start ] } } | tokens ] , buffer , stack , opts ) do
433+ to_tree ( tokens , [ ] , [ { :comment , text , buffer } | stack ] , opts )
427434 end
428435
429436 defp to_tree (
430437 [ { :text , text , % { context: [ :comment_end | _rest ] } } | tokens ] ,
431438 buffer ,
432439 [ { :comment , start_text , upper_buffer } | stack ] ,
433- source
440+ opts
434441 ) do
435442 buffer = Enum . reverse ( [ { :text , String . trim_trailing ( text ) , % { } } | buffer ] )
436443 text = { :text , String . trim_leading ( start_text ) , % { } }
437- to_tree ( tokens , [ { :html_comment , [ text | buffer ] } | upper_buffer ] , stack , source )
444+ to_tree ( tokens , [ { :html_comment , [ text | buffer ] } | upper_buffer ] , stack , opts )
438445 end
439446
440447 defp to_tree (
441448 [ { :text , text , % { context: [ :comment_start , :comment_end ] } } | tokens ] ,
442449 buffer ,
443450 stack ,
444- source
451+ opts
445452 ) do
446453 meta = % {
447454 newlines_before_text: count_newlines_before_text ( text ) ,
448455 newlines_after_text: count_newlines_after_text ( text )
449456 }
450457
451- to_tree ( tokens , [ { :html_comment , [ { :text , String . trim ( text ) , meta } ] } | buffer ] , stack , source )
458+ to_tree ( tokens , [ { :html_comment , [ { :text , String . trim ( text ) , meta } ] } | buffer ] , stack , opts )
452459 end
453460
454- defp to_tree ( [ { :text , text , _meta } | tokens ] , buffer , stack , source ) do
461+ defp to_tree ( [ { :text , text , _meta } | tokens ] , buffer , stack , opts ) do
455462 buffer = may_set_preserve_on_block ( buffer , text )
456463
457464 if line_html_comment? ( text ) do
458- to_tree ( tokens , [ { :comment , text } | buffer ] , stack , source )
465+ to_tree ( tokens , [ { :comment , text } | buffer ] , stack , opts )
459466 else
460467 meta = % { newlines: count_newlines_before_text ( text ) }
461- to_tree ( tokens , [ { :text , text , meta } | buffer ] , stack , source )
468+ to_tree ( tokens , [ { :text , text , meta } | buffer ] , stack , opts )
462469 end
463470 end
464471
465- defp to_tree ( [ { :body_expr , value , meta } | tokens ] , buffer , stack , source ) do
472+ defp to_tree ( [ { :body_expr , value , meta } | tokens ] , buffer , stack , opts ) do
466473 buffer = set_preserve_on_block ( buffer )
467- to_tree ( tokens , [ { :body_expr , value , meta } | buffer ] , stack , source )
474+ to_tree ( tokens , [ { :body_expr , value , meta } | buffer ] , stack , opts )
468475 end
469476
470- defp to_tree ( [ { type , _name , attrs , % { closing: _ } = meta } | tokens ] , buffer , stack , source )
477+ defp to_tree ( [ { type , _name , attrs , % { closing: _ } = meta } | tokens ] , buffer , stack , opts )
471478 when is_tag_open ( type ) do
472- to_tree ( tokens , [ { :tag_self_close , meta . tag_name , attrs } | buffer ] , stack , source )
479+ to_tree ( tokens , [ { :tag_self_close , meta . tag_name , attrs } | buffer ] , stack , opts )
473480 end
474481
475- defp to_tree ( [ { type , _name , attrs , meta } | tokens ] , buffer , stack , source )
482+ defp to_tree ( [ { type , _name , attrs , meta } | tokens ] , buffer , stack , opts )
476483 when is_tag_open ( type ) do
477- to_tree ( tokens , [ ] , [ { meta . tag_name , attrs , meta , buffer } | stack ] , source )
484+ to_tree ( tokens , [ ] , [ { meta . tag_name , attrs , meta , buffer } | stack ] , opts )
478485 end
479486
480487 defp to_tree (
481488 [ { :close , _type , _name , close_meta } | tokens ] ,
482489 reversed_buffer ,
483490 [ { tag_name , attrs , open_meta , upper_buffer } | stack ] ,
484- source
491+ opts
485492 ) do
486493 { mode , block } =
487494 cond do
488495 tag_name in [ "pre" , "textarea" ] or contains_special_attrs? ( attrs ) ->
489496 content =
490- content_from_source ( source , open_meta . inner_location , close_meta . inner_location )
497+ content_from_source ( opts . source , open_meta . inner_location , close_meta . inner_location )
491498
492499 { :preserve , [ { :text , content , % { newlines: 0 } } ] }
493500
494501 preceeded_by_non_white_space? ( upper_buffer ) ->
495502 { :preserve , Enum . reverse ( reversed_buffer ) }
496503
497- tag_name in @ inline_elements ->
504+ inline? ( tag_name , opts . inline_elements , opts . inline_matcher ) ->
498505 { :inline ,
499506 reversed_buffer
500507 |> may_set_preserve_on_text ( :last )
@@ -506,66 +513,71 @@ defmodule Phoenix.LiveView.HTMLFormatter do
506513 end
507514
508515 tag_block = { :tag_block , tag_name , attrs , block , % { mode: mode } }
509- to_tree ( tokens , [ tag_block | upper_buffer ] , stack , source )
516+ to_tree ( tokens , [ tag_block | upper_buffer ] , stack , opts )
510517 end
511518
512519 # handle eex
513520
514- defp to_tree ( [ { :eex_comment , text , _meta } | tokens ] , buffer , stack , source ) do
515- to_tree ( tokens , [ { :eex_comment , text } | buffer ] , stack , source )
521+ defp to_tree ( [ { :eex_comment , text , _meta } | tokens ] , buffer , stack , opts ) do
522+ to_tree ( tokens , [ { :eex_comment , text } | buffer ] , stack , opts )
516523 end
517524
518- defp to_tree ( [ { :eex , :start_expr , expr , meta } | tokens ] , buffer , stack , source ) do
519- to_tree ( tokens , [ ] , [ { :eex_block , expr , meta , buffer } | stack ] , source )
525+ defp to_tree ( [ { :eex , :start_expr , expr , meta } | tokens ] , buffer , stack , opts ) do
526+ to_tree ( tokens , [ ] , [ { :eex_block , expr , meta , buffer } | stack ] , opts )
520527 end
521528
522529 defp to_tree (
523530 [ { :eex , :middle_expr , middle_expr , _meta } | tokens ] ,
524531 buffer ,
525532 [ { :eex_block , expr , meta , upper_buffer , middle_buffer } | stack ] ,
526- source
533+ opts
527534 ) do
528535 middle_buffer = [ { Enum . reverse ( buffer ) , middle_expr } | middle_buffer ]
529- to_tree ( tokens , [ ] , [ { :eex_block , expr , meta , upper_buffer , middle_buffer } | stack ] , source )
536+ to_tree ( tokens , [ ] , [ { :eex_block , expr , meta , upper_buffer , middle_buffer } | stack ] , opts )
530537 end
531538
532539 defp to_tree (
533540 [ { :eex , :middle_expr , middle_expr , _meta } | tokens ] ,
534541 buffer ,
535542 [ { :eex_block , expr , meta , upper_buffer } | stack ] ,
536- source
543+ opts
537544 ) do
538545 middle_buffer = [ { Enum . reverse ( buffer ) , middle_expr } ]
539- to_tree ( tokens , [ ] , [ { :eex_block , expr , meta , upper_buffer , middle_buffer } | stack ] , source )
546+ to_tree ( tokens , [ ] , [ { :eex_block , expr , meta , upper_buffer , middle_buffer } | stack ] , opts )
540547 end
541548
542549 defp to_tree (
543550 [ { :eex , :end_expr , end_expr , _meta } | tokens ] ,
544551 buffer ,
545552 [ { :eex_block , expr , meta , upper_buffer , middle_buffer } | stack ] ,
546- source
553+ opts
547554 ) do
548555 block = Enum . reverse ( [ { Enum . reverse ( buffer ) , end_expr } | middle_buffer ] )
549- to_tree ( tokens , [ { :eex_block , expr , block , meta } | upper_buffer ] , stack , source )
556+ to_tree ( tokens , [ { :eex_block , expr , block , meta } | upper_buffer ] , stack , opts )
550557 end
551558
552559 defp to_tree (
553560 [ { :eex , :end_expr , end_expr , _meta } | tokens ] ,
554561 buffer ,
555562 [ { :eex_block , expr , meta , upper_buffer } | stack ] ,
556- source
563+ opts
557564 ) do
558565 block = [ { Enum . reverse ( buffer ) , end_expr } ]
559- to_tree ( tokens , [ { :eex_block , expr , block , meta } | upper_buffer ] , stack , source )
566+ to_tree ( tokens , [ { :eex_block , expr , block , meta } | upper_buffer ] , stack , opts )
560567 end
561568
562- defp to_tree ( [ { :eex , _type , expr , meta } | tokens ] , buffer , stack , source ) do
569+ defp to_tree ( [ { :eex , _type , expr , meta } | tokens ] , buffer , stack , opts ) do
563570 buffer = set_preserve_on_block ( buffer )
564- to_tree ( tokens , [ { :eex , expr , meta } | buffer ] , stack , source )
571+ to_tree ( tokens , [ { :eex , expr , meta } | buffer ] , stack , opts )
565572 end
566573
567574 # -- HELPERS
568575
576+ defp inline? ( tag_name , inline_elements , inline_matcher ) do
577+ tag_name in inline_elements or
578+ Enum . any? ( inline_matcher , & Regex . match? ( & 1 , tag_name ) )
579+ end
580+
569581 defp count_newlines_before_text ( binary ) ,
570582 do: count_newlines_until_text ( binary , 0 , 0 , 1 )
571583
@@ -665,7 +677,11 @@ defmodule Phoenix.LiveView.HTMLFormatter do
665677 end )
666678 end
667679
668- defp content_from_source ( { source , newlines } , { line_start , column_start } , { line_end , column_end } ) do
680+ defp content_from_source (
681+ { source , newlines } ,
682+ { line_start , column_start } ,
683+ { line_end , column_end }
684+ ) do
669685 lines = Enum . slice ( [ { 0 , 0 } | newlines ] , ( line_start - 1 ) .. ( line_end - 1 ) )
670686 [ first_line | _ ] = lines
671687 [ last_line | _ ] = Enum . reverse ( lines )
0 commit comments