Browse Source

[F#/Oxpecker] Improved fortunes rendering (#9234)

Vladimir Shchur 11 months ago
parent
commit
8606bb835c

+ 3 - 2
frameworks/FSharp/oxpecker/src/App/App.fsproj

@@ -8,12 +8,13 @@
   <ItemGroup>
     <Compile Include="Common.fs" />
     <Compile Include="Db.fs" />
+    <Compile Include="RenderHelpers.fs" />
     <Compile Include="Program.fs" />
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Update="FSharp.Core" Version="8.0.300" />
-    <PackageReference Include="Oxpecker" Version="0.13.0" />
+    <PackageReference Update="FSharp.Core" Version="8.0.400" />
+    <PackageReference Include="Oxpecker" Version="0.14.1" />
     <PackageReference Include="Npgsql" Version="8.0.3" />
   </ItemGroup>
 </Project>

+ 26 - 24
frameworks/FSharp/oxpecker/src/App/Program.fs

@@ -7,32 +7,34 @@ open Oxpecker
 module HtmlViews =
     open Oxpecker.ViewEngine
 
-    let private fortunesHead =
-        head() {
-            title() { raw "Fortunes" }
-        }
-
-    let private layout (content: HtmlElement) =
-        html() {
-            fortunesHead
-            body() { content }
-        }
-
-    let private fortunesTableHeader =
-        tr() {
-            th() { raw "id" }
-            th() { raw "message" }
-        }
+    let private head, tail =
+        (fun (content: HtmlElement) ->
+            html() {
+                head() {
+                    title() { "Fortunes" }
+                }
+                body() {
+                    table() {
+                        tr() {
+                            th() { "id" }
+                            th() { "message" }
+                        }
+                        content
+                    }
+                }
+            } :> HtmlElement
+        ) |> RenderHelpers.prerender
 
     let fortunes (fortunesData: ResizeArray<Fortune>) =
-        table() {
-            fortunesTableHeader
-            for fortune in fortunesData do
-                tr() {
-                    td() { raw <| string fortune.id }
-                    td() { fortune.message }
-                }
-        } |> layout
+        RenderHelpers.combine head tail (
+            __() {
+                for fortune in fortunesData do
+                    tr() {
+                        td() { raw <| string fortune.id }
+                        td() { fortune.message }
+                    }
+            }
+        )
 
 [<RequireQualifiedAccess>]
 module HttpHandlers =

+ 24 - 0
frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs

@@ -0,0 +1,24 @@
+module RenderHelpers
+
+    open System.Text
+    open Oxpecker.ViewEngine
+
+    let prerender (view: HtmlElement -> HtmlElement) =
+        let sb = StringBuilder()
+        let mutable head = ""
+        let fakeHole =
+           { new HtmlElement with
+                member this.Render(sb) =
+                 head <- sb.ToString()
+                 sb.Clear() |> ignore }
+        let readyView = view fakeHole
+        readyView.Render(sb)
+        (head, sb.ToString())
+
+    let inline combine (head: string) (tail: string) (hole: HtmlElement) =
+        { new HtmlElement with
+            member this.Render(sb) =
+                sb.Append(head) |> ignore
+                hole.Render(sb)
+                sb.Append(tail) |> ignore
+        }