├── .nvmrc ├── sample ├── Views │ ├── _ViewImports.cshtml │ ├── _ViewStart.cshtml │ ├── Shared │ │ └── _Layout.cshtml │ └── Home │ │ └── Index.cshtml ├── wwwroot │ └── favicon.ico ├── Controllers │ └── HomeController.cs ├── appsettings.json ├── Sample.csproj ├── appsettings.Development.json ├── Program.cs ├── Properties │ └── launchSettings.json └── Startup.cs ├── .markdownlint.json ├── assets ├── logo.png ├── README.md └── logo.svg ├── obsolete_icons.txt ├── generator ├── .editorconfig ├── Properties │ └── launchSettings.json ├── StringBuilderExtensions.cs ├── IconDetails.cs ├── StringExtensions.cs ├── generator.props ├── IconSourceGenerator.csproj ├── IconExtractor.cs └── IconSourceGenerator.cs ├── nuget.config ├── .github ├── workflows │ ├── fixup-commits.yml │ ├── dotnet-sdk-updater.yml │ ├── dependabot-auto-merge.yml │ ├── codeql-analysis.yml │ ├── pull_request.yml │ ├── ci.yml │ └── release.yml └── dependabot.yml ├── Directory.Build.targets ├── package.json ├── .config └── dotnet-tools.json ├── .vscode └── settings.json ├── test ├── .editorconfig ├── HeroiconsTagHelperTests.csproj ├── TagHelperTestBase.cs ├── IconFocusableTagHelperTests.cs ├── IconListTests.cs ├── IconAccessibilityTagHelperTests.cs └── IconTagHelperTests.cs ├── global.json ├── src ├── HeroiconOptions.cs ├── IconFocusableTagHelper.cs ├── HeroiconsExtensions.cs ├── IconAccessibilityTagHelper.cs ├── HeroiconsTagHelper.csproj └── IconTagHelper.cs ├── LICENSE ├── Directory.Build.props ├── analysis ├── code-style.editorconfig ├── code-quality.editorconfig └── roslynator.editorconfig ├── .gitattributes ├── HeroiconsTagHelper.sln ├── .editorconfig ├── README.md ├── .gitignore └── CHANGELOG.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 21 2 | -------------------------------------------------------------------------------- /sample/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper *, HeroiconsTagHelper 2 | -------------------------------------------------------------------------------- /sample/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD013": false, 3 | "MD033": false, 4 | "MD045": false 5 | } 6 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xt0rted/heroicons-tag-helper/HEAD/assets/logo.png -------------------------------------------------------------------------------- /sample/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xt0rted/heroicons-tag-helper/HEAD/sample/wwwroot/favicon.ico -------------------------------------------------------------------------------- /obsolete_icons.txt: -------------------------------------------------------------------------------- 1 | arrow-left-on-rectangle 2 | arrow-right-on-rectangle 3 | arrow-small-down 4 | arrow-small-left 5 | arrow-small-right 6 | arrow-small-up 7 | minus-small 8 | plus-small 9 | -------------------------------------------------------------------------------- /generator/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | # IDE0079: Remove unnecessary suppression 3 | dotnet_diagnostic.IDE0079.severity = none 4 | 5 | # RS2008: Enable analyzer release tracking 6 | dotnet_diagnostic.RS2008.severity = none 7 | -------------------------------------------------------------------------------- /sample/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Controllers; 2 | 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | public class HomeController : Controller 6 | { 7 | public IActionResult Index() => View(); 8 | } 9 | -------------------------------------------------------------------------------- /generator/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "HeroiconsTagHelper": { 4 | "commandName": "DebugRoslynComponent", 5 | "targetProject": "..\\src\\HeroiconsTagHelper.csproj" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /sample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AllowedHosts": "*", 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.github/workflows/fixup-commits.yml: -------------------------------------------------------------------------------- 1 | name: Block on fixup commits 2 | 3 | on: pull_request_target 4 | 5 | permissions: 6 | pull-requests: read 7 | 8 | jobs: 9 | message: 10 | uses: xt0rted/.github/.github/workflows/fixup-commits.yml@main 11 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "heroicons-tag-helper", 3 | "private": true, 4 | "scripts": { 5 | "test": "markdownlint \"**/*.md\" --ignore node_modules" 6 | }, 7 | "dependencies": { 8 | "heroicons": "2.1.3" 9 | }, 10 | "devDependencies": { 11 | "markdownlint-cli": "^0.47.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "run-script": { 6 | "version": "0.6.0", 7 | "commands": [ 8 | "r" 9 | ] 10 | }, 11 | "rimraf": { 12 | "version": "0.3.1", 13 | "commands": [ 14 | "rimraf" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "cref", 4 | "evenodd", 5 | "heroicon", 6 | "heroicons", 7 | "inheritdoc", 8 | "labeledby", 9 | "linecap", 10 | "linejoin", 11 | "viewbox" 12 | ], 13 | "dotnet.defaultSolution": "HeroiconsTagHelper.sln" 14 | } 15 | -------------------------------------------------------------------------------- /sample/Sample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(_TargetFramework) 5 | 1701;1702;CS0618 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /sample/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Sample 7 | 8 | 9 | 10 | @RenderBody() 11 | 12 | 13 | -------------------------------------------------------------------------------- /sample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Heroicons": { 3 | "IncludeComments": true, 4 | "SetAccessibilityAttributes": true, 5 | "SetFocusableAttribute": true 6 | }, 7 | "Logging": { 8 | "LogLevel": { 9 | "Default": "Information", 10 | "Microsoft": "Warning", 11 | "Microsoft.Hosting.Lifetime": "Information" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.github/workflows/dotnet-sdk-updater.yml: -------------------------------------------------------------------------------- 1 | name: .NET SDK updater 2 | 3 | on: 4 | schedule: 5 | - cron: "0 12 * * 1-5" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | update: 10 | uses: xt0rted/.github/.github/workflows/dotnet-sdk-updater.yml@main 11 | secrets: 12 | DOTNET_UPDATER_APP_ID: ${{ secrets.DOTNET_UPDATER_APP_ID }} 13 | DOTNET_UPDATER_PRIVATE_KEY: ${{ secrets.DOTNET_UPDATER_PRIVATE_KEY }} 14 | -------------------------------------------------------------------------------- /generator/StringBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace IconSourceGenerator; 2 | 3 | internal static class StringBuilderExtensions 4 | { 5 | public static StringBuilder AppendLine(this StringBuilder builder, params string[] value) 6 | { 7 | for (var i = 0; i < value.Length; i++) 8 | { 9 | builder.Append(value[i]); 10 | } 11 | 12 | return builder.AppendLine(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /sample/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Sample; 2 | 3 | public static class Program 4 | { 5 | public static void Main(string[] args) 6 | => CreateHostBuilder(args) 7 | .Build() 8 | .Run(); 9 | 10 | public static IHostBuilder CreateHostBuilder(string[] args) 11 | => Host.CreateDefaultBuilder(args) 12 | .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); 13 | } 14 | -------------------------------------------------------------------------------- /generator/IconDetails.cs: -------------------------------------------------------------------------------- 1 | namespace IconSourceGenerator; 2 | 3 | internal class IconDetails 4 | { 5 | public string Path { get; set; } = null!; 6 | 7 | public string Name { get; set; } = null!; 8 | 9 | public string ClassName { get; set; } = null!; 10 | 11 | public string Style { get; set; } = null!; 12 | 13 | public bool UsesStroke { get; set; } 14 | 15 | public AdditionalText File { get; set; } = null!; 16 | } 17 | -------------------------------------------------------------------------------- /test/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | # CA1063: Implement IDisposable Correctly 3 | dotnet_diagnostic.CA1063.severity = none 4 | 5 | # CA1707: Identifiers should not contain underscores 6 | dotnet_diagnostic.CA1707.severity = none 7 | 8 | # CA1816: Dispose methods should call SuppressFinalize 9 | dotnet_diagnostic.CA1816.severity = none 10 | 11 | # CA2234: Pass system uri objects instead of strings 12 | dotnet_diagnostic.CA2234.severity = none 13 | 14 | # CS8618: Non-nullable field is uninitialized. Consider declaring as nullable. 15 | dotnet_diagnostic.CS8618.severity = none 16 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # Assets 2 | 3 | The source for the logo is available on [Figma](https://www.figma.com/file/FBPemu54a3c2fWO55x8bDr/heroicons-tag-helper). 4 | It's a mix of the `arrow-narrow-right` and `shield-exclamation` outline variant icons in v0.4.2. 5 | 6 | The colors used are `#A65FEC` (grape from the [heroicons.com repo](https://github.com/tailwindlabs/heroicons.com/blob/015d9ece75b1ad1fe44e82914777f2c5170d4e74/tailwind.config.js#L27)) and `#6b7280` (`gray-500` from TailwindUI). 7 | 8 | Format | Preview 9 | :-- | :--: 10 | `.png` | ![Logo preview](logo.png) 11 | `.svg` | ![Logo preview](logo.svg) 12 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "8.0.415" 4 | }, 5 | "scripts": { 6 | "clean": "dotnet rimraf artifacts", 7 | "clean:bin": "dotnet rimraf **/bin **/obj", 8 | "build": "dotnet build", 9 | "test": "dotnet test", 10 | "test:6": "dotnet test --framework net6.0", 11 | "test:8": "dotnet test --framework net8.0", 12 | "pack": "dotnet pack --output ./artifacts", 13 | "ci": "dotnet r build test pack", 14 | "watch": "dotnet r [env:DOTNET_WATCH_RESTART_ON_RUDE_EDIT=true] watch:sample", 15 | "watch:sample": "dotnet watch --verbose --project sample" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /generator/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace IconSourceGenerator; 2 | 3 | internal static class StringExtensions 4 | { 5 | public static string FirstCharToUpper(this string input) 6 | { 7 | var arr = input.ToCharArray(); 8 | 9 | arr[0] = char.ToUpperInvariant(arr[0]); 10 | 11 | return new string(arr); 12 | } 13 | 14 | public static string ToPascalCase(this string name) 15 | { 16 | var splitName = name.Split('-'); 17 | 18 | for (var i = 0; i < splitName.Length; i++) 19 | { 20 | splitName[i] = FirstCharToUpper(splitName[i]); 21 | } 22 | 23 | return string.Concat(splitName); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /generator/generator.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | <_AdditionalFilesCleanup Include="@(AdditionalFiles)" /> 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /sample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:57627", 7 | "sslPort": 44382 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "sample": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /generator/IconSourceGenerator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | true 6 | false 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | 3 | on: pull_request_target 4 | 5 | permissions: 6 | contents: read 7 | pull-requests: read 8 | 9 | jobs: 10 | dependabot: 11 | uses: xt0rted/.github/.github/workflows/dependabot-auto-merge.yml@main 12 | secrets: 13 | GITHUB_APP_ID: ${{ secrets.DEPENDAMERGE_APP_ID }} 14 | GITHUB_APP_PRIVATE_KEY: ${{ secrets.DEPENDAMERGE_PRIVATE_KEY }} 15 | with: 16 | allowed-groups: | 17 | { 18 | "github_actions": [ 19 | "github-actions", 20 | "my-actions", 21 | ], 22 | "nuget": [ 23 | "analyzers", 24 | "testing", 25 | ], 26 | } 27 | allowed-packages: | 28 | { 29 | "nuget": [ 30 | "rimraf", 31 | "run-script", 32 | ], 33 | } 34 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | groups: 9 | github-actions: 10 | patterns: 11 | - "actions/*" 12 | my-actions: 13 | patterns: 14 | - "xt0rted/*" 15 | 16 | - package-ecosystem: "npm" 17 | directory: "/" 18 | schedule: 19 | interval: "weekly" 20 | 21 | - package-ecosystem: "nuget" 22 | directory: "/" 23 | schedule: 24 | interval: "weekly" 25 | groups: 26 | analyzers: 27 | patterns: 28 | - "IDisposableAnalyzers" 29 | - "Roslynator.*" 30 | testing: 31 | patterns: 32 | - "GitHubActionsTestLogger" 33 | - "Microsoft.NET.Test.Sdk" 34 | - "Shouldly" 35 | - "xunit" 36 | - "xunit.*" 37 | -------------------------------------------------------------------------------- /src/HeroiconOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | /// 4 | /// Global settings used when emitting Heroicons. 5 | /// 6 | public class HeroiconOptions 7 | { 8 | /// 9 | /// Add an html comment before the svg tag with the style and name of the icon to help make development/debugging easier. 10 | /// 11 | /// This is off by default. 12 | public bool IncludeComments { get; set; } 13 | 14 | /// 15 | /// Adds various accessibility attributes based on the default state of the tag. 16 | /// 17 | /// This is off by default. 18 | public bool SetAccessibilityAttributes { get; set; } 19 | 20 | /// 21 | /// Adds the focusable attribute set to false to prevent the icon from receiving focus in Internet Explorer and Edge Legacy. 22 | /// 23 | /// This is off by default. 24 | public bool SetFocusableAttribute { get; set; } 25 | } 26 | -------------------------------------------------------------------------------- /generator/IconExtractor.cs: -------------------------------------------------------------------------------- 1 | namespace IconSourceGenerator; 2 | 3 | internal static class IconExtractor 4 | { 5 | private static readonly Regex ViewBoxRegEx = new("viewBox=\"(?[^\"]+)\"", RegexOptions.Compiled); 6 | private static readonly Regex StrokeWidthRegEx = new("stroke-width=\"(?[^\"]+)\"", RegexOptions.Compiled); 7 | 8 | public static string GetPaths(string icon) 9 | { 10 | var lines = icon.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Select(path => path.Trim()).ToArray(); 11 | 12 | var paths = lines.Skip(1).Take(lines.Length - 2); 13 | 14 | return string.Concat(paths); 15 | } 16 | 17 | public static string GetViewBox(string icon) 18 | { 19 | var match = ViewBoxRegEx.Match(icon); 20 | 21 | return match.Groups["viewbox"].Value; 22 | } 23 | 24 | public static string GetStrokeWidth(string icon) 25 | { 26 | var match = StrokeWidthRegEx.Match(icon); 27 | 28 | return match.Groups["width"].Value; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Brian Surowiec 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /sample/Startup.cs: -------------------------------------------------------------------------------- 1 | namespace Sample; 2 | 3 | public class Startup 4 | { 5 | public Startup(IConfiguration configuration) 6 | => Configuration = configuration; 7 | 8 | public IConfiguration Configuration { get; } 9 | 10 | // This method gets called by the runtime. Use this method to add services to the container. 11 | public void ConfigureServices(IServiceCollection services) 12 | { 13 | services.AddControllersWithViews(); 14 | 15 | services.AddHeroicons(Configuration); 16 | } 17 | 18 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 19 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 20 | { 21 | if (env.IsDevelopment()) 22 | { 23 | app.UseDeveloperExceptionPage(); 24 | } 25 | 26 | app.UseHttpsRedirection(); 27 | app.UseStaticFiles(); 28 | 29 | app.UseRouting(); 30 | 31 | app.UseEndpoints(endpoints => 32 | { 33 | endpoints.MapControllerRoute( 34 | name: "default", 35 | pattern: "{controller=Home}/{action=Index}/{id?}"); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | schedule: 11 | - cron: "0 6 * * 1" 12 | workflow_dispatch: 13 | 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ github.ref }} 16 | cancel-in-progress: true 17 | 18 | env: 19 | DOTNET_NOLOGO: true 20 | FORCE_COLOR: 3 21 | 22 | jobs: 23 | analyze: 24 | name: Analyze 25 | 26 | runs-on: ubuntu-latest 27 | 28 | permissions: 29 | actions: read 30 | contents: read 31 | security-events: write 32 | 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | language: 37 | - csharp 38 | 39 | steps: 40 | - name: Check out repository 41 | uses: actions/checkout@v5.0.0 42 | 43 | - name: Set up Node 44 | uses: actions/setup-node@v6.0.0 45 | with: 46 | node-version-file: .nvmrc 47 | 48 | - run: npm ci 49 | 50 | - name: Initialize CodeQL 51 | uses: github/codeql-action/init@v4 52 | with: 53 | languages: ${{ matrix.language }} 54 | 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v4 57 | 58 | - name: Perform CodeQL Analysis 59 | uses: github/codeql-action/analyze@v4 60 | -------------------------------------------------------------------------------- /test/HeroiconsTagHelperTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(_TargetFrameworks) 5 | Tailwind.Heroicons 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | all 18 | runtime; build; native; contentfiles; analyzers 19 | 20 | 21 | 22 | 23 | 24 | all 25 | runtime; build; native; contentfiles; analyzers; buildtransitive 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /test/TagHelperTestBase.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | public abstract class TagHelperTestBase 4 | { 5 | protected static TagHelperContext MakeTagHelperContext(string tagName, TagHelperAttributeList? attributes = null) 6 | { 7 | attributes ??= new TagHelperAttributeList(); 8 | 9 | return new TagHelperContext( 10 | tagName, 11 | allAttributes: attributes, 12 | items: new Dictionary(), 13 | uniqueId: Guid.NewGuid().ToString("N")); 14 | } 15 | 16 | protected static TagHelperOutput MakeTagHelperOutput(string tagName, TagHelperAttributeList? attributes = null) 17 | { 18 | attributes ??= new TagHelperAttributeList(); 19 | 20 | return new TagHelperOutput( 21 | tagName, 22 | attributes: attributes, 23 | getChildContentAsync: (_, __) => Task.FromResult(new DefaultTagHelperContent())); 24 | } 25 | 26 | protected static void AssertAttributeValue(TagHelperAttributeList attributes, string name, string value) 27 | { 28 | if (attributes is null) throw new ArgumentNullException(nameof(attributes)); 29 | 30 | attributes 31 | .Count(a => a.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) 32 | .ShouldBe(1); 33 | 34 | attributes[name].Value.ShouldBe(value); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/IconFocusableTagHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | /// 4 | /// Tag helper that sets focusable to false on instances. 5 | /// 6 | [HtmlTargetElement("heroicon-micro")] 7 | [HtmlTargetElement("heroicon-mini")] 8 | [HtmlTargetElement("heroicon-outline")] 9 | [HtmlTargetElement("heroicon-solid")] 10 | public class IconFocusableTagHelper : TagHelper 11 | { 12 | private readonly HeroiconOptions _settings; 13 | 14 | /// 15 | /// Creates a new . 16 | /// 17 | /// The to use when processing the target element. 18 | /// 19 | public IconFocusableTagHelper(IOptions settings) 20 | => _settings = settings?.Value ?? throw new ArgumentNullException(nameof(settings)); 21 | 22 | /// 23 | public override int Order => 1000; 24 | 25 | /// 26 | public override void Process(TagHelperContext context, TagHelperOutput output) 27 | { 28 | ArgumentNullException.ThrowIfNull(context); 29 | ArgumentNullException.ThrowIfNull(output); 30 | 31 | if (!_settings.SetFocusableAttribute) 32 | { 33 | return; 34 | } 35 | 36 | output.Attributes.SetAttribute("focusable", "false"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <_TargetFramework>net8.0 5 | <_TargetFrameworks>$(_TargetFramework);net6.0 6 | preview 7 | enable 8 | enable 9 | false 10 | 11 | 12 | 13 | 2.1.3 14 | Brian Surowiec 15 | 16 | 17 | 18 | true 19 | 20 | 21 | 22 | 23 | all 24 | runtime; build; native; contentfiles; analyzers 25 | 26 | 27 | all 28 | runtime; build; native; contentfiles; analyzers 29 | 30 | 31 | all 32 | runtime; build; native; contentfiles; analyzers 33 | 34 | 35 | all 36 | runtime; build; native; contentfiles; analyzers 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/HeroiconsExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Extensions.DependencyInjection; 2 | 3 | /// 4 | /// Contains extension methods to for configuring heroicons. 5 | /// 6 | public static class HeroiconsExtensions 7 | { 8 | /// 9 | /// Adds the default heroicons configuration. 10 | /// 11 | /// The services available in the application. 12 | /// The configuration available in the application. 13 | /// The services. 14 | /// 15 | public static IServiceCollection AddHeroicons(this IServiceCollection services, IConfiguration configuration) 16 | { 17 | ArgumentNullException.ThrowIfNull(services); 18 | ArgumentNullException.ThrowIfNull(configuration); 19 | 20 | services.Configure(configuration.GetSection("Heroicons")); 21 | 22 | return services; 23 | } 24 | 25 | /// 26 | /// Adds a custom heroicons configuration. 27 | /// 28 | /// The services available in the application. 29 | /// An action to configure the . 30 | /// The services. 31 | /// 32 | public static IServiceCollection AddHeroicons(this IServiceCollection services, Action configureOptions) 33 | { 34 | ArgumentNullException.ThrowIfNull(services); 35 | ArgumentNullException.ThrowIfNull(configureOptions); 36 | 37 | services.Configure(configureOptions); 38 | 39 | return services; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /analysis/code-style.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | 3 | # 4 | # Options 5 | 6 | # Add a blank line between using and Import directives based on their name 7 | dotnet_separate_import_directive_groups = true 8 | 9 | # Sort using and Import directives with System.* appearing first 10 | dotnet_sort_system_directives_first = true 11 | 12 | dotnet_style_coalesce_expression = true:suggestion 13 | dotnet_style_collection_initializer = true:error 14 | dotnet_style_explicit_tuple_names = true:error 15 | dotnet_style_null_propagation = true:error 16 | dotnet_style_object_initializer = true:error 17 | 18 | # Prefer parentheses for improved clarity 19 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:error 20 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:error 21 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:error 22 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:error 23 | dotnet_style_predefined_type_for_locals_parameters_members = true:error 24 | dotnet_style_predefined_type_for_member_access = true:error 25 | 26 | # Avoid "this." and "Me." if not necessary 27 | dotnet_style_qualification_for_field = false:error 28 | dotnet_style_qualification_for_property = false:error 29 | dotnet_style_qualification_for_method = false:error 30 | dotnet_style_qualification_for_event = false:error 31 | 32 | # 33 | # Rules 34 | 35 | # IDE0001: Simplify name 36 | dotnet_diagnostic.IDE0001.severity = error 37 | 38 | # IDE0029: Use coalesce expression 39 | dotnet_diagnostic.IDE0029.severity = none 40 | 41 | # IDE0039: Use local function 42 | dotnet_diagnostic.IDE0039.severity = none 43 | 44 | # IDE0046: Convert to conditional expression 45 | dotnet_diagnostic.IDE0046.severity = none 46 | 47 | # IDE0270: Use coalesce expression 48 | dotnet_diagnostic.IDE0270.severity = suggestion 49 | -------------------------------------------------------------------------------- /.github/workflows/pull_request.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request 2 | 3 | on: pull_request 4 | 5 | concurrency: 6 | group: ${{ github.workflow }}-${{ github.ref }} 7 | cancel-in-progress: true 8 | 9 | env: 10 | CONFIGURATION: Release 11 | DOTNET_NOLOGO: true 12 | FORCE_COLOR: 3 13 | 14 | jobs: 15 | lint-markdown: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Check out repository 20 | uses: actions/checkout@v5.0.0 21 | 22 | - name: Install Node 23 | uses: actions/setup-node@v6.0.0 24 | with: 25 | node-version-file: .nvmrc 26 | 27 | - uses: xt0rted/markdownlint-problem-matcher@v3.0.0 28 | 29 | - run: npm ci 30 | 31 | - run: npm test 32 | 33 | build: 34 | runs-on: ubuntu-latest 35 | 36 | steps: 37 | - name: Check out repository 38 | uses: actions/checkout@v5.0.0 39 | 40 | - name: Build version suffix 41 | run: echo "VERSION_SUFFIX=alpha.${{ github.event.number }}" >> $GITHUB_ENV 42 | 43 | - name: Set up Node 44 | uses: actions/setup-node@v6.0.0 45 | with: 46 | node-version-file: .nvmrc 47 | 48 | - name: Set up .NET 49 | uses: xt0rted/setup-dotnet@v1.5.0 50 | 51 | - name: Set up .NET 52 | uses: xt0rted/setup-dotnet@v1.5.0 53 | with: 54 | colored-output: false 55 | strip-comments-from-global-json: false 56 | dotnet-version: | 57 | 6.0.x 58 | 59 | - run: npm ci 60 | 61 | - run: dotnet tool restore 62 | 63 | - run: dotnet r build 64 | 65 | - run: dotnet r test -- --no-build --logger GitHubActions 66 | 67 | - run: dotnet r pack -- --no-build --version-suffix $VERSION_SUFFIX 68 | 69 | - name: Publish artifacts 70 | uses: actions/upload-artifact@v5.0.0 71 | with: 72 | path: ./artifacts/*.nupkg 73 | -------------------------------------------------------------------------------- /test/IconFocusableTagHelperTests.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | public class IconFocusableTagHelperTests : TagHelperTestBase 4 | { 5 | [Fact] 6 | public void Should_not_set_focusable_attribute_when_disabled() 7 | { 8 | // Given 9 | var context = MakeTagHelperContext("heroicon-outline"); 10 | var output = MakeTagHelperOutput("heroicon-outline"); 11 | 12 | var options = Options.Create(new HeroiconOptions { SetFocusableAttribute = false }); 13 | var helper = new IconFocusableTagHelper(options); 14 | 15 | // When 16 | helper.Process(context, output); 17 | 18 | // Then 19 | output.Attributes.ShouldNotContain(a => a.Name == "focusable"); 20 | } 21 | 22 | [Fact] 23 | public void Should_set_focusable_attribute() 24 | { 25 | // Given 26 | var context = MakeTagHelperContext("heroicon-outline"); 27 | var output = MakeTagHelperOutput("heroicon-outline"); 28 | 29 | var options = Options.Create(new HeroiconOptions { SetFocusableAttribute = true }); 30 | var helper = new IconFocusableTagHelper(options); 31 | 32 | // When 33 | helper.Process(context, output); 34 | 35 | // Then 36 | AssertAttributeValue(output.Attributes, "focusable", "false"); 37 | } 38 | 39 | [Fact] 40 | public void Should_set_focusable_attribute_to_false() 41 | { 42 | // Given 43 | var context = MakeTagHelperContext( 44 | "heroicon-outline", 45 | new TagHelperAttributeList 46 | { 47 | { "focusable", "true" }, 48 | }); 49 | var output = MakeTagHelperOutput( 50 | "heroicon-outline", 51 | new TagHelperAttributeList 52 | { 53 | { "focusable", "true" }, 54 | }); 55 | 56 | var options = Options.Create(new HeroiconOptions { SetFocusableAttribute = true }); 57 | var helper = new IconFocusableTagHelper(options); 58 | 59 | // When 60 | helper.Process(context, output); 61 | 62 | // Then 63 | AssertAttributeValue(output.Attributes, "focusable", "false"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | env: 13 | CONFIGURATION: Release 14 | DOTNET_NOLOGO: true 15 | FORCE_COLOR: 3 16 | 17 | jobs: 18 | lint-markdown: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Check out repository 23 | uses: actions/checkout@v5.0.0 24 | 25 | - name: Install Node 26 | uses: actions/setup-node@v6.0.0 27 | with: 28 | node-version-file: .nvmrc 29 | 30 | - uses: xt0rted/markdownlint-problem-matcher@v3.0.0 31 | 32 | - run: npm ci 33 | 34 | - run: npm test 35 | 36 | build: 37 | needs: lint-markdown 38 | 39 | runs-on: ubuntu-latest 40 | 41 | permissions: 42 | packages: write 43 | 44 | steps: 45 | - name: Check out repository 46 | uses: actions/checkout@v5.0.0 47 | 48 | - name: Build version suffix 49 | run: echo "VERSION_SUFFIX=beta.${{ github.run_number }}" >> $GITHUB_ENV 50 | 51 | - name: Set up Node 52 | uses: actions/setup-node@v6.0.0 53 | with: 54 | node-version-file: .nvmrc 55 | 56 | - name: Set up .NET 57 | uses: xt0rted/setup-dotnet@v1.5.0 58 | 59 | - name: Set up .NET 60 | uses: xt0rted/setup-dotnet@v1.5.0 61 | with: 62 | colored-output: false 63 | strip-comments-from-global-json: false 64 | dotnet-version: | 65 | 6.0.x 66 | 67 | - run: npm ci 68 | 69 | - run: dotnet tool restore 70 | 71 | - run: dotnet r build 72 | 73 | - run: dotnet r test -- --no-build --logger GitHubActions 74 | 75 | - run: dotnet r pack -- --no-build --version-suffix $VERSION_SUFFIX 76 | 77 | - name: Publish artifacts 78 | uses: actions/upload-artifact@v5.0.0 79 | with: 80 | path: ./artifacts/*.nupkg 81 | 82 | - name: Publish to GPR 83 | run: | 84 | dotnet nuget push "./artifacts/*.nupkg" \ 85 | --api-key ${{ secrets.GITHUB_TOKEN }} \ 86 | --source https://nuget.pkg.github.com/${{ github.repository_owner }} 87 | -------------------------------------------------------------------------------- /src/IconAccessibilityTagHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | /// 4 | /// Tag helper that sets the aria-hidden or role attribute based on if aria-label or aria-labeledby are set. 5 | /// The attributes will only be set if they don't already exist on the element. 6 | /// 7 | [HtmlTargetElement("heroicon-micro")] 8 | [HtmlTargetElement("heroicon-mini")] 9 | [HtmlTargetElement("heroicon-outline")] 10 | [HtmlTargetElement("heroicon-solid")] 11 | public class IconAccessibilityTagHelper : TagHelper 12 | { 13 | private readonly HeroiconOptions _settings; 14 | 15 | /// 16 | /// Creates a new . 17 | /// 18 | /// The to use when processing the target element. 19 | /// 20 | public IconAccessibilityTagHelper(IOptions settings) 21 | => _settings = settings?.Value ?? throw new ArgumentNullException(nameof(settings)); 22 | 23 | /// 24 | public override int Order => 1000; 25 | 26 | /// 27 | public override void Process(TagHelperContext context, TagHelperOutput output) 28 | { 29 | ArgumentNullException.ThrowIfNull(context); 30 | ArgumentNullException.ThrowIfNull(output); 31 | 32 | if (!_settings.SetAccessibilityAttributes) 33 | { 34 | return; 35 | } 36 | 37 | var isUsedAsImage = 38 | output.Attributes.ContainsName("aria-label") || 39 | output.Attributes.ContainsName("aria-labeledby"); 40 | 41 | if (isUsedAsImage) 42 | { 43 | // If the attribute is already set then honor that value instead of forcing it to img 44 | if (!output.Attributes.ContainsName("role")) 45 | { 46 | output.Attributes.SetAttribute("role", "img"); 47 | } 48 | } 49 | else 50 | { 51 | // If the attribute is already set then honor that value instead of forcing it to true 52 | if (!output.Attributes.ContainsName("aria-hidden")) 53 | { 54 | output.Attributes.SetAttribute("aria-hidden", "true"); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | 8 | permissions: 9 | contents: write 10 | packages: write 11 | 12 | env: 13 | CONFIGURATION: Release 14 | DOTNET_NOLOGO: true 15 | FORCE_COLOR: 3 16 | 17 | jobs: 18 | build: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Get version from tag 23 | id: tag_name 24 | run: echo "current_version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT 25 | 26 | - name: Check out repository 27 | uses: actions/checkout@v5.0.0 28 | 29 | - name: Set up Node 30 | uses: actions/setup-node@v6.0.0 31 | with: 32 | node-version-file: .nvmrc 33 | 34 | - name: Set up .NET 35 | uses: xt0rted/setup-dotnet@v1.5.0 36 | 37 | - name: Set up .NET 38 | uses: xt0rted/setup-dotnet@v1.5.0 39 | with: 40 | colored-output: false 41 | strip-comments-from-global-json: false 42 | dotnet-version: | 43 | 6.0.x 44 | 45 | - run: npm ci 46 | 47 | - run: dotnet tool restore 48 | 49 | - run: dotnet r build 50 | 51 | - run: dotnet r test -- --no-build --logger GitHubActions 52 | 53 | - run: dotnet r pack -- --no-build 54 | 55 | - name: Publish artifacts 56 | uses: actions/upload-artifact@v5.0.0 57 | with: 58 | path: ./artifacts/*.nupkg 59 | 60 | - name: Get changelog entry 61 | uses: mindsers/changelog-reader-action@v2.2.3 62 | id: changelog_reader 63 | with: 64 | version: ${{ steps.tag_name.outputs.current_version }} 65 | 66 | - name: Upload release assets 67 | uses: softprops/action-gh-release@v2.5.0 68 | id: release_updater 69 | with: 70 | body: ${{ steps.changelog_reader.outputs.changes }} 71 | files: ./artifacts/*.nupkg 72 | 73 | - name: Create discussion for release 74 | run: | 75 | gh api \ 76 | --method PATCH \ 77 | -H "Accept: application/vnd.github+json" \ 78 | /repos/${{ github.repository }}/releases/${{ steps.release_updater.outputs.id }} \ 79 | -f discussion_category_name='Announcements' 80 | env: 81 | GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} 82 | 83 | - name: Publish to GPR 84 | run: | 85 | dotnet nuget push "./artifacts/*.nupkg" \ 86 | --api-key ${{ secrets.GITHUB_TOKEN }} \ 87 | --source https://nuget.pkg.github.com/${{ github.repository_owner }} 88 | 89 | - name: Publish to nuget.org 90 | run: | 91 | dotnet nuget push "./artifacts/*.nupkg" \ 92 | --api-key ${{ secrets.NUGET_TOKEN }} \ 93 | --source https://api.nuget.org/v3/index.json 94 | -------------------------------------------------------------------------------- /test/IconListTests.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | public class IconListTests 4 | { 5 | [Fact] 6 | public void Should_return_the_ArrowDownCircle_icon_in_the_micro_style() 7 | { 8 | // Given / When 9 | var icon = IconList.Micro(IconSymbol.ArrowDownCircle); 10 | 11 | // Then 12 | icon.Path.ShouldBe( 13 | """ 14 | 15 | """); 16 | icon.ViewBox.ShouldBe("0 0 16 16"); 17 | icon.StrokeWidth.ShouldBeNull(); 18 | } 19 | 20 | [Fact] 21 | public void Should_return_the_ArrowDownCircle_icon_in_the_mini_style() 22 | { 23 | // Given / When 24 | var icon = IconList.Mini(IconSymbol.ArrowDownCircle); 25 | 26 | // Then 27 | icon.Path.ShouldBe( 28 | """ 29 | 30 | """); 31 | icon.ViewBox.ShouldBe("0 0 20 20"); 32 | icon.StrokeWidth.ShouldBeNull(); 33 | } 34 | 35 | [Fact] 36 | public void Should_return_the_ArrowDownCircle_icon_in_the_outline_style() 37 | { 38 | // Given / When 39 | var icon = IconList.Outline(IconSymbol.ArrowDownCircle); 40 | 41 | // Then 42 | icon.Path.ShouldBe( 43 | """ 44 | 45 | """); 46 | icon.ViewBox.ShouldBe("0 0 24 24"); 47 | icon.StrokeWidth.ShouldBe("1.5"); 48 | } 49 | 50 | [Fact] 51 | public void Should_return_the_ArrowDownCircle_icon_in_the_solid_style() 52 | { 53 | // Given / When 54 | var icon = IconList.Solid(IconSymbol.ArrowDownCircle); 55 | 56 | // Then 57 | icon.Path.ShouldBe( 58 | """ 59 | 60 | """); 61 | icon.ViewBox.ShouldBe("0 0 24 24"); 62 | icon.StrokeWidth.ShouldBeNull(); 63 | } 64 | 65 | [Fact] 66 | public void Should_throw_for_unsupported_icon_in_micro_set() 67 | { 68 | // Given 69 | #pragma warning disable CS0618 // Type or member is obsolete 70 | const IconSymbol icon = IconSymbol.PlusSmall; 71 | #pragma warning restore CS0618 // Type or member is obsolete 72 | 73 | // When 74 | var result = () => IconList.Micro(icon); 75 | 76 | // Then 77 | var ex = Should.Throw(result); 78 | ex.Style.ShouldBe("micro"); 79 | ex.Name.ShouldBe("plus-small"); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /HeroiconsTagHelper.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31825.309 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HeroiconsTagHelper", "src\HeroiconsTagHelper.csproj", "{FBD1EFF0-360A-4D88-AA08-525FDA4DF972}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{23F1CB61-0E53-4E6C-A71F-592441EDBAD2}" 9 | ProjectSection(SolutionItems) = preProject 10 | .editorconfig = .editorconfig 11 | .gitattributes = .gitattributes 12 | .gitignore = .gitignore 13 | CHANGELOG.md = CHANGELOG.md 14 | Directory.Build.props = Directory.Build.props 15 | global.json = global.json 16 | LICENSE = LICENSE 17 | obsolete_icons.txt = obsolete_icons.txt 18 | package.json = package.json 19 | README.md = README.md 20 | EndProjectSection 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HeroiconsTagHelperTests", "test\HeroiconsTagHelperTests.csproj", "{E8846EB7-AAD0-440F-8077-D097436AB53E}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "sample\Sample.csproj", "{11897DA3-A787-4D94-81B2-224EEF36E0CB}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IconSourceGenerator", "generator\IconSourceGenerator.csproj", "{B993F048-E11B-41F3-8AC5-B7F712F10B32}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {FBD1EFF0-360A-4D88-AA08-525FDA4DF972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {FBD1EFF0-360A-4D88-AA08-525FDA4DF972}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {FBD1EFF0-360A-4D88-AA08-525FDA4DF972}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {FBD1EFF0-360A-4D88-AA08-525FDA4DF972}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {E8846EB7-AAD0-440F-8077-D097436AB53E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {E8846EB7-AAD0-440F-8077-D097436AB53E}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {E8846EB7-AAD0-440F-8077-D097436AB53E}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {E8846EB7-AAD0-440F-8077-D097436AB53E}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {11897DA3-A787-4D94-81B2-224EEF36E0CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {11897DA3-A787-4D94-81B2-224EEF36E0CB}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {11897DA3-A787-4D94-81B2-224EEF36E0CB}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {11897DA3-A787-4D94-81B2-224EEF36E0CB}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {B993F048-E11B-41F3-8AC5-B7F712F10B32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {B993F048-E11B-41F3-8AC5-B7F712F10B32}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {B993F048-E11B-41F3-8AC5-B7F712F10B32}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {B993F048-E11B-41F3-8AC5-B7F712F10B32}.Release|Any CPU.Build.0 = Release|Any CPU 50 | EndGlobalSection 51 | GlobalSection(SolutionProperties) = preSolution 52 | HideSolutionNode = FALSE 53 | EndGlobalSection 54 | GlobalSection(ExtensibilityGlobals) = postSolution 55 | SolutionGuid = {E554F9FA-ADBD-4565-BAE1-B56DB92FED89} 56 | EndGlobalSection 57 | EndGlobal 58 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | insert_final_newline = true 6 | indent_style = space 7 | trim_trailing_whitespace = true 8 | 9 | [*.cs] 10 | indent_size = 4 11 | 12 | [*.cshtml] 13 | charset = utf-8-bom 14 | indent_size = 2 15 | 16 | # Xml project files 17 | [*.csproj] 18 | charset = utf-8 19 | indent_size = 2 20 | 21 | # Xml config files 22 | [*.{config,props,targets}] 23 | indent_size = 2 24 | 25 | [*.json] 26 | indent_size = 2 27 | 28 | [*.yml] 29 | indent_size = 2 30 | 31 | # CSharp code style settings: 32 | [*.cs] 33 | # Prefer "var" everywhere 34 | csharp_style_var_for_built_in_types = true:error 35 | csharp_style_var_when_type_is_apparent = true:error 36 | csharp_style_var_elsewhere = true:error 37 | 38 | csharp_style_expression_bodied_accessors = true:suggestion 39 | csharp_style_expression_bodied_constructors = true:suggestion 40 | csharp_style_expression_bodied_indexers = true:suggestion 41 | # IDE0022: Use block body for methods 42 | csharp_style_expression_bodied_methods = true:suggestion 43 | csharp_style_expression_bodied_properties = true:suggestion 44 | 45 | csharp_style_inlined_variable_declaration = true:error 46 | 47 | # Require using directives inside a namespace 48 | csharp_using_directive_placement = inside_namespace:error 49 | csharp_indent_case_contents = true 50 | csharp_indent_case_contents_when_block = false 51 | csharp_preserve_single_line_blocks = true 52 | csharp_preserve_single_line_statements = true 53 | csharp_indent_switch_labels = true 54 | 55 | # Formatting - new line options 56 | 57 | # Place catch statements on a new line 58 | csharp_new_line_before_catch = true 59 | # Place else statements on a new line 60 | csharp_new_line_before_else = true 61 | # Require braces to be on a new line for methods, control_blocks, lambdas, types, and object_collection (also known as "Allman" style) 62 | csharp_new_line_before_open_brace = all 63 | # IDE0011: Add braces 64 | csharp_prefer_braces = when_multiline:error 65 | 66 | # Formatting - spacing options 67 | 68 | # Require NO space between a cast and the value 69 | csharp_space_after_cast = false 70 | # Require a space before the colon for bases or interfaces in a type declaration 71 | csharp_space_after_colon_in_inheritance_clause = true 72 | # Require a space after a keyword in a control flow statement such as a for loop 73 | csharp_space_after_keywords_in_control_flow_statements = true 74 | # Require a space before the colon for bases or interfaces in a type declaration 75 | csharp_space_before_colon_in_inheritance_clause = true 76 | # Remove space within empty argument list parentheses 77 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 78 | # Remove space between method call name and opening parenthesis 79 | csharp_space_between_method_call_name_and_opening_parenthesis = false 80 | # Do not place space characters after the opening parenthesis and before the closing parenthesis of a method call 81 | csharp_space_between_method_call_parameter_list_parentheses = false 82 | # Remove space within empty parameter list parentheses for a method declaration 83 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 84 | # Place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. 85 | csharp_space_between_method_declaration_parameter_list_parentheses = false 86 | -------------------------------------------------------------------------------- /src/HeroiconsTagHelper.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(_TargetFrameworks) 5 | HeroiconsTagHelper 6 | Tailwind.Heroicons 7 | true 8 | embedded 9 | true 10 | true 11 | true 12 | True 13 | 14 | 15 | 16 | ASP.NET tag helper for adding Heroicons to your razor views 17 | true 18 | true 19 | logo.png 20 | MIT 21 | https://github.com/xt0rted/heroicons-tag-helper 22 | README.md 23 | See https://github.com/xt0rted/heroicons-tag-helper/blob/main/CHANGELOG.md for more info 24 | Heroicons;Icons;Tailwind;TailwindCSS;TagHelper;TagHelpers 25 | true 26 | main 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | icons 40 | 41 | 42 | icons/micro 43 | 44 | 45 | icons/mini 46 | 47 | 48 | icons/outline 49 | 50 | 51 | icons/solid 52 | 53 | 54 | 55 | 56 | 57 | assets 58 | 59 | 60 | assets 61 | 62 | 63 | assets 64 | 65 | 66 | assets/heroicons 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/IconTagHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | /// 4 | /// Tag helper that emits Heroicon icons as inline svg elements. 5 | /// 6 | [HtmlTargetElement("heroicon-micro", TagStructure = TagStructure.WithoutEndTag)] 7 | [HtmlTargetElement("heroicon-mini", TagStructure = TagStructure.WithoutEndTag)] 8 | [HtmlTargetElement("heroicon-outline", TagStructure = TagStructure.WithoutEndTag)] 9 | [HtmlTargetElement("heroicon-solid", TagStructure = TagStructure.WithoutEndTag)] 10 | [OutputElementHint("svg")] 11 | public class IconTagHelper : TagHelper 12 | { 13 | private readonly HeroiconOptions _settings; 14 | 15 | /// 16 | /// Creates a new . 17 | /// 18 | /// The to use when processing the target element. 19 | /// 20 | public IconTagHelper(IOptions settings) 21 | => _settings = settings?.Value ?? throw new ArgumentNullException(nameof(settings)); 22 | 23 | /// 24 | public override int Order => 0; 25 | 26 | /// 27 | /// The name of the Heroicon to use. 28 | /// 29 | [HtmlAttributeName("icon")] 30 | public IconSymbol Icon { get; set; } 31 | 32 | /// 33 | public override void Process(TagHelperContext context, TagHelperOutput output) 34 | { 35 | ArgumentNullException.ThrowIfNull(context); 36 | ArgumentNullException.ThrowIfNull(output); 37 | 38 | var isMicro = context.TagName.Equals("heroicon-micro", StringComparison.OrdinalIgnoreCase); 39 | var isMini = context.TagName.Equals("heroicon-mini", StringComparison.OrdinalIgnoreCase); 40 | var isSolid = context.TagName.Equals("heroicon-solid", StringComparison.OrdinalIgnoreCase); 41 | 42 | Icon icon; 43 | 44 | if (isMicro) 45 | { 46 | icon = IconList.Micro(Icon); 47 | } 48 | else if (isMini) 49 | { 50 | icon = IconList.Mini(Icon); 51 | } 52 | else if (isSolid) 53 | { 54 | icon = IconList.Solid(Icon); 55 | } 56 | else 57 | { 58 | icon = IconList.Outline(Icon); 59 | } 60 | 61 | output.TagMode = TagMode.StartTagAndEndTag; 62 | output.TagName = "svg"; 63 | 64 | if (isMicro || isMini || isSolid) 65 | { 66 | output.Attributes.SetAttribute("fill", "currentColor"); 67 | } 68 | else 69 | { 70 | output.Attributes.SetAttribute("fill", "none"); 71 | output.Attributes.SetAttribute("stroke", "currentColor"); 72 | output.Attributes.SetAttribute("stroke-width", icon.StrokeWidth); 73 | } 74 | 75 | output.Attributes.SetAttribute("viewbox", icon.ViewBox); 76 | 77 | output.Content.AppendHtml(icon.Path); 78 | 79 | if (_settings.IncludeComments) 80 | { 81 | var iconStyle = IconStyle( 82 | isMicro, 83 | isMini, 84 | isSolid); 85 | 86 | output.PreElement.AppendHtml(""); 91 | } 92 | } 93 | 94 | private static string IconStyle( 95 | bool isMicro, 96 | bool isMini, 97 | bool isSolid) 98 | { 99 | if (isMicro) 100 | { 101 | return "micro"; 102 | } 103 | 104 | if (isMini) 105 | { 106 | return "mini"; 107 | } 108 | 109 | if (isSolid) 110 | { 111 | return "solid"; 112 | } 113 | 114 | return "outline"; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # heroicons-tag-helper 2 | 3 | [![CI build status](https://github.com/xt0rted/heroicons-tag-helper/workflows/CI/badge.svg)](https://github.com/xt0rted/heroicons-tag-helper/actions?query=workflow%3ACI) 4 | [![NuGet Package](https://img.shields.io/nuget/v/HeroiconsTagHelper?logo=nuget)](https://www.nuget.org/packages/HeroiconsTagHelper) 5 | [![GitHub Package Registry](https://img.shields.io/badge/github-package_registry-yellow?logo=nuget)](https://nuget.pkg.github.com/xt0rted/index.json) 6 | [![Project license](https://img.shields.io/github/license/xt0rted/heroicons-tag-helper)](LICENSE) 7 | 8 | ASP.NET tag helper for adding [Heroicons](https://heroicons.com/) to your razor views. 9 | 10 | ## Installation 11 | 12 | > [!NOTE] 13 | > This package's version is aligned with the [heroicons NPM package](https://www.npmjs.com/package/heroicons) so you always know which version you're using. 14 | 15 | ```terminal 16 | dotnet add package HeroiconsTagHelper 17 | ``` 18 | 19 | CI builds can be downloaded from the [packages page](https://github.com/xt0rted/heroicons-tag-helper/packages/473445) or the GitHub feed. 20 | They're also available as build artifacts on every PR. 21 | 22 | ## Setup 23 | 24 | In your `_ViewImports.cshtml` add: 25 | 26 | ```html 27 | @addTagHelper *, HeroiconsTagHelper 28 | ``` 29 | 30 | In your `Startup.cs` add: 31 | 32 | ```csharp 33 | public void ConfigureServices(IServiceCollection services) 34 | { 35 | services.AddHeroicons(Configuration); 36 | } 37 | ``` 38 | 39 | In your `appsettings.json` add: 40 | 41 | ```json 42 | { 43 | "Heroicons": { 44 | "IncludeComments": true, 45 | "SetAccessibilityAttributes": true, 46 | "SetFocusableAttribute": true 47 | } 48 | } 49 | ``` 50 | 51 | ## Settings 52 | 53 | Name | Default Value | Description 54 | :-- | :-- | :-- 55 | `IncludeComments` | `false` | Add an html comment before the svg tag with the style and name of the icon to help make development/debugging easier. 56 | `SetAccessibilityAttributes` | `false` | Adds various accessibility attributes based on the default state of the tag. 57 | `SetFocusableAttribute` | `false` | Adds the `focusable` attribute set to `false` to prevent the icon from receiving focus in Internet Explorer and Edge Legacy. 58 | 59 | ### SetAccessibilityAttributes 60 | 61 | If `aria-label` or `aria-labeledby` are set then the icon is being used as an image so [`role="img"`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Role_Img#svg_and_roleimg) will be added to the svg tag, otherwise [`aria-hidden="true"`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-hidden_attribute) will be added. 62 | 63 | > **Note**: If the element already contains an `aria-hidden` or `role` attribute then it will not be modified. 64 | 65 | ## Usage 66 | 67 | There are two versions of the tag helper which are used to pick between the `outline` and `solid` icon styles. 68 | 69 | ```html 70 | 71 | ``` 72 | 73 | will output 74 | 75 | ```xml 76 | 77 | 78 | 79 | ``` 80 | 81 | ```html 82 | 83 | ``` 84 | 85 | will output 86 | 87 | ```xml 88 | 89 | 90 | 91 | ``` 92 | 93 | ## Development 94 | 95 | This project uses the [run-script](https://github.com/xt0rted/dotnet-run-script) dotnet tool to manage its build and test scripts. 96 | To use this you'll need to run `dotnet tool install` and then `dotnet r` to see the available commands or look at the `scripts` section in the [global.json](global.json). 97 | -------------------------------------------------------------------------------- /test/IconAccessibilityTagHelperTests.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | public class IconAccessibilityTagHelperTests : TagHelperTestBase 4 | { 5 | [Fact] 6 | public void Should_not_set_accessibility_attributes_when_option_is_disabled() 7 | { 8 | // Given 9 | var context = MakeTagHelperContext("heroicon-outline"); 10 | var output = MakeTagHelperOutput("heroicon-outline"); 11 | 12 | var options = Options.Create(new HeroiconOptions { SetAccessibilityAttributes = false }); 13 | var helper = new IconAccessibilityTagHelper(options); 14 | 15 | // When 16 | helper.Process(context, output); 17 | 18 | // Then 19 | output.Attributes.ShouldNotContain(a => a.Name == "aria-hidden"); 20 | output.Attributes.ShouldNotContain(a => a.Name == "role"); 21 | } 22 | 23 | [Theory] 24 | [InlineData("aria-label")] 25 | [InlineData("aria-labeledby")] 26 | public void Should_set_role_attribute_when_label_attribute_is_set_and_role_is_not(string attributeName) 27 | { 28 | // Given 29 | var context = MakeTagHelperContext( 30 | "heroicon-outline", 31 | new TagHelperAttributeList 32 | { 33 | { attributeName, "test" }, 34 | }); 35 | var output = MakeTagHelperOutput( 36 | "heroicon-outline", 37 | new TagHelperAttributeList 38 | { 39 | { attributeName, "test" }, 40 | }); 41 | 42 | var options = Options.Create(new HeroiconOptions { SetAccessibilityAttributes = true }); 43 | var helper = new IconAccessibilityTagHelper(options); 44 | 45 | // When 46 | helper.Process(context, output); 47 | 48 | // Then 49 | AssertAttributeValue(output.Attributes, "role", "img"); 50 | } 51 | 52 | [Theory] 53 | [InlineData("aria-label")] 54 | [InlineData("aria-labeledby")] 55 | public void Should_not_set_role_attribute_when_label_attribute_is_set_and_role_already_is(string attributeName) 56 | { 57 | // Given 58 | var context = MakeTagHelperContext( 59 | "heroicon-outline", 60 | new TagHelperAttributeList 61 | { 62 | { attributeName, "test" }, 63 | { "role", "button" }, 64 | }); 65 | var output = MakeTagHelperOutput( 66 | "heroicon-outline", 67 | new TagHelperAttributeList 68 | { 69 | { attributeName, "test" }, 70 | { "role", "button" }, 71 | }); 72 | 73 | var options = Options.Create(new HeroiconOptions { SetAccessibilityAttributes = true }); 74 | var helper = new IconAccessibilityTagHelper(options); 75 | 76 | // When 77 | helper.Process(context, output); 78 | 79 | // Then 80 | AssertAttributeValue(output.Attributes, "role", "button"); 81 | } 82 | 83 | [Fact] 84 | public void Should_set_aria_hidden_attribute_to_true_when_not_used_as_an_image_and_attribute_is_not_already_set() 85 | { 86 | // Given 87 | var context = MakeTagHelperContext("heroicon-outline"); 88 | var output = MakeTagHelperOutput("heroicon-outline"); 89 | 90 | var options = Options.Create(new HeroiconOptions { SetAccessibilityAttributes = true }); 91 | var helper = new IconAccessibilityTagHelper(options); 92 | 93 | // When 94 | helper.Process(context, output); 95 | 96 | // Then 97 | AssertAttributeValue(output.Attributes, "aria-hidden", "true"); 98 | } 99 | 100 | [Fact] 101 | public void Should_not_set_aria_hidden_attribute_to_true_when_not_used_as_an_image_and_attribute_is_already_set() 102 | { 103 | // Given 104 | var context = MakeTagHelperContext( 105 | "heroicon-outline", 106 | new TagHelperAttributeList 107 | { 108 | { "aria-hidden", "foo" }, 109 | }); 110 | var output = MakeTagHelperOutput( 111 | "heroicon-outline", 112 | new TagHelperAttributeList 113 | { 114 | { "aria-hidden", "foo" }, 115 | }); 116 | 117 | var options = Options.Create(new HeroiconOptions { SetAccessibilityAttributes = true }); 118 | var helper = new IconAccessibilityTagHelper(options); 119 | 120 | // When 121 | helper.Process(context, output); 122 | 123 | // Then 124 | AssertAttributeValue(output.Attributes, "aria-hidden", "foo"); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # JustCode is a .NET coding add-in 131 | .JustCode 132 | 133 | # TeamCity is a build add-in 134 | _TeamCity* 135 | 136 | # DotCover is a Code Coverage Tool 137 | *.dotCover 138 | 139 | # AxoCover is a Code Coverage Tool 140 | .axoCover/* 141 | !.axoCover/settings.json 142 | 143 | # Visual Studio code coverage results 144 | *.coverage 145 | *.coveragexml 146 | 147 | # NCrunch 148 | _NCrunch_* 149 | .*crunch*.local.xml 150 | nCrunchTemp_* 151 | 152 | # MightyMoose 153 | *.mm.* 154 | AutoTest.Net/ 155 | 156 | # Web workbench (sass) 157 | .sass-cache/ 158 | 159 | # Installshield output folder 160 | [Ee]xpress/ 161 | 162 | # DocProject is a documentation generator add-in 163 | DocProject/buildhelp/ 164 | DocProject/Help/*.HxT 165 | DocProject/Help/*.HxC 166 | DocProject/Help/*.hhc 167 | DocProject/Help/*.hhk 168 | DocProject/Help/*.hhp 169 | DocProject/Help/Html2 170 | DocProject/Help/html 171 | 172 | # Click-Once directory 173 | publish/ 174 | 175 | # Publish Web Output 176 | *.[Pp]ublish.xml 177 | *.azurePubxml 178 | # Note: Comment the next line if you want to checkin your web deploy settings, 179 | # but database connection strings (with potential passwords) will be unencrypted 180 | *.pubxml 181 | *.publishproj 182 | 183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 184 | # checkin your Azure Web App publish settings, but sensitive information contained 185 | # in these scripts will be unencrypted 186 | PublishScripts/ 187 | 188 | # NuGet Packages 189 | *.nupkg 190 | # NuGet Symbol Packages 191 | *.snupkg 192 | # The packages folder can be ignored because of Package Restore 193 | **/[Pp]ackages/* 194 | # except build/, which is used as an MSBuild target. 195 | !**/[Pp]ackages/build/ 196 | # Uncomment if necessary however generally it will be regenerated when needed 197 | #!**/[Pp]ackages/repositories.config 198 | # NuGet v3's project.json files produces more ignorable files 199 | *.nuget.props 200 | *.nuget.targets 201 | 202 | # Microsoft Azure Build Output 203 | csx/ 204 | *.build.csdef 205 | 206 | # Microsoft Azure Emulator 207 | ecf/ 208 | rcf/ 209 | 210 | # Windows Store app package directories and files 211 | AppPackages/ 212 | BundleArtifacts/ 213 | Package.StoreAssociation.xml 214 | _pkginfo.txt 215 | *.appx 216 | *.appxbundle 217 | *.appxupload 218 | 219 | # Visual Studio cache files 220 | # files ending in .cache can be ignored 221 | *.[Cc]ache 222 | # but keep track of directories ending in .cache 223 | !?*.[Cc]ache/ 224 | 225 | # Others 226 | ClientBin/ 227 | ~$* 228 | *~ 229 | *.dbmdl 230 | *.dbproj.schemaview 231 | *.jfm 232 | *.pfx 233 | *.publishsettings 234 | orleans.codegen.cs 235 | 236 | # Including strong name files can present a security risk 237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 238 | #*.snk 239 | 240 | # Since there are multiple workflows, uncomment next line to ignore bower_components 241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 242 | #bower_components/ 243 | 244 | # RIA/Silverlight projects 245 | Generated_Code/ 246 | 247 | # Backup & report files from converting an old project file 248 | # to a newer Visual Studio version. Backup files are not needed, 249 | # because we have git ;-) 250 | _UpgradeReport_Files/ 251 | Backup*/ 252 | UpgradeLog*.XML 253 | UpgradeLog*.htm 254 | ServiceFabricBackup/ 255 | *.rptproj.bak 256 | 257 | # SQL Server files 258 | *.mdf 259 | *.ldf 260 | *.ndf 261 | 262 | # Business Intelligence projects 263 | *.rdl.data 264 | *.bim.layout 265 | *.bim_*.settings 266 | *.rptproj.rsuser 267 | *- [Bb]ackup.rdl 268 | *- [Bb]ackup ([0-9]).rdl 269 | *- [Bb]ackup ([0-9][0-9]).rdl 270 | 271 | # Microsoft Fakes 272 | FakesAssemblies/ 273 | 274 | # GhostDoc plugin setting file 275 | *.GhostDoc.xml 276 | 277 | # Node.js Tools for Visual Studio 278 | .ntvs_analysis.dat 279 | node_modules/ 280 | 281 | # Visual Studio 6 build log 282 | *.plg 283 | 284 | # Visual Studio 6 workspace options file 285 | *.opt 286 | 287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 288 | *.vbw 289 | 290 | # Visual Studio LightSwitch build output 291 | **/*.HTMLClient/GeneratedArtifacts 292 | **/*.DesktopClient/GeneratedArtifacts 293 | **/*.DesktopClient/ModelManifest.xml 294 | **/*.Server/GeneratedArtifacts 295 | **/*.Server/ModelManifest.xml 296 | _Pvt_Extensions 297 | 298 | # Paket dependency manager 299 | .paket/paket.exe 300 | paket-files/ 301 | 302 | # FAKE - F# Make 303 | .fake/ 304 | 305 | # CodeRush personal settings 306 | .cr/personal 307 | 308 | # Python Tools for Visual Studio (PTVS) 309 | __pycache__/ 310 | *.pyc 311 | 312 | # Cake - Uncomment if you are using it 313 | # tools/** 314 | # !tools/packages.config 315 | 316 | # Tabs Studio 317 | *.tss 318 | 319 | # Telerik's JustMock configuration file 320 | *.jmconfig 321 | 322 | # BizTalk build output 323 | *.btp.cs 324 | *.btm.cs 325 | *.odx.cs 326 | *.xsd.cs 327 | 328 | # OpenCover UI analysis results 329 | OpenCover/ 330 | 331 | # Azure Stream Analytics local run output 332 | ASALocalRun/ 333 | 334 | # MSBuild Binary and Structured Log 335 | *.binlog 336 | 337 | # NVidia Nsight GPU debugger configuration file 338 | *.nvuser 339 | 340 | # MFractors (Xamarin productivity tool) working folder 341 | .mfractor/ 342 | 343 | # Local History for Visual Studio 344 | .localhistory/ 345 | 346 | # BeatPulse healthcheck temp database 347 | healthchecksdb 348 | 349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 350 | MigrationBackup/ 351 | 352 | # Ionide (cross platform F# VS Code tools) working folder 353 | .ionide/ 354 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased 4 | 5 | ## [2.1.3](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.1.2...v2.1.3) - 2024-04-07 6 | 7 | - Bumped `heroicons` from 2.1.2 to 2.1.3 8 | 9 | ## [2.1.2](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.1.1...v2.1.2) - 2024-04-07 10 | 11 | - Bumped `heroicons` from 2.1.1 to 2.1.2 12 | 13 | ## [2.1.1](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.1.0...v2.1.1) - 2024-04-07 14 | 15 | - Bumped `heroicons` from 2.1.0 to 2.1.1 16 | 17 | ## [2.1.0](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.18...v2.1.0) - 2024-04-07 18 | 19 | - Bumped `heroicons` from 2.0.18 to 2.1.0 20 | - Adds new `micro` style 21 | - Renamed the following icons while keeping their old name as an obsolete alias: 22 | - Renamed `arrow-left-on-rectangle` to `arrow-left-end-on-rectangle` 23 | - Renamed `arrow-right-on-rectangle` to `arrow-right-end-on-rectangle` 24 | - All `*-small` icons in the outline and solid sets use the mini set instead and are marked as obsolete 25 | - All `*-small` icons in the mini set use the micro set instead and are marked as obsolete 26 | - Dropped support for .NET 7 which is no longer supported 27 | - Added support for .NET 8 28 | - Removed the deprecated `stroke-width` attribute 29 | - The `IconList` enum contains every icon across all styles and a new `UnsupportedIconException` will be thrown if you try to use an icon that's not supported for the given style 30 | - A future version might split this into one enum per style, if you have any feedback on this change please open an issue 31 | 32 | ## [2.0.18](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.17...v2.0.18) - 2023-07-02 33 | 34 | - Bumped `heroicons` from 2.0.17 to 2.0.18 35 | 36 | ## [2.0.17](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.16...v2.0.17) - 2023-07-02 37 | 38 | - Bumped `heroicons` from 2.0.16 to 2.0.17 39 | 40 | ## [2.0.16](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.15...v2.0.16) - 2023-07-02 41 | 42 | > **Note**: 43 | > This version drops support for .NET Core 3.1 44 | 45 | - Started targeting .NET 7.0 46 | - Bumped `heroicons` from 2.0.15 to 2.0.16 47 | 48 | ## [2.0.15](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.14...v2.0.15) - 2023-02-14 49 | 50 | - Bumped `heroicons` from 2.0.14 to 2.0.15 51 | 52 | ## [2.0.14](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.13...v2.0.14) - 2023-02-14 53 | 54 | - Bumped `heroicons` from 2.0.13 to 2.0.14 55 | 56 | ## [2.0.13](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.12...v2.0.13) - 2022-11-13 57 | 58 | - Bumped `heroicons` from 2.0.12 to 2.0.13 59 | 60 | ## [2.0.12](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.11...v2.0.12) - 2022-10-11 61 | 62 | - Bumped `heroicons` from 2.0.11 to 2.0.12 63 | 64 | ## [2.0.11](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.10...v2.0.11) - 2022-10-11 65 | 66 | - Bumped `heroicons` from 2.0.10 to 2.0.11 67 | - Adds new icons: `bug-ant`, `eye-dropper`, `pause-circle`, `play-circle`, `power`, `rocket-launch`, `square-2-stack-3d`, `stop-circle`, `trophy`, `tv`, `viewfinder-circle`, `window` 68 | 69 | ## [2.0.10](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.9...v2.0.10) - 2022-10-11 70 | 71 | - Bumped `heroicons` from 2.0.9 to 2.0.10 72 | 73 | ## [2.0.9](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.8...v2.0.9) - 2022-10-11 74 | 75 | - Bumped `heroicons` from 2.0.8 to 2.0.9 76 | - Adds new icons: `arrow-small-down`, `arrow-small-left`, `arrow-small-right`, `arrow-small-up`, `battery-0`, `battery-100`, `battery-50`, `cube-transparent`, `currency-bangladeshi`, `minus-small`, `paint-brush`, `plus-small`, `variable`, `wallet`, `arrow-path-rounded-square` 77 | 78 | ## [2.0.8](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.7...v2.0.8) - 2022-10-11 79 | 80 | - Bumped `heroicons` from 2.0.7 to 2.0.8 81 | - Adds new icons: `user-minus` 82 | 83 | ## [2.0.7](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.6...v2.0.7) - 2022-10-11 84 | 85 | - Bumped `heroicons` from 2.0.6 to 2.0.7 86 | 87 | ## [2.0.6](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.5...v2.0.6) - 2022-10-11 88 | 89 | - Bumped `heroicons` from 2.0.5 to 2.0.6 90 | 91 | ## [2.0.5](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.4...v2.0.5) - 2022-10-11 92 | 93 | - Bumped `heroicons` from 2.0.4 to 2.0.5 94 | 95 | ## [2.0.4](https://github.com/xt0rted/heroicons-tag-helper/compare/v2.0.3...v2.0.4) - 2022-10-11 96 | 97 | - Bumped `heroicons` from 2.0.3 to 2.0.4 98 | 99 | ## [2.0.3](https://github.com/xt0rted/heroicons-tag-helper/compare/v1.0.5...v2.0.3) - 2022-10-11 100 | 101 | > **Note**: Due to a number of missing/incorrectly named icons the following versions were skipped: v2.0.0, v2.0.1, v2.0.2 102 | 103 | - Bumped `heroicons` from 1.0.6 to 2.0.3 ([#186](https://github.com/xt0rted/heroicons-tag-helper/pull/186)) 104 | - A lot of icons were renamed in this release, see the `Update icon names` section in the [2.0.0 release notes](https://github.com/tailwindlabs/heroicons/releases/tag/v2.0.0) for more details 105 | - The new mini variant is available using the tag name `heroicon-mini` which supports the same settings as the solid variant 106 | - Dropped support for .NET 5 which is no longer supported 107 | - Fixed xml documentation file so it's included in the package ([#189](https://github.com/xt0rted/heroicons-tag-helper/pull/189)) 108 | - Adjusted `IconAccessibilityTagHelper` so it only sets the `aria-hidden` or `role` attributes if they don't already exist ([#191](https://github.com/xt0rted/heroicons-tag-helper/pull/191)) 109 | - In rare situations this could be a breaking change if you were relying on this to force a value 110 | - The `stroke-width` attribute is now deprecated in favor of [styling with css](https://tailwindcss.com/docs/stroke-width) ([#192](https://github.com/xt0rted/heroicons-tag-helper/pull/192)) 111 | - Switched from [actions/setup-dotnet](https://github.com/actions/setup-dotnet) to [xt0rted/setup-dotnet](https://github.com/xt0rted/setup-dotnet) ([#144](https://github.com/xt0rted/heroicons-tag-helper/pull/144)) 112 | 113 | ## [1.0.6](https://github.com/xt0rted/heroicons-tag-helper/compare/v1.0.5...v1.0.6) - 2022-03-15 114 | 115 | - Bumped `heroicons` from 1.0.5 to 1.0.6 ([#131](https://github.com/xt0rted/heroicons-tag-helper/pull/131)) 116 | - They moved the `stroke-width` attribute from the `path` to the `svg` element in this version. This attribute is still supported, but styling with css is the preferred method now. 117 | - Target .NET Core 3.1, .NET 5.0, and .NET 6.0 ([#95](https://github.com/xt0rted/heroicons-tag-helper/pull/95)) 118 | - Moved build scripts over to the [run-script](https://github.com/xt0rted/dotnet-run-script) dotnet tool ([#136](https://github.com/xt0rted/heroicons-tag-helper/pull/136)) 119 | 120 | ## [1.0.5](https://github.com/xt0rted/heroicons-tag-helper/compare/v1.0.4...v1.0.5) - 2021-11-07 121 | 122 | - Include `README.md` in the nupkg 123 | - Target .NET Core 3.1 and .NET 5.0 124 | - Bumped `heroicons` from 1.0.4 to 1.0.5 125 | 126 | ## [1.0.4](https://github.com/xt0rted/heroicons-tag-helper/compare/v1.0.2...v1.0.4) - 2021-08-19 127 | 128 | - Bumped `heroicons` from 1.0.2 to 1.0.4 129 | 130 | ## [1.0.2](https://github.com/xt0rted/heroicons-tag-helper/compare/v1.0.1...v1.0.2) - 2021-07-23 131 | 132 | - Bumped `heroicons` from 1.0.1 to 1.0.2 133 | 134 | ## [1.0.1](https://github.com/xt0rted/heroicons-tag-helper/compare/v1.0.0...v1.0.1) - 2021-04-21 135 | 136 | - Bumped `heroicons` from 1.0.0 to 1.0.1 137 | 138 | ## [1.0.0](https://github.com/xt0rted/heroicons-tag-helper/compare/v0.4.2...v1.0.0) - 2021-04-21 139 | 140 | - Bumped `heroicons` from 0.4.2 to 1.0.0 141 | 142 | ## [0.4.2](https://github.com/xt0rted/heroicons-tag-helper/releases/tag/v0.4.2) - 2021-04-20 143 | 144 | - Set `heroicons` version to v0.4.2 145 | - Added outline icons 146 | - Added solid icons 147 | - Added settings for `IncludeComments`, `SetAccessibilityAttributes`, and `SetFocusableAttribute` 148 | -------------------------------------------------------------------------------- /test/IconTagHelperTests.cs: -------------------------------------------------------------------------------- 1 | namespace Tailwind.Heroicons; 2 | 3 | public class IconTagHelperTests : TagHelperTestBase 4 | { 5 | [Fact] 6 | public void Should_set_svg_attributes() 7 | { 8 | // Given 9 | var context = MakeTagHelperContext("heroicon-outline"); 10 | var output = MakeTagHelperOutput("heroicon-outline"); 11 | 12 | var options = Options.Create(new HeroiconOptions()); 13 | var helper = new IconTagHelper(options); 14 | 15 | // When 16 | helper.Process(context, output); 17 | 18 | // Then 19 | output.TagMode.ShouldBe(TagMode.StartTagAndEndTag); 20 | output.TagName.ShouldBe("svg"); 21 | AssertAttributeValue(output.Attributes, "viewbox", "0 0 24 24"); 22 | } 23 | 24 | [Fact] 25 | public void Should_overwrite_existing_attributes_for_solid_style() 26 | { 27 | // Given 28 | var context = MakeTagHelperContext( 29 | "heroicon-solid", 30 | new TagHelperAttributeList 31 | { 32 | { "fill", "blue" }, 33 | { "viewbox", "0 0 1 1" }, 34 | }); 35 | var output = MakeTagHelperOutput( 36 | "heroicon-solid", 37 | new TagHelperAttributeList 38 | { 39 | { "fill", "blue" }, 40 | { "viewbox", "0 0 1 1" }, 41 | }); 42 | 43 | var options = Options.Create(new HeroiconOptions()); 44 | var helper = new IconTagHelper(options) 45 | { 46 | Icon = IconSymbol.Bell, 47 | }; 48 | 49 | // When 50 | helper.Process(context, output); 51 | 52 | // Then 53 | AssertAttributeValue(output.Attributes, "fill", "currentColor"); 54 | AssertAttributeValue(output.Attributes, "viewbox", "0 0 24 24"); 55 | output.Attributes.ShouldNotContain(a => a.Name == "stroke"); 56 | } 57 | 58 | [Fact] 59 | public void Should_overwrite_existing_attributes_for_outline_style() 60 | { 61 | // Given 62 | var context = MakeTagHelperContext( 63 | "heroicon-outline", 64 | new TagHelperAttributeList 65 | { 66 | { "fill", "blue" }, 67 | { "stroke", "blue" }, 68 | { "viewbox", "0 0 1 1" }, 69 | }); 70 | var output = MakeTagHelperOutput( 71 | "heroicon-outline", 72 | new TagHelperAttributeList 73 | { 74 | { "fill", "blue" }, 75 | { "stroke", "blue" }, 76 | { "viewbox", "0 0 1 1" }, 77 | }); 78 | 79 | var options = Options.Create(new HeroiconOptions()); 80 | var helper = new IconTagHelper(options) 81 | { 82 | Icon = IconSymbol.Bell, 83 | }; 84 | 85 | // When 86 | helper.Process(context, output); 87 | 88 | // Then 89 | AssertAttributeValue(output.Attributes, "fill", "none"); 90 | AssertAttributeValue(output.Attributes, "stroke", "currentColor"); 91 | AssertAttributeValue(output.Attributes, "viewbox", "0 0 24 24"); 92 | } 93 | 94 | [Theory] 95 | [InlineData("heroicon-micro")] 96 | [InlineData("Heroicon-Micro")] 97 | [InlineData("HEROICON-MICRO")] 98 | public void Should_output_micro_bell_icon(string tagName) 99 | { 100 | // Given 101 | var context = MakeTagHelperContext(tagName); 102 | var output = MakeTagHelperOutput(tagName); 103 | 104 | var options = Options.Create(new HeroiconOptions()); 105 | var helper = new IconTagHelper(options) 106 | { 107 | Icon = IconSymbol.Bell, 108 | }; 109 | 110 | // When 111 | helper.Process(context, output); 112 | 113 | // Then 114 | AssertAttributeValue(output.Attributes, "fill", "currentColor"); 115 | AssertAttributeValue(output.Attributes, "viewbox", "0 0 16 16"); 116 | output.Attributes.ShouldNotContain(a => a.Name == "stroke"); 117 | output.Attributes.ShouldNotContain(a => a.Name == "stroke-width"); 118 | output.Content.GetContent().ShouldBe( 119 | """ 120 | 121 | """); 122 | } 123 | 124 | [Theory] 125 | [InlineData("heroicon-mini")] 126 | [InlineData("Heroicon-Mini")] 127 | [InlineData("HEROICON-MINI")] 128 | public void Should_output_mini_bell_icon(string tagName) 129 | { 130 | // Given 131 | var context = MakeTagHelperContext(tagName); 132 | var output = MakeTagHelperOutput(tagName); 133 | 134 | var options = Options.Create(new HeroiconOptions()); 135 | var helper = new IconTagHelper(options) 136 | { 137 | Icon = IconSymbol.Bell, 138 | }; 139 | 140 | // When 141 | helper.Process(context, output); 142 | 143 | // Then 144 | AssertAttributeValue(output.Attributes, "fill", "currentColor"); 145 | AssertAttributeValue(output.Attributes, "viewbox", "0 0 20 20"); 146 | output.Attributes.ShouldNotContain(a => a.Name == "stroke"); 147 | output.Attributes.ShouldNotContain(a => a.Name == "stroke-width"); 148 | output.Content.GetContent().ShouldBe( 149 | """ 150 | 151 | """); 152 | } 153 | 154 | [Theory] 155 | [InlineData("heroicon-outline")] 156 | [InlineData("Heroicon-Outline")] 157 | [InlineData("HEROICON-OUTLINE")] 158 | public void Should_output_outline_bell_icon(string tagName) 159 | { 160 | // Given 161 | var context = MakeTagHelperContext(tagName); 162 | var output = MakeTagHelperOutput(tagName); 163 | 164 | var options = Options.Create(new HeroiconOptions()); 165 | var helper = new IconTagHelper(options) 166 | { 167 | Icon = IconSymbol.Bell, 168 | }; 169 | 170 | // When 171 | helper.Process(context, output); 172 | 173 | // Then 174 | AssertAttributeValue(output.Attributes, "fill", "none"); 175 | AssertAttributeValue(output.Attributes, "stroke", "currentColor"); 176 | AssertAttributeValue(output.Attributes, "stroke-width", "1.5"); 177 | AssertAttributeValue(output.Attributes, "viewbox", "0 0 24 24"); 178 | output.Content.GetContent().ShouldBe( 179 | """ 180 | 181 | """); 182 | } 183 | 184 | [Theory] 185 | [InlineData("heroicon-solid")] 186 | [InlineData("Heroicon-Solid")] 187 | [InlineData("HEROICON-SOLID")] 188 | public void Should_output_solid_bell_icon(string tagName) 189 | { 190 | // Given 191 | var context = MakeTagHelperContext(tagName); 192 | var output = MakeTagHelperOutput(tagName); 193 | 194 | var options = Options.Create(new HeroiconOptions()); 195 | var helper = new IconTagHelper(options) 196 | { 197 | Icon = IconSymbol.Bell, 198 | }; 199 | 200 | // When 201 | helper.Process(context, output); 202 | 203 | // Then 204 | AssertAttributeValue(output.Attributes, "fill", "currentColor"); 205 | AssertAttributeValue(output.Attributes, "viewbox", "0 0 24 24"); 206 | output.Attributes.ShouldNotContain(a => a.Name == "stroke"); 207 | output.Attributes.ShouldNotContain(a => a.Name == "stroke-width"); 208 | output.Content.GetContent().ShouldBe( 209 | """ 210 | 211 | """); 212 | } 213 | 214 | [Theory] 215 | [InlineData("class", "h-6 w-6")] 216 | [InlineData("style", "height: 32px; width: 32px;")] 217 | [InlineData("data-icon", "heroicons")] 218 | public void Should_apply_custom_attributes(string attributeName, string attributeValue) 219 | { 220 | // Given 221 | var context = MakeTagHelperContext( 222 | "heroicon-solid", 223 | new TagHelperAttributeList 224 | { 225 | { attributeName, attributeValue }, 226 | }); 227 | var output = MakeTagHelperOutput( 228 | "heroicon-solid", 229 | new TagHelperAttributeList 230 | { 231 | { attributeName, attributeValue }, 232 | }); 233 | 234 | var options = Options.Create(new HeroiconOptions()); 235 | var helper = new IconTagHelper(options) 236 | { 237 | Icon = IconSymbol.Bell, 238 | }; 239 | 240 | // When 241 | helper.Process(context, output); 242 | 243 | // Then 244 | AssertAttributeValue(output.Attributes, attributeName, attributeValue); 245 | } 246 | 247 | [Fact] 248 | public void Should_not_include_html_comment_when_IncludeComments_is_false() 249 | { 250 | // Given 251 | var context = MakeTagHelperContext("heroicon-outline"); 252 | var output = MakeTagHelperOutput("heroicon-outline"); 253 | 254 | var options = Options.Create( 255 | new HeroiconOptions 256 | { 257 | IncludeComments = false, 258 | }); 259 | var helper = new IconTagHelper(options) 260 | { 261 | Icon = IconSymbol.Bell, 262 | }; 263 | 264 | // When 265 | helper.Process(context, output); 266 | 267 | // Then 268 | output.PreElement.GetContent().ShouldBeEmpty(); 269 | } 270 | 271 | [Fact] 272 | public void Should_include_html_comment_when_IncludeComments_is_true() 273 | { 274 | // Given 275 | var context = MakeTagHelperContext("heroicon-outline"); 276 | var output = MakeTagHelperOutput("heroicon-outline"); 277 | 278 | var options = Options.Create( 279 | new HeroiconOptions 280 | { 281 | IncludeComments = true, 282 | }); 283 | var helper = new IconTagHelper(options) 284 | { 285 | Icon = IconSymbol.Bell, 286 | }; 287 | 288 | // When 289 | helper.Process(context, output); 290 | 291 | // Then 292 | output.PreElement.GetContent().ShouldBe( 293 | """ 294 | 295 | 296 | """); 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /generator/IconSourceGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace IconSourceGenerator; 2 | 3 | using AllIcons = List<(string name, string className)>; 4 | using IconMap = Dictionary>; 5 | 6 | [Generator] 7 | public class IconSourceGenerator : ISourceGenerator 8 | { 9 | private static readonly DiagnosticDescriptor _errorDescriptor = new( 10 | "SI0000", 11 | "Error in the IconSourceGenerator generator", 12 | "Error in the IconSourceGenerator generator: '{0}'", 13 | "IconSourceGenerator", 14 | DiagnosticSeverity.Error, 15 | isEnabledByDefault: true); 16 | 17 | public void Execute(GeneratorExecutionContext context) 18 | { 19 | try 20 | { 21 | ExecuteInternal(context); 22 | } 23 | catch (Exception ex) 24 | { 25 | context.ReportDiagnostic(Diagnostic.Create(_errorDescriptor, Location.None, ex.ToString())); 26 | } 27 | } 28 | 29 | [MethodImpl(MethodImplOptions.NoInlining)] 30 | private void ExecuteInternal(GeneratorExecutionContext context) 31 | { 32 | var obsoleteIcons = LoadObsoleteIconList(context); 33 | var icons = LoadIcons(context); 34 | 35 | // Merge all icon names into a single list 36 | var allIcons = icons 37 | .SelectMany(i => i.Value.Select(i => (i.Name, i.ClassName))) 38 | .Distinct() 39 | .OrderBy(i => i) 40 | .ToList(); 41 | 42 | AddSupportingFiles(context); 43 | BuildSymbolEnum(context, allIcons, obsoleteIcons); 44 | BuildIconListClass(context, allIcons, icons); 45 | } 46 | 47 | private List? LoadObsoleteIconList(GeneratorExecutionContext context) 48 | => context 49 | .AdditionalFiles 50 | .Where(at => at.Path.EndsWith("obsolete_icons.txt", StringComparison.InvariantCultureIgnoreCase)) 51 | .Select(file => 52 | { 53 | var text = file.GetText(context.CancellationToken); 54 | 55 | if (text is null) 56 | { 57 | throw new Exception("Obsolete icon file could not be read."); 58 | } 59 | 60 | return text 61 | .Lines 62 | .Select(line => line.ToString()) 63 | .ToList(); 64 | }) 65 | .FirstOrDefault(); 66 | 67 | private IconMap LoadIcons(GeneratorExecutionContext context) 68 | => context 69 | .AdditionalFiles 70 | .Where(at => at.Path.EndsWith(".svg", StringComparison.InvariantCultureIgnoreCase)) 71 | .Select(file => 72 | { 73 | var options = context.AnalyzerConfigOptions.GetOptions(file); 74 | if (!options.TryGetValue("build_metadata.AdditionalFiles.IconStyle", out var iconStyle)) 75 | { 76 | throw new Exception($"IconStyle not specified for file {file.Path}"); 77 | } 78 | 79 | context.AnalyzerConfigOptions.GetOptions(file).TryGetValue("build_metadata.AdditionalFiles.UsesStroke", out var usesStrokeValue); 80 | bool.TryParse(usesStrokeValue, out var usesStroke); 81 | 82 | var directory = Path.GetDirectoryName(file.Path); 83 | var name = Path.GetFileNameWithoutExtension(file.Path); 84 | 85 | return new IconDetails 86 | { 87 | ClassName = name.ToPascalCase(), 88 | File = file, 89 | Name = name, 90 | Path = file.Path, 91 | Style = iconStyle, 92 | UsesStroke = usesStroke, 93 | }; 94 | }) 95 | .OrderBy(o => o.Style) 96 | .ThenBy(o => o.Name) 97 | .GroupBy(g => g.Style) 98 | .ToDictionary(k => k.Key, k => k.ToList()); 99 | 100 | private void AddSupportingFiles(GeneratorExecutionContext context) 101 | { 102 | const string iconClassSource = """ 103 | // 104 | namespace Tailwind.Heroicons; 105 | 106 | /// 107 | /// A parsed Heroicon. 108 | /// 109 | public class Icon 110 | { 111 | /// 112 | /// The filename without extension. 113 | /// 114 | public string Name { get; set; } 115 | 116 | /// 117 | /// The svg path element. 118 | /// 119 | public string Path { get; set; } 120 | 121 | /// 122 | /// The svg viewbox attribute value. 123 | /// 124 | public string ViewBox { get; set; } 125 | 126 | /// 127 | /// The svg stroke-width attribute value. 128 | /// 129 | public string StrokeWidth { get; set; } 130 | } 131 | """; 132 | 133 | const string iconExceptionSource = """ 134 | // 135 | namespace Tailwind.Heroicons; 136 | 137 | /// 138 | /// The exception that is thrown when an icon is not supported in the given set. 139 | /// 140 | public class UnsupportedIconException : Exception 141 | { 142 | /// 143 | /// Initializes a new instance of the class with a specified icon style and name. 144 | /// 145 | /// The icon style/set. 146 | /// The icon name. 147 | public UnsupportedIconException(string style, string name) 148 | : base($"Icon '{name}' doesn't have a {style} style.") 149 | { 150 | new ArrayTypeMismatchException(""); 151 | Style = style; 152 | Name = name; 153 | } 154 | 155 | /// 156 | /// The set that the icon is missing from. 157 | /// 158 | public string Style { get; set; } = null!; 159 | 160 | /// 161 | /// The name of the icon. 162 | /// 163 | public string Name { get; set; } = null!; 164 | } 165 | """; 166 | 167 | context.AddSource("Icon", SourceText.From(iconClassSource, Encoding.UTF8)); 168 | context.AddSource("UnsupportedIconException", SourceText.From(iconExceptionSource, Encoding.UTF8)); 169 | } 170 | 171 | private void BuildSymbolEnum( 172 | GeneratorExecutionContext context, 173 | AllIcons allIcons, 174 | List? obsoleteIcons) 175 | { 176 | var source = new StringBuilder( 177 | """ 178 | // 179 | namespace Tailwind.Heroicons; 180 | 181 | /// 182 | /// The available icons. 183 | /// 184 | public enum IconSymbol 185 | { 186 | 187 | """); 188 | 189 | foreach (var (name, className) in allIcons) 190 | { 191 | source.AppendLine(" /// "); 192 | source.AppendLine(" /// Heroicon name: ", name); 193 | source.AppendLine(" /// "); 194 | 195 | if (obsoleteIcons?.Contains(name) is true) 196 | { 197 | source.AppendLine(" [Obsolete(\"Icon '", name, "' is now an alias and will be removed in a future version. See the Heroicons release notes for more information.\")]"); 198 | } 199 | 200 | source.AppendLine(" ", className, ","); 201 | source.AppendLine(); 202 | } 203 | 204 | source.AppendLine("}"); 205 | 206 | context.AddSource("IconSymbol", SourceText.From(source.ToString(), Encoding.UTF8)); 207 | } 208 | 209 | private void BuildIconListClass( 210 | GeneratorExecutionContext context, 211 | AllIcons allIcons, 212 | IconMap icons) 213 | { 214 | var source = new StringBuilder( 215 | """ 216 | #pragma warning disable CS0618 217 | 218 | // 219 | namespace Tailwind.Heroicons; 220 | 221 | using System; 222 | 223 | /// 224 | /// Helper used to get parsed icon details. 225 | /// 226 | public static class IconList 227 | { 228 | 229 | """); 230 | 231 | foreach (var style in icons) 232 | { 233 | source.AppendLine(" /// "); 234 | source.AppendLine(" /// Get the details of an icon in the ", style.Key.FirstCharToUpper(), " variation."); 235 | source.AppendLine(" /// "); 236 | source.AppendLine(" /// The to get the details of."); 237 | source.AppendLine(" /// The icon details."); 238 | source.AppendLine(" public static Icon ", style.Key.FirstCharToUpper(), "(IconSymbol symbol)"); 239 | source.AppendLine( 240 | """ 241 | { 242 | switch (symbol) 243 | { 244 | """); 245 | 246 | foreach (var (name, className) in allIcons) 247 | { 248 | var icon = style.Value.Find(i => i.Name == name); 249 | 250 | source.AppendLine(" case IconSymbol.", className, ":"); 251 | 252 | if (icon is null) 253 | { 254 | source.AppendLine(" throw new UnsupportedIconException(\"", style.Key, "\", \"", name, "\");"); 255 | } 256 | else 257 | { 258 | var file = icon.File.GetText(context.CancellationToken)!.ToString(); 259 | var path = IconExtractor.GetPaths(file); 260 | var viewBox = IconExtractor.GetViewBox(file); 261 | 262 | source.AppendLine(" return new Icon"); 263 | source.AppendLine(" {"); 264 | source.AppendLine(" Name = \"", name, "\","); 265 | source.AppendLine(" Path = \"\"\"", path, "\"\"\","); 266 | source.AppendLine(" ViewBox = \"", viewBox, "\","); 267 | 268 | if (icon.UsesStroke) 269 | { 270 | var strokeWidth = IconExtractor.GetStrokeWidth(file); 271 | 272 | source.AppendLine(" StrokeWidth = \"", strokeWidth, "\","); 273 | } 274 | 275 | source.AppendLine(" };"); 276 | } 277 | 278 | source.AppendLine(); 279 | } 280 | 281 | source.AppendLine( 282 | """ 283 | default: 284 | throw new ArgumentOutOfRangeException(nameof(symbol), symbol, "Unsupported icon name"); 285 | } 286 | } 287 | """); 288 | } 289 | 290 | source.AppendLine("}"); 291 | 292 | context.AddSource("IconList", SourceText.From(source.ToString(), Encoding.UTF8)); 293 | } 294 | 295 | #pragma warning disable RCS1016 // Use block body or expression body. 296 | public void Initialize(GeneratorInitializationContext context) 297 | { 298 | // System.Diagnostics.Debugger.Launch(); 299 | } 300 | #pragma warning restore RCS1016 // Use block body or expression body. 301 | } 302 | -------------------------------------------------------------------------------- /analysis/code-quality.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | 3 | # CA1000: Do not declare static members on generic types 4 | dotnet_diagnostic.CA1000.severity = warning 5 | 6 | # CA1001: Types that own disposable fields should be disposable 7 | dotnet_diagnostic.CA1001.severity = warning 8 | 9 | # CA1002: Do not expose generic lists 10 | dotnet_diagnostic.CA1002.severity = warning 11 | 12 | # CA1003: Use generic event handler instances 13 | dotnet_diagnostic.CA1003.severity = warning 14 | 15 | # CA1008: Enums should have zero value 16 | dotnet_diagnostic.CA1008.severity = warning 17 | 18 | # CA1010: Generic interface should also be implemented 19 | dotnet_diagnostic.CA1010.severity = warning 20 | 21 | # CA1012: Abstract types should not have public constructors 22 | dotnet_diagnostic.CA1012.severity = warning 23 | 24 | # CA1014: Mark assemblies with CLSCompliant 25 | dotnet_diagnostic.CA1014.severity = none 26 | 27 | # CA1016: Mark assemblies with assembly version 28 | dotnet_diagnostic.CA1016.severity = warning 29 | 30 | # CA1018: Mark attributes with AttributeUsageAttribute 31 | dotnet_diagnostic.CA1018.severity = warning 32 | 33 | # CA1019: Define accessors for attribute arguments 34 | dotnet_diagnostic.CA1019.severity = warning 35 | 36 | # CA1024: Use properties where appropriate 37 | dotnet_diagnostic.CA1024.severity = warning 38 | 39 | # CA1027: Mark enums with FlagsAttribute 40 | dotnet_diagnostic.CA1027.severity = warning 41 | 42 | # CA1028: Enum Storage should be Int32 43 | dotnet_diagnostic.CA1028.severity = warning 44 | 45 | # CA1030: Use events where appropriate 46 | dotnet_diagnostic.CA1030.severity = warning 47 | 48 | # CA1031: Do not catch general exception types 49 | dotnet_diagnostic.CA1031.severity = warning 50 | 51 | # CA1032: Implement standard exception constructors 52 | dotnet_diagnostic.CA1032.severity = warning 53 | 54 | # CA1033: Interface methods should be callable by child types 55 | dotnet_diagnostic.CA1033.severity = warning 56 | 57 | # CA1034: Nested types should not be visible 58 | dotnet_diagnostic.CA1034.severity = none 59 | 60 | # CA1036: Override methods on comparable types 61 | dotnet_diagnostic.CA1036.severity = warning 62 | 63 | # CA1040: Avoid empty interfaces 64 | dotnet_diagnostic.CA1040.severity = warning 65 | 66 | # CA1041: Provide ObsoleteAttribute message 67 | dotnet_diagnostic.CA1041.severity = warning 68 | 69 | # CA1043: Use Integral Or String Argument For Indexers 70 | dotnet_diagnostic.CA1043.severity = warning 71 | 72 | # CA1044: Properties should not be write only 73 | dotnet_diagnostic.CA1044.severity = warning 74 | 75 | # CA1046: Do not overload equality operator on reference types 76 | dotnet_diagnostic.CA1046.severity = warning 77 | 78 | # CA1047: Do not declare protected member in sealed type 79 | dotnet_diagnostic.CA1047.severity = warning 80 | 81 | # CA1050: Declare types in namespaces 82 | dotnet_diagnostic.CA1050.severity = warning 83 | 84 | # CA1051: Do not declare visible instance fields 85 | dotnet_diagnostic.CA1051.severity = warning 86 | 87 | # CA1052: Static holder types should be Static or NotInheritable 88 | dotnet_diagnostic.CA1052.severity = warning 89 | 90 | # CA1054: URI-like parameters should not be strings 91 | dotnet_diagnostic.CA1054.severity = warning 92 | 93 | # CA1055: URI-like return values should not be strings 94 | dotnet_diagnostic.CA1055.severity = none 95 | 96 | # CA1056: URI-like properties should not be strings 97 | dotnet_diagnostic.CA1056.severity = none 98 | 99 | # CA1058: Types should not extend certain base types 100 | dotnet_diagnostic.CA1058.severity = warning 101 | 102 | # CA1061: Do not hide base class methods 103 | dotnet_diagnostic.CA1061.severity = warning 104 | 105 | # CA1062: Validate arguments of public methods 106 | dotnet_diagnostic.CA1062.severity = warning 107 | 108 | # CA1063: Implement IDisposable Correctly 109 | dotnet_diagnostic.CA1063.severity = warning 110 | 111 | # CA1064: Exceptions should be public 112 | dotnet_diagnostic.CA1064.severity = warning 113 | 114 | # CA1065: Do not raise exceptions in unexpected locations 115 | dotnet_diagnostic.CA1065.severity = warning 116 | 117 | # CA1066: Implement IEquatable when overriding Object.Equals 118 | dotnet_diagnostic.CA1066.severity = warning 119 | 120 | # CA1067: Override Object.Equals(object) when implementing IEquatable 121 | dotnet_diagnostic.CA1067.severity = warning 122 | 123 | # CA1068: CancellationToken parameters must come last 124 | dotnet_diagnostic.CA1068.severity = warning 125 | 126 | # CA1069: Enums values should not be duplicated 127 | dotnet_diagnostic.CA1069.severity = warning 128 | 129 | # CA1070: Do not declare event fields as virtual 130 | dotnet_diagnostic.CA1070.severity = warning 131 | 132 | # CA1200: Avoid using cref tags with a prefix 133 | dotnet_diagnostic.CA1200.severity = warning 134 | 135 | # CA1303: Do not pass literals as localized parameters 136 | dotnet_diagnostic.CA1303.severity = none 137 | 138 | # CA1304: Specify CultureInfo 139 | dotnet_diagnostic.CA1304.severity = warning 140 | 141 | # CA1305: Specify IFormatProvider 142 | dotnet_diagnostic.CA1305.severity = warning 143 | 144 | # CA1307: Specify StringComparison for clarity 145 | dotnet_diagnostic.CA1307.severity = warning 146 | 147 | # CA1308: Normalize strings to uppercase 148 | dotnet_diagnostic.CA1308.severity = none 149 | 150 | # CA1309: Use ordinal string comparison 151 | dotnet_diagnostic.CA1309.severity = warning 152 | 153 | # CA1310: Specify StringComparison for correctness 154 | dotnet_diagnostic.CA1310.severity = warning 155 | 156 | # CA1401: P/Invokes should not be visible 157 | dotnet_diagnostic.CA1401.severity = warning 158 | 159 | # CA1507: Use nameof to express symbol names 160 | dotnet_diagnostic.CA1507.severity = warning 161 | 162 | # CA1508: Avoid dead conditional code 163 | dotnet_diagnostic.CA1508.severity = warning 164 | 165 | # CA1700: Do not name enum values 'Reserved' 166 | dotnet_diagnostic.CA1700.severity = warning 167 | 168 | # CA1707: Identifiers should not contain underscores 169 | dotnet_diagnostic.CA1707.severity = warning 170 | 171 | # CA1708: Identifiers should differ by more than case 172 | dotnet_diagnostic.CA1708.severity = warning 173 | 174 | # CA1710: Identifiers should have correct suffix 175 | dotnet_diagnostic.CA1710.severity = warning 176 | 177 | # CA1711: Identifiers should not have incorrect suffix 178 | dotnet_diagnostic.CA1711.severity = warning 179 | 180 | # CA1712: Do not prefix enum values with type name 181 | dotnet_diagnostic.CA1712.severity = warning 182 | 183 | # CA1713: Events should not have 'Before' or 'After' prefix 184 | dotnet_diagnostic.CA1713.severity = warning 185 | 186 | # CA1715: Identifiers should have correct prefix 187 | dotnet_diagnostic.CA1715.severity = warning 188 | 189 | # CA1716: Identifiers should not match keywords 190 | dotnet_diagnostic.CA1716.severity = warning 191 | 192 | # CA1720: Identifier contains type name 193 | dotnet_diagnostic.CA1720.severity = warning 194 | 195 | # CA1721: Property names should not match get methods 196 | dotnet_diagnostic.CA1721.severity = warning 197 | 198 | # CA1724: Type names should not match namespaces 199 | dotnet_diagnostic.CA1724.severity = warning 200 | 201 | # CA1725: Parameter names should match base declaration 202 | dotnet_diagnostic.CA1725.severity = warning 203 | 204 | # CA1801: Review unused parameters 205 | dotnet_diagnostic.CA1801.severity = warning 206 | 207 | # CA1802: Use literals where appropriate 208 | dotnet_diagnostic.CA1802.severity = warning 209 | 210 | # CA1805: Do not initialize unnecessarily 211 | dotnet_diagnostic.CA1805.severity = warning 212 | 213 | # CA1806: Do not ignore method results 214 | dotnet_diagnostic.CA1806.severity = warning 215 | 216 | # CA1810: Initialize reference type static fields inline 217 | dotnet_diagnostic.CA1810.severity = warning 218 | 219 | # CA1812: Avoid uninstantiated internal classes 220 | dotnet_diagnostic.CA1812.severity = warning 221 | 222 | # CA1813: Avoid unsealed attributes 223 | dotnet_diagnostic.CA1813.severity = warning 224 | 225 | # CA1814: Prefer jagged arrays over multidimensional 226 | dotnet_diagnostic.CA1814.severity = warning 227 | 228 | # CA1815: Override equals and operator equals on value types 229 | dotnet_diagnostic.CA1815.severity = warning 230 | 231 | # CA1816: Dispose methods should call SuppressFinalize 232 | dotnet_diagnostic.CA1816.severity = warning 233 | 234 | # CA1819: Properties should not return arrays 235 | dotnet_diagnostic.CA1819.severity = none 236 | 237 | # CA1820: Test for empty strings using string length 238 | dotnet_diagnostic.CA1820.severity = warning 239 | 240 | # CA1821: Remove empty Finalizers 241 | dotnet_diagnostic.CA1821.severity = warning 242 | 243 | # CA1822: Mark members as static 244 | dotnet_diagnostic.CA1822.severity = suggestion 245 | 246 | # CA1823: Avoid unused private fields 247 | dotnet_diagnostic.CA1823.severity = warning 248 | 249 | # CA1824: Mark assemblies with NeutralResourcesLanguageAttribute 250 | dotnet_diagnostic.CA1824.severity = warning 251 | 252 | # CA1825: Avoid zero-length array allocations 253 | dotnet_diagnostic.CA1825.severity = warning 254 | 255 | # CA1826: Do not use Enumerable methods on indexable collections 256 | dotnet_diagnostic.CA1826.severity = warning 257 | 258 | # CA1827: Do not use Count() or LongCount() when Any() can be used 259 | dotnet_diagnostic.CA1827.severity = warning 260 | 261 | # CA1828: Do not use CountAsync() or LongCountAsync() when AnyAsync() can be used 262 | dotnet_diagnostic.CA1828.severity = warning 263 | 264 | # CA1829: Use Length/Count property instead of Count() when available 265 | dotnet_diagnostic.CA1829.severity = warning 266 | 267 | # CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder 268 | dotnet_diagnostic.CA1830.severity = warning 269 | 270 | # CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate 271 | dotnet_diagnostic.CA1832.severity = warning 272 | 273 | # CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate 274 | dotnet_diagnostic.CA1833.severity = warning 275 | 276 | # CA1834: Consider using 'StringBuilder.Append(char)' when applicable 277 | dotnet_diagnostic.CA1834.severity = warning 278 | 279 | # CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync' 280 | dotnet_diagnostic.CA1835.severity = warning 281 | 282 | # CA1836: Prefer IsEmpty over Count 283 | dotnet_diagnostic.CA1836.severity = warning 284 | 285 | # CA1837: Use 'Environment.ProcessId' 286 | dotnet_diagnostic.CA1837.severity = warning 287 | 288 | # CA1838: Avoid 'StringBuilder' parameters for P/Invokes 289 | dotnet_diagnostic.CA1838.severity = warning 290 | 291 | # CA2000: Dispose objects before losing scope 292 | dotnet_diagnostic.CA2000.severity = warning 293 | 294 | # CA2002: Do not lock on objects with weak identity 295 | dotnet_diagnostic.CA2002.severity = warning 296 | 297 | # CA2007: Consider calling ConfigureAwait on the awaited task 298 | dotnet_diagnostic.CA2007.severity = none 299 | 300 | # CA2008: Do not create tasks without passing a TaskScheduler 301 | dotnet_diagnostic.CA2008.severity = warning 302 | 303 | # CA2009: Do not call ToImmutableCollection on an ImmutableCollection value 304 | dotnet_diagnostic.CA2009.severity = warning 305 | 306 | # CA2011: Avoid infinite recursion 307 | dotnet_diagnostic.CA2011.severity = warning 308 | 309 | # CA2012: Use ValueTasks correctly 310 | dotnet_diagnostic.CA2012.severity = warning 311 | 312 | # CA2016: Forward the 'CancellationToken' parameter to methods that take one 313 | dotnet_diagnostic.CA2016.severity = error 314 | 315 | # CA2100: Review SQL queries for security vulnerabilities 316 | dotnet_diagnostic.CA2100.severity = warning 317 | 318 | # CA2101: Specify marshaling for P/Invoke string arguments 319 | dotnet_diagnostic.CA2101.severity = warning 320 | 321 | # CA2109: Review visible event handlers 322 | dotnet_diagnostic.CA2109.severity = warning 323 | 324 | # CA2119: Seal methods that satisfy private interfaces 325 | dotnet_diagnostic.CA2119.severity = warning 326 | 327 | # CA2153: Do Not Catch Corrupted State Exceptions 328 | dotnet_diagnostic.CA2153.severity = warning 329 | 330 | # CA2201: Do not raise reserved exception types 331 | dotnet_diagnostic.CA2201.severity = warning 332 | 333 | # CA2207: Initialize value type static fields inline 334 | dotnet_diagnostic.CA2207.severity = warning 335 | 336 | # CA2208: Instantiate argument exceptions correctly 337 | dotnet_diagnostic.CA2208.severity = warning 338 | 339 | # CA2211: Non-constant fields should not be visible 340 | dotnet_diagnostic.CA2211.severity = warning 341 | 342 | # CA2213: Disposable fields should be disposed 343 | dotnet_diagnostic.CA2213.severity = warning 344 | 345 | # CA2214: Do not call overridable methods in constructors 346 | dotnet_diagnostic.CA2214.severity = warning 347 | 348 | # CA2215: Dispose methods should call base class dispose 349 | dotnet_diagnostic.CA2215.severity = warning 350 | 351 | # CA2216: Disposable types should declare finalizer 352 | dotnet_diagnostic.CA2216.severity = warning 353 | 354 | # CA2217: Do not mark enums with FlagsAttribute 355 | dotnet_diagnostic.CA2217.severity = warning 356 | 357 | # CA2218: Override GetHashCode on overriding Equals 358 | dotnet_diagnostic.CA2218.severity = warning 359 | 360 | # CA2219: Do not raise exceptions in finally clauses 361 | dotnet_diagnostic.CA2219.severity = warning 362 | 363 | # CA2224: Override Equals on overloading operator equals 364 | dotnet_diagnostic.CA2224.severity = warning 365 | 366 | # CA2225: Operator overloads have named alternates 367 | dotnet_diagnostic.CA2225.severity = warning 368 | 369 | # CA2226: Operators should have symmetrical overloads 370 | dotnet_diagnostic.CA2226.severity = warning 371 | 372 | # CA2227: Collection properties should be read only 373 | dotnet_diagnostic.CA2227.severity = warning 374 | 375 | # CA2229: Implement serialization constructors 376 | dotnet_diagnostic.CA2229.severity = warning 377 | 378 | # CA2231: Overload operator equals on overriding value type Equals 379 | dotnet_diagnostic.CA2231.severity = warning 380 | 381 | # CA2234: Pass system uri objects instead of strings 382 | dotnet_diagnostic.CA2234.severity = warning 383 | 384 | # CA2235: Mark all non-serializable fields 385 | dotnet_diagnostic.CA2235.severity = warning 386 | 387 | # CA2237: Mark ISerializable types with serializable 388 | dotnet_diagnostic.CA2237.severity = warning 389 | 390 | # CA2241: Provide correct arguments to formatting methods 391 | dotnet_diagnostic.CA2241.severity = warning 392 | 393 | # CA2242: Test for NaN correctly 394 | dotnet_diagnostic.CA2242.severity = warning 395 | 396 | # CA2243: Attribute string literals should parse correctly 397 | dotnet_diagnostic.CA2243.severity = warning 398 | 399 | # CA2244: Do not duplicate indexed element initializations 400 | dotnet_diagnostic.CA2244.severity = warning 401 | 402 | # CA2245: Do not assign a property to itself 403 | dotnet_diagnostic.CA2245.severity = warning 404 | 405 | # CA2246: Assigning symbol and its member in the same statement 406 | dotnet_diagnostic.CA2246.severity = warning 407 | 408 | # CA2248: Provide correct 'enum' argument to 'Enum.HasFlag' 409 | dotnet_diagnostic.CA2248.severity = warning 410 | 411 | # CA2249: Consider using 'string.Contains' instead of 'string.IndexOf' 412 | dotnet_diagnostic.CA2249.severity = warning 413 | 414 | # CA2300: Do not use insecure deserializer BinaryFormatter 415 | dotnet_diagnostic.CA2300.severity = warning 416 | 417 | # CA2301: Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder 418 | dotnet_diagnostic.CA2301.severity = warning 419 | 420 | # CA2302: Ensure BinaryFormatter.Binder is set before calling BinaryFormatter.Deserialize 421 | dotnet_diagnostic.CA2302.severity = warning 422 | 423 | # CA2305: Do not use insecure deserializer LosFormatter 424 | dotnet_diagnostic.CA2305.severity = warning 425 | 426 | # CA2310: Do not use insecure deserializer NetDataContractSerializer 427 | dotnet_diagnostic.CA2310.severity = warning 428 | 429 | # CA2311: Do not deserialize without first setting NetDataContractSerializer.Binder 430 | dotnet_diagnostic.CA2311.severity = warning 431 | 432 | # CA2312: Ensure NetDataContractSerializer.Binder is set before deserializing 433 | dotnet_diagnostic.CA2312.severity = warning 434 | 435 | # CA2315: Do not use insecure deserializer ObjectStateFormatter 436 | dotnet_diagnostic.CA2315.severity = warning 437 | 438 | # CA2321: Do not deserialize with JavaScriptSerializer using a SimpleTypeResolver 439 | dotnet_diagnostic.CA2321.severity = warning 440 | 441 | # CA2322: Ensure JavaScriptSerializer is not initialized with SimpleTypeResolver before deserializing 442 | dotnet_diagnostic.CA2322.severity = warning 443 | 444 | # CA2326: Do not use TypeNameHandling values other than None 445 | dotnet_diagnostic.CA2326.severity = warning 446 | 447 | # CA2327: Do not use insecure JsonSerializerSettings 448 | dotnet_diagnostic.CA2327.severity = warning 449 | 450 | # CA2328: Ensure that JsonSerializerSettings are secure 451 | dotnet_diagnostic.CA2328.severity = warning 452 | 453 | # CA2329: Do not deserialize with JsonSerializer using an insecure configuration 454 | dotnet_diagnostic.CA2329.severity = warning 455 | 456 | # CA2330: Ensure that JsonSerializer has a secure configuration when deserializing 457 | dotnet_diagnostic.CA2330.severity = warning 458 | 459 | # CA2350: Do not use DataTable.ReadXml() with untrusted data 460 | dotnet_diagnostic.CA2350.severity = warning 461 | 462 | # CA2351: Do not use DataSet.ReadXml() with untrusted data 463 | dotnet_diagnostic.CA2351.severity = warning 464 | 465 | # CA2352: Unsafe DataSet or DataTable in serializable type can be vulnerable to remote code execution attacks 466 | dotnet_diagnostic.CA2352.severity = warning 467 | 468 | # CA2353: Unsafe DataSet or DataTable in serializable type 469 | dotnet_diagnostic.CA2353.severity = warning 470 | 471 | # CA2354: Unsafe DataSet or DataTable in deserialized object graph can be vulnerable to remote code execution attacks 472 | dotnet_diagnostic.CA2354.severity = warning 473 | 474 | # CA2355: Unsafe DataSet or DataTable type found in deserializable object graph 475 | dotnet_diagnostic.CA2355.severity = warning 476 | 477 | # CA2356: Unsafe DataSet or DataTable type in web deserializable object graph 478 | dotnet_diagnostic.CA2356.severity = warning 479 | 480 | # CA2361: Ensure autogenerated class containing DataSet.ReadXml() is not used with untrusted data 481 | dotnet_diagnostic.CA2361.severity = warning 482 | 483 | # CA2362: Unsafe DataSet or DataTable in autogenerated serializable type can be vulnerable to remote code execution attacks 484 | dotnet_diagnostic.CA2362.severity = warning 485 | 486 | # CA3001: Review code for SQL injection vulnerabilities 487 | dotnet_diagnostic.CA3001.severity = warning 488 | 489 | # CA3002: Review code for XSS vulnerabilities 490 | dotnet_diagnostic.CA3002.severity = warning 491 | 492 | # CA3003: Review code for file path injection vulnerabilities 493 | dotnet_diagnostic.CA3003.severity = warning 494 | 495 | # CA3004: Review code for information disclosure vulnerabilities 496 | dotnet_diagnostic.CA3004.severity = warning 497 | 498 | # CA3005: Review code for LDAP injection vulnerabilities 499 | dotnet_diagnostic.CA3005.severity = warning 500 | 501 | # CA3006: Review code for process command injection vulnerabilities 502 | dotnet_diagnostic.CA3006.severity = warning 503 | 504 | # CA3007: Review code for open redirect vulnerabilities 505 | dotnet_diagnostic.CA3007.severity = warning 506 | 507 | # CA3008: Review code for XPath injection vulnerabilities 508 | dotnet_diagnostic.CA3008.severity = warning 509 | 510 | # CA3009: Review code for XML injection vulnerabilities 511 | dotnet_diagnostic.CA3009.severity = warning 512 | 513 | # CA3010: Review code for XAML injection vulnerabilities 514 | dotnet_diagnostic.CA3010.severity = warning 515 | 516 | # CA3011: Review code for DLL injection vulnerabilities 517 | dotnet_diagnostic.CA3011.severity = warning 518 | 519 | # CA3012: Review code for regex injection vulnerabilities 520 | dotnet_diagnostic.CA3012.severity = warning 521 | 522 | # CA3061: Do Not Add Schema By URL 523 | dotnet_diagnostic.CA3061.severity = warning 524 | 525 | # CA3075: Insecure DTD processing in XML 526 | dotnet_diagnostic.CA3075.severity = warning 527 | 528 | # CA3076: Insecure XSLT script processing. 529 | dotnet_diagnostic.CA3076.severity = warning 530 | 531 | # CA3077: Insecure Processing in API Design, XmlDocument and XmlTextReader 532 | dotnet_diagnostic.CA3077.severity = warning 533 | 534 | # CA3147: Mark Verb Handlers With Validate Antiforgery Token 535 | dotnet_diagnostic.CA3147.severity = warning 536 | 537 | # CA5350: Do Not Use Weak Cryptographic Algorithms 538 | dotnet_diagnostic.CA5350.severity = warning 539 | 540 | # CA5351: Do Not Use Broken Cryptographic Algorithms 541 | dotnet_diagnostic.CA5351.severity = warning 542 | 543 | # CA5358: Review cipher mode usage with cryptography experts 544 | dotnet_diagnostic.CA5358.severity = warning 545 | 546 | # CA5359: Do Not Disable Certificate Validation 547 | dotnet_diagnostic.CA5359.severity = warning 548 | 549 | # CA5360: Do Not Call Dangerous Methods In Deserialization 550 | dotnet_diagnostic.CA5360.severity = warning 551 | 552 | # CA5361: Do Not Disable SChannel Use of Strong Crypto 553 | dotnet_diagnostic.CA5361.severity = warning 554 | 555 | # CA5362: Potential reference cycle in deserialized object graph 556 | dotnet_diagnostic.CA5362.severity = warning 557 | 558 | # CA5363: Do Not Disable Request Validation 559 | dotnet_diagnostic.CA5363.severity = warning 560 | 561 | # CA5364: Do Not Use Deprecated Security Protocols 562 | dotnet_diagnostic.CA5364.severity = warning 563 | 564 | # CA5365: Do Not Disable HTTP Header Checking 565 | dotnet_diagnostic.CA5365.severity = warning 566 | 567 | # CA5366: Use XmlReader For DataSet Read Xml 568 | dotnet_diagnostic.CA5366.severity = warning 569 | 570 | # CA5367: Do Not Serialize Types With Pointer Fields 571 | dotnet_diagnostic.CA5367.severity = warning 572 | 573 | # CA5368: Set ViewStateUserKey For Classes Derived From Page 574 | dotnet_diagnostic.CA5368.severity = warning 575 | 576 | # CA5369: Use XmlReader For Deserialize 577 | dotnet_diagnostic.CA5369.severity = warning 578 | 579 | # CA5370: Use XmlReader For Validating Reader 580 | dotnet_diagnostic.CA5370.severity = warning 581 | 582 | # CA5371: Use XmlReader For Schema Read 583 | dotnet_diagnostic.CA5371.severity = warning 584 | 585 | # CA5372: Use XmlReader For XPathDocument 586 | dotnet_diagnostic.CA5372.severity = warning 587 | 588 | # CA5373: Do not use obsolete key derivation function 589 | dotnet_diagnostic.CA5373.severity = warning 590 | 591 | # CA5374: Do Not Use XslTransform 592 | dotnet_diagnostic.CA5374.severity = warning 593 | 594 | # CA5375: Do Not Use Account Shared Access Signature 595 | dotnet_diagnostic.CA5375.severity = warning 596 | 597 | # CA5376: Use SharedAccessProtocol HttpsOnly 598 | dotnet_diagnostic.CA5376.severity = warning 599 | 600 | # CA5377: Use Container Level Access Policy 601 | dotnet_diagnostic.CA5377.severity = warning 602 | 603 | # CA5378: Do not disable ServicePointManagerSecurityProtocols 604 | dotnet_diagnostic.CA5378.severity = warning 605 | 606 | # CA5379: Do Not Use Weak Key Derivation Function Algorithm 607 | dotnet_diagnostic.CA5379.severity = warning 608 | 609 | # CA5380: Do Not Add Certificates To Root Store 610 | dotnet_diagnostic.CA5380.severity = warning 611 | 612 | # CA5381: Ensure Certificates Are Not Added To Root Store 613 | dotnet_diagnostic.CA5381.severity = warning 614 | 615 | # CA5382: Use Secure Cookies In ASP.Net Core 616 | dotnet_diagnostic.CA5382.severity = warning 617 | 618 | # CA5383: Ensure Use Secure Cookies In ASP.Net Core 619 | dotnet_diagnostic.CA5383.severity = warning 620 | 621 | # CA5384: Do Not Use Digital Signature Algorithm (DSA) 622 | dotnet_diagnostic.CA5384.severity = warning 623 | 624 | # CA5385: Use Rivest–Shamir–Adleman (RSA) Algorithm With Sufficient Key Size 625 | dotnet_diagnostic.CA5385.severity = warning 626 | 627 | # CA5386: Avoid hardcoding SecurityProtocolType value 628 | dotnet_diagnostic.CA5386.severity = warning 629 | 630 | # CA5387: Do Not Use Weak Key Derivation Function With Insufficient Iteration Count 631 | dotnet_diagnostic.CA5387.severity = warning 632 | 633 | # CA5388: Ensure Sufficient Iteration Count When Using Weak Key Derivation Function 634 | dotnet_diagnostic.CA5388.severity = warning 635 | 636 | # CA5389: Do Not Add Archive Item's Path To The Target File System Path 637 | dotnet_diagnostic.CA5389.severity = warning 638 | 639 | # CA5390: Do not hard-code encryption key 640 | dotnet_diagnostic.CA5390.severity = warning 641 | 642 | # CA5391: Use antiforgery tokens in ASP.NET Core MVC controllers 643 | dotnet_diagnostic.CA5391.severity = warning 644 | 645 | # CA5392: Use DefaultDllImportSearchPaths attribute for P/Invokes 646 | dotnet_diagnostic.CA5392.severity = warning 647 | 648 | # CA5393: Do not use unsafe DllImportSearchPath value 649 | dotnet_diagnostic.CA5393.severity = warning 650 | 651 | # CA5394: Do not use insecure randomness 652 | dotnet_diagnostic.CA5394.severity = warning 653 | 654 | # CA5395: Miss HttpVerb attribute for action methods 655 | dotnet_diagnostic.CA5395.severity = warning 656 | 657 | # CA5396: Set HttpOnly to true for HttpCookie 658 | dotnet_diagnostic.CA5396.severity = warning 659 | 660 | # CA5397: Do not use deprecated SslProtocols values 661 | dotnet_diagnostic.CA5397.severity = warning 662 | 663 | # CA5398: Avoid hardcoded SslProtocols values 664 | dotnet_diagnostic.CA5398.severity = warning 665 | 666 | # CA5399: HttpClients should enable certificate revocation list checks 667 | dotnet_diagnostic.CA5399.severity = warning 668 | 669 | # CA5400: Ensure HttpClient certificate revocation list check is not disabled 670 | dotnet_diagnostic.CA5400.severity = warning 671 | 672 | # CA5401: Do not use CreateEncryptor with non-default IV 673 | dotnet_diagnostic.CA5401.severity = warning 674 | 675 | # CA5402: Use CreateEncryptor with the default IV 676 | dotnet_diagnostic.CA5402.severity = warning 677 | 678 | # CA5403: Do not hard-code certificate 679 | dotnet_diagnostic.CA5403.severity = warning 680 | -------------------------------------------------------------------------------- /sample/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | Outline/Solid 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 | Outline/Solid 48 |

49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
87 |
88 |
89 |

90 | Outline with stroke-width attribute (doesn't do anything as of v2.1) 91 |

92 |
93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 |
111 |
112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
130 |
131 |
132 |

133 | Outline with stroke class 134 |

135 |
136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 |
154 |
155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 |
173 |
174 |
175 |

176 | Solid/Mini 177 |

178 |
179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 |
197 |
198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 |
216 |
217 |
218 |

219 | Solid/Mini 220 |

221 |
222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 |
240 |
241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 |
259 |
260 |
261 |

262 | Mini/Micro 263 |

264 |
265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 |
283 |
284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 |
302 |
303 |
304 |

305 | Mini/Micro 306 |

307 |
308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 |
326 |
327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 |
345 |
346 |
347 | -------------------------------------------------------------------------------- /analysis/roslynator.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | 3 | # 4 | # Options 5 | 6 | roslynator_accessibility_modifiers = explicit 7 | roslynator_accessor_braces_style = single_line_when_expression_is_on_single_line 8 | roslynator_array_creation_type_style = implicit 9 | roslynator_arrow_token_new_line = before 10 | roslynator_binary_operator_new_line = after 11 | roslynator_blank_line_between_closing_brace_and_switch_section = false 12 | roslynator_blank_line_between_single_line_accessors = false 13 | roslynator_blank_line_between_using_directives = separate_groups 14 | roslynator_block_braces_style = multi_line 15 | roslynator_body_style = expression 16 | roslynator_conditional_operator_condition_parentheses_style = omit 17 | roslynator_conditional_operator_new_line = before 18 | roslynator_configure_await = false 19 | roslynator_doc_comment_summary_style = multi_line 20 | roslynator_empty_string_style = literal 21 | roslynator_enum_flag_value_style = decimal_number 22 | roslynator_enum_has_flag_style = method 23 | roslynator_new_line_before_while_in_do_statement = true 24 | roslynator_infinite_loop_style = while 25 | roslynator_null_check_style = pattern_matching 26 | roslynator_object_creation_parentheses_style = omit 27 | roslynator_suppress_unity_script_methods = false 28 | roslynator_use_var_instead_of_implicit_object_creation = true 29 | 30 | # 31 | # Rules 32 | 33 | # RCS0001: Add blank line after embedded statement 34 | dotnet_diagnostic.RCS0001.severity = error 35 | 36 | # RCS0002: Add blank line after #region 37 | dotnet_diagnostic.RCS0002.severity = error 38 | 39 | # RCS0003: Add blank line after using directive list 40 | dotnet_diagnostic.RCS0003.severity = error 41 | 42 | # RCS0005: Add blank line before #endregion 43 | dotnet_diagnostic.RCS0005.severity = error 44 | 45 | # RCS0006: Add blank line before using directive list 46 | dotnet_diagnostic.RCS0006.severity = none 47 | 48 | # RCS0007: Add blank line between accessors 49 | dotnet_diagnostic.RCS0007.severity = none 50 | 51 | # RCS0008: Add blank line between closing brace and next statement 52 | dotnet_diagnostic.RCS0008.severity = error 53 | 54 | # RCS0009: Add blank line between declaration and documentation comment 55 | dotnet_diagnostic.RCS0009.severity = error 56 | 57 | # RCS0010: Add blank line between declarations 58 | dotnet_diagnostic.RCS0010.severity = error 59 | 60 | # RCS0011: Add/remove blank line between single-line accessors 61 | dotnet_diagnostic.RCS0011.severity = error 62 | 63 | # RCS0012: Add blank line between single-line declarations 64 | dotnet_diagnostic.RCS0012.severity = none 65 | 66 | # RCS0013: Add blank line between single-line declarations of different kind 67 | dotnet_diagnostic.RCS0013.severity = error 68 | 69 | # RCS0014: Add blank line between switch sections 70 | dotnet_diagnostic.RCS0014.severity = error 71 | 72 | # RCS0015: Add/remove blank line between using directives 73 | dotnet_diagnostic.RCS0015.severity = error 74 | 75 | # RCS0016: Put attribute list on its own line 76 | dotnet_diagnostic.RCS0016.severity = error 77 | 78 | # RCS0020: Format accessor's braces on a single line or multiple lines 79 | dotnet_diagnostic.RCS0020.severity = error 80 | 81 | # RCS0021: Format block's braces on a single line or multiple lines 82 | dotnet_diagnostic.RCS0021.severity = error 83 | 84 | # RCS0022: Add new line after opening brace of empty block 85 | dotnet_diagnostic.RCS0022.severity = error 86 | 87 | # RCS0023: Format type declaration's braces 88 | dotnet_diagnostic.RCS0023.severity = error 89 | 90 | # RCS0024: Add new line after switch label 91 | dotnet_diagnostic.RCS0024.severity = error 92 | 93 | # RCS0025: Put full accessor on its own line 94 | dotnet_diagnostic.RCS0025.severity = error 95 | 96 | # RCS0027: Place new line after/before binary operator 97 | dotnet_diagnostic.RCS0053.severity = error 98 | 99 | # RCS0028: Place new line after/before '?:' operator 100 | dotnet_diagnostic.RCS0053.severity = error 101 | 102 | # RCS0029: Put constructor initializer on its own line 103 | dotnet_diagnostic.RCS0029.severity = error 104 | 105 | # RCS0030: Add new line before embedded statement 106 | dotnet_diagnostic.RCS0030.severity = none 107 | 108 | # RCS0031: Add new line before enum member 109 | dotnet_diagnostic.RCS0031.severity = error 110 | 111 | # RCS0032: Place new line after/before arrow token 112 | dotnet_diagnostic.RCS0032.severity = error 113 | 114 | # RCS0033: Add new line before statement 115 | dotnet_diagnostic.RCS0033.severity = error 116 | 117 | # RCS0034: Add new line before type parameter constraint 118 | dotnet_diagnostic.RCS0034.severity = error 119 | 120 | # RCS0036: Remove blank line between single-line declarations of same kind 121 | dotnet_diagnostic.RCS0036.severity = none 122 | 123 | # RCS0038: Remove blank line between using directives with same root namespace 124 | dotnet_diagnostic.RCS0038.severity = error 125 | 126 | # RCS0039: Remove new line before base list 127 | dotnet_diagnostic.RCS0039.severity = error 128 | 129 | # RCS0041: Remove new line between 'if' keyword and 'else' keyword 130 | dotnet_diagnostic.RCS0041.severity = error 131 | 132 | # RCS0042: Put auto-accessors on a single line 133 | dotnet_diagnostic.RCS0042.severity = error 134 | 135 | # RCS0043: Format accessor's braces on a single line when expression is on single line 136 | dotnet_diagnostic.RCS0043.severity = error 137 | 138 | # RCS0044: Use carriage return + linefeed as new line 139 | dotnet_diagnostic.RCS0044.severity = none 140 | 141 | # RCS0045: Use linefeed as new line 142 | dotnet_diagnostic.RCS0045.severity = none 143 | 144 | # RCS0046: Use spaces instead of tab 145 | dotnet_diagnostic.RCS0046.severity = error 146 | 147 | # RCS0048: Put initializer on a single line 148 | dotnet_diagnostic.RCS0048.severity = none 149 | 150 | # RCS0049: Add blank line after top comment 151 | dotnet_diagnostic.RCS0049.severity = error 152 | 153 | # RCS0050: Add blank line before top declaration 154 | dotnet_diagnostic.RCS0050.severity = error 155 | 156 | # RCS0051: Add/remove new line before 'while' in 'do' statement 157 | dotnet_diagnostic.RCS0051.severity = error 158 | 159 | # RCS0052: Place new line after/before equals token 160 | dotnet_diagnostic.RCS0052.severity = none 161 | 162 | # RCS0053: Fix formatting of a list 163 | dotnet_diagnostic.RCS0053.severity = error 164 | 165 | # RCS0054: Fix formatting of a call chain 166 | dotnet_diagnostic.RCS0054.severity = error 167 | 168 | # RCS0055: Fix formatting of a binary expression chain 169 | dotnet_diagnostic.RCS0055.severity = error 170 | 171 | # RCS0056: A line is too long 172 | dotnet_diagnostic.RCS0056.severity = none 173 | 174 | # RCS1001: Add braces (when expression spans over multiple lines) 175 | dotnet_diagnostic.RCS1001.severity = error 176 | 177 | # RCS1002: Remove braces 178 | dotnet_diagnostic.RCS1002.severity = none 179 | 180 | # RCS1003: Add braces to if-else (when expression spans over multiple lines) 181 | dotnet_diagnostic.RCS1003.severity = error 182 | 183 | # RCS1004: Remove braces from if-else 184 | dotnet_diagnostic.RCS1004.severity = none 185 | 186 | # RCS1005: Simplify nested using statement 187 | dotnet_diagnostic.RCS1005.severity = error 188 | 189 | # RCS1006: Merge 'else' with nested 'if' 190 | dotnet_diagnostic.RCS1006.severity = error 191 | 192 | # RCS1007: Add braces 193 | dotnet_diagnostic.RCS1007.severity = none 194 | 195 | # RCS1008: Use explicit type instead of 'var' (when the type is not obvious) 196 | dotnet_diagnostic.RCS1008.severity = none 197 | 198 | # RCS1009: Use explicit type instead of 'var' (foreach variable) 199 | dotnet_diagnostic.RCS1009.severity = none 200 | 201 | # RCS1010: Use 'var' instead of explicit type (when the type is obvious) 202 | dotnet_diagnostic.RCS1010.severity = error 203 | 204 | # RCS1012: Use explicit type instead of 'var' (when the type is obvious) 205 | dotnet_diagnostic.RCS1012.severity = none 206 | 207 | # RCS1013: Use predefined type 208 | dotnet_diagnostic.RCS1013.severity = error 209 | 210 | # RCS1014: Use explicitly/implicitly typed array 211 | dotnet_diagnostic.RCS1014.severity = error 212 | 213 | # RCS1015: Use nameof operator 214 | dotnet_diagnostic.RCS1015.severity = error 215 | 216 | # RCS1016: Use block body or expression body 217 | dotnet_diagnostic.RCS1016.severity = error 218 | 219 | # RCS1018: Add/remove accessibility modifiers 220 | dotnet_diagnostic.RCS1018.severity = error 221 | 222 | # RCS1019: Order modifiers 223 | dotnet_diagnostic.RCS1019.severity = error 224 | 225 | # RCS1020: Simplify Nullable to T? 226 | dotnet_diagnostic.RCS1020.severity = error 227 | 228 | # RCS1021: Convert lambda expression body to expression body 229 | dotnet_diagnostic.RCS1021.severity = error 230 | 231 | # RCS1031: Remove unnecessary braces 232 | dotnet_diagnostic.RCS1031.severity = error 233 | 234 | # RCS1032: Remove redundant parentheses 235 | dotnet_diagnostic.RCS1032.severity = error 236 | 237 | # RCS1033: Remove redundant boolean literal 238 | dotnet_diagnostic.RCS1033.severity = error 239 | 240 | # RCS1034: Remove redundant 'sealed' modifier 241 | dotnet_diagnostic.RCS1034.severity = error 242 | 243 | # RCS1035: Remove redundant comma in initializer 244 | dotnet_diagnostic.RCS1035.severity = none 245 | 246 | # RCS1036: Remove unnecessary blank line 247 | dotnet_diagnostic.RCS1036.severity = error 248 | 249 | # RCS1037: Remove trailing white-space 250 | dotnet_diagnostic.RCS1037.severity = error 251 | 252 | # RCS1038: Remove empty statement 253 | dotnet_diagnostic.RCS1038.severity = error 254 | 255 | # RCS1039: Remove argument list from attribute 256 | dotnet_diagnostic.RCS1039.severity = error 257 | 258 | # RCS1040: Remove empty 'else' clause 259 | dotnet_diagnostic.RCS1040.severity = error 260 | 261 | # RCS1041: Remove empty initializer 262 | dotnet_diagnostic.RCS1041.severity = error 263 | 264 | # RCS1042: Remove enum default underlying type 265 | dotnet_diagnostic.RCS1042.severity = error 266 | 267 | # RCS1043: Remove 'partial' modifier from type with a single part 268 | dotnet_diagnostic.RCS1043.severity = error 269 | 270 | # RCS1044: Remove original exception from throw statement 271 | dotnet_diagnostic.RCS1044.severity = error 272 | 273 | # RCS1046: Asynchronous method name should end with 'Async' 274 | dotnet_diagnostic.RCS1046.severity = error 275 | 276 | # RCS1047: Non-asynchronous method name should not end with 'Async' 277 | dotnet_diagnostic.RCS1047.severity = error 278 | 279 | # RCS1048: Use lambda expression instead of anonymous method 280 | dotnet_diagnostic.RCS1048.severity = error 281 | 282 | # RCS1049: Simplify boolean comparison 283 | dotnet_diagnostic.RCS1049.severity = error 284 | 285 | # RCS1050: Include/omit parentheses when creating new object 286 | dotnet_diagnostic.RCS1050.severity = error 287 | 288 | # RCS1051: Add/remove parentheses from condition in conditional operator 289 | dotnet_diagnostic.RCS1051.severity = error 290 | 291 | # RCS1052: Declare each attribute separately 292 | dotnet_diagnostic.RCS1052.severity = error 293 | 294 | # RCS1055: Avoid semicolon at the end of declaration 295 | dotnet_diagnostic.RCS1055.severity = error 296 | 297 | # RCS1056: Avoid usage of using alias directive 298 | dotnet_diagnostic.RCS1056.severity = none 299 | 300 | # RCS1058: Use compound assignment 301 | dotnet_diagnostic.RCS1058.severity = error 302 | 303 | # RCS1059: Avoid locking on publicly accessible instance 304 | dotnet_diagnostic.RCS1059.severity = error 305 | 306 | # RCS1060: Declare each type in separate file 307 | dotnet_diagnostic.RCS1060.severity = error 308 | 309 | # RCS1061: Merge 'if' with nested 'if' 310 | dotnet_diagnostic.RCS1061.severity = error 311 | 312 | # RCS1063: Avoid usage of do statement to create an infinite loop 313 | dotnet_diagnostic.RCS1063.severity = error 314 | 315 | # RCS1064: Avoid usage of for statement to create an infinite loop 316 | dotnet_diagnostic.RCS1064.severity = error 317 | 318 | # RCS1065: Avoid usage of while statement to create an infinite loop 319 | dotnet_diagnostic.RCS1065.severity = error 320 | 321 | # RCS1066: Remove empty 'finally' clause 322 | dotnet_diagnostic.RCS1066.severity = error 323 | 324 | # RCS1068: Simplify logical negation 325 | dotnet_diagnostic.RCS1068.severity = error 326 | 327 | # RCS1069: Remove unnecessary case label 328 | dotnet_diagnostic.RCS.severity = error 329 | 330 | # RCS1070: Remove redundant default switch section 331 | dotnet_diagnostic.RCS1070.severity = error 332 | 333 | # RCS1071: Remove redundant base constructor call 334 | dotnet_diagnostic.RCS1071.severity = error 335 | 336 | # RCS1072: Remove empty namespace declaration 337 | dotnet_diagnostic.RCS1072.severity = error 338 | 339 | # RCS1073: Convert 'if' to 'return' statement 340 | dotnet_diagnostic.RCS1073.severity = error 341 | 342 | # RCS1074: Remove redundant constructor 343 | dotnet_diagnostic.RCS1074.severity = error 344 | 345 | # RCS1075: Avoid empty catch clause that catches System.Exception 346 | dotnet_diagnostic.RCS1075.severity = error 347 | 348 | # RCS1077: Optimize LINQ method call 349 | dotnet_diagnostic.RCS1077.severity = error 350 | 351 | # RCS1078: Use "" or 'string.Empty' 352 | dotnet_diagnostic.RCS.severity = error 353 | 354 | # RCS1079: Throwing of new NotImplementedException 355 | dotnet_diagnostic.RCS.severity = warning 356 | 357 | # RCS1080: Use 'Count/Length' property instead of 'Any' method 358 | dotnet_diagnostic.RCS1080.severity = error 359 | 360 | # RCS1081: Split variable declaration 361 | dotnet_diagnostic.RCS1081.severity = error 362 | 363 | # RCS1084: Use coalesce expression instead of conditional expression 364 | dotnet_diagnostic.RCS1084.severity = error 365 | 366 | # RCS1085: Use auto-implemented property 367 | dotnet_diagnostic.RCS1085.severity = error 368 | 369 | # RCS1089: Use --/++ operator instead of assignment 370 | dotnet_diagnostic.RCS1089.severity = error 371 | 372 | # RCS1090: Add/remove 'ConfigureAwait(false)' call 373 | dotnet_diagnostic.RCS1090.severity = error 374 | 375 | # RCS1091: Remove empty region 376 | dotnet_diagnostic.RCS1091.severity = error 377 | 378 | # RCS1093: Remove file with no code 379 | dotnet_diagnostic.RCS1093.severity = error 380 | 381 | # RCS1094: Declare using directive on top level 382 | dotnet_diagnostic.RCS1094.severity = none 383 | 384 | # RCS1096: Use 'HasFlag' method or bitwise operator 385 | dotnet_diagnostic.RCS1096.severity = error 386 | 387 | # RCS1097: Remove redundant 'ToString' call 388 | dotnet_diagnostic.RCS1097.severity = error 389 | 390 | # RCS1098: Constant values should be placed on right side of comparisons 391 | dotnet_diagnostic.RCS1098.severity = error 392 | 393 | # RCS1099: Default label should be the last label in a switch section 394 | dotnet_diagnostic.RCS1099.severity = error 395 | 396 | # RCS1102: Make class static 397 | dotnet_diagnostic.RCS1102.severity = error 398 | 399 | # RCS1103: Convert 'if' to assignment 400 | dotnet_diagnostic.RCS1103.severity = error 401 | 402 | # RCS1104: Simplify conditional expression 403 | dotnet_diagnostic.RCS1104.severity = error 404 | 405 | # RCS1105: Unnecessary interpolation 406 | dotnet_diagnostic.RCS1105.severity = error 407 | 408 | # RCS1106: Remove empty destructor 409 | dotnet_diagnostic.RCS1106.severity = error 410 | 411 | # RCS1107: Remove redundant 'ToCharArray' call 412 | dotnet_diagnostic.RCS1107.severity = error 413 | 414 | # RCS1108: Add 'static' modifier to all partial class declarations 415 | dotnet_diagnostic.RCS1108.severity = error 416 | 417 | # RCS1110: Declare type inside namespace 418 | dotnet_diagnostic.RCS1110.severity = error 419 | 420 | # RCS1111: Add braces to switch section with multiple statements 421 | dotnet_diagnostic.RCS1111.severity = error 422 | 423 | # RCS1112: Combine 'Enumerable.Where' method chain 424 | dotnet_diagnostic.RCS.severity = suggestion 425 | 426 | # RCS1113: Use 'string.IsNullOrEmpty' method 427 | dotnet_diagnostic.RCS1113.severity = error 428 | 429 | # RCS1114: Remove redundant delegate creation 430 | dotnet_diagnostic.RCS1114.severity = error 431 | 432 | # RCS1118: Mark local variable as const 433 | dotnet_diagnostic.RCS1118.severity = error 434 | 435 | # RCS1123: Add parentheses when necessary 436 | dotnet_diagnostic.RCS1123.severity = error 437 | 438 | # RCS1124: Inline local variable 439 | dotnet_diagnostic.RCS1124.severity = error 440 | 441 | # RCS1126: Add braces to if-else 442 | dotnet_diagnostic.RCS1126.severity = error 443 | 444 | # RCS1128: Use coalesce expression 445 | dotnet_diagnostic.RCS1128.severity = error 446 | 447 | # RCS1129: Remove redundant field initialization 448 | dotnet_diagnostic.RCS1129.severity = error 449 | 450 | # RCS1130: Bitwise operation on enum without Flags attribute 451 | dotnet_diagnostic.RCS1130.severity = error 452 | 453 | # RCS1132: Remove redundant overriding member 454 | dotnet_diagnostic.RCS1132.severity = error 455 | 456 | # RCS1133: Remove redundant Dispose/Close call 457 | dotnet_diagnostic.RCS1133.severity = error 458 | 459 | # RCS1134: Remove redundant statement 460 | dotnet_diagnostic.RCS1134.severity = error 461 | 462 | # RCS1135: Declare enum member with zero value (when enum has FlagsAttribute) 463 | dotnet_diagnostic.RCS1135.severity = error 464 | 465 | # RCS1136: Merge switch sections with equivalent content 466 | dotnet_diagnostic.RCS1136.severity = error 467 | 468 | # RCS1138: Add summary to documentation comment 469 | dotnet_diagnostic.RCS1138.severity = none 470 | 471 | # RCS1139: Add summary element to documentation comment 472 | dotnet_diagnostic.RCS1139.severity = error 473 | 474 | # RCS1140: Add exception to documentation comment 475 | dotnet_diagnostic.RCS1140.severity = error 476 | 477 | # RCS1141: Add 'param' element to documentation comment 478 | dotnet_diagnostic.RCS1141.severity = error 479 | 480 | # RCS1142: Add 'typeparam' element to documentation comment 481 | dotnet_diagnostic.RCS1142.severity = error 482 | 483 | # RCS1143: Simplify coalesce expression 484 | dotnet_diagnostic.RCS1143.severity = error 485 | 486 | # RCS1145: Remove redundant 'as' operator 487 | dotnet_diagnostic.RCS1145.severity = error 488 | 489 | # RCS1146: Use conditional access 490 | dotnet_diagnostic.RCS1146.severity = error 491 | 492 | # RCS1151: Remove redundant cast 493 | dotnet_diagnostic.RCS1151.severity = error 494 | 495 | # RCS1154: Sort enum members 496 | dotnet_diagnostic.RCS1154.severity = error 497 | 498 | # RCS1155: Use StringComparison when comparing strings 499 | dotnet_diagnostic.RCS1155.severity = error 500 | 501 | # RCS1156: Use string.Length instead of comparison with empty string 502 | dotnet_diagnostic.RCS1156.severity = error 503 | 504 | # RCS1157: Composite enum value contains undefined flag 505 | dotnet_diagnostic.RCS1157.severity = error 506 | 507 | # RCS1158: Static member in generic type should use a type parameter 508 | dotnet_diagnostic.RCS1158.severity = error 509 | 510 | # RCS1159: Use EventHandler 511 | dotnet_diagnostic.RCS1159.severity = error 512 | 513 | # RCS1160: Abstract type should not have public constructors 514 | dotnet_diagnostic.RCS1160.severity = error 515 | 516 | # RCS1161: Enum should declare explicit values 517 | dotnet_diagnostic.RCS1161.severity = error 518 | 519 | # RCS1162: Avoid chain of assignments 520 | dotnet_diagnostic.RCS1162.severity = error 521 | 522 | # RCS1163: Unused parameter 523 | dotnet_diagnostic.RCS1163.severity = error 524 | 525 | # RCS1164: Unused type parameter 526 | dotnet_diagnostic.RCS1164.severity = error 527 | 528 | # RCS1165: Unconstrained type parameter checked for null 529 | dotnet_diagnostic.RCS1165.severity = error 530 | 531 | # RCS1166: Value type object is never equal to null 532 | dotnet_diagnostic.RCS1166.severity = error 533 | 534 | # RCS1168: Parameter name differs from base name 535 | dotnet_diagnostic.RCS1168.severity = error 536 | 537 | # RCS1169: Make field read-only 538 | dotnet_diagnostic.RCS1169.severity = error 539 | 540 | # RCS1170: Use read-only auto-implemented property 541 | dotnet_diagnostic.RCS1170.severity = error 542 | 543 | # RCS1171: Simplify lazy initialization 544 | dotnet_diagnostic.RCS1171.severity = error 545 | 546 | # RCS1172: Use 'is' operator instead of 'as' operator 547 | dotnet_diagnostic.RCS1172.severity = error 548 | 549 | # RCS1173: Use coalesce expression instead of 'if' 550 | dotnet_diagnostic.RCS1173.severity = error 551 | 552 | # RCS1174: Remove redundant async/await 553 | dotnet_diagnostic.RCS1174.severity = error 554 | 555 | # RCS1175: Unused this parameter 556 | dotnet_diagnostic.RCS1175.severity = error 557 | 558 | # RCS1176: Use 'var' instead of explicit type (when the type is not obvious) 559 | dotnet_diagnostic.RCS1176.severity = error 560 | 561 | # RCS1177: Use 'var' instead of explicit type (in foreach) 562 | dotnet_diagnostic.RCS1177.severity = error 563 | 564 | # RCS1179: Unnecessary assignment 565 | dotnet_diagnostic.RCS1179.severity = error 566 | 567 | # RCS1180: Inline lazy initialization 568 | dotnet_diagnostic.RCS1180.severity = error 569 | 570 | # RCS1181: Convert comment to documentation comment 571 | dotnet_diagnostic.RCS1181.severity = none 572 | 573 | # RCS1182: Remove redundant base interface 574 | dotnet_diagnostic.RCS1182.severity = error 575 | 576 | # RCS1186: Use Regex instance instead of static method 577 | dotnet_diagnostic.RCS1186.severity = error 578 | 579 | # RCS1187: Use constant instead of field 580 | dotnet_diagnostic.RCS1187.severity = error 581 | 582 | # RCS1188: Remove redundant auto-property initialization 583 | dotnet_diagnostic.RCS1188.severity = error 584 | 585 | # RCS1189: Add or remove region name 586 | dotnet_diagnostic.RCS1189.severity = none 587 | 588 | # RCS1190: Join string expressions 589 | dotnet_diagnostic.RCS1190.severity = error 590 | 591 | # RCS1191: Declare enum value as combination of names 592 | dotnet_diagnostic.RCS1191.severity = error 593 | 594 | # RCS1192: Unnecessary usage of verbatim string literal 595 | dotnet_diagnostic.RCS1192.severity = error 596 | 597 | # RCS1193: Overriding member should not change 'params' modifier 598 | dotnet_diagnostic.RCS1193.severity = error 599 | 600 | # RCS1194: Implement exception constructors 601 | dotnet_diagnostic.RCS1194.severity = error 602 | 603 | # RCS1195: Use ^ operator 604 | dotnet_diagnostic.RCS1195.severity = error 605 | 606 | # RCS1196: Call extension method as instance method 607 | dotnet_diagnostic.RCS1196.severity = error 608 | 609 | # RCS1197: Optimize StringBuilder.Append/AppendLine call 610 | dotnet_diagnostic.RCS1197.severity = error 611 | 612 | # RCS1198: Avoid unnecessary boxing of value type 613 | dotnet_diagnostic.RCS1198.severity = none 614 | 615 | # RCS1199: Unnecessary null check 616 | dotnet_diagnostic.RCS1199.severity = error 617 | 618 | # RCS1200: Call 'Enumerable.ThenBy' instead of 'Enumerable.OrderBy' 619 | dotnet_diagnostic.RCS1200.severity = error 620 | 621 | # RCS1201: Use method chaining 622 | dotnet_diagnostic.RCS.severity = suggestion 623 | 624 | # RCS1202: Avoid NullReferenceException 625 | dotnet_diagnostic.RCS1202.severity = error 626 | 627 | # RCS1203: Use AttributeUsageAttribute 628 | dotnet_diagnostic.RCS1203.severity = error 629 | 630 | # RCS1204: Use EventArgs.Empty 631 | dotnet_diagnostic.RCS1204.severity = error 632 | 633 | # RCS1205: Order named arguments according to the order of parameters 634 | dotnet_diagnostic.RCS1205.severity = error 635 | 636 | # RCS1206: Use conditional access instead of conditional expression 637 | dotnet_diagnostic.RCS1206.severity = error 638 | 639 | # RCS1207: Use anonymous function or method group 640 | dotnet_diagnostic.RCS1207.severity = error 641 | 642 | # RCS1208: Reduce 'if' nesting 643 | dotnet_diagnostic.RCS1208.severity = suggestion 644 | 645 | # RCS1209: Order type parameter constraints 646 | dotnet_diagnostic.RCS1209.severity = error 647 | 648 | # RCS1210: Return completed task instead of returning null 649 | dotnet_diagnostic.RCS1210.severity = none 650 | 651 | # RCS1211: Remove unnecessary 'else' 652 | dotnet_diagnostic.RCS1211.severity = error 653 | 654 | # RCS1212: Remove redundant assignment 655 | dotnet_diagnostic.RCS1212.severity = error 656 | 657 | # RCS1213: Remove unused member declaration 658 | dotnet_diagnostic.RCS1213.severity = error 659 | 660 | # RCS1214: Unnecessary interpolated string 661 | dotnet_diagnostic.RCS1214.severity = error 662 | 663 | # RCS1215: Expression is always equal to true/false 664 | dotnet_diagnostic.RCS1215.severity = error 665 | 666 | # RCS1216: Unnecessary unsafe context 667 | dotnet_diagnostic.RCS1216.severity = error 668 | 669 | # RCS1217: Convert interpolated string to concatenation 670 | dotnet_diagnostic.RCS1217.severity = none 671 | 672 | # RCS1218: Simplify code branching 673 | dotnet_diagnostic.RCS1218.severity = error 674 | 675 | # RCS1220: Use pattern matching instead of combination of 'is' operator and cast operator 676 | dotnet_diagnostic.RCS1220.severity = error 677 | 678 | # RCS1221: Use pattern matching instead of combination of 'as' operator and null check 679 | dotnet_diagnostic.RCS1221.severity = error 680 | 681 | # RCS1222: Merge preprocessor directives 682 | dotnet_diagnostic.RCS1222.severity = error 683 | 684 | # RCS1223: Mark publicly visible type with DebuggerDisplay attribute 685 | dotnet_diagnostic.RCS1223.severity = none 686 | 687 | # RCS1224: Make method an extension method 688 | dotnet_diagnostic.RCS1224.severity = suggestion 689 | 690 | # RCS1225: Make class sealed 691 | dotnet_diagnostic.RCS1225.severity = error 692 | 693 | # RCS1226: Add paragraph to documentation comment 694 | dotnet_diagnostic.RCS1226.severity = error 695 | 696 | # RCS1227: Validate arguments correctly 697 | dotnet_diagnostic.RCS1227.severity = error 698 | 699 | # RCS1228: Unused element in documentation comment 700 | dotnet_diagnostic.RCS1228.severity = error 701 | 702 | # RCS1229: Use async/await when necessary 703 | dotnet_diagnostic.RCS1229.severity = error 704 | 705 | # RCS1230: Unnecessary explicit use of enumerator 706 | dotnet_diagnostic.RCS1230.severity = error 707 | 708 | # RCS1231: Make parameter ref read-only 709 | dotnet_diagnostic.RCS1231.severity = none 710 | 711 | # RCS1232: Order elements in documentation comment 712 | dotnet_diagnostic.RCS1232.severity = error 713 | 714 | # RCS1233: Use short-circuiting operator 715 | dotnet_diagnostic.RCS1233.severity = error 716 | 717 | # RCS1234: Duplicate enum value 718 | dotnet_diagnostic.RCS1234.severity = error 719 | 720 | # RCS1235: Optimize method call 721 | dotnet_diagnostic.RCS1235.severity = error 722 | 723 | # RCS1236: Use exception filter 724 | dotnet_diagnostic.RCS1236.severity = error 725 | 726 | # RCS1237: Use bit shift operator 727 | dotnet_diagnostic.RCS1237.severity = none 728 | 729 | # RCS1238: Avoid nested ?: operators 730 | dotnet_diagnostic.RCS1238.severity = error 731 | 732 | # RCS1239: Use 'for' statement instead of 'while' statement 733 | dotnet_diagnostic.RCS1239.severity = error 734 | 735 | # RCS1240: Operator is unnecessary 736 | dotnet_diagnostic.RCS1240.severity = error 737 | 738 | # RCS1241: Implement non-generic counterpart 739 | dotnet_diagnostic.RCS1241.severity = error 740 | 741 | # RCS1242: Do not pass non-read-only struct by read-only reference 742 | dotnet_diagnostic.RCS1242.severity = error 743 | 744 | # RCS1243: Duplicate word in a comment 745 | dotnet_diagnostic.RCS1243.severity = error 746 | 747 | # RCS1244: Simplify 'default' expression 748 | dotnet_diagnostic.RCS1244.severity = error 749 | 750 | # RCS1246: Use element access 751 | dotnet_diagnostic.RCS1246.severity = error 752 | 753 | # RCS1247: Fix documentation comment tag 754 | dotnet_diagnostic.RCS1247.severity = error 755 | 756 | # RCS1248: Normalize null check 757 | dotnet_diagnostic.RCS1248.severity = error 758 | 759 | # RCS1249: Unnecessary null-forgiving operator 760 | dotnet_diagnostic.RCS1249.severity = error 761 | 762 | # RCS1250: Use implicit/explicit object creation 763 | dotnet_diagnostic.RCS1250.severity = error 764 | 765 | # RCS1251: Remove unnecessary braces from record declaration 766 | dotnet_diagnostic.RCS1251.severity = error 767 | 768 | # RCS1252: Normalize usage of infinite loop 769 | dotnet_diagnostic.RCS1252.severity = error 770 | 771 | # RCS1253: Normalize format of enum flag value 772 | dotnet_diagnostic.RCS1253.severity = error 773 | 774 | # RCS1254: Normalize format of enum flag value 775 | dotnet_diagnostic.RCS1254.severity = error 776 | 777 | # RCS9001: Use pattern matching 778 | dotnet_diagnostic.RCS9001.severity = error 779 | 780 | # RCS9002: Use property SyntaxNode.SpanStart 781 | dotnet_diagnostic.RCS9002.severity = error 782 | 783 | # RCS9003: Unnecessary conditional access 784 | dotnet_diagnostic.RCS9003.severity = error 785 | 786 | # RCS9004: Call 'Any' instead of accessing 'Count' 787 | dotnet_diagnostic.RCS9004.severity = error 788 | 789 | # RCS9005: Unnecessary null check 790 | dotnet_diagnostic.RCS9005.severity = error 791 | 792 | # RCS9006: Use element access 793 | dotnet_diagnostic.RCS9006.severity = error 794 | 795 | # RCS9007: Use return value 796 | dotnet_diagnostic.RCS9007.severity = error 797 | 798 | # RCS9008: Call 'Last' instead of using [] 799 | dotnet_diagnostic.RCS9008.severity = error 800 | 801 | # RCS9009: Unknown language name 802 | dotnet_diagnostic.RCS9009.severity = error 803 | 804 | # RCS9010: Specify ExportCodeRefactoringProviderAttribute.Name 805 | dotnet_diagnostic.RCS9010.severity = error 806 | 807 | # RCS9011: Specify ExportCodeFixProviderAttribute.Name 808 | dotnet_diagnostic.RCS9011.severity = error 809 | 810 | # 811 | # Refactorings 812 | 813 | # Enable all refactorings 814 | roslynator_refactorings.enabled = true 815 | 816 | # 817 | # Compiler diagnostic fixes 818 | 819 | # Enable all compiler diagnostic fixes 820 | roslynator_compiler_diagnostic_fixes.enabled = true 821 | --------------------------------------------------------------------------------