From 3dcbe1cf788468b2e68eb50c1117f7b21cb83d34 Mon Sep 17 00:00:00 2001 From: rameel Date: Sat, 8 Aug 2026 16:56:26 +0500 Subject: [PATCH 1/9] Fix script initialization to avoid error when loaded in without defer --- src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.js | 2 +- src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.min.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.js b/src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.js index 762b083..6099862 100644 --- a/src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.js +++ b/src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.js @@ -1,4 +1,4 @@ -document.body._r_htmx ??= ((document, htmx) => { +document._r_htmx ||= ((document, htmx) => { document.addEventListener("htmx:afterOnLoad", e => { if (e.detail.boosted) { const html = new DOMParser().parseFromString(e.detail.xhr.responseText, "text/html"); diff --git a/src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.min.js b/src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.min.js index 5d972ea..811157f 100644 --- a/src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.min.js +++ b/src/Ramstack.HtmxToolkit/Assets/htmx-toolkit.min.js @@ -1 +1 @@ -document.body._r_htmx??=((e,t)=>(e.addEventListener("htmx:afterOnLoad",e=>{if(e.detail.boosted){const r=(new DOMParser).parseFromString(e.detail.xhr.responseText,"text/html").querySelector("meta[name='htmx-config']");r&&(t.config.antiForgery=JSON.parse(r.content).antiForgery)}}),e.addEventListener("htmx:configRequest",e=>{if(!/^get$/i.test(e.detail.verb)){const{headerName:r,formFieldName:a,requestToken:n}=t.config.antiForgery??{};n&&!e.detail.parameters[a]&&(r?e.detail.headers[r]=n:e.detail.parameters[a]=n)}}),!0))(document,htmx); \ No newline at end of file +document._r_htmx||=((e,t)=>(e.addEventListener("htmx:afterOnLoad",e=>{if(e.detail.boosted){const r=(new DOMParser).parseFromString(e.detail.xhr.responseText,"text/html").querySelector("meta[name='htmx-config']");r&&(t.config.antiForgery=JSON.parse(r.content).antiForgery)}}),e.addEventListener("htmx:configRequest",e=>{if(!/^get$/i.test(e.detail.verb)){const{headerName:r,formFieldName:a,requestToken:n}=t.config.antiForgery??{};n&&!e.detail.parameters[a]&&(r?e.detail.headers[r]=n:e.detail.parameters[a]=n)}}),!0))(document,htmx); \ No newline at end of file From 77ba48eaaee3ba40a208e8b1f45060cd4637b855 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 9 Aug 2026 14:39:20 +0500 Subject: [PATCH 2/9] Make HtmxResponseHeaders a readonly struct The type was originally intended as a lightweight wrapper/struct rather than a reference type --- src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs b/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs index a63b1e6..6e355d7 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs @@ -10,7 +10,7 @@ namespace Ramstack.HtmxToolkit; /// Represents strongly typed HTMX response headers. /// [DebuggerTypeProxy(typeof(HtmxResponseHeadersDebugView))] -public sealed class HtmxResponseHeaders +public readonly struct HtmxResponseHeaders { private readonly HttpResponse _response; From 94676e18836f97889db6829bae35ce54076c2820 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 9 Aug 2026 14:41:47 +0500 Subject: [PATCH 3/9] Use file-scoped namespace --- .../TagHelpers/HtmxHeaderTagHelper.cs | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs index 441061c..983e588 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs @@ -5,40 +5,39 @@ using Ramstack.HtmxToolkit.Internal; -namespace Ramstack.HtmxToolkit.TagHelpers +namespace Ramstack.HtmxToolkit.TagHelpers; + +/// +/// Represents a implementation that applies the hx-headers attribute to matching elements. +/// +/// +/// +/// hx-headers is inherited and can be placed on a parent element. +/// A child declaration of a header overrides a parent declaration. +/// +/// +[HtmlTargetElement(Attributes = HeadersDictionaryName)] +[HtmlTargetElement(Attributes = HeadersPrefix + "*")] +public sealed class HtmxHeaderTagHelper : TagHelper { + private const string HeadersPrefix = "hx-header-"; + private const string HeadersDictionaryName = "hx-all-headers"; + /// - /// Represents a implementation that applies the hx-headers attribute to matching elements. + /// Gets or sets the hx-header attribute values. /// - /// - /// - /// hx-headers is inherited and can be placed on a parent element. - /// A child declaration of a header overrides a parent declaration. - /// - /// - [HtmlTargetElement(Attributes = HeadersDictionaryName)] - [HtmlTargetElement(Attributes = HeadersPrefix + "*")] - public sealed class HtmxHeaderTagHelper : TagHelper + [HtmlAttributeName(HeadersDictionaryName, DictionaryAttributePrefix = HeadersPrefix)] + public Dictionary Headers { get; set; } = new(); + + /// + public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - private const string HeadersPrefix = "hx-header-"; - private const string HeadersDictionaryName = "hx-all-headers"; - - /// - /// Gets or sets the hx-header attribute values. - /// - [HtmlAttributeName(HeadersDictionaryName, DictionaryAttributePrefix = HeadersPrefix)] - public Dictionary Headers { get; set; } = new(); - - /// - public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - var headers = new HtmlString( - JsonSerializer.Serialize(Headers, JsonOptions.PreserveKeyCase)); - - output.Attributes.SetAttribute( - new TagHelperAttribute("hx-headers", headers, HtmlAttributeValueStyle.SingleQuotes)); - - return Task.CompletedTask; - } + var headers = new HtmlString( + JsonSerializer.Serialize(Headers, JsonOptions.PreserveKeyCase)); + + output.Attributes.SetAttribute( + new TagHelperAttribute("hx-headers", headers, HtmlAttributeValueStyle.SingleQuotes)); + + return Task.CompletedTask; } } From 9e2695c71af0dbeccaba86dedf1d884111f1ec1e Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 9 Aug 2026 14:52:01 +0500 Subject: [PATCH 4/9] Fix diFix dictionary type to string for proper Razor attribute handling --- .../TagHelpers/HtmxUrlTagHelper.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs index 84835a8..87f2891 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs @@ -43,7 +43,7 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper private static readonly string[] s_methods = ["hx-get", "hx-post", "hx-delete", "hx-put", "hx-patch"]; - private RouteValueDictionary? _routeValues; + private IDictionary? _routeValues; /// public override int Order => -1000; @@ -128,9 +128,9 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper /// Gets or sets the additional parameters for the route. /// [HtmlAttributeName(RouteValuesDictionaryName, DictionaryAttributePrefix = RouteValuesPrefix)] - public RouteValueDictionary RouteValues + public IDictionary RouteValues { - get => _routeValues ??= []; + get => _routeValues ??= new Dictionary(StringComparer.OrdinalIgnoreCase); set => _routeValues = value; } @@ -148,13 +148,18 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp var actionLink = Controller != null || Action != null; var pageLink = Page != null || PageHandler != null; - if ((routeLink && actionLink) || (routeLink && pageLink) || (actionLink && pageLink)) + if ((routeLink && (actionLink || pageLink)) || (actionLink && pageLink)) Error_CannotDetermineUrl(); + RouteValueDictionary? routeValues = null; + if (_routeValues is { Count: > 0 }) + routeValues = new RouteValueDictionary(_routeValues!); + if (Area is not null) { // Unconditionally replace any value from hx-area - RouteValues["area"] = Area; + routeValues ??= new RouteValueDictionary(); + routeValues["area"] = Area; } var generator = factory.GetUrlHelper(ViewContext); @@ -165,7 +170,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp url = generator.Page( pageName: Page, pageHandler: PageHandler, - values: RouteValues, + values: routeValues, protocol: Protocol, host: Host, fragment: Fragment); @@ -174,7 +179,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp { url = generator.RouteUrl( routeName: Route, - values: RouteValues, + values: routeValues, protocol: Protocol, host: Host, fragment: Fragment); @@ -184,7 +189,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp url = generator.Action( action: Action, controller: Controller, - values: RouteValues, + values: routeValues, protocol: Protocol, host: Host, fragment: Fragment); From fe54e48647af981f79a14f01803e2dcef19ce348 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 9 Aug 2026 14:57:31 +0500 Subject: [PATCH 5/9] Fix workflow not triggering on PR updates --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ec7160c..7516b48 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,7 @@ on: pull_request: branches: [main] + types: [opened, synchronize, reopened, ready_for_review] jobs: publish: @@ -17,7 +18,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 1 - name: Build (Debug) run: dotnet build -c Debug From 92bef370e9efea1b37ca9c46fed4403e8180762b Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 9 Aug 2026 15:01:55 +0500 Subject: [PATCH 6/9] Update npm dependencies --- package.json | 6 +- pnpm-lock.yaml | 278 ++++++++++++++++++++++++------------------------- 2 files changed, 141 insertions(+), 143 deletions(-) diff --git a/package.json b/package.json index 133492b..d7cfdf2 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,9 @@ "author": "rameel ", "license": "MIT", "devDependencies": { - "@rollup/plugin-terser": "^0.4.4", - "rollup": "^4.57.1", + "@rollup/plugin-terser": "^1.0.0", + "rollup": "^4.62.4", "rollup-plugin-bundle-size": "^1.0.3", - "terser": "^5.46.0" + "terser": "^5.49.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46da4b0..af19fab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,17 +9,17 @@ importers: .: devDependencies: '@rollup/plugin-terser': - specifier: ^0.4.4 - version: 0.4.4(rollup@4.57.1) + specifier: ^1.0.0 + version: 1.0.0(rollup@4.62.4) rollup: - specifier: ^4.57.1 - version: 4.57.1 + specifier: ^4.62.4 + version: 4.62.4 rollup-plugin-bundle-size: specifier: ^1.0.3 version: 1.0.3 terser: - specifier: ^5.46.0 - version: 5.46.0 + specifier: ^5.49.2 + version: 5.49.2 packages: @@ -39,155 +39,162 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@rollup/plugin-terser@0.4.4': - resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} - engines: {node: '>=14.0.0'} + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==} + engines: {node: ^22.20 || ^24.12 || >=25} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/plugin-terser@1.0.0': + resolution: {integrity: sha512-FnCxhTBx6bMOYQrar6C8h3scPt8/JwIzw3+AJ2K++6guogH5fYaIFia+zZuhqv0eo1RN7W1Pz630SyvLbDjhtQ==} + engines: {node: '>=20.0.0'} peerDependencies: rollup: ^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.57.1': - resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + '@rollup/rollup-android-arm-eabi@4.62.4': + resolution: {integrity: sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.57.1': - resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + '@rollup/rollup-android-arm64@4.62.4': + resolution: {integrity: sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.57.1': - resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + '@rollup/rollup-darwin-arm64@4.62.4': + resolution: {integrity: sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.57.1': - resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + '@rollup/rollup-darwin-x64@4.62.4': + resolution: {integrity: sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.57.1': - resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + '@rollup/rollup-freebsd-arm64@4.62.4': + resolution: {integrity: sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.57.1': - resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + '@rollup/rollup-freebsd-x64@4.62.4': + resolution: {integrity: sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': - resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + '@rollup/rollup-linux-arm-gnueabihf@4.62.4': + resolution: {integrity: sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.57.1': - resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + '@rollup/rollup-linux-arm-musleabihf@4.62.4': + resolution: {integrity: sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.57.1': - resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + '@rollup/rollup-linux-arm64-gnu@4.62.4': + resolution: {integrity: sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.57.1': - resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + '@rollup/rollup-linux-arm64-musl@4.62.4': + resolution: {integrity: sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.57.1': - resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + '@rollup/rollup-linux-loong64-gnu@4.62.4': + resolution: {integrity: sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.57.1': - resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + '@rollup/rollup-linux-loong64-musl@4.62.4': + resolution: {integrity: sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.57.1': - resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + '@rollup/rollup-linux-ppc64-gnu@4.62.4': + resolution: {integrity: sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.57.1': - resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + '@rollup/rollup-linux-ppc64-musl@4.62.4': + resolution: {integrity: sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.57.1': - resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + '@rollup/rollup-linux-riscv64-gnu@4.62.4': + resolution: {integrity: sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.57.1': - resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + '@rollup/rollup-linux-riscv64-musl@4.62.4': + resolution: {integrity: sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.57.1': - resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + '@rollup/rollup-linux-s390x-gnu@4.62.4': + resolution: {integrity: sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.57.1': - resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + '@rollup/rollup-linux-x64-gnu@4.62.4': + resolution: {integrity: sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.57.1': - resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + '@rollup/rollup-linux-x64-musl@4.62.4': + resolution: {integrity: sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.57.1': - resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + '@rollup/rollup-openbsd-x64@4.62.4': + resolution: {integrity: sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.57.1': - resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + '@rollup/rollup-openharmony-arm64@4.62.4': + resolution: {integrity: sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.57.1': - resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + '@rollup/rollup-win32-arm64-msvc@4.62.4': + resolution: {integrity: sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.57.1': - resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + '@rollup/rollup-win32-ia32-msvc@4.62.4': + resolution: {integrity: sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.57.1': - resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} + '@rollup/rollup-win32-x64-gnu@4.62.4': + resolution: {integrity: sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.57.1': - resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + '@rollup/rollup-win32-x64-msvc@4.62.4': + resolution: {integrity: sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==} cpu: [x64] os: [win32] - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} @@ -252,22 +259,17 @@ packages: resolution: {integrity: sha512-eb7ZAeUTgfh294cElcu51w+OTRp/6ItW758LjwJSK72LDevcuJn0P4eD71PLMDGPwwatXmAmYHTkzvpKlJE3ow==} engines: {node: '>=0.10.0'} - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - rollup-plugin-bundle-size@1.0.3: resolution: {integrity: sha512-aWj0Pvzq90fqbI5vN1IvUrlf4utOqy+AERYxwWjegH1G8PzheMnrRIgQ5tkwKVtQMDP0bHZEACW/zLDF+XgfXQ==} - rollup@4.57.1: - resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + rollup@4.62.4: + resolution: {integrity: sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + serialize-javascript@7.1.0: + resolution: {integrity: sha512-RNEqWOyhhUQYN9V1GfHwu9AR/g+NTciH6Z5u3/no6X3/w+04J2lVDL+svFQVXgXrEGBMG2puMVN3gq2SNGuTGw==} + engines: {node: '>=20.0.0'} smob@1.5.0: resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} @@ -287,8 +289,8 @@ packages: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} - terser@5.46.0: - resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==} + terser@5.49.2: + resolution: {integrity: sha512-rGbJiKeQ4WDe3EXlDAIaQcwftVfv2Q8o1awFNfvXolJYKkb1AuZY1RTOmqx4LJXZENbWZA7eIsYGHuEzHsi1nQ==} engines: {node: '>=10'} hasBin: true @@ -313,90 +315,93 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@rollup/plugin-terser@0.4.4(rollup@4.57.1)': + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + optional: true + + '@rollup/plugin-terser@1.0.0(rollup@4.62.4)': dependencies: - serialize-javascript: 6.0.2 + serialize-javascript: 7.1.0 smob: 1.5.0 - terser: 5.46.0 + terser: 5.49.2 optionalDependencies: - rollup: 4.57.1 + rollup: 4.62.4 - '@rollup/rollup-android-arm-eabi@4.57.1': + '@rollup/rollup-android-arm-eabi@4.62.4': optional: true - '@rollup/rollup-android-arm64@4.57.1': + '@rollup/rollup-android-arm64@4.62.4': optional: true - '@rollup/rollup-darwin-arm64@4.57.1': + '@rollup/rollup-darwin-arm64@4.62.4': optional: true - '@rollup/rollup-darwin-x64@4.57.1': + '@rollup/rollup-darwin-x64@4.62.4': optional: true - '@rollup/rollup-freebsd-arm64@4.57.1': + '@rollup/rollup-freebsd-arm64@4.62.4': optional: true - '@rollup/rollup-freebsd-x64@4.57.1': + '@rollup/rollup-freebsd-x64@4.62.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + '@rollup/rollup-linux-arm-gnueabihf@4.62.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.57.1': + '@rollup/rollup-linux-arm-musleabihf@4.62.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.57.1': + '@rollup/rollup-linux-arm64-gnu@4.62.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.57.1': + '@rollup/rollup-linux-arm64-musl@4.62.4': optional: true - '@rollup/rollup-linux-loong64-gnu@4.57.1': + '@rollup/rollup-linux-loong64-gnu@4.62.4': optional: true - '@rollup/rollup-linux-loong64-musl@4.57.1': + '@rollup/rollup-linux-loong64-musl@4.62.4': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.57.1': + '@rollup/rollup-linux-ppc64-gnu@4.62.4': optional: true - '@rollup/rollup-linux-ppc64-musl@4.57.1': + '@rollup/rollup-linux-ppc64-musl@4.62.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.57.1': + '@rollup/rollup-linux-riscv64-gnu@4.62.4': optional: true - '@rollup/rollup-linux-riscv64-musl@4.57.1': + '@rollup/rollup-linux-riscv64-musl@4.62.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.57.1': + '@rollup/rollup-linux-s390x-gnu@4.62.4': optional: true - '@rollup/rollup-linux-x64-gnu@4.57.1': + '@rollup/rollup-linux-x64-gnu@4.62.4': optional: true - '@rollup/rollup-linux-x64-musl@4.57.1': + '@rollup/rollup-linux-x64-musl@4.62.4': optional: true - '@rollup/rollup-openbsd-x64@4.57.1': + '@rollup/rollup-openbsd-x64@4.62.4': optional: true - '@rollup/rollup-openharmony-arm64@4.57.1': + '@rollup/rollup-openharmony-arm64@4.62.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.57.1': + '@rollup/rollup-win32-arm64-msvc@4.62.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.57.1': + '@rollup/rollup-win32-ia32-msvc@4.62.4': optional: true - '@rollup/rollup-win32-x64-gnu@4.57.1': + '@rollup/rollup-win32-x64-gnu@4.62.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.57.1': + '@rollup/rollup-win32-x64-msvc@4.62.4': optional: true - '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} acorn@8.15.0: {} @@ -451,51 +456,44 @@ snapshots: dependencies: number-is-nan: 1.0.1 - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - rollup-plugin-bundle-size@1.0.3: dependencies: chalk: 1.1.3 maxmin: 2.1.0 - rollup@4.57.1: + rollup@4.62.4: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.57.1 - '@rollup/rollup-android-arm64': 4.57.1 - '@rollup/rollup-darwin-arm64': 4.57.1 - '@rollup/rollup-darwin-x64': 4.57.1 - '@rollup/rollup-freebsd-arm64': 4.57.1 - '@rollup/rollup-freebsd-x64': 4.57.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 - '@rollup/rollup-linux-arm-musleabihf': 4.57.1 - '@rollup/rollup-linux-arm64-gnu': 4.57.1 - '@rollup/rollup-linux-arm64-musl': 4.57.1 - '@rollup/rollup-linux-loong64-gnu': 4.57.1 - '@rollup/rollup-linux-loong64-musl': 4.57.1 - '@rollup/rollup-linux-ppc64-gnu': 4.57.1 - '@rollup/rollup-linux-ppc64-musl': 4.57.1 - '@rollup/rollup-linux-riscv64-gnu': 4.57.1 - '@rollup/rollup-linux-riscv64-musl': 4.57.1 - '@rollup/rollup-linux-s390x-gnu': 4.57.1 - '@rollup/rollup-linux-x64-gnu': 4.57.1 - '@rollup/rollup-linux-x64-musl': 4.57.1 - '@rollup/rollup-openbsd-x64': 4.57.1 - '@rollup/rollup-openharmony-arm64': 4.57.1 - '@rollup/rollup-win32-arm64-msvc': 4.57.1 - '@rollup/rollup-win32-ia32-msvc': 4.57.1 - '@rollup/rollup-win32-x64-gnu': 4.57.1 - '@rollup/rollup-win32-x64-msvc': 4.57.1 + '@napi-rs/lzma-linux-x64-gnu': 1.5.1 + '@rollup/rollup-android-arm-eabi': 4.62.4 + '@rollup/rollup-android-arm64': 4.62.4 + '@rollup/rollup-darwin-arm64': 4.62.4 + '@rollup/rollup-darwin-x64': 4.62.4 + '@rollup/rollup-freebsd-arm64': 4.62.4 + '@rollup/rollup-freebsd-x64': 4.62.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.4 + '@rollup/rollup-linux-arm-musleabihf': 4.62.4 + '@rollup/rollup-linux-arm64-gnu': 4.62.4 + '@rollup/rollup-linux-arm64-musl': 4.62.4 + '@rollup/rollup-linux-loong64-gnu': 4.62.4 + '@rollup/rollup-linux-loong64-musl': 4.62.4 + '@rollup/rollup-linux-ppc64-gnu': 4.62.4 + '@rollup/rollup-linux-ppc64-musl': 4.62.4 + '@rollup/rollup-linux-riscv64-gnu': 4.62.4 + '@rollup/rollup-linux-riscv64-musl': 4.62.4 + '@rollup/rollup-linux-s390x-gnu': 4.62.4 + '@rollup/rollup-linux-x64-gnu': 4.62.4 + '@rollup/rollup-linux-x64-musl': 4.62.4 + '@rollup/rollup-openbsd-x64': 4.62.4 + '@rollup/rollup-openharmony-arm64': 4.62.4 + '@rollup/rollup-win32-arm64-msvc': 4.62.4 + '@rollup/rollup-win32-ia32-msvc': 4.62.4 + '@rollup/rollup-win32-x64-gnu': 4.62.4 + '@rollup/rollup-win32-x64-msvc': 4.62.4 fsevents: 2.3.3 - safe-buffer@5.2.1: {} - - serialize-javascript@6.0.2: - dependencies: - randombytes: 2.1.0 + serialize-javascript@7.1.0: {} smob@1.5.0: {} @@ -512,7 +510,7 @@ snapshots: supports-color@2.0.0: {} - terser@5.46.0: + terser@5.49.2: dependencies: '@jridgewell/source-map': 0.3.11 acorn: 8.15.0 From 4e8431c7f50d476790fdadfad67612b94ae06b5f Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 9 Aug 2026 15:07:51 +0500 Subject: [PATCH 7/9] Fix solution reference for rollup config rename Update file reference to match the renamed rollup.config.js, which was overlooked when the extension was changed from .mjs --- Ramstack.HtmxToolkit.slnx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Ramstack.HtmxToolkit.slnx b/Ramstack.HtmxToolkit.slnx index 49a153d..ecb0b2f 100644 --- a/Ramstack.HtmxToolkit.slnx +++ b/Ramstack.HtmxToolkit.slnx @@ -6,7 +6,7 @@ - + From ed5941d3a94657e11c227c4d79895a64e654df68 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 9 Aug 2026 18:27:35 +0500 Subject: [PATCH 8/9] Add source-generated JSON serialization where possible --- .../Ramstack.HtmxToolkit.csproj | 2 +- .../HtmxConfigJsonSerializerContext.cs | 14 +++++++++++ .../TagHelpers/HtmxConfigTagHelper.cs | 23 +++++++++++++------ .../HtmxHeaderJsonSerializerContext.cs | 9 ++++++++ .../TagHelpers/HtmxHeaderTagHelper.cs | 4 +--- 5 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigJsonSerializerContext.cs create mode 100644 src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderJsonSerializerContext.cs diff --git a/src/Ramstack.HtmxToolkit/Ramstack.HtmxToolkit.csproj b/src/Ramstack.HtmxToolkit/Ramstack.HtmxToolkit.csproj index bfb969f..f9b5bec 100644 --- a/src/Ramstack.HtmxToolkit/Ramstack.HtmxToolkit.csproj +++ b/src/Ramstack.HtmxToolkit/Ramstack.HtmxToolkit.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0 Enables seamless integration of HTMX with ASP.NET Core (https://htmx.org). enable enable diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigJsonSerializerContext.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigJsonSerializerContext.cs new file mode 100644 index 0000000..ef77bad --- /dev/null +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigJsonSerializerContext.cs @@ -0,0 +1,14 @@ +#if NET8_0_OR_GREATER +using System.Text.Json.Serialization; + +namespace Ramstack.HtmxToolkit.TagHelpers; + +[JsonSourceGenerationOptions( + WriteIndented = false, + PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + GenerationMode = JsonSourceGenerationMode.Serialization)] +[JsonSerializable(typeof(HtmxConfigTagHelper.HtmxConfiguration))] +[JsonSerializable(typeof(HtmxConfigTagHelper.AntiForgeryTokenData))] +internal partial class HtmxConfigJsonSerializerContext : JsonSerializerContext; +#endif diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs index 877b705..5d6eba4 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs @@ -19,6 +19,8 @@ namespace Ramstack.HtmxToolkit.TagHelpers; [HtmlTargetElement("htmx-config", TagStructure = TagStructure.WithoutEndTag)] public sealed class HtmxConfigTagHelper(IAntiforgery antiforgery) : TagHelper { + private readonly IAntiforgery _antiforgery = antiforgery; + /// /// Gets or sets a value indicating whether history is enabled. /// Defaults to . @@ -263,10 +265,17 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp output.Attributes.SetAttribute("name", "htmx-config"); + #if NET8_0_OR_GREATER + var config = new HtmlString( + JsonSerializer.Serialize( + new HtmxConfiguration(this), + HtmxConfigJsonSerializerContext.Default.HtmxConfiguration)); + #else var config = new HtmlString( JsonSerializer.Serialize( - new HtmxConfiguration(this, antiforgery), + new HtmxConfiguration(this), JsonOptions.CamelCase)); + #endif output.Attributes.SetAttribute( new TagHelperAttribute("content", config, HtmlAttributeValueStyle.SingleQuotes)); @@ -280,7 +289,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp /// Represents a proxy structure for the class. /// [SuppressMessage("ReSharper", "UnusedMember.Local")] - private readonly struct HtmxConfiguration(HtmxConfigTagHelper helper, IAntiforgery antiforgery) + internal readonly struct HtmxConfiguration(HtmxConfigTagHelper helper) { public bool? HistoryEnabled => helper.HistoryEnabled; public int? HistoryCacheSize => helper.HistoryCacheSize; @@ -313,11 +322,11 @@ private readonly struct HtmxConfiguration(HtmxConfigTagHelper helper, IAntiforge public bool? IgnoreTitle => helper.IgnoreTitle; public bool? ScrollIntoViewOnBoost => helper.ScrollIntoViewOnBoost; public string? TriggerSpecsCache => helper.TriggerSpecsCache; - public AntiForgeryTokenData? AntiForgery => GetAntiForgeryToken(); + public AntiForgeryTokenData? AntiForgery => GetAntiForgeryToken(helper); - private AntiForgeryTokenData? GetAntiForgeryToken() => - helper.IncludeAntiForgeryToken - ? new AntiForgeryTokenData(antiforgery.GetAndStoreTokens(helper.ViewContext.HttpContext)) + private static AntiForgeryTokenData? GetAntiForgeryToken(HtmxConfigTagHelper h) => + h.IncludeAntiForgeryToken + ? new AntiForgeryTokenData(h._antiforgery.GetAndStoreTokens(h.ViewContext.HttpContext)) : null; } @@ -329,7 +338,7 @@ private readonly struct HtmxConfiguration(HtmxConfigTagHelper helper, IAntiforge /// Represents a proxy structure for the class. /// [SuppressMessage("ReSharper", "UnusedMember.Local")] - private readonly struct AntiForgeryTokenData(AntiforgeryTokenSet antiforgery) + internal readonly struct AntiForgeryTokenData(AntiforgeryTokenSet antiforgery) { public string? HeaderName => antiforgery.HeaderName; public string FormFieldName => antiforgery.FormFieldName; diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderJsonSerializerContext.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderJsonSerializerContext.cs new file mode 100644 index 0000000..b1a5bd9 --- /dev/null +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderJsonSerializerContext.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace Ramstack.HtmxToolkit.TagHelpers; + +[JsonSerializable(typeof(Dictionary))] +[JsonSourceGenerationOptions( + WriteIndented = false, + GenerationMode = JsonSourceGenerationMode.Serialization)] +internal partial class HtmxHeaderJsonSerializerContext : JsonSerializerContext; diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs index 983e588..bf27c73 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs @@ -3,8 +3,6 @@ using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Razor.TagHelpers; -using Ramstack.HtmxToolkit.Internal; - namespace Ramstack.HtmxToolkit.TagHelpers; /// @@ -33,7 +31,7 @@ public sealed class HtmxHeaderTagHelper : TagHelper public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { var headers = new HtmlString( - JsonSerializer.Serialize(Headers, JsonOptions.PreserveKeyCase)); + JsonSerializer.Serialize(Headers, HtmxHeaderJsonSerializerContext.Default.DictionaryStringString)); output.Attributes.SetAttribute( new TagHelperAttribute("hx-headers", headers, HtmlAttributeValueStyle.SingleQuotes)); From c05fd141257a713af3319959c4e5c29447bac672 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 9 Aug 2026 18:50:31 +0500 Subject: [PATCH 9/9] Fix default-settle-delay documentation --- src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs index 5d6eba4..a7567fc 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs @@ -57,7 +57,7 @@ public sealed class HtmxConfigTagHelper(IAntiforgery antiforgery) : TagHelper public int? DefaultSwapDelay { get; set; } /// - /// Gets or sets the default settle delay. Defaults to 100. + /// Gets or sets the default settle delay. Defaults to 20. /// [HtmlAttributeName("default-settle-delay")] public int? DefaultSettleDelay { get; set; }