diff --git a/src/Common.Tests/Giraffe.Htmx.Common.Tests.fsproj b/src/Common.Tests/Giraffe.Htmx.Common.Tests.fsproj
new file mode 100644
index 0000000..58aa294
--- /dev/null
+++ b/src/Common.Tests/Giraffe.Htmx.Common.Tests.fsproj
@@ -0,0 +1,30 @@
+
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
diff --git a/src/Common.Tests/Program.fs b/src/Common.Tests/Program.fs
new file mode 100644
index 0000000..fdc31cd
--- /dev/null
+++ b/src/Common.Tests/Program.fs
@@ -0,0 +1 @@
+module Program = let [] main _ = 0
diff --git a/src/Common.Tests/Tests.fs b/src/Common.Tests/Tests.fs
new file mode 100644
index 0000000..4172698
--- /dev/null
+++ b/src/Common.Tests/Tests.fs
@@ -0,0 +1,35 @@
+module Tests
+
+open Giraffe.Htmx
+open Xunit
+
+/// Tests for the HxSwap module
+module Swap =
+
+ []
+ let ``InnerHtml is correct`` () =
+ Assert.Equal ("innerHTML", HxSwap.InnerHtml)
+
+ []
+ let ``OuterHtml is correct`` () =
+ Assert.Equal ("outerHTML", HxSwap.OuterHtml)
+
+ []
+ let ``BeforeBegin is correct`` () =
+ Assert.Equal ("beforebegin", HxSwap.BeforeBegin)
+
+ []
+ let ``BeforeEnd is correct`` () =
+ Assert.Equal ("beforeend", HxSwap.BeforeEnd)
+
+ []
+ let ``AfterBegin is correct`` () =
+ Assert.Equal ("afterbegin", HxSwap.AfterBegin)
+
+ []
+ let ``AfterEnd is correct`` () =
+ Assert.Equal ("afterend", HxSwap.AfterEnd)
+
+ []
+ let ``None is correct`` () =
+ Assert.Equal ("none", HxSwap.None)
diff --git a/src/Common/Common.fs b/src/Common/Common.fs
new file mode 100644
index 0000000..9a75b8c
--- /dev/null
+++ b/src/Common/Common.fs
@@ -0,0 +1,28 @@
+/// Common definitions shared between attribute values and response headers
+[]
+module Giraffe.Htmx.Common
+
+/// Valid values for the `hx-swap` attribute / `HX-Reswap` header (may be combined with swap/settle/scroll/show config)
+[]
+module HxSwap =
+
+ /// The default, replace the inner html of the target element
+ let InnerHtml = "innerHTML"
+
+ /// Replace the entire target element with the response
+ let OuterHtml = "outerHTML"
+
+ /// Insert the response before the target element
+ let BeforeBegin = "beforebegin"
+
+ /// Insert the response before the first child of the target element
+ let AfterBegin = "afterbegin"
+
+ /// Insert the response after the last child of the target element
+ let BeforeEnd = "beforeend"
+
+ /// Insert the response after the target element
+ let AfterEnd = "afterend"
+
+ /// Does not append content from response (out of band items will still be processed).
+ let None = "none"
diff --git a/src/Common/Giraffe.Htmx.Common.fsproj b/src/Common/Giraffe.Htmx.Common.fsproj
new file mode 100644
index 0000000..112a122
--- /dev/null
+++ b/src/Common/Giraffe.Htmx.Common.fsproj
@@ -0,0 +1,11 @@
+
+
+
+ true
+
+
+
+
+
+
+
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 560d16f..dba8c92 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -1,8 +1,9 @@
- 1.7.0
- Support new attributes/headers in htmx 1.7.0
+ net6.0
+ 1.8.0
+ Support new attributes/headers in htmx 1.8.0
danieljsummers
Bit Badger Solutions
https://github.com/bit-badger/Giraffe.Htmx
diff --git a/src/Giraffe.Htmx.sln b/src/Giraffe.Htmx.sln
new file mode 100644
index 0000000..c1ebafb
--- /dev/null
+++ b/src/Giraffe.Htmx.sln
@@ -0,0 +1,52 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Giraffe.Htmx", "Htmx\Giraffe.Htmx.fsproj", "{8AB3085C-5236-485A-8565-A09106E72E1E}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Giraffe.Htmx.Tests", "Htmx.Tests\Giraffe.Htmx.Tests.fsproj", "{D7CDD578-7A6F-4EF6-846A-80A55037E049}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Giraffe.ViewEngine.Htmx", "ViewEngine.Htmx\Giraffe.ViewEngine.Htmx.fsproj", "{F718B3C1-EE01-4F04-ABCE-BF2AE700FDA9}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Giraffe.ViewEngine.Htmx.Tests", "ViewEngine.Htmx.Tests\Giraffe.ViewEngine.Htmx.Tests.fsproj", "{F21C28CE-1F18-4CB0-B2F7-10DABE84FB78}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Giraffe.Htmx.Common", "Common\Giraffe.Htmx.Common.fsproj", "{75D66845-F93A-4463-AD29-A8B16E4D4BA9}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Giraffe.Htmx.Common.Tests", "Common.Tests\Giraffe.Htmx.Common.Tests.fsproj", "{E261A653-68D5-4D7B-99A4-F09282B50F8A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8AB3085C-5236-485A-8565-A09106E72E1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8AB3085C-5236-485A-8565-A09106E72E1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8AB3085C-5236-485A-8565-A09106E72E1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8AB3085C-5236-485A-8565-A09106E72E1E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D7CDD578-7A6F-4EF6-846A-80A55037E049}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D7CDD578-7A6F-4EF6-846A-80A55037E049}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D7CDD578-7A6F-4EF6-846A-80A55037E049}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D7CDD578-7A6F-4EF6-846A-80A55037E049}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F718B3C1-EE01-4F04-ABCE-BF2AE700FDA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F718B3C1-EE01-4F04-ABCE-BF2AE700FDA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F718B3C1-EE01-4F04-ABCE-BF2AE700FDA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F718B3C1-EE01-4F04-ABCE-BF2AE700FDA9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F21C28CE-1F18-4CB0-B2F7-10DABE84FB78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F21C28CE-1F18-4CB0-B2F7-10DABE84FB78}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F21C28CE-1F18-4CB0-B2F7-10DABE84FB78}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F21C28CE-1F18-4CB0-B2F7-10DABE84FB78}.Release|Any CPU.Build.0 = Release|Any CPU
+ {75D66845-F93A-4463-AD29-A8B16E4D4BA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {75D66845-F93A-4463-AD29-A8B16E4D4BA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {75D66845-F93A-4463-AD29-A8B16E4D4BA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {75D66845-F93A-4463-AD29-A8B16E4D4BA9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E261A653-68D5-4D7B-99A4-F09282B50F8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E261A653-68D5-4D7B-99A4-F09282B50F8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E261A653-68D5-4D7B-99A4-F09282B50F8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E261A653-68D5-4D7B-99A4-F09282B50F8A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/src/Htmx.Tests/Giraffe.Htmx.Tests.fsproj b/src/Htmx.Tests/Giraffe.Htmx.Tests.fsproj
index a9d2f4e..056f57c 100644
--- a/src/Htmx.Tests/Giraffe.Htmx.Tests.fsproj
+++ b/src/Htmx.Tests/Giraffe.Htmx.Tests.fsproj
@@ -1,8 +1,6 @@
- net6.0
-
false
false
diff --git a/src/Htmx.Tests/Tests.fs b/src/Htmx.Tests/Tests.fs
index 80fb933..213ac70 100644
--- a/src/Htmx.Tests/Tests.fs
+++ b/src/Htmx.Tests/Tests.fs
@@ -9,332 +9,364 @@ open Xunit
/// Tests for the IHeaderDictionary extension properties
module IHeaderDictionaryExtensions =
- []
- let ``HxBoosted succeeds when the header is not present`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Option.isNone ctx.Request.Headers.HxBoosted |> Assert.True
+ []
+ let ``HxBoosted succeeds when the header is not present`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Option.isNone ctx.Request.Headers.HxBoosted |> Assert.True
- []
- let ``HxBoosted succeeds when the header is present and true`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Boosted", "true")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxBoosted |> Assert.True
- Option.get ctx.Request.Headers.HxBoosted |> Assert.True
+ []
+ let ``HxBoosted succeeds when the header is present and true`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Boosted", "true")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxBoosted |> Assert.True
+ Option.get ctx.Request.Headers.HxBoosted |> Assert.True
- []
- let ``HxBoosted succeeds when the header is present and false`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Boosted", "false")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxBoosted |> Assert.True
- Option.get ctx.Request.Headers.HxBoosted |> Assert.False
+ []
+ let ``HxBoosted succeeds when the header is present and false`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Boosted", "false")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxBoosted |> Assert.True
+ Option.get ctx.Request.Headers.HxBoosted |> Assert.False
- []
- let ``HxCurrentUrl succeeds when the header is not present`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Option.isNone ctx.Request.Headers.HxCurrentUrl |> Assert.True
+ []
+ let ``HxCurrentUrl succeeds when the header is not present`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Option.isNone ctx.Request.Headers.HxCurrentUrl |> Assert.True
- []
- let ``HxCurrentUrl succeeds when the header is present`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Current-URL", "http://localhost/test.htm")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxCurrentUrl |> Assert.True
- Assert.Equal (Uri "http://localhost/test.htm", Option.get ctx.Request.Headers.HxCurrentUrl)
+ []
+ let ``HxCurrentUrl succeeds when the header is present`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Current-URL", "http://localhost/test.htm")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxCurrentUrl |> Assert.True
+ Assert.Equal (Uri "http://localhost/test.htm", Option.get ctx.Request.Headers.HxCurrentUrl)
- []
- let ``HxHistoryRestoreRequest succeeds when the header is not present`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Option.isNone ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True
+ []
+ let ``HxHistoryRestoreRequest succeeds when the header is not present`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Option.isNone ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True
- []
- let ``HxHistoryRestoreRequest succeeds when the header is present and true`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-History-Restore-Request", "true")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True
- Option.get ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True
+ []
+ let ``HxHistoryRestoreRequest succeeds when the header is present and true`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-History-Restore-Request", "true")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True
+ Option.get ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True
- []
- let ``HxHistoryRestoreRequest succeeds when the header is present and false`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-History-Restore-Request", "false")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True
- Option.get ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.False
+ []
+ let ``HxHistoryRestoreRequest succeeds when the header is present and false`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-History-Restore-Request", "false")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True
+ Option.get ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.False
- []
- let ``HxPrompt succeeds when the header is not present`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Option.isNone ctx.Request.Headers.HxPrompt |> Assert.True
+ []
+ let ``HxPrompt succeeds when the header is not present`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Option.isNone ctx.Request.Headers.HxPrompt |> Assert.True
- []
- let ``HxPrompt succeeds when the header is present`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Prompt", "of course")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxPrompt |> Assert.True
- Assert.Equal("of course", Option.get ctx.Request.Headers.HxPrompt)
+ []
+ let ``HxPrompt succeeds when the header is present`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Prompt", "of course")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxPrompt |> Assert.True
+ Assert.Equal("of course", Option.get ctx.Request.Headers.HxPrompt)
- []
- let ``HxRequest succeeds when the header is not present`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Option.isNone ctx.Request.Headers.HxRequest |> Assert.True
+ []
+ let ``HxRequest succeeds when the header is not present`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Option.isNone ctx.Request.Headers.HxRequest |> Assert.True
- []
- let ``HxRequest succeeds when the header is present and true`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "true")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxRequest |> Assert.True
- Option.get ctx.Request.Headers.HxRequest |> Assert.True
+ []
+ let ``HxRequest succeeds when the header is present and true`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Request", "true")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxRequest |> Assert.True
+ Option.get ctx.Request.Headers.HxRequest |> Assert.True
- []
- let ``HxRequest succeeds when the header is present and false`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "false")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxRequest |> Assert.True
- Option.get ctx.Request.Headers.HxRequest |> Assert.False
+ []
+ let ``HxRequest succeeds when the header is present and false`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Request", "false")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxRequest |> Assert.True
+ Option.get ctx.Request.Headers.HxRequest |> Assert.False
- []
- let ``HxTarget succeeds when the header is not present`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Option.isNone ctx.Request.Headers.HxTarget |> Assert.True
+ []
+ let ``HxTarget succeeds when the header is not present`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Option.isNone ctx.Request.Headers.HxTarget |> Assert.True
- []
- let ``HxTarget succeeds when the header is present`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Target", "#leItem")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxTarget |> Assert.True
- Assert.Equal("#leItem", Option.get ctx.Request.Headers.HxTarget)
+ []
+ let ``HxTarget succeeds when the header is present`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Target", "#leItem")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxTarget |> Assert.True
+ Assert.Equal("#leItem", Option.get ctx.Request.Headers.HxTarget)
- []
- let ``HxTrigger succeeds when the header is not present`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Option.isNone ctx.Request.Headers.HxTrigger |> Assert.True
+ []
+ let ``HxTrigger succeeds when the header is not present`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Option.isNone ctx.Request.Headers.HxTrigger |> Assert.True
- []
- let ``HxTrigger succeeds when the header is present`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Trigger", "#trig")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxTrigger |> Assert.True
- Assert.Equal("#trig", Option.get ctx.Request.Headers.HxTrigger)
+ []
+ let ``HxTrigger succeeds when the header is present`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Trigger", "#trig")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxTrigger |> Assert.True
+ Assert.Equal("#trig", Option.get ctx.Request.Headers.HxTrigger)
- []
- let ``HxTriggerName succeeds when the header is not present`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Option.isNone ctx.Request.Headers.HxTriggerName |> Assert.True
+ []
+ let ``HxTriggerName succeeds when the header is not present`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Option.isNone ctx.Request.Headers.HxTriggerName |> Assert.True
- []
- let ``HxTriggerName succeeds when the header is present`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Trigger-Name", "click")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Option.isSome ctx.Request.Headers.HxTriggerName |> Assert.True
- Assert.Equal("click", Option.get ctx.Request.Headers.HxTriggerName)
+ []
+ let ``HxTriggerName succeeds when the header is present`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Trigger-Name", "click")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Option.isSome ctx.Request.Headers.HxTriggerName |> Assert.True
+ Assert.Equal("click", Option.get ctx.Request.Headers.HxTriggerName)
/// Tests for the HttpRequest extension properties
module HttpRequestExtensions =
- []
- let ``IsHtmx succeeds when request is not from htmx`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Assert.False ctx.Request.IsHtmx
+ []
+ let ``IsHtmx succeeds when request is not from htmx`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Assert.False ctx.Request.IsHtmx
- []
- let ``IsHtmx succeeds when request is from htmx`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "true")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Assert.True ctx.Request.IsHtmx
+ []
+ let ``IsHtmx succeeds when request is from htmx`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Request", "true")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Assert.True ctx.Request.IsHtmx
- []
- let ``IsHtmxRefresh succeeds when request is not from htmx`` () =
- let ctx = Substitute.For ()
- ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
- Assert.False ctx.Request.IsHtmxRefresh
+ []
+ let ``IsHtmxRefresh succeeds when request is not from htmx`` () =
+ let ctx = Substitute.For ()
+ ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
+ Assert.False ctx.Request.IsHtmxRefresh
- []
- let ``IsHtmxRefresh succeeds when request is from htmx, but not a refresh`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- dic.Add ("HX-Request", "true")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Assert.False ctx.Request.IsHtmxRefresh
+ []
+ let ``IsHtmxRefresh succeeds when request is from htmx, but not a refresh`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ dic.Add ("HX-Request", "true")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Assert.False ctx.Request.IsHtmxRefresh
- []
- let ``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")
- ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
- Assert.True ctx.Request.IsHtmxRefresh
+ []
+ let ``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")
+ ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
+ Assert.True ctx.Request.IsHtmxRefresh
/// Tests for the HttpHandler functions provided in the Handlers module
module HandlerTests =
- open System.Threading.Tasks
-
- /// Dummy "next" parameter to get the pipeline to execute/terminate
- let next (ctx : HttpContext) = Task.FromResult (Some ctx)
-
- []
- let ``withHxPush succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxPush "/a-new-url" next ctx
- Assert.True (dic.ContainsKey "HX-Push")
- Assert.Equal ("/a-new-url", dic.["HX-Push"].[0])
- }
-
- []
- let ``withHxNoPush succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxNoPush next ctx
- Assert.True (dic.ContainsKey "HX-Push")
- Assert.Equal ("false", dic.["HX-Push"].[0])
- }
-
- []
- let ``withHxRedirect succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxRedirect "/somewhere-else" next ctx
- Assert.True (dic.ContainsKey "HX-Redirect")
- Assert.Equal ("/somewhere-else", dic.["HX-Redirect"].[0])
- }
-
- []
- let ``withHxRefresh succeeds when set to true`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxRefresh true next ctx
- Assert.True (dic.ContainsKey "HX-Refresh")
- Assert.Equal ("true", dic.["HX-Refresh"].[0])
- }
-
- []
- let ``withHxRefresh succeeds when set to false`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxRefresh false next ctx
- Assert.True (dic.ContainsKey "HX-Refresh")
- Assert.Equal ("false", dic.["HX-Refresh"].[0])
- }
-
- []
- let ``withHxRetarget succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxRetarget "#somewhereElse" next ctx
- Assert.True (dic.ContainsKey "HX-Retarget")
- Assert.Equal ("#somewhereElse", dic.["HX-Retarget"].[0])
- }
+ open System.Threading.Tasks
- []
- let ``withHxTrigger succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxTrigger "doSomething" next ctx
- Assert.True (dic.ContainsKey "HX-Trigger")
- Assert.Equal ("doSomething", dic.["HX-Trigger"].[0])
- }
+ /// Dummy "next" parameter to get the pipeline to execute/terminate
+ let next (ctx : HttpContext) = Task.FromResult (Some ctx)
+
+ []
+ let ``withHxPushUrl succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxPushUrl "/a-new-url" next ctx
+ Assert.True (dic.ContainsKey "HX-Push-Url")
+ Assert.Equal ("/a-new-url", dic["HX-Push-Url"][0])
+ }
- []
- let ``withHxTriggerMany succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxTriggerMany [ "blah", "foo"; "bleh", "bar" ] next ctx
- Assert.True (dic.ContainsKey "HX-Trigger")
- Assert.Equal ("""{ "blah": "foo", "bleh": "bar" }""", dic.["HX-Trigger"].[0])
- }
+ []
+ let ``withHxNoPushUrl succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxNoPushUrl next ctx
+ Assert.True (dic.ContainsKey "HX-Push-Url")
+ Assert.Equal ("false", dic["HX-Push-Url"][0])
+ }
- []
- let ``withHxTriggerAfterSettle succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxTriggerAfterSettle "byTheWay" next ctx
- Assert.True (dic.ContainsKey "HX-Trigger-After-Settle")
- Assert.Equal ("byTheWay", dic.["HX-Trigger-After-Settle"].[0])
- }
+ []
+ let ``withHxRedirect succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxRedirect "/somewhere-else" next ctx
+ Assert.True (dic.ContainsKey "HX-Redirect")
+ Assert.Equal ("/somewhere-else", dic["HX-Redirect"][0])
+ }
- []
- let ``withHxTriggerManyAfterSettle succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxTriggerManyAfterSettle [ "oof", "ouch"; "hmm", "uh" ] next ctx
- Assert.True (dic.ContainsKey "HX-Trigger-After-Settle")
- Assert.Equal ("""{ "oof": "ouch", "hmm": "uh" }""", dic.["HX-Trigger-After-Settle"].[0])
- }
+ []
+ let ``withHxRefresh succeeds when set to true`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxRefresh true next ctx
+ Assert.True (dic.ContainsKey "HX-Refresh")
+ Assert.Equal ("true", dic["HX-Refresh"][0])
+ }
- []
- let ``withHxTriggerAfterSwap succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxTriggerAfterSwap "justASec" next ctx
- Assert.True (dic.ContainsKey "HX-Trigger-After-Swap")
- Assert.Equal ("justASec", dic.["HX-Trigger-After-Swap"].[0])
- }
+ []
+ let ``withHxRefresh succeeds when set to false`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxRefresh false next ctx
+ Assert.True (dic.ContainsKey "HX-Refresh")
+ Assert.Equal ("false", dic["HX-Refresh"][0])
+ }
- []
- let ``withHxTriggerManyAfterSwap succeeds`` () =
- let ctx = Substitute.For ()
- let dic = HeaderDictionary ()
- ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
- task {
- let! _ = withHxTriggerManyAfterSwap [ "this", "1"; "that", "2" ] next ctx
- Assert.True (dic.ContainsKey "HX-Trigger-After-Swap")
- Assert.Equal ("""{ "this": "1", "that": "2" }""", dic.["HX-Trigger-After-Swap"].[0])
- }
+ []
+ let ``withHxReplaceUrl succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxReplaceUrl "/a-substitute-url" next ctx
+ Assert.True (dic.ContainsKey "HX-Replace-Url")
+ Assert.Equal ("/a-substitute-url", dic["HX-Replace-Url"][0])
+ }
+ []
+ let ``withHxNoReplaceUrl succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxNoReplaceUrl next ctx
+ Assert.True (dic.ContainsKey "HX-Replace-Url")
+ Assert.Equal ("false", dic["HX-Replace-Url"][0])
+ }
+
+ []
+ let ``withHxReswap succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxReswap HxSwap.BeforeEnd next ctx
+ Assert.True (dic.ContainsKey "HX-Reswap")
+ Assert.Equal (HxSwap.BeforeEnd, dic["HX-Reswap"][0])
+ }
+
+ []
+ let ``withHxRetarget succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxRetarget "#somewhereElse" next ctx
+ Assert.True (dic.ContainsKey "HX-Retarget")
+ Assert.Equal ("#somewhereElse", dic["HX-Retarget"][0])
+ }
+
+ []
+ let ``withHxTrigger succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxTrigger "doSomething" next ctx
+ Assert.True (dic.ContainsKey "HX-Trigger")
+ Assert.Equal ("doSomething", dic["HX-Trigger"][0])
+ }
+
+ []
+ let ``withHxTriggerMany succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxTriggerMany [ "blah", "foo"; "bleh", "bar" ] next ctx
+ Assert.True (dic.ContainsKey "HX-Trigger")
+ Assert.Equal ("""{ "blah": "foo", "bleh": "bar" }""", dic["HX-Trigger"][0])
+ }
+
+ []
+ let ``withHxTriggerAfterSettle succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxTriggerAfterSettle "byTheWay" next ctx
+ Assert.True (dic.ContainsKey "HX-Trigger-After-Settle")
+ Assert.Equal ("byTheWay", dic["HX-Trigger-After-Settle"][0])
+ }
+
+ []
+ let ``withHxTriggerManyAfterSettle succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxTriggerManyAfterSettle [ "oof", "ouch"; "hmm", "uh" ] next ctx
+ Assert.True (dic.ContainsKey "HX-Trigger-After-Settle")
+ Assert.Equal ("""{ "oof": "ouch", "hmm": "uh" }""", dic["HX-Trigger-After-Settle"][0])
+ }
+
+ []
+ let ``withHxTriggerAfterSwap succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxTriggerAfterSwap "justASec" next ctx
+ Assert.True (dic.ContainsKey "HX-Trigger-After-Swap")
+ Assert.Equal ("justASec", dic["HX-Trigger-After-Swap"][0])
+ }
+
+ []
+ let ``withHxTriggerManyAfterSwap succeeds`` () =
+ let ctx = Substitute.For ()
+ let dic = HeaderDictionary ()
+ ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
+ task {
+ let! _ = withHxTriggerManyAfterSwap [ "this", "1"; "that", "2" ] next ctx
+ Assert.True (dic.ContainsKey "HX-Trigger-After-Swap")
+ Assert.Equal ("""{ "this": "1", "that": "2" }""", dic["HX-Trigger-After-Swap"][0])
+ }
diff --git a/src/Htmx/Giraffe.Htmx.fsproj b/src/Htmx/Giraffe.Htmx.fsproj
index 6063798..09928ad 100644
--- a/src/Htmx/Giraffe.Htmx.fsproj
+++ b/src/Htmx/Giraffe.Htmx.fsproj
@@ -1,7 +1,6 @@
- net6.0
true
htmx header extensions and helpers for Giraffe
README.md
@@ -16,4 +15,8 @@
+
+
+
+
diff --git a/src/Htmx/Htmx.fs b/src/Htmx/Htmx.fs
index 51489a5..ff7f1e0 100644
--- a/src/Htmx/Htmx.fs
+++ b/src/Htmx/Htmx.fs
@@ -6,102 +6,122 @@ open System
/// Determine if the given header is present
let private hdr (headers : IHeaderDictionary) hdr =
- match headers.[hdr] with it when it = StringValues.Empty -> None | it -> Some it.[0]
+ match headers[hdr] with it when it = StringValues.Empty -> None | it -> Some it[0]
/// Extensions to the header dictionary
type IHeaderDictionary with
- /// Indicates that the request is via an element using `hx-boost`
- member this.HxBoosted with get () = hdr this "HX-Boosted" |> Option.map bool.Parse
-
- /// The current URL of the browser _(note that this does not update until after settle)_
- 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
- member this.HxHistoryRestoreRequest with get () = hdr this "HX-History-Restore-Request" |> Option.map bool.Parse
-
- /// The user response to an `hx-prompt`
- member this.HxPrompt with get () = hdr this "HX-Prompt"
+ /// Indicates that the request is via an element using `hx-boost`
+ member this.HxBoosted with get () = hdr this "HX-Boosted" |> Option.map bool.Parse
+
+ /// The current URL of the browser _(note that this does not update until after settle)_
+ 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
+ member this.HxHistoryRestoreRequest with get () = hdr this "HX-History-Restore-Request" |> Option.map bool.Parse
+
+ /// The user response to an `hx-prompt`
+ member this.HxPrompt with get () = hdr this "HX-Prompt"
- /// `true` if the request came from HTMX
- member this.HxRequest with get () = hdr this "HX-Request" |> Option.map bool.Parse
+ /// `true` if the request came from HTMX
+ member this.HxRequest with get () = hdr this "HX-Request" |> Option.map bool.Parse
- /// The `id` of the target element if it exists
- member this.HxTarget with get () = hdr this "HX-Target"
+ /// The `id` of the target element if it exists
+ member this.HxTarget with get () = hdr this "HX-Target"
- /// The `id` of the triggered element if it exists
- member this.HxTrigger with get () = hdr this "HX-Trigger"
+ /// The `id` of the triggered element if it exists
+ member this.HxTrigger with get () = hdr this "HX-Trigger"
- /// The `name` of the triggered element if it exists
- member this.HxTriggerName with get () = hdr this "HX-Trigger-Name"
+ /// The `name` of the triggered element if it exists
+ member this.HxTriggerName with get () = hdr this "HX-Trigger-Name"
/// Extensions for the request object
type HttpRequest with
- /// Whether this request was initiated from htmx
- member this.IsHtmx with get () = this.Headers.HxRequest |> Option.defaultValue false
+ /// Whether this request was initiated from htmx
+ member this.IsHtmx with get () = this.Headers.HxRequest |> Option.defaultValue false
- /// Whether this request is an htmx history-miss refresh request
- member this.IsHtmxRefresh with get () =
- this.IsHtmx && (this.Headers.HxHistoryRestoreRequest |> Option.defaultValue false)
+ /// Whether this request is an htmx history-miss refresh request
+ member this.IsHtmxRefresh with get () =
+ this.IsHtmx && (this.Headers.HxHistoryRestoreRequest |> Option.defaultValue false)
/// HTTP handlers for setting output headers
[]
module Handlers =
- /// Convert a boolean to lowercase `true` or `false`
- let private toLowerBool (trueOrFalse : bool) =
- (string trueOrFalse).ToLowerInvariant ()
+ /// Convert a boolean to lowercase `true` or `false`
+ let private toLowerBool (trueOrFalse : bool) =
+ (string trueOrFalse).ToLowerInvariant ()
- /// Serialize a list of key/value pairs to JSON (very rudimentary)
- let private toJson (evts : (string * string) list) =
- evts
- |> List.map (fun evt -> sprintf "\"%s\": \"%s\"" (fst evt) ((snd evt).Replace ("\"", "\\\"")))
- |> String.concat ", "
- |> sprintf "{ %s }"
+ /// Serialize a list of key/value pairs to JSON (very rudimentary)
+ let private toJson (evts : (string * string) list) =
+ evts
+ |> List.map (fun evt -> sprintf "\"%s\": \"%s\"" (fst evt) ((snd evt).Replace ("\"", "\\\"")))
+ |> String.concat ", "
+ |> sprintf "{ %s }"
- // Pushes a new url into the history stack
- let withHxPush : string -> HttpHandler =
- setHttpHeader "HX-Push"
+ /// Pushes a new url into the history stack
+ let withHxPushUrl : string -> HttpHandler =
+ setHttpHeader "HX-Push-Url"
- // Explicitly do not push a new URL into the history stack
- let withHxNoPush : HttpHandler =
- toLowerBool false |> withHxPush
+ /// Explicitly do not push a new URL into the history stack
+ let withHxNoPushUrl : HttpHandler =
+ toLowerBool false |> withHxPushUrl
+
+ /// Pushes a new url into the history stack
+ []
+ let withHxPush = withHxPushUrl
- /// Can be used to do a client-side redirect to a new location
- let withHxRedirect : string -> HttpHandler =
- setHttpHeader "HX-Redirect"
+ /// 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
+ let withHxRedirect : string -> HttpHandler =
+ setHttpHeader "HX-Redirect"
- /// If set to `true` the client side will do a a full refresh of the page
- let withHxRefresh : bool -> HttpHandler =
- toLowerBool >> setHttpHeader "HX-Refresh"
+ /// If set to `true` the client side will do a a full refresh of the page
+ let withHxRefresh : bool -> HttpHandler =
+ toLowerBool >> setHttpHeader "HX-Refresh"
- /// Allows you to override the `hx-target` attribute
- let withHxRetarget : string -> HttpHandler =
- setHttpHeader "HX-Retarget"
+ /// Replaces the current URL in the history stack
+ let withHxReplaceUrl : string -> HttpHandler =
+ setHttpHeader "HX-Replace-Url"
- /// Allows you to trigger a single client side event
- let withHxTrigger : string -> HttpHandler =
- setHttpHeader "HX-Trigger"
+ /// Explicitly do not replace the current URL in the history stack
+ let withHxNoReplaceUrl : HttpHandler =
+ toLowerBool false |> withHxReplaceUrl
+
+ /// Override the `hx-swap` attribute from the initiating element
+ let withHxReswap : string -> HttpHandler =
+ setHttpHeader "HX-Reswap"
- /// Allows you to trigger multiple client side events
- let withHxTriggerMany evts : HttpHandler =
- toJson evts |> setHttpHeader "HX-Trigger"
+ /// Allows you to override the `hx-target` attribute
+ let withHxRetarget : string -> HttpHandler =
+ setHttpHeader "HX-Retarget"
- /// Allows you to trigger a single client side event after changes have settled
- let withHxTriggerAfterSettle : string -> HttpHandler =
- setHttpHeader "HX-Trigger-After-Settle"
+ /// Allows you to trigger a single client side event
+ let withHxTrigger : string -> HttpHandler =
+ setHttpHeader "HX-Trigger"
- /// Allows you to trigger multiple client side events after changes have settled
- let withHxTriggerManyAfterSettle evts : HttpHandler =
- toJson evts |> setHttpHeader "HX-Trigger-After-Settle"
+ /// Allows you to trigger multiple client side events
+ let withHxTriggerMany evts : HttpHandler =
+ toJson evts |> setHttpHeader "HX-Trigger"
- /// Allows you to trigger a single client side event after DOM swapping occurs
- let withHxTriggerAfterSwap : string -> HttpHandler =
- setHttpHeader "HX-Trigger-After-Swap"
+ /// Allows you to trigger a single client side event after changes have settled
+ let withHxTriggerAfterSettle : string -> HttpHandler =
+ setHttpHeader "HX-Trigger-After-Settle"
- /// Allows you to trigger multiple client side events after DOM swapping occurs
- let withHxTriggerManyAfterSwap evts : HttpHandler =
- toJson evts |> setHttpHeader "HX-Trigger-After-Swap"
+ /// Allows you to trigger multiple client side events after changes have settled
+ let withHxTriggerManyAfterSettle evts : HttpHandler =
+ toJson evts |> setHttpHeader "HX-Trigger-After-Settle"
+
+ /// Allows you to trigger a single client side event after DOM swapping occurs
+ let withHxTriggerAfterSwap : string -> HttpHandler =
+ setHttpHeader "HX-Trigger-After-Swap"
+
+ /// Allows you to trigger multiple client side events after DOM swapping occurs
+ let withHxTriggerManyAfterSwap evts : HttpHandler =
+ toJson evts |> setHttpHeader "HX-Trigger-After-Swap"
diff --git a/src/ViewEngine.Htmx.Tests/Giraffe.ViewEngine.Htmx.Tests.fsproj b/src/ViewEngine.Htmx.Tests/Giraffe.ViewEngine.Htmx.Tests.fsproj
index 2d275f3..9d9d736 100644
--- a/src/ViewEngine.Htmx.Tests/Giraffe.ViewEngine.Htmx.Tests.fsproj
+++ b/src/ViewEngine.Htmx.Tests/Giraffe.ViewEngine.Htmx.Tests.fsproj
@@ -1,8 +1,6 @@
- net6.0
-
false
false
diff --git a/src/ViewEngine.Htmx.Tests/Tests.fs b/src/ViewEngine.Htmx.Tests/Tests.fs
index 86ed2cf..c9a4a5b 100644
--- a/src/ViewEngine.Htmx.Tests/Tests.fs
+++ b/src/ViewEngine.Htmx.Tests/Tests.fs
@@ -5,463 +5,441 @@ open Xunit
/// Tests for the HxEncoding module
module Encoding =
-
- []
- let ``Form is correct`` () =
- Assert.Equal ("application/x-www-form-urlencoded", HxEncoding.Form)
-
- []
- let ``MultipartForm is correct`` () =
- Assert.Equal ("multipart/form-data", HxEncoding.MultipartForm)
+
+ []
+ let ``Form is correct`` () =
+ Assert.Equal ("application/x-www-form-urlencoded", HxEncoding.Form)
+
+ []
+ let ``MultipartForm is correct`` () =
+ Assert.Equal ("multipart/form-data", HxEncoding.MultipartForm)
/// Tests for the HxHeaders module
module Headers =
-
- []
- let ``From succeeds with an empty list`` () =
- Assert.Equal ("{ }", HxHeaders.From [])
-
- []
- let ``From succeeds and escapes quotes`` () =
- Assert.Equal ("{ \"test\": \"one two three\", \"again\": \"four \\\"five\\\" six\" }",
- HxHeaders.From [ "test", "one two three"; "again", "four \"five\" six" ])
+
+ []
+ let ``From succeeds with an empty list`` () =
+ Assert.Equal ("{ }", HxHeaders.From [])
+
+ []
+ let ``From succeeds and escapes quotes`` () =
+ Assert.Equal ("{ \"test\": \"one two three\", \"again\": \"four \\\"five\\\" six\" }",
+ HxHeaders.From [ "test", "one two three"; "again", "four \"five\" six" ])
/// Tests for the HxParams module
module Params =
-
- []
- let ``All is correct`` () =
- Assert.Equal ("*", HxParams.All)
-
- []
- let ``None is correct`` () =
- Assert.Equal ("none", HxParams.None)
- []
- let ``With succeeds with empty list`` () =
- Assert.Equal ("", HxParams.With [])
-
- []
- let ``With succeeds with one list item`` () =
- Assert.Equal ("boo", HxParams.With [ "boo" ])
-
- []
- let ``With succeeds with multiple list items`` () =
- Assert.Equal ("foo,bar,baz", HxParams.With [ "foo"; "bar"; "baz" ])
+ []
+ let ``All is correct`` () =
+ Assert.Equal ("*", HxParams.All)
- []
- let ``Except succeeds with empty list`` () =
- Assert.Equal ("not ", HxParams.Except [])
-
- []
- let ``Except succeeds with one list item`` () =
- Assert.Equal ("not that", HxParams.Except [ "that" ])
-
- []
- let ``Except succeeds with multiple list items`` () =
- Assert.Equal ("not blue,green", HxParams.Except [ "blue"; "green" ])
+ []
+ let ``None is correct`` () =
+ Assert.Equal ("none", HxParams.None)
+
+ []
+ let ``With succeeds with empty list`` () =
+ Assert.Equal ("", HxParams.With [])
+
+ []
+ let ``With succeeds with one list item`` () =
+ Assert.Equal ("boo", HxParams.With [ "boo" ])
+
+ []
+ let ``With succeeds with multiple list items`` () =
+ Assert.Equal ("foo,bar,baz", HxParams.With [ "foo"; "bar"; "baz" ])
+
+ []
+ let ``Except succeeds with empty list`` () =
+ Assert.Equal ("not ", HxParams.Except [])
+
+ []
+ let ``Except succeeds with one list item`` () =
+ Assert.Equal ("not that", HxParams.Except [ "that" ])
+
+ []
+ let ``Except succeeds with multiple list items`` () =
+ Assert.Equal ("not blue,green", HxParams.Except [ "blue"; "green" ])
/// Tests for the HxRequest module
module Request =
-
- []
- let ``Configure succeeds with an empty list`` () =
- Assert.Equal ("{ }", HxRequest.Configure [])
-
- []
- let ``Configure succeeds with a non-empty list`` () =
- Assert.Equal ("{ \"a\": \"b\", \"c\": \"d\" }", HxRequest.Configure [ "\"a\": \"b\""; "\"c\": \"d\"" ])
-
- []
- let ``Configure succeeds with all known params configured`` () =
- Assert.Equal ("{ \"timeout\": 1000, \"credentials\": false, \"noHeaders\": true }",
- HxRequest.Configure [ HxRequest.Timeout 1000; HxRequest.Credentials false; HxRequest.NoHeaders true ])
-
- []
- let ``Timeout succeeds`` () =
- Assert.Equal ("\"timeout\": 50", HxRequest.Timeout 50)
-
- []
- let ``Credentials succeeds when set to true`` () =
- Assert.Equal ("\"credentials\": true", HxRequest.Credentials true)
-
- []
- let ``Credentials succeeds when set to false`` () =
- Assert.Equal ("\"credentials\": false", HxRequest.Credentials false)
-
- []
- let ``NoHeaders succeeds when set to true`` () =
- Assert.Equal ("\"noHeaders\": true", HxRequest.NoHeaders true)
-
- []
- let ``NoHeaders succeeds when set to false`` () =
- Assert.Equal ("\"noHeaders\": false", HxRequest.NoHeaders false)
+
+ []
+ let ``Configure succeeds with an empty list`` () =
+ Assert.Equal ("{ }", HxRequest.Configure [])
+
+ []
+ let ``Configure succeeds with a non-empty list`` () =
+ Assert.Equal ("{ \"a\": \"b\", \"c\": \"d\" }", HxRequest.Configure [ "\"a\": \"b\""; "\"c\": \"d\"" ])
+
+ []
+ let ``Configure succeeds with all known params configured`` () =
+ Assert.Equal ("{ \"timeout\": 1000, \"credentials\": false, \"noHeaders\": true }",
+ HxRequest.Configure [ HxRequest.Timeout 1000; HxRequest.Credentials false; HxRequest.NoHeaders true ])
+
+ []
+ let ``Timeout succeeds`` () =
+ Assert.Equal ("\"timeout\": 50", HxRequest.Timeout 50)
+
+ []
+ let ``Credentials succeeds when set to true`` () =
+ Assert.Equal ("\"credentials\": true", HxRequest.Credentials true)
+
+ []
+ let ``Credentials succeeds when set to false`` () =
+ Assert.Equal ("\"credentials\": false", HxRequest.Credentials false)
+
+ []
+ let ``NoHeaders succeeds when set to true`` () =
+ Assert.Equal ("\"noHeaders\": true", HxRequest.NoHeaders true)
+
+ []
+ let ``NoHeaders succeeds when set to false`` () =
+ Assert.Equal ("\"noHeaders\": false", HxRequest.NoHeaders false)
-/// Tests for the HxSwap module
-module Swap =
-
- []
- let ``InnerHtml is correct`` () =
- Assert.Equal ("innerHTML", HxSwap.InnerHtml)
-
- []
- let ``OuterHtml is correct`` () =
- Assert.Equal ("outerHTML", HxSwap.OuterHtml)
-
- []
- let ``BeforeBegin is correct`` () =
- Assert.Equal ("beforebegin", HxSwap.BeforeBegin)
-
- []
- let ``BeforeEnd is correct`` () =
- Assert.Equal ("beforeend", HxSwap.BeforeEnd)
-
- []
- let ``AfterBegin is correct`` () =
- Assert.Equal ("afterbegin", HxSwap.AfterBegin)
-
- []
- let ``AfterEnd is correct`` () =
- Assert.Equal ("afterend", HxSwap.AfterEnd)
-
- []
- let ``None is correct`` () =
- Assert.Equal ("none", HxSwap.None)
-
-
/// Tests for the HxTrigger module
module Trigger =
-
- []
- let ``Click is correct`` () =
- Assert.Equal ("click", HxTrigger.Click)
-
- []
- let ``Load is correct`` () =
- Assert.Equal ("load", HxTrigger.Load)
-
- []
- let ``Revealed is correct`` () =
- Assert.Equal ("revealed", HxTrigger.Revealed)
-
- []
- let ``Every succeeds`` () =
- Assert.Equal ("every 3s", HxTrigger.Every "3s")
- []
- let ``Filter.Alt succeeds`` () =
- Assert.Equal ("click[altKey]", HxTrigger.Filter.Alt HxTrigger.Click)
-
- []
- let ``Filter.Ctrl succeeds`` () =
- Assert.Equal ("click[ctrlKey]", HxTrigger.Filter.Ctrl HxTrigger.Click)
-
- []
- let ``Filter.Shift succeeds`` () =
- Assert.Equal ("click[shiftKey]", HxTrigger.Filter.Shift HxTrigger.Click)
-
- []
- let ``Filter.CtrlAlt succeeds`` () =
- Assert.Equal ("click[ctrlKey&&altKey]", HxTrigger.Filter.CtrlAlt HxTrigger.Click)
+ []
+ let ``Click is correct`` () =
+ Assert.Equal ("click", HxTrigger.Click)
- []
- let ``Filter.CtrlShift succeeds`` () =
- Assert.Equal ("click[ctrlKey&&shiftKey]", HxTrigger.Filter.CtrlShift HxTrigger.Click)
+ []
+ let ``Load is correct`` () =
+ Assert.Equal ("load", HxTrigger.Load)
- []
- let ``Filter.CtrlAltShift succeeds`` () =
- Assert.Equal ("click[ctrlKey&&altKey&&shiftKey]", HxTrigger.Filter.CtrlAltShift HxTrigger.Click)
+ []
+ let ``Revealed is correct`` () =
+ Assert.Equal ("revealed", HxTrigger.Revealed)
- []
- let ``Filter.AltShift succeeds`` () =
- Assert.Equal ("click[altKey&&shiftKey]", HxTrigger.Filter.AltShift HxTrigger.Click)
+ []
+ let ``Every succeeds`` () =
+ Assert.Equal ("every 3s", HxTrigger.Every "3s")
- []
- let ``Once succeeds when it is the first modifier`` () =
- Assert.Equal ("once", HxTrigger.Once "")
-
- []
- let ``Once succeeds when it is not the first modifier`` () =
- Assert.Equal ("click once", HxTrigger.Once "click")
+ []
+ let ``Filter.Alt succeeds`` () =
+ Assert.Equal ("click[altKey]", HxTrigger.Filter.Alt HxTrigger.Click)
- []
- let ``Changed succeeds when it is the first modifier`` () =
- Assert.Equal ("changed", HxTrigger.Changed "")
-
- []
- let ``Changed succeeds when it is not the first modifier`` () =
- Assert.Equal ("click changed", HxTrigger.Changed "click")
+ []
+ let ``Filter.Ctrl succeeds`` () =
+ Assert.Equal ("click[ctrlKey]", HxTrigger.Filter.Ctrl HxTrigger.Click)
- []
- let ``Delay succeeds when it is the first modifier`` () =
- Assert.Equal ("delay:1s", HxTrigger.Delay "1s" "")
-
- []
- let ``Delay succeeds when it is not the first modifier`` () =
- Assert.Equal ("click delay:2s", HxTrigger.Delay "2s" "click")
+ []
+ let ``Filter.Shift succeeds`` () =
+ Assert.Equal ("click[shiftKey]", HxTrigger.Filter.Shift HxTrigger.Click)
- []
- let ``Throttle succeeds when it is the first modifier`` () =
- Assert.Equal ("throttle:4s", HxTrigger.Throttle "4s" "")
-
- []
- let ``Throttle succeeds when it is not the first modifier`` () =
- Assert.Equal ("click throttle:7s", HxTrigger.Throttle "7s" "click")
+ []
+ let ``Filter.CtrlAlt succeeds`` () =
+ Assert.Equal ("click[ctrlKey&&altKey]", HxTrigger.Filter.CtrlAlt HxTrigger.Click)
- []
- let ``From succeeds when it is the first modifier`` () =
- Assert.Equal ("from:.nav", HxTrigger.From ".nav" "")
-
- []
- let ``From succeeds when it is not the first modifier`` () =
- Assert.Equal ("click from:#somewhere", HxTrigger.From "#somewhere" "click")
+ []
+ let ``Filter.CtrlShift succeeds`` () =
+ Assert.Equal ("click[ctrlKey&&shiftKey]", HxTrigger.Filter.CtrlShift HxTrigger.Click)
- []
- let ``FromDocument succeeds when it is the first modifier`` () =
- Assert.Equal ("from:document", HxTrigger.FromDocument "")
-
- []
- let ``FromDocument succeeds when it is not the first modifier`` () =
- Assert.Equal ("click from:document", HxTrigger.FromDocument "click")
+ []
+ let ``Filter.CtrlAltShift succeeds`` () =
+ Assert.Equal ("click[ctrlKey&&altKey&&shiftKey]", HxTrigger.Filter.CtrlAltShift HxTrigger.Click)
- []
- let ``FromWindow succeeds when it is the first modifier`` () =
- Assert.Equal ("from:window", HxTrigger.FromWindow "")
-
- []
- let ``FromWindow succeeds when it is not the first modifier`` () =
- Assert.Equal ("click from:window", HxTrigger.FromWindow "click")
+ []
+ let ``Filter.AltShift succeeds`` () =
+ Assert.Equal ("click[altKey&&shiftKey]", HxTrigger.Filter.AltShift HxTrigger.Click)
- []
- let ``FromClosest succeeds when it is the first modifier`` () =
- Assert.Equal ("from:closest div", HxTrigger.FromClosest "div" "")
-
- []
- let ``FromClosest succeeds when it is not the first modifier`` () =
- Assert.Equal ("click from:closest p", HxTrigger.FromClosest "p" "click")
+ []
+ let ``Once succeeds when it is the first modifier`` () =
+ Assert.Equal ("once", HxTrigger.Once "")
- []
- let ``FromFind succeeds when it is the first modifier`` () =
- Assert.Equal ("from:find li", HxTrigger.FromFind "li" "")
-
- [