Skip to content

Instantly share code, notes, and snippets.

@kolektiv
Last active July 14, 2016 17:18
Show Gist options
  • Save kolektiv/7cf41bc701bc4be790f3ffb47e0d0650 to your computer and use it in GitHub Desktop.
Save kolektiv/7cf41bc701bc4be790f3ffb47e0d0650 to your computer and use it in GitHub Desktop.
HTML CompEx playground
// Builder
type Builder<'a> (operations: BuilderOperations<'a>) =
member __.Return _ : 'a =
operations.Init ()
member __.ReturnFrom (c: 'a) : 'a =
c
member __.Bind (m: 'a, f: unit -> 'a) : 'a =
operations.Bind (m, f)
member __.Combine (m1: 'a, m2: 'a) : 'a =
operations.Bind (m1, (fun () -> m2))
member __.Zero () : 'a =
operations.Init ()
and BuilderOperations<'a> =
{ Init: unit -> 'a
Bind: ('a * (unit -> 'a)) -> 'a }
// Types
type Body =
| Body of BodyContent list
and BodyContent =
| Div of Div
| Hr of Hr
and Div =
| Div of DivContent list
and DivContent =
| Div of Div
| Hr of Hr
and Hr =
| Hr
// HTML Builders
// Body
type BodyBuilder () =
inherit Builder<Body> {
Init = fun () -> Body []
Bind = fun (Body b, f) -> Body (b @ (f () |> function | Body b -> b)) }
// Div
type DivBuilder () =
inherit Builder<Div> {
Init = fun () -> Div.Div []
Bind = fun (Div.Div d, f) -> Div.Div (d @ (f () |> function | Div.Div d -> d)) }
// Operations
// Body
type BodyBuilder with
[<CustomOperation ("div", MaintainsVariableSpaceUsingBind = true)>]
member inline __.Div (Body b, div) : Body =
Body (b @ [ BodyContent.Div div ])
[<CustomOperation ("hr", MaintainsVariableSpaceUsingBind = true)>]
member inline __.Hr (Body b) : Body =
Body (b @ [ BodyContent.Hr Hr ])
// Div
type DivBuilder with
[<CustomOperation ("hr", MaintainsVariableSpaceUsingBind = true)>]
member inline __.Hr (Div.Div d) : Div =
Div.Div (d @ [ DivContent.Hr Hr ])
// Expressions
module Html =
// Body
let body =
BodyBuilder ()
// Div
let div =
DivBuilder ()
// Alias
module h =
Html
// Main
[<EntryPoint>]
let main _ =
let template =
h.body {
hr
div (h.div {
hr }) }
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment