-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
ComputeCssScope.cs
70 lines (55 loc) · 2.21 KB
/
ComputeCssScope.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Numerics;
using System.Security.Cryptography;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.StaticWebAssets.Tasks
{
public class ComputeCssScope : Task
{
[Required]
public ITaskItem[] ScopedCssInput { get; set; }
[Required]
public string TargetName { get; set; }
[Output]
public ITaskItem[] ScopedCss { get; set; }
public override bool Execute()
{
ScopedCss = new ITaskItem[ScopedCssInput.Length];
for (var i = 0; i < ScopedCssInput.Length; i++)
{
var input = ScopedCssInput[i];
var relativePath = input.ItemSpec.ToLowerInvariant().Replace("\\","//");
var scope = input.GetMetadata("CssScope");
scope = !string.IsNullOrEmpty(scope) ? scope : GenerateScope(TargetName, relativePath);
var outputItem = new TaskItem(input);
outputItem.SetMetadata("CssScope", scope);
ScopedCss[i] = outputItem;
}
return !Log.HasLoggedErrors;
}
private string GenerateScope(string targetName, string relativePath)
{
using var hash = SHA256.Create();
var bytes = Encoding.UTF8.GetBytes(relativePath + targetName);
var hashBytes = hash.ComputeHash(bytes);
var builder = new StringBuilder();
builder.Append("b-");
builder.Append(ToBase36(hashBytes));
return builder.ToString();
}
private static string ToBase36(byte[] hash)
{
const string chars = "0123456789abcdefghijklmnopqrstuvwxyz";
var result = new char[10];
var dividend = BigInteger.Abs(new BigInteger(hash.AsSpan().Slice(0, 9).ToArray()));
for (var i = 0; i < 10; i++)
{
dividend = BigInteger.DivRem(dividend, 36, out var remainder);
result[i] = chars[(int)remainder];
}
return new string(result);
}
}
}