diff --git a/src/Common/Common.fs b/src/Common/Common.fs
index d4c5e79..7b13f34 100644
--- a/src/Common/Common.fs
+++ b/src/Common/Common.fs
@@ -11,15 +11,16 @@ let internal toJson (pairs: (string * string) list) =
|> String.concat ", "
|> sprintf "{ %s }"
-/// Convert a boolean to lowercase true or false
+/// Convert a boolean to lowercase "true" or "false"
/// The boolean value to convert
-/// "true" for true, "false" for false
+/// "true" for true, "false" for false
let internal toLowerBool (boolValue: bool) =
(string boolValue).ToLowerInvariant()
-/// Valid values for the hx-swap attribute / HX-Reswap header
-/// May be combined with swap / settle / scroll / show config)
+/// Valid values for the hx-swap attribute / HX-Reswap header
+/// May be combined with swap / settle / scroll / show config)
+/// Documentation
[]
module HxSwap =
diff --git a/src/Htmx/Htmx.fs b/src/Htmx/Htmx.fs
index 09c1698..affa2db 100644
--- a/src/Htmx/Htmx.fs
+++ b/src/Htmx/Htmx.fs
@@ -11,7 +11,7 @@ let private hdr (headers : IHeaderDictionary) hdr =
/// Extensions to the header dictionary
type IHeaderDictionary with
- /// Indicates that the request is via an element using hx-boost
+ /// Indicates that the request is via an element using hx-boost
member this.HxBoosted
with get () = hdr this "HX-Boosted" |> Option.map bool.Parse
@@ -19,29 +19,27 @@ type IHeaderDictionary with
member this.HxCurrentUrl
with get () = hdr this "HX-Current-URL" |> Option.map Uri
- ///
- /// true if the request is for history restoration after a miss in the local history cache
- ///
+ /// true if the request is for history restoration after a miss in the local history cache
member this.HxHistoryRestoreRequest
with get () = hdr this "HX-History-Restore-Request" |> Option.map bool.Parse
- /// The user response to an hx-prompt
+ /// The user response to an hx-prompt
member this.HxPrompt
with get () = hdr this "HX-Prompt"
- /// true if the request came from htmx
+ /// true if the request came from htmx
member this.HxRequest
with get () = hdr this "HX-Request" |> Option.map bool.Parse
- /// The id attribute of the target element if it exists
+ /// The id attribute of the target element if it exists
member this.HxTarget
with get () = hdr this "HX-Target"
- /// The id attribute of the triggered element if it exists
+ /// The id attribute of the triggered element if it exists
member this.HxTrigger
with get () = hdr this "HX-Trigger"
- /// The name attribute of the triggered element if it exists
+ /// The name attribute of the triggered element if it exists
member this.HxTriggerName
with get () = hdr this "HX-Trigger-Name"
@@ -64,99 +62,111 @@ module Handlers =
open Giraffe.Htmx.Common
+ /// Instruct htmx to perform a client-side redirect for content
+ /// The path where the content should be found
+ /// An HTTP handler with the HX-Location header set
+ /// Documentation
+ let withHxLocation (path: string) : HttpHandler =
+ setHttpHeader "HX-Location" path
+
/// Pushes a new url into the history stack
/// The URL to be pushed
- /// An HTTP handler with the HX-Push-Url header set
+ /// An HTTP handler with the HX-Push-Url header set
+ /// Use to explicitly not push a new URL
+ /// Documentation
let withHxPushUrl (url: string) : HttpHandler =
setHttpHeader "HX-Push-Url" url
/// Explicitly do not push a new URL into the history stack
- /// An HTTP handler with the HX-Push-Url header set to false
+ /// An HTTP handler with the HX-Push-Url header set to false
+ /// Documentation
let withHxNoPushUrl : HttpHandler =
toLowerBool false |> withHxPushUrl
- /// Pushes a new url into the history stack
- []
- let withHxPush = withHxPushUrl
-
- /// Explicitly do not push a new URL into the history stack
- []
- let withHxNoPush = withHxNoPushUrl
-
/// Can be used to do a client-side redirect to a new location
/// The URL to which the client should be redirected
- /// An HTTP handler with the HX-Redirect header set
+ /// An HTTP handler with the HX-Redirect header set
+ /// Documentation
let withHxRedirect (url: string) : HttpHandler =
setHttpHeader "HX-Redirect" url
- /// If set to true the client side will do a full refresh of the page
+ /// If set to true the client side will do a full refresh of the page
/// Whether the client should refresh their page
- /// An HTTP handler with the HX-Refresh header set
+ /// An HTTP handler with the HX-Refresh header set
let withHxRefresh shouldRefresh : HttpHandler =
(toLowerBool >> setHttpHeader "HX-Refresh") shouldRefresh
/// Replaces the current URL in the history stack
/// The URL to place in the history stack in place of the current one
- /// An HTTP handler with the HX-Replace-URL header set
+ /// An HTTP handler with the HX-Replace-URL header set
+ /// Use to explicitly not replace the current URL
+ /// Documentation
let withHxReplaceUrl url : HttpHandler =
setHttpHeader "HX-Replace-Url" url
/// Explicitly do not replace the current URL in the history stack
- /// An HTTP handler with the HX-Replace-URL header set to false
+ /// An HTTP handler with the HX-Replace-URL header set to false
+ /// Documentation
let withHxNoReplaceUrl : HttpHandler =
toLowerBool false |> withHxReplaceUrl
/// Override which portion of the response will be swapped into the target document
/// The selector for the new response target
- /// An HTTP handler with the HX-Reselect header set
+ /// An HTTP handler with the HX-Reselect header set
let withHxReselect (target: string) : HttpHandler =
setHttpHeader "HX-Reselect" target
- /// Override the hx-swap attribute from the initiating element
+ /// Override the hx-swap attribute from the initiating element
/// The swap value to override
- /// An HTTP handler with the HX-Reswap header set
+ /// An HTTP handler with the HX-Reswap header set
/// Use HxSwap constants for best results
let withHxReswap (swap: string) : HttpHandler =
setHttpHeader "HX-Reswap" swap
- /// Allows you to override the hx-target attribute
+ /// Allows you to override the hx-target attribute
/// The new target for the response
- /// An HTTP handler with the HX-Retarget header set
+ /// An HTTP handler with the HX-Retarget header set
let withHxRetarget (target: string) : HttpHandler =
setHttpHeader "HX-Retarget" target
/// Allows you to trigger a single client side event
/// The call to the event that should be triggered
- /// An HTTP handler with the HX-Trigger header set
+ /// An HTTP handler with the HX-Trigger header set
+ /// Documentation
let withHxTrigger (evt: string) : HttpHandler =
setHttpHeader "HX-Trigger" evt
/// Allows you to trigger multiple client side events
/// The calls to events that should be triggered
- /// An HTTP handler with the HX-Trigger header set for all given events
+ /// An HTTP handler with the HX-Trigger header set for all given events
+ /// Documentation
let withHxTriggerMany evts : HttpHandler =
toJson evts |> setHttpHeader "HX-Trigger"
/// Allows you to trigger a single client side event after changes have settled
/// The call to the event that should be triggered
- /// An HTTP handler with the HX-Trigger-After-Settle header set
+ /// An HTTP handler with the HX-Trigger-After-Settle header set
+ /// Documentation
let withHxTriggerAfterSettle (evt: string) : HttpHandler =
setHttpHeader "HX-Trigger-After-Settle" evt
/// Allows you to trigger multiple client side events after changes have settled
/// The calls to events that should be triggered
- /// An HTTP handler with the HX-Trigger-After-Settle header set for all given events
+ /// An HTTP handler with the HX-Trigger-After-Settle header set for all given events
+ /// Documentation
let withHxTriggerManyAfterSettle evts : HttpHandler =
toJson evts |> setHttpHeader "HX-Trigger-After-Settle"
/// Allows you to trigger a single client side event after DOM swapping occurs
/// The call to the event that should be triggered
- /// An HTTP handler with the HX-Trigger-After-Swap header set
+ /// An HTTP handler with the HX-Trigger-After-Swap header set
+ /// Documentation
let withHxTriggerAfterSwap (evt: string) : HttpHandler =
setHttpHeader "HX-Trigger-After-Swap" evt
/// Allows you to trigger multiple client side events after DOM swapping occurs
/// The calls to events that should be triggered
- /// An HTTP handler with the HX-Trigger-After-Swap header set for all given events
+ /// An HTTP handler with the HX-Trigger-After-Swap header set for all given events
+ /// Documentation
let withHxTriggerManyAfterSwap evts : HttpHandler =
toJson evts |> setHttpHeader "HX-Trigger-After-Swap"
diff --git a/src/Tests/Htmx.fs b/src/Tests/Htmx.fs
index 5b1d162..76121e1 100644
--- a/src/Tests/Htmx.fs
+++ b/src/Tests/Htmx.fs
@@ -11,22 +11,22 @@ let dictExtensions =
testList "IHeaderDictionaryExtensions" [
testList "HxBoosted" [
test "succeeds when the header is not present" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isNone ctx.Request.Headers.HxBoosted "There should not have been a header returned"
}
test "succeeds when the header is present and true" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Boosted", "true")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Boosted", "true")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxBoosted "There should be a header present"
Expect.isTrue ctx.Request.Headers.HxBoosted.Value "The header value should have been true"
}
test "succeeds when the header is present and false" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Boosted", "false")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Boosted", "false")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxBoosted "There should be a header present"
Expect.isFalse ctx.Request.Headers.HxBoosted.Value "The header value should have been false"
@@ -34,14 +34,14 @@ let dictExtensions =
]
testList "HxCurrentUrl" [
test "succeeds when the header is not present" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isNone ctx.Request.Headers.HxCurrentUrl "There should not have been a header returned"
}
test "succeeds when the header is present" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Current-URL", "http://localhost/test.htm")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Current-URL", "http://localhost/test.htm")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxCurrentUrl "There should be a header present"
Expect.equal
@@ -51,22 +51,22 @@ let dictExtensions =
]
testList "HxHistoryRestoreRequest" [
test "succeeds when the header is not present" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isNone ctx.Request.Headers.HxHistoryRestoreRequest "There should not have been a header returned"
}
test "succeeds when the header is present and true" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-History-Restore-Request", "true")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-History-Restore-Request", "true")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxHistoryRestoreRequest "There should be a header present"
Expect.isTrue ctx.Request.Headers.HxHistoryRestoreRequest.Value "The header value should have been true"
}
test "succeeds when the header is present and false" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-History-Restore-Request", "false")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-History-Restore-Request", "false")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxHistoryRestoreRequest "There should be a header present"
Expect.isFalse
@@ -75,14 +75,14 @@ let dictExtensions =
]
testList "HxPrompt" [
test "succeeds when the header is not present" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isNone ctx.Request.Headers.HxPrompt "There should not have been a header returned"
}
test "succeeds when the header is present" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Prompt", "of course")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Prompt", "of course")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxPrompt "There should be a header present"
Expect.equal ctx.Request.Headers.HxPrompt.Value "of course" "The header value was incorrect"
@@ -90,22 +90,22 @@ let dictExtensions =
]
testList "HxRequest" [
test "succeeds when the header is not present" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isNone ctx.Request.Headers.HxRequest "There should not have been a header returned"
}
test "succeeds when the header is present and true" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "true")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Request", "true")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxRequest "There should be a header present"
Expect.isTrue ctx.Request.Headers.HxRequest.Value "The header should have been true"
}
test "succeeds when the header is present and false" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "false")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Request", "false")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxRequest "There should be a header present"
Expect.isFalse ctx.Request.Headers.HxRequest.Value "The header should have been false"
@@ -113,14 +113,14 @@ let dictExtensions =
]
testList "HxTarget" [
test "succeeds when the header is not present" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isNone ctx.Request.Headers.HxTarget "There should not have been a header returned"
}
test "succeeds when the header is present" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Target", "#leItem")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Target", "#leItem")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxTarget "There should be a header present"
Expect.equal ctx.Request.Headers.HxTarget.Value "#leItem" "The header value was incorrect"
@@ -128,14 +128,14 @@ let dictExtensions =
]
testList "HxTrigger" [
test "succeeds when the header is not present" {
- let ctx = Substitute.For ()
+ let ctx = Substitute.For()
ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
Expect.isNone ctx.Request.Headers.HxTrigger "There should not have been a header returned"
}
test "succeeds when the header is present" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Trigger", "#trig")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Trigger", "#trig")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxTrigger "There should be a header present"
Expect.equal ctx.Request.Headers.HxTrigger.Value "#trig" "The header value was incorrect"
@@ -143,14 +143,14 @@ let dictExtensions =
]
testList "HxTriggerName" [
test "succeeds when the header is not present" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isNone ctx.Request.Headers.HxTriggerName "There should not have been a header returned"
}
test "HxTriggerName succeeds when the header is present" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Trigger-Name", "click")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Trigger-Name", "click")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isSome ctx.Request.Headers.HxTriggerName "There should be a header present"
Expect.equal ctx.Request.Headers.HxTriggerName.Value "click" "The header value was incorrect"
@@ -163,36 +163,36 @@ let reqExtensions =
testList "HttpRequestExtensions" [
testList "IsHtmx" [
test "succeeds when request is not from htmx" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isFalse ctx.Request.IsHtmx "The request should not be an htmx request"
}
test "succeeds when request is from htmx" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "true")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Request", "true")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isTrue ctx.Request.IsHtmx "The request should have been an htmx request"
}
]
testList "IsHtmxRefresh" [
test "succeeds when request is not from htmx" {
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ let ctx = Substitute.For()
+ ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isFalse ctx.Request.IsHtmxRefresh "The request should not have been an htmx refresh"
}
test "succeeds when request is from htmx, but not a refresh" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "true")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Request", "true")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isFalse ctx.Request.IsHtmxRefresh "The request should not have been an htmx refresh"
}
test "IsHtmxRefresh succeeds when request is from htmx and is a refresh" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "true")
- dic.Add ("HX-History-Restore-Request", "true")
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ dic.Add("HX-Request", "true")
+ dic.Add("HX-History-Restore-Request", "true")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
Expect.isTrue ctx.Request.IsHtmxRefresh "The request should have been an htmx refresh"
}
@@ -202,30 +202,38 @@ let reqExtensions =
open System.Threading.Tasks
/// Dummy "next" parameter to get the pipeline to execute/terminate
-let next (ctx : HttpContext) = Task.FromResult (Some ctx)
+let next (ctx: HttpContext) = Task.FromResult(Some ctx)
/// Tests for the HttpHandler functions provided in the Handlers module
let handlers =
testList "HandlerTests" [
+ testTask "withHxLocation succeeds" {
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ let! _ = withHxLocation "/pagina-otro.html" next ctx
+ Expect.isTrue (dic.ContainsKey "HX-Location") "The HX-Location header should be present"
+ Expect.equal dic["HX-Location"].[0] "/pagina-otro.html" "The HX-Location value was incorrect"
+ }
testTask "withHxPushUrl succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxPushUrl "/a-new-url" next ctx
Expect.isTrue (dic.ContainsKey "HX-Push-Url") "The HX-Push-Url header should be present"
Expect.equal dic["HX-Push-Url"].[0] "/a-new-url" "The HX-Push-Url value was incorrect"
}
testTask "withHxNoPushUrl succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxNoPushUrl next ctx
Expect.isTrue (dic.ContainsKey "HX-Push-Url") "The HX-Push-Url header should be present"
Expect.equal dic["HX-Push-Url"].[0] "false" "The HX-Push-Url value was incorrect"
}
testTask "withHxRedirect succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxRedirect "/somewhere-else" next ctx
Expect.isTrue (dic.ContainsKey "HX-Redirect") "The HX-Redirect header should be present"
@@ -233,16 +241,16 @@ let handlers =
}
testList "withHxRefresh" [
testTask "succeeds when set to true" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxRefresh true next ctx
Expect.isTrue (dic.ContainsKey "HX-Refresh") "The HX-Refresh header should be present"
Expect.equal dic["HX-Refresh"].[0] "true" "The HX-Refresh value was incorrect"
}
testTask "succeeds when set to false" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxRefresh false next ctx
Expect.isTrue (dic.ContainsKey "HX-Refresh") "The HX-Refresh header should be present"
@@ -250,56 +258,56 @@ let handlers =
}
]
testTask "withHxReplaceUrl succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxReplaceUrl "/a-substitute-url" next ctx
Expect.isTrue (dic.ContainsKey "HX-Replace-Url") "The HX-Replace-Url header should be present"
Expect.equal dic["HX-Replace-Url"].[0] "/a-substitute-url" "The HX-Replace-Url value was incorrect"
}
testTask "withHxNoReplaceUrl succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxNoReplaceUrl next ctx
Expect.isTrue (dic.ContainsKey "HX-Replace-Url") "The HX-Replace-Url header should be present"
Expect.equal dic["HX-Replace-Url"].[0] "false" "The HX-Replace-Url value was incorrect"
}
testTask "withHxReselect succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxReselect "#test" next ctx
Expect.isTrue (dic.ContainsKey "HX-Reselect") "The HX-Reselect header should be present"
Expect.equal dic["HX-Reselect"].[0] "#test" "The HX-Reselect value was incorrect"
}
testTask "withHxReswap succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxReswap HxSwap.BeforeEnd next ctx
Expect.isTrue (dic.ContainsKey "HX-Reswap") "The HX-Reswap header should be present"
Expect.equal dic["HX-Reswap"].[0] HxSwap.BeforeEnd "The HX-Reswap value was incorrect"
}
testTask "withHxRetarget succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxRetarget "#somewhereElse" next ctx
Expect.isTrue (dic.ContainsKey "HX-Retarget") "The HX-Retarget header should be present"
Expect.equal dic["HX-Retarget"].[0] "#somewhereElse" "The HX-Retarget value was incorrect"
}
testTask "withHxTrigger succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxTrigger "doSomething" next ctx
Expect.isTrue (dic.ContainsKey "HX-Trigger") "The HX-Trigger header should be present"
Expect.equal dic["HX-Trigger"].[0] "doSomething" "The HX-Trigger value was incorrect"
}
testTask "withHxTriggerMany succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxTriggerMany [ "blah", "foo"; "bleh", "bar" ] next ctx
Expect.isTrue (dic.ContainsKey "HX-Trigger") "The HX-Trigger header should be present"
@@ -307,8 +315,8 @@ let handlers =
dic["HX-Trigger"].[0] """{ "blah": "foo", "bleh": "bar" }""" "The HX-Trigger value was incorrect"
}
testTask "withHxTriggerAfterSettle succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxTriggerAfterSettle "byTheWay" next ctx
Expect.isTrue
@@ -316,8 +324,8 @@ let handlers =
Expect.equal dic["HX-Trigger-After-Settle"].[0] "byTheWay" "The HX-Trigger-After-Settle value was incorrect"
}
testTask "withHxTriggerManyAfterSettle succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxTriggerManyAfterSettle [ "oof", "ouch"; "hmm", "uh" ] next ctx
Expect.isTrue
@@ -327,16 +335,16 @@ let handlers =
"The HX-Trigger-After-Settle value was incorrect"
}
testTask "withHxTriggerAfterSwap succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxTriggerAfterSwap "justASec" next ctx
Expect.isTrue (dic.ContainsKey "HX-Trigger-After-Swap") "The HX-Trigger-After-Swap header should be present"
Expect.equal dic["HX-Trigger-After-Swap"].[0] "justASec" "The HX-Trigger-After-Swap value was incorrect"
}
testTask "withHxTriggerManyAfterSwap succeeds" {
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
+ let ctx = Substitute.For()
+ let dic = HeaderDictionary()
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
let! _ = withHxTriggerManyAfterSwap [ "this", "1"; "that", "2" ] next ctx
Expect.isTrue (dic.ContainsKey "HX-Trigger-After-Swap") "The HX-Trigger-After-Swap header should be present"
diff --git a/src/Tests/ViewEngine.fs b/src/Tests/ViewEngine.fs
index 4653bbe..779b194 100644
--- a/src/Tests/ViewEngine.fs
+++ b/src/Tests/ViewEngine.fs
@@ -406,8 +406,8 @@ let hxEvent =
Expect.equal (XhrProgress.ToHxOnString()) "xhr:progress" "XhrProgress hx-on event name not correct"
}
]
-
]
+
/// Tests for the HxHeaders module
let hxHeaders =
testList "HxHeaders" [
@@ -726,7 +726,7 @@ let attributes =
|> shouldRender """"""
}
test "_hxHistory succeeds" {
- span [ _hxHistory "false" ] [] |> shouldRender """"""
+ span [ _hxHistory false ] [] |> shouldRender """"""
}
test "_hxHistoryElt succeeds" {
table [ _hxHistoryElt ] [] |> shouldRender """
"""
@@ -839,7 +839,7 @@ let renderFragment =
/// Validate that the two object references are the same object
let isSame obj1 obj2 message =
- Expect.isTrue (obj.ReferenceEquals (obj1, obj2)) message
+ Expect.isTrue (obj.ReferenceEquals(obj1, obj2)) message
testList "findIdNode" [
test "fails with a Text node" {
@@ -921,7 +921,7 @@ let renderFragment =
}
test "fails when an ID is not matched" {
Expect.equal
- (RenderFragment.AsBytes.htmlFromNodes "whiff" []) (utf8.GetBytes (nodeNotFound "whiff"))
+ (RenderFragment.AsBytes.htmlFromNodes "whiff" []) (utf8.GetBytes(nodeNotFound "whiff"))
"HTML bytes are incorrect"
}
]
@@ -938,7 +938,7 @@ let renderFragment =
}
test "fails when an ID is not matched" {
Expect.equal
- (RenderFragment.AsBytes.htmlFromNode "foo" (hr [])) (utf8.GetBytes (nodeNotFound "foo"))
+ (RenderFragment.AsBytes.htmlFromNode "foo" (hr [])) (utf8.GetBytes(nodeNotFound "foo"))
"HTML bytes are incorrect"
}
]
@@ -946,31 +946,31 @@ let renderFragment =
testList "IntoStringBuilder" [
testList "htmlFromNodes" [
test "succeeds when an ID is matched" {
- let sb = StringBuilder ()
+ let sb = StringBuilder()
RenderFragment.IntoStringBuilder.htmlFromNodes sb "find-me"
[ p [] []; p [ _id "peekaboo" ] [ str "bzz"; str "nope"; span [ _id "find-me" ] [ str ";)" ] ]]
Expect.equal (string sb) """;)""" "HTML is incorrect"
}
test "fails when an ID is not matched" {
- let sb = StringBuilder ()
+ let sb = StringBuilder()
RenderFragment.IntoStringBuilder.htmlFromNodes sb "missing" []
Expect.equal (string sb) (nodeNotFound "missing") "HTML is incorrect"
}
]
testList "htmlFromNode" [
test "succeeds when ID is matched at top level" {
- let sb = StringBuilder ()
+ let sb = StringBuilder()
RenderFragment.IntoStringBuilder.htmlFromNode sb "top" (p [ _id "top" ] [ str "pinnacle" ])
Expect.equal (string sb) """
pinnacle
""" "HTML is incorrect"
}
test "succeeds when ID is matched in child element" {
- let sb = StringBuilder ()
+ let sb = StringBuilder()
div [] [ p [] [ str "nada" ]; p [ _id "it" ] [ str "is here" ]]
|> RenderFragment.IntoStringBuilder.htmlFromNode sb "it"
Expect.equal (string sb) """
is here
""" "HTML is incorrect"
}
test "fails when an ID is not matched" {
- let sb = StringBuilder ()
+ let sb = StringBuilder()
RenderFragment.IntoStringBuilder.htmlFromNode sb "bar" (hr [])
Expect.equal (string sb) (nodeNotFound "bar") "HTML is incorrect"
}
diff --git a/src/ViewEngine.Htmx/Htmx.fs b/src/ViewEngine.Htmx/Htmx.fs
index d8784c9..5d69ca1 100644
--- a/src/ViewEngine.Htmx/Htmx.fs
+++ b/src/ViewEngine.Htmx/Htmx.fs
@@ -1,7 +1,7 @@
/// Types and functions supporting htmx attributes in Giraffe View Engine
module Giraffe.ViewEngine.Htmx
-/// Valid values for the hx-encoding attribute
+/// Valid values for the hx-encoding attribute
[]
module HxEncoding =
@@ -195,11 +195,11 @@ type HxEvent =
/// The htmx event name
override this.ToString() = fst HxEvent.Values[this]
- /// The hx-on variant of the htmx event name
+ /// The hx-on variant of the htmx event name
member this.ToHxOnString() = snd HxEvent.Values[this]
-/// Helper to create the hx-headers attribute
+/// Helper to create the hx-headers attribute
[]
module HxHeaders =
@@ -207,7 +207,8 @@ module HxHeaders =
let From = Giraffe.Htmx.Common.toJson
-/// Values / helpers for the hx-params attribute
+/// Values / helpers for the hx-params attribute
+/// Documentation
[]
module HxParams =
@@ -219,18 +220,19 @@ module HxParams =
/// Include the specified parameters
/// One or more fields to include in the request
- /// The list of fields for the hx-params attribute value
+ /// The list of fields for the hx-params attribute value
let With fields =
match fields with [] -> "" | _ -> fields |> List.reduce (fun acc it -> $"{acc},{it}")
/// Exclude the specified parameters
/// One or more fields to exclude from the request
- /// The list of fields for the hx-params attribute value prefixed with "not"
+ /// The list of fields for the hx-params attribute value prefixed with "not"
let Except fields =
With fields |> sprintf "not %s"
-/// Helpers to define hx-request attribute values
+/// Helpers to define hx-request attribute values
+/// Documentation
[]
module HxRequest =
@@ -251,21 +253,21 @@ module HxRequest =
$"\"timeout\": {ms}"
/// Include or exclude credentials from the request
- /// true if credentials should be sent, false if not
+ /// true if credentials should be sent, false if not
/// A string with the configured credential options
let Credentials send =
(toLowerBool >> sprintf "\"credentials\": %s") send
/// Exclude or include headers from the request
///
- /// true if no headers should be sent; false if headers should be sent
+ /// true if no headers should be sent; false if headers should be sent
///
/// A string with the configured header options
let NoHeaders exclude =
(toLowerBool >> sprintf "\"noHeaders\": %s") exclude
-/// Helpers for the `hx-trigger` attribute
+/// Helpers for the hx-trigger attribute
[]
module HxTrigger =
@@ -366,7 +368,8 @@ module HxTrigger =
let QueueNone = Queue "none"
-/// Helper to create the `hx-vals` attribute
+/// Helper to create the hx-vals attribute
+/// Documentation
[]
module HxVals =
@@ -374,149 +377,291 @@ module HxVals =
let From = Giraffe.Htmx.Common.toJson
+open Giraffe.Htmx
+
/// Attributes and flags for htmx
[]
module HtmxAttrs =
/// Progressively enhances anchors and forms to use AJAX requests
- /// Use _hxNoBoost to set to false
+ /// Use _hxNoBoost to set to false
+ /// Documentation
let _hxBoost = attr "hx-boost" "true"
- /// Shows a confirm() dialog before issuing a request
+ /// Shows a confirm() dialog before issuing a request
/// The prompt to present to the user when seeking their confirmation
- /// A configured hx-confirm attribute
+ /// A configured hx-confirm attribute
+ /// Documentation
let _hxConfirm prompt =
attr "hx-confirm" prompt
- /// Issues a DELETE to the specified URL
- /// The URL to which the DELETE request should be sent
- /// A configured hx-delete attribute
+ /// Issues a DELETE to the specified URL
+ /// The URL to which the DELETE request should be sent
+ /// A configured hx-delete attribute
+ /// Documentation
let _hxDelete url =
attr "hx-delete" url
/// Disables htmx processing for the given node and any children nodes
+ /// Documentation
let _hxDisable = flag "hx-disable"
/// Specifies elements that should be disabled when an htmx request is in flight
/// The element to disable when an htmx request is in flight
- /// A configured hx-disabled-elt attribute
+ /// A configured hx-disabled-elt attribute
+ /// Documentation
let _hxDisabledElt elt =
attr "hx-disabled-elt" elt
/// Disinherit all ("*") or specific htmx attributes
/// The htmx attributes to disinherit (should start with "hx-")
- /// A configured hx-disinherit attribute
+ /// A configured hx-disinherit attribute
+ /// Documentation
let _hxDisinherit hxAttrs =
attr "hx-disinherit" hxAttrs
/// Changes the request encoding type
- /// The encoding type (use HxEncoding constants)
- /// A configured hx-encoding attribute
+ /// The encoding type (use HxEncoding constants)
+ /// A configured hx-encoding attribute
+ ///
+ /// Documentation
let _hxEncoding enc =
attr "hx-encoding" enc
/// Extensions to use for this element
/// A list of extensions to apply to this element
- /// A configured hx-ext attribute
+ /// A configured hx-ext attribute
+ /// Documentation
let _hxExt exts =
attr "hx-ext" exts
- /// Issues a GET to the specified URL
- /// The URL to which the GET request should be sent
- /// A configured hx-get attribute
+ /// Issues a GET to the specified URL
+ /// The URL to which the GET request should be sent
+ /// A configured hx-get attribute
+ /// Documentation
let _hxGet url =
attr "hx-get" url
/// Adds to the headers that will be submitted with the request
- []
- let _hxHeaders = attr "hx-headers"
+ /// The headers to include with the request
+ /// A configured hx-headers attribute
+ /// Documentation
+ let _hxHeaders hdrs =
+ attr "hx-headers" hdrs
+ ///
/// Set to "false" to prevent pages with sensitive information from being stored in the history cache
- let _hxHistory = attr "hx-history"
+ ///
+ /// Whether the page should be stored in the history cache
+ /// A configured hx-history attribute
+ /// Documentation
+ let _hxHistory shouldStore =
+ attr "hx-history" (toLowerBool shouldStore)
- /// The element to snapshot and restore during history navigation
- let _hxHistoryElt = flag "hx-history-elt"
+ /// The element to snapshot and restore during history navigation
+ /// Documentation
+ let _hxHistoryElt =
+ flag "hx-history-elt"
- /// Includes additional data in AJAX requests
- let _hxInclude = attr "hx-include"
+ /// Includes additional data in AJAX requests
+ /// The specification of what should be included in the request
+ /// A configured hx-include attribute
+ /// Documentation
+ let _hxInclude spec =
+ attr "hx-include" spec
- /// The element to put the htmx-request class on during the AJAX request
- let _hxIndicator = attr "hx-indicator"
+ /// The element to put the htmx-request class on during the AJAX request
+ /// The selector for the indicator element
+ /// A configured hx-indicator attribute
+ /// Documentation
+ let _hxIndicator selector =
+ attr "hx-indicator" selector
- /// Overrides a previous `hx-boost`
- let _hxNoBoost = attr "hx-boost" "false"
+ /// Overrides a previous hx-boost (hx-boost="false")
+ /// Documentation
+ let _hxNoBoost =
+ attr "hx-boost" "false"
- /// Attach an event handler for DOM events
- let _hxOnEvent evtName =
- attr $"hx-on:%s{evtName}"
+ /// Attach an event handler for DOM events
+ /// The name of the event
+ /// The script to be executed when the event occurs
+ /// A configured hx-on attribute
+ /// Documentation
+ let _hxOnEvent evtName handler =
+ attr $"hx-on:%s{evtName}" handler
- /// Attach an event handler for htmx events
- let _hxOnHxEvent (hxEvent: HxEvent) =
- _hxOnEvent $":{hxEvent.ToHxOnString()}"
+ /// Attach an event handler for htmx events
+ /// The HxEvent to be handled
+ /// The script to be executed when the event occurs
+ /// A configured hx-on:: attribute
+ ///
+ /// Documentation
+ let _hxOnHxEvent (hxEvent: HxEvent) handler =
+ _hxOnEvent $":{hxEvent.ToHxOnString()}" handler
- /// Filters the parameters that will be submitted with a request
- let _hxParams = attr "hx-params"
+ /// Filters the parameters that will be submitted with a request
+ /// The fields to include (use HxParams to generate this value)
+ /// A configured hx-params attribute
+ ///
+ /// Documentation
+ let _hxParams toInclude =
+ attr "hx-params" toInclude
- /// Issues a PATCH to the specified URL
- let _hxPatch = attr "hx-patch"
+ /// Issues a PATCH to the specified URL
+ /// The URL to which the request should be directed
+ /// A configured hx-patch attribute
+ /// Documentation
+ let _hxPatch url =
+ attr "hx-patch" url
- /// Issues a POST to the specified URL
- let _hxPost = attr "hx-post"
+ /// Issues a POST to the specified URL
+ /// The URL to which the request should be directed
+ /// A configured hx-post attribute
+ /// Documentation
+ let _hxPost url =
+ attr "hx-post" url
- /// Preserves an element between requests
- let _hxPreserve = attr "hx-preserve" "true"
+ /// Preserves an element between requests
+ /// Documentation
+ let _hxPreserve =
+ flag "hx-preserve"
- /// Shows a prompt before submitting a request
- let _hxPrompt = attr "hx-prompt"
+ /// Shows a prompt() dialog before submitting a request
+ /// The text for the prompt
+ /// A configured hx-prompt attribute
+ /// The value provided will be in the HX-Prompt request header
+ /// Documentation
+ let _hxPrompt text =
+ attr "hx-prompt" text
- /// Pushes the URL into the location bar, creating a new history entry
- let _hxPushUrl = attr "hx-push-url"
+ /// Pushes the URL into the location bar, creating a new history entry
+ ///
+ ///
+ ///
"true" to push the fetched URL
+ ///
"false" to explicitly not push the fetched URL
+ ///
A specific URL to push
+ ///
+ ///
+ /// A configured hx-push-url attribute
+ /// Documentation
+ let _hxPushUrl spec =
+ attr "hx-push-url" spec
- /// Issues a PUT to the specified URL
- let _hxPut = attr "hx-put"
+ /// Issues a PUT to the specified URL
+ /// The URL to which the request should be directed
+ /// A configured hx-put attribute
+ /// Documentation
+ let _hxPut url =
+ attr "hx-put" url
- /// Replaces the current URL in the browser's history stack
- let _hxReplaceUrl = attr "hx-replace-url"
+ /// Replaces the current URL in the browser's history stack
+ ///
+ ///
+ ///
"true" to replace the current URL with the fetched one
+ ///
"false" to explicitly replace nothing
+ ///
A specific URL to replace in the browser's history
+ ///
+ ///
+ /// A configured hx-replace-url attribute
+ /// Documentation
+ let _hxReplaceUrl spec =
+ attr "hx-replace-url" spec
- /// Configures various aspects of the request
- let _hxRequest = attr "hx-request"
+ /// Configures various aspects of the request
+ /// The configuration spec (use HxRequest.Configure to create value)
+ /// A configured hx-request attribute
+ ///
+ /// Documentation
+ let _hxRequest spec =
+ attr "hx-request" spec
- /// Selects a subset of the server response to process
- let _hxSelect = attr "hx-select"
+ /// Selects a subset of the server response to process
+ /// A CSS selector for the content to be selected
+ /// A configured hx-select attribute
+ /// Documentation
+ let _hxSelect selector =
+ attr "hx-select" selector
- /// Selects a subset of an out-of-band server response
- let _hxSelectOob = attr "hx-select-oob"
+ /// Selects a subset of an out-of-band server response
+ /// One or more comma-delimited CSS selectors for the content to be selected
+ /// A configured hx-select-oob attribute
+ /// Documentation
+ let _hxSelectOob selectors =
+ attr "hx-select-oob" selectors
- /// Controls how the response content is swapped into the DOM (e.g. 'outerHTML' or 'beforeEnd')
- let _hxSwap = attr "hx-swap"
+ ///
+ /// Controls how the response content is swapped into the DOM (e.g. outerHTML or beforeEnd)
+ ///
+ /// The type of swap to perform (use HxSwap values)
+ /// A configured hx-swap attribute
+ /// Documentation
+ let _hxSwap swap =
+ attr "hx-swap" swap
- /// Controls how the response content is swapped into the DOM (e.g. 'outerHTML' or 'beforeEnd'), enabling CSS
- /// transitions
- let _hxSwapWithTransition = sprintf "%s transition:true" >> _hxSwap
+ ///
+ /// Controls how the response content is swapped into the DOM (e.g. outerHTML or beforeEnd), enabling
+ /// CSS transitions
+ ///
+ /// The type of swap to perform (use HxSwap values)
+ /// A configured hx-swap attribute
+ /// Documentation
+ let _hxSwapWithTransition swap =
+ _hxSwap $"%s{swap} transition:true"
+ ///
/// Marks content in a response as being "Out of Band", i.e. swapped somewhere other than the target
- let _hxSwapOob = attr "hx-swap-oob"
+ ///
+ ///
+ ///
+ ///
"true" to mark this as an OOB swap
+ ///
Any HxSwap value
+ ///
Any HxSwap value, followed by a colon (:) and a CSS selector
+ ///
+ ///
+ /// A configured hx-swap-oob attribute
+ /// Documentation
+ let _hxSwapOob swap =
+ attr "hx-swap-oob" swap
/// Synchronize events based on another element
let _hxSync = attr "hx-sync"
- /// Specifies the target element to be swapped
- let _hxTarget = attr "hx-target"
+ /// Specifies the target element to be swapped
+ /// A CSS selector or relative reference (or both) to identify the target
+ /// A configured hx-target attribute
+ /// Documentation
+ let _hxTarget selector =
+ attr "hx-target" selector
/// Specifies the event that triggers the request
let _hxTrigger = attr "hx-trigger"
- /// Validate an input element (uses HTML5 validation API)
- let _hxValidate = flag "hx-validate"
+ /// Validate an input element (uses HTML5 validation API)
+ /// Documentation
+ let _hxValidate =
+ flag "hx-validate"
- /// Adds to the parameters that will be submitted with the request
- let _hxVals = attr "hx-vals"
+ /// Adds to the parameters that will be submitted with the request
+ /// The values for the parameters (use HxVals.From to create)
+ /// A configured hx-vals attribute
+ ///
+ /// Documentation
+ let _hxVals values =
+ attr "hx-vals" values
- /// The name of the message to swap into the DOM.
- let _sseSwap = attr "sse-swap"
+ /// The URL of the SSE server
+ /// The URL from which events will be received
+ /// A configured sse-connect attribute
+ /// Extension Docs
+ let _sseConnect url =
+ attr "sse-connect" url
- /// The URL of the SSE server.
- let _sseConnect = attr "sse-connect"
+ /// The name(s) of the message(s) to swap into the DOM
+ /// The message names (comma-delimited) to swap (use "message" for unnamed events)
+ /// A configured sse-swap attribute
+ /// Extension Docs
+ let _sseSwap messages =
+ attr "sse-swap" messages
/// Script tags to pull htmx into a web page
@@ -552,9 +697,9 @@ module RenderFragment =
$"– ID {nodeId} not found –"
/// Find the node with the named ID
- /// The id attribute to find
+ /// The id attribute to find
/// The node tree to search
- /// The node with the requested id attribute, or None if it was not found
+ /// The node with the requested id attribute, or None if it was not found
let rec findIdNode nodeId (node: XmlNode) : XmlNode option =
match node with
| Text _ -> None
@@ -567,18 +712,18 @@ module RenderFragment =
module AsString =
/// Render to HTML for the given ID
- /// The id attribute for the node to be rendered
+ /// The id attribute for the node to be rendered
/// The node trees to search
- /// The HTML for the given id node, or an error message if it was not found
+ /// The HTML for the given id node, or an error message if it was not found
let htmlFromNodes nodeId (nodes: XmlNode list) =
match nodes |> List.tryPick (findIdNode nodeId) with
| Some idNode -> RenderView.AsString.htmlNode idNode
| None -> nodeNotFound nodeId
/// Render to HTML for the given ID
- /// The id attribute for the node to be rendered
+ /// The id attribute for the node to be rendered
/// The node tree to search
- /// The HTML for the given id node, or an error message if it was not found
+ /// The HTML for the given id node, or an error message if it was not found
let htmlFromNode nodeId node =
match findIdNode nodeId node with
| Some idNode -> RenderView.AsString.htmlNode idNode
@@ -591,18 +736,18 @@ module RenderFragment =
let private utf8 = System.Text.Encoding.UTF8
/// Render to bytes for the given ID
- /// The id attribute for the node to be rendered
+ /// The id attribute for the node to be rendered
/// The node trees to search
- /// The bytes for the given id node, or an error message if it was not found
+ /// The bytes for the given id node, or an error message if it was not found
let htmlFromNodes nodeId (nodes: XmlNode list) =
match nodes |> List.tryPick (findIdNode nodeId) with
| Some idNode -> RenderView.AsBytes.htmlNode idNode
| None -> nodeNotFound nodeId |> utf8.GetBytes
/// Render to bytes for the given ID
- /// The id attribute for the node to be rendered
+ /// The id attribute for the node to be rendered
/// The node tree to search
- /// The bytes for the given id node, or an error message if it was not found
+ /// The bytes for the given id node, or an error message if it was not found
let htmlFromNode nodeId node =
match findIdNode nodeId node with
| Some idNode -> RenderView.AsBytes.htmlNode idNode
@@ -612,18 +757,18 @@ module RenderFragment =
[]
module IntoStringBuilder =
- /// Render HTML into a StringBuilder for the given ID
- /// The StringBuilder into which the bytes will be rendered
- /// The id attribute for the node to be rendered
+ /// Render HTML into a StringBuilder for the given ID
+ /// The StringBuilder into which the bytes will be rendered
+ /// The id attribute for the node to be rendered
/// The node trees to search
let htmlFromNodes sb nodeId (nodes: XmlNode list) =
match nodes |> List.tryPick (findIdNode nodeId) with
| Some idNode -> RenderView.IntoStringBuilder.htmlNode sb idNode
| None -> nodeNotFound nodeId |> sb.Append |> ignore
- /// Render HTML into a StringBuilder for the given ID
- /// The StringBuilder into which the bytes will be rendered
- /// The id attribute for the node to be rendered
+ /// Render HTML into a StringBuilder for the given ID
+ /// The StringBuilder into which the bytes will be rendered
+ /// The id attribute for the node to be rendered
/// The node tree to search
let htmlFromNode sb nodeId node =
match findIdNode nodeId node with