Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- `isImageMimeType`, `isPdfMimeType`, `isVideoMimeType`, `isAudioMimeType`, `isTextMimeType`, and `isApplicationMimeType` MIME type utility functions

## [1.4.0] - 2025-06-24

### Added
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from "./lib/date";
export * from "./lib/enum";
export * from "./lib/guid";
export * from "./lib/localStorage";
export * from "./lib/mimeType";
export * from "./lib/number";
export * from "./lib/object";
export * from "./lib/string";
122 changes: 122 additions & 0 deletions src/lib/mimeType.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { isImageMimeType, isPdfMimeType, isVideoMimeType, isAudioMimeType, isTextMimeType, isApplicationMimeType } from "./mimeType";

describe("mimeType tests", () => {
// Common invalid inputs
const invalidInputs: [string | null | undefined | number | Date, boolean][] = [
[null as unknown as string, false],
[undefined as unknown as string, false],
[0 as unknown as string, false],
[new Date() as unknown as string, false],
["", false],
[" ", false],
["not-a-mime-type", false],
];

test.each([
...invalidInputs,
// Valid image MIME types
["image/jpeg", true],
["image/png", true],
["image/gif", true],
["image/webp", true],
["image/svg+xml", true],
["IMAGE/JPEG", true], // Case insensitive
[" image/gif ", true], // Whitespace trimmed
// Invalid cases
["application/pdf", false],
["text/plain", false],
["video/mp4", false],
["image", false],
["image/", false],
["/image", false],
])("isImageMimeType", (mimeType, expected) => {
expect(isImageMimeType(mimeType as string)).toBe(expected);
});

test.each([
...invalidInputs,
// Valid PDF MIME type
["application/pdf", true],
["APPLICATION/PDF", true], // Case insensitive
[" application/pdf ", true], // Whitespace trimmed
// Invalid cases
["image/jpeg", false],
["application/json", false],
["pdf", false],
["application/", false],
])("isPdfMimeType", (mimeType, expected) => {
expect(isPdfMimeType(mimeType as string)).toBe(expected);
});

test.each([
...invalidInputs,
// Valid video MIME types
["video/mp4", true],
["video/mpeg", true],
["video/webm", true],
["VIDEO/MP4", true], // Case insensitive
[" video/webm ", true], // Whitespace trimmed
// Invalid cases
["image/jpeg", false],
["audio/mp3", false],
["video", false],
["video/", false],
["/video", false],
])("isVideoMimeType", (mimeType, expected) => {
expect(isVideoMimeType(mimeType as string)).toBe(expected);
});

test.each([
...invalidInputs,
// Valid audio MIME types
["audio/mp3", true],
["audio/mpeg", true],
["audio/wav", true],
["AUDIO/MP3", true], // Case insensitive
[" audio/ogg ", true], // Whitespace trimmed
// Invalid cases
["video/mp4", false],
["image/jpeg", false],
["audio", false],
["audio/", false],
["/audio", false],
])("isAudioMimeType", (mimeType, expected) => {
expect(isAudioMimeType(mimeType as string)).toBe(expected);
});

test.each([
...invalidInputs,
// Valid text MIME types
["text/plain", true],
["text/html", true],
["text/css", true],
["TEXT/PLAIN", true], // Case insensitive
[" text/css ", true], // Whitespace trimmed
// Invalid cases
["application/pdf", false],
["image/jpeg", false],
["text", false],
["text/", false],
["/text", false],
])("isTextMimeType", (mimeType, expected) => {
expect(isTextMimeType(mimeType as string)).toBe(expected);
});

test.each([
...invalidInputs,
// Valid application MIME types
["application/pdf", true],
["application/json", true],
["application/xml", true],
["APPLICATION/PDF", true], // Case insensitive
[" application/xml ", true], // Whitespace trimmed
// Invalid cases
["text/plain", false],
["image/jpeg", false],
["application", false],
["application/", false],
["/application", false],
])("isApplicationMimeType", (mimeType, expected) => {
expect(isApplicationMimeType(mimeType as string)).toBe(expected);
});
});
91 changes: 91 additions & 0 deletions src/lib/mimeType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { isNullOrEmpty } from "./string";

/**
* Private helper function to check if a MIME type matches a main type pattern
* @param mimeType The MIME type to check
* @param mainType The main MIME type (e.g., "image", "video")
* @returns true if the MIME type matches the pattern
*/
function isMainMimeType(mimeType: string, mainType: string): boolean {
const normalizedMimeType = mimeType.toLowerCase().trim();
return normalizedMimeType.startsWith(`${mainType}/`) && normalizedMimeType.length > mainType.length + 1;
}

/**
* Check if the MIME type represents an image
* @param mimeType The MIME type to check
* @returns true if the MIME type is for an image
*/
export function isImageMimeType(mimeType?: string): boolean {
if (isNullOrEmpty(mimeType)) {
return false;
}

return isMainMimeType(mimeType!, "image");
}

/**
* Check if the MIME type represents a PDF document
* @param mimeType The MIME type to check
* @returns true if the MIME type is for a PDF document
*/
export function isPdfMimeType(mimeType?: string): boolean {
if (isNullOrEmpty(mimeType)) {
return false;
}

const normalizedMimeType = mimeType!.toLowerCase().trim();
return normalizedMimeType === "application/pdf";
}

/**
* Check if the MIME type represents a video
* @param mimeType The MIME type to check
* @returns true if the MIME type is for a video
*/
export function isVideoMimeType(mimeType?: string): boolean {
if (isNullOrEmpty(mimeType)) {
return false;
}

return isMainMimeType(mimeType!, "video");
}

/**
* Check if the MIME type represents an audio file
* @param mimeType The MIME type to check
* @returns true if the MIME type is for an audio file
*/
export function isAudioMimeType(mimeType?: string): boolean {
if (isNullOrEmpty(mimeType)) {
return false;
}

return isMainMimeType(mimeType!, "audio");
}

/**
* Check if the MIME type represents a text file
* @param mimeType The MIME type to check
* @returns true if the MIME type is for a text file
*/
export function isTextMimeType(mimeType?: string): boolean {
if (isNullOrEmpty(mimeType)) {
return false;
}

return isMainMimeType(mimeType!, "text");
}

/**
* Check if the MIME type represents an application file
* @param mimeType The MIME type to check
* @returns true if the MIME type is for an application file
*/
export function isApplicationMimeType(mimeType?: string): boolean {
if (isNullOrEmpty(mimeType)) {
return false;
}

return isMainMimeType(mimeType!, "application");
}