Compare commits

..

2 Commits

Author SHA1 Message Date
danieljsummers cfd8d7eb68 v2,0.10 (#21)
Update script to 2.0.10, convert sln to slnx

Reviewed-on: #21
2026-07-03 23:44:51 +00:00
danieljsummers 8f93aa4d35 Add htmx 4 notes to README 2026-06-30 14:02:34 +00:00
14 changed files with 714 additions and 1326 deletions
+2
View File
@@ -6,6 +6,8 @@
htmx uses attributes and HTTP headers to attain its interactivity; the libraries here contain extensions to both Giraffe and Giraffe View Engine to enable strongly-typed development of htmx applications.
> **NOTE** htmx v4 is curently in beta; this library is supporting it on the [`htmx-v4` branch](https://git.bitbadger.solutions/bit-badger/Giraffe.Htmx/src/branch/htmx-v4/). Beta versions of the v4 library include warnings about obsolete constructs. The htmx project intends to continue supporting the 2.x line (just as they still do the 1.x line, which we track on the [`htmx-v1` branch](https://git.bitbadger.solutions/bit-badger/Giraffe.Htmx/src/branch/htmx-v1/)); the upgrade is available, not forced. See the [htmx v4 migration docs](https://four.htmx.org/docs#migration) for more information.
## Installation
`Giraffe.Htmx` provides extensions that facilitate using htmx on the server side, primarily reading and setting headers. `Giraffe.ViewEngine.Htmx` provides attributes and helpers to produce views that utilize htmx. Both can be installed from NuGet via standard methods.
+14 -52
View File
@@ -3,7 +3,7 @@
module Giraffe.Htmx.Common
/// <summary>The version of htmx embedded in the package</summary>
let HtmxVersion = "4.0.0-alpha6"
let HtmxVersion = "2.0.10"
/// <summary>The path for the provided htmx script</summary>
let internal htmxLocalScript = $"/_content/Giraffe.Htmx.Common/htmx.min.js?ver={HtmxVersion}"
@@ -25,73 +25,35 @@ let internal toLowerBool (boolValue: bool) =
/// <summary>Valid values for the <c>hx-swap</c> attribute / <c>HX-Reswap</c> header</summary>
/// <remarks>May be combined with <c>swap</c> / <c>scroll</c> / <c>show</c> config)</remarks>
/// <seealso href="https://four.htmx.org/attributes/hx-swap/">Documentation</seealso>
/// <remarks>May be combined with <c>swap</c> / <c>settle</c> / <c>scroll</c> / <c>show</c> config)</remarks>
/// <seealso href="https://htmx.org/attributes/hx-swap/">Documentation</seealso>
[<RequireQualifiedAccess>]
module HxSwap =
/// <summary>The default, replace the inner HTML of the target element</summary>
[<Literal>]
let InnerHtml = "innerHTML"
/// <summary>Replace the entire target element with the response</summary>
[<Literal>]
let OuterHtml = "outerHTML"
/// <summary>Morph the inner HTML of the target to the new content</summary>
[<Literal>]
let InnerMorph = "innerMorph"
/// <summary>Morph the outer HTML of the target to the new content</summary>
[<Literal>]
let OuterMorph = "innerMorph"
/// <summary>Replace the text content of the target without parsing the response as HTML</summary>
[<Literal>]
let TextContent = "textContent"
/// <summary>Insert the response before the target element</summary>
[<Literal>]
let Before = "before"
/// <summary>Insert the response before the target element (pre-v4 name)</summary>
[<Literal>]
let BeforeBegin = Before
let BeforeBegin = "beforebegin"
/// <summary>Insert the response before the first child of the target element</summary>
[<Literal>]
let Prepend = "prepend"
/// <summary>Insert the response before the first child of the target element (pre-v4 name)</summary>
[<Literal>]
let AfterBegin = Prepend
let AfterBegin = "afterbegin"
/// <summary>Insert the response after the last child of the target element</summary>
[<Literal>]
let Append = "append"
/// <summary>Insert the response after the last child of the target element (pre-v4 name)</summary>
[<Literal>]
let BeforeEnd = Append
let BeforeEnd = "beforeend"
/// <summary>Insert the response after the target element</summary>
[<Literal>]
let After = "after"
let AfterEnd = "afterend"
/// <summary>Insert the response after the target element (pre-v4 name)</summary>
[<Literal>]
let AfterEnd = After
/// <summary>Delete the target element regardless of response</summary>
[<Literal>]
let Delete = "delete"
/// <summary>Does not append content from response (out of band items will still be processed)</summary>
/// <summary>Does not append content from response (out of band items will still be processed).</summary>
[<Literal>]
let None = "none"
/// <summary>Update existing elements by <c>id</c> and add new ones</summary>
/// <remarks>This requires the <c>upsert</c> extension</remarks>
/// <seealso href="https://four.htmx.org/extensions/upsert">Extension</seealso>
[<Literal>]
let Upsert = "upsert"
+1 -3
View File
@@ -2,6 +2,4 @@
This package contains common code shared between [`Giraffe.Htmx`](https://www.nuget.org/packages/Giraffe.Htmx) and [`Giraffe.ViewEngine.Htmx`](https://www.nuget.org/packages/Giraffe.ViewEngine.Htmx), and will be automatically installed when you install either one. It also contains htmx as a static web asset, allowing it to be loaded from your local (or published) project.
**htmx version: 4.0.0-alpha6**
_**NOTE:** Pay special attention to breaking changes highlighted in the packages listed above._
**htmx version: 2.0.10**
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -8
View File
@@ -2,16 +2,11 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<VersionPrefix>4.0.0</VersionPrefix>
<VersionSuffix>alpha6a</VersionSuffix>
<VersionPrefix>2.0.10</VersionPrefix>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageReleaseNotes>First htmx 4 alpha release of these libraries
- [Server] Marked removed headers as obsolete; added new HX-Source header
- [View Engine] Marked removed attributes as obsolete
- [View Engine] Added new attributes, modifiers, and support for new hx-partial tag
- Updated script tags to pull htmx 4.0.0-alpha6
<PackageReleaseNotes>- Updates provided script and CDN links to serve htmx 2.0.10 (no header or attribute changes)
See package READMEs; this is not an update-and-forget-it release
NOTE: As of 2.0.6, the CDN for htmx changed from unpkg.com to cdn.jsdelivr.net; sites with Content-Security-Policy headers will want to update their allowed script-src domains accordingly
</PackageReleaseNotes>
<Authors>danieljsummers</Authors>
<Company>Bit Badger Solutions</Company>
-40
View File
@@ -1,40 +0,0 @@
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.ViewEngine.Htmx", "ViewEngine.Htmx\Giraffe.ViewEngine.Htmx.fsproj", "{F718B3C1-EE01-4F04-ABCE-BF2AE700FDA9}"
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}") = "Tests", "Tests\Tests.fsproj", "{39823773-4311-4E79-9CA0-F9DDC40CAF6A}"
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
{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
{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
{39823773-4311-4E79-9CA0-F9DDC40CAF6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39823773-4311-4E79-9CA0-F9DDC40CAF6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39823773-4311-4E79-9CA0-F9DDC40CAF6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39823773-4311-4E79-9CA0-F9DDC40CAF6A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
+6
View File
@@ -0,0 +1,6 @@
<Solution>
<Project Path="Common/Giraffe.Htmx.Common.fsproj" />
<Project Path="Htmx/Giraffe.Htmx.fsproj" />
<Project Path="Tests/Tests.fsproj" />
<Project Path="ViewEngine.Htmx/Giraffe.ViewEngine.Htmx.fsproj" />
</Solution>
-15
View File
@@ -24,7 +24,6 @@ type IHeaderDictionary with
with get () = hdr this "HX-History-Restore-Request" |> Option.map bool.Parse
/// <summary>The user response to an <c>hx-prompt</c></summary>
[<Obsolete "hx-prompt is removed in v4">]
member this.HxPrompt
with get () = hdr this "HX-Prompt"
@@ -32,29 +31,15 @@ type IHeaderDictionary with
member this.HxRequest
with get () = hdr this "HX-Request" |> Option.map bool.Parse
/// <summary>The tag name (fst) and <c>id</c> attribute (snd) of the element triggering this request</summary>
member this.HxSource
with get () =
match hdr this "HX-Source" with
| Some src ->
let parts = src.Split "#"
if parts.Length = 1 then
Some (parts[0], None)
else
Some (parts[0], if parts[1] <> "" then Some parts[1] else None)
| None -> None
/// <summary>The <c>id</c> attribute of the target element if it exists</summary>
member this.HxTarget
with get () = hdr this "HX-Target"
/// <summary>The <c>id</c> attribute of the triggered element if it exists</summary>
[<Obsolete "HX-Trigger is removed in v4; use the second item of HX-Source">]
member this.HxTrigger
with get () = hdr this "HX-Trigger"
/// <summary>The <c>name</c> attribute of the triggered element if it exists</summary>
[<Obsolete "HX-Trigger-Name is removed in v4; may be available via extension, but will be removed from this library">]
member this.HxTriggerName
with get () = hdr this "HX-Trigger-Name"
+5 -7
View File
@@ -2,11 +2,9 @@
This package enables server-side support for [htmx](https://htmx.org) within [Giraffe](https://giraffe.wiki) and ASP.NET's `HttpContext`.
**htmx version: 4.0.0-alpha6**
**htmx version: 2.0.10**
_Upgrading from v2.x: the [migration guide](https://four.htmx.org/migration-guide-htmx-4/) lists changes for v4. For this package, the `HX-Trigger` and `HX-Trigger-Name` headers are marked obsolete. They are replaced by `HX-Source`, which provides the triggering tag name and `id` attribute. The `HX-Prompt` header has also been marked as obsolete, as the `hx-prompt` attribute which generated its content has been removed._
_Obsolete elements will be removed in the first production v4 release._
_Upgrading from v1.x: the [migration guide](https://htmx.org/migration-guide-htmx-1/) does not currently specify any request or response header changes. This means that there are no required code changes in moving from v1.* to v2.*._
### Setup
@@ -20,9 +18,9 @@ To obtain a request header, using the `IHeaderDictionary` extension properties:
```fsharp
let myHandler : HttpHander =
fun next ctx ->
match ctx.Target with
| Some elt -> ... // do something with id of the target element
| None -> ... // no target element provided
match ctx.HxPrompt with
| Some prompt -> ... // do something with the text the user provided
| None -> ... // no text provided
```
To set a response header:
+6 -33
View File
@@ -6,7 +6,7 @@ open Giraffe.Htmx
/// Test to ensure the version was updated
let version =
test "HtmxVersion is correct" {
Expect.equal HtmxVersion "4.0.0-alpha6" "htmx version incorrect"
Expect.equal HtmxVersion "2.0.10" "htmx version incorrect"
}
/// Tests for the HxSwap module
@@ -18,48 +18,21 @@ let swap =
test "OuterHtml is correct" {
Expect.equal HxSwap.OuterHtml "outerHTML" "Outer HTML swap value incorrect"
}
test "InnerMorph is correct" {
Expect.equal HxSwap.InnerMorph "innerMorph" "Inner Morph swap value incorrect"
}
test "OuterMorph is correct" {
Expect.equal HxSwap.OuterMorph "innerMorph" "Outer Morph swap value incorrect"
}
test "TextContent is correct" {
Expect.equal HxSwap.TextContent "textContent" "Text Content swap value incorrect"
}
test "Before is correct" {
Expect.equal HxSwap.Before "before" "Before swap value incorrect"
}
test "BeforeBegin is correct" {
Expect.equal HxSwap.BeforeBegin HxSwap.Before "Before Begin swap value incorrect"
}
test "Prepend is correct" {
Expect.equal HxSwap.Prepend "prepend" "Prepend swap value incorrect"
}
test "AfterBegin is correct" {
Expect.equal HxSwap.AfterBegin HxSwap.Prepend "Prepend swap value incorrect"
}
test "Append is correct" {
Expect.equal HxSwap.Append "append" "Append swap value incorrect"
Expect.equal HxSwap.BeforeBegin "beforebegin" "Before Begin swap value incorrect"
}
test "BeforeEnd is correct" {
Expect.equal HxSwap.BeforeEnd HxSwap.Append "Before End swap value incorrect"
Expect.equal HxSwap.BeforeEnd "beforeend" "Before End swap value incorrect"
}
test "After is correct" {
Expect.equal HxSwap.After "after" "After swap value incorrect"
test "AfterBegin is correct" {
Expect.equal HxSwap.AfterBegin "afterbegin" "After Begin swap value incorrect"
}
test "AfterEnd is correct" {
Expect.equal HxSwap.AfterEnd HxSwap.After "After End swap value incorrect"
}
test "Delete is correct" {
Expect.equal HxSwap.Delete "delete" "Delete swap value incorrect"
Expect.equal HxSwap.AfterEnd "afterend" "After End swap value incorrect"
}
test "None is correct" {
Expect.equal HxSwap.None "none" "None swap value incorrect"
}
test "Upsert is correct" {
Expect.equal HxSwap.Upsert "upsert" "Upsert swap value incorrect"
}
]
/// All tests for this module
+51 -93
View File
@@ -3,6 +3,7 @@ module Htmx
open System
open Expecto
open Giraffe.Htmx
open Microsoft.AspNetCore.Html
open Microsoft.AspNetCore.Http
open NSubstitute
@@ -73,6 +74,21 @@ let dictExtensions =
ctx.Request.Headers.HxHistoryRestoreRequest.Value "The header should have been false"
}
]
testList "HxPrompt" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
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<HttpContext>()
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"
}
]
testList "HxRequest" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
@@ -96,44 +112,6 @@ let dictExtensions =
Expect.isFalse ctx.Request.Headers.HxRequest.Value "The header should have been false"
}
]
testList "HxSource" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
Expect.isNone ctx.Request.Headers.HxSource "There should not have been a header returned"
}
test "succeeds when the header is present and both parts exist" {
let ctx = Substitute.For<HttpContext>()
let dic = HeaderDictionary()
dic.Add("HX-Source", "button#theId")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
let hdr = ctx.Request.Headers.HxSource
Expect.isSome hdr "There should be a header present"
Expect.equal (fst hdr.Value) "button" "The source tag was incorrect"
Expect.isSome (snd hdr.Value) "There should be a source ID present"
Expect.equal (snd hdr.Value).Value "theId" "The source ID was incorrect"
}
test "succeeds when the header is present and ID is blank" {
let ctx = Substitute.For<HttpContext>()
let dic = HeaderDictionary()
dic.Add("HX-Source", "a#")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
let hdr = ctx.Request.Headers.HxSource
Expect.isSome hdr "There should be a header present"
Expect.equal (fst hdr.Value) "a" "The source tag was incorrect"
Expect.isNone (snd hdr.Value) "There should not be a source ID present"
}
test "succeeds when the header is present and ID is missing" {
let ctx = Substitute.For<HttpContext>()
let dic = HeaderDictionary()
dic.Add("HX-Source", "form")
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
let hdr = ctx.Request.Headers.HxSource
Expect.isSome hdr "There should be a header present"
Expect.equal (fst hdr.Value) "form" "The source tag was incorrect"
Expect.isNone (snd hdr.Value) "There should not be a source ID present"
}
]
testList "HxTarget" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
@@ -149,6 +127,36 @@ let dictExtensions =
Expect.equal ctx.Request.Headers.HxTarget.Value "#leItem" "The header value was incorrect"
}
]
testList "HxTrigger" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
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<HttpContext>()
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"
}
]
testList "HxTriggerName" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
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<HttpContext>()
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"
}
]
]
/// Tests for the HttpRequest extension properties
@@ -159,7 +167,7 @@ let reqExtensions =
let ctx = Substitute.For<HttpContext>()
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<HttpContext>()
let dic = HeaderDictionary()
@@ -196,7 +204,7 @@ open System.Threading.Tasks
/// Dummy "next" parameter to get the pipeline to execute/terminate
let next (ctx: HttpContext) = Task.FromResult(Some ctx)
/// Tests for the HttpHandler functions provided in the Handlers module
let handlers =
testList "HandlerTests" [
@@ -273,7 +281,7 @@ let handlers =
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<HttpContext>()
let dic = HeaderDictionary()
@@ -281,7 +289,7 @@ let handlers =
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<HttpContext>()
let dic = HeaderDictionary()
@@ -358,55 +366,5 @@ let script =
}
]
#nowarn 44 // Obsolete items still have tests
let dictExtensionsObs =
testList "IHeaderDictionaryExtensions (Obsolete)" [
testList "HxPrompt" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
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<HttpContext>()
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"
}
]
testList "HxTrigger" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
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<HttpContext>()
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"
}
]
testList "HxTriggerName" [
test "succeeds when the header is not present" {
let ctx = Substitute.For<HttpContext>()
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<HttpContext>()
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"
}
]
]
/// All tests for this module
let allTests = testList "Htmx" [ dictExtensions; reqExtensions; handlers; script; dictExtensionsObs ]
let allTests = testList "Htmx" [ dictExtensions; reqExtensions; handlers; script ]
+413 -675
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+4 -9
View File
@@ -2,13 +2,9 @@
This package enables [htmx](https://htmx.org) support within the [Giraffe](https://giraffe.wiki) view engine.
**htmx version: 4.0.0-alpha6**
**htmx version: 2.0.10**
_Upgrading from v2.x: see [the migration guide](https://four.htmx.org/migration-guide-htmx-4/) for changes, which are plentiful. htmx switches from `XMLHTTPRequest` to `fetch`, and many changes are related to the new event cycle._
_Inheritance is now explicit; to have an attribute's value inherited to its children, wrap the attribute in `hxInherited` (ex. `hxInherited (_hxTarget "#main")`). Values can be appended to inherited values as well using the `hxAppend` modifier._
_Several constructs have been marked obsolete in this release, and will be removed from the first production release of v4. With the exception of `_hxDisable`, though (which now functions as the deprecated `_hxDisabledElt` did), this should not introduce compile errors. Rather, this package will raise warnings for deprecated constructs, along with suggestions of what to use instead._
_Upgrading from v1.x: see [the migration guide](https://htmx.org/migration-guide-htmx-1/) for changes_
### Setup
@@ -25,11 +21,10 @@ let autoload =
```
Support modules include:
- `HxConfig` _(new in v4)_
- `HxEncoding`
- `HxHeaders`
- ~~`HxParams`~~ _(removed in v4)_
- ~~`HxRequest`~~ _(renamed to `HxConfig`)_
- `HxParams`
- `HxRequest`
- `HxSwap` (requires `open Giraffe.Htmx`)
- `HxTrigger`
- `HxVals`