interface Html.Internal.Server exposes [ appendRenderedStatic, initServerApp, ] imports [ Html.Internal.Shared.{ Html, Attribute, App, translateStatic, text, element }, Json, ] # ------------------------------- # STATIC HTML # ------------------------------- appendRenderedStatic : Str, Html [] -> Str appendRenderedStatic = \buffer, node -> when node is Text content -> Str.concat buffer content Element name _ attrs children -> withTagName = "\(buffer)<\(name)" withAttrs = if List.isEmpty attrs then withTagName else init = { buffer: Str.concat withTagName " ", styles: "" } { buffer: attrBuffer, styles } = List.walk attrs init appendRenderedStaticAttr if Str.isEmpty styles then attrBuffer else "\(attrBuffer) style=\"\(styles)\"" withTag = Str.concat withAttrs ">" withChildren = List.walk children withTag appendRenderedStatic "\(withChildren)" None -> buffer appendRenderedStaticAttr : { buffer : Str, styles : Str }, Attribute [] -> { buffer : Str, styles : Str } appendRenderedStaticAttr = \{ buffer, styles }, attr -> when attr is HtmlAttr key value -> newBuffer = "\(buffer) \(key)=\"\(value)\"" { buffer: newBuffer, styles } Style key value -> newStyles = "\(styles) \(key): \(value);" { buffer, styles: newStyles } DomProp _ _ -> { buffer, styles } # ------------------------------- # INITIALISATION # ------------------------------- initServerApp : App state initData, initData, Str -> Result (Html []) [InvalidDocument] | initData has Encoding initServerApp = \app, initData, hostJavaScript -> initData |> Ok |> app.init |> app.render |> translateStatic |> insertRocScript initData app.wasmUrl hostJavaScript insertRocScript : Html [], initData, Str, Str -> Result (Html []) [InvalidDocument] | initData has Encoding insertRocScript = \document, initData, wasmUrl, hostJavaScript -> encode = \value -> value |> Encode.toBytes Json.toUtf8 |> Str.fromUtf8 |> Result.withDefault "" # Convert initData to JSON as a Roc Str, then convert the Roc Str to a JS string. # JSON won't have invalid UTF-8 in it, since it would be escaped as part of JSON encoding. jsInitData = initData |> encode |> encode jsWasmUrl = encode wasmUrl script : Html [] script = (element "script") [] [ text """ \(hostJavaScript) (function(){ const initData = \(jsInitData); const wasmUrl = \(jsWasmUrl); window.roc = roc_init(initData, wasmUrl); })(); """, ] # append the