Skip to content

Latest commit

 

History

History
96 lines (67 loc) · 2.92 KB

Formatting-Elmish-code.md

File metadata and controls

96 lines (67 loc) · 2.92 KB

Formatting Elmish style guide

This guide explains the main reasoning of how Fantomas formats "Elmish" inspired code.

Scope

To keep things focused, the scope is currently limited to the Fable.React and Feliz bindings:

Fabulous might be covered in the future as well.

Key concepts

There are two active patterns for SynExpr that capture the shapes in the Elmish DSL.

See SourceParser:

let (|ElmishReactWithoutChildren|_|) e = ...

let (|ElmishReactWithChildren|_|) e = ...

ElmishReactWithoutChildren

Captures unary tags like <input /> or <br />. Translated in the F# DSL, they match a function that takes a single list as arguments.

let i = input [ Type "hidden" ]

The props or attributes parameter is formatted like a normal list or array would be in default Fantomas.

// short
myTag [ a1; a2 ]

// long
myTag [ a1
        a2
        a3 ]

The tag and attributes will always align.

Feliz

Translated in the Feliz DSL, tags with children also take a single list as arguments.

When fsharp_single_argument_web_mode is true, props and children have one extra indent starting from the parent tag column. The opening bracket starts right after the tag, and the closing bracket matches the start column of the tag.

let myContainer =
    Html.div [
        prop.className "container"
        prop.children [
            Html.h1 "my title"
        ]
    ]

ElmishReactWithChildren

Captures the non-unary tags like <p>...</p> or <div>...</div>. Translated in the F# DSL, they match a function that takes two lists as arguments. The first argument matches the same rules as the unary tag.

The second argument starts its opening bracket right after the closing of the attributes. The closing bracket of the children matches the start column of the tag unless the entire expression is short.

Like with fsharp_single_argument_web_mode, children have one extra indent starting from the parent tag column.

// short
let myParagraph = p [] [ str "short" ]

// long
let myContainer =
    div [ ClassName "container" ] [
        h1 [] [ str "my title" ]
    ]

When the children argument is empty, it is placed right after the attributes.

let x =
    div [ OnClick(fun _ -> printfn "meh")
          ClassName "container" ] []