dillonkearns / elm-review-html-to-elm

Turn HTML into Elm. With support for elm-tailwind-modules.

Home Page:http://html-to-elm.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nicer whitespace

dillonkearns opened this issue · comments

Right now, all the generated code is on one line. For example, this HTML input:

<!-- This example requires Tailwind CSS v2.0+ -->
<div class="bg-white">
  <div class="max-w-7xl mx-auto text-center py-12 px-4 sm:px-6 lg:py-16 lg:px-8">
    <h2 class="text-3xl font-extrabold tracking-tight text-gray-900 sm:text-4xl">
      <span class="block">Ready to dive in?</span>
      <span class="block">Start your free trial today.</span>
    </h2>
    <div class="mt-8 flex justify-center">
      <div class="inline-flex rounded-md shadow">
        <a href="#" class="inline-flex items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700">
          Get started
        </a>
      </div>
      <div class="ml-3 inline-flex">
        <a href="#" class="inline-flex items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-indigo-700 bg-indigo-100 hover:bg-indigo-200">
          Learn more
        </a>
      </div>
    </div>
  </div>
</div>

Gives this Elm output:

div [ css [ Tw.bg_white ] ] [ div [ css [ Tw.max_w_7xl, Tw.mx_auto, Tw.text_center, Tw.py_12, Tw.px_4, Bp.lg [ Tw.py_16, Tw.px_8 ], Bp.sm [ Tw.px_6 ] ] ] [ h2 [ css [ Tw.text_3xl, Tw.font_extrabold, Tw.tracking_tight, Tw.text_gray_900, Bp.sm [ Tw.text_4xl ] ] ] [ span [ css [ Tw.block ] ] [ text "Ready to dive in?" ], span [ css [ Tw.block ] ] [ text "Start your free trial today." ] ], div [ css [ Tw.mt_8, Tw.flex, Tw.justify_center ] ] [ div [ css [ Tw.inline_flex, Tw.rounded_md, Tw.shadow ] ] [ a [ Attr.href "#" ,  css [ Tw.inline_flex, Tw.items_center, Tw.justify_center, Tw.px_5, Tw.py_3, Tw.border, Tw.border_transparent, Tw.text_base, Tw.font_medium, Tw.rounded_md, Tw.text_white, Tw.bg_indigo_600, Bp.hover [ Tw.bg_indigo_700 ] ] ] [ text "Get started" ] ], div [ css [ Tw.ml_3, Tw.inline_flex ] ] [ a [ Attr.href "#" ,  css [ Tw.inline_flex, Tw.items_center, Tw.justify_center, Tw.px_5, Tw.py_3, Tw.border, Tw.border_transparent, Tw.text_base, Tw.font_medium, Tw.rounded_md, Tw.text_indigo_700, Tw.bg_indigo_100, Bp.hover [ Tw.bg_indigo_200 ] ] ] [ text "Learn more" ] ] ] ] ]

It would be more readable and usable with whitespace.

A couple of things to consider:

  • Indentation - we'll probably need to pass through the indentation level recursively as we traverse the children nodes, and increment the indentation level as we do so.
  • What's the ideal indentation? Maybe we can discuss how we would ideally format the above example in this thread here.

Some style options:

  • Attribute lists on a new line always, sometimes, or never?
  • Children list on a new line always, sometimes, or never?
  • Breakpoint/pseudoclass lists on a new line always, sometimes, or never?

And if we go with sometimes for any of those options, then what is the condition? Line length? Number of items in the list? For empty lists, it's probably a safe bet to keep things on the same line. What about for 1 item? 2?

Indentation - we'll probably need to pass through the indentation level recursively as we traverse the children nodes, and increment the indentation level as we do so.

I've got some logic for generating elm-formatted elm code string in elm-tailwind-modules. Please borrow it!

https://github.com/matheus23/elm-tailwind-modules/blob/master/src/code-generators/generate.ts

The main datatype translated into elm would be this:

type Indentable =
    Indentable ({ indentation : Int, preindent : Bool } -> String)

You need to know whether you need to prefix a piece of code with indentation or not, depending on its context. E.g. here:

x =
    [ div [] -- No indentation before `div`!
        [] -- We *do* "preindent" the list
    ]

What's the ideal indentation? Maybe we can discuss how we would ideally format the above example in this thread here.

In general I'd err on the side of more indentation.

This is the 'rule' I follow personally:

  • Always put an html element's children list on a new line, except for things like br [] [] or hr [] []
  • If the attribute list or any of the lists nested in it (e.g. the list to css) contains more than 1 element, multiline it.

The current output isn't 100% perfect, but it's quite good now! It's at the point where most people won't notice that it differs from elm-format, so I'm happy with the current state.

I'll close this for now, but I'm open to pull requests if anyone wants to tinker with whitespace in the future to make further improvements!