Skip to content

Commit

Permalink
Merge pull request #191 from PhyxionNL/issue-188
Browse files Browse the repository at this point in the history
Fixes #188
  • Loading branch information
Shazwazza authored May 19, 2023
2 parents 9510e0f + 1cb0028 commit 47bc22d
Showing 1 changed file with 37 additions and 45 deletions.
82 changes: 37 additions & 45 deletions src/Smidge/TagHelpers/SmidgeLinkTagHelper.cs
Original file line number Diff line number Diff line change
@@ -1,47 +1,36 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using System.Collections.Generic;
using System;

namespace Smidge.TagHelpers
{
[HtmlTargetElement("link", Attributes = HrefAttributeName, TagStructure = TagStructure.WithoutEndTag)]
public class SmidgeLinkTagHelper : TagHelper
{
private const string HrefIncludeAttributeName = "asp-href-include";
private const string HrefExcludeAttributeName = "asp-href-exclude";
private const string FallbackHrefAttributeName = "asp-fallback-href";
private const string SuppressFallbackIntegrityAttributeName = "asp-suppress-fallback-integrity";
private const string FallbackHrefIncludeAttributeName = "asp-fallback-href-include";
private const string FallbackHrefExcludeAttributeName = "asp-fallback-href-exclude";
private const string FallbackTestClassAttributeName = "asp-fallback-test-class";
private const string FallbackTestPropertyAttributeName = "asp-fallback-test-property";
private const string FallbackTestValueAttributeName = "asp-fallback-test-value";
private const string AppendVersionAttributeName = "asp-append-version";
private const string HrefAttributeName = "href";
private readonly IBundleManager _bundleManager;
private readonly HtmlEncoder _encoder;

private readonly HashSet<string> _invalid = new()
private readonly HashSet<string> _invalidAttributes = new()
{
HrefIncludeAttributeName,
HrefExcludeAttributeName,
FallbackHrefAttributeName,
FallbackHrefIncludeAttributeName,
FallbackTestClassAttributeName,
FallbackTestPropertyAttributeName,
SuppressFallbackIntegrityAttributeName,
FallbackHrefExcludeAttributeName,
FallbackTestValueAttributeName,
AppendVersionAttributeName
"asp-href-include",
"asp-href-exclude",
"asp-fallback-href",
"asp-fallback-href-exclude",
"asp-fallback-test-class",
"asp-fallback-test-property",
"asp-fallback-test-value",
"asp-suppress-fallback-integrity",
"asp-suppress-fallback-integrity",
"asp-append-version"
};

private readonly SmidgeHelper _smidgeHelper;
private readonly IBundleManager _bundleManager;
private readonly HtmlEncoder _encoder;

public SmidgeLinkTagHelper(SmidgeHelper smidgeHelper, IBundleManager bundleManager, HtmlEncoder encoder)
{
Expand All @@ -50,28 +39,28 @@ public SmidgeLinkTagHelper(SmidgeHelper smidgeHelper, IBundleManager bundleManag
_encoder = encoder;
}

[HtmlAttributeName("debug")]
public bool Debug { get; set; }

/// <summary>
/// TODO: Need to figure out why we need this. If the order is default and executes 'after' the
/// TODO: Need to figure out why we need this. If the order is default and executes 'after' the
/// default tag helpers like the script tag helper and url resolution tag helper, the url resolution
/// doesn't actually work, it simply doesn't get passed through. Not sure if this is a bug or if I'm
/// doesn't actually work, it simply doesn't get passed through. Not sure if this is a bug or if I'm
/// doing it wrong. In the meantime, setting this to execute before the defaults works.
/// </summary>
public override int Order => -2000;

[HtmlAttributeName(HrefAttributeName)]
public string Source { get; set; }

[HtmlAttributeName("debug")]
public bool Debug { get; set; }

public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (string.IsNullOrWhiteSpace(Source))
{
return;
}

var exists = _bundleManager.Exists(Source);
bool exists = _bundleManager.Exists(Source);

// Pass through attribute that is also a well-known HTML attribute.
// this is required to make sure that other tag helpers executing against this element have
Expand All @@ -83,29 +72,32 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu
return;
}

if (context.AllAttributes.Any(x => _invalid.Contains(x.Name)))
if (context.AllAttributes.Any(x => _invalidAttributes.Contains(x.Name)))
{
return;
}

if (context.AllAttributes.TryGetAttribute("as", out TagHelperAttribute attribute) && attribute.Value is not "style")
{
throw new InvalidOperationException("Smidge tag helpers do not support the ASP.NET tag helpers: " + string.Join(", ", _invalid));
return;
}

var result = (await _smidgeHelper.GenerateCssUrlsAsync(Source, Debug)).ToArray();
var currAttr = output.Attributes.ToDictionary(x => x.Name, x => x.Value);
using (var writer = new StringWriter())
var attributes = output.Attributes.ToDictionary(x => x.Name, x => x.Value);
await using (var writer = new StringWriter())
{
foreach (var s in result)
foreach (var url in await _smidgeHelper.GenerateCssUrlsAsync(Source, Debug))
{
var builder = new TagBuilder(output.TagName)
{
TagRenderMode = TagRenderMode.SelfClosing
};
builder.MergeAttributes(currAttr);
builder.Attributes["href"] = s;
var builder = new TagBuilder(output.TagName) { TagRenderMode = TagRenderMode.SelfClosing };
builder.MergeAttributes(attributes);
builder.Attributes["href"] = url;

builder.WriteTo(writer, _encoder);
}
writer.Flush();

await writer.FlushAsync();
output.PostElement.SetHtmlContent(new HtmlString(writer.ToString()));
}

//This ensures the original tag is not written.
output.TagName = null;
}
Expand Down

0 comments on commit 47bc22d

Please sign in to comment.