add new tag helpers

This commit is contained in:
2024-04-05 13:03:12 +02:00
parent ebf4e430c3
commit e60fbc6d0a
4 changed files with 144 additions and 30 deletions
+38 -9
View File
@@ -9,9 +9,30 @@ namespace TurnstileTag;
public interface ITurnstile
{
/// <summary>
/// Generates the placeholder which renders the turnstile challenge.
/// </summary>
public IHtmlContent GetInputHtml();
/// <summary>
/// Generates the script tag which loads the turnstile library.
/// </summary>
public IHtmlContent GetScriptHtml();
/// <summary>
///
/// </summary>
IHtmlContent GenerateTurnstileFormHtml(ViewContext viewContext);
IHtmlContent GetHtml();
/// <summary>
///
/// </summary>
Task ValidateRequestAsync(HttpContext httpContext);
/// <summary>
///
/// </summary>
Task<bool> Verify(string value);
}
@@ -27,6 +48,7 @@ public class Turnstile : ITurnstile
}
/// <inheritdoc />
public async Task ValidateRequestAsync(HttpContext httpContext)
{
ArgumentNullException.ThrowIfNull(httpContext);
@@ -61,6 +83,7 @@ public class Turnstile : ITurnstile
}
/// <inheritdoc />
public async Task<bool> Verify(string value)
{
using HttpClient http = new();
@@ -74,20 +97,25 @@ public class Turnstile : ITurnstile
}
/// <summary>
/// Generates the placeholder which renders the turnstile challenge.
/// </summary>
public IHtmlContent GetHtml()
/// <inheritdoc />
public IHtmlContent GetInputHtml()
{
HtmlContentBuilder builder = new();
builder.AppendHtml($"<div class=\"cf-turnstile\" data-sitekey=\"{_options.PublicKey}\"></div>");
builder.AppendHtml($"<script src=\"{_options.ApiUrl}/api.js\" async defer></script>");
//<script src="@(Model.Turnstile.Options.ApiUrl)/api.js" async defer></script>
//<div class="cf-turnstile" data-sitekey="@Model.Turnstile.Options.PublicKey"></div>
return builder;
}
/// <inheritdoc />
public IHtmlContent GetScriptHtml()
{
HtmlContentBuilder builder = new();
builder.AppendHtml($"<script src=\"{_options.ApiUrl}/api.js\" async defer></script>");
return builder;
}
/// <inheritdoc />
public IHtmlContent GenerateTurnstileFormHtml(ViewContext viewContext)
{
ArgumentNullException.ThrowIfNull(viewContext);
@@ -103,7 +131,8 @@ public class Turnstile : ITurnstile
formContext.FormData.Add("turnstile", true);
}
return GetHtml();
viewContext.ViewData.TryAdd("turnstile", true);
return GetInputHtml();
}
+43
View File
@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace TurnstileTag;
[HtmlTargetElement("form", Attributes = "cf-turnstile")]
public class TurnstileAttributeTagHelper : TagHelper
{
readonly ITurnstile _turnstile;
public TurnstileAttributeTagHelper(ITurnstile turnstile)
{
_turnstile = turnstile;
}
/// <summary>
/// Whether turnstile should be activated.
/// </summary>
public bool? CfTurnstile { get; set; }
/// <summary>
/// Gets the <see cref="Rendering.ViewContext"/> of the executing view.
/// </summary>
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext? ViewContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (CfTurnstile ?? false)
{
IHtmlContent content = _turnstile.GenerateTurnstileFormHtml(ViewContext!);
if (content != null)
{
output.PostContent.AppendHtml(content);
}
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Options;
namespace TurnstileTag;
[HtmlTargetElement("cf-turnstile-script", TagStructure = TagStructure.NormalOrSelfClosing)]
public class TurnstileScriptTagHelper : TagHelper
{
/// <summary>
/// Force rendering of script tag.
/// Otherwise it is only rendered when a turnstile input was rendered.
/// </summary>
public bool Force { get; set; }
readonly IOptions<TurnstileOptions> _options;
/// <summary>
/// Gets the <see cref="Rendering.ViewContext"/> of the executing view.
/// </summary>
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext? ViewContext { get; set; }
public TurnstileScriptTagHelper(IOptions<TurnstileOptions> options)
{
_options = options;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (Force || (ViewContext != null && ViewContext.ViewData.ContainsKey("turnstile")))
{
output.TagMode = TagMode.StartTagAndEndTag;
output.TagName = "script";
output.Attributes.Add(new TagHelperAttribute("async"));
output.Attributes.Add(new TagHelperAttribute("defer"));
output.Attributes.Add("src", _options.Value.ApiUrl + "/api.js");
}
else
{
output.SuppressOutput();
}
}
}
+15 -21
View File
@@ -1,24 +1,15 @@
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Options;
namespace TurnstileTag;
[HtmlTargetElement("form", Attributes = "cf-turnstile")]
[HtmlTargetElement("cf-turnstile-input", TagStructure = TagStructure.NormalOrSelfClosing)]
public class TurnstileTagHelper : TagHelper
{
readonly ITurnstile _turnstile;
readonly IOptions<TurnstileOptions> _options;
public TurnstileTagHelper(ITurnstile turnstile)
{
_turnstile = turnstile;
}
/// <summary>
/// Whether turnstile should be activated.
/// </summary>
public bool? CfTurnstile { get; set; }
/// <summary>
/// Gets the <see cref="Rendering.ViewContext"/> of the executing view.
@@ -28,15 +19,18 @@ public class TurnstileTagHelper : TagHelper
public ViewContext? ViewContext { get; set; }
public TurnstileTagHelper(IOptions<TurnstileOptions> options)
{
_options = options;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (CfTurnstile ?? false)
{
IHtmlContent content = _turnstile.GenerateTurnstileFormHtml(ViewContext!);
if (content != null)
{
output.PostContent.AppendHtml(content);
}
}
output.TagMode = TagMode.StartTagAndEndTag;
output.TagName = "div";
output.Attributes.Add("class", "cf-turnstile");
output.Attributes.Add("data-sitekey", _options.Value.PublicKey);
ViewContext!.ViewData.TryAdd("turnstile", true);
}
}