From 6fb073e226f7aea94679607c227d231b8f238737 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 30 Aug 2026 13:34:03 +0500 Subject: [PATCH 1/4] Refine XML documentation --- src/Ramstack.HtmxToolkit/ActionResultExtensions.cs | 14 +++++++------- .../Builder/EndpointRouteBuilderExtensions.cs | 2 +- .../HtmxHistoryModeJsonConverter.cs | 2 +- src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs | 6 +++--- src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs | 4 ++-- src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs | 2 +- src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs | 2 +- .../HtmxResponseHeaderNames.cs | 4 ++-- src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs | 2 +- src/Ramstack.HtmxToolkit/HtmxResult.cs | 4 ++-- src/Ramstack.HtmxToolkit/HtmxResult`1.cs | 4 ++-- .../HtmxTriggerSpecsCacheJsonConverter.cs | 2 +- src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs | 4 ++-- src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs | 14 +++++++------- src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs | 10 +++++----- src/Ramstack.HtmxToolkit/HttpVerb.cs | 2 +- src/Ramstack.HtmxToolkit/PendingEvents.cs | 2 +- .../TagHelpers/HtmxRequestTagHelper.cs | 2 +- .../TagHelpers/HtmxUrlTagHelper.cs | 2 +- .../TagHelpers/ResponseHandlingConfig.cs | 4 ++-- 20 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/Ramstack.HtmxToolkit/ActionResultExtensions.cs b/src/Ramstack.HtmxToolkit/ActionResultExtensions.cs index 1fbda14..be5f164 100644 --- a/src/Ramstack.HtmxToolkit/ActionResultExtensions.cs +++ b/src/Ramstack.HtmxToolkit/ActionResultExtensions.cs @@ -3,30 +3,30 @@ namespace Ramstack.HtmxToolkit; /// -/// Provides extension methods for to configure htmx response headers. +/// Provides extension methods for to configure HTMX response headers. /// public static class ActionResultExtensions { /// - /// Configures htmx response headers for the specified . + /// Configures HTMX response headers for the specified . /// /// The to configure. - /// A delegate to configure the htmx response headers. + /// A delegate to configure the HTMX response headers. /// - /// An that wraps the original result with htmx configuration. + /// An that wraps the original result with HTMX configuration. /// public static HtmxResult Htmx(this IActionResult result, Action configure) => new(result, configure); /// - /// Configures htmx response headers for the specified using a state object. + /// Configures HTMX response headers for the specified using a state object. /// /// The type of the state object passed to the configuration delegate. /// The to configure. - /// A delegate to configure the htmx response headers using the state object. + /// A delegate to configure the HTMX response headers using the state object. /// The state object passed to the delegate. /// - /// An that wraps the original result with htmx configuration. + /// An that wraps the original result with HTMX configuration. /// public static HtmxResult Htmx(this IActionResult result, Action configure, TState state) => new(result, configure, state); diff --git a/src/Ramstack.HtmxToolkit/Builder/EndpointRouteBuilderExtensions.cs b/src/Ramstack.HtmxToolkit/Builder/EndpointRouteBuilderExtensions.cs index 158cc7d..e3dd735 100644 --- a/src/Ramstack.HtmxToolkit/Builder/EndpointRouteBuilderExtensions.cs +++ b/src/Ramstack.HtmxToolkit/Builder/EndpointRouteBuilderExtensions.cs @@ -11,7 +11,7 @@ namespace Ramstack.HtmxToolkit.Builder; public static class EndpointRouteBuilderExtensions { /// - /// Gets the default path to the htmx anti-forgery script asset. + /// Gets the default path to the HTMX antiforgery script asset. /// internal static string AssetPath { get; private set; } = $"/htmxtoolkit/{HtmxAssets.Hash}"; diff --git a/src/Ramstack.HtmxToolkit/HtmxHistoryModeJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxHistoryModeJsonConverter.cs index 285c00f..b16ef1f 100644 --- a/src/Ramstack.HtmxToolkit/HtmxHistoryModeJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxHistoryModeJsonConverter.cs @@ -13,7 +13,7 @@ namespace Ramstack.HtmxToolkit; /// /// Unlike other enum values, which are serialized as strings, this one requires a custom /// converter: and -/// must be written as actual JSON booleans rather than strings, since otherwise htmx +/// must be written as actual JSON booleans rather than strings, since otherwise HTMX /// would not recognize them. /// internal sealed class HtmxHistoryModeJsonConverter : JsonConverter diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs b/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs index dee1b2a..3b615ab 100644 --- a/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs +++ b/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs @@ -3,7 +3,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Identifies an action that supports htmx requests. +/// Identifies an action that supports HTMX requests. /// [AttributeUsage(AttributeTargets.Method)] public sealed class HtmxRequestAttribute : Attribute, IActionConstraint @@ -13,13 +13,13 @@ public sealed class HtmxRequestAttribute : Attribute, IActionConstraint /// /// Gets or sets a value that indicates whether the action should be executed - /// for boosted or non-boosted htmx requests. + /// for boosted or non-boosted HTMX requests. /// /// /// /// If set to , the action will be executed only for boosted requests. /// If set to , the action will be executed only for non-boosted requests. - /// If set to , the action will be executed for any htmx request. + /// If set to , the action will be executed for any HTMX request. /// /// public bool? Boosted { get; set; } diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs b/src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs index 8cb4e1f..f297dad 100644 --- a/src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs +++ b/src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs @@ -1,7 +1,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Defines constants for the well-known names of htmx request headers. +/// Defines constants for the well-known names of HTMX request headers. /// For more information, see https://htmx.org/reference/#request_headers /// public static class HtmxRequestHeaderNames @@ -29,7 +29,7 @@ public static class HtmxRequestHeaderNames public const string Prompt = "HX-Prompt"; /// - /// The HX-Request header is a general header sent with every htmx request. + /// The HX-Request header is a general header sent with every HTMX request. /// Always "true". /// public const string Request = "HX-Request"; diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs b/src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs index 9e12bf2..e02f809 100644 --- a/src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs +++ b/src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs @@ -40,7 +40,7 @@ internal HtmxRequestHeaders(HttpRequest request) => public bool HistoryRestoreRequest => GetBoolean(_headers, HtmxRequestHeaderNames.HistoryRestoreRequest); /// - /// Gets the user response to "hx-prompt" on the client. + /// Gets the user's response to an hx-prompt on the client. /// /// public string? Prompt => GetString(_headers, HtmxRequestHeaderNames.Prompt); diff --git a/src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs b/src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs index 622d8a8..6d89057 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs @@ -8,7 +8,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Identifies an action that sets htmx response headers. +/// Identifies an action that sets HTMX response headers. /// [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] public sealed class HtmxResponseAttribute : Attribute, IResultFilter diff --git a/src/Ramstack.HtmxToolkit/HtmxResponseHeaderNames.cs b/src/Ramstack.HtmxToolkit/HtmxResponseHeaderNames.cs index 66ea317..5203ded 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResponseHeaderNames.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResponseHeaderNames.cs @@ -1,7 +1,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Defines constants for the well-known names of htmx response headers. +/// Defines constants for the well-known names of HTMX response headers. /// For more information, see https://htmx.org/reference/#response_headers /// public static class HtmxResponseHeaderNames @@ -57,7 +57,7 @@ public static class HtmxResponseHeaderNames /// /// The HX-Trigger-After-Settle header is used to trigger an event - /// on the client side after the htmx request has settled. + /// on the client side after the HTMX request has settled. /// public const string TriggerAfterSettle = "HX-Trigger-After-Settle"; diff --git a/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs b/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs index dae0d05..82eef4c 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs @@ -145,7 +145,7 @@ public IReadOnlyDictionary TriggerAfterSwap /// /// Gets or sets the HX-Trigger-After-Settle header, which specifies a dictionary of client-side events - /// to trigger after the htmx request has settled. + /// to trigger after the HTMX request has settled. /// /// /// Event values are accumulated for the current response and serialized into the header immediately diff --git a/src/Ramstack.HtmxToolkit/HtmxResult.cs b/src/Ramstack.HtmxToolkit/HtmxResult.cs index f2f0791..b806f27 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResult.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResult.cs @@ -3,10 +3,10 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents an that is used to configure the htmx response headers. +/// Represents an that is used to configure the HTMX response headers. /// /// The to produce the response result. -/// The function to configure the htmx response headers. +/// The function to configure the HTMX response headers. public sealed class HtmxResult(IActionResult result, Action configure) : IActionResult { /// diff --git a/src/Ramstack.HtmxToolkit/HtmxResult`1.cs b/src/Ramstack.HtmxToolkit/HtmxResult`1.cs index 15ddb54..a1925fd 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResult`1.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResult`1.cs @@ -3,11 +3,11 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents an that is used to configure the htmx response headers. +/// Represents an that is used to configure the HTMX response headers. /// /// The type of the value to pass to . Used to reduce memory allocations. /// The to produce the response result. -/// The function to configure the htmx response headers. +/// The function to configure the HTMX response headers. /// The value to pass to . public sealed class HtmxResult(IActionResult result, Action configure, TState state) : IActionResult { diff --git a/src/Ramstack.HtmxToolkit/HtmxTriggerSpecsCacheJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxTriggerSpecsCacheJsonConverter.cs index 1ab32d3..a409d13 100644 --- a/src/Ramstack.HtmxToolkit/HtmxTriggerSpecsCacheJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxTriggerSpecsCacheJsonConverter.cs @@ -6,7 +6,7 @@ namespace Ramstack.HtmxToolkit; /// /// Represents a that serializes the triggerSpecsCache /// configuration option from its boolean form: is written as an empty -/// JSON object ({}), instructing htmx to use a never-clearing trigger specification cache, +/// JSON object ({}), instructing HTMX to use a never-clearing trigger specification cache, /// while and are written as JSON null. /// internal sealed class HtmxTriggerSpecsCacheJsonConverter : JsonConverter diff --git a/src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs b/src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs index 7887762..2137f4d 100644 --- a/src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs +++ b/src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs @@ -1,7 +1,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Specifies the time at which an event will be triggered in htmx. +/// Specifies the time at which an event will be triggered in HTMX. /// public enum HtmxTriggerTiming { @@ -19,7 +19,7 @@ public enum HtmxTriggerTiming /// /// Maps to the HX-Trigger-After-Settle header that is used to trigger an event - /// on the client side after the htmx request has settled. + /// on the client side after the HTMX request has settled. /// AfterSettle } diff --git a/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs b/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs index 272f5f2..e1ae5a6 100644 --- a/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs +++ b/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs @@ -8,24 +8,24 @@ namespace Ramstack.HtmxToolkit; public static class HttpRequestExtensions { /// - /// Determines whether the specified HTTP request is htmx request. + /// Determines whether the specified HTTP request is an HTMX request. /// /// The HTTP request. /// - /// if the specified HTTP request is htmx request; + /// if the specified HTTP request is an HTMX request; /// otherwise, . /// public static bool IsHtmxRequest(this HttpRequest request) => request.Headers.ContainsKey(HtmxRequestHeaderNames.Request); /// - /// Determines whether the specified HTTP request is htmx request. + /// Determines whether the specified HTTP request is an HTMX request. /// /// The HTTP request. /// When this method returns, contains the - /// that provides well-known htmx headers. + /// that provides access to well-known HTMX headers. /// - /// if the specified HTTP request is htmx request; otherwise, . + /// if the specified HTTP request is an HTMX request; otherwise, . /// public static bool IsHtmxRequest(this HttpRequest request, out HtmxRequestHeaders headers) { @@ -49,7 +49,7 @@ public static bool IsHtmxBoosted(this HttpRequest request) => /// /// The HTTP request. /// When this method returns, contains the - /// that provides well-known htmx headers. + /// that provides access to well-known HTMX headers. /// /// if the specified HTTP request is boosted; otherwise, . /// @@ -60,7 +60,7 @@ public static bool IsHtmxBoosted(this HttpRequest request, out HtmxRequestHeader } /// - /// Returns the that provides well-known htmx headers. + /// Returns the that provides access to well-known HTMX headers. /// /// The HTTP request. /// diff --git a/src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs b/src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs index c0e06b8..7cc2cc8 100644 --- a/src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs +++ b/src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs @@ -8,7 +8,7 @@ namespace Ramstack.HtmxToolkit; public static class HttpResponseExtensions { /// - /// Returns the that provides well-known htmx headers. + /// Returns the that provides access to well-known HTMX headers. /// /// The HTTP response. /// @@ -18,10 +18,10 @@ public static HtmxResponseHeaders GetHtmxHeaders(this HttpResponse response) => new(response); /// - /// Configures the htmx response headers. + /// Configures the HTMX response headers. /// /// The HTTP response to configure. - /// The function to configure the htmx response headers. + /// The function to configure the HTMX response headers. public static void Htmx(this HttpResponse response, Action configure) { if (response.HttpContext.Request.IsHtmxRequest()) @@ -29,10 +29,10 @@ public static void Htmx(this HttpResponse response, Action configu } /// - /// Configures the htmx response headers. + /// Configures the HTMX response headers. /// /// The HTTP response to configure. - /// The function to configure the htmx response headers. + /// The function to configure the HTMX response headers. /// The value to pass to the . public static void Htmx(this HttpResponse response, Action configure, TState state) { diff --git a/src/Ramstack.HtmxToolkit/HttpVerb.cs b/src/Ramstack.HtmxToolkit/HttpVerb.cs index 4e68ca0..de04385 100644 --- a/src/Ramstack.HtmxToolkit/HttpVerb.cs +++ b/src/Ramstack.HtmxToolkit/HttpVerb.cs @@ -1,7 +1,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Defines the HTTP methods that can be used in htmx configuration. +/// Defines the HTTP methods that can be used in HTMX configuration. /// public enum HttpVerb { diff --git a/src/Ramstack.HtmxToolkit/PendingEvents.cs b/src/Ramstack.HtmxToolkit/PendingEvents.cs index 0179884..5f4eac2 100644 --- a/src/Ramstack.HtmxToolkit/PendingEvents.cs +++ b/src/Ramstack.HtmxToolkit/PendingEvents.cs @@ -8,7 +8,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Accumulates htmx events per for a single request, +/// Accumulates HTMX events per for a single request, /// deferring header serialization until the response is about to start. /// internal sealed class PendingEvents diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestTagHelper.cs index bd21571..00d9257 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestTagHelper.cs @@ -70,7 +70,7 @@ public HtmxRequestCredentials? Credentials } /// - /// Gets or sets a value indicating whether htmx strips all request headers. + /// Gets or sets a value indicating whether HTMX strips all request headers. /// /// Supported in HTMX 1.x and 2.x. Removed in HTMX 4.x. [HtmlAttributeName(RequestNoHeadersAttributeName)] diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs index 87f2891..c9fa704 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs @@ -13,7 +13,7 @@ namespace Ramstack.HtmxToolkit.TagHelpers; /// /// Represents a implementation -/// used to generate URIs for htmx actions on matching elements. +/// used to generate URIs for HTMX actions on matching elements. /// /// The . [HtmlTargetElement(Attributes = ActionAttributeName)] diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/ResponseHandlingConfig.cs b/src/Ramstack.HtmxToolkit/TagHelpers/ResponseHandlingConfig.cs index e7d2974..b360412 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/ResponseHandlingConfig.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/ResponseHandlingConfig.cs @@ -16,12 +16,12 @@ public sealed class ResponseHandlingConfig public bool? Swap { get; set; } /// - /// Gets or sets a value indicating whether htmx should treat this response as an error. + /// Gets or sets a value indicating whether HTMX should treat this response as an error. /// public bool? Error { get; set; } /// - /// Gets or sets a value indicating whether htmx should ignore title tags in the response. + /// Gets or sets a value indicating whether HTMX should ignore title tags in the response. /// public bool? IgnoreTitle { get; set; } From cadf522d2f7248fa8170fe53f1e1ecf6ce2f6c30 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 30 Aug 2026 13:34:59 +0500 Subject: [PATCH 2/4] Fix README examples --- README.md | 327 +++++++++++++++++++++++++++++------------------------- 1 file changed, 174 insertions(+), 153 deletions(-) diff --git a/README.md b/README.md index f099fb6..0d1908a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Provides HTMX integration for ASP.NET Core applications. * [HtmxRequestAttribute](#htmxrequestattribute) * [HttpResponse](#httpresponse) * [The declarative way of setting response headers](#the-declarative-way-of-setting-response-headers) - * [TagHelpers](#taghelpers) + * [Tag Helpers](#tag-helpers) * [HtmxUrlTagHelper](#htmxurltaghelper) * [HtmxHeaderTagHelper](#htmxheadertaghelper) * [HtmxValsTagHelper](#htmxvalstaghelper) @@ -26,8 +26,8 @@ Provides HTMX integration for ASP.NET Core applications. ## Getting Started -Install `Ramstack.HtmxToolkit` [NuGet package](https://www.nuget.org/packages/Ramstack.HtmxToolkit/) to your project, -use the following command +Add the [`Ramstack.HtmxToolkit` NuGet package](https://www.nuget.org/packages/Ramstack.HtmxToolkit/) +to your project with the following command: ```console dotnet add package Ramstack.HtmxToolkit @@ -56,8 +56,7 @@ builder.Services.AddHtmxToolkit(); ## HttpRequest -The library provides a set of classes for working with `HttpRequest`. -First off, there's the `HttpRequestExtensions` class. +The library provides the `HttpRequestExtensions` class for working with `HttpRequest`. ```csharp /// @@ -66,22 +65,23 @@ First off, there's the `HttpRequestExtensions` class. public static class HttpRequestExtensions { /// - /// Determines whether the specified HTTP request is htmx request. + /// Determines whether the specified HTTP request is an HTMX request. /// /// The HTTP request. /// - /// true if the specified HTTP request is htmx request; otherwise, false. + /// if the specified HTTP request is an HTMX request; + /// otherwise, . /// public static bool IsHtmxRequest(this HttpRequest request); /// - /// Determines whether the specified HTTP request is htmx request. + /// Determines whether the specified HTTP request is an HTMX request. /// /// The HTTP request. - /// When this methods returns, contains the - /// that provides well-known htmx headers. + /// When this method returns, contains the + /// that provides access to well-known HTMX headers. /// - /// true if the specified HTTP request is htmx request; otherwise, false. + /// if the specified HTTP request is an HTMX request; otherwise, . /// public static bool IsHtmxRequest(this HttpRequest request, out HtmxRequestHeaders headers); @@ -91,7 +91,7 @@ public static class HttpRequestExtensions /// /// The HTTP request. /// - /// true if the specified HTTP request is boosted; otherwise, false. + /// if the specified HTTP request is boosted; otherwise, . /// public static bool IsHtmxBoosted(this HttpRequest request); @@ -100,15 +100,15 @@ public static class HttpRequestExtensions /// instead of a normal navigation. /// /// The HTTP request. - /// When this methods returns, contains the - /// that provides well-known htmx headers. + /// When this method returns, contains the + /// that provides access to well-known HTMX headers. /// - /// true if the specified HTTP request is boosted; otherwise, false. + /// if the specified HTTP request is boosted; otherwise, . /// public static bool IsHtmxBoosted(this HttpRequest request, out HtmxRequestHeaders headers); /// - /// Returns the that provides well-known htmx headers. + /// Returns the that provides access to well-known HTMX headers. /// /// The HTTP request. /// @@ -118,13 +118,13 @@ public static class HttpRequestExtensions } ``` -The `IsHtmxRequest` method allows you to determine whether the current request is initiated by HTMX. +Use `IsHtmxRequest` to determine whether the current request was issued by HTMX. ```csharp HttpContext.Request.IsHtmxRequest() ``` -And thus, you can define different scenarios depending on the result, for example: +You can then handle HTMX and regular requests differently, for example: ```csharp if (Request.IsHtmxRequest()) @@ -133,7 +133,7 @@ if (Request.IsHtmxRequest()) return View(); ``` -The overloads of these methods provide access to strongly typed headers set by HTMX: +The overloads with an `out` parameter also provide access to strongly typed headers set by HTMX: ```csharp if (Request.IsHtmxRequest(out var headers)) @@ -145,13 +145,13 @@ if (Request.IsHtmxRequest(out var headers)) } ``` -In addition, access to strongly typed headers can be obtained by calling `GetHtmxHeaders`: +You can also access strongly typed headers by calling `GetHtmxHeaders`: ```csharp var headers = Request.GetHtmxHeaders(); ``` -The full list of headers is presented below: +The complete set of request header properties is shown below: ```csharp /// @@ -160,8 +160,7 @@ The full list of headers is presented below: public readonly struct HtmxRequestHeaders { /// - /// Gets a value indicating whether the request - /// was made using AJAX instead of a normal navigation. + /// Gets a value indicating whether the request was made using AJAX instead of a normal navigation. /// public bool Boosted { get; } @@ -171,18 +170,17 @@ public readonly struct HtmxRequestHeaders public string? CurrentUrl { get; } /// - /// Gets a value indicating whether the request - /// is for history restoration after a miss in the local history cache. + /// Gets a value indicating whether the request is for history restoration after a miss in the local history cache. /// public bool HistoryRestoreRequest { get; } /// - /// Gets the user response to an hx-prompt on the client. + /// Gets the user's response to an hx-prompt on the client. /// public string? Prompt { get; } /// - /// Gets a value indicating whether the current request is htmx request. + /// Gets a value indicating whether the current request is an HTMX request. /// public bool Request { get; } @@ -197,29 +195,27 @@ public readonly struct HtmxRequestHeaders public string? TriggerName { get; } /// - /// Gets the ID of the triggered element if it exists - /// as indicated by the HX-Trigger header. + /// Gets the ID of the triggered element if it exists as indicated by the HX-Trigger header. /// public string? Trigger { get; } } ``` -Example of usage: +For example: ```csharp -if (Request.GetHtmxHeaders().HistoryRestoreRequests) +if (Request.GetHtmxHeaders().HistoryRestoreRequest) { ... } ``` -The library also provides a set of predefined string constants for request headers, -so you don't have to remember them each time and risk making mistakes in spelling. -You can find them in the `HtmxRequestHeaderNames` class. +The `HtmxRequestHeaderNames` class also provides constants for well-known request header names, +so you do not have to remember their exact spelling. ```csharp /// -/// Defines constants for the well-known names of htmx request headers. +/// Defines constants for the well-known names of HTMX request headers. /// For more information, see https://htmx.org/reference/#request_headers /// public static class HtmxRequestHeaderNames @@ -242,11 +238,11 @@ public static class HtmxRequestHeaderNames ### HtmxRequestAttribute -To simplify some manual checks, the library provides an ASP.NET Core result filter -that can be applied to an action controller, page handler, or the entire controller: +To route HTMX requests to a specific controller action, apply the `HtmxRequestAttribute` +action constraint to that action: ```csharp -public class UserController : ControlleBase +public class UserController : ControllerBase { [HtmxRequest] public IActionResult UpdateProfile(UserProfile profile) @@ -256,10 +252,10 @@ public class UserController : ControlleBase } ``` -If you are processing boosted requests in a special way, add the `Boosted` parameter. +To match only boosted requests, set the `Boosted` property to `true`: ```csharp -public class UserController : ControlleBase +public class UserController : ControllerBase { ... [HtmxRequest(Boosted = true)] @@ -272,8 +268,7 @@ public class UserController : ControlleBase ## HttpResponse -For working with response headers, the library also provides a set of classes. -The first one is the `HttpResponseExtension` class with extension methods: +For working with response headers, the library provides the `HttpResponseExtensions` class: ```csharp /// @@ -282,7 +277,7 @@ The first one is the `HttpResponseExtension` class with extension methods: public static class HttpResponseExtensions { /// - /// Returns the that provides well-known htmx headers. + /// Returns the that provides access to well-known HTMX headers. /// /// The HTTP response. /// @@ -291,17 +286,17 @@ public static class HttpResponseExtensions public static HtmxResponseHeaders GetHtmxHeaders(this HttpResponse response); /// - /// Configures the htmx response headers. + /// Configures the HTMX response headers. /// /// The HTTP response to configure. - /// The function to configure the htmx response headers. + /// The function to configure the HTMX response headers. public static void Htmx(this HttpResponse response, Action configure); /// - /// Configures the htmx response headers. + /// Configures the HTMX response headers. /// /// The HTTP response to configure. - /// The function to configure the htmx response headers. + /// The function to configure the HTMX response headers. /// The value to pass to the . public static void Htmx(this HttpResponse response, Action configure, TState state); } @@ -317,14 +312,13 @@ that control HTMX behavior. public readonly struct HtmxResponseHeaders { /// - /// Gets or sets the HX-Location header to a client-side redirect - /// that does not do a full page reload. + /// Gets or sets the HX-Location header to perform a client-side redirect without a full page reload. /// [MaybeNull] public string Location { get; set; } /// - /// Gets or sets the HX-Push-Url header to push a new URL into the history stack. + /// Gets or sets the HX-Push-Url header to push a new URL into the browser's history stack. /// [MaybeNull] public string PushUrl { get; set; } @@ -334,29 +328,28 @@ public readonly struct HtmxResponseHeaders } ``` -Just like `HtmxRequestHeaderNames`, which consists of predefined string constants for HTMX request headers, -there is a corresponding `HtmxResponseHeaderNames` class containing -a list of string constants for HTMX response headers. +Just as `HtmxRequestHeaderNames` defines constants for HTMX request headers, +`HtmxResponseHeaderNames` defines constants for HTMX response headers. ```csharp /// -/// Defines constants for the well-known names of htmx response headers. +/// Defines constants for the well-known names of HTMX response headers. /// For more information, see https://htmx.org/reference/#response_headers /// public static class HtmxResponseHeaderNames { /// - /// The HX-Location header is used to a client-side redirect that does not do a full page reload. + /// The HX-Location header is used to perform a client-side redirect without a full page reload. /// public const string Location = "HX-Location"; /// - /// The HX-Push-Url header is used to push a new URL into the history stack. + /// The HX-Push-Url header is used to push a new URL into the browser's history stack. /// public const string PushUrl = "HX-Push-Url"; /// - /// The HX-Redirect header is used to client-side redirect to a new location. + /// The HX-Redirect header is used to perform a client-side redirect to a new location. /// public const string Redirect = "HX-Redirect"; @@ -365,9 +358,8 @@ public static class HtmxResponseHeaderNames } ``` -However, the most convenient and efficient way is by using one of the provided `Htmx` methods -with a callback that accepts `HtmxResponse`, allowing you to specify response headers -in a fluent style: +The most convenient approach is to use one of the `Htmx` extension methods. +Its callback receives an `HtmxResponse`, allowing you to configure response headers in a fluent style: ```csharp Response.Htmx(h => h @@ -377,7 +369,7 @@ Response.Htmx(h => h .StopPolling(ShouldStopPolling)); ``` -:bulb: The second Htmx method accepts an additional parameter to avoid unnecessary allocations due to closures: +:bulb: The generic overload accepts an additional state parameter to avoid closure allocations: ```csharp Response.Htmx( @@ -395,17 +387,16 @@ Response.Htmx( return Json(profile).Htmx(h => h.StopPolling(ShouldStopPolling)); ``` -In both cases, the headers will be set only in the case of an `htmx` request. -In the case of a regular request, the callback passed to the `Htmx(this)` method will not be executed, -which allows avoiding unnecessary work. +In all these examples, headers are set only for an HTMX request. For a regular request, +the callback passed to `Htmx` is not executed, avoiding unnecessary work. ### The declarative way of setting response headers -Some of the response headers can be set declaratively using the `HtmxResponseAttribute`, -which is applied to the controller, action, or page. +Some response headers can be set declaratively by applying `HtmxResponseAttribute` +to a controller or action: ```csharp -public class UserController : ControlleBase +public class UserController : ControllerBase { [HtmxRequest] [HtmxResponse( @@ -418,8 +409,8 @@ public class UserController : ControlleBase } ``` -:bulb: If a more complex expression is needed for `swap`, for example, `innerHTML show:#result:top`, -you can use the `Reswap` method in the `HtmxResponse` class, which accepts a string. +:bulb: For a more complex swap expression, such as `innerHTML show:#result:top`, +use the `Reswap` overload that accepts a string. ```csharp /// @@ -441,47 +432,55 @@ public HtmxResponse Reswap(string value); public HtmxResponse Reswap(HtmxSwap value); ``` -And for the `HtmxResponseAttribute`, there is the `ReswapExpression` property. +For declarative configuration, `HtmxResponseAttribute` provides the `ReswapExpression` property: ```csharp /// -/// Gets or sets the HX-Reswap header that allows to specify how the response will be swapped. +/// Gets or sets the HX-Reswap header to specify how the response will be swapped into the DOM. /// [MaybeNull] public string ReswapExpression { get; set; } /// -/// Gets or sets the HX-Reswap header that allows to specify how the response will be swapped. +/// Gets or sets the HX-Reswap header to specify how the response will be swapped into the DOM. /// public HtmxSwap Reswap { get; set; } ``` -allowing you to flexibly configure the `swap` header you need. +Use `ReswapExpression` when the strongly typed `Reswap` property is not flexible enough. -## TagHelpers +## Tag Helpers -The library provides 4 tag helpers: +The library provides five tag helpers: * `HtmxUrlTagHelper` * `HtmxHeaderTagHelper` -* `HtmxConfigTagHelper` +* `HtmxValsTagHelper` * `HtmxRequestTagHelper` +* `HtmxConfigTagHelper` -To make them available in your project, add the `@addTagHelper` directive in the Razor view. +To make them available in your project, add the `@addTagHelper` directive to a Razor view: ```razor @addTagHelper *, Ramstack.HtmxToolkit ``` -To make the tag helpers available globally for the entire application, you should add this line -to the `_ViewImports.cshtml` file, which is inherited by all view files by default. +To make the tag helpers available throughout the application, add this line to +`_ViewImports.cshtml`, which is inherited by Razor views by default. + +Import the toolkit namespace there as well if a view refers to toolkit types: + +```razor +@using Ramstack.HtmxToolkit +``` ### HtmxUrlTagHelper -The `HtmxUrlTagHelper` allows generating links for HTMX methods similar to how it's done in ASP.NET Core -for generating links, just replace the `asp-` prefix with the `hx-` prefix. +The `HtmxUrlTagHelper` generates URLs for HTMX requests in much the same way that +the built-in ASP.NET Core tag helpers generate links. In most cases, replace the `asp-` prefix +with `hx-`: -```html +```razor
+
``` -Also, the `hx-all-route-data` attribute is available, which accepts a dictionary where -the key is the parameter name, and the value is the parameter value. In the example below, -a dictionary with specific parameters is created, which is then used as the value -of the `hx-all-route-data` attribute. +The `hx-all-route-data` attribute accepts an `IDictionary` containing +additional route values: -```html +```razor @{ - var parameters = new { - category = "science", - pdf = true + var parameters = new Dictionary + { + ["category"] = "science", + ["pdf"] = "true" }; } ``` The following code will be generated: ```html - ``` -In addition to the examples mentioned, the following properties are also available: +The following URL-generation attributes are also available: + * `hx-host` * `hx-protocol` * `hx-fragment` ### HtmxHeaderTagHelper -The `htmx` library allows adding custom headers that will be submitted with an AJAX request. -However, since JSON format should be used for this, writing it out manually is not always convenient, -especially considering the need to escape special characters. Fortunately, the library provides -the `HtmxHeaderTagHelper` class, which takes care of this and allows specifying headers -in a clearer and more readable format. +HTMX lets you add custom request headers through a JSON-valued attribute. Because writing and +escaping that JSON manually can be inconvenient, `HtmxHeaderTagHelper` provides a clearer format: -```html -
- Get Some HTML, Including A Custom Header in the Request -
+```razor +
+ Get some HTML and include custom headers in the request +
``` The following code will be generated: ```html -
- Get Some HTML, Including A Custom Header in the Request -
+
+ Get some HTML and include custom headers in the request +
``` -Also, if you have a dictionary with the headers you need, -you can assign them to the `hx-all-headers` attribute: +You can also assign an `IDictionary` to `hx-all-headers`: -```html -
- Get Some HTML, Including A Custom Header in the Request -
+```razor +@{ + var headers = new Dictionary + { + ["Key-1"] = "Value-1", + ["Key-2"] = "Value-2" + }; +} + +
+ Get some HTML and include custom headers in the request +
``` -The `HtmxHeaderTagHelper` will take care of all the remaining work regarding JSON serialization and escaping. +`HtmxHeaderTagHelper` handles JSON serialization and escaping. ### HtmxValsTagHelper The `HtmxValsTagHelper` adds values that HTMX includes with a request. Use `hx-val-*` attributes instead of writing JSON manually: -```html +```razor ``` -You can also provide the values as a dictionary with the `hx-all-vals` attribute. +You can also assign an `IDictionary` to `hx-all-vals`. ### HtmxRequestTagHelper -The `HtmxRequestTagHelper` configures the htmx request options supported by HTMX 1.9.x and 2.x. -Use the typed `hx-request-*` attributes instead of writing JSON manually: +`HtmxRequestTagHelper` configures request options for the selected HTMX version. +For HTMX 1.9.x and 2.x, use typed `hx-request-*` attributes instead of writing `hx-request` +JSON manually: -```html +```razor @@ -651,6 +656,29 @@ The following HTML will be generated: ``` +For HTMX 4.x, the tag helper generates `hx-config`. In addition to `timeout` and `credentials`, +HTMX 4.x supports `cache`, `redirect`, `referrer`, `integrity`, and `validate`. The `noHeaders` +option is available only in HTMX 1.9.x and 2.x. + +```razor + +``` + +With HTMX 4.x selected, the following HTML will be generated: + +```html + +``` + ### HtmxConfigTagHelper HTMX configuration is defined at application startup through `AddHtmxToolkit`. @@ -728,7 +756,7 @@ public sealed class ConfigurationInspector(IOptions options) #### Response Handling Configuration HTMX 2.x introduces the [`responseHandling`](https://htmx.org/docs/#response-handling) configuration option, -allowing you to define how htmx should handle responses based on HTTP status codes. Rules are +allowing you to define how HTMX should handle responses based on HTTP status codes. Rules are configured in order through `HtmxV2Config`: ```csharp @@ -770,30 +798,27 @@ builder.Services.AddHtmxToolkit(options => }); ``` -To do this, you can directly include the contents of the script file on the page: +You can embed the minified script directly in a Razor view: -```html +```razor ``` -Alternatively, to retrieve the debug version of the script, -you can pass the debug parameter with a value of `true`: +Pass `true` to embed the debug version instead: -```html +```razor ``` -The `debug` parameter determines which version will be included. By default, the minimized version -of the script will be returned, which weighs very little and takes up approximately 520 bytes. +The minified version is used by default and is less than 1 KB. -The method returns a pre-initialized `HtmlString` with the script content, -so there will be no unnecessary conversions and allocations every time it's used. +The method returns a cached `HtmlString`, avoiding repeated conversions and allocations. -Alternatively, you can register the corresponding endpoint for the script by calling: +Alternatively, register an endpoint that serves the script: ```csharp app.UseAuthorization(); @@ -803,37 +828,32 @@ app.MapControllers(); ``` By default, the registered path is mapped to `/htmxtoolkit/[sha1-hash]`, -where **[sha1-hash]** represents a precalculated hash of the script content. -This approach eliminates the need to worry about cache invalidating -when updating the script in the future as the hash automatically changes -when the script content is modified. +where **[sha1-hash]** represents a precomputed hash of the script content. +The hash changes whenever the script changes, providing automatic cache invalidation. -If you want to change the path to your own, specify this path in the parameter. +To use a custom path, pass it to `MapHtmxToolkitScript`: ```csharp app.MapHtmxToolkitScript("/my-path"); ``` -Now, include it on the page. +Then include the mapped script in a Razor view: -```html +```razor ``` -Alternatively, to retrieve the debug version of the script, you can pass the `debug` parameter -with a value of `true`, which instructs to include a query parameter `?debug` in the path. -The presence of this parameter determines the loading of the debug version: +Pass `true` to generate a path with the `?debug` query string and load the debug version: -```html +```razor ``` -The `debug` parameter determines whether to load the minimized version (used by default) -or the debug version of the script. +Without the `debug` argument, the endpoint serves the minified version. ## Supported Versions -All releases in the following HTMX version lines are supported: +The following .NET and HTMX versions are supported: | | Version | |------|----------------------------------| @@ -845,5 +865,6 @@ All releases in the following HTMX version lines are supported: Bug reports and contributions are welcome. ## License + This package is released as open source under the **MIT License**. See the [LICENSE](https://github.com/rameel/ramstack.htmxtoolkit/blob/main/LICENSE) file for more details. From af5a5d8377c4f4165d5a4cebf925efdea1b71539 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 30 Aug 2026 17:59:07 +0500 Subject: [PATCH 3/4] Polish XML doc comments and README text --- README.md | 53 +++-- .../ActionResultExtensions.cs | 21 +- .../Builder/EndpointRouteBuilderExtensions.cs | 8 +- .../Builder/ServiceCollectionExtensions.cs | 2 +- .../Collections/SmallDictionary.cs | 197 ++++++++++-------- .../Collections/SmallDictionaryDebugView.cs | 6 +- .../HtmlHelperExtensions.cs | 24 ++- src/Ramstack.HtmxToolkit/HtmxAssets.cs | 24 ++- src/Ramstack.HtmxToolkit/HtmxBinaryType.cs | 12 +- .../HtmxBinaryTypeJsonConverter.cs | 2 +- src/Ramstack.HtmxToolkit/HtmxConfig.cs | 6 +- src/Ramstack.HtmxToolkit/HtmxFetchMode.cs | 2 +- .../HtmxFetchModeJsonConverter.cs | 2 +- src/Ramstack.HtmxToolkit/HtmxFieldValues.cs | 67 +++--- .../HtmxFieldValuesJsonConverter.cs | 2 +- src/Ramstack.HtmxToolkit/HtmxHistoryMode.cs | 3 +- .../HtmxHistoryModeJsonConverter.cs | 16 +- .../HtmxLocationOptions.cs | 8 +- .../HtmxRequestAttribute.cs | 17 +- .../HtmxRequestHeaderNames.cs | 16 +- .../HtmxRequestHeaders.cs | 73 +++++-- src/Ramstack.HtmxToolkit/HtmxResponse.cs | 140 ++++++++----- .../HtmxResponseAttribute.cs | 29 ++- .../HtmxResponseHeaderNames.cs | 35 ++-- .../HtmxResponseHeaders.cs | 80 ++++--- src/Ramstack.HtmxToolkit/HtmxResult.cs | 7 +- src/Ramstack.HtmxToolkit/HtmxResult`1.cs | 15 +- .../HtmxScrollBehavior.cs | 6 +- .../HtmxScrollBehaviorJsonConverter.cs | 2 +- src/Ramstack.HtmxToolkit/HtmxSwap.cs | 2 +- .../HtmxSwapJsonConverter.cs | 2 +- .../HtmxToolkitOptions.cs | 29 ++- .../HtmxTriggerSpecsCacheJsonConverter.cs | 5 +- src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs | 18 +- src/Ramstack.HtmxToolkit/HtmxV1Config.cs | 78 +++---- src/Ramstack.HtmxToolkit/HtmxV2Config.cs | 94 +++++---- src/Ramstack.HtmxToolkit/HtmxV4Config.cs | 52 ++--- .../HttpRequestExtensions.cs | 22 +- .../HttpResponseExtensions.cs | 13 +- src/Ramstack.HtmxToolkit/HttpVerb.cs | 15 +- .../HttpVerbArrayJsonConverter.cs | 2 +- .../Internal/DebugHelpers.cs | 7 +- .../Internal/EnumHelper.cs | 48 +++-- .../Internal/JsonOptions.cs | 13 +- src/Ramstack.HtmxToolkit/PendingEvents.cs | 39 ++-- .../Properties/CollectionBuilderAttribute.cs | 25 ++- .../TagHelpers/HtmxConfigTagHelper.cs | 5 +- .../TagHelpers/HtmxHeaderTagHelper.cs | 2 +- .../HtmxRequestJsonSerializerContext.cs | 2 +- .../TagHelpers/HtmxRequestTagHelper.cs | 64 ++++-- .../TagHelpers/HtmxUrlTagHelper.cs | 37 ++-- .../TagHelpers/HtmxValsTagHelper.cs | 2 +- .../TagHelpers/ResponseHandlingConfig.cs | 5 +- 53 files changed, 867 insertions(+), 589 deletions(-) diff --git a/README.md b/README.md index 0d1908a..aa8c142 100644 --- a/README.md +++ b/README.md @@ -108,11 +108,11 @@ public static class HttpRequestExtensions public static bool IsHtmxBoosted(this HttpRequest request, out HtmxRequestHeaders headers); /// - /// Returns the that provides access to well-known HTMX headers. + /// Returns a strongly typed view of the HTMX request headers. /// /// The HTTP request. /// - /// The . + /// The . /// public static HtmxRequestHeaders GetHtmxHeaders(this HttpRequest request); } @@ -170,7 +170,7 @@ public readonly struct HtmxRequestHeaders public string? CurrentUrl { get; } /// - /// Gets a value indicating whether the request is for history restoration after a miss in the local history cache. + /// Gets a value indicating whether the request restores history after a miss in the local history cache. /// public bool HistoryRestoreRequest { get; } @@ -185,17 +185,17 @@ public readonly struct HtmxRequestHeaders public bool Request { get; } /// - /// Gets the ID of the target element if it exists. + /// Gets the ID of the target element, if present. /// public string? Target { get; } /// - /// Gets the name of the triggered element if it exists. + /// Gets the name of the triggered element, if present. /// public string? TriggerName { get; } /// - /// Gets the ID of the triggered element if it exists as indicated by the HX-Trigger header. + /// Gets the ID of the triggered element, if present. /// public string? Trigger { get; } } @@ -216,8 +216,10 @@ so you do not have to remember their exact spelling. ```csharp /// /// Defines constants for the well-known names of HTMX request headers. -/// For more information, see https://htmx.org/reference/#request_headers /// +/// +/// For more information, see HTMX Request Headers Reference. +/// public static class HtmxRequestHeaderNames { /// @@ -277,11 +279,11 @@ For working with response headers, the library provides the `HttpResponseExtensi public static class HttpResponseExtensions { /// - /// Returns the that provides access to well-known HTMX headers. + /// Returns a strongly typed view of the HTMX response headers. /// /// The HTTP response. /// - /// The . + /// The . /// public static HtmxResponseHeaders GetHtmxHeaders(this HttpResponse response); @@ -289,15 +291,16 @@ public static class HttpResponseExtensions /// Configures the HTMX response headers. /// /// The HTTP response to configure. - /// The function to configure the HTMX response headers. + /// The delegate that configures the HTMX response headers. public static void Htmx(this HttpResponse response, Action configure); /// /// Configures the HTMX response headers. /// /// The HTTP response to configure. - /// The function to configure the HTMX response headers. - /// The value to pass to the . + /// The delegate that configures the HTMX response headers + /// using . + /// The state passed to . public static void Htmx(this HttpResponse response, Action configure, TState state); } ``` @@ -312,13 +315,15 @@ that control HTMX behavior. public readonly struct HtmxResponseHeaders { /// - /// Gets or sets the HX-Location header to perform a client-side redirect without a full page reload. + /// Gets or sets the value of the HX-Location header, which performs + /// a client-side redirect without a full-page reload. /// [MaybeNull] public string Location { get; set; } /// - /// Gets or sets the HX-Push-Url header to push a new URL into the browser's history stack. + /// Gets or sets the value of the HX-Push-Url header, which pushes a new URL + /// onto the browser's history stack. /// [MaybeNull] public string PushUrl { get; set; } @@ -334,22 +339,24 @@ Just as `HtmxRequestHeaderNames` defines constants for HTMX request headers, ```csharp /// /// Defines constants for the well-known names of HTMX response headers. -/// For more information, see https://htmx.org/reference/#response_headers /// +/// +/// For more information, see HTMX Response Headers Reference. +/// public static class HtmxResponseHeaderNames { /// - /// The HX-Location header is used to perform a client-side redirect without a full page reload. + /// The HX-Location header performs a client-side redirect without a full-page reload. /// public const string Location = "HX-Location"; /// - /// The HX-Push-Url header is used to push a new URL into the browser's history stack. + /// The HX-Push-Url header pushes a new URL onto the browser's history stack. /// public const string PushUrl = "HX-Push-Url"; /// - /// The HX-Redirect header is used to perform a client-side redirect to a new location. + /// The HX-Redirect header performs a client-side redirect to a new location. /// public const string Redirect = "HX-Redirect"; @@ -416,11 +423,11 @@ use the `Reswap` overload that accepts a string. /// /// Sets the HX-Reswap header to specify how the response will be swapped. /// -/// The header value to set. +/// The swap style to assign to the header. /// /// The current instance. /// -public HtmxResponse Reswap(string value); +public HtmxResponse Reswap(HtmxSwap value); /// /// Sets the HX-Reswap header to specify how the response will be swapped. @@ -429,20 +436,20 @@ public HtmxResponse Reswap(string value); /// /// The current instance. /// -public HtmxResponse Reswap(HtmxSwap value); +public HtmxResponse Reswap(string value); ``` For declarative configuration, `HtmxResponseAttribute` provides the `ReswapExpression` property: ```csharp /// -/// Gets or sets the HX-Reswap header to specify how the response will be swapped into the DOM. +/// Gets or sets the complete HX-Reswap header value, including any swap modifiers. /// [MaybeNull] public string ReswapExpression { get; set; } /// -/// Gets or sets the HX-Reswap header to specify how the response will be swapped into the DOM. +/// Gets or sets the swap style to specify in the HX-Reswap header. /// public HtmxSwap Reswap { get; set; } ``` diff --git a/src/Ramstack.HtmxToolkit/ActionResultExtensions.cs b/src/Ramstack.HtmxToolkit/ActionResultExtensions.cs index be5f164..6c9bf3a 100644 --- a/src/Ramstack.HtmxToolkit/ActionResultExtensions.cs +++ b/src/Ramstack.HtmxToolkit/ActionResultExtensions.cs @@ -3,30 +3,31 @@ namespace Ramstack.HtmxToolkit; /// -/// Provides extension methods for to configure HTMX response headers. +/// Provides extension methods for the interface +/// that configures HTMX response headers. /// public static class ActionResultExtensions { /// - /// Configures HTMX response headers for the specified . + /// Configures HTMX response headers for the specified . /// - /// The to configure. - /// A delegate to configure the HTMX response headers. + /// The to configure. + /// The delegate that configures the HTMX response headers. /// - /// An that wraps the original result with HTMX configuration. + /// An that wraps . /// public static HtmxResult Htmx(this IActionResult result, Action configure) => new(result, configure); /// - /// Configures HTMX response headers for the specified using a state object. + /// Configures HTMX response headers for the specified using a state object. /// /// The type of the state object passed to the configuration delegate. - /// The to configure. - /// A delegate to configure the HTMX response headers using the state object. - /// The state object passed to the delegate. + /// The to configure. + /// The delegate that configures the HTMX response headers using the state object. + /// The state object passed to the delegate. /// - /// An that wraps the original result with HTMX configuration. + /// An that wraps . /// public static HtmxResult Htmx(this IActionResult result, Action configure, TState state) => new(result, configure, state); diff --git a/src/Ramstack.HtmxToolkit/Builder/EndpointRouteBuilderExtensions.cs b/src/Ramstack.HtmxToolkit/Builder/EndpointRouteBuilderExtensions.cs index e3dd735..9718fad 100644 --- a/src/Ramstack.HtmxToolkit/Builder/EndpointRouteBuilderExtensions.cs +++ b/src/Ramstack.HtmxToolkit/Builder/EndpointRouteBuilderExtensions.cs @@ -6,17 +6,17 @@ namespace Ramstack.HtmxToolkit.Builder; /// -/// Provides extension methods for the interface to add "htmxtoolkit" endpoints. +/// Provides HTMX Toolkit endpoint mappings for an . /// public static class EndpointRouteBuilderExtensions { /// - /// Gets the default path to the HTMX antiforgery script asset. + /// Gets the current path to the HTMX Toolkit script asset. /// internal static string AssetPath { get; private set; } = $"/htmxtoolkit/{HtmxAssets.Hash}"; /// - /// Maps an endpoint that serves the HTMX toolkit script at the default path. + /// Maps an endpoint that serves the HTMX Toolkit script at the default path. /// /// The endpoint route builder. /// @@ -26,7 +26,7 @@ public static IEndpointConventionBuilder MapHtmxToolkitScript(this IEndpointRout builder.MapHtmxToolkitScript(AssetPath); /// - /// Maps an endpoint that serves the HTMX toolkit script at the specified path. + /// Maps an endpoint that serves the HTMX Toolkit script at the specified path. /// /// The endpoint route builder. /// The path at which to serve the script. diff --git a/src/Ramstack.HtmxToolkit/Builder/ServiceCollectionExtensions.cs b/src/Ramstack.HtmxToolkit/Builder/ServiceCollectionExtensions.cs index d3ce941..d6fd5e6 100644 --- a/src/Ramstack.HtmxToolkit/Builder/ServiceCollectionExtensions.cs +++ b/src/Ramstack.HtmxToolkit/Builder/ServiceCollectionExtensions.cs @@ -3,7 +3,7 @@ namespace Ramstack.HtmxToolkit.Builder; /// -/// Provides extension methods for registering HTMX Toolkit services. +/// Provides HTMX Toolkit service registration for an . /// public static class ServiceCollectionExtensions { diff --git a/src/Ramstack.HtmxToolkit/Collections/SmallDictionary.cs b/src/Ramstack.HtmxToolkit/Collections/SmallDictionary.cs index d42f881..2dc9446 100644 --- a/src/Ramstack.HtmxToolkit/Collections/SmallDictionary.cs +++ b/src/Ramstack.HtmxToolkit/Collections/SmallDictionary.cs @@ -5,20 +5,21 @@ namespace Ramstack.HtmxToolkit.Collections; /// -/// Represents the implementation optimized for a small number of entries. +/// Provides a compact implementation +/// optimized for a small number of entries. /// +/// The type of keys in the dictionary. +/// The type of values in the dictionary. /// /// This type is intended for scenarios in which a dictionary typically contains only a few entries. -/// It uses compact array-based storage to reduce memory usage and the overhead of creating, populating, -/// and searching the dictionary. +/// It uses array-based storage to reduce memory usage and the overhead of creating, +/// populating, and searching the dictionary. /// -/// For up to entries, keys are located using a linear search. -/// When the number of entries exceeds this threshold, the entries are sorted by key and subsequent -/// lookups use a binary search. Insertions then preserve the key order. +/// For up to entries, keys are located using +/// a linear search. Above this threshold, the entries are sorted by key and +/// subsequent lookups use a binary search. Insertions then preserve the key order. /// /// -/// The type of keys in the dictionary. -/// The type of values in the dictionary. [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(SmallDictionaryDebugView<,>))] internal sealed class SmallDictionary : IDictionary, IReadOnlyDictionary where TKey : notnull @@ -32,7 +33,7 @@ internal sealed class SmallDictionary : IDictionary, private KeyValuePair[] _items = []; private int _count; - /// + /// public int Count => _count; /// @@ -41,7 +42,7 @@ internal sealed class SmallDictionary : IDictionary, /// public ValueCollection Values => [with(this)]; - /// + /// public TValue this[TKey key] { get @@ -70,10 +71,10 @@ public TValue this[TKey key] } /// - /// Initializes a new instance of the class using the specified key comparer. + /// Initializes a new instance of the class + /// using the specified key comparer. /// /// The comparer to use when comparing keys. - /// is . public SmallDictionary(IComparer comparer) { ArgumentNullException.ThrowIfNull(comparer); @@ -81,14 +82,12 @@ public SmallDictionary(IComparer comparer) } /// - /// Initializes a new instance of the class that contains - /// entries copied from the specified collection and uses the specified key comparer. + /// Initializes a new instance of the class + /// with entries copied from the specified collection and the specified + /// key comparer. /// /// The collection whose entries are copied to the new dictionary. /// The comparer to use when comparing keys. - /// - /// or is . - /// public SmallDictionary(IEnumerable> collection, IComparer comparer) : this(comparer) { ArgumentNullException.ThrowIfNull(collection); @@ -114,11 +113,11 @@ public SmallDictionary(IEnumerable> collection, IComp } } - /// + /// public bool ContainsKey(TKey key) => IndexOf(key) >= 0; - /// + /// public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) { ref var item = ref Find(key); @@ -132,7 +131,7 @@ public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) return false; } - /// + /// public void Add(TKey key, TValue value) { var index = IndexOf(key); @@ -151,10 +150,9 @@ public void Add(TKey key, TValue value) /// The key of the entry to add. /// The value of the entry to add. /// - /// if the key/value pair was added to the dictionary; - /// otherwise, . + /// if the key/value pair was added to the dictionary; + /// otherwise, . /// - /// is . public bool TryAdd(TKey key, TValue value) { var index = IndexOf(key); @@ -165,7 +163,7 @@ public bool TryAdd(TKey key, TValue value) return true; } - /// + /// public bool Remove(TKey key) { var index = IndexOf(key); @@ -176,7 +174,7 @@ public bool Remove(TKey key) return true; } - /// + /// public void Clear() { if (RuntimeHelpers.IsReferenceOrContainsReferences>()) @@ -189,42 +187,47 @@ public void Clear() _count = 0; } - /// + /// + /// Returns an enumerator that iterates through the . + /// + /// + /// A structure for the . + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() => new(this); /// - /// Gets the underlying array used to store the dictionary entries. + /// Gets the underlying array used to store dictionary entries, including any unused capacity. /// /// - /// The internal backing array. + /// The internal backing array. Only the first elements contain active entries. /// internal KeyValuePair[] GetUnderlyingArray() => _items; #region ICollection: explicit interface implementations - /// + /// bool ICollection>.IsReadOnly => false; - /// + /// ICollection IDictionary.Keys => new KeyCollection(this); - /// + /// ICollection IDictionary.Values => new ValueCollection(this); - /// + /// IEnumerable IReadOnlyDictionary.Keys => Keys; - /// + /// IEnumerable IReadOnlyDictionary.Values => Values; - /// + /// void ICollection>.Add(KeyValuePair item) => Add(item.Key, item.Value); - /// + /// bool ICollection>.Contains(KeyValuePair item) { var index = IndexOf(item.Key); @@ -234,11 +237,11 @@ bool ICollection>.Contains(KeyValuePair return false; } - /// + /// void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) => _items.AsSpan(0, _count).CopyTo(array.AsSpan(arrayIndex)); - /// + /// bool ICollection>.Remove(KeyValuePair item) { var index = IndexOf(item.Key); @@ -258,11 +261,11 @@ bool ICollection>.Remove(KeyValuePair i #region IEnumerable: explicit interface implementations - /// + /// IEnumerator> IEnumerable>.GetEnumerator() => GetEnumerator(); - /// + /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); @@ -271,7 +274,8 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => /// /// Ensures that the dictionary can hold the specified number of entries without resizing. /// - /// The minimum number of entries that the dictionary must be able to hold. + /// The minimum number of entries + /// that the dictionary must be able to hold. private void EnsureCapacity(int capacity) { const int DefaultCapacity = 4; @@ -323,8 +327,10 @@ private void Insert(int index, TKey key, TValue value) items[index] = new KeyValuePair(key, value); // - // Once the entry count exceeds the threshold, the dictionary switches from a linear search over - // unsorted storage to a binary search over sorted storage. Subsequent insertions preserve key order. + // Once the entry count exceeds the threshold, + // the dictionary switches from a linear search over + // unsorted storage to a binary search over sorted storage. + // Subsequent insertions preserve key order. // count++; if (count == LinearSearchThreshold + 1) @@ -338,7 +344,8 @@ private void Insert(int index, TKey key, TValue value) /// /// The key of the entry to find. /// - /// A reference to the entry associated with , or a reference if the key is not found. + /// A reference to the entry associated with , + /// or a reference if the key is not found. /// private ref KeyValuePair Find(TKey key) { @@ -390,8 +397,8 @@ private ref KeyValuePair Find(TKey key) ///
/// The key to locate. /// - /// The zero-based index of if it is found; otherwise, the bitwise complement of the index - /// at which the key should be inserted. + /// The zero-based index of if it is found; otherwise, + /// the bitwise complement of the index at which the key should be inserted. /// private int IndexOf(TKey key) { @@ -466,7 +473,7 @@ private static void Error_KeyNotFound() => throw new KeyNotFoundException(); /// - /// Throws an exception indicating that a dictionary key cannot be . + /// Throws an exception indicating that a dictionary key cannot be . /// /// Always thrown. [DoesNotReturn] @@ -498,7 +505,7 @@ private static void Error_NotSupported() => /// The comparer to use when comparing keys. private sealed class KeyValuePairComparer(IComparer comparer) : IComparer> { - /// + /// public int Compare(KeyValuePair x, KeyValuePair y) => comparer.Compare(x.Key, y.Key); } @@ -508,43 +515,48 @@ public int Compare(KeyValuePair x, KeyValuePair y) = #region Inner type: KeyCollection /// - /// Represents the collection of keys in a . + /// Represents the collection of keys in a . /// /// The dictionary whose keys are exposed by the collection. public sealed class KeyCollection(SmallDictionary dictionary) : ICollection { - /// + /// public int Count => dictionary.Count; - /// + /// public bool Contains(TKey item) => dictionary.ContainsKey(item); - /// + /// + /// Returns an enumerator that iterates through the . + /// + /// + /// A for the . + /// public Enumerator GetEnumerator() => new(dictionary); #region ICollection: explicit interface implementations - /// + /// bool ICollection.IsReadOnly => true; - /// + /// void ICollection.Add(TKey item) => Error_NotSupported(); - /// + /// void ICollection.Clear() => Error_NotSupported(); - /// + /// bool ICollection.Remove(TKey item) { Error_NotSupported(); return false; } - /// + /// void ICollection.CopyTo(TKey[] array, int arrayIndex) { var items = dictionary._items.AsSpan(0, dictionary._count); @@ -558,11 +570,11 @@ void ICollection.CopyTo(TKey[] array, int arrayIndex) #region IEnumerable: explicit interface implementations - /// + /// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - /// + /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); @@ -571,7 +583,7 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => #region Inner type: Enumerator /// - /// Represents an enumerator for the keys in a . + /// Represents an enumerator for the keys in a . /// public struct Enumerator : IEnumerator { @@ -579,7 +591,7 @@ public struct Enumerator : IEnumerator private readonly int _count; private int _index; - /// + /// public TKey Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -587,7 +599,7 @@ public TKey Current } /// - /// Initializes a new instance of the structure for the specified dictionary. + /// Initializes an enumerator for the specified dictionary. /// /// The dictionary whose keys are to be enumerated. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -598,7 +610,7 @@ internal Enumerator(SmallDictionary dictionary) _items = dictionary._items; } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { @@ -614,17 +626,17 @@ public bool MoveNext() return false; } - /// + /// public void Dispose() { } #region IEnumerator: Explicit interface implementations - /// + /// object System.Collections.IEnumerator.Current => Current!; - /// + /// void System.Collections.IEnumerator.Reset() => Error_NotSupported(); @@ -639,15 +651,15 @@ void System.Collections.IEnumerator.Reset() => #region Inner type: ValueCollection /// - /// Represents the collection of values in a . + /// Represents the collection of values in a . /// /// The dictionary whose values are exposed by the collection. public sealed class ValueCollection(SmallDictionary dictionary) : ICollection { - /// + /// public int Count => dictionary.Count; - /// + /// public bool Contains(TValue item) { var items = dictionary._items.AsSpan(0, dictionary._count); @@ -658,31 +670,36 @@ public bool Contains(TValue item) return false; } - /// + /// + /// Returns an enumerator that iterates through the . + /// + /// + /// A for the . + /// public Enumerator GetEnumerator() => new(dictionary); #region ICollection: explicit interface implementations - /// + /// bool ICollection.IsReadOnly => true; - /// + /// void ICollection.Add(TValue item) => Error_NotSupported(); - /// + /// void ICollection.Clear() => Error_NotSupported(); - /// + /// bool ICollection.Remove(TValue item) { Error_NotSupported(); return false; } - /// + /// void ICollection.CopyTo(TValue[] array, int arrayIndex) { var items = dictionary._items.AsSpan(0, dictionary._count); @@ -696,11 +713,11 @@ void ICollection.CopyTo(TValue[] array, int arrayIndex) #region IEnumerable: explicit interface implementations - /// + /// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - /// + /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); @@ -709,7 +726,7 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => #region Inner type: Enumerator /// - /// Represents an enumerator for the values in a . + /// Enumerates the values in a . /// public struct Enumerator : IEnumerator { @@ -717,7 +734,7 @@ public struct Enumerator : IEnumerator private readonly int _count; private int _index; - /// + /// public TValue Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -725,7 +742,7 @@ public TValue Current } /// - /// Initializes a new instance of the structure for the specified dictionary. + /// Initializes an enumerator for the specified dictionary. /// /// The dictionary whose values are to be enumerated. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -736,7 +753,7 @@ internal Enumerator(SmallDictionary dictionary) _items = dictionary._items; } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { @@ -752,17 +769,17 @@ public bool MoveNext() return false; } - /// + /// public void Dispose() { } #region IEnumerator: Explicit interface implementations - /// + /// object System.Collections.IEnumerator.Current => Current!; - /// + /// void System.Collections.IEnumerator.Reset() => Error_NotSupported(); @@ -777,7 +794,7 @@ void System.Collections.IEnumerator.Reset() => #region Inner type: Enumerator /// - /// Represents an enumerator for the entries in a . + /// Represents an enumerator for the entries in a . /// public struct Enumerator : IEnumerator> { @@ -785,7 +802,7 @@ public struct Enumerator : IEnumerator> private readonly int _count; private int _index; - /// + /// public KeyValuePair Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -793,7 +810,7 @@ public KeyValuePair Current } /// - /// Initializes a new instance of the structure for the specified dictionary. + /// Initializes an enumerator for the specified dictionary. /// /// The dictionary whose entries are to be enumerated. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -804,7 +821,7 @@ internal Enumerator(SmallDictionary dictionary) _items = dictionary._items; } - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { @@ -820,17 +837,17 @@ public bool MoveNext() return false; } - /// + /// public void Dispose() { } #region IEnumerator: Explicit interface implementations - /// + /// object System.Collections.IEnumerator.Current => Current; - /// + /// void System.Collections.IEnumerator.Reset() => Error_NotSupported(); diff --git a/src/Ramstack.HtmxToolkit/Collections/SmallDictionaryDebugView.cs b/src/Ramstack.HtmxToolkit/Collections/SmallDictionaryDebugView.cs index f44ffbd..413a941 100644 --- a/src/Ramstack.HtmxToolkit/Collections/SmallDictionaryDebugView.cs +++ b/src/Ramstack.HtmxToolkit/Collections/SmallDictionaryDebugView.cs @@ -3,14 +3,14 @@ namespace Ramstack.HtmxToolkit.Collections; /// -/// Represents a debugger view for the class, allowing inspection of its contents. +/// Provides a debugger view of a . /// /// The type of the keys in the dictionary. /// The type of the values in the dictionary. internal sealed class SmallDictionaryDebugView(SmallDictionary? dictionary) where TKey : notnull { /// - /// Gets the array of key-value pairs contained in the for debugging purposes. + /// Gets the active dictionary entries for display in the debugger. /// [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public DictionaryEntry[] Items @@ -33,7 +33,7 @@ public DictionaryEntry[] Items #region Inner type: DictionaryEntry /// - /// Represents a class that contains the key/value pairs of the dictionary entry for displaying by a debugger. + /// Represents a dictionary entry displayed by the debugger. /// /// The key of the entry. /// The value of the entry. diff --git a/src/Ramstack.HtmxToolkit/HtmlHelperExtensions.cs b/src/Ramstack.HtmxToolkit/HtmlHelperExtensions.cs index b100f0c..3d6f8f7 100644 --- a/src/Ramstack.HtmxToolkit/HtmlHelperExtensions.cs +++ b/src/Ramstack.HtmxToolkit/HtmlHelperExtensions.cs @@ -6,7 +6,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Provides extension methods for the interface. +/// Provides extension methods for the interface. /// public static class HtmlHelperExtensions { @@ -14,33 +14,35 @@ public static class HtmlHelperExtensions private static readonly HtmlString s_debugScript = new(HtmxAssets.DebugScript); /// - /// Gets the HTML string that represents the path to the minified version of the script. + /// Gets or sets the HTML string that represents the path to the minified script. /// internal static HtmlString Path { get; set; } = new(EndpointRouteBuilderExtensions.AssetPath); /// - /// Gets the HTML string that represents the path to the debug version of the script. + /// Gets or sets the HTML string that represents the path to the debug script. /// internal static HtmlString DebugPath { get; set; } = new(EndpointRouteBuilderExtensions.AssetPath + "?debug"); /// - /// Returns the HTMX toolkit script content. + /// Returns the embedded HTMX Toolkit script. /// - /// The HTML helper. - /// Whether to return the debug version of the script. + /// The HTML helper instance. + /// to return the debug script; + /// otherwise, . /// - /// The HTMX toolkit script content. + /// The embedded script content. /// public static IHtmlContent HtmxToolkitScript(this IHtmlHelper _, bool debug = false) => debug ? s_debugScript : s_script; /// - /// Returns the path to the HTMX toolkit script endpoint. + /// Returns the path to the HTMX Toolkit script endpoint. /// - /// The HTML helper. - /// Whether to return the debug version of the script. + /// The HTML helper instance. + /// to return the debug script path; + /// otherwise, . /// - /// The HTMX toolkit script endpoint path. + /// The HTMX Toolkit script endpoint path. /// public static IHtmlContent HtmxToolkitScriptPath(this IHtmlHelper _, bool debug = false) => debug ? DebugPath : Path; diff --git a/src/Ramstack.HtmxToolkit/HtmxAssets.cs b/src/Ramstack.HtmxToolkit/HtmxAssets.cs index dd35b7c..4b7b712 100644 --- a/src/Ramstack.HtmxToolkit/HtmxAssets.cs +++ b/src/Ramstack.HtmxToolkit/HtmxAssets.cs @@ -4,31 +4,37 @@ namespace Ramstack.HtmxToolkit; /// -/// Provides access to the embedded HTMX toolkit script assets. +/// Provides access to the embedded HTMX Toolkit script assets. /// public static class HtmxAssets { /// - /// The unminified HTMX toolkit script. + /// The unminified HTMX Toolkit script. /// - public static readonly string DebugScript = GetResource("htmx-toolkit.js"); + public static readonly string DebugScript = GetResourceContent("htmx-toolkit.js"); /// - /// The minified HTMX toolkit script. + /// The minified HTMX Toolkit script. /// - public static readonly string Script = GetResource("htmx-toolkit.min.js"); + public static readonly string Script = GetResourceContent("htmx-toolkit.min.js"); /// - /// The content hash of the HTMX toolkit script. + /// The content hash of the HTMX Toolkit script. /// public static readonly string Hash = Convert .ToHexString(SHA1.HashData(Encoding.UTF8.GetBytes(DebugScript)).AsSpan(0, 8)) .ToLowerInvariant(); - private static string GetResource(string name) + /// + /// Reads an embedded text resource. + /// + /// The manifest resource name. + /// + /// The resource contents. + /// + private static string GetResourceContent(string name) { - var stream = typeof(HtmxAssets).Assembly.GetManifestResourceStream(name)!; - + using var stream = typeof(HtmxAssets).Assembly.GetManifestResourceStream(name)!; using var reader = new StreamReader(stream); return reader.ReadToEnd(); } diff --git a/src/Ramstack.HtmxToolkit/HtmxBinaryType.cs b/src/Ramstack.HtmxToolkit/HtmxBinaryType.cs index 3840ee4..13f16fc 100644 --- a/src/Ramstack.HtmxToolkit/HtmxBinaryType.cs +++ b/src/Ramstack.HtmxToolkit/HtmxBinaryType.cs @@ -1,23 +1,21 @@ namespace Ramstack.HtmxToolkit; /// -/// Defines the type of binary data -/// being received over the WebSocket connection. +/// Specifies how binary data received over a WebSocket connection is represented. /// /// -/// https://developer.mozilla.org/docs/Web/API/WebSocket/binaryType +/// For more information, see WebSocket: binaryType property. /// public enum HtmxBinaryType { /// - /// Use Blob objects for binary data. - /// This is the default value. + /// Represents binary data as Blob objects. + /// This is the default. /// Blob, /// - /// Use ArrayBuffer - /// objects for binary data. + /// Represents binary data as ArrayBuffer objects. /// ArrayBuffer } diff --git a/src/Ramstack.HtmxToolkit/HtmxBinaryTypeJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxBinaryTypeJsonConverter.cs index bc0a363..5aa23c5 100644 --- a/src/Ramstack.HtmxToolkit/HtmxBinaryTypeJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxBinaryTypeJsonConverter.cs @@ -6,7 +6,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents a for nullable values. +/// Represents a for nullable values. /// internal sealed class HtmxBinaryTypeJsonConverter : JsonConverter { diff --git a/src/Ramstack.HtmxToolkit/HtmxConfig.cs b/src/Ramstack.HtmxToolkit/HtmxConfig.cs index 2c3f229..db12174 100644 --- a/src/Ramstack.HtmxToolkit/HtmxConfig.cs +++ b/src/Ramstack.HtmxToolkit/HtmxConfig.cs @@ -14,9 +14,11 @@ public abstract class HtmxConfig public HtmxTargetVersion TargetVersion { get; } /// - /// Initializes a new instance of the class with the specified target HTMX version. + /// Initializes a new instance of the class for + /// the specified target HTMX version. /// - /// The target major version of HTMX that this configuration applies to. + /// The target HTMX major version + /// to which this configuration applies. internal HtmxConfig(HtmxTargetVersion version) => TargetVersion = version; diff --git a/src/Ramstack.HtmxToolkit/HtmxFetchMode.cs b/src/Ramstack.HtmxToolkit/HtmxFetchMode.cs index 46835c1..3ec8c7f 100644 --- a/src/Ramstack.HtmxToolkit/HtmxFetchMode.cs +++ b/src/Ramstack.HtmxToolkit/HtmxFetchMode.cs @@ -7,7 +7,7 @@ namespace Ramstack.HtmxToolkit; /// In HTMX 4.x this is passed as the mode option of the Fetch API. /// /// In HTMX 1.x and 2.x (compatibility mode) this maps to the selfRequestsOnly -/// boolean configuration option, where yields +/// boolean configuration option, where yields /// and any other value yields . /// /// diff --git a/src/Ramstack.HtmxToolkit/HtmxFetchModeJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxFetchModeJsonConverter.cs index a1c5e1e..8b02b38 100644 --- a/src/Ramstack.HtmxToolkit/HtmxFetchModeJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxFetchModeJsonConverter.cs @@ -6,7 +6,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents a for nullable values. +/// Represents a for nullable values. /// internal sealed class HtmxFetchModeJsonConverter : JsonConverter { diff --git a/src/Ramstack.HtmxToolkit/HtmxFieldValues.cs b/src/Ramstack.HtmxToolkit/HtmxFieldValues.cs index 6e908c2..b552d3b 100644 --- a/src/Ramstack.HtmxToolkit/HtmxFieldValues.cs +++ b/src/Ramstack.HtmxToolkit/HtmxFieldValues.cs @@ -7,9 +7,6 @@ namespace Ramstack.HtmxToolkit; /// /// Represents one or more values for a form field submitted with an HTMX request. /// -/// -/// A single value can be assigned from a string. Multiple values can be specified with a collection expression. -/// [JsonConverter(typeof(HtmxFieldValuesJsonConverter))] [CollectionBuilder(typeof(HtmxFieldValues), nameof(Create))] public readonly struct HtmxFieldValues : IReadOnlyList @@ -55,33 +52,35 @@ public string this[int index] } /// - /// Gets the underlying value representation. + /// Gets the underlying storage: a string, a string array, or . /// internal object? Values => _values; /// - /// Initializes a new instance of the structure with a single value. + /// Initializes a new instance of the structure + /// with a single value. /// - /// The value to store, or to represent no values. + /// The value to store, or + /// to represent no values. public HtmxFieldValues(string? value) => _values = value; /// - /// Initializes a new instance of the structure with the specified values. + /// Initializes a new instance of the structure + /// with the specified values. /// - /// The values to store, or to represent no values. - /// - /// The specified array is stored directly and is not copied. - /// + /// The specified array is stored directly and is not copied. + /// The values to store, or + /// to represent no values. public HtmxFieldValues(string[]? values) => _values = values; /// - /// Creates an from the specified values. + /// Creates an from the specified values. /// /// The values to include. /// - /// An containing the specified values. + /// An containing the specified values. /// public static HtmxFieldValues Create(ReadOnlySpan values) { @@ -94,16 +93,24 @@ public static HtmxFieldValues Create(ReadOnlySpan values) } /// - /// Converts a string to an . + /// Converts a string to an . /// - /// The value to convert, or to represent no values. + /// The value to convert, or + /// to represent no values. + /// + /// An containing . + /// public static implicit operator HtmxFieldValues(string? value) => new(value); /// - /// Converts an array of strings to an . + /// Converts an array of strings to an . /// - /// The values to convert, or to represent no values. + /// The values to convert, or + /// to represent no values. + /// + /// An containing . + /// public static implicit operator HtmxFieldValues(string[]? values) => new(values); @@ -128,6 +135,13 @@ IEnumerator IEnumerable.GetEnumerator() => #endregion + /// + /// Throws the standard exception produced by indexing an empty array. + /// + /// + /// This method does not return. + /// + /// Always thrown. [MethodImpl(MethodImplOptions.NoInlining)] private static string OutOfBounds() => Array.Empty()[0]; @@ -135,15 +149,20 @@ private static string OutOfBounds() => /// /// Copies the specified read-only span to a new array. /// + /// + /// + /// The JIT compiler inlines the implementation of + /// into its caller, producing a disproportionately large amount of native code + /// at the call site. + /// + /// + /// This non-inlined wrapper keeps that implementation out of . + /// + /// /// The values to copy. /// /// A new array containing the specified values. /// - /// - /// The JIT compiler inlines the implementation of - /// into its caller, producing a disproportionately large amount of native code at the call site. - /// This non-inlined wrapper keeps that implementation out of . - /// [MethodImpl(MethodImplOptions.NoInlining)] private static string[] CreateArray(ReadOnlySpan s) => s.ToArray(); @@ -151,7 +170,7 @@ private static string[] CreateArray(ReadOnlySpan s) => #region Inner type: Enumerator /// - /// Enumerates the strings represented by an . + /// Enumerates the strings represented by an . /// public struct Enumerator : IEnumerator { @@ -163,7 +182,7 @@ public struct Enumerator : IEnumerator public readonly string Current => _current!; /// - /// Initializes a new enumerator for the specified . + /// Initializes a new enumerator for the specified . /// /// The value whose strings to enumerate. public Enumerator(HtmxFieldValues value) diff --git a/src/Ramstack.HtmxToolkit/HtmxFieldValuesJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxFieldValuesJsonConverter.cs index 98cd0d1..c40bddf 100644 --- a/src/Ramstack.HtmxToolkit/HtmxFieldValuesJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxFieldValuesJsonConverter.cs @@ -5,7 +5,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents a JSON converter for . +/// Represents a JSON converter for . /// internal sealed class HtmxFieldValuesJsonConverter : JsonConverter { diff --git a/src/Ramstack.HtmxToolkit/HtmxHistoryMode.cs b/src/Ramstack.HtmxToolkit/HtmxHistoryMode.cs index c5eec00..58dc23f 100644 --- a/src/Ramstack.HtmxToolkit/HtmxHistoryMode.cs +++ b/src/Ramstack.HtmxToolkit/HtmxHistoryMode.cs @@ -16,7 +16,8 @@ public enum HtmxHistoryMode Disabled, /// - /// Reloads the page when restoring history in HTMX 4. HTMX 1 and 2 treat this as . + /// Reloads the page when restoring history. /// + /// Supported only in HTMX 4.x. Reload } diff --git a/src/Ramstack.HtmxToolkit/HtmxHistoryModeJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxHistoryModeJsonConverter.cs index b16ef1f..553b0c0 100644 --- a/src/Ramstack.HtmxToolkit/HtmxHistoryModeJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxHistoryModeJsonConverter.cs @@ -4,23 +4,13 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents a for values -/// written in the format expected by the history configuration option: -/// and -/// are written as booleans, while any other value is written as its lowercase -/// string representation (e.g. "reload"). +/// Converts values to the JSON representation expected +/// by the history configuration option. /// -/// -/// Unlike other enum values, which are serialized as strings, this one requires a custom -/// converter: and -/// must be written as actual JSON booleans rather than strings, since otherwise HTMX -/// would not recognize them. -/// internal sealed class HtmxHistoryModeJsonConverter : JsonConverter { /// - /// Pre-encoded "reload" text; encoding it once as a static field avoids - /// repeated UTF-8 encoding overhead on each serialization. + /// The pre-encoded reload value used to avoid repeated UTF-8 encoding during serialization. /// private static readonly JsonEncodedText s_reload = JsonEncodedText.Encode("reload"); diff --git a/src/Ramstack.HtmxToolkit/HtmxLocationOptions.cs b/src/Ramstack.HtmxToolkit/HtmxLocationOptions.cs index 7d96aad..4277559 100644 --- a/src/Ramstack.HtmxToolkit/HtmxLocationOptions.cs +++ b/src/Ramstack.HtmxToolkit/HtmxLocationOptions.cs @@ -8,7 +8,7 @@ namespace Ramstack.HtmxToolkit; public sealed class HtmxLocationOptions { /// - /// Gets or sets the path used for the AJAX request. + /// Gets the path used for the AJAX request. /// /// Supported in HTMX 1.9.x, HTMX 2.x, and HTMX 4.x. public string? Path { get; internal set; } @@ -40,7 +40,7 @@ public sealed class HtmxLocationOptions /// /// Gets or sets the headers to include with the request. - /// Header values must be strings; complex data should be passed as a pre-serialized JSON string. + /// Header values must be strings. Pass complex data as a pre-serialized JSON string. /// /// Supported in HTMX 1.9.x, HTMX 2.x, and HTMX 4.x. public IDictionary? Headers { get; set; } @@ -54,13 +54,13 @@ public sealed class HtmxLocationOptions /// /// Gets or sets a selector used to select content for out-of-band swaps from the response. /// - /// Supported in HTMX 2.x and HTMX 4.x. + /// Supported only in HTMX 2.x. [JsonPropertyName("selectOOB")] public string? SelectOob { get; set; } /// /// Gets or sets the path to push into the browser history. - /// Set to false to prevent the URL from being pushed. + /// Set this property to "false" to prevent the URL from being pushed. /// /// Supported in HTMX 2.x and HTMX 4.x. public string? Push { get; set; } diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs b/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs index 3b615ab..892436f 100644 --- a/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs +++ b/src/Ramstack.HtmxToolkit/HtmxRequestAttribute.cs @@ -3,7 +3,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Identifies an action that supports HTMX requests. +/// Restricts an action to HTMX requests. /// [AttributeUsage(AttributeTargets.Method)] public sealed class HtmxRequestAttribute : Attribute, IActionConstraint @@ -12,14 +12,14 @@ public sealed class HtmxRequestAttribute : Attribute, IActionConstraint public int Order => 0; /// - /// Gets or sets a value that indicates whether the action should be executed - /// for boosted or non-boosted HTMX requests. + /// Gets or sets a value indicating whether the action accepts boosted + /// or non-boosted HTMX requests. /// /// /// - /// If set to , the action will be executed only for boosted requests. - /// If set to , the action will be executed only for non-boosted requests. - /// If set to , the action will be executed for any HTMX request. + /// accepts only boosted requests. + /// accepts only non-boosted requests. + /// accepts any HTMX request. /// /// public bool? Boosted { get; set; } @@ -28,8 +28,9 @@ public sealed class HtmxRequestAttribute : Attribute, IActionConstraint public bool Accept(ActionConstraintContext context) { var request = context.RouteContext.HttpContext.Request; - var boosted = Boosted; + if (request.IsHtmxRequest()) + return Boosted is null || request.IsHtmxBoosted() == Boosted.GetValueOrDefault(); - return request.IsHtmxRequest() && (boosted is null || request.IsHtmxBoosted() == boosted.Value); + return false; } } diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs b/src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs index f297dad..f553f07 100644 --- a/src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs +++ b/src/Ramstack.HtmxToolkit/HtmxRequestHeaderNames.cs @@ -2,8 +2,10 @@ namespace Ramstack.HtmxToolkit; /// /// Defines constants for the well-known names of HTMX request headers. -/// For more information, see https://htmx.org/reference/#request_headers /// +/// +/// For more information, see HTMX Request Headers Reference. +/// public static class HtmxRequestHeaderNames { /// @@ -24,28 +26,28 @@ public static class HtmxRequestHeaderNames public const string HistoryRestoreRequest = "HX-History-Restore-Request"; /// - /// The HX-Prompt header contains the user response to "hx-prompt". + /// The HX-Prompt header contains the user's response to an hx-prompt. /// public const string Prompt = "HX-Prompt"; /// - /// The HX-Request header is a general header sent with every HTMX request. - /// Always "true". + /// The HX-Request header indicates that the request was issued by HTMX. + /// Its value is always "true". /// public const string Request = "HX-Request"; /// - /// The HX-Target header contains the ID of the target element if it exists. + /// The HX-Target header contains the ID of the target element, if present. /// public const string Target = "HX-Target"; /// - /// The HX-Trigger-Name header contains the name of the triggered element if it exists. + /// The HX-Trigger-Name header contains the name of the triggered element, if present. /// public const string TriggerName = "HX-Trigger-Name"; /// - /// The HX-Trigger header contains the ID of the triggered element if it exists. + /// The HX-Trigger header contains the ID of the triggered element, if present. /// public const string Trigger = "HX-Trigger"; } diff --git a/src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs b/src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs index e02f809..550ff25 100644 --- a/src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs +++ b/src/Ramstack.HtmxToolkit/HtmxRequestHeaders.cs @@ -15,63 +15,98 @@ public readonly struct HtmxRequestHeaders private readonly IHeaderDictionary _headers; /// - /// Initializes a new instance of the structure. + /// Initializes a new instance of the structure. /// /// The HTTP request. internal HtmxRequestHeaders(HttpRequest request) => _headers = request.Headers; /// - /// Gets a value indicating whether the request was made using AJAX instead of a normal navigation. + /// Gets a value indicating whether the request was made + /// using AJAX instead of a normal navigation. /// - /// + /// + /// The header name is . + /// public bool Boosted => GetBoolean(_headers, HtmxRequestHeaderNames.Boosted); /// /// Gets the current URL of the browser. /// - /// + /// + /// The header name is . + /// public string? CurrentUrl => GetString(_headers, HtmxRequestHeaderNames.CurrentUrl); /// - /// Gets a value indicating whether the request is for history restoration after a miss in the local history cache. + /// Gets a value indicating whether the request restores history + /// after a miss in the local history cache. /// - /// + /// + /// The header name is . + /// public bool HistoryRestoreRequest => GetBoolean(_headers, HtmxRequestHeaderNames.HistoryRestoreRequest); /// /// Gets the user's response to an hx-prompt on the client. /// - /// + /// + /// The header name is . + /// public string? Prompt => GetString(_headers, HtmxRequestHeaderNames.Prompt); /// /// Gets a value indicating whether the current request is an HTMX request. /// - /// + /// + /// The header name is . + /// public bool Request => GetBoolean(_headers, HtmxRequestHeaderNames.Request); /// - /// Gets the ID of the target element if it exists. + /// Gets the ID of the target element, if present. /// - /// + /// + /// The header name is . + /// public string? Target => GetString(_headers, HtmxRequestHeaderNames.Target); /// - /// Gets the name of the triggered element if it exists. + /// Gets the name of the triggered element, if present. /// - /// + /// + /// The header name is . + /// public string? TriggerName => GetString(_headers, HtmxRequestHeaderNames.TriggerName); /// - /// Gets the ID of the triggered element if it exists as indicated by the HX-Trigger header. + /// Gets the ID of the triggered element, if present. /// - /// + /// + /// The header name is . + /// public string? Trigger => GetString(_headers, HtmxRequestHeaderNames.Trigger); + /// + /// Determines whether the specified header has the value "true". + /// + /// The header collection to inspect. + /// The name of the header. + /// + /// if the header value is "true"; + /// otherwise, . + /// private static bool GetBoolean(IHeaderDictionary dictionary, string key) => dictionary.TryGetValue(key, out var value) && value[0] == "true"; + /// + /// Gets the value of the specified header. + /// + /// The header collection to inspect. + /// The name of the header. + /// + /// The header value, or if the header is not present. + /// private static string? GetString(IHeaderDictionary dictionary, string key) { dictionary.TryGetValue(key, out var value); @@ -80,8 +115,18 @@ private static bool GetBoolean(IHeaderDictionary dictionary, string key) => #region Inner type: HtmxRequestHeadersDebugView + /// + /// Provides a debugger view for . + /// + /// The instance + /// whose headers will be displayed. private sealed class HtmxRequestHeadersDebugView(HtmxRequestHeaders headers) { + /// + /// Gets the collection of all HTTP headers stored + /// in the associated instance + /// as an array of key-value pairs. + /// [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public KeyValuePair[] Items => DebugHelpers.GetHeaders(headers._headers); } diff --git a/src/Ramstack.HtmxToolkit/HtmxResponse.cs b/src/Ramstack.HtmxToolkit/HtmxResponse.cs index dfa1c8d..986c128 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResponse.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResponse.cs @@ -11,8 +11,9 @@ namespace Ramstack.HtmxToolkit; /// Represents an HTTP response whose HTMX response headers can be configured. /// /// -/// Like and themselves, this type is not thread-safe. -/// Its members should not be called concurrently from multiple threads for the same request. +/// Like and themselves, +/// this type is not thread-safe. Its members should not be called concurrently +/// from multiple threads for the same request. /// [DebuggerTypeProxy(typeof(HtmxResponseDebugView))] public readonly struct HtmxResponse @@ -20,39 +21,41 @@ public readonly struct HtmxResponse private readonly HttpResponse _response; /// - /// The custom status code to stop the polling. + /// The HTTP status code used by HTMX to stop polling. /// public const int StopPollingStatusCode = 286; /// - /// Gets the HTMX headers. + /// Gets the strongly typed HTMX response headers. /// public HtmxResponseHeaders Headers => new(_response); /// - /// Initializes a new instance of the structure. + /// Initializes a new instance of the structure. /// /// The HTTP response. internal HtmxResponse(HttpResponse response) => _response = response; /// - /// Sets the HX-Location header to a client-side redirect that does not do a full page reload. + /// Sets the HX-Location header to perform a client-side redirect + /// without a full-page reload. /// - /// The header value to set. + /// The path or serialized JSON options to assign to the header. /// - /// The current instance. + /// The current instance. /// public HtmxResponse Location(string value) => SetHeader(this, HtmxResponseHeaderNames.Location, value); /// - /// Sets the HX-Location header to a client-side redirect that does not do a full page reload. + /// Sets the HX-Location header to perform a client-side redirect + /// without a full-page reload. /// - /// The path of the request. - /// The options for the HX-Location request. + /// The path to request. + /// The options used to issue the request. /// - /// The current instance. + /// The current instance. /// public HtmxResponse Location(string path, HtmxLocationOptions options) { @@ -62,27 +65,27 @@ static HtmxResponse LocationImpl(HtmxResponse response, string path, HtmxLocatio { options.Path = path; - var value = JsonSerializer.Serialize(options, HtmxLocationOptionsJsonSerializerContext.Default.HtmxLocationOptions); - return SetHeader(response, HtmxResponseHeaderNames.Location, value); + var json = JsonSerializer.Serialize(options, HtmxLocationOptionsJsonSerializerContext.Default.HtmxLocationOptions); + return SetHeader(response, HtmxResponseHeaderNames.Location, json); } } /// - /// Sets the HX-Push-Url header to push a new URL into the history stack. + /// Sets the HX-Push-Url header to push a new URL onto the browser's history stack. /// /// The header value to set. /// - /// The current instance. + /// The current instance. /// /// /// The possible values for this header are: /// /// /// A URL to be pushed into the location bar. This may be relative or absolute, - /// as per history.pushState(). + /// as supported by history.pushState(). /// /// - /// , which prevents the browser's history being updated. + /// "false", which prevents the browser's history from being updated. /// /// /// @@ -90,29 +93,30 @@ public HtmxResponse PushUrl(string value) => SetHeader(this, HtmxResponseHeaderNames.PushUrl, value); /// - /// Sets the HX-Push-Url header to that prevents the browser's history being updated. + /// Sets the HX-Push-Url header to "false" to prevent the browser's + /// history from being updated. /// /// - /// The current instance. + /// The current instance. /// public HtmxResponse PreventPushUrl() => SetHeader(this, HtmxResponseHeaderNames.PushUrl, "false"); /// - /// Sets the HX-Redirect header to a client-side redirect to a new location. + /// Sets the HX-Redirect header to perform a client-side redirect to a new location. /// /// The header value to set. /// - /// The current instance. + /// The current instance. /// public HtmxResponse Redirect(string value) => SetHeader(this, HtmxResponseHeaderNames.Redirect, value); /// - /// Sets the HX-Refresh header to full refresh of the page. + /// Sets the HX-Refresh header to request a full-page refresh. /// /// - /// The current instance. + /// The current instance. /// public HtmxResponse Refresh() => SetHeader(this, HtmxResponseHeaderNames.Refresh, "true"); @@ -122,18 +126,19 @@ public HtmxResponse Refresh() => ///
/// The header value to set. /// - /// The current instance. + /// The current instance. /// /// /// The possible values for this header are: /// /// - /// A URL to replace the current URL in the location bar. This may be relative or absolute, - /// as per history.replaceState(), + /// A URL to replace the current URL in the location bar. This may be relative + /// or absolute, as supported by + /// history.replaceState(), /// but must have the same origin as the current URL. /// /// - /// , which prevents the browser's current URL from being updated. + /// "false", which prevents the browser's current URL from being updated. /// /// /// @@ -141,10 +146,11 @@ public HtmxResponse ReplaceUrl(string value) => SetHeader(this, HtmxResponseHeaderNames.ReplaceUrl, value); /// - /// Sets the HX-Replace-Url header to that prevents the browser's history being updated. + /// Sets the HX-Replace-Url header to "false" to prevent the browser's + /// current URL from being updated. /// /// - /// The current instance. + /// The current instance. /// public HtmxResponse PreventReplaceUrl() => SetHeader(this, HtmxResponseHeaderNames.ReplaceUrl, "false"); @@ -152,9 +158,9 @@ public HtmxResponse PreventReplaceUrl() => /// /// Sets the HX-Reswap header to specify how the response will be swapped. /// - /// The header value to set. + /// The swap style to assign to the header. /// - /// The current instance. + /// The current instance. /// public HtmxResponse Reswap(HtmxSwap value) => SetHeader(this, HtmxResponseHeaderNames.Reswap, value.GetSwapValue()); @@ -164,7 +170,7 @@ public HtmxResponse Reswap(HtmxSwap value) => ///
/// The header value to set. /// - /// The current instance. + /// The current instance. /// public HtmxResponse Reswap(string value) => SetHeader(this, HtmxResponseHeaderNames.Reswap, value); @@ -175,41 +181,41 @@ public HtmxResponse Reswap(string value) => /// /// The CSS selector to set. /// - /// The current instance. + /// The current instance. /// public HtmxResponse Retarget(string value) => SetHeader(this, HtmxResponseHeaderNames.Retarget, value); /// - /// Sets the HX-Reselect header to choose which part of the response is used to be swapped in. + /// Sets the HX-Reselect header to select the part of the response to swap in. /// /// The CSS selector to set. /// - /// The current instance. + /// The current instance. /// public HtmxResponse Reselect(string value) => SetHeader(this, HtmxResponseHeaderNames.Reselect, value); /// - /// Sets one of HX-Trigger headers to trigger a client-side event. + /// Adds a client-side event to the response header selected by . /// /// The event name to trigger. - /// The time at which the event will be triggered. Defaults to . + /// The event timing. Defaults to . /// - /// The current instance. + /// The current instance. /// public HtmxResponse TriggerEvent(string eventName, HtmxTriggerTiming trigger = HtmxTriggerTiming.Receive) => TriggerEvent(eventName, "", trigger); /// - /// Sets one of HX-Trigger headers to trigger a client-side event. + /// Adds a client-side event and its detail to the response header selected by + /// . /// /// The event name to trigger. /// The event detail. - /// The time at which an event will be triggered. - /// Defaults to . + /// The event timing. Defaults to . /// - /// The current instance. + /// The current instance. /// public HtmxResponse TriggerEvent(string eventName, object detail, HtmxTriggerTiming timing = HtmxTriggerTiming.Receive) { @@ -220,32 +226,32 @@ static HtmxResponse TriggerEventImpl(HtmxResponse response, string eventName, ob } /// - /// Sets one of HX-Trigger headers to trigger client-side events. + /// Adds client-side events to the response header selected by . /// - /// A dictionary containing event names as keys and event details as values. - /// The time at which an event will be triggered. - /// Defaults to . + /// The event names and their associated details. + /// The event timing. Defaults to . /// - /// The current instance. + /// The current instance. /// public HtmxResponse TriggerEvents(IReadOnlyDictionary events, HtmxTriggerTiming timing = HtmxTriggerTiming.Receive) => AddEvents(this, events, timing); /// - /// Sets the special HTTP status code 286 that is used to stop the polling. + /// Sets HTTP status code 286 to stop polling. /// /// - /// The current instance. + /// The current instance. /// public HtmxResponse StopPolling() => StopPolling(true); /// - /// Sets the special HTTP status code 286 to stop the polling. + /// Sets HTTP status code 286 when is . /// - /// A boolean condition indicating whether to stop the polling. + /// to stop polling; + /// otherwise, . /// - /// The current instance. + /// The current instance. /// public HtmxResponse StopPolling(bool condition) { @@ -255,12 +261,30 @@ public HtmxResponse StopPolling(bool condition) return this; } + /// + /// Sets a response header and returns the response wrapper for fluent chaining. + /// + /// The response wrapper to update. + /// The name of the header. + /// The header value. + /// + /// The updated response wrapper. + /// private static HtmxResponse SetHeader(HtmxResponse response, string key, string value) { response._response.Headers[key] = [with(value)]; return response; } + /// + /// Adds pending client-side events and returns the response wrapper for fluent chaining. + /// + /// The response wrapper to update. + /// The event names and their associated details. + /// The time at which to trigger the events. + /// + /// The updated response wrapper. + /// private static HtmxResponse AddEvents(HtmxResponse response, IReadOnlyDictionary events, HtmxTriggerTiming timing) { PendingEvents.GetOrCreate(response._response).AddEvents(timing, events); @@ -269,8 +293,18 @@ private static HtmxResponse AddEvents(HtmxResponse response, IReadOnlyDictionary #region Inner type: HtmxResponseDebugView + /// + /// Provides a debugger view for . + /// + /// The instance + /// whose response headers will be displayed. private sealed class HtmxResponseDebugView(HtmxResponse response) { + /// + /// Gets the collection of HTTP response headers + /// from the associated instance + /// as an array of key-value pairs. + /// [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public KeyValuePair[] Items => DebugHelpers.GetHeaders(response._response.Headers); } diff --git a/src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs b/src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs index 6d89057..8770ba6 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResponseAttribute.cs @@ -8,7 +8,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Identifies an action that sets HTMX response headers. +/// Specifies HTMX response headers to apply when an action result is executed for an HTMX request. /// [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] public sealed class HtmxResponseAttribute : Attribute, IResultFilter @@ -16,7 +16,8 @@ public sealed class HtmxResponseAttribute : Attribute, IResultFilter private readonly List<(string Key, string Value)> _headers = []; /// - /// Gets or sets the HX-Refresh header to perform a full page refresh. + /// Gets or sets a value indicating whether the HX-Refresh header is set + /// to request a full-page refresh. /// public bool Refresh { @@ -25,7 +26,7 @@ public bool Refresh } /// - /// Gets or sets the HX-Reswap header to specify how the response will be swapped into the DOM. + /// Gets or sets the swap style to specify in the HX-Reswap header. /// public HtmxSwap Reswap { @@ -38,7 +39,7 @@ public HtmxSwap Reswap } /// - /// Gets or sets the HX-Reswap header to specify how the response will be swapped into the DOM. + /// Gets or sets the complete HX-Reswap header value, including any swap modifiers. /// [MaybeNull] public string ReswapExpression @@ -48,8 +49,7 @@ public string ReswapExpression } /// - /// Gets or sets the HX-Retarget header that specifies a selector to change - /// the target of the content update to a different element on the page. + /// Gets or sets the CSS selector to specify in the HX-Retarget header. /// [MaybeNull] public string Retarget @@ -59,8 +59,7 @@ public string Retarget } /// - /// Gets or sets the HX-Reselect header that specifies a selector - /// to choose which part of the response content will be swapped in. + /// Gets or sets the CSS selector to specify in the HX-Reselect header. /// [MaybeNull] public string Reselect @@ -70,7 +69,7 @@ public string Reselect } /// - /// Gets or sets a value indicating whether a special HTTP status code should be set to stop polling. + /// Gets or sets a value indicating whether to set HTTP status code 286 to stop polling. /// public bool StopPolling { get; set; } @@ -94,6 +93,13 @@ public void OnResultExecuted(ResultExecutedContext context) { } + /// + /// Gets the pending value of the specified response header. + /// + /// The name of the header. + /// + /// The header value, or if no value has been configured. + /// private string? GetValue(string key) { foreach (ref var kvp in CollectionsMarshal.AsSpan(_headers)) @@ -103,6 +109,11 @@ public void OnResultExecuted(ResultExecutedContext context) return null; } + /// + /// Adds a nonempty response header value to the pending headers. + /// + /// The name of the header. + /// The header value. private void SetValue(string key, string value) { if (!string.IsNullOrEmpty(value)) diff --git a/src/Ramstack.HtmxToolkit/HtmxResponseHeaderNames.cs b/src/Ramstack.HtmxToolkit/HtmxResponseHeaderNames.cs index 5203ded..f9bbf6f 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResponseHeaderNames.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResponseHeaderNames.cs @@ -2,68 +2,69 @@ namespace Ramstack.HtmxToolkit; /// /// Defines constants for the well-known names of HTMX response headers. -/// For more information, see https://htmx.org/reference/#response_headers /// +/// +/// For more information, see HTMX Response Headers Reference. +/// public static class HtmxResponseHeaderNames { /// - /// The HX-Location header is used to perform a client-side redirect without a full page reload. + /// The HX-Location header performs a client-side redirect without a full-page reload. /// public const string Location = "HX-Location"; /// - /// The HX-Push-Url header is used to push a new URL into the browser's history stack. + /// The HX-Push-Url header pushes a new URL onto the browser's history stack. /// public const string PushUrl = "HX-Push-Url"; /// - /// The HX-Redirect header is used to perform a client-side redirect to a new location. + /// The HX-Redirect header performs a client-side redirect to a new location. /// public const string Redirect = "HX-Redirect"; /// - /// The HX-Refresh header is used to perform a full page refresh. + /// The HX-Refresh header performs a full-page refresh when its value is "true". /// public const string Refresh = "HX-Refresh"; /// - /// The HX-Replace-Url header is used to replace the current URL + /// The HX-Replace-Url header replaces the current URL /// without pushing a new entry to the browser's history stack. /// public const string ReplaceUrl = "HX-Replace-Url"; /// - /// The HX-Reswap header is used to specify how the response will be swapped into the DOM. + /// The HX-Reswap header specifies how the response is swapped into the DOM. /// public const string Reswap = "HX-Reswap"; /// - /// The HX-Retarget header sets a selector to change - /// the target of the content update to a different element on the page. + /// The HX-Retarget header specifies a CSS selector + /// that changes the target of the content update. /// public const string Retarget = "HX-Retarget"; /// - /// The HX-Reselect header sets a selector to choose - /// which part of the response content will be swapped in. + /// The HX-Reselect header specifies a CSS selector that determines + /// which part of the response is swapped in. /// public const string Reselect = "HX-Reselect"; /// - /// The HX-Trigger header is used to trigger an event on the client side - /// after the server response has been processed. + /// The HX-Trigger header triggers client-side events. /// public const string Trigger = "HX-Trigger"; /// - /// The HX-Trigger-After-Settle header is used to trigger an event - /// on the client side after the HTMX request has settled. + /// The HX-Trigger-After-Settle header triggers client-side events after the settle step. /// + /// Supported only in HTMX 1.x and 2.x. public const string TriggerAfterSettle = "HX-Trigger-After-Settle"; /// - /// The HX-Trigger-After-Swap header is used to trigger an event - /// on the client side after the response has been swapped into the DOM. + /// The HX-Trigger-After-Swap header triggers client-side events after the swap step. /// + /// Supported only in HTMX 1.x and 2.x. public const string TriggerAfterSwap = "HX-Trigger-After-Swap"; } diff --git a/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs b/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs index 82eef4c..7ba7e24 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResponseHeaders.cs @@ -15,14 +15,15 @@ public readonly struct HtmxResponseHeaders private readonly HttpResponse _response; /// - /// Initializes a new instance of the structure. + /// Initializes a new instance of the structure. /// /// The HTTP response. internal HtmxResponseHeaders(HttpResponse response) => _response = response; /// - /// Gets or sets the HX-Location header to perform a client-side redirect without a full page reload. + /// Gets or sets the value of the HX-Location header, which performs + /// a client-side redirect without a full-page reload. /// [MaybeNull] public string Location @@ -32,7 +33,8 @@ public string Location } /// - /// Gets or sets the HX-Push-Url header to push a new URL into the browser's history stack. + /// Gets or sets the value of the HX-Push-Url header, which pushes a new URL + /// onto the browser's history stack. /// [MaybeNull] public string PushUrl @@ -42,7 +44,8 @@ public string PushUrl } /// - /// Gets or sets the HX-Redirect header to perform a client-side redirect to a new location. + /// Gets or sets the value of the HX-Redirect header, which performs + /// a client-side redirect to a new location. /// [MaybeNull] public string Redirect @@ -52,7 +55,7 @@ public string Redirect } /// - /// Gets or sets the HX-Refresh header to perform a full page refresh. + /// Gets or sets a value indicating whether the HX-Refresh header requests a full-page refresh. /// public bool Refresh { @@ -61,7 +64,7 @@ public bool Refresh } /// - /// Gets or sets the HX-Replace-Url header to replace the current URL + /// Gets or sets the value of the HX-Replace-Url header, which replaces the current URL /// without pushing a new entry to the browser's history stack. /// [MaybeNull] @@ -72,7 +75,7 @@ public string ReplaceUrl } /// - /// Gets or sets the HX-Reswap header to specify how the response will be swapped into the DOM. + /// Gets or sets the swap style specified by the HX-Reswap header. /// [DisallowNull] public HtmxSwap? Reswap @@ -82,7 +85,7 @@ public HtmxSwap? Reswap } /// - /// Gets or sets the HX-Reswap header to specify how the response will be swapped into the DOM. + /// Gets or sets the complete HX-Reswap header value, including any swap modifiers. /// [MaybeNull] public string ReswapExpression @@ -92,8 +95,8 @@ public string ReswapExpression } /// - /// Gets or sets the HX-Retarget header that specifies a selector to change - /// the target of the content update to a different element on the page. + /// Gets or sets the CSS selector specified by the HX-Retarget header + /// to change the target of the content update. /// [MaybeNull] public string Retarget @@ -103,8 +106,8 @@ public string Retarget } /// - /// Gets or sets the HX-Reselect header that specifies a selector - /// to choose which part of the response content will be swapped in. + /// Gets or sets the CSS selector specified by the HX-Reselect header + /// to determine which part of the response is swapped in. /// [MaybeNull] public string Reselect @@ -114,12 +117,11 @@ public string Reselect } /// - /// Gets or sets the HX-Trigger header, which specifies a dictionary of client-side events - /// to trigger after the server response is processed. + /// Gets or sets the client-side events to trigger through the HX-Trigger header. /// /// - /// Event values are accumulated for the current response and serialized into the header immediately - /// before the response starts. + /// Event values are accumulated for the current response and serialized + /// into the header immediately before the response starts. /// [MaybeNull] public IReadOnlyDictionary Trigger @@ -129,12 +131,15 @@ public IReadOnlyDictionary Trigger } /// - /// Gets or sets the HX-Trigger-After-Swap header, which specifies a dictionary of client-side events - /// to trigger after the response content has been swapped into the DOM. + /// Gets or sets the client-side events to trigger through + /// the HX-Trigger-After-Swap header after the swap step. /// /// - /// Event values are accumulated for the current response and serialized into the header immediately - /// before the response starts. + /// + /// Event values are accumulated for the current response and serialized + /// into the header immediately before the response starts. + /// + /// This header is supported only in HTMX 1.x and 2.x. /// [MaybeNull] public IReadOnlyDictionary TriggerAfterSwap @@ -144,12 +149,15 @@ public IReadOnlyDictionary TriggerAfterSwap } /// - /// Gets or sets the HX-Trigger-After-Settle header, which specifies a dictionary of client-side events - /// to trigger after the HTMX request has settled. + /// Gets or sets the client-side events to trigger through + /// the HX-Trigger-After-Settle header after the settle step. /// /// - /// Event values are accumulated for the current response and serialized into the header immediately - /// before the response starts. + /// + /// Event values are accumulated for the current response and serialized + /// into the header immediately before the response starts. + /// + /// This header is supported only in HTMX 1.x and 2.x. /// [MaybeNull] public IReadOnlyDictionary TriggerAfterSettle @@ -158,12 +166,26 @@ public IReadOnlyDictionary TriggerAfterSettle set => PendingEvents.GetOrCreate(_response).SetEvents(HtmxTriggerTiming.AfterSettle, value); } + /// + /// Gets the value of the specified header. + /// + /// The header collection to inspect. + /// The name of the header. + /// + /// The header value, or if the header is not present. + /// private static string? GetHeader(IHeaderDictionary headers, string key) { headers.TryGetValue(key, out var values); return values; } + /// + /// Sets the specified header when is not . + /// + /// The header collection to update. + /// The name of the header. + /// The header value. private static void SetHeader(IHeaderDictionary headers, string key, string? value) { if (value is not null) @@ -172,8 +194,18 @@ private static void SetHeader(IHeaderDictionary headers, string key, string? val #region Inner type: HtmxResponseHeadersDebugView + /// + /// Provides a debugger view for . + /// + /// The instance + /// whose response headers will be displayed. private sealed class HtmxResponseHeadersDebugView(HtmxResponseHeaders headers) { + /// + /// Gets the collection of HTTP response headers + /// from the associated instance + /// as an array of key-value pairs. + /// [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public KeyValuePair[] Items => DebugHelpers.GetHeaders(headers._response.Headers); } diff --git a/src/Ramstack.HtmxToolkit/HtmxResult.cs b/src/Ramstack.HtmxToolkit/HtmxResult.cs index b806f27..0e33d61 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResult.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResult.cs @@ -3,10 +3,11 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents an that is used to configure the HTMX response headers. +/// Wraps an and configures HTMX response headers +/// before executing it for an HTMX request. /// -/// The to produce the response result. -/// The function to configure the HTMX response headers. +/// The action result to execute. +/// The delegate that configures the HTMX response headers. public sealed class HtmxResult(IActionResult result, Action configure) : IActionResult { /// diff --git a/src/Ramstack.HtmxToolkit/HtmxResult`1.cs b/src/Ramstack.HtmxToolkit/HtmxResult`1.cs index a1925fd..85b95c1 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResult`1.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResult`1.cs @@ -3,12 +3,17 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents an that is used to configure the HTMX response headers. +/// Wraps an and configures HTMX response headers +/// before executing it for an HTMX request. /// -/// The type of the value to pass to . Used to reduce memory allocations. -/// The to produce the response result. -/// The function to configure the HTMX response headers. -/// The value to pass to . +/// The type of state passed to . +/// The action result to execute. +/// The delegate that configures the HTMX response headers +/// using . +/// The state passed to . +/// +/// The state parameter enables callers to avoid closure allocations. +/// public sealed class HtmxResult(IActionResult result, Action configure, TState state) : IActionResult { /// diff --git a/src/Ramstack.HtmxToolkit/HtmxScrollBehavior.cs b/src/Ramstack.HtmxToolkit/HtmxScrollBehavior.cs index 2182ae1..a29e312 100644 --- a/src/Ramstack.HtmxToolkit/HtmxScrollBehavior.cs +++ b/src/Ramstack.HtmxToolkit/HtmxScrollBehavior.cs @@ -6,17 +6,17 @@ namespace Ramstack.HtmxToolkit; public enum HtmxScrollBehavior { /// - /// Specifies instant scrolling behavior, similar to a vanilla link. + /// Uses the auto scrolling behavior. /// Auto, /// - /// Specifies smooth scrolling to the top of the page. + /// Uses the smooth scrolling behavior. /// Smooth, /// - /// Specifies instant scrolling with no animation. + /// Uses the instant scrolling behavior. /// Supported only in HTMX 2.x. /// Instant diff --git a/src/Ramstack.HtmxToolkit/HtmxScrollBehaviorJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxScrollBehaviorJsonConverter.cs index 02cf09c..775d159 100644 --- a/src/Ramstack.HtmxToolkit/HtmxScrollBehaviorJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxScrollBehaviorJsonConverter.cs @@ -6,7 +6,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents a for nullable values. +/// Represents a for nullable values. /// internal sealed class HtmxScrollBehaviorJsonConverter : JsonConverter { diff --git a/src/Ramstack.HtmxToolkit/HtmxSwap.cs b/src/Ramstack.HtmxToolkit/HtmxSwap.cs index 62ee1f7..ec6c78b 100644 --- a/src/Ramstack.HtmxToolkit/HtmxSwap.cs +++ b/src/Ramstack.HtmxToolkit/HtmxSwap.cs @@ -61,7 +61,7 @@ public enum HtmxSwap Delete, /// - /// Does not append content from the response (out-of-band items will still be processed). + /// Does not swap content from the response. Out-of-band items are still processed. /// None } diff --git a/src/Ramstack.HtmxToolkit/HtmxSwapJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxSwapJsonConverter.cs index ce56ff4..7babc0b 100644 --- a/src/Ramstack.HtmxToolkit/HtmxSwapJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxSwapJsonConverter.cs @@ -6,7 +6,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents a for nullable values. +/// Represents a for nullable values. /// internal sealed class HtmxSwapJsonConverter : JsonConverter { diff --git a/src/Ramstack.HtmxToolkit/HtmxToolkitOptions.cs b/src/Ramstack.HtmxToolkit/HtmxToolkitOptions.cs index a37c98d..4aff53e 100644 --- a/src/Ramstack.HtmxToolkit/HtmxToolkitOptions.cs +++ b/src/Ramstack.HtmxToolkit/HtmxToolkitOptions.cs @@ -4,7 +4,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents configuration options for services provided by the HTMX toolkit. +/// Represents configuration options for services provided by HTMX Toolkit. /// public sealed class HtmxToolkitOptions { @@ -28,8 +28,9 @@ public HtmxConfig HtmxConfig } /// - /// Gets or sets a value indicating whether antiforgery request metadata is rendered by the configuration tag helper. - /// Defaults to . + /// Gets or sets a value indicating whether antiforgery request metadata is rendered + /// by the configuration tag helper. + /// Defaults to . /// public bool IncludeAntiforgeryToken { get; set; } = true; @@ -45,6 +46,9 @@ public HtmxConfig HtmxConfig /// /// The current options instance. /// + /// + /// A different HTMX major version has already been selected. + /// [MemberNotNull(nameof(_config))] public HtmxToolkitOptions UseHtmxV1(Action? configure = null) { @@ -60,6 +64,9 @@ public HtmxToolkitOptions UseHtmxV1(Action? configure = null) /// /// The current options instance. /// + /// + /// A different HTMX major version has already been selected. + /// [MemberNotNull(nameof(_config))] public HtmxToolkitOptions UseHtmxV2(Action? configure = null) { @@ -75,6 +82,9 @@ public HtmxToolkitOptions UseHtmxV2(Action? configure = null) /// /// The current options instance. /// + /// + /// A different HTMX major version has already been selected. + /// [MemberNotNull(nameof(_config))] public HtmxToolkitOptions UseHtmxV4(Action? configure = null) { @@ -84,13 +94,15 @@ public HtmxToolkitOptions UseHtmxV4(Action? configure = null) } /// - /// Returns the selected version-specific HTMX configuration, - /// and throws an exception if the requested configuration type does not match the configured HTMX target version. + /// Returns the selected version-specific HTMX configuration. /// /// The expected configuration type. /// /// The requested configuration instance. /// + /// + /// does not match the selected HTMX major version. + /// public TConfig GetHtmxConfig() where TConfig : HtmxConfig { if (HtmxConfig is TConfig config) @@ -137,8 +149,8 @@ private void EnsureCanSelectVersion(HtmxTargetVersion version) } /// - /// Throws an when the requested HTMX configuration type - /// does not match the configured target version. + /// Throws an when the requested HTMX + /// configuration type does not match the configured target version. /// /// The current HTMX target version. /// Always thrown. @@ -147,7 +159,8 @@ private static void Error_ConfigTypeMismatch(HtmxTargetVersion version) => throw new InvalidOperationException($"HTMX configuration version '{version}' does not match the requested configuration type."); /// - /// Throws an when attempting to reconfigure the HTMX target version. + /// Throws an when attempting to reconfigure + /// the HTMX target version. /// /// The version that has already been configured. /// The new version being attempted. diff --git a/src/Ramstack.HtmxToolkit/HtmxTriggerSpecsCacheJsonConverter.cs b/src/Ramstack.HtmxToolkit/HtmxTriggerSpecsCacheJsonConverter.cs index a409d13..627e5db 100644 --- a/src/Ramstack.HtmxToolkit/HtmxTriggerSpecsCacheJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HtmxTriggerSpecsCacheJsonConverter.cs @@ -4,10 +4,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents a that serializes the triggerSpecsCache -/// configuration option from its boolean form: is written as an empty -/// JSON object ({}), instructing HTMX to use a never-clearing trigger specification cache, -/// while and are written as JSON null. +/// Converts the boolean triggerSpecsCache abstraction to its HTMX JSON representation. /// internal sealed class HtmxTriggerSpecsCacheJsonConverter : JsonConverter { diff --git a/src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs b/src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs index 2137f4d..d603282 100644 --- a/src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs +++ b/src/Ramstack.HtmxToolkit/HtmxTriggerTiming.cs @@ -1,25 +1,29 @@ namespace Ramstack.HtmxToolkit; /// -/// Specifies the time at which an event will be triggered in HTMX. +/// Specifies the response header used to trigger client-side events. /// public enum HtmxTriggerTiming { /// - /// Maps to the HX-Trigger header that is used to trigger an event - /// on the client side after the server response is processed. + /// Maps to the HX-Trigger header. /// + /// + /// HTMX 1.x and 2.x trigger these events when the response is received. + /// HTMX 4.x triggers them after the swap completes. + /// Receive, /// - /// Maps to the HX-Trigger-After-Swap header that is used to trigger an event - /// on the client side after the response content has been swapped into the DOM. + /// Maps to the HX-Trigger-After-Swap header, which triggers events after the swap step. /// + /// Supported only in HTMX 1.x and 2.x. AfterSwap, /// - /// Maps to the HX-Trigger-After-Settle header that is used to trigger an event - /// on the client side after the HTMX request has settled. + /// Maps to the HX-Trigger-After-Settle header, which triggers events + /// after the settle step. /// + /// Supported only in HTMX 1.x and 2.x. AfterSettle } diff --git a/src/Ramstack.HtmxToolkit/HtmxV1Config.cs b/src/Ramstack.HtmxToolkit/HtmxV1Config.cs index bac0afa..1dcf201 100644 --- a/src/Ramstack.HtmxToolkit/HtmxV1Config.cs +++ b/src/Ramstack.HtmxToolkit/HtmxV1Config.cs @@ -10,190 +10,192 @@ public sealed class HtmxV1Config() : HtmxConfig(HtmxTargetVersion.V1) { /// /// Gets or sets a value indicating whether HTMX history support is enabled. - /// Defaults to . + /// The HTMX default is . /// public bool? HistoryEnabled { get; set; } /// /// Gets or sets the size of the history cache. - /// Defaults to 10. + /// The HTMX default is 10. /// public int? HistoryCacheSize { get; set; } /// - /// Gets or sets a value indicating whether a full page refresh should be issued + /// Gets or sets a value indicating whether a full-page refresh should be issued /// on history misses rather than using an AJAX request. - /// Defaults to . + /// The HTMX default is . /// public bool? RefreshOnHistoryMiss { get; set; } /// - /// Gets or sets the default swap style. Defaults to . + /// Gets or sets the default swap style. + /// The HTMX default is . /// [JsonConverter(typeof(HtmxSwapJsonConverter))] public HtmxSwap? DefaultSwapStyle { get; set; } /// /// Gets or sets the default swap delay in milliseconds. - /// Defaults to 0. + /// The HTMX default is 0. /// public int? DefaultSwapDelay { get; set; } /// /// Gets or sets the default settle delay in milliseconds. - /// Defaults to 20. + /// The HTMX default is 20. /// public int? DefaultSettleDelay { get; set; } /// /// Gets or sets a value indicating whether the indicator styles are loaded. - /// Defaults to . + /// The HTMX default is . /// public bool? IncludeIndicatorStyles { get; set; } /// /// Gets or sets the indicator class. - /// Defaults to htmx-indicator. + /// The HTMX default is htmx-indicator. /// public string? IndicatorClass { get; set; } /// /// Gets or sets the request class. - /// Defaults to htmx-request. + /// The HTMX default is htmx-request. /// public string? RequestClass { get; set; } /// /// Gets or sets the added class. - /// Defaults to htmx-added. + /// The HTMX default is htmx-added. /// public string? AddedClass { get; set; } /// /// Gets or sets the swapping class. - /// Defaults to htmx-swapping. + /// The HTMX default is htmx-swapping. /// public string? SwappingClass { get; set; } /// /// Gets or sets the settling class. - /// Defaults to htmx-settling. + /// The HTMX default is htmx-settling. /// public string? SettlingClass { get; set; } /// - /// Gets or sets a value indicating whether eval is allowed. - /// Defaults to . + /// Gets or sets a value indicating whether the use of eval is allowed. + /// The HTMX default is . /// public bool? AllowEval { get; set; } /// /// Gets or sets a value indicating whether script tags should be processed in new content. - /// Defaults to . + /// The HTMX default is . /// public bool? AllowScriptTags { get; set; } /// /// Gets or sets the nonce added to inline scripts. - /// Defaults to an empty string. + /// The HTMX default is an empty string. /// public string? InlineScriptNonce { get; set; } /// /// Gets or sets the attributes to settle during the settling phase. - /// Defaults to ["class", "style", "width", "height"]. + /// The HTMX default is ["class", "style", "width", "height"]. /// public string[]? AttributesToSettle { get; set; } /// - /// Gets or sets a value indicating whether HTML template tags should be used for parsing content. - /// Defaults to . + /// Gets or sets a value indicating whether HTML template tags are used to parse content. + /// The HTMX default is . /// public bool? UseTemplateFragments { get; set; } /// - /// Gets or sets the WebSocket reconnect delay. Defaults to full-jitter. + /// Gets or sets the WebSocket reconnection delay strategy. + /// The HTMX default is full-jitter. /// public string? WsReconnectDelay { get; set; } /// /// Gets or sets the type of binary data received over WebSocket connections. - /// Defaults to . + /// The HTMX default is . /// [JsonConverter(typeof(HtmxBinaryTypeJsonConverter))] public HtmxBinaryType? WsBinaryType { get; set; } /// /// Gets or sets the selector for elements that HTMX must not process. - /// Defaults to [disable-htmx], [data-disable-htmx]. + /// The HTMX default is [disable-htmx], [data-disable-htmx]. /// public string? DisableSelector { get; set; } /// - /// Gets or sets a value indicating whether cross-site requests include credentials. - /// Defaults to . + /// Gets or sets a value indicating whether credentials are included in cross-origin requests. + /// The HTMX default is . /// public bool? WithCredentials { get; set; } /// - /// Gets or sets the number of milliseconds a request can take before being terminated. - /// Defaults to 0. + /// Gets or sets the request timeout, in milliseconds. + /// The HTMX default is 0. /// public int? Timeout { get; set; } /// /// Gets or sets a value indicating whether requests are restricted to the current origin. - /// Defaults to . + /// The HTMX default is . /// public bool? SelfRequestsOnly { get; set; } /// /// Gets or sets the scrolling behavior for boosted links. - /// Defaults to . + /// The HTMX default is . /// [JsonConverter(typeof(HtmxScrollBehaviorJsonConverter))] public HtmxScrollBehavior? ScrollBehavior { get; set; } /// /// Gets or sets a value indicating whether the focused element should be scrolled into view. - /// Defaults to . + /// The HTMX default is . /// public bool? DefaultFocusScroll { get; set; } /// - /// Gets or sets a value indicating whether a cache-busting parameter should be included in GET requests. - /// Defaults to . + /// Gets or sets a value indicating whether GET requests use a cache-busting parameter. + /// The HTMX default is . /// public bool? GetCacheBusterParam { get; set; } /// /// Gets or sets a value indicating whether the View Transition API should be used for swaps. - /// Defaults to . + /// The HTMX default is . /// public bool? GlobalViewTransitions { get; set; } /// /// Gets or sets the HTTP methods that use URL parameters. - /// Defaults to ["get"]. + /// The HTMX default is ["get"]. /// [JsonConverter(typeof(HttpVerbArrayJsonConverter))] public HttpVerb[]? MethodsThatUseUrlParams { get; set; } /// /// Gets or sets a value indicating whether document titles found in new content are ignored. - /// Defaults to . + /// The HTMX default is . /// public bool? IgnoreTitle { get; set; } /// /// Gets or sets a value indicating whether boosted targets are scrolled into the viewport. - /// Defaults to . + /// The HTMX default is . /// public bool? ScrollIntoViewOnBoost { get; set; } /// - /// Gets or sets a value indicating whether HTMX uses a never-clearing cache for parsed trigger specifications. - /// Defaults to . + /// Gets or sets a value indicating whether parsed trigger specifications use + /// a never-clearing cache. The cache is disabled by default. /// [JsonPropertyName("triggerSpecsCache")] [JsonConverter(typeof(HtmxTriggerSpecsCacheJsonConverter))] diff --git a/src/Ramstack.HtmxToolkit/HtmxV2Config.cs b/src/Ramstack.HtmxToolkit/HtmxV2Config.cs index 1789c60..bdfab03 100644 --- a/src/Ramstack.HtmxToolkit/HtmxV2Config.cs +++ b/src/Ramstack.HtmxToolkit/HtmxV2Config.cs @@ -12,197 +12,198 @@ public sealed class HtmxV2Config() : HtmxConfig(HtmxTargetVersion.V2) { /// /// Gets or sets a value indicating whether HTMX history support is enabled. - /// Defaults to . + /// The HTMX default is . /// public bool? HistoryEnabled { get; set; } /// /// Gets or sets the size of the history cache. - /// Defaults to 10. + /// The HTMX default is 10. /// public int? HistoryCacheSize { get; set; } /// - /// Gets or sets a value indicating whether a full page refresh should be issued on history misses rather than using an AJAX request. - /// Defaults to . + /// Gets or sets a value indicating whether a history miss causes a full-page refresh + /// instead of an AJAX request. + /// The HTMX default is . /// public bool? RefreshOnHistoryMiss { get; set; } /// /// Gets or sets the default swap style. - /// Defaults to . + /// The HTMX default is . /// [JsonConverter(typeof(HtmxSwapJsonConverter))] public HtmxSwap? DefaultSwapStyle { get; set; } /// /// Gets or sets the default swap delay in milliseconds. - /// Defaults to 0. + /// The HTMX default is 0. /// public int? DefaultSwapDelay { get; set; } /// /// Gets or sets the default settle delay in milliseconds. - /// Defaults to 20. + /// The HTMX default is 20. /// public int? DefaultSettleDelay { get; set; } /// /// Gets or sets a value indicating whether the indicator styles are loaded. - /// Defaults to . + /// The HTMX default is . /// public bool? IncludeIndicatorStyles { get; set; } /// /// Gets or sets the indicator class. - /// Defaults to htmx-indicator. + /// The HTMX default is htmx-indicator. /// public string? IndicatorClass { get; set; } /// /// Gets or sets the request class. - /// Defaults to htmx-request. + /// The HTMX default is htmx-request. /// public string? RequestClass { get; set; } /// /// Gets or sets the added class. - /// Defaults to htmx-added. + /// The HTMX default is htmx-added. /// public string? AddedClass { get; set; } /// /// Gets or sets the swapping class. - /// Defaults to htmx-swapping. + /// The HTMX default is htmx-swapping. /// public string? SwappingClass { get; set; } /// /// Gets or sets the settling class. - /// Defaults to htmx-settling. + /// The HTMX default is htmx-settling. /// public string? SettlingClass { get; set; } /// - /// Gets or sets a value indicating whether eval is allowed. - /// Defaults to . + /// Gets or sets a value indicating whether the use of eval is allowed. + /// The HTMX default is . /// public bool? AllowEval { get; set; } /// /// Gets or sets a value indicating whether script tags should be processed in new content. - /// Defaults to . + /// The HTMX default is . /// public bool? AllowScriptTags { get; set; } /// /// Gets or sets the nonce added to inline scripts. - /// Defaults to an empty string. + /// The HTMX default is an empty string. /// public string? InlineScriptNonce { get; set; } /// /// Gets or sets the nonce added to inline styles. - /// Defaults to an empty string. + /// The HTMX default is an empty string. /// public string? InlineStyleNonce { get; set; } /// /// Gets or sets the attributes to settle during the settling phase. - /// Defaults to ["class", "style", "width", "height"]. + /// The HTMX default is ["class", "style", "width", "height"]. /// public string[]? AttributesToSettle { get; set; } /// - /// Gets or sets the WebSocket reconnect delay. - /// Defaults to full-jitter. + /// Gets or sets the WebSocket reconnection delay strategy. + /// The HTMX default is full-jitter. /// public string? WsReconnectDelay { get; set; } /// /// Gets or sets the type of binary data received over WebSocket connections. - /// Defaults to . + /// The HTMX default is . /// [JsonConverter(typeof(HtmxBinaryTypeJsonConverter))] public HtmxBinaryType? WsBinaryType { get; set; } /// /// Gets or sets the selector for elements that HTMX must not process. - /// Defaults to [disable-htmx], [data-disable-htmx]. + /// The HTMX default is [disable-htmx], [data-disable-htmx]. /// public string? DisableSelector { get; set; } /// - /// Gets or sets a value indicating whether cross-site requests include credentials. - /// Defaults to . + /// Gets or sets a value indicating whether credentials are included in cross-origin requests. + /// The HTMX default is . /// public bool? WithCredentials { get; set; } /// /// Gets or sets a value indicating whether attribute inheritance is disabled. - /// Defaults to . + /// The HTMX default is . /// public bool? DisableInheritance { get; set; } /// - /// Gets or sets the number of milliseconds a request can take before being terminated. - /// Defaults to 0. + /// Gets or sets the request timeout, in milliseconds. + /// The HTMX default is 0. /// public int? Timeout { get; set; } /// /// Gets or sets a value indicating whether requests are restricted to the current origin. - /// Defaults to . + /// The HTMX default is . /// public bool? SelfRequestsOnly { get; set; } /// /// Gets or sets the scrolling behavior for boosted links. - /// Defaults to . + /// The HTMX default is . /// [JsonConverter(typeof(HtmxScrollBehaviorJsonConverter))] public HtmxScrollBehavior? ScrollBehavior { get; set; } /// /// Gets or sets a value indicating whether the focused element should be scrolled into view. - /// Defaults to . + /// The HTMX default is . /// public bool? DefaultFocusScroll { get; set; } /// - /// Gets or sets a value indicating whether a cache-busting parameter should be included in GET requests. - /// Defaults to . + /// Gets or sets a value indicating whether GET requests use a cache-busting parameter. + /// The HTMX default is . /// public bool? GetCacheBusterParam { get; set; } /// /// Gets or sets a value indicating whether the View Transition API should be used for swaps. - /// Defaults to . + /// The HTMX default is . /// public bool? GlobalViewTransitions { get; set; } /// /// Gets or sets the HTTP methods that use URL parameters. - /// Defaults to ["get", "delete"]. + /// The HTMX default is ["get", "delete"]. /// [JsonConverter(typeof(HttpVerbArrayJsonConverter))] public HttpVerb[]? MethodsThatUseUrlParams { get; set; } /// /// Gets or sets a value indicating whether document titles found in new content are ignored. - /// Defaults to . + /// The HTMX default is . /// public bool? IgnoreTitle { get; set; } /// /// Gets or sets a value indicating whether boosted targets are scrolled into the viewport. - /// Defaults to . + /// The HTMX default is . /// public bool? ScrollIntoViewOnBoost { get; set; } /// - /// Gets or sets a value indicating whether HTMX uses a never-clearing cache for parsed trigger specifications. - /// Defaults to . + /// Gets or sets a value indicating whether parsed trigger specifications use + /// a never-clearing cache. The cache is disabled by default. /// [JsonConverter(typeof(HtmxTriggerSpecsCacheJsonConverter))] [JsonPropertyName("triggerSpecsCache")] @@ -214,20 +215,23 @@ public sealed class HtmxV2Config() : HtmxConfig(HtmxTargetVersion.V2) public IList? ResponseHandling { get; set; } /// - /// Gets or sets a value indicating whether out-of-band swaps nested in the main response are processed. - /// Defaults to . + /// Gets or sets a value indicating whether out-of-band swaps nested in the main + /// response are processed. + /// The HTMX default is . /// public bool? AllowNestedOobSwaps { get; set; } /// - /// Gets or sets a value indicating whether history restoration requests include HTMX request headers. - /// Defaults to . + /// Gets or sets a value indicating whether history cache-miss requests are marked + /// as HTMX requests. + /// The HTMX default is . /// public bool? HistoryRestoreAsHxRequest { get; set; } /// - /// Gets or sets a value indicating whether form validity is reported before a request is issued. - /// Defaults to . + /// Gets or sets a value indicating whether form validity is reported before + /// a request is issued. + /// The HTMX default is . /// public bool? ReportValidityOfForms { get; set; } diff --git a/src/Ramstack.HtmxToolkit/HtmxV4Config.cs b/src/Ramstack.HtmxToolkit/HtmxV4Config.cs index cd5756b..fd2ef2e 100644 --- a/src/Ramstack.HtmxToolkit/HtmxV4Config.cs +++ b/src/Ramstack.HtmxToolkit/HtmxV4Config.cs @@ -10,136 +10,140 @@ public sealed class HtmxV4Config() : HtmxConfig(HtmxTargetVersion.V4) { /// /// Gets or sets a value indicating whether all HTMX events are logged to the console. - /// Defaults to . + /// The HTMX default is . /// public bool? LogAll { get; set; } /// - /// Gets or sets the secondary attribute prefix recognized alongside hx-. - /// Defaults to data-hx-. + /// Gets or sets the secondary attribute prefix recognized alongside hx-*. + /// The HTMX default is data-hx-. /// public string? Prefix { get; set; } /// /// Gets or sets the character used instead of : in attribute names. + /// The HTMX default is undefined. /// public string? MetaCharacter { get; set; } /// /// Gets or sets how HTMX history restoration is handled. - /// Defaults to . + /// The HTMX default is . /// [JsonConverter(typeof(HtmxHistoryModeJsonConverter))] public HtmxHistoryMode? History { get; set; } /// /// Gets or sets the default swap style. - /// Defaults to . + /// The HTMX default is . /// [JsonConverter(typeof(HtmxSwapJsonConverter))] public HtmxSwap? DefaultSwap { get; set; } /// - /// Gets or sets a value indicating whether an empty response body should replace the main swap target. + /// Gets or sets a value indicating whether an empty response body replaces the main swap target. + /// The HTMX default is undefined. /// public bool? DefaultSwapEmpty { get; set; } /// /// Gets or sets the default settle delay in milliseconds. - /// Defaults to 1. + /// The HTMX default is 1. /// public int? DefaultSettleDelay { get; set; } /// /// Gets or sets a value indicating whether the indicator styles are loaded. - /// Defaults to . + /// The HTMX default is . /// [JsonPropertyName("includeIndicatorCSS")] public bool? IncludeIndicatorCss { get; set; } /// /// Gets or sets the indicator class. - /// Defaults to htmx-indicator. + /// The HTMX default is htmx-indicator. /// public string? IndicatorClass { get; set; } /// /// Gets or sets the request class. - /// Defaults to htmx-request. + /// The HTMX default is htmx-request. /// public string? RequestClass { get; set; } /// - /// Gets or sets a value meaning that no nonce will be added to inline scripts. - /// Defaults to "". + /// Gets or sets the nonce added to inline scripts. + /// The HTMX default is undefined, which means that no nonce is added. /// public string? InlineScriptNonce { get; set; } /// /// Gets or sets a comma-separated list of extensions that HTMX is allowed to load. - /// Defaults to an empty string. + /// The HTMX default is an empty string. /// public string? Extensions { get; set; } /// /// Gets or sets a value indicating whether HTMX attributes are inherited implicitly. - /// Defaults to . + /// The HTMX default is . /// public bool? ImplicitInheritance { get; set; } /// /// Gets or sets the default request timeout in milliseconds. - /// Defaults to 60000. + /// The HTMX default is 60000. /// public int? DefaultTimeout { get; set; } /// /// Gets or sets the request mode passed to the Fetch API. - /// Defaults to same-origin. + /// The HTMX default is same-origin. /// [JsonConverter(typeof(HtmxFetchModeJsonConverter))] public HtmxFetchMode? Mode { get; set; } /// /// Gets or sets a value indicating whether the focused element should be scrolled into view. - /// Defaults to and can be overridden using the focus-scroll swap modifier. + /// The HTMX default is and can be overridden + /// using the focus-scroll swap modifier. /// public bool? DefaultFocusScroll { get; set; } /// /// Gets or sets a value indicating whether the - /// View Transition API - /// should be used when swapping in new content. Defaults to . + /// View Transition API + /// should be used when swapping in new content. + /// The HTMX default is . /// public bool? Transitions { get; set; } /// /// Gets or sets the attribute name prefixes to preserve during morphing. - /// Defaults to ["data-htmx-powered"]. + /// The HTMX default is ["data-htmx-powered"]. /// public string[]? MorphIgnore { get; set; } /// /// Gets or sets the selector for elements to skip during morphing. - /// Defaults to [hx-morph-skip]. + /// The HTMX default is [hx-morph-skip]. /// public string? MorphSkip { get; set; } /// /// Gets or sets the selector for elements whose children should not be morphed. - /// Defaults to [hx-morph-skip-children]. + /// The HTMX default is [hx-morph-skip-children]. /// public string? MorphSkipChildren { get; set; } /// /// Gets or sets the maximum number of siblings scanned while matching elements during morphing. - /// Defaults to 10. + /// The HTMX default is 10. /// public int? MorphScanLimit { get; set; } /// /// Gets or sets the response status codes or patterns for which HTMX does not perform a swap. - /// Defaults to [204, 304]. + /// The HTMX default is [204, 304]. /// /// /// Although HTMX declares this option as a number array, it converts each entry to a string diff --git a/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs b/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs index e1ae5a6..1b420c1 100644 --- a/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs +++ b/src/Ramstack.HtmxToolkit/HttpRequestExtensions.cs @@ -3,7 +3,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Provides extension methods for the class. +/// Provides extension methods for the class. /// public static class HttpRequestExtensions { @@ -22,10 +22,11 @@ public static bool IsHtmxRequest(this HttpRequest request) => /// Determines whether the specified HTTP request is an HTMX request. /// /// The HTTP request. - /// When this method returns, contains the + /// When this method returns, contains the /// that provides access to well-known HTMX headers. /// - /// if the specified HTTP request is an HTMX request; otherwise, . + /// if the specified HTTP request is an HTMX request; + /// otherwise, . /// public static bool IsHtmxRequest(this HttpRequest request, out HtmxRequestHeaders headers) { @@ -38,20 +39,21 @@ public static bool IsHtmxRequest(this HttpRequest request, out HtmxRequestHeader /// /// The HTTP request. /// - /// if the specified HTTP request is boosted; otherwise, . + /// if the specified HTTP request is boosted; + /// otherwise, . /// public static bool IsHtmxBoosted(this HttpRequest request) => request.Headers.TryGetValue(HtmxRequestHeaderNames.Boosted, out var value) && value is ["true"]; /// - /// Determines whether the specified HTTP request was made using AJAX - /// instead of a normal navigation. + /// Determines whether the specified HTTP request was made using AJAX instead of a normal navigation. /// /// The HTTP request. - /// When this method returns, contains the + /// When this method returns, contains the /// that provides access to well-known HTMX headers. /// - /// if the specified HTTP request is boosted; otherwise, . + /// if the specified HTTP request is boosted; + /// otherwise, . /// public static bool IsHtmxBoosted(this HttpRequest request, out HtmxRequestHeaders headers) { @@ -60,11 +62,11 @@ public static bool IsHtmxBoosted(this HttpRequest request, out HtmxRequestHeader } /// - /// Returns the that provides access to well-known HTMX headers. + /// Returns a strongly typed view of the HTMX request headers. /// /// The HTTP request. /// - /// The . + /// The . /// public static HtmxRequestHeaders GetHtmxHeaders(this HttpRequest request) => new(request); diff --git a/src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs b/src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs index 7cc2cc8..bfd75bc 100644 --- a/src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs +++ b/src/Ramstack.HtmxToolkit/HttpResponseExtensions.cs @@ -3,16 +3,16 @@ namespace Ramstack.HtmxToolkit; /// -/// Provides extension methods for the class. +/// Provides extension methods for the class. /// public static class HttpResponseExtensions { /// - /// Returns the that provides access to well-known HTMX headers. + /// Returns a strongly typed view of the HTMX response headers. /// /// The HTTP response. /// - /// The . + /// The . /// public static HtmxResponseHeaders GetHtmxHeaders(this HttpResponse response) => new(response); @@ -21,7 +21,7 @@ public static HtmxResponseHeaders GetHtmxHeaders(this HttpResponse response) => /// Configures the HTMX response headers. /// /// The HTTP response to configure. - /// The function to configure the HTMX response headers. + /// The delegate that configures the HTMX response headers. public static void Htmx(this HttpResponse response, Action configure) { if (response.HttpContext.Request.IsHtmxRequest()) @@ -32,8 +32,9 @@ public static void Htmx(this HttpResponse response, Action configu /// Configures the HTMX response headers. /// /// The HTTP response to configure. - /// The function to configure the HTMX response headers. - /// The value to pass to the . + /// The delegate that configures the HTMX response headers + /// using . + /// The state passed to . public static void Htmx(this HttpResponse response, Action configure, TState state) { if (response.HttpContext.Request.IsHtmxRequest()) diff --git a/src/Ramstack.HtmxToolkit/HttpVerb.cs b/src/Ramstack.HtmxToolkit/HttpVerb.cs index de04385..201f931 100644 --- a/src/Ramstack.HtmxToolkit/HttpVerb.cs +++ b/src/Ramstack.HtmxToolkit/HttpVerb.cs @@ -11,7 +11,8 @@ public enum HttpVerb Get, /// - /// The HEAD method asks for a response identical to a GET request, but without the response body. + /// The HEAD method requests a response identical to a GET response, + /// but without the response body. /// Head, @@ -21,7 +22,8 @@ public enum HttpVerb Post, /// - /// The PUT method replaces all current representations of the target resource with the request payload. + /// The PUT method replaces all current representations of the target resource + /// with the request payload. /// Put, @@ -31,17 +33,20 @@ public enum HttpVerb Delete, /// - /// The CONNECT method establishes a tunnel to the server identified by the target resource. + /// The CONNECT method establishes a tunnel to the server + /// identified by the target resource. /// Connect, /// - /// The OPTIONS method describes the communication options for the target resource. + /// The OPTIONS method describes the communication options + /// for the target resource. /// Options, /// - /// The TRACE method performs a message loop-back test along the path to the target resource. + /// The TRACE method performs a message loop-back test + /// along the path to the target resource. /// Trace, diff --git a/src/Ramstack.HtmxToolkit/HttpVerbArrayJsonConverter.cs b/src/Ramstack.HtmxToolkit/HttpVerbArrayJsonConverter.cs index f88fb46..bf93b71 100644 --- a/src/Ramstack.HtmxToolkit/HttpVerbArrayJsonConverter.cs +++ b/src/Ramstack.HtmxToolkit/HttpVerbArrayJsonConverter.cs @@ -6,7 +6,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Represents a for arrays of values. +/// Represents a for arrays of values. /// internal sealed class HttpVerbArrayJsonConverter : JsonConverter { diff --git a/src/Ramstack.HtmxToolkit/Internal/DebugHelpers.cs b/src/Ramstack.HtmxToolkit/Internal/DebugHelpers.cs index 972a9c3..b1382e7 100644 --- a/src/Ramstack.HtmxToolkit/Internal/DebugHelpers.cs +++ b/src/Ramstack.HtmxToolkit/Internal/DebugHelpers.cs @@ -3,16 +3,17 @@ namespace Ramstack.HtmxToolkit.Internal; /// -/// Provides helper methods for debugging purposes. +/// Provides helper methods for debugger views. /// internal static class DebugHelpers { /// - /// Extracts all headers that start with "HX-" (case-insensitive) from the given header collection. + /// Returns all headers whose names start with "HX-", + /// using a case-insensitive comparison. /// /// The header dictionary to inspect. /// - /// An array of key-value pairs representing the headers that start with "HX-". + /// An array containing the matching header names and values. /// public static KeyValuePair[] GetHeaders(IHeaderDictionary headers) { diff --git a/src/Ramstack.HtmxToolkit/Internal/EnumHelper.cs b/src/Ramstack.HtmxToolkit/Internal/EnumHelper.cs index bb5f687..5d56111 100644 --- a/src/Ramstack.HtmxToolkit/Internal/EnumHelper.cs +++ b/src/Ramstack.HtmxToolkit/Internal/EnumHelper.cs @@ -6,21 +6,23 @@ namespace Ramstack.HtmxToolkit.Internal; internal static class EnumHelper { /// - /// Converts a value to its corresponding WebSocket binary type string. + /// Converts a value + /// to the corresponding WebSocket binary type string. /// - /// The value. + /// The value. /// - /// The string representation: either "blob" or "arraybuffer". + /// blob or arraybuffer. /// public static string GetWsBinaryTypeValue(this HtmxBinaryType value) => value == HtmxBinaryType.Blob ? "blob" : "arraybuffer"; /// - /// Converts a value to its corresponding string value used in HTML scroll behavior. + /// Converts a value + /// to the corresponding scrolling behavior string. /// - /// The value. + /// The value. /// - /// The string representation: "auto", "smooth" or "instant". + /// auto, smooth, or instant. /// public static string GetScrollBehaviorValue(this HtmxScrollBehavior value) { @@ -33,10 +35,10 @@ public static string GetScrollBehaviorValue(this HtmxScrollBehavior value) } /// - /// Converts a value to its corresponding string representation, + /// Converts a value to its corresponding string representation, /// or returns if the value is . /// - /// The nullable value. + /// The nullable value. /// /// The string representation of the value, /// or if the value is . @@ -45,12 +47,13 @@ public static string GetScrollBehaviorValue(this HtmxScrollBehavior value) value?.GetSwapValue(); /// - /// Converts a value to its corresponding string representation used in HTMX attributes. + /// Converts a value to the corresponding string + /// representation used in HTMX attributes. /// - /// The value. + /// The value. /// - /// The corresponding string, such as "innerHTML", "beforebegin", etc. - /// Defaults to "none" if the value is unrecognized. + /// The corresponding HTMX swap value, or none if + /// is not recognized. /// public static string GetSwapValue(this HtmxSwap value) { @@ -72,11 +75,11 @@ public static string GetSwapValue(this HtmxSwap value) } /// - /// Converts a value to its corresponding lowercase HTTP method string. + /// Converts a value to its corresponding lowercase HTTP method string. /// - /// The value. + /// The value. /// - /// The lowercase string representation, such as "get", "post", "delete", etc. + /// The lowercase HTTP method name, such as get, post, or delete. /// public static string GetHttpVerbValue(this HttpVerb value) { @@ -95,11 +98,12 @@ public static string GetHttpVerbValue(this HttpVerb value) } /// - /// Converts a value to its corresponding Fetch API request mode string. + /// Converts a value + /// to the corresponding Fetch API request mode string. /// - /// The value. + /// The value. /// - /// The string representation: "same-origin", "cors" or "no-cors". + /// same-origin, cors, or no-cors. /// public static string GetFetchModeValue(this HtmxFetchMode value) { @@ -112,11 +116,11 @@ public static string GetFetchModeValue(this HtmxFetchMode value) } /// - /// Parses a string into a value. + /// Parses a string into a value. /// /// The string to parse. /// - /// The parsed value if successful; + /// The parsed value if successful; /// otherwise, . /// public static HtmxFetchMode? ParseHtmxFetchMode(string? expression) @@ -131,11 +135,11 @@ public static string GetFetchModeValue(this HtmxFetchMode value) } /// - /// Parses a string into a value. + /// Parses a string into a value. /// /// The string to parse. /// - /// The parsed value if successful; + /// The parsed value if successful; /// otherwise, . /// public static HtmxSwap? ParseHtmxSwap(string? expression) diff --git a/src/Ramstack.HtmxToolkit/Internal/JsonOptions.cs b/src/Ramstack.HtmxToolkit/Internal/JsonOptions.cs index c0fd200..f25eac3 100644 --- a/src/Ramstack.HtmxToolkit/Internal/JsonOptions.cs +++ b/src/Ramstack.HtmxToolkit/Internal/JsonOptions.cs @@ -6,26 +6,29 @@ namespace Ramstack.HtmxToolkit.Internal; /// -/// Provides preconfigured for JSON serialization. +/// Provides preconfigured for JSON serialization. /// internal static class JsonOptions { /// - /// Encodes all Unicode ranges while escaping JavaScript and HTML-sensitive characters. + /// Preserves characters from all Unicode ranges while escaping JavaScript- + /// and HTML-sensitive characters. /// private static readonly JavaScriptEncoder s_encoder = JavaScriptEncoder.Create(new TextEncoderSettings(UnicodeRanges.All)); /// - /// Configures serializer options to preserve Unicode characters while escaping HTML-sensitive characters. + /// Configures serializer options to preserve Unicode characters while escaping + /// JavaScript- and HTML-sensitive characters. /// /// The serializer options to configure. public static void ConfigureHtmlSafeUnicode(JsonSerializerOptions options) => options.Encoder = s_encoder; /// - /// JSON serializer options using for property names and dictionary keys, - /// and ignoring properties with values. + /// The shared JSON serializer options that use + /// for property names and dictionary keys and omit properties + /// whose values are . /// public static readonly JsonSerializerOptions CamelCase = new() { diff --git a/src/Ramstack.HtmxToolkit/PendingEvents.cs b/src/Ramstack.HtmxToolkit/PendingEvents.cs index 5f4eac2..27fe7d4 100644 --- a/src/Ramstack.HtmxToolkit/PendingEvents.cs +++ b/src/Ramstack.HtmxToolkit/PendingEvents.cs @@ -8,7 +8,7 @@ namespace Ramstack.HtmxToolkit; /// -/// Accumulates HTMX events per for a single request, +/// Accumulates HTMX events by for a single request, /// deferring header serialization until the response is about to start. /// internal sealed class PendingEvents @@ -21,18 +21,19 @@ internal sealed class PendingEvents private SmallDictionary? _afterSettle; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The HTTP response to which the events belong. private PendingEvents(HttpResponse response) => _response = response; /// - /// Adds the specified events to the pending set for the given . - /// When a key already exists, the duplicate event is accumulated under a rs:events key and replayed client-side. + /// Adds the specified events to the pending set for . + /// When an event name already exists, the duplicate is stored under the + /// rs:events key for client-side replay. /// - /// The time at which the events will be triggered. - /// A dictionary containing event names as keys and event details as values. + /// The time at which to trigger the events. + /// The event names and their associated details. public void AddEvents(HtmxTriggerTiming timing, IReadOnlyDictionary events) { var current = timing switch @@ -58,11 +59,11 @@ public void AddEvents(HtmxTriggerTiming timing, IReadOnlyDictionary - /// Returns the pending events for the specified . + /// Returns the pending events for the specified . /// - /// The time at which the events will be triggered. + /// The time at which to trigger the events. /// - /// The pending events, or if none were registered. + /// The pending events, or if none were registered. /// public IReadOnlyDictionary? GetEvents(HtmxTriggerTiming timing) { @@ -75,10 +76,10 @@ public void AddEvents(HtmxTriggerTiming timing, IReadOnlyDictionary - /// Replaces the pending events for the specified . + /// Replaces the pending events for the specified . /// - /// The time at which the events will be triggered. - /// A dictionary containing event names as keys and event details as values. + /// The time at which to trigger the events. + /// The replacement event names and their associated details. public void SetEvents(HtmxTriggerTiming timing, IReadOnlyDictionary events) { var replacement = new SmallDictionary(events, StringComparer.Ordinal); @@ -97,7 +98,8 @@ public void SetEvents(HtmxTriggerTiming timing, IReadOnlyDictionary - /// Serializes the accumulated events, if any, into the corresponding HX-Trigger response headers. + /// Serializes the accumulated events, if any, into the corresponding + /// HX-Trigger response headers. /// public void Flush() { @@ -111,13 +113,14 @@ public void Flush() /// /// The HTTP response that owns the events. /// - /// The pending events accumulator, or if none was registered. + /// The pending events accumulator, or if none was registered. /// public static PendingEvents? TryGet(HttpResponse response) => response.HttpContext.Items[typeof(PendingEvents)] as PendingEvents; /// - /// Returns the pending events accumulator, creating and registering it for the response when necessary. + /// Returns the pending events accumulator, creating and registering it + /// for the response when necessary. /// /// The HTTP response that owns the events. /// @@ -142,6 +145,12 @@ public static PendingEvents GetOrCreate(HttpResponse response) return pending; } + /// + /// Serializes the specified events into a response header + /// when the collection is not . + /// + /// The response header name. + /// The events to serialize. private void SetHeader(string name, SmallDictionary? events) { if (events is not null) diff --git a/src/Ramstack.HtmxToolkit/Properties/CollectionBuilderAttribute.cs b/src/Ramstack.HtmxToolkit/Properties/CollectionBuilderAttribute.cs index 444806b..ff1aa00 100644 --- a/src/Ramstack.HtmxToolkit/Properties/CollectionBuilderAttribute.cs +++ b/src/Ramstack.HtmxToolkit/Properties/CollectionBuilderAttribute.cs @@ -1,4 +1,6 @@ #if !NET8_0_OR_GREATER + +// ReSharper disable once CheckNamespace namespace System.Runtime.CompilerServices; /// @@ -7,17 +9,6 @@ namespace System.Runtime.CompilerServices; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] internal sealed class CollectionBuilderAttribute : Attribute { - /// - /// Initializes a new instance of the class. - /// - /// The type containing the builder method. - /// The name of the builder method. - public CollectionBuilderAttribute(Type builderType, string methodName) - { - BuilderType = builderType; - MethodName = methodName; - } - /// /// Gets the type containing the builder method. /// @@ -27,5 +18,17 @@ public CollectionBuilderAttribute(Type builderType, string methodName) /// Gets the name of the builder method. /// public string MethodName { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The type containing the builder method. + /// The name of the builder method. + public CollectionBuilderAttribute(Type builderType, string methodName) + { + BuilderType = builderType; + MethodName = methodName; + } } + #endif diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs index 1a020b2..18a8865 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxConfigTagHelper.cs @@ -8,8 +8,7 @@ namespace Ramstack.HtmxToolkit.TagHelpers; /// -/// Represents the implementation that renders -/// the application-wide HTMX configuration as a meta element. +/// Renders the application-wide HTMX configuration as a meta element. /// /// The service used to generate antiforgery tokens. /// The configured HTMX Toolkit options. @@ -22,7 +21,7 @@ public sealed class HtmxConfigTagHelper(IAntiforgery antiforgery, IOptions - /// Gets or sets the current view context. + /// Gets or sets the view context for the current request. /// [ViewContext] [HtmlAttributeNotBound] diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs index d69f0fc..5f7347d 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxHeaderTagHelper.cs @@ -8,7 +8,7 @@ namespace Ramstack.HtmxToolkit.TagHelpers; /// -/// Represents a implementation that applies the hx-headers attribute to matching elements. +/// Applies an hx-headers attribute assembled from strongly typed tag helper attributes. /// /// /// diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestJsonSerializerContext.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestJsonSerializerContext.cs index f77f907..09a65ef 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestJsonSerializerContext.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestJsonSerializerContext.cs @@ -12,7 +12,7 @@ namespace Ramstack.HtmxToolkit.TagHelpers; PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, GenerationMode = JsonSourceGenerationMode.Default)] -[JsonSerializable(typeof(HtmxRequestTagHelper.HtmxRequestDataLegacy))] +[JsonSerializable(typeof(HtmxRequestTagHelper.HtmxRequestDataPrior))] [JsonSerializable(typeof(HtmxRequestTagHelper.HtmxRequestDataV4))] internal partial class HtmxRequestJsonSerializerContext : JsonSerializerContext { diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestTagHelper.cs index 00d9257..6420a9d 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxRequestTagHelper.cs @@ -7,11 +7,11 @@ namespace Ramstack.HtmxToolkit.TagHelpers; /// -/// Represents a implementation that applies request configuration to matching elements. +/// Applies version-specific HTMX request configuration to matching elements. /// /// -/// HTMX 1.x and 2.x use merge-inherited hx-request -/// HTMX 4.x uses hx-config +/// HTMX 1.x and 2.x use the merge-inherited hx-request attribute. +/// HTMX 4.x uses the hx-config attribute. /// [HtmlTargetElement(Attributes = RequestTimeoutAttributeName)] [HtmlTargetElement(Attributes = RequestCredentialsAttributeName)] @@ -50,16 +50,18 @@ public int? Timeout /// /// /// - /// In HTMX 1.x and 2.x this maps to the credentials boolean option of hx-request, - /// where yields and - /// yields . + /// In HTMX 1.x and 2.x, this property maps to the Boolean + /// credentials option of hx-request. + /// yields . + /// yields . /// /// - /// In HTMX 4.x this maps to the credentials string option of hx-config. + /// In HTMX 4.x, this property maps to the string credentials option + /// of hx-config. /// /// - /// is unsupported in HTMX 1.x and 2.x, so the option - /// is omitted and HTMX uses its default value. A future version may throw an exception instead. + /// is unsupported in HTMX 1.x and 2.x, + /// so the option is omitted and HTMX uses its default value. /// /// [HtmlAttributeName(RequestCredentialsAttributeName)] @@ -70,7 +72,7 @@ public HtmxRequestCredentials? Credentials } /// - /// Gets or sets a value indicating whether HTMX strips all request headers. + /// Gets or sets a value indicating whether HTMX-specific request headers are omitted. /// /// Supported in HTMX 1.x and 2.x. Removed in HTMX 4.x. [HtmlAttributeName(RequestNoHeadersAttributeName)] @@ -141,7 +143,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp var targetVersion = options.Value.TargetVersion; var request = targetVersion == HtmxTargetVersion.V4 ? JsonSerializer.Serialize(new HtmxRequestDataV4(_request), HtmxRequestJsonSerializerContext.Default.HtmxRequestDataV4) - : JsonSerializer.Serialize(new HtmxRequestDataLegacy(_request), HtmxRequestJsonSerializerContext.Default.HtmxRequestDataLegacy); + : JsonSerializer.Serialize(new HtmxRequestDataPrior(_request), HtmxRequestJsonSerializerContext.Default.HtmxRequestDataPrior); if (request != "{}") { @@ -156,27 +158,47 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp #region Inner types /// - /// Represents all typed request configuration data. + /// Stores the request configuration shared by all supported HTMX versions. /// internal sealed class HtmxRequestData { + /// public int? Timeout { get; set; } + + /// public HtmxRequestCredentials? Credentials { get; set; } + + /// public bool? NoHeaders { get; set; } + + /// public string? Cache { get; set; } + + /// public string? Redirect { get; set; } + + /// public string? Referrer { get; set; } + + /// public string? Integrity { get; set; } + + /// public bool? Validate { get; set; } } /// /// Projects request configuration into the hx-request contract used by HTMX 1.x and 2.x. /// - internal readonly struct HtmxRequestDataLegacy(HtmxRequestData data) + /// The shared request configuration. + internal readonly struct HtmxRequestDataPrior(HtmxRequestData data) { + /// public int? Timeout => data.Timeout; + /// + /// Gets the boolean credentials value supported by HTMX 1.x and 2.x. + /// public bool? Credentials => data.Credentials switch { HtmxRequestCredentials.SameOrigin => false, @@ -186,15 +208,22 @@ internal readonly struct HtmxRequestDataLegacy(HtmxRequestData data) _ => null }; + /// public bool? NoHeaders => data.NoHeaders; } /// /// Projects request configuration into the hx-config contract used by HTMX 4.x. /// + /// The shared request configuration. internal readonly struct HtmxRequestDataV4(HtmxRequestData data) { + /// public int? Timeout => data.Timeout; + + /// + /// Gets the Fetch API credentials mode supported by HTMX 4.x. + /// public string? Credentials => data.Credentials switch { HtmxRequestCredentials.SameOrigin => "same-origin", @@ -203,10 +232,19 @@ internal readonly struct HtmxRequestDataV4(HtmxRequestData data) _ => null }; + /// public string? Cache => data.Cache; + + /// public string? Redirect => data.Redirect; + + /// public string? Referrer => data.Referrer; + + /// public string? Integrity => data.Integrity; + + /// public bool? Validate => data.Validate; } diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs index c9fa704..a0a1d5f 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxUrlTagHelper.cs @@ -12,10 +12,9 @@ namespace Ramstack.HtmxToolkit.TagHelpers; /// -/// Represents a implementation -/// used to generate URIs for HTMX actions on matching elements. +/// Generates URLs for HTMX request attributes on matching elements. /// -/// The . +/// The factory used to create URL helpers. [HtmlTargetElement(Attributes = ActionAttributeName)] [HtmlTargetElement(Attributes = ControllerAttributeName)] [HtmlTargetElement(Attributes = AreaAttributeName)] @@ -52,7 +51,9 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper /// Gets or sets the name of the route. /// /// - /// Must be if one of , , or is non-. + /// Must be if , + /// , , or + /// is not . /// [HtmlAttributeName(RouteAttributeName)] public string? Route { get; set; } @@ -61,7 +62,7 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper /// Gets or sets the name of the area. /// /// - /// Must be if is non-. + /// Must be if is not . /// [AspMvcArea] [HtmlAttributeName(AreaAttributeName)] @@ -71,7 +72,8 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper /// Gets or sets the name of the controller. /// /// - /// Must be if or is non-. + /// Must be if , , + /// or is not . /// [AspMvcController] [HtmlAttributeName(ControllerAttributeName)] @@ -81,7 +83,8 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper /// Gets or sets the name of the action. /// /// - /// Must be if or is non-. + /// Must be if , , + /// or is not . /// [AspMvcAction] [HtmlAttributeName(ActionAttributeName)] @@ -91,7 +94,8 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper /// Gets or sets the name of the page. /// /// - /// Must be if one of , or is non-. + /// Must be if , , + /// or is not . /// [AspMvcView] [HtmlAttributeName(PageAttributeName)] @@ -101,13 +105,14 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper /// Gets or sets the name of the page handler. /// /// - /// Must be if one of , or is non-. + /// Must be if , , + /// or is not . /// [HtmlAttributeName(PageHandlerAttributeName)] public string? PageHandler { get; set; } /// - /// Gets or sets the protocol for the URL, such as "http" or "https". + /// Gets or sets the protocol for the URL, such as http or https. /// [HtmlAttributeName(ProtocolAttributeName)] public string? Protocol { get; set; } @@ -125,7 +130,7 @@ public sealed class HtmxUrlTagHelper(IUrlHelperFactory factory) : TagHelper public string? Fragment { get; set; } /// - /// Gets or sets the additional parameters for the route. + /// Gets or sets the additional route values. /// [HtmlAttributeName(RouteValuesDictionaryName, DictionaryAttributePrefix = RouteValuesPrefix)] public IDictionary RouteValues @@ -135,7 +140,7 @@ public IDictionary RouteValues } /// - /// Gets or sets the for the current request. + /// Gets or sets the view context for the current request. /// [ViewContext] [HtmlAttributeNotBound] @@ -214,6 +219,10 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp return Task.CompletedTask; } + /// + /// Throws an exception indicating that mutually exclusive URL attributes were specified. + /// + /// Always thrown. [DoesNotReturn] private static void Error_CannotDetermineUrl() { @@ -226,6 +235,10 @@ private static void Error_CannotDetermineUrl() throw new InvalidOperationException(Message); } + /// + /// Throws an exception indicating that multiple HTMX method attributes were specified. + /// + /// Always thrown. [DoesNotReturn] private static void Error_AmbiguousMethods() { diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxValsTagHelper.cs b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxValsTagHelper.cs index ddc87fd..ad60952 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/HtmxValsTagHelper.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/HtmxValsTagHelper.cs @@ -8,7 +8,7 @@ namespace Ramstack.HtmxToolkit.TagHelpers; /// -/// Represents a implementation that applies the hx-vals attribute to matching elements. +/// Applies an hx-vals attribute assembled from strongly typed tag helper attributes. /// /// /// diff --git a/src/Ramstack.HtmxToolkit/TagHelpers/ResponseHandlingConfig.cs b/src/Ramstack.HtmxToolkit/TagHelpers/ResponseHandlingConfig.cs index b360412..29f617a 100644 --- a/src/Ramstack.HtmxToolkit/TagHelpers/ResponseHandlingConfig.cs +++ b/src/Ramstack.HtmxToolkit/TagHelpers/ResponseHandlingConfig.cs @@ -1,12 +1,13 @@ namespace Ramstack.HtmxToolkit.TagHelpers; /// -/// Represents the response handling configuration for responses matching a specific HTTP status code pattern. +/// Represents the response handling configuration for responses that match +/// a specific HTTP status code pattern. /// public sealed class ResponseHandlingConfig { /// - /// Gets or sets a regular expression that will be tested against response status codes. + /// Gets or sets the regular expression used to match response status codes. /// public string? Code { get; set; } From 0d14ed98b29bc7d2e25379c1579f0196287305a4 Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 30 Aug 2026 20:43:24 +0500 Subject: [PATCH 4/4] Refine XML comments --- src/Ramstack.HtmxToolkit/HtmxResult.cs | 4 ++-- src/Ramstack.HtmxToolkit/HtmxResult`1.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ramstack.HtmxToolkit/HtmxResult.cs b/src/Ramstack.HtmxToolkit/HtmxResult.cs index 0e33d61..6d8c9ac 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResult.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResult.cs @@ -3,8 +3,8 @@ namespace Ramstack.HtmxToolkit; /// -/// Wraps an and configures HTMX response headers -/// before executing it for an HTMX request. +/// Represents an that when executed configures HTMX response headers +/// before executing the wrapped result. /// /// The action result to execute. /// The delegate that configures the HTMX response headers. diff --git a/src/Ramstack.HtmxToolkit/HtmxResult`1.cs b/src/Ramstack.HtmxToolkit/HtmxResult`1.cs index 85b95c1..cbbadce 100644 --- a/src/Ramstack.HtmxToolkit/HtmxResult`1.cs +++ b/src/Ramstack.HtmxToolkit/HtmxResult`1.cs @@ -3,8 +3,8 @@ namespace Ramstack.HtmxToolkit; /// -/// Wraps an and configures HTMX response headers -/// before executing it for an HTMX request. +/// Represents an that when executed configures HTMX response headers +/// before executing the wrapped result. /// /// The type of state passed to . /// The action result to execute.