Skip to content

Commit 9a0ee91

Browse files
committed
build
1 parent 0f2b596 commit 9a0ee91

File tree

9 files changed

+224
-29
lines changed

9 files changed

+224
-29
lines changed

.github/workflows/dotnet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- name: Setup .NET
2222
uses: actions/setup-dotnet@v1
2323
with:
24-
dotnet-version: 6.0.x
24+
dotnet-version: 9.0.x
2525

2626
# run build and test
2727
- name: Restore dependencies

Directory.Build.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
<RepositoryUrl>https://github.com/managedcode/MimeTypes</RepositoryUrl>
1818
<PackageProjectUrl>https://github.com/managedcode/MimeTypes</PackageProjectUrl>
1919
<Product>Managed Code - MimeTypes</Product>
20-
<Version>1.0.1</Version>
21-
<PackageVersion>1.0.1</PackageVersion>
20+
<Version>1.0.2</Version>
21+
<PackageVersion>1.0.2</PackageVersion>
2222

2323
</PropertyGroup>
2424
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
@@ -29,7 +29,7 @@
2929
<None Include="$(SolutionDir)\README.md" Pack="true" Visible="false" PackagePath="\"/>
3030
</ItemGroup>
3131
<ItemGroup>
32-
<PackageReference Include="DotNet.ReproducibleBuilds" Version="1.1.1">
32+
<PackageReference Update="DotNet.ReproducibleBuilds" Version="1.2.25">
3333
<PrivateAssets>all</PrivateAssets>
3434
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3535
</PackageReference>

ManagedCode.MimeTypes.Generator/ManagedCode.MimeTypes.Generator.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.1.0" PrivateAssets="all" />
11-
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3">
10+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" PrivateAssets="all" />
11+
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
1212
<PrivateAssets>all</PrivateAssets>
1313
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1414
</PackageReference>
15-
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" PrivateAssets="all" />
15+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" PrivateAssets="all" />
1616
</ItemGroup>
1717

1818
<PropertyGroup>

ManagedCode.MimeTypes.Tests/GeneratorTests.cs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
using System;
2-
using System.IO;
3-
using System.Linq;
4-
using FluentAssertions;
5-
using ManagedCode.MimeTypes.Generator;
6-
using Newtonsoft.Json.Linq;
1+
using Shouldly;
72
using Xunit;
83

94
namespace ManagedCode.MimeTypes.Tests;
@@ -13,18 +8,18 @@ public class GeneratorTests
138
[Fact]
149
public void ExtensionsTest()
1510
{
16-
MimeHelper.GetMimeType("pdf").Should().Be("application/pdf");
17-
MimeHelper.GetMimeType(".gz").Should().Be("application/gzip");
18-
MimeHelper.GetMimeType("word.docx").Should().Be("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
19-
MimeHelper.GetMimeType("C:\\\\users\\file.txt").Should().Be("text/plain");
11+
MimeHelper.GetMimeType("pdf").ShouldBe("application/pdf");
12+
MimeHelper.GetMimeType(".gz").ShouldBe("application/gzip");
13+
MimeHelper.GetMimeType("word.docx").ShouldBe("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
14+
MimeHelper.GetMimeType("C:\\\\users\\file.txt").ShouldBe("text/plain");
2015
}
2116

2217
[Fact]
2318
public void EmptyExtensionsTest()
2419
{
25-
MimeHelper.GetMimeType("").Should().Be("application/octet-stream");
26-
MimeHelper.GetMimeType(" ").Should().Be("application/octet-stream");
27-
MimeHelper.GetMimeType(null as string).Should().Be("application/octet-stream");
20+
MimeHelper.GetMimeType("").ShouldBe("application/octet-stream");
21+
MimeHelper.GetMimeType(" ").ShouldBe("application/octet-stream");
22+
MimeHelper.GetMimeType(null as string).ShouldBe("application/octet-stream");
2823
}
2924

3025
[Fact]

ManagedCode.MimeTypes.Tests/ManagedCode.MimeTypes.Tests.csproj

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,27 @@
1717
</None>
1818
</ItemGroup>
1919
<ItemGroup>
20-
<PackageReference Include="FluentAssertions" Version="6.5.1" />
21-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
22-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
20+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.1" />
21+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
22+
<PackageReference Include="Shouldly" Version="4.3.0" />
2323
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
24-
<PackageReference Include="xunit" Version="2.4.1" />
25-
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
24+
<PackageReference Include="xunit" Version="2.9.3" />
25+
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.1">
2626
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2727
<PrivateAssets>all</PrivateAssets>
2828
</PackageReference>
29-
<PackageReference Include="coverlet.collector" Version="3.1.2">
29+
<PackageReference Include="coverlet.collector" Version="6.0.4">
3030
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3131
<PrivateAssets>all</PrivateAssets>
3232
</PackageReference>
33-
<PackageReference Include="coverlet.msbuild" Version="3.1.2">
33+
<PackageReference Include="coverlet.msbuild" Version="6.0.4">
3434
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3535
<PrivateAssets>all</PrivateAssets>
3636
</PackageReference>
37+
<PackageReference Update="DotNet.ReproducibleBuilds" Version="1.2.25">
38+
<PrivateAssets>all</PrivateAssets>
39+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
40+
</PackageReference>
3741
</ItemGroup>
3842

3943
<ItemGroup>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using Shouldly;
2+
using Xunit;
3+
4+
namespace ManagedCode.MimeTypes.Tests;
5+
6+
public class MimeCategoryTests
7+
{
8+
[Theory]
9+
[InlineData("video/mp4", MimeTypeCategory.Video)]
10+
[InlineData("video/x-msvideo", MimeTypeCategory.Video)]
11+
[InlineData("audio/mpeg", MimeTypeCategory.Audio)]
12+
[InlineData("audio/midi", MimeTypeCategory.Audio)]
13+
[InlineData("image/jpeg", MimeTypeCategory.Image)]
14+
[InlineData("image/png", MimeTypeCategory.Image)]
15+
[InlineData("text/plain", MimeTypeCategory.Text)]
16+
[InlineData("text/html", MimeTypeCategory.Text)]
17+
[InlineData("font/ttf", MimeTypeCategory.Font)]
18+
[InlineData("font/woff2", MimeTypeCategory.Font)]
19+
[InlineData("model/gltf-binary", MimeTypeCategory.Model)]
20+
[InlineData("application/pdf", MimeTypeCategory.Pdf)]
21+
public void BasicMimeCategories_ShouldMatch(string mime, MimeTypeCategory expectedCategory)
22+
{
23+
MimeHelper.GetMimeCategory(mime).ShouldBe(expectedCategory);
24+
}
25+
26+
[Theory]
27+
[InlineData("application/json")]
28+
[InlineData("application/ld+json")]
29+
[InlineData("application/json5")]
30+
[InlineData("application/activity+json")]
31+
public void JsonMimeTypes_ShouldBeJson(string mime)
32+
{
33+
MimeHelper.GetMimeCategory(mime).ShouldBe(MimeTypeCategory.Json);
34+
MimeHelper.IsJson(mime).ShouldBeTrue();
35+
}
36+
37+
[Theory]
38+
[InlineData("application/xml")]
39+
[InlineData("text/xml")]
40+
[InlineData("application/atom+xml")]
41+
[InlineData("application/mathml+xml")]
42+
public void XmlMimeTypes_ShouldBeXml(string mime)
43+
{
44+
MimeHelper.GetMimeCategory(mime).ShouldBe(MimeTypeCategory.Xml);
45+
MimeHelper.IsXml(mime).ShouldBeTrue();
46+
}
47+
48+
[Theory]
49+
[InlineData("application/zip")]
50+
[InlineData("application/x-7z-compressed")]
51+
[InlineData("application/x-rar-compressed")]
52+
[InlineData("application/gzip")]
53+
public void ArchiveMimeTypes_ShouldBeArchive(string mime)
54+
{
55+
MimeHelper.GetMimeCategory(mime).ShouldBe(MimeTypeCategory.Archive);
56+
MimeHelper.IsArchive(mime).ShouldBeTrue();
57+
}
58+
59+
[Theory]
60+
[InlineData("application/x-msdownload")]
61+
[InlineData("application/x-executable")]
62+
[InlineData("application/x-msi")]
63+
[InlineData("application/x-apple-diskimage")]
64+
public void ExecutableMimeTypes_ShouldBeExecutable(string mime)
65+
{
66+
MimeHelper.GetMimeCategory(mime).ShouldBe(MimeTypeCategory.Executable);
67+
MimeHelper.IsExecutable(mime).ShouldBeTrue();
68+
}
69+
70+
[Theory]
71+
[InlineData("application/x-x509-ca-cert")]
72+
[InlineData("application/pkix-cert")]
73+
[InlineData("application/x-pkcs12")]
74+
public void CertificateMimeTypes_ShouldBeCertificate(string mime)
75+
{
76+
MimeHelper.GetMimeCategory(mime).ShouldBe(MimeTypeCategory.Certificate);
77+
MimeHelper.IsCertificate(mime).ShouldBeTrue();
78+
}
79+
80+
[Theory]
81+
[InlineData("")]
82+
[InlineData(null)]
83+
[InlineData(" ")]
84+
public void EmptyMimeTypes_ShouldBeUnknown(string mime)
85+
{
86+
MimeHelper.GetMimeCategory(mime).ShouldBe(MimeTypeCategory.Unknown);
87+
}
88+
89+
[Theory]
90+
[InlineData("application/msword")]
91+
[InlineData("application/vnd.ms-excel")]
92+
[InlineData("application/vnd.openxmlformats-officedocument.wordprocessingml.document")]
93+
public void DocumentMimeTypes_ShouldBeDocument(string mime)
94+
{
95+
MimeHelper.GetMimeCategory(mime).ShouldBe(MimeTypeCategory.Document);
96+
MimeHelper.IsDocument(mime).ShouldBeTrue();
97+
}
98+
99+
[Fact]
100+
public void InvalidMimeType_ShouldBeUnknown()
101+
{
102+
MimeHelper.GetMimeCategory("invalid/mime-type").ShouldBe(MimeTypeCategory.Unknown);
103+
}
104+
}

ManagedCode.MimeTypes/ManagedCode.MimeTypes.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<Nullable>enable</Nullable>
6-
<LangVersion>10</LangVersion>
6+
<LangVersion>13</LangVersion>
77
</PropertyGroup>
88

99
<ItemGroup>
@@ -19,7 +19,7 @@
1919
</PropertyGroup>
2020

2121
<ItemGroup>
22-
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
22+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
2323
</ItemGroup>
2424

2525
</Project>

ManagedCode.MimeTypes/MimeHelper.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.Text.RegularExpressions;
45

56
namespace ManagedCode.MimeTypes;
67

@@ -35,4 +36,72 @@ public static string GetMimeType(string extension)
3536
extension = extension.Replace('.', '\0');
3637
return MimeTypes.TryGetValue(extension, out var mime) ? mime : "application/octet-stream";
3738
}
39+
40+
private static readonly Regex XmlPattern = new(@"^(?:application|text)/.*?\+?xml$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
41+
private static readonly Regex JsonPattern = new(@"^application/(?:.*?\+)?json5?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
42+
private static readonly Regex ArchivePattern = new(@"^application/(?:zip|x-(?:7z|rar|tar|bzip2|gzip)-compressed|gzip|vnd\.rar|octet-stream)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
43+
private static readonly Regex ExecutablePattern = new(@"^application/(?:x-msdownload|x-executable|x-msi|x-apple-diskimage|octet-stream)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
44+
private static readonly Regex CertificatePattern = new(@"^application/(?:x-x509-ca-cert|pkix-cert|x-pkcs12)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
45+
46+
// New patterns for specific document types
47+
private static readonly Regex WordPattern = new(@"^application/(?:msword|vnd\.openxmlformats-officedocument\.wordprocessingml\.|vnd\.ms-word\.|vnd\.oasis\.opendocument\.text)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
48+
private static readonly Regex SpreadsheetPattern = new(@"^application/(?:vnd\.ms-excel|vnd\.openxmlformats-officedocument\.spreadsheetml\.|vnd\.oasis\.opendocument\.spreadsheet)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
49+
private static readonly Regex PresentationPattern = new(@"^application/(?:vnd\.ms-powerpoint|vnd\.openxmlformats-officedocument\.presentationml\.|vnd\.oasis\.opendocument\.presentation)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
50+
private static readonly Regex CalendarPattern = new(@"^(?:text/calendar|application/ics)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
51+
private static readonly Regex EmailPattern = new(@"^(?:message/(?:rfc822|global)|application/(?:mbox|x-msmessage))", RegexOptions.Compiled | RegexOptions.IgnoreCase);
52+
53+
public static MimeTypeCategory GetMimeCategory(string mime)
54+
{
55+
if (string.IsNullOrWhiteSpace(mime))
56+
return MimeTypeCategory.Unknown;
57+
58+
var m = mime.ToLowerInvariant();
59+
60+
// Primary types
61+
if (m.StartsWith("video/")) return MimeTypeCategory.Video;
62+
if (m.StartsWith("audio/")) return MimeTypeCategory.Audio;
63+
if (m.StartsWith("image/")) return MimeTypeCategory.Image;
64+
if (m.StartsWith("text/")) return MimeTypeCategory.Text;
65+
if (m.StartsWith("font/")) return MimeTypeCategory.Font;
66+
if (m.StartsWith("model/")) return MimeTypeCategory.Model;
67+
68+
// Document types
69+
if (m == "application/pdf") return MimeTypeCategory.Pdf;
70+
if (WordPattern.IsMatch(m)) return MimeTypeCategory.Document;
71+
if (SpreadsheetPattern.IsMatch(m)) return MimeTypeCategory.Spreadsheet;
72+
if (PresentationPattern.IsMatch(m)) return MimeTypeCategory.Presentation;
73+
74+
// Data formats
75+
if (JsonPattern.IsMatch(m)) return MimeTypeCategory.Json;
76+
if (XmlPattern.IsMatch(m)) return MimeTypeCategory.Xml;
77+
78+
// Special types
79+
if (ArchivePattern.IsMatch(m)) return MimeTypeCategory.Archive;
80+
if (ExecutablePattern.IsMatch(m)) return MimeTypeCategory.Executable;
81+
if (CertificatePattern.IsMatch(m)) return MimeTypeCategory.Certificate;
82+
if (CalendarPattern.IsMatch(m)) return MimeTypeCategory.Calendar;
83+
if (EmailPattern.IsMatch(m)) return MimeTypeCategory.Email;
84+
85+
// Generic application type
86+
return m.StartsWith("application/") ? MimeTypeCategory.Document : MimeTypeCategory.Unknown;
87+
}
88+
89+
public static bool IsVideo(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Video;
90+
public static bool IsAudio(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Audio;
91+
public static bool IsImage(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Image;
92+
public static bool IsDocument(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Document;
93+
public static bool IsPdf(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Pdf;
94+
public static bool IsArchive(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Archive;
95+
96+
public static bool IsText(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Text;
97+
public static bool IsJson(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Json;
98+
public static bool IsXml(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Xml;
99+
public static bool IsFont(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Font;
100+
public static bool IsModel(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Model;
101+
public static bool IsExecutable(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Executable;
102+
public static bool IsCertificate(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Certificate;
103+
public static bool IsSpreadsheet(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Spreadsheet;
104+
public static bool IsPresentation(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Presentation;
105+
public static bool IsCalendar(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Calendar;
106+
public static bool IsEmail(string mime) => GetMimeCategory(mime) == MimeTypeCategory.Email;
38107
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace ManagedCode.MimeTypes;
2+
3+
public enum MimeTypeCategory
4+
{
5+
Unknown,
6+
Video,
7+
Audio,
8+
Image,
9+
Document,
10+
Spreadsheet,
11+
Presentation,
12+
Pdf,
13+
Archive,
14+
Text,
15+
Json,
16+
Xml,
17+
Font,
18+
Model,
19+
Executable,
20+
Certificate,
21+
Calendar,
22+
Email
23+
}

0 commit comments

Comments
 (0)