├── index
├── empty.bin
├── empty.rtf
├── empty.zip
├── empty.pgm
├── empty.ppm
├── empty.7z
├── empty.bmp
├── empty.bz2
├── empty.dib
├── empty.emf
├── empty.gif
├── empty.gz
├── empty.ico
├── empty.j2c
├── empty.jp2
├── empty.jpc
├── empty.jpe
├── empty.jpg
├── empty.jxr
├── empty.kmz
├── empty.odp
├── empty.ods
├── empty.odt
├── empty.pbm
├── empty.png
├── empty.rle
├── empty.tga
├── empty.tif
├── empty.wdp
├── empty.wmp
├── empty.xz
├── empty.7zip
├── empty.avif
├── empty.bzip2
├── empty.docx
├── empty.exif
├── empty.gzip
├── empty.heic
├── empty.heif
├── empty.jfif
├── empty.jpeg
├── empty.nupkg
├── empty.pptx
├── empty.tiff
├── empty.webp
├── empty.xlsx
├── empty.pcx
├── empty.dds
├── empty.pdf
└── empty.tar
├── files
├── binary
│ └── empty.bin
├── document
│ ├── empty.rtf
│ ├── empty.docx
│ ├── empty.odt
│ └── empty.pdf
├── archive
│ ├── empty.zip
│ ├── empty.7z
│ ├── empty.gz
│ ├── empty.xz
│ ├── empty.7zip
│ ├── empty.bz2
│ ├── empty.bzip2
│ ├── empty.gzip
│ ├── empty.kmz
│ ├── empty.nupkg
│ └── empty.tar
├── image
│ ├── empty.pgm
│ ├── empty.ppm
│ ├── empty.avif
│ ├── empty.bmp
│ ├── empty.dib
│ ├── empty.emf
│ ├── empty.exif
│ ├── empty.gif
│ ├── empty.heic
│ ├── empty.heif
│ ├── empty.ico
│ ├── empty.j2c
│ ├── empty.jfif
│ ├── empty.jp2
│ ├── empty.jpc
│ ├── empty.jpe
│ ├── empty.jpeg
│ ├── empty.jpg
│ ├── empty.jxr
│ ├── empty.pbm
│ ├── empty.png
│ ├── empty.rle
│ ├── empty.tga
│ ├── empty.tif
│ ├── empty.tiff
│ ├── empty.wdp
│ ├── empty.webp
│ ├── empty.wmp
│ ├── empty.pcx
│ └── empty.dds
├── sheet
│ ├── empty.ods
│ └── empty.xlsx
└── slide
│ ├── empty.odp
│ └── empty.pptx
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── feature_request.md
│ └── bug_report.md
├── dependabot.yml
├── workflows
│ ├── merge-dependabot.yml
│ └── on-push-do-doco.yml
└── stale.yml
├── docs
├── intro.include.md
├── zzz.png
└── zzz.include.md
├── src
├── EmptyFiles
│ ├── ClsCompliant.cs
│ ├── IsTextFile.cs
│ ├── GlobalUsings.cs
│ ├── Category.cs
│ ├── EmptyFile.cs
│ ├── AssemblyLocation.cs
│ ├── EmptyFileTargets.md
│ ├── Guard.cs
│ ├── EmptyFiles.csproj
│ ├── ContentTypes.cs
│ ├── AllFiles.cs
│ └── FileExtensions.cs
├── icon.png
├── key.snk
├── Tests
│ ├── GlobalUsings.cs
│ ├── ImmutableVersionTests.cs
│ ├── Size.cs
│ ├── IndexWriter.cs
│ ├── Tests.csproj
│ ├── SolutionDirectoryFinder.cs
│ ├── ContentTypesTests.cs
│ ├── ExtensionsTests.cs
│ └── Tests.cs
├── global.json
├── mdsnippets.json
├── EmptyFiles.targets
├── EmptyFiles.Tool
│ ├── AssemblyInfo.cs
│ ├── Program.cs
│ └── EmptyFiles.Tool.csproj
├── EmptyFiles.slnx
├── nuget.md
├── Directory.Build.props
├── EmptyFiles.slnx.DotSettings
├── Directory.Packages.props
├── nuget.config
├── appveyor.yml
├── extensions.include.md
├── .editorconfig
└── Shared.sln.DotSettings
├── .gitignore
├── .gitattributes
├── license.txt
├── code_of_conduct.md
└── readme.md
/index/empty.bin:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/files/binary/empty.bin:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/index/empty.rtf:
--------------------------------------------------------------------------------
1 | {\rtf}
--------------------------------------------------------------------------------
/files/document/empty.rtf:
--------------------------------------------------------------------------------
1 | {\rtf}
--------------------------------------------------------------------------------
/index/empty.zip:
--------------------------------------------------------------------------------
1 | PK
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: VerifyTests
2 |
--------------------------------------------------------------------------------
/index/empty.pgm:
--------------------------------------------------------------------------------
1 | P5
2 | 1 1
3 | 255
4 |
--------------------------------------------------------------------------------
/index/empty.ppm:
--------------------------------------------------------------------------------
1 | P6
2 | 1 1
3 | 255
4 |
--------------------------------------------------------------------------------
/files/archive/empty.zip:
--------------------------------------------------------------------------------
1 | PK
--------------------------------------------------------------------------------
/files/image/empty.pgm:
--------------------------------------------------------------------------------
1 | P5
2 | 1 1
3 | 255
4 |
--------------------------------------------------------------------------------
/files/image/empty.ppm:
--------------------------------------------------------------------------------
1 | P6
2 | 1 1
3 | 255
4 |
--------------------------------------------------------------------------------
/docs/intro.include.md:
--------------------------------------------------------------------------------
1 | A collection of minimal binary files.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
--------------------------------------------------------------------------------
/src/EmptyFiles/ClsCompliant.cs:
--------------------------------------------------------------------------------
1 | [assembly: CLSCompliant(true)]
--------------------------------------------------------------------------------
/docs/zzz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/docs/zzz.png
--------------------------------------------------------------------------------
/src/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/src/icon.png
--------------------------------------------------------------------------------
/src/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/src/key.snk
--------------------------------------------------------------------------------
/index/empty.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.7z
--------------------------------------------------------------------------------
/index/empty.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.bmp
--------------------------------------------------------------------------------
/index/empty.bz2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.bz2
--------------------------------------------------------------------------------
/index/empty.dib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.dib
--------------------------------------------------------------------------------
/index/empty.emf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.emf
--------------------------------------------------------------------------------
/index/empty.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.gif
--------------------------------------------------------------------------------
/index/empty.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.gz
--------------------------------------------------------------------------------
/index/empty.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.ico
--------------------------------------------------------------------------------
/index/empty.j2c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.j2c
--------------------------------------------------------------------------------
/index/empty.jp2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.jp2
--------------------------------------------------------------------------------
/index/empty.jpc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.jpc
--------------------------------------------------------------------------------
/index/empty.jpe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.jpe
--------------------------------------------------------------------------------
/index/empty.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.jpg
--------------------------------------------------------------------------------
/index/empty.jxr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.jxr
--------------------------------------------------------------------------------
/index/empty.kmz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.kmz
--------------------------------------------------------------------------------
/index/empty.odp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.odp
--------------------------------------------------------------------------------
/index/empty.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.ods
--------------------------------------------------------------------------------
/index/empty.odt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.odt
--------------------------------------------------------------------------------
/index/empty.pbm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.pbm
--------------------------------------------------------------------------------
/index/empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.png
--------------------------------------------------------------------------------
/index/empty.rle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.rle
--------------------------------------------------------------------------------
/index/empty.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.tga
--------------------------------------------------------------------------------
/index/empty.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.tif
--------------------------------------------------------------------------------
/index/empty.wdp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.wdp
--------------------------------------------------------------------------------
/index/empty.wmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.wmp
--------------------------------------------------------------------------------
/index/empty.xz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.xz
--------------------------------------------------------------------------------
/index/empty.7zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.7zip
--------------------------------------------------------------------------------
/index/empty.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.avif
--------------------------------------------------------------------------------
/index/empty.bzip2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.bzip2
--------------------------------------------------------------------------------
/index/empty.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.docx
--------------------------------------------------------------------------------
/index/empty.exif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.exif
--------------------------------------------------------------------------------
/index/empty.gzip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.gzip
--------------------------------------------------------------------------------
/index/empty.heic:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.heic
--------------------------------------------------------------------------------
/index/empty.heif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.heif
--------------------------------------------------------------------------------
/index/empty.jfif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.jfif
--------------------------------------------------------------------------------
/index/empty.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.jpeg
--------------------------------------------------------------------------------
/index/empty.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.nupkg
--------------------------------------------------------------------------------
/index/empty.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.pptx
--------------------------------------------------------------------------------
/index/empty.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.tiff
--------------------------------------------------------------------------------
/index/empty.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.webp
--------------------------------------------------------------------------------
/index/empty.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/index/empty.xlsx
--------------------------------------------------------------------------------
/files/archive/empty.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.7z
--------------------------------------------------------------------------------
/files/archive/empty.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.gz
--------------------------------------------------------------------------------
/files/archive/empty.xz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.xz
--------------------------------------------------------------------------------
/files/image/empty.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.avif
--------------------------------------------------------------------------------
/files/image/empty.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.bmp
--------------------------------------------------------------------------------
/files/image/empty.dib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.dib
--------------------------------------------------------------------------------
/files/image/empty.emf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.emf
--------------------------------------------------------------------------------
/files/image/empty.exif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.exif
--------------------------------------------------------------------------------
/files/image/empty.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.gif
--------------------------------------------------------------------------------
/files/image/empty.heic:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.heic
--------------------------------------------------------------------------------
/files/image/empty.heif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.heif
--------------------------------------------------------------------------------
/files/image/empty.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.ico
--------------------------------------------------------------------------------
/files/image/empty.j2c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.j2c
--------------------------------------------------------------------------------
/files/image/empty.jfif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.jfif
--------------------------------------------------------------------------------
/files/image/empty.jp2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.jp2
--------------------------------------------------------------------------------
/files/image/empty.jpc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.jpc
--------------------------------------------------------------------------------
/files/image/empty.jpe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.jpe
--------------------------------------------------------------------------------
/files/image/empty.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.jpeg
--------------------------------------------------------------------------------
/files/image/empty.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.jpg
--------------------------------------------------------------------------------
/files/image/empty.jxr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.jxr
--------------------------------------------------------------------------------
/files/image/empty.pbm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.pbm
--------------------------------------------------------------------------------
/files/image/empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.png
--------------------------------------------------------------------------------
/files/image/empty.rle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.rle
--------------------------------------------------------------------------------
/files/image/empty.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.tga
--------------------------------------------------------------------------------
/files/image/empty.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.tif
--------------------------------------------------------------------------------
/files/image/empty.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.tiff
--------------------------------------------------------------------------------
/files/image/empty.wdp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.wdp
--------------------------------------------------------------------------------
/files/image/empty.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.webp
--------------------------------------------------------------------------------
/files/image/empty.wmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/image/empty.wmp
--------------------------------------------------------------------------------
/files/sheet/empty.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/sheet/empty.ods
--------------------------------------------------------------------------------
/files/sheet/empty.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/sheet/empty.xlsx
--------------------------------------------------------------------------------
/files/slide/empty.odp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/slide/empty.odp
--------------------------------------------------------------------------------
/files/slide/empty.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/slide/empty.pptx
--------------------------------------------------------------------------------
/files/archive/empty.7zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.7zip
--------------------------------------------------------------------------------
/files/archive/empty.bz2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.bz2
--------------------------------------------------------------------------------
/files/archive/empty.bzip2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.bzip2
--------------------------------------------------------------------------------
/files/archive/empty.gzip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.gzip
--------------------------------------------------------------------------------
/files/archive/empty.kmz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.kmz
--------------------------------------------------------------------------------
/files/archive/empty.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/archive/empty.nupkg
--------------------------------------------------------------------------------
/files/document/empty.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/document/empty.docx
--------------------------------------------------------------------------------
/files/document/empty.odt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerifyTests/EmptyFiles/HEAD/files/document/empty.odt
--------------------------------------------------------------------------------
/src/EmptyFiles/IsTextFile.cs:
--------------------------------------------------------------------------------
1 | namespace EmptyFiles;
2 |
3 | public delegate bool IsTextFile(CharSpan path);
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.suo
2 | *.user
3 | bin/
4 | obj/
5 | .vs/
6 | *.DotSettings.user
7 | .idea/
8 | *.received.*
9 | nugets/
--------------------------------------------------------------------------------
/src/Tests/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using EmptyFiles;
2 | global using NUnit.Framework;
3 | global using System.Collections.Immutable;
--------------------------------------------------------------------------------
/src/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "10.0.101",
4 | "allowPrerelease": true,
5 | "rollForward": "latestFeature"
6 | }
7 | }
--------------------------------------------------------------------------------
/index/empty.pcx:
--------------------------------------------------------------------------------
1 |
2 | ` `
--------------------------------------------------------------------------------
/src/EmptyFiles/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using System.Diagnostics.CodeAnalysis;
2 | global using System.Collections.Frozen;
3 | global using System.Text;
--------------------------------------------------------------------------------
/files/image/empty.pcx:
--------------------------------------------------------------------------------
1 |
2 | ` `
--------------------------------------------------------------------------------
/index/empty.dds:
--------------------------------------------------------------------------------
1 | DDS |
2 | DXT1
--------------------------------------------------------------------------------
/files/image/empty.dds:
--------------------------------------------------------------------------------
1 | DDS |
2 | DXT1
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: nuget
4 | directory: "/src"
5 | schedule:
6 | interval: daily
7 | open-pull-requests-limit: 10
8 |
--------------------------------------------------------------------------------
/src/EmptyFiles/Category.cs:
--------------------------------------------------------------------------------
1 | namespace EmptyFiles;
2 |
3 | public enum Category
4 | {
5 | Archive,
6 | Document,
7 | Image,
8 | Sheet,
9 | Slide,
10 | Binary
11 | }
--------------------------------------------------------------------------------
/src/mdsnippets.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/SimonCropp/MarkdownSnippets/master/schema.json",
3 | "TocExcludes": [ "NuGet package", "Release Notes", "Icon" ],
4 | "MaxWidth": 100,
5 | "Convention": "InPlaceOverwrite"
6 | }
--------------------------------------------------------------------------------
/index/empty.pdf:
--------------------------------------------------------------------------------
1 | %PDF-1.0
2 | 1 0 obj<>endobj 2 0 obj<>endobj 3 0 obj<>endobj
3 | xref
4 | 0 4
5 | 0000000000 65535 f
6 | 0000000010 00000 n
7 | 0000000053 00000 n
8 | 0000000102 00000 n
9 | trailer<>
10 | startxref
11 | 149
12 | %EOF
--------------------------------------------------------------------------------
/files/document/empty.pdf:
--------------------------------------------------------------------------------
1 | %PDF-1.0
2 | 1 0 obj<>endobj 2 0 obj<>endobj 3 0 obj<>endobj
3 | xref
4 | 0 4
5 | 0000000000 65535 f
6 | 0000000010 00000 n
7 | 0000000053 00000 n
8 | 0000000102 00000 n
9 | trailer<>
10 | startxref
11 | 149
12 | %EOF
--------------------------------------------------------------------------------
/src/EmptyFiles.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/src/EmptyFiles.Tool/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly: InternalsVisibleTo("Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e191859fcd1deee68b96927c170783ced0c9a471a6424a0a011cfd31156a49dd73c4ad4a88b995fb918c0b43e0c005ef5fb72d53a328a64bde825cb5f2e4c53d66f69fcbb87d6737128b98e677a42091974b5f56093123a2dd6bc738af751b101d41c4f7a996e217b61967a3aa1ae7bc791d19c1cbeef47f0cdd20d288dff1a3")]
--------------------------------------------------------------------------------
/src/Tests/ImmutableVersionTests.cs:
--------------------------------------------------------------------------------
1 | #if NETFRAMEWORK
2 |
3 | public class ImmutableVersionTests
4 | {
5 | // work around https://github.com/orgs/VerifyTests/discussions/1366
6 | [Test]
7 | public void AssertVersion()
8 | {
9 | var assemblyName = typeof(ImmutableDictionary).Assembly.GetName();
10 | AreEqual(new Version(8, 0, 0, 0), assemblyName.Version);
11 | }
12 | }
13 |
14 | #endif
--------------------------------------------------------------------------------
/.github/workflows/merge-dependabot.yml:
--------------------------------------------------------------------------------
1 | name: merge-dependabot
2 | on:
3 | pull_request:
4 | jobs:
5 | automerge:
6 | runs-on: ubuntu-latest
7 | if: github.actor == 'dependabot[bot]'
8 | steps:
9 | - name: Dependabot Auto Merge
10 | uses: ahmadnassri/action-dependabot-auto-merge@v2.6.6
11 | with:
12 | target: minor
13 | github-token: ${{ secrets.dependabot }}
14 | command: squash and merge
--------------------------------------------------------------------------------
/docs/zzz.include.md:
--------------------------------------------------------------------------------
1 | ### Entity Framework Extensions
2 |
3 | [Entity Framework Extensions](https://entityframework-extensions.net/?utm_source=simoncropp&utm_medium=EmptyFiles) is a major sponsor and is proud to contribute to the development this project.
4 |
5 | [](https://entityframework-extensions.net/?utm_source=simoncropp&utm_medium=EmptyFiles)
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text
2 | *.snk binary
3 | *.png binary
4 |
5 | /files/** binary
6 | /files/**/*.* binary
7 | /files/*.* binary
8 | /index/** binary
9 | /index/*.* binary
10 |
11 | *.verified.txt text eol=lf working-tree-encoding=UTF-8
12 | *.verified.xml text eol=lf working-tree-encoding=UTF-8
13 | *.verified.json text eol=lf working-tree-encoding=UTF-8
14 |
15 | .editorconfig text eol=lf working-tree-encoding=UTF-8
16 | *.sln.DotSettings text eol=lf working-tree-encoding=UTF-8
17 | *.slnx.DotSettings text eol=lf working-tree-encoding=UTF-8
--------------------------------------------------------------------------------
/src/EmptyFiles.Tool/Program.cs:
--------------------------------------------------------------------------------
1 | using EmptyFiles;
2 |
3 | if (args.Length == 0)
4 | {
5 | Console.Error.Write("No input");
6 | return 1;
7 | }
8 |
9 | var arg = args[0];
10 |
11 | string path;
12 | if (arg.Any(_ => _ is
13 | '.' or
14 | '/' or
15 | '\\'))
16 | {
17 | path = arg;
18 | }
19 | else
20 | {
21 | path = $"empty.{arg}";
22 | }
23 |
24 | if (AllFiles.TryCreateFile(
25 | path,
26 | useEmptyStringForTextFiles: true))
27 | {
28 | return 0;
29 | }
30 |
31 | Console.Error.Write("Unknown extension");
32 | return 1;
--------------------------------------------------------------------------------
/src/EmptyFiles.slnx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/EmptyFiles/EmptyFile.cs:
--------------------------------------------------------------------------------
1 | namespace EmptyFiles;
2 |
3 | public class EmptyFile
4 | {
5 | public string Path { get; }
6 | public DateTime LastWriteTime { get; }
7 | public Category Category { get; }
8 |
9 | internal static EmptyFile Build(string file, Category category)
10 | {
11 | var writeTime = File.GetLastWriteTime(file);
12 | return new(file, writeTime, category);
13 | }
14 |
15 | public EmptyFile(string path, in DateTime lastWriteTime, in Category category)
16 | {
17 | Guard.AgainstNullOrEmpty(path);
18 | Path = path;
19 | LastWriteTime = lastWriteTime;
20 | Category = category;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Tests/Size.cs:
--------------------------------------------------------------------------------
1 | static class Size
2 | {
3 | static string[] SizeSuffixes =
4 | [
5 | "bytes",
6 | "KB",
7 | "MB"
8 | ];
9 |
10 | public static string Suffix(long value)
11 | {
12 | if (value == 0)
13 | {
14 | return "0 bytes";
15 | }
16 |
17 | var mag = (int) Math.Log(value, 1024);
18 |
19 | var adjustedSize = (decimal) value / (1L << (mag * 10));
20 |
21 | if (Math.Round(adjustedSize, 1) >= 1000)
22 | {
23 | mag += 1;
24 | adjustedSize /= 1024;
25 | }
26 |
27 | return $"{adjustedSize:0.#} {SizeSuffixes[mag]}";
28 | }
29 | }
--------------------------------------------------------------------------------
/src/EmptyFiles/AssemblyLocation.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable IL3000
2 |
3 | static class AssemblyLocation
4 | {
5 | static AssemblyLocation()
6 | {
7 | var assembly = typeof(AssemblyLocation).Assembly;
8 | #if NET5_0_OR_GREATER
9 | Path = assembly.Location;
10 | #else
11 | var uri = new UriBuilder(assembly.CodeBase);
12 | Path = Uri.UnescapeDataString(uri.Path);
13 | #endif
14 |
15 | if (string.IsNullOrWhiteSpace(Path))
16 | {
17 | Path = AppContext.BaseDirectory;
18 | }
19 |
20 | Directory = System.IO.Path.GetDirectoryName(Path)!;
21 | }
22 |
23 | public static string Path;
24 |
25 | public static string Directory;
26 | }
--------------------------------------------------------------------------------
/src/EmptyFiles/EmptyFileTargets.md:
--------------------------------------------------------------------------------
1 | How it works:
2 |
3 | 1. Inputs="$(MSBuildThisFileFile)" - Tracks the package file timestamp
4 | 2. Outputs="$(EmptyFilesMarker)" - Tracks a marker file in the output directory
5 | 3. MSBuild automatically skips the target if all outputs are newer than all inputs
6 | 4. SkipUnchangedFiles="true" - Additional optimization to skip individual unchanged files
7 | 5. Touch - Updates the marker file timestamp after successful copy
8 |
9 | This will only copy files when:
10 |
11 | 1. The targets is newer than the marker file, OR
12 | 2. The marker file doesn't exist (first build/clean build)
13 |
14 | Benefits:
15 |
16 | * Dramatically reduces IO on incremental builds
17 | * Works with dotnet clean (removes marker file)
18 | * Still respects individual file changes via SkipUnchangedFiles
19 |
--------------------------------------------------------------------------------
/.github/workflows/on-push-do-doco.yml:
--------------------------------------------------------------------------------
1 | name: on-push-do-doco
2 | on:
3 | push:
4 | jobs:
5 | release:
6 | runs-on: windows-latest
7 | steps:
8 | - uses: actions/checkout@v4
9 | - name: Run MarkdownSnippets
10 | run: |
11 | dotnet tool install --global MarkdownSnippets.Tool
12 | mdsnippets ${GITHUB_WORKSPACE}
13 | shell: bash
14 | - name: Push changes
15 | run: |
16 | git config --local user.email "action@github.com"
17 | git config --local user.name "GitHub Action"
18 | git commit -m "Doco changes" -a || echo "nothing to commit"
19 | remote="https://${GITHUB_ACTOR}:${{secrets.GITHUB_TOKEN}}@github.com/${GITHUB_REPOSITORY}.git"
20 | branch="${GITHUB_REF:11}"
21 | git push "${remote}" ${branch} || echo "nothing to push"
22 | shell: bash
--------------------------------------------------------------------------------
/src/nuget.md:
--------------------------------------------------------------------------------
1 | [Documentation](https://github.com/VerifyTests/EmptyFiles)
2 |
3 | A collection of minimal binary files.
4 |
5 | **See [Milestones](https://github.com/VerifyTests/EmptyFiles/milestones?state=closed) for release notes.**
6 |
7 |
8 | ## Sponsors
9 |
10 |
11 | ### Entity Framework Extensions
12 |
13 | [Entity Framework Extensions](https://entityframework-extensions.net/?utm_source=simoncropp&utm_medium=EmptyFiles) is a major sponsor and is proud to contribute to the development this project.
14 |
15 | [](https://entityframework-extensions.net/?utm_source=simoncropp&utm_medium=EmptyFiles)
16 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CS1591;CS0649;NU5119;NU1608;NU1109
5 | 8.17.1
6 | preview
7 | 1.0.0
8 | A collection of minimal binary files.
9 | false
10 | true
11 | true
12 | true
13 | true
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 7
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Set to true to ignore issues in a milestone (defaults to false)
6 | exemptMilestones: true
7 | # Comment to post when marking an issue as stale. Set to `false` to disable
8 | markComment: >
9 | This issue has been automatically marked as stale because it has not had
10 | recent activity. It will be closed if no further activity occurs. Thank you
11 | for your contributions.
12 | # Comment to post when closing a stale issue. Set to `false` to disable
13 | closeComment: false
14 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
15 | pulls:
16 | daysUntilStale: 30
17 | exemptLabels:
18 | - Question
19 | - Bug
20 | - Feature
21 | - Improvement
--------------------------------------------------------------------------------
/src/EmptyFiles.slnx.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | ..\Shared.sln.DotSettings
3 | True
4 | True
5 | 1
6 |
--------------------------------------------------------------------------------
/src/Tests/IndexWriter.cs:
--------------------------------------------------------------------------------
1 | #if NET9_0
2 | public class IndexWriter
3 | {
4 | static List> files = null!;
5 |
6 | [ModuleInitializer]
7 | public static void Init() =>
8 | files = AllFiles
9 | .Files.OrderBy(_ => _.Key)
10 | .ToList();
11 | [Test]
12 | public void CreateIndex() =>
13 | InnerCreateIndex();
14 |
15 | static void InnerCreateIndex([CallerFilePath] string filePath = "")
16 | {
17 | var rootDirectory = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(filePath)!, @"..\..\"));
18 | var indexPath = Path.Combine(rootDirectory, "index");
19 | Directory.CreateDirectory(indexPath);
20 | foreach (var toDelete in Directory.EnumerateFiles(indexPath))
21 | {
22 | File.Delete(toDelete);
23 | }
24 |
25 | foreach (var (key, value) in files)
26 | {
27 | File.Copy(value.Path, Path.Combine(indexPath, $"empty{key}"));
28 | }
29 | }
30 | }
31 | #endif
--------------------------------------------------------------------------------
/src/Tests/Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net48
5 | net8.0;net9.0;net10.0;$(TargetFrameworks)
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | true
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/EmptyFiles/Guard.cs:
--------------------------------------------------------------------------------
1 | static class Guard
2 | {
3 | public static void FileExists(string path, [CallerArgumentExpression("path")] string argumentName = "")
4 | {
5 | AgainstNullOrEmpty(argumentName, path);
6 | if (!File.Exists(path))
7 | {
8 | throw new ArgumentException($"File not found. Path: {path}");
9 | }
10 | }
11 |
12 | public static void AgainstNullOrEmpty(string value, [CallerArgumentExpression("value")] string argumentName = "")
13 | {
14 | if (string.IsNullOrWhiteSpace(value))
15 | {
16 | throw new ArgumentNullException(argumentName);
17 | }
18 | }
19 |
20 | public static string ValidExtension(string extension, [CallerArgumentExpression(nameof(extension))] string argumentName = "")
21 | {
22 | if (extension.Length == 0)
23 | {
24 | throw new ArgumentNullException(argumentName);
25 | }
26 |
27 | if (extension.StartsWith('.'))
28 | {
29 | return extension;
30 | }
31 |
32 | return $".{extension}";
33 | }
34 | }
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Simon Cropp
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 |
--------------------------------------------------------------------------------
/src/Tests/SolutionDirectoryFinder.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | static class SolutionDirectoryFinder
4 | {
5 | public static string Find([CallerFilePath] string testFile = "")
6 | {
7 | var testDirectory = Path.GetDirectoryName(testFile)!;
8 | if (!TryFind(testDirectory, out var solutionDirectory))
9 | {
10 | throw new("Could not find solution directory");
11 | }
12 |
13 | return solutionDirectory;
14 | }
15 |
16 | public static bool TryFind(string testDirectory, [NotNullWhen(true)] out string? path)
17 | {
18 | var currentDirectory = testDirectory;
19 | do
20 | {
21 | if (Directory
22 | .GetFiles(currentDirectory, "*.slnx").Length != 0)
23 | {
24 | path = currentDirectory;
25 | return true;
26 | }
27 |
28 | var parent = Directory.GetParent(currentDirectory);
29 | if (parent == null)
30 | {
31 | path = null;
32 | return false;
33 | }
34 |
35 | currentDirectory = parent.FullName;
36 | } while (true);
37 | }
38 | }
--------------------------------------------------------------------------------
/src/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
20 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/EmptyFiles.Tool/EmptyFiles.Tool.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net10.0
5 | emptyfile
6 | emptyfile
7 | EmptyFiles.Tool
8 | True
9 | .NET Core Global Tool for creating minimal binary files
10 | true
11 | $(NoWarn);NU5118
12 | LatestMajor
13 |
14 |
15 |
16 |
17 |
18 | true
19 | tools\net10.0\any\EmptyFiles
20 |
21 |
22 | EmptyFiles\%(RecursiveDir)%(Filename)%(Extension)
23 | PreserveNewest
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/appveyor.yml:
--------------------------------------------------------------------------------
1 | image:
2 | - Visual Studio 2022
3 | # - macOS
4 | # - Ubuntu
5 | environment:
6 | DOTNET_NOLOGO: true
7 | DOTNET_CLI_TELEMETRY_OPTOUT: true
8 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
9 | build_script:
10 | - pwsh: |
11 | if ($isWindows) {
12 | Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile "./dotnet-install.ps1"
13 | ./dotnet-install.ps1 -JSonFile src/global.json -Architecture x64 -InstallDir 'C:\Program Files\dotnet'
14 | }
15 | if ($isMacOS) {
16 | Invoke-WebRequest "https://dot.net/v1/dotnet-install.sh" -OutFile "./dotnet-install.sh"
17 | sudo chmod u+x dotnet-install.sh
18 | sudo ./dotnet-install.sh --jsonfile src/global.json --architecture x64 --install-dir '/usr/local/share/dotnet'
19 | sudo ./dotnet-install.sh --version 9.0.306 --architecture x64 --install-dir '/usr/local/share/dotnet'
20 | }
21 | if ($isLinux) {
22 | Invoke-WebRequest "https://dot.net/v1/dotnet-install.sh" -OutFile "./dotnet-install.sh"
23 | sudo chmod u+x dotnet-install.sh
24 | sudo ./dotnet-install.sh --jsonfile src/global.json --architecture x64 --install-dir '/usr/share/dotnet'
25 | }
26 | - dotnet build src --configuration Release
27 | - dotnet test src --configuration Release --no-build --no-restore
28 | test: off
29 | artifacts:
30 | - path: nugets\*.nupkg
--------------------------------------------------------------------------------
/src/extensions.include.md:
--------------------------------------------------------------------------------
1 |
2 | ### Archive
3 |
4 | * .7z (32 bytes)
5 | * .7zip (32 bytes)
6 | * .bz2 (14 bytes)
7 | * .bzip2 (14 bytes)
8 | * .gz (29 bytes)
9 | * .gzip (29 bytes)
10 | * .kmz (292 bytes)
11 | * .nupkg (1.8 KB)
12 | * .tar (1.5 KB)
13 | * .xz (32 bytes)
14 | * .zip (22 bytes)
15 |
16 | ### Document
17 |
18 | * .docx (1.9 KB)
19 | * .odt (2.2 KB)
20 | * .pdf (280 bytes)
21 | * .rtf (6 bytes)
22 |
23 | ### Image
24 |
25 | * .avif (298 bytes)
26 | * .bmp (58 bytes)
27 | * .dds (136 bytes)
28 | * .dib (58 bytes)
29 | * .emf (620 bytes)
30 | * .exif (734 bytes)
31 | * .gif (799 bytes)
32 | * .heic (3.2 KB)
33 | * .heif (209 bytes)
34 | * .ico (70 bytes)
35 | * .j2c (270 bytes)
36 | * .jfif (734 bytes)
37 | * .jp2 (354 bytes)
38 | * .jpc (270 bytes)
39 | * .jpe (734 bytes)
40 | * .jpeg (734 bytes)
41 | * .jpg (734 bytes)
42 | * .jxr (300 bytes)
43 | * .pbm (8 bytes)
44 | * .pcx (131 bytes)
45 | * .pgm (12 bytes)
46 | * .png (119 bytes)
47 | * .ppm (14 bytes)
48 | * .rle (58 bytes)
49 | * .tga (543 bytes)
50 | * .tif (250 bytes)
51 | * .tiff (250 bytes)
52 | * .wdp (300 bytes)
53 | * .webp (228 bytes)
54 | * .wmp (300 bytes)
55 |
56 | ### Sheet
57 |
58 | * .ods (2.7 KB)
59 | * .xlsx (4.5 KB)
60 |
61 | ### Slide
62 |
63 | * .odp (7.8 KB)
64 | * .pptx (13.3 KB)
65 |
66 | ### Binary
67 |
68 | * .bin (0 bytes)
69 |
--------------------------------------------------------------------------------
/index/empty.tar:
--------------------------------------------------------------------------------
1 | empty 0100777 0000000 0000000 00000000000 13602262730 007064 0 ustar 00
--------------------------------------------------------------------------------
/files/archive/empty.tar:
--------------------------------------------------------------------------------
1 | empty 0100777 0000000 0000000 00000000000 13602262730 007064 0 ustar 00
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: How to raise feature requests
4 | ---
5 |
6 |
7 | Note: New issues raised, where it is clear the submitter has not read the issue template, are likely to be closed with "please read the issue template". Please don't take offense at this. It is simply a time management decision. If someone raises an issue, and can't be bothered to spend the time to read the issue template, then the project maintainers should not be expected to spend the time to read the submitted issue. Often too much time is spent going back and forth in issue comments asking for information that is outlined in the issue template.
8 |
9 | If you are certain the feature will be accepted, it is better to raise a [Pull Request (PR)](https://help.github.com/articles/about-pull-requests/).
10 |
11 | If you are uncertain if the feature will be accepted, outline the proposal below to confirm it is viable, prior to raising a PR that implements the feature.
12 |
13 | Note that even if the feature is a good idea and viable, it may not be accepted since the ongoing effort in maintaining the feature may outweigh the benefit it delivers.
14 |
15 |
16 | #### Is the feature request related to a problem
17 |
18 | A clear and concise description of what the problem is.
19 |
20 |
21 | #### Describe the solution
22 |
23 | A clear and concise proposal of how you intend to implement the feature.
24 |
25 |
26 | #### Describe alternatives considered
27 |
28 | A clear and concise description of any alternative solutions or features you've considered.
29 |
30 |
31 | #### Additional context
32 |
33 | Add any other context about the feature request here.
34 |
--------------------------------------------------------------------------------
/src/Tests/ContentTypesTests.cs:
--------------------------------------------------------------------------------
1 | public class ContentTypesTests
2 | {
3 | [Test]
4 | public void TryGetExtension()
5 | {
6 | True(ContentTypes.TryGetExtension("application/json", out var extension));
7 | AreEqual("json", extension);
8 | True(ContentTypes.TryGetExtension("foo/bar+json", out extension));
9 | AreEqual("json", extension);
10 | True(ContentTypes.TryGetExtension("text/html; charset=utf-8", out extension));
11 | AreEqual("html", extension);
12 | True(ContentTypes.TryGetExtension("foo/bin", out extension));
13 | AreEqual("bin", extension);
14 | }
15 |
16 | [Test]
17 | public void TryGetMediaType()
18 | {
19 | True(ContentTypes.TryGetMediaType("json", out var media));
20 | AreEqual("application/json", media);
21 | True(ContentTypes.TryGetMediaType("html", out media));
22 | AreEqual("text/html", media);
23 | True(ContentTypes.TryGetMediaType("bin", out media));
24 | AreEqual("application/octet-stream", media);
25 | }
26 |
27 | [Test]
28 | public void IsText()
29 | {
30 | True(ContentTypes.IsText("application/json", out var extension));
31 | AreEqual("json", extension);
32 | True(ContentTypes.IsText("text/html; charset=utf-8", out extension));
33 | AreEqual("html", extension);
34 | True(ContentTypes.IsText("foo/bar+json", out extension));
35 | AreEqual("json", extension);
36 | False(ContentTypes.IsText("foo/bin", out extension));
37 |
38 | True(ContentTypes.IsText("application/json"));
39 | True(ContentTypes.IsText("foo/bar+json"));
40 | False(ContentTypes.IsText("foo/bin"));
41 | }
42 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug fix
3 | about: Create a bug fix to help us improve
4 | ---
5 |
6 | Note: New issues raised, where it is clear the submitter has not read the issue template, are likely to be closed with "please read the issue template". Please don't take offense at this. It is simply a time management decision. If someone raises an issue, and can't be bothered to spend the time to read the issue template, then the project maintainers should not be expected to spend the time to read the submitted issue. Often too much time is spent going back and forth in issue comments asking for information that is outlined in the issue template.
7 |
8 |
9 | #### Preamble
10 |
11 | General questions may be better placed [StackOveflow](https://stackoverflow.com/).
12 |
13 | Where relevant, ensure you are using the current stable versions on your development stack. For example:
14 |
15 | * Visual Studio
16 | * [.NET SDK or .NET Core SDK](https://www.microsoft.com/net/download)
17 | * Any related NuGet packages
18 |
19 | Any code or stack traces must be properly formatted with [GitHub markdown](https://guides.github.com/features/mastering-markdown/).
20 |
21 |
22 | #### Describe the bug
23 |
24 | A clear and concise description of what the bug is. Include any relevant version information.
25 |
26 | A clear and concise description of what you expected to happen.
27 |
28 | Add any other context about the problem here.
29 |
30 |
31 | #### Minimal Repro
32 |
33 | Ensure you have replicated the bug in a minimal solution with the fewest moving parts. Often this will help point to the true cause of the problem. Upload this repro as part of the issue, preferably a public GitHub repository or a downloadable zip. The repro will allow the maintainers of this project to smoke test the any fix.
34 |
35 | #### Submit a PR that fixes the bug
36 |
37 | Submit a [Pull Request (PR)](https://help.github.com/articles/about-pull-requests/) that fixes the bug. Include in this PR a test that verifies the fix. If you were not able to fix the bug, a PR that illustrates your partial progress will suffice.
38 |
--------------------------------------------------------------------------------
/src/EmptyFiles/EmptyFiles.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net462;net472;net48
4 | $(TargetFrameworks);net6.0;net7.0;net8.0;net9.0;net10.0
5 | true
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | true
19 | files
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Tests/ExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | public class ExtensionsTests
2 | {
3 | [Test]
4 | public void IsText()
5 | {
6 | #region IsText
7 |
8 | True(FileExtensions.IsTextFile("file.txt"));
9 | False(FileExtensions.IsTextFile("file.bin"));
10 | True(FileExtensions.IsTextExtension(".txt"));
11 | False(FileExtensions.IsTextExtension(".bin"));
12 | True(FileExtensions.IsTextExtension("txt"));
13 | False(FileExtensions.IsTextExtension("bin"));
14 |
15 | #endregion
16 |
17 | False(FileExtensions.IsTextFile(".StartingWithDot"));
18 | False(FileExtensions.IsTextFile("NoExtension"));
19 |
20 | #region TextViaConvention
21 |
22 | True(FileExtensions.IsTextFile("c:/path/file.txtViaConvention"));
23 |
24 | #endregion
25 | }
26 |
27 | #region AddTextFileConvention
28 | [ModuleInitializer]
29 | public static void AddTextFileConvention() =>
30 | // Treat files ending with .txtViaConvention as text files
31 | FileExtensions.AddTextFileConvention(path => path.EndsWith(".txtViaConvention"));
32 |
33 | #endregion
34 |
35 | [Test]
36 | public void IsTextLegacy()
37 | {
38 | #pragma warning disable CS0618 // Type or member is obsolete
39 | True(FileExtensions.IsText("file.txt"));
40 | False(FileExtensions.IsText("file.bin"));
41 | True(FileExtensions.IsText("c:/file.txt"));
42 | False(FileExtensions.IsText("c:/file.bin"));
43 | True(FileExtensions.IsText(".txt"));
44 | True(FileExtensions.IsText("txt"));
45 | False(FileExtensions.IsText(".bin"));
46 | False(FileExtensions.IsText("bin"));
47 | #pragma warning restore CS0618 // Type or member is obsolete
48 | }
49 |
50 | [Test]
51 | public void AddTextExtension()
52 | {
53 | #region AddTextExtension
54 |
55 | FileExtensions.AddTextExtension(".ext1");
56 | True(FileExtensions.IsTextExtension(".ext1"));
57 | True(FileExtensions.IsTextFile("file.ext1"));
58 |
59 | #endregion
60 |
61 | FileExtensions.AddTextExtension("ext2");
62 | True(FileExtensions.IsTextExtension("ext2"));
63 | True(FileExtensions.IsTextFile("file.ext2"));
64 | }
65 |
66 | [Test]
67 | public void RemoveTextExtension()
68 | {
69 | #region RemoveTextExtension
70 |
71 | FileExtensions.AddTextExtension(".ext1");
72 | True(FileExtensions.IsTextExtension(".ext1"));
73 | FileExtensions.RemoveTextExtension(".ext1");
74 | False(FileExtensions.IsTextExtension(".ext1"));
75 |
76 | #endregion
77 |
78 | FileExtensions.AddTextExtension("ext1");
79 | True(FileExtensions.IsTextExtension("ext1"));
80 | FileExtensions.RemoveTextExtension("ext1");
81 | False(FileExtensions.IsTextExtension("ext1"));
82 | }
83 | }
--------------------------------------------------------------------------------
/code_of_conduct.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at simon.cropp@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/src/Tests/Tests.cs:
--------------------------------------------------------------------------------
1 | [TestFixture]
2 | public class Tests
3 | {
4 | [Test]
5 | public void CreateFile_overwrite_binary()
6 | {
7 | AllFiles.CreateFile("foo.bmp");
8 | AllFiles.CreateFile("foo.bmp");
9 | True(File.Exists("foo.bmp"));
10 | }
11 |
12 | [Test]
13 | public void CreateFile_NoDir_binary()
14 | {
15 | if (Directory.Exists("myTempDir"))
16 | {
17 | Directory.Delete("myTempDir", true);
18 | }
19 |
20 | AllFiles.CreateFile("myTempDir/foo.bmp");
21 | True(File.Exists("myTempDir/foo.bmp"));
22 | }
23 |
24 | [Test]
25 | public void CreateFile_preamble()
26 | {
27 | AllFiles.CreateFile("foo.txt", true);
28 |
29 | var preamble = Encoding.UTF8.GetPreamble();
30 | var bytes = File.ReadAllBytes("foo.txt");
31 | if (bytes.Length < preamble.Length ||
32 | preamble
33 | .Where((p, i) => p != bytes[i])
34 | .Any())
35 | {
36 | throw new ArgumentException("Not utf8-BOM");
37 | }
38 | }
39 |
40 | [Test]
41 | public void CreateFile_overwrite_txt()
42 | {
43 | AllFiles.CreateFile("foo.txt", true);
44 | AllFiles.CreateFile("foo.txt", true);
45 | True(File.Exists("foo.txt"));
46 | }
47 |
48 | [Test]
49 | public void CreateFile_NoDir_txt()
50 | {
51 | if (Directory.Exists("myTempDir"))
52 | {
53 | Directory.Delete("myTempDir", true);
54 | }
55 |
56 | AllFiles.CreateFile("myTempDir/foo.txt", true);
57 | True(File.Exists("myTempDir/foo.txt"));
58 | }
59 |
60 | [Test]
61 | public void TryCreateFile_overwrite_txt()
62 | {
63 | True(AllFiles.TryCreateFile("foo.txt", true));
64 | True(AllFiles.TryCreateFile("foo.txt", true));
65 | True(File.Exists("foo.txt"));
66 | }
67 |
68 | [Test]
69 | public void TryCreateFile_NoDir_txt()
70 | {
71 | if (Directory.Exists("myTempDir"))
72 | {
73 | Directory.Delete("myTempDir", true);
74 | }
75 |
76 | True(AllFiles.TryCreateFile("myTempDir/foo.txt", true));
77 | True(File.Exists("myTempDir/foo.txt"));
78 | }
79 |
80 | [Test]
81 | public void TryCreateFile_overwrite_binary()
82 | {
83 | True(AllFiles.TryCreateFile("foo.bmp"));
84 | True(AllFiles.TryCreateFile("foo.bmp"));
85 | True(File.Exists("foo.bmp"));
86 | }
87 |
88 | [Test]
89 | public void TryCreateFile_NoDir_binary()
90 | {
91 | if (Directory.Exists("myTempDir"))
92 | {
93 | Directory.Delete("myTempDir", true);
94 | }
95 |
96 | True(AllFiles.TryCreateFile("myTempDir/foo.bmp"));
97 | True(File.Exists("myTempDir/foo.bmp"));
98 | }
99 |
100 | [Test]
101 | public void Unknown_extension()
102 | {
103 | Throws(() => AllFiles.GetPathFor("txt"));
104 | False(AllFiles.TryGetPathFor("txt", out var result));
105 | Null(result);
106 | False(AllFiles.TryGetPathFor(".txt", out result));
107 | Null(result);
108 | False(AllFiles.TryCreateFile("foo.txt"));
109 | Null(result);
110 | Throws(() => AllFiles.GetPathFor(".txt"));
111 | Throws(() => AllFiles.CreateFile("foo.txt"));
112 | }
113 |
114 | [Test]
115 | public void GetPathFor()
116 | {
117 | #region GetPathFor
118 |
119 | var path = AllFiles.GetPathFor(".jpg");
120 |
121 | #endregion
122 |
123 | NotNull(path);
124 | True(File.Exists(path));
125 |
126 | path = AllFiles.GetPathFor("jpg");
127 | NotNull(path);
128 | True(File.Exists(path));
129 | }
130 |
131 | [Test]
132 | public void CreateFile()
133 | {
134 | var pathOfFileToCreate = "file.jpg";
135 | File.Delete(pathOfFileToCreate);
136 |
137 | #region CreateFile
138 |
139 | AllFiles.CreateFile(pathOfFileToCreate);
140 |
141 | #endregion
142 |
143 | True(File.Exists(pathOfFileToCreate));
144 | File.Delete(pathOfFileToCreate);
145 |
146 | AllFiles.CreateFile("foo.txt", true);
147 | True(File.Exists("foo.txt"));
148 | File.Delete("foo.txt");
149 |
150 | True(AllFiles.TryCreateFile(pathOfFileToCreate));
151 | True(File.Exists(pathOfFileToCreate));
152 | File.Delete(pathOfFileToCreate);
153 |
154 | False(AllFiles.TryCreateFile("foo.txt"));
155 | False(File.Exists("foo.txt"));
156 | File.Delete("foo.txt");
157 |
158 | True(AllFiles.TryCreateFile("foo.txt", true));
159 | True(File.Exists("foo.txt"));
160 | File.Delete("foo.txt");
161 | }
162 |
163 | [Test]
164 | public void IsEmptyFile()
165 | {
166 | #region IsEmptyFile
167 |
168 | var path = AllFiles.GetPathFor(".jpg");
169 | True(AllFiles.IsEmptyFile(path));
170 | var temp = Path.GetTempFileName();
171 | False(AllFiles.IsEmptyFile(temp));
172 |
173 | #endregion
174 |
175 | File.Delete(temp);
176 | }
177 |
178 | [Test]
179 | public void AllPaths()
180 | {
181 | IsNotEmpty(AllFiles.AllPaths);
182 |
183 | #region AllPaths
184 |
185 | foreach (var path in AllFiles.AllPaths)
186 | {
187 | Trace.WriteLine(path);
188 | }
189 |
190 | #endregion
191 | }
192 |
193 | static string ThisFile([CallerFilePath] string testFile = "") =>
194 | testFile;
195 |
196 | //[Test]
197 | #pragma warning disable CA1822
198 | public void UseFile()
199 | #pragma warning restore CA1822
200 | {
201 | var pathToFile = ThisFile();
202 |
203 | #region UseFile
204 |
205 | AllFiles.UseFile(Category.Document, pathToFile);
206 | IsTrue(AllFiles.DocumentPaths.Contains(pathToFile));
207 |
208 | #endregion
209 | }
210 |
211 | #if NET9_0
212 |
213 | [Test]
214 | public async Task WriteExtensions()
215 | {
216 | var md = Path.Combine(SolutionDirectoryFinder.Find(), "extensions.include.md");
217 | File.Delete(md);
218 | await using var writer = File.CreateText(md);
219 | await WriteCategory(writer, "Archive", AllFiles.Archives);
220 | await WriteCategory(writer, "Document", AllFiles.Documents);
221 | await WriteCategory(writer, "Image", AllFiles.Images);
222 | await WriteCategory(writer, "Sheet", AllFiles.Sheets);
223 | await WriteCategory(writer, "Slide", AllFiles.Slides);
224 | await WriteCategory(writer, "Binary", AllFiles.Binary);
225 | }
226 |
227 | static async Task WriteCategory(StreamWriter writer, string category, IReadOnlyDictionary files)
228 | {
229 | await writer.WriteLineAsync("");
230 | await writer.WriteLineAsync($"### {category}");
231 | await writer.WriteLineAsync("");
232 | foreach (var file in files.OrderBy(_ => _.Key))
233 | {
234 | var size = Size.Suffix(new FileInfo(file.Value.Path).Length);
235 | await writer.WriteLineAsync($" * {file.Key} ({size})");
236 | }
237 | }
238 |
239 | #endif
240 | }
--------------------------------------------------------------------------------
/src/EmptyFiles/ContentTypes.cs:
--------------------------------------------------------------------------------
1 | namespace EmptyFiles;
2 |
3 | public static class ContentTypes
4 | {
5 | static ContentTypes()
6 | {
7 | foreach (var (media, extension) in mediaToExtension)
8 | {
9 | extensionToMedia.TryAdd(extension, media);
10 | }
11 | }
12 |
13 | static Dictionary extensionToMedia = new(StringComparer.OrdinalIgnoreCase);
14 |
15 | public static bool IsText(string? mediaType) =>
16 | IsText(mediaType, out _);
17 |
18 | public static bool TryGetMediaType(string extension, [NotNullWhen(true)] out string? mediaType)
19 | {
20 | if (extension.StartsWith('.'))
21 | {
22 | extension = extension[1..];
23 | }
24 |
25 | return extensionToMedia.TryGetValue(extension, out mediaType);
26 | }
27 |
28 | public static bool IsText(string? mediaType, [NotNullWhen(true)] out string? extension)
29 | {
30 | if (TryGetExtension(mediaType, out extension))
31 | {
32 | if (FileExtensions.IsTextExtension(extension))
33 | {
34 | return true;
35 | }
36 | }
37 |
38 | extension = null;
39 | return false;
40 | }
41 |
42 | public static bool TryGetExtension(string? mediaType, [NotNullWhen(true)] out string? extension)
43 | {
44 | if (mediaType == null)
45 | {
46 | extension = null;
47 | return false;
48 | }
49 |
50 | var indexOf = mediaType.IndexOf(';');
51 | if(indexOf != -1)
52 | {
53 | mediaType = mediaType[..indexOf];
54 | }
55 |
56 | if (mediaToExtension.TryGetValue(mediaType, out extension))
57 | {
58 | return true;
59 | }
60 |
61 | var mediaTypeSpan = mediaType.AsSpan();
62 | var plusIndex = mediaTypeSpan.LastIndexOf('+');
63 |
64 | if (plusIndex > -1)
65 | {
66 | extension = mediaTypeSpan[(plusIndex + 1)..]
67 | .ToString();
68 | return true;
69 | }
70 |
71 | var slashIndex = mediaTypeSpan.LastIndexOf('/');
72 |
73 | if (slashIndex > -1)
74 | {
75 | extension = mediaTypeSpan[(slashIndex + 1)..]
76 | .ToString();
77 | return true;
78 | }
79 |
80 | return false;
81 | }
82 |
83 | static Dictionary mediaToExtension = new(StringComparer.OrdinalIgnoreCase)
84 | {
85 | //extra
86 | {
87 | "application/graphql", "gql"
88 | },
89 | {
90 | "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx"
91 | },
92 | {
93 | "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "dotx"
94 | },
95 | {
96 | "application/vnd.ms-word.document.macroEnabled.12", "docm"
97 | },
98 | {
99 | "application/vnd.ms-word.template.macroEnabled.12", "dotm"
100 | },
101 | {
102 | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx"
103 | },
104 | {
105 | "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "xltx"
106 | },
107 | {
108 | "application/vnd.ms-excel.sheet.macroEnabled.12", "xlsm"
109 | },
110 | {
111 | "application/vnd.ms-excel.template.macroEnabled.12", "xltm"
112 | },
113 | {
114 | "application/vnd.ms-excel.addin.macroEnabled.12", "xlam"
115 | },
116 | {
117 | "application/vnd.ms-excel.sheet.binary.macroEnabled.12", "xlsb"
118 | },
119 | {
120 | "application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx"
121 | },
122 | {
123 | "application/vnd.openxmlformats-officedocument.presentationml.template", "potx"
124 | },
125 | {
126 | "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "ppsx"
127 | },
128 | {
129 | "application/vnd.ms-powerpoint.addin.macroEnabled.12", "ppam"
130 | },
131 | {
132 | "application/vnd.ms-powerpoint.presentation.macroEnabled.12", "pptm"
133 | },
134 | {
135 | "application/vnd.ms-powerpoint.template.macroEnabled.12", "potm"
136 | },
137 | {
138 | "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", "ppsm"
139 | },
140 |
141 | {
142 | "application/fsharp-script", "fsx"
143 | },
144 | {
145 | "application/msaccess", "adp"
146 | },
147 | {
148 | "application/msword", "doc"
149 | },
150 | {
151 | "application/octet-stream", "bin"
152 | },
153 | {
154 | "application/onenote", "one"
155 | },
156 | {
157 | "application/postscript", "eps"
158 | },
159 | {
160 | "application/xml", "xml"
161 | },
162 | {
163 | "application/soap+xml", "xml"
164 | },
165 | {
166 | "application/step", "step"
167 | },
168 | {
169 | "application/vnd.ms-excel", "xls"
170 | },
171 | {
172 | "application/vnd.ms-powerpoint", "ppt"
173 | },
174 | {
175 | "application/vnd.ms-works", "wks"
176 | },
177 | {
178 | "application/vnd.visio", "vsd"
179 | },
180 | {
181 | "application/x-director", "dir"
182 | },
183 | {
184 | "application/x-msdos-program", "exe"
185 | },
186 | {
187 | "application/x-shockwave-flash", "swf"
188 | },
189 | {
190 | "application/x-x509-ca-cert", "cer"
191 | },
192 | {
193 | "application/x-zip-compressed", "zip"
194 | },
195 | {
196 | "application/xhtml+xml", "xhtml"
197 | },
198 | {
199 | "application/xrd+xml", "xml"
200 | },
201 | {
202 | "application/json", "json"
203 | },
204 | {
205 | "audio/aac", "aac"
206 | },
207 | {
208 | "audio/aiff", "aiff"
209 | },
210 | {
211 | "audio/basic", "snd"
212 | },
213 | {
214 | "audio/mid", "midi"
215 | },
216 | {
217 | "audio/mp4", "m4a"
218 | },
219 | {
220 | "audio/wav", "wav"
221 | },
222 | {
223 | "audio/x-m4a", "m4a"
224 | },
225 | {
226 | "audio/x-mpegurl", "m3u"
227 | },
228 | {
229 | "audio/x-pn-realaudio", "ra"
230 | },
231 | {
232 | "audio/x-smd", "smd"
233 | },
234 | {
235 | "image/bmp", "bmp"
236 | },
237 | {
238 | "image/heic", ".heic"
239 | },
240 | {
241 | "image/heic-sequence", "heics"
242 | },
243 | {
244 | "image/jpeg", "jpg"
245 | },
246 | {
247 | "image/gif", "gif"
248 | },
249 | {
250 | "image/pict", "pic"
251 | },
252 | {
253 | "image/png", "png"
254 | },
255 | {
256 | "image/x-png", "png"
257 | },
258 | {
259 | "image/svg+xml", "svg"
260 | },
261 | {
262 | "image/tiff", "tiff"
263 | },
264 | {
265 | "image/x-macpaint", "mac"
266 | },
267 | {
268 | "image/x-quicktime", "qti"
269 | },
270 | {
271 | "message/rfc822", "eml"
272 | },
273 | {
274 | "text/calendar", "ics"
275 | },
276 | {
277 | "text/html", "html"
278 | },
279 | {
280 | "text/htmx", "htmx"
281 | },
282 | {
283 | "text/javascript", "js"
284 | },
285 | {
286 | "text/plain", "txt"
287 | },
288 | {
289 | "text/scriptlet", "wsc"
290 | },
291 | {
292 | "text/xml", "xml"
293 | },
294 | {
295 | "text/csv", "csv"
296 | },
297 | {
298 | "video/3gpp", "3gp"
299 | },
300 | {
301 | "video/3gpp2", "3gp2"
302 | },
303 | {
304 | "video/mp4", "mp4"
305 | },
306 | {
307 | "video/mpeg", "mpg"
308 | },
309 | {
310 | "video/quicktime", "mov"
311 | },
312 | {
313 | "video/vnd.dlna.mpeg-tts", "m2t"
314 | },
315 | {
316 | "video/x-dv", "dv"
317 | },
318 | {
319 | "video/x-la-asf", "lsf"
320 | },
321 | {
322 | "video/x-ms-asf", "asf"
323 | },
324 | {
325 | "x-world/x-vrml", "xof"
326 | }
327 | };
328 | }
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | #
EmptyFiles
2 |
3 | [](https://github.com/orgs/VerifyTests/discussions)
4 | [](https://ci.appveyor.com/project/SimonCropp/EmptyFiles)
5 | [](https://www.nuget.org/packages/EmptyFiles/)
6 | [](https://www.nuget.org/packages/EmptyFiles.Tool/)
7 |
8 | A collection of minimal binary files.
9 |
10 | **See [Milestones](../../milestones?state=closed) for release notes.**
11 |
12 |
13 | ## Sponsors
14 |
15 |
16 | ### Entity Framework Extensions
17 |
18 | [Entity Framework Extensions](https://entityframework-extensions.net/?utm_source=simoncropp&utm_medium=EmptyFiles) is a major sponsor and is proud to contribute to the development this project.
19 |
20 | [](https://entityframework-extensions.net/?utm_source=simoncropp&utm_medium=EmptyFiles)
21 |
22 |
23 | ### JetBrains
24 |
25 | [](https://jb.gg/OpenSourceSupport)
26 |
27 |
28 | ## NuGet
29 |
30 | * https://nuget.org/packages/EmptyFiles/
31 | * https://nuget.org/packages/EmptyFiles.Tool/
32 |
33 |
34 | ## Files
35 |
36 | All files: https://github.com/VerifyTests/EmptyFiles/tree/main/files
37 |
38 |
39 |
40 | ### Archive
41 |
42 | * .7z (32 bytes)
43 | * .7zip (32 bytes)
44 | * .bz2 (14 bytes)
45 | * .bzip2 (14 bytes)
46 | * .gz (29 bytes)
47 | * .gzip (29 bytes)
48 | * .kmz (292 bytes)
49 | * .nupkg (1.8 KB)
50 | * .tar (1.5 KB)
51 | * .xz (32 bytes)
52 | * .zip (22 bytes)
53 |
54 | ### Document
55 |
56 | * .docx (1.9 KB)
57 | * .odt (2.2 KB)
58 | * .pdf (280 bytes)
59 | * .rtf (6 bytes)
60 |
61 | ### Image
62 |
63 | * .avif (298 bytes)
64 | * .bmp (58 bytes)
65 | * .dds (136 bytes)
66 | * .dib (58 bytes)
67 | * .emf (620 bytes)
68 | * .exif (734 bytes)
69 | * .gif (799 bytes)
70 | * .heic (3.2 KB)
71 | * .heif (209 bytes)
72 | * .ico (70 bytes)
73 | * .j2c (270 bytes)
74 | * .jfif (734 bytes)
75 | * .jp2 (354 bytes)
76 | * .jpc (270 bytes)
77 | * .jpe (734 bytes)
78 | * .jpeg (734 bytes)
79 | * .jpg (734 bytes)
80 | * .jxr (300 bytes)
81 | * .pbm (8 bytes)
82 | * .pcx (131 bytes)
83 | * .pgm (12 bytes)
84 | * .png (119 bytes)
85 | * .ppm (14 bytes)
86 | * .rle (58 bytes)
87 | * .tga (543 bytes)
88 | * .tif (250 bytes)
89 | * .tiff (250 bytes)
90 | * .wdp (300 bytes)
91 | * .webp (228 bytes)
92 | * .wmp (300 bytes)
93 |
94 | ### Sheet
95 |
96 | * .ods (2.7 KB)
97 | * .xlsx (4.5 KB)
98 |
99 | ### Slide
100 |
101 | * .odp (7.8 KB)
102 | * .pptx (13.3 KB)
103 |
104 | ### Binary
105 |
106 | * .bin (0 bytes)
107 |
108 |
109 | ## Consuming files as a web resource
110 |
111 | Files can be consumed as a web resource using the following url:
112 |
113 | ```
114 | https://github.com/VerifyTests/EmptyFiles/raw/main/index/empty.{extension}
115 | ```
116 |
117 | So for example to consume a jpg use
118 |
119 | ```
120 | https://github.com/VerifyTests/EmptyFiles/raw/main/index/empty.jpg
121 | ```
122 |
123 | A 404 will result for non-existent files.
124 |
125 |
126 | ## Tool Usage
127 |
128 |
129 | ### Installation
130 |
131 | Ensure [dotnet CLI is installed](https://docs.microsoft.com/en-us/dotnet/core/tools/).
132 |
133 | Install [EmptyFiles.Tool](https://nuget.org/packages/EmptyFiles.Tool/)
134 |
135 | ```ps
136 | dotnet tool install -g EmptyFiles.Tool
137 | ```
138 |
139 |
140 | ### Extension only Usage
141 |
142 | ```
143 | emptyfile bmp
144 | ```
145 |
146 | Creates `{CurrentDirectory}/empty.bmp`
147 |
148 |
149 | ### File Usage
150 |
151 | ```
152 | emptyfile myfile.bmp
153 | ```
154 |
155 | Creates `{CurrentDirectory}/myfile.bmp`
156 |
157 |
158 | ### Path Usage
159 |
160 | ```
161 | emptyfile path/myfile.bmp
162 | ```
163 |
164 | Creates `path/myfile.bmp`
165 |
166 |
167 | ## Library Usage
168 |
169 |
170 | ### CreateFile
171 |
172 | Creates a new empty file
173 |
174 |
175 |
176 | ```cs
177 | AllFiles.CreateFile(pathOfFileToCreate);
178 | ```
179 | snippet source | anchor
180 |
181 |
182 | Throws an exception if the extension is not known. There is also a `TryCreateFile` that will return false if the extension is not known.
183 |
184 | Use the optional `useEmptyStringForTextFiles` to create a empty text file if the extension is text. The file will be UTF8 no BOM as per https://www.unicode.org/versions/Unicode5.0.0/ch02.pdf "Use of a BOM is neither required nor recommended for UTF-8".
185 |
186 |
187 | ### GetPathFor
188 |
189 | Gets the path to an empty file for a given extension
190 |
191 |
192 |
193 | ```cs
194 | var path = AllFiles.GetPathFor(".jpg");
195 | ```
196 | snippet source | anchor
197 |
198 |
199 | Throws an exception if the extension is not known. There is also a `TryGetPathFor` that will return false if the extension is not known.
200 |
201 |
202 | ### IsEmptyFile
203 |
204 | Returns true if the target file is an empty file.
205 |
206 |
207 |
208 | ```cs
209 | var path = AllFiles.GetPathFor(".jpg");
210 | True(AllFiles.IsEmptyFile(path));
211 | var temp = Path.GetTempFileName();
212 | False(AllFiles.IsEmptyFile(temp));
213 | ```
214 | snippet source | anchor
215 |
216 |
217 |
218 | ### AllPaths
219 |
220 | Enumerates all empty files
221 |
222 |
223 |
224 | ```cs
225 | foreach (var path in AllFiles.AllPaths)
226 | {
227 | Trace.WriteLine(path);
228 | }
229 | ```
230 | snippet source | anchor
231 |
232 |
233 |
234 | ### UseFile
235 |
236 | Use or replace a file
237 |
238 |
239 |
240 | ```cs
241 | AllFiles.UseFile(Category.Document, pathToFile);
242 | IsTrue(AllFiles.DocumentPaths.Contains(pathToFile));
243 | ```
244 | snippet source | anchor
245 |
246 |
247 |
248 | ### Extensions helper
249 |
250 |
251 | #### IsText
252 |
253 | https://github.com/sindresorhus/text-extensions/blob/master/text-extensions.json
254 |
255 |
256 |
257 | ```cs
258 | True(FileExtensions.IsTextFile("file.txt"));
259 | False(FileExtensions.IsTextFile("file.bin"));
260 | True(FileExtensions.IsTextExtension(".txt"));
261 | False(FileExtensions.IsTextExtension(".bin"));
262 | True(FileExtensions.IsTextExtension("txt"));
263 | False(FileExtensions.IsTextExtension("bin"));
264 | ```
265 | snippet source | anchor
266 |
267 |
268 |
269 | #### AddTextExtension
270 |
271 |
272 |
273 | ```cs
274 | FileExtensions.AddTextExtension(".ext1");
275 | True(FileExtensions.IsTextExtension(".ext1"));
276 | True(FileExtensions.IsTextFile("file.ext1"));
277 | ```
278 | snippet source | anchor
279 |
280 |
281 |
282 | #### RemoveTextExtension
283 |
284 |
285 |
286 | ```cs
287 | FileExtensions.AddTextExtension(".ext1");
288 | True(FileExtensions.IsTextExtension(".ext1"));
289 | FileExtensions.RemoveTextExtension(".ext1");
290 | False(FileExtensions.IsTextExtension(".ext1"));
291 | ```
292 | snippet source | anchor
293 |
294 |
295 |
296 | #### AddTextFileConvention
297 |
298 | `AddTextFileConvention` allows the use of a convention based text file detection via a callback.
299 |
300 | At app startup add a convention using `FileExtensions.AddTextFileConvention`:
301 |
302 |
303 |
304 | ```cs
305 | [ModuleInitializer]
306 | public static void AddTextFileConvention() =>
307 | // Treat files ending with .txtViaConvention as text files
308 | FileExtensions.AddTextFileConvention(path => path.EndsWith(".txtViaConvention"));
309 | ```
310 | snippet source | anchor
311 |
312 |
313 | Then any call to `FileExtensions.IsTextFile` will, in addition to checking the known text extensions, also check if any of the added text contentions return true.
314 |
315 |
316 |
317 | ```cs
318 | True(FileExtensions.IsTextFile("c:/path/file.txtViaConvention"));
319 | ```
320 | snippet source | anchor
321 |
322 |
323 | An alternative approach to a text file convention would be to check if a file has a preamble that matches an known text encoding.
324 |
325 |
326 | ## Icon
327 |
328 | [Hollow](https://thenounproject.com/term/hollow/51835/) designed by [Michael Senkow](https://thenounproject.com/mhsenkow/) from [The Noun Project](https://thenounproject.com).
329 |
--------------------------------------------------------------------------------
/src/EmptyFiles/AllFiles.cs:
--------------------------------------------------------------------------------
1 | namespace EmptyFiles;
2 |
3 | public static class AllFiles
4 | {
5 | public static FrozenDictionary Files => files;
6 |
7 | static FrozenDictionary files;
8 |
9 | public static FrozenDictionary Archives => archives;
10 |
11 | static FrozenDictionary archives;
12 |
13 | public static FrozenDictionary Documents => documents;
14 |
15 | static FrozenDictionary documents;
16 |
17 | public static FrozenDictionary Images => images;
18 |
19 | static FrozenDictionary images;
20 |
21 | public static FrozenDictionary Sheets => sheets;
22 |
23 | static FrozenDictionary sheets;
24 |
25 | public static FrozenDictionary Binary => binary;
26 |
27 | static FrozenDictionary binary;
28 |
29 | public static FrozenDictionary Slides => slides;
30 |
31 | static FrozenDictionary slides;
32 |
33 | static AllFiles()
34 | {
35 | var directory = FindEmptyFilesDirectory();
36 |
37 | archives = AddCategory(archiveExtensions, Category.Archive, directory);
38 | documents = AddCategory(documentExtensions, Category.Document, directory);
39 | images = AddCategory(imageExtensions, Category.Image, directory);
40 | sheets = AddCategory(sheetExtensions, Category.Sheet, directory);
41 | slides = AddCategory(slideExtensions, Category.Slide, directory);
42 | binary = AddCategory(binaryExtensions, Category.Binary, directory);
43 | var all = new Dictionary();
44 | Append(archives);
45 | Append(documents);
46 | Append(images);
47 | Append(sheets);
48 | Append(slides);
49 | Append(binary);
50 |
51 | files = all.ToFrozenDictionary();
52 |
53 | void Append(FrozenDictionary files)
54 | {
55 | foreach (var (key, value) in files)
56 | {
57 | all[key] = value;
58 | }
59 | }
60 | }
61 |
62 | static FrozenDictionary AddCategory(FrozenSet extensions, Category category, string emptyDirectory)
63 | {
64 | Dictionary items = [];
65 | var categoryDirectory = Path.Combine(
66 | emptyDirectory,
67 | category
68 | .ToString()
69 | .ToLowerInvariant());
70 | foreach (var extension in extensions)
71 | {
72 | var file = Path.Combine(categoryDirectory, $"empty{extension}");
73 | items[extension] = EmptyFile.Build(file, category);
74 | }
75 |
76 | return items.ToFrozenDictionary();
77 | }
78 |
79 | static string FindEmptyFilesDirectory()
80 | {
81 | var directories = FindDirectories()
82 | .Select(_ => Path.Combine(_, "EmptyFiles"))
83 | .ToList();
84 | foreach (var directory in directories)
85 | {
86 | if (Directory.Exists(directory))
87 | {
88 | return directory;
89 | }
90 | }
91 |
92 | throw new(
93 | $"""
94 | Could not find empty files directory. Searched:
95 | {string.Join(Environment.NewLine, directories)}
96 | """);
97 | }
98 |
99 | static IEnumerable FindDirectories()
100 | {
101 | yield return AppDomain.CurrentDomain.BaseDirectory;
102 | yield return AssemblyLocation.Directory;
103 | yield return Environment.CurrentDirectory;
104 | }
105 |
106 | public static void UseFile(Category category, string file)
107 | {
108 | Guard.FileExists(file);
109 | var extension = Path.GetExtension(file);
110 | var emptyFile = EmptyFile.Build(file, category);
111 | switch (category)
112 | {
113 | case Category.Archive:
114 | Init(ref archives, ref archiveExtensions);
115 | break;
116 | case Category.Document:
117 | Init(ref documents, ref documentExtensions);
118 | break;
119 | case Category.Image:
120 | Init(ref images, ref imageExtensions);
121 | break;
122 | case Category.Sheet:
123 | Init(ref sheets, ref sheetExtensions);
124 | break;
125 | case Category.Slide:
126 | Init(ref slides, ref slideExtensions);
127 | break;
128 | case Category.Binary:
129 | Init(ref binary, ref binaryExtensions);
130 | break;
131 | default:
132 | throw new($"Unknown category: {category}");
133 | }
134 |
135 | void Init(ref FrozenDictionary emptyFiles, ref FrozenSet extensions)
136 | {
137 | var tempDictionary = new Dictionary();
138 | foreach (var (key, value) in emptyFiles)
139 | {
140 | tempDictionary[key] = value;
141 | }
142 |
143 | tempDictionary[extension] = emptyFile;
144 | emptyFiles = tempDictionary.ToFrozenDictionary();
145 | var tempSet = new HashSet(extensions)
146 | {
147 | extension
148 | };
149 | extensions = tempSet.ToFrozenSet();
150 | }
151 | }
152 |
153 | public static IEnumerable AllPaths => files.Values.Select(_ => _.Path);
154 |
155 | // ReSharper disable once UseSymbolAlias
156 | public static IReadOnlyCollection AllExtensions => files.Keys;
157 |
158 | public static IEnumerable ArchivePaths => archives.Values.Select(_ => _.Path);
159 |
160 | public static FrozenSet ArchiveExtensions => archiveExtensions;
161 |
162 | static FrozenSet archiveExtensions = FrozenSet.ToFrozenSet(
163 | [
164 | ".7z",
165 | ".7zip",
166 | ".bz2",
167 | ".bzip2",
168 | ".gz",
169 | ".gzip",
170 | ".kmz",
171 | ".nupkg",
172 | ".tar",
173 | ".xz",
174 | ".zip"
175 | ]);
176 |
177 | public static IEnumerable DocumentPaths => documents.Values.Select(_ => _.Path);
178 |
179 | public static FrozenSet DocumentExtensions => documentExtensions;
180 |
181 | static FrozenSet documentExtensions = FrozenSet.ToFrozenSet(
182 | [
183 | ".docx",
184 | ".odt",
185 | ".pdf",
186 | ".rtf"
187 | ]);
188 |
189 | public static IEnumerable ImagePaths => images.Values.Select(_ => _.Path);
190 |
191 | public static FrozenSet ImageExtensions => imageExtensions;
192 |
193 | static FrozenSet imageExtensions = FrozenSet.ToFrozenSet(
194 | [
195 | ".avif",
196 | ".bmp",
197 | ".dds",
198 | ".dib",
199 | ".emf",
200 | ".exif",
201 | ".gif",
202 | ".heic",
203 | ".heif",
204 | ".ico",
205 | ".j2c",
206 | ".jfif",
207 | ".jp2",
208 | ".jpc",
209 | ".jpe",
210 | ".jpeg",
211 | ".jpg",
212 | ".jxr",
213 | ".pbm",
214 | ".pcx",
215 | ".pgm",
216 | ".png",
217 | ".ppm",
218 | ".rle",
219 | ".tga",
220 | ".tif",
221 | ".tiff",
222 | ".wdp",
223 | ".webp",
224 | ".wmp"
225 | ]);
226 |
227 | public static IEnumerable SheetPaths => sheets.Values.Select(_ => _.Path);
228 |
229 | public static FrozenSet SheetExtensions => sheetExtensions;
230 |
231 | static FrozenSet sheetExtensions = FrozenSet.ToFrozenSet(
232 | [
233 | ".ods",
234 | ".xlsx"
235 | ]);
236 |
237 | public static IEnumerable SlidePaths => slides.Values.Select(_ => _.Path);
238 |
239 | public static FrozenSet SlideExtensions => slideExtensions;
240 |
241 | static FrozenSet slideExtensions = FrozenSet.ToFrozenSet(
242 | [
243 | ".odp",
244 | ".pptx"
245 | ]);
246 |
247 | public static IEnumerable BinaryPaths => binary.Values.Select(_ => _.Path);
248 |
249 | public static FrozenSet BinaryExtensions => binaryExtensions;
250 |
251 | static FrozenSet binaryExtensions = FrozenSet.ToFrozenSet(
252 | [
253 | ".bin"
254 | ]);
255 |
256 | public static bool IsEmptyFile(string path)
257 | {
258 | Guard.FileExists(path);
259 | var extension = Path.GetExtension(path);
260 | if (!files.TryGetValue(extension, out var emptyFile))
261 | {
262 | return false;
263 | }
264 |
265 | return File.GetLastWriteTime(path) == emptyFile.LastWriteTime;
266 | }
267 |
268 | public static void CreateFile(string path, bool useEmptyStringForTextFiles = false, Encoding? encoding = null)
269 | {
270 | TryCreateDirectory(path);
271 | var extension = Path.GetExtension(path);
272 | if (useEmptyStringForTextFiles &&
273 | FileExtensions.IsTextExtension(extension))
274 | {
275 | CreateTextFile(path, encoding);
276 | return;
277 | }
278 |
279 | File.Copy(GetPathFor(extension), path, true);
280 | }
281 |
282 | static void CreateTextFile(string path, Encoding? encoding)
283 | {
284 | File.Delete(path);
285 | encoding ??= Encoding.UTF8;
286 | File.WriteAllBytes(path, encoding.GetPreamble());
287 | }
288 |
289 | public static string GetPathFor(string extension)
290 | {
291 | extension = Guard.ValidExtension(extension);
292 | if (files.TryGetValue(extension, out var emptyFile))
293 | {
294 | return emptyFile.Path;
295 | }
296 |
297 | throw new($"Unknown extension: {extension}");
298 | }
299 |
300 | public static bool TryCreateFile(string path, bool useEmptyStringForTextFiles = false, Encoding? encoding = null)
301 | {
302 | Guard.AgainstNullOrEmpty(path);
303 | var extension = Path.GetExtension(path);
304 |
305 | if (useEmptyStringForTextFiles &&
306 | FileExtensions.IsTextExtension(extension))
307 | {
308 | TryCreateDirectory(path);
309 |
310 | CreateTextFile(path, encoding);
311 | return true;
312 | }
313 |
314 | if (!TryGetPathFor(extension, out var source))
315 | {
316 | return false;
317 | }
318 |
319 | TryCreateDirectory(path);
320 |
321 | File.Copy(source, path, true);
322 | return true;
323 | }
324 |
325 | static void TryCreateDirectory(string path)
326 | {
327 | var directory = Path.GetDirectoryName(path);
328 |
329 | if (!string.IsNullOrWhiteSpace(directory))
330 | {
331 | Directory.CreateDirectory(directory);
332 | }
333 | }
334 |
335 | public static bool TryGetPathFor(string extension, [NotNullWhen(true)] out string? path)
336 | {
337 | if (files.TryGetValue(extension, out var emptyFile))
338 | {
339 | path = emptyFile.Path;
340 | return true;
341 | }
342 |
343 | path = null;
344 | return false;
345 | }
346 | }
--------------------------------------------------------------------------------
/src/EmptyFiles/FileExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace EmptyFiles;
2 |
3 | public static class FileExtensions
4 | {
5 | public static bool IsTextExtension(string extension)
6 | {
7 | extension = Guard.ValidExtension(extension);
8 |
9 | return textExtensions.Contains(extension);
10 | }
11 |
12 | public static bool IsTextExtension(CharSpan extension) =>
13 | IsTextExtension(extension.ToString());
14 |
15 | public static bool IsTextFile(string path) =>
16 | IsTextFile(path.AsSpan());
17 |
18 | public static bool IsTextFile(CharSpan path)
19 | {
20 | foreach (var convention in textFileConventions)
21 | {
22 | if (convention(path))
23 | {
24 | return true;
25 | }
26 | }
27 |
28 | var extension = Path.GetExtension(path);
29 |
30 | if (extension.Length == 0)
31 | {
32 | return false;
33 | }
34 |
35 | return IsTextExtension(extension);
36 | }
37 |
38 | public static void RemoveTextExtension(string extension)
39 | {
40 | extension = Guard.ValidExtension(extension);
41 | var copy = new HashSet(textExtensions);
42 | copy.Remove(extension);
43 | textExtensions = copy.ToFrozenSet();
44 | }
45 |
46 | public static void RemoveTextExtension(CharSpan extension) =>
47 | RemoveTextExtension(extension.ToString());
48 |
49 | public static void RemoveTextExtensions(params string[] extensions)
50 | {
51 | foreach (var extension in extensions)
52 | {
53 | RemoveTextExtension(extension);
54 | }
55 | }
56 |
57 | public static void RemoveTextExtensions(IEnumerable extensions)
58 | {
59 | foreach (var extension in extensions)
60 | {
61 | RemoveTextExtension(extension);
62 | }
63 | }
64 |
65 | public static void AddTextExtension(string extension)
66 | {
67 | extension = Guard.ValidExtension(extension);
68 | var copy = new HashSet(textExtensions)
69 | {
70 | extension
71 | };
72 | textExtensions = copy.ToFrozenSet();
73 | }
74 |
75 | public static void AddTextExtension(CharSpan extension) =>
76 | AddTextExtension(extension.ToString());
77 |
78 | public static void AddTextExtensions(params string[] extensions)
79 | {
80 | foreach (var extension in extensions)
81 | {
82 | AddTextExtension(extension);
83 | }
84 | }
85 |
86 | public static void AddTextExtensions(IEnumerable extensions)
87 | {
88 | foreach (var extension in extensions)
89 | {
90 | AddTextExtension(extension);
91 | }
92 | }
93 |
94 | public static void AddTextFileConvention(IsTextFile convention) =>
95 | textFileConventions.Add(convention);
96 |
97 | static List textFileConventions = [];
98 |
99 | //From https://github.com/sindresorhus/text-extensions/blob/master/text-extensions.json
100 | static IReadOnlyCollection textExtensions = new HashSet
101 | {
102 | ".ada",
103 | ".adb",
104 | ".ads",
105 | ".applescript",
106 | ".as",
107 | ".asc",
108 | ".ascii",
109 | ".ascx",
110 | ".asm",
111 | ".asmx",
112 | ".asp",
113 | ".aspx",
114 | ".atom",
115 | ".au3",
116 | ".awk",
117 | ".bas",
118 | ".bash",
119 | ".bashrc",
120 | ".bat",
121 | ".bbcolors",
122 | ".bcp",
123 | ".bdsgroup",
124 | ".bdsproj",
125 | ".bib",
126 | ".bicep",
127 | ".bowerrc",
128 | ".c",
129 | ".cbl",
130 | ".cc",
131 | ".cfc",
132 | ".cfg",
133 | ".cfm",
134 | ".cfml",
135 | ".cgi",
136 | ".cjs",
137 | ".clj",
138 | ".cljs",
139 | ".cls",
140 | ".cmake",
141 | ".cmd",
142 | ".cnf",
143 | ".cob",
144 | ".code-snippets",
145 | ".coffee",
146 | ".coffeekup",
147 | ".conf",
148 | ".config",
149 | ".cp",
150 | ".cpp",
151 | ".cpt",
152 | ".cpy",
153 | ".crt",
154 | ".cs",
155 | ".csh",
156 | ".cson",
157 | ".csproj",
158 | ".csr",
159 | ".css",
160 | ".csslintrc",
161 | ".csv",
162 | ".ctl",
163 | ".curlrc",
164 | ".cxx",
165 | ".d",
166 | ".dart",
167 | ".dfm",
168 | ".diff",
169 | ".dof",
170 | ".dpk",
171 | ".dpr",
172 | ".dproj",
173 | ".dtd",
174 | ".dockerfile",
175 | ".eco",
176 | ".editorconfig",
177 | ".ejs",
178 | ".el",
179 | ".elm",
180 | ".emacs",
181 | ".eml",
182 | ".ent",
183 | ".env",
184 | ".erb",
185 | ".erl",
186 | ".eslintignore",
187 | ".eslintrc",
188 | ".ex",
189 | ".exs",
190 | ".f",
191 | ".f03",
192 | ".f77",
193 | ".f90",
194 | ".f95",
195 | ".fish",
196 | ".for",
197 | ".fpp",
198 | ".frm",
199 | ".fs",
200 | ".fsproj",
201 | ".fsx",
202 | ".ftn",
203 | ".gemrc",
204 | ".gemspec",
205 | ".gitattributes",
206 | ".gitconfig",
207 | ".gitignore",
208 | ".gitkeep",
209 | ".gitmodules",
210 | ".go",
211 | ".gpp",
212 | ".gradle",
213 | ".graphql",
214 | ".groovy",
215 | ".groupproj",
216 | ".grunit",
217 | ".gtmpl",
218 | ".gv",
219 | ".gvimrc",
220 | ".h",
221 | ".haml",
222 | ".hbs",
223 | ".hgignore",
224 | ".hh",
225 | ".hpp",
226 | ".hrl",
227 | ".hs",
228 | ".hta",
229 | ".htaccess",
230 | ".htc",
231 | ".htm",
232 | ".html",
233 | ".htmx",
234 | ".htpasswd",
235 | ".hxx",
236 | ".ics",
237 | ".iced",
238 | ".il",
239 | ".iml",
240 | ".inc",
241 | ".inf",
242 | ".info",
243 | ".ini",
244 | ".ino",
245 | ".int",
246 | ".irbrc",
247 | ".itcl",
248 | ".itermcolors",
249 | ".itk",
250 | ".jade",
251 | ".java",
252 | ".jhtm",
253 | ".jhtml",
254 | ".js",
255 | ".javascript",
256 | ".jscsrc",
257 | ".jshintignore",
258 | ".jshintrc",
259 | ".json",
260 | ".json5",
261 | ".jsonld",
262 | ".jsp",
263 | ".jspx",
264 | ".jsx",
265 | ".ksh",
266 | ".less",
267 | ".lhs",
268 | ".lisp",
269 | ".log",
270 | ".ls",
271 | ".lsp",
272 | ".lua",
273 | ".m",
274 | ".m4",
275 | ".mak",
276 | ".map",
277 | ".markdown",
278 | ".master",
279 | ".md",
280 | ".mdown",
281 | ".mdwn",
282 | ".mdx",
283 | ".mermaid",
284 | ".metadata",
285 | ".mht",
286 | ".mhtml",
287 | ".mjs",
288 | ".mk",
289 | ".mkd",
290 | ".mkdn",
291 | ".mkdown",
292 | ".ml",
293 | ".mli",
294 | ".mm",
295 | ".mmd",
296 | ".mxml",
297 | ".nfm",
298 | ".nfo",
299 | ".noon",
300 | ".npmignore",
301 | ".npmrc",
302 | ".nuspec",
303 | ".nvmrc",
304 | ".ops",
305 | ".pas",
306 | ".pasm",
307 | ".patch",
308 | ".pbxproj",
309 | ".pch",
310 | ".pem",
311 | ".pg",
312 | ".php",
313 | ".php3",
314 | ".php4",
315 | ".php5",
316 | ".phpt",
317 | ".phtml",
318 | ".pir",
319 | ".pl",
320 | ".pm",
321 | ".pmc",
322 | ".pod",
323 | ".pot",
324 | ".prettierrc",
325 | ".properties",
326 | ".props",
327 | ".ps1",
328 | ".pt",
329 | ".pug",
330 | ".purs",
331 | ".py",
332 | ".pyx",
333 | ".r",
334 | ".rake",
335 | ".rb",
336 | ".rbw",
337 | ".rc",
338 | ".rdoc",
339 | ".rdoc_options",
340 | ".rels",
341 | ".resx",
342 | ".rexx",
343 | ".rhtml",
344 | ".rjs",
345 | ".rlib",
346 | ".ron",
347 | ".rs",
348 | ".rss",
349 | ".rst",
350 | ".rtf",
351 | ".rvmrc",
352 | ".rxml",
353 | ".s",
354 | ".sass",
355 | ".scala",
356 | ".scm",
357 | ".scss",
358 | ".seestyle",
359 | ".sh",
360 | ".shtml",
361 | ".sln",
362 | ".slnx",
363 | ".slnf",
364 | ".sls",
365 | ".spec",
366 | ".sql",
367 | ".sqlite",
368 | ".sqlproj",
369 | ".srt",
370 | ".ss",
371 | ".sss",
372 | ".st",
373 | ".strings",
374 | ".sty",
375 | ".styl",
376 | ".stylus",
377 | ".sub",
378 | ".sublime-build",
379 | ".sublime-commands",
380 | ".sublime-completions",
381 | ".sublime-keymap",
382 | ".sublime-macro",
383 | ".sublime-menu",
384 | ".sublime-project",
385 | ".sublime-settings",
386 | ".sublime-workspace",
387 | ".sv",
388 | ".svc",
389 | ".svg",
390 | ".swift",
391 | ".t",
392 | ".tcl",
393 | ".tcsh",
394 | ".terminal",
395 | ".tex",
396 | ".text",
397 | ".textile",
398 | ".tg",
399 | ".tk",
400 | ".tmLanguage",
401 | ".tmpl",
402 | ".tmTheme",
403 | ".toml",
404 | ".tpl",
405 | ".ts",
406 | ".tsv",
407 | ".tsx",
408 | ".tt",
409 | ".tt2",
410 | ".ttml",
411 | ".twig",
412 | ".txt",
413 | ".v",
414 | ".vb",
415 | ".vbproj",
416 | ".vbs",
417 | ".vcproj",
418 | ".vcxproj",
419 | ".vh",
420 | ".vhd",
421 | ".vhdl",
422 | ".vim",
423 | ".viminfo",
424 | ".vimrc",
425 | ".vm",
426 | ".vue",
427 | ".webapp",
428 | ".webmanifest",
429 | ".wsc",
430 | ".x-php",
431 | ".xaml",
432 | ".xht",
433 | ".xhtml",
434 | ".xml",
435 | ".xs",
436 | ".xsd",
437 | ".xsl",
438 | ".xslt",
439 | ".y",
440 | ".yaml",
441 | ".yml",
442 | ".zsh",
443 | ".zshrc"
444 | }
445 | .ToFrozenSet();
446 |
447 | public static IReadOnlyCollection TextExtensions => textExtensions;
448 |
449 | [Obsolete("Use IsTextFile or IsTextExtension")]
450 | public static bool IsText([NotNullWhen(true)] string? extensionOrPath)
451 | {
452 | if (extensionOrPath == null)
453 | {
454 | return false;
455 | }
456 |
457 | if (extensionOrPath.Contains('.') ||
458 | extensionOrPath.Contains(Path.DirectorySeparatorChar) ||
459 | extensionOrPath.Contains(Path.AltDirectorySeparatorChar))
460 | {
461 | var extension = Path.GetExtension(extensionOrPath);
462 | return textExtensions.Contains(extension);
463 | }
464 |
465 | return textExtensions.Contains($".{extensionOrPath}");
466 | }
467 |
468 | [Obsolete("Use IsTextFile or IsTextExtension")]
469 | public static bool IsText(CharSpan extensionOrPath) =>
470 | IsText(extensionOrPath.ToString());
471 | }
472 |
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 |
6 | [*.cs]
7 | indent_size = 4
8 | charset = utf-8
9 |
10 | # Redundant accessor body
11 | resharper_redundant_accessor_body_highlighting = error
12 |
13 | # Replace with field keyword
14 | resharper_replace_with_field_keyword_highlighting = error
15 |
16 | # Replace with single call to Single(..)
17 | resharper_replace_with_single_call_to_single_highlighting = error
18 |
19 | # Replace with single call to SingleOrDefault(..)
20 | resharper_replace_with_single_call_to_single_or_default_highlighting = error
21 |
22 | # Replace with single call to LastOrDefault(..)
23 | resharper_replace_with_single_call_to_last_or_default_highlighting = error
24 |
25 | # Element is localizable
26 | resharper_localizable_element_highlighting = none
27 |
28 | # Replace with single call to Last(..)
29 | resharper_replace_with_single_call_to_last_highlighting = error
30 |
31 | # Replace with single call to First(..)
32 | resharper_replace_with_single_call_to_first_highlighting = error
33 |
34 | # Replace with single call to FirstOrDefault(..)
35 | resharper_replace_with_single_call_to_first_or_default_highlighting = error
36 |
37 | # Replace with single call to Any(..)
38 | resharper_replace_with_single_call_to_any_highlighting = error
39 |
40 | # Simplify negative equality expression
41 | resharper_negative_equality_expression_highlighting = error
42 |
43 | # Replace with single call to Count(..)
44 | resharper_replace_with_single_call_to_count_highlighting = error
45 |
46 | # Declare types in namespaces
47 | dotnet_diagnostic.CA1050.severity = none
48 |
49 | # Use Literals Where Appropriate
50 | dotnet_diagnostic.CA1802.severity = error
51 |
52 | # Template should be a static expression
53 | dotnet_diagnostic.CA2254.severity = error
54 |
55 | # Potentially misleading parameter name in lambda or local function
56 | resharper_all_underscore_local_parameter_name_highlighting = none
57 |
58 | # Redundant explicit collection creation in argument of 'params' parameter
59 | resharper_redundant_explicit_params_array_creation_highlighting = error
60 |
61 | # Do not initialize unnecessarily
62 | dotnet_diagnostic.CA1805.severity = error
63 |
64 | # Avoid unsealed attributes
65 | dotnet_diagnostic.CA1813.severity = error
66 |
67 | # Test for empty strings using string length
68 | dotnet_diagnostic.CA1820.severity = none
69 |
70 | # Remove empty finalizers
71 | dotnet_diagnostic.CA1821.severity = error
72 |
73 | # Mark members as static
74 | dotnet_diagnostic.CA1822.severity = error
75 |
76 | # Avoid unused private fields
77 | dotnet_diagnostic.CA1823.severity = error
78 |
79 | # Avoid zero-length array allocations
80 | dotnet_diagnostic.CA1825.severity = error
81 |
82 | # Use property instead of Linq Enumerable method
83 | dotnet_diagnostic.CA1826.severity = error
84 |
85 | # Do not use Count()/LongCount() when Any() can be used
86 | dotnet_diagnostic.CA1827.severity = error
87 | dotnet_diagnostic.CA1828.severity = error
88 |
89 | # Use Length/Count property instead of Enumerable.Count method
90 | dotnet_diagnostic.CA1829.severity = error
91 |
92 | # Prefer strongly-typed Append and Insert method overloads on StringBuilder
93 | dotnet_diagnostic.CA1830.severity = error
94 |
95 | # Use AsSpan instead of Range-based indexers for string when appropriate
96 | dotnet_diagnostic.CA1831.severity = error
97 |
98 | # Use AsSpan instead of Range-based indexers for string when appropriate
99 | dotnet_diagnostic.CA1831.severity = error
100 | dotnet_diagnostic.CA1832.severity = error
101 | dotnet_diagnostic.CA1833.severity = error
102 |
103 | # Use StringBuilder.Append(char) for single character strings
104 | dotnet_diagnostic.CA1834.severity = error
105 |
106 | # Prefer IsEmpty over Count when available
107 | dotnet_diagnostic.CA1836.severity = error
108 |
109 | # Prefer IsEmpty over Count when available
110 | dotnet_diagnostic.CA1836.severity = error
111 |
112 | # Use Environment.ProcessId instead of Process.GetCurrentProcess().Id
113 | dotnet_diagnostic.CA1837.severity = error
114 |
115 | # Use Environment.ProcessPath instead of Process.GetCurrentProcess().MainModule.FileName
116 | dotnet_diagnostic.CA1839.severity = error
117 |
118 | # Use Environment.CurrentManagedThreadId instead of Thread.CurrentThread.ManagedThreadId
119 | dotnet_diagnostic.CA1840.severity = error
120 |
121 | # Prefer Dictionary Contains methods
122 | dotnet_diagnostic.CA1841.severity = error
123 |
124 | # Do not use WhenAll with a single task
125 | dotnet_diagnostic.CA1842.severity = error
126 |
127 | # Do not use WhenAll/WaitAll with a single task
128 | dotnet_diagnostic.CA1842.severity = error
129 | dotnet_diagnostic.CA1843.severity = error
130 |
131 | # Use span-based 'string.Concat'
132 | dotnet_diagnostic.CA1845.severity = error
133 |
134 | # Prefer AsSpan over Substring
135 | dotnet_diagnostic.CA1846.severity = error
136 |
137 | # Use string.Contains(char) instead of string.Contains(string) with single characters
138 | dotnet_diagnostic.CA1847.severity = error
139 |
140 | # Prefer static HashData method over ComputeHash
141 | dotnet_diagnostic.CA1850.severity = error
142 |
143 | # Possible multiple enumerations of IEnumerable collection
144 | dotnet_diagnostic.CA1851.severity = error
145 |
146 | # Unnecessary call to Dictionary.ContainsKey(key)
147 | dotnet_diagnostic.CA1853.severity = error
148 |
149 | # Prefer the IDictionary.TryGetValue(TKey, out TValue) method
150 | dotnet_diagnostic.CA1854.severity = error
151 |
152 | # Use Span.Clear() instead of Span.Fill()
153 | dotnet_diagnostic.CA1855.severity = error
154 |
155 | # Incorrect usage of ConstantExpected attribute
156 | dotnet_diagnostic.CA1856.severity = error
157 |
158 | # The parameter expects a constant for optimal performance
159 | dotnet_diagnostic.CA1857.severity = error
160 |
161 | # Use StartsWith instead of IndexOf
162 | dotnet_diagnostic.CA1858.severity = error
163 |
164 | # Avoid using Enumerable.Any() extension method
165 | dotnet_diagnostic.CA1860.severity = error
166 |
167 | # Avoid constant arrays as arguments
168 | dotnet_diagnostic.CA1861.severity = error
169 |
170 | # Use the StringComparison method overloads to perform case-insensitive string comparisons
171 | dotnet_diagnostic.CA1862.severity = error
172 |
173 | # Prefer the IDictionary.TryAdd(TKey, TValue) method
174 | dotnet_diagnostic.CA1864.severity = error
175 |
176 | # Use string.Method(char) instead of string.Method(string) for string with single char
177 | dotnet_diagnostic.CA1865.severity = error
178 | dotnet_diagnostic.CA1866.severity = error
179 | dotnet_diagnostic.CA1867.severity = error
180 |
181 | # Unnecessary call to 'Contains' for sets
182 | dotnet_diagnostic.CA1868.severity = error
183 |
184 | # Cache and reuse 'JsonSerializerOptions' instances
185 | dotnet_diagnostic.CA1869.severity = error
186 |
187 | # Use a cached 'SearchValues' instance
188 | dotnet_diagnostic.CA1870.severity = error
189 |
190 | # Microsoft .NET properties
191 | trim_trailing_whitespace = true
192 | csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion
193 | resharper_namespace_body = file_scoped
194 | dotnet_naming_rule.private_constants_rule.severity = warning
195 | dotnet_naming_rule.private_constants_rule.style = lower_camel_case_style
196 | dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols
197 | dotnet_naming_rule.private_instance_fields_rule.severity = warning
198 | dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style
199 | dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols
200 | dotnet_naming_rule.private_static_fields_rule.severity = warning
201 | dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style
202 | dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols
203 | dotnet_naming_rule.private_static_readonly_rule.severity = warning
204 | dotnet_naming_rule.private_static_readonly_rule.style = lower_camel_case_style
205 | dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols
206 | dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
207 | dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case
208 | dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private
209 | dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field
210 | dotnet_naming_symbols.private_constants_symbols.required_modifiers = const
211 | dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities = private
212 | dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds = field
213 | dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities = private
214 | dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds = field
215 | dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static
216 | dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private
217 | dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field
218 | dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static, readonly
219 | dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
220 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none
221 | dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
222 |
223 | # ReSharper properties
224 | resharper_object_creation_when_type_not_evident = target_typed
225 |
226 | # ReSharper inspection severities
227 | resharper_arrange_object_creation_when_type_evident_highlighting = error
228 | resharper_arrange_object_creation_when_type_not_evident_highlighting = error
229 | resharper_arrange_redundant_parentheses_highlighting = error
230 | resharper_arrange_static_member_qualifier_highlighting = error
231 | resharper_arrange_this_qualifier_highlighting = error
232 | resharper_arrange_type_member_modifiers_highlighting = none
233 | resharper_built_in_type_reference_style_for_member_access_highlighting = hint
234 | resharper_built_in_type_reference_style_highlighting = hint
235 | resharper_check_namespace_highlighting = none
236 | resharper_convert_to_using_declaration_highlighting = error
237 | resharper_field_can_be_made_read_only_local_highlighting = none
238 | resharper_merge_into_logical_pattern_highlighting = warning
239 | resharper_merge_into_pattern_highlighting = error
240 | resharper_method_has_async_overload_highlighting = warning
241 | # because stop rider giving errors before source generators have run
242 | resharper_partial_type_with_single_part_highlighting = warning
243 | resharper_redundant_base_qualifier_highlighting = warning
244 | resharper_redundant_cast_highlighting = error
245 | resharper_redundant_empty_object_creation_argument_list_highlighting = error
246 | resharper_redundant_empty_object_or_collection_initializer_highlighting = error
247 | resharper_redundant_name_qualifier_highlighting = error
248 | resharper_redundant_suppress_nullable_warning_expression_highlighting = error
249 | resharper_redundant_using_directive_highlighting = error
250 | resharper_redundant_verbatim_string_prefix_highlighting = error
251 | resharper_redundant_lambda_signature_parentheses_highlighting = error
252 | resharper_replace_substring_with_range_indexer_highlighting = warning
253 | resharper_suggest_var_or_type_built_in_types_highlighting = error
254 | resharper_suggest_var_or_type_elsewhere_highlighting = error
255 | resharper_suggest_var_or_type_simple_types_highlighting = error
256 | resharper_unnecessary_whitespace_highlighting = error
257 | resharper_use_await_using_highlighting = warning
258 | resharper_use_deconstruction_highlighting = warning
259 |
260 | # Sort using and Import directives with System.* appearing first
261 | dotnet_sort_system_directives_first = true
262 |
263 | # Avoid "this." and "Me." if not necessary
264 | dotnet_style_qualification_for_field = false:error
265 | dotnet_style_qualification_for_property = false:error
266 | dotnet_style_qualification_for_method = false:error
267 | dotnet_style_qualification_for_event = false:error
268 |
269 | # Use language keywords instead of framework type names for type references
270 | dotnet_style_predefined_type_for_locals_parameters_members = true:error
271 | dotnet_style_predefined_type_for_member_access = true:error
272 |
273 | # Suggest more modern language features when available
274 | dotnet_style_object_initializer = true:error
275 | dotnet_style_collection_initializer = true:error
276 | dotnet_style_coalesce_expression = false:error
277 | dotnet_style_null_propagation = true:error
278 | dotnet_style_explicit_tuple_names = true:error
279 |
280 | # Use collection expression syntax
281 | resharper_use_collection_expression_highlighting = error
282 |
283 | # Prefer "var" everywhere
284 | csharp_style_var_for_built_in_types = true:error
285 | csharp_style_var_when_type_is_apparent = true:error
286 | csharp_style_var_elsewhere = true:error
287 |
288 | # Prefer method-like constructs to have a block body
289 | csharp_style_expression_bodied_methods = true:error
290 | csharp_style_expression_bodied_local_functions = true:error
291 | csharp_style_expression_bodied_constructors = true:error
292 | csharp_style_expression_bodied_operators = true:error
293 | resharper_place_expr_method_on_single_line = false
294 |
295 | # Prefer property-like constructs to have an expression-body
296 | csharp_style_expression_bodied_properties = true:error
297 | csharp_style_expression_bodied_indexers = true:error
298 | csharp_style_expression_bodied_accessors = true:error
299 |
300 | # Suggest more modern language features when available
301 | csharp_style_pattern_matching_over_is_with_cast_check = true:error
302 | csharp_style_pattern_matching_over_as_with_null_check = true:error
303 | csharp_style_inlined_variable_declaration = true:suggestion
304 | csharp_style_throw_expression = true:suggestion
305 | csharp_style_conditional_delegate_call = true:suggestion
306 |
307 | # Newline settings
308 | #csharp_new_line_before_open_brace = all:error
309 | resharper_max_array_initializer_elements_on_line = 1
310 | csharp_new_line_before_else = true
311 | csharp_new_line_before_catch = true
312 | csharp_new_line_before_finally = true
313 | csharp_new_line_before_members_in_object_initializers = true
314 | csharp_new_line_before_members_in_anonymous_types = true
315 | resharper_wrap_before_first_type_parameter_constraint = true
316 | resharper_wrap_extends_list_style = chop_always
317 | resharper_wrap_after_dot_in_method_calls = false
318 | resharper_wrap_before_binary_pattern_op = false
319 | resharper_wrap_object_and_collection_initializer_style = chop_always
320 | resharper_place_simple_initializer_on_single_line = false
321 |
322 | # space
323 | resharper_space_around_lambda_arrow = true
324 |
325 | dotnet_style_require_accessibility_modifiers = never:error
326 | resharper_place_type_constraints_on_same_line = false
327 | resharper_blank_lines_inside_namespace = 0
328 | resharper_blank_lines_after_file_scoped_namespace_directive = 1
329 | resharper_blank_lines_inside_type = 0
330 |
331 | insert_final_newline = false
332 | resharper_place_attribute_on_same_line = false
333 |
334 | #braces https://www.jetbrains.com/help/resharper/EditorConfig_CSHARP_CSharpCodeStylePageImplSchema.html#Braces
335 | resharper_braces_for_ifelse = required
336 | resharper_braces_for_foreach = required
337 | resharper_braces_for_while = required
338 | resharper_braces_for_dowhile = required
339 | resharper_braces_for_lock = required
340 | resharper_braces_for_fixed = required
341 | resharper_braces_for_for = required
342 |
343 | resharper_return_value_of_pure_method_is_not_used_highlighting = error
344 |
345 |
346 | resharper_misleading_body_like_statement_highlighting = error
347 |
348 | resharper_redundant_record_class_keyword_highlighting = error
349 |
350 | resharper_redundant_extends_list_entry_highlighting = error
351 |
352 | resharper_redundant_type_arguments_inside_nameof_highlighting = error
353 |
354 | # Xml files
355 | [*.{xml,config,nuspec,resx,vsixmanifest,csproj,targets,props,fsproj}]
356 | indent_size = 2
357 | # https://www.jetbrains.com/help/resharper/EditorConfig_XML_XmlCodeStylePageSchema.html#resharper_xml_blank_line_after_pi
358 | resharper_blank_line_after_pi = false
359 | resharper_space_before_self_closing = true
360 | ij_xml_space_inside_empty_tag = true
361 |
362 | [*.json]
363 | indent_size = 2
364 |
365 | # Verify settings
366 | [*.{received,verified}.{txt,xml,json,md,sql,csv,html,htm,nuspec,rels}]
367 | charset = utf-8-bom
368 | end_of_line = lf
369 | indent_size = unset
370 | indent_style = unset
371 | insert_final_newline = false
372 | tab_width = unset
373 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/src/Shared.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | False
3 | Quiet
4 | True
5 | True
6 | True
7 | DO_NOT_SHOW
8 | ERROR
9 | ERROR
10 | ERROR
11 | WARNING
12 | ERROR
13 | ERROR
14 | ERROR
15 | ERROR
16 | ERROR
17 | ERROR
18 | ERROR
19 | ERROR
20 | ERROR
21 | ERROR
22 | ERROR
23 | ERROR
24 | ERROR
25 | ERROR
26 | ERROR
27 | ERROR
28 | ERROR
29 | ERROR
30 | ERROR
31 | ERROR
32 | ERROR
33 | ERROR
34 | ERROR
35 | ERROR
36 | ERROR
37 | ERROR
38 | ERROR
39 | ERROR
40 | ERROR
41 | ERROR
42 | ERROR
43 | DO_NOT_SHOW
44 | DO_NOT_SHOW
45 | ERROR
46 | ERROR
47 | ERROR
48 | ERROR
49 | ERROR
50 | ERROR
51 | ERROR
52 | ERROR
53 | ERROR
54 | ERROR
55 | ERROR
56 | ERROR
57 | C90+,E79+,S14+
58 | ERROR
59 | ERROR
60 | ERROR
61 | ERROR
62 | ERROR
63 | ERROR
64 | ERROR
65 | ERROR
66 | ERROR
67 | ERROR
68 | ERROR
69 | ERROR
70 | ERROR
71 | ERROR
72 | ERROR
73 | ERROR
74 | ERROR
75 | ERROR
76 | ERROR
77 | ERROR
78 | ERROR
79 | ERROR
80 | ERROR
81 | ERROR
82 | ERROR
83 | ERROR
84 | ERROR
85 | ERROR
86 | ERROR
87 | ERROR
88 | ERROR
89 | ERROR
90 | ERROR
91 | ERROR
92 | ERROR
93 | ERROR
94 | ERROR
95 | ERROR
96 | ERROR
97 | ERROR
98 | ERROR
99 | ERROR
100 | ERROR
101 | ERROR
102 | ERROR
103 | ERROR
104 | ERROR
105 | ERROR
106 | ERROR
107 | ERROR
108 | ERROR
109 | ERROR
110 | ERROR
111 | ERROR
112 | ERROR
113 | ERROR
114 | ERROR
115 | ERROR
116 | ERROR
117 | ERROR
118 | ERROR
119 | ERROR
120 | ERROR
121 | ERROR
122 | DO_NOT_SHOW
123 | *.received.*
124 | *.verified.*
125 | ERROR
126 | ERROR
127 | DO_NOT_SHOW
128 | ECMAScript 2016
129 | <?xml version="1.0" encoding="utf-16"?><Profile name="c# Cleanup"><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><CSCodeStyleAttributes ArrangeVarStyle="True" ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeCodeBodyStyle="True" ArrangeTrailingCommas="True" ArrangeObjectCreation="True" ArrangeDefaultValue="True" ArrangeNamespaces="True" /><CssAlphabetizeProperties>True</CssAlphabetizeProperties><JSStringLiteralQuotesDescriptor>True</JSStringLiteralQuotesDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><JsInsertSemicolon>True</JsInsertSemicolon><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs><OptimizeReferenceCommentsTs>True</OptimizeReferenceCommentsTs><PublicModifierStyleTs>True</PublicModifierStyleTs><ExplicitAnyTs>True</ExplicitAnyTs><TypeAnnotationStyleTs>True</TypeAnnotationStyleTs><RelativePathStyleTs>True</RelativePathStyleTs><AsInsteadOfCastTs>True</AsInsteadOfCastTs><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CssReformatCode>True</CssReformatCode><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><HtmlReformatCode>True</HtmlReformatCode><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><IDEA_SETTINGS><profile version="1.0">
130 | <option name="myName" value="c# Cleanup" />
131 | </profile></IDEA_SETTINGS><RIDER_SETTINGS><profile>
132 | <Language id="EditorConfig">
133 | <Reformat>false</Reformat>
134 | </Language>
135 | <Language id="HTML">
136 | <OptimizeImports>false</OptimizeImports>
137 | <Reformat>false</Reformat>
138 | <Rearrange>false</Rearrange>
139 | </Language>
140 | <Language id="JSON">
141 | <Reformat>false</Reformat>
142 | </Language>
143 | <Language id="RELAX-NG">
144 | <Reformat>false</Reformat>
145 | </Language>
146 | <Language id="XML">
147 | <OptimizeImports>false</OptimizeImports>
148 | <Reformat>false</Reformat>
149 | <Rearrange>false</Rearrange>
150 | </Language>
151 | </profile></RIDER_SETTINGS></Profile>
152 | ExpressionBody
153 | ExpressionBody
154 | ExpressionBody
155 | False
156 | NEVER
157 | NEVER
158 | False
159 | False
160 | False
161 | True
162 | False
163 | CHOP_ALWAYS
164 | False
165 | False
166 | RemoveIndent
167 | RemoveIndent
168 | False
169 | True
170 | True
171 | True
172 | True
173 | True
174 | ERROR
175 | DoNothing
176 |
--------------------------------------------------------------------------------