Skip to content

Instantly share code, notes, and snippets.

@RyushiAok
Created October 18, 2023 15:03
Show Gist options
  • Save RyushiAok/dc3ace1a2d603c79758f86579e6954df to your computer and use it in GitHub Desktop.
Save RyushiAok/dc3ace1a2d603c79758f86579e6954df to your computer and use it in GitHub Desktop.
F# Markdown Builder
type Block =
| H1 of string
| H2 of string
| P of string
type Markdown = {
title: string
author: string
blocks: Block list
} with
static member Empty = { title = ""; author = ""; blocks = [] }
override this.ToString() =
let meta = $"---\ntitle: {this.title}\nauthor: {this.author}\n---\n"
let md =
this.blocks
|> List.map (fun b ->
match b with
| H1 s -> sprintf "# %s" s
| H2 s -> sprintf "## %s" s
| P s -> sprintf "%s" s)
|> String.concat "\n"
meta + md
type MarkdownBuilder() =
member _.Yield(_) = Markdown.Empty
[<CustomOperation("title")>]
member _.Title(md: Markdown, s: string) = { md with title = s }
[<CustomOperation("author")>]
member _.Author(md: Markdown, s: string) = { md with author = s }
[<CustomOperation("h1")>]
member _.H1(md: Markdown, s: string) = {
md with
blocks = md.blocks @ [ H1 s ]
}
[<CustomOperation("h2")>]
member _.H2(md: Markdown, s: string) = {
md with
blocks = md.blocks @ [ H2 s ]
}
[<CustomOperation("p")>]
member _.P(md: Markdown, s: string) = { md with blocks = md.blocks @ [ P s ] }
let markdown = MarkdownBuilder()
markdown {
title "Markdown DSL"
author "Aoki"
h1 "Custom Operator"
h2 "サイコーーー!!!"
p "F# |> I 💛"
}
|> fun md -> md.ToString()
|> printfn "%s"
(*
---
title: Markdown DSL
author: Aoki
---
# Custom Operator
## サイコーーー!!!
F# |> I 💛
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment