file-type 18.6.0 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core.d.ts +99 -8
- package/core.js +105 -63
- package/index.js +4 -3
- package/package.json +12 -7
- package/readme.md +77 -19
- package/supported.js +3 -1
package/core.d.ts
CHANGED
|
@@ -153,6 +153,7 @@ export type FileExtension =
|
|
|
153
153
|
| 'ace'
|
|
154
154
|
| 'avro'
|
|
155
155
|
| 'icc'
|
|
156
|
+
| 'fbx'
|
|
156
157
|
; // eslint-disable-line semi-style
|
|
157
158
|
|
|
158
159
|
export type MimeType =
|
|
@@ -191,7 +192,7 @@ export type MimeType =
|
|
|
191
192
|
| 'video/webm'
|
|
192
193
|
| 'video/quicktime'
|
|
193
194
|
| 'video/vnd.avi'
|
|
194
|
-
| 'audio/
|
|
195
|
+
| 'audio/wav'
|
|
195
196
|
| 'audio/qcelp'
|
|
196
197
|
| 'audio/x-ms-asf'
|
|
197
198
|
| 'video/x-ms-asf'
|
|
@@ -302,6 +303,7 @@ export type MimeType =
|
|
|
302
303
|
| 'application/x-ace-compressed'
|
|
303
304
|
| 'application/avro'
|
|
304
305
|
| 'application/vnd.iccprofile'
|
|
306
|
+
| 'application/x.autodesk.fbx'
|
|
305
307
|
; // eslint-disable-line semi-style
|
|
306
308
|
|
|
307
309
|
export type FileTypeResult = {
|
|
@@ -327,8 +329,8 @@ The file type is detected by checking the [magic number](https://en.wikipedia.or
|
|
|
327
329
|
|
|
328
330
|
If file access is available, it is recommended to use `.fromFile()` instead.
|
|
329
331
|
|
|
330
|
-
@param buffer - An Uint8Array or Buffer representing file data. It works best if the buffer contains the entire file
|
|
331
|
-
@returns The detected file type
|
|
332
|
+
@param buffer - An Uint8Array or Buffer representing file data. It works best if the buffer contains the entire file. It may work with a smaller portion as well.
|
|
333
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
332
334
|
*/
|
|
333
335
|
export function fileTypeFromBuffer(buffer: Uint8Array | ArrayBuffer): Promise<FileTypeResult | undefined>;
|
|
334
336
|
|
|
@@ -338,7 +340,7 @@ Detect the file type of a Node.js [readable stream](https://nodejs.org/api/strea
|
|
|
338
340
|
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
339
341
|
|
|
340
342
|
@param stream - A readable stream representing file data.
|
|
341
|
-
@returns The detected file type
|
|
343
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
342
344
|
*/
|
|
343
345
|
export function fileTypeFromStream(stream: ReadableStream): Promise<FileTypeResult | undefined>;
|
|
344
346
|
|
|
@@ -350,7 +352,7 @@ This method is used internally, but can also be used for a special "tokenizer" r
|
|
|
350
352
|
A tokenizer propagates the internal read functions, allowing alternative transport mechanisms, to access files, to be implemented and used.
|
|
351
353
|
|
|
352
354
|
@param tokenizer - File source implementing the tokenizer interface.
|
|
353
|
-
@returns The detected file type
|
|
355
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
354
356
|
|
|
355
357
|
An example is [`@tokenizer/http`](https://github.com/Borewit/tokenizer-http), which requests data using [HTTP-range-requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests). A difference with a conventional stream and the [*tokenizer*](https://github.com/Borewit/strtok3#tokenizer), is that it is able to *ignore* (seek, fast-forward) in the stream. For example, you may only need and read the first 6 bytes, and the last 128 bytes, which may be an advantage in case reading the entire file would take longer.
|
|
356
358
|
|
|
@@ -421,19 +423,108 @@ if (stream2.fileType?.mime === 'image/jpeg') {
|
|
|
421
423
|
export function fileTypeStream(readableStream: ReadableStream, options?: StreamOptions): Promise<ReadableStreamWithFileType>;
|
|
422
424
|
|
|
423
425
|
/**
|
|
424
|
-
Detect the file type of a [`Blob`](https://nodejs.org/api/buffer.html#class-blob).
|
|
426
|
+
Detect the file type of a [`Blob`](https://nodejs.org/api/buffer.html#class-blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).
|
|
427
|
+
|
|
428
|
+
@param blob - The [`Blob`](https://nodejs.org/api/buffer.html#class-blob) used for file detection.
|
|
429
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
425
430
|
|
|
426
431
|
@example
|
|
427
432
|
```
|
|
428
433
|
import {fileTypeFromBlob} from 'file-type';
|
|
429
434
|
|
|
430
435
|
const blob = new Blob(['<?xml version="1.0" encoding="ISO-8859-1" ?>'], {
|
|
431
|
-
type: 'plain
|
|
436
|
+
type: 'text/plain',
|
|
432
437
|
endings: 'native'
|
|
433
438
|
});
|
|
434
439
|
|
|
435
440
|
console.log(await fileTypeFromBlob(blob));
|
|
436
|
-
//=> {ext: 'txt', mime: 'plain
|
|
441
|
+
//=> {ext: 'txt', mime: 'text/plain'}
|
|
437
442
|
```
|
|
438
443
|
*/
|
|
439
444
|
export declare function fileTypeFromBlob(blob: Blob): Promise<FileTypeResult | undefined>;
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
Function that allows specifying custom detection mechanisms.
|
|
448
|
+
|
|
449
|
+
An iterable of detectors can be provided via the `fileTypeOptions` argument for the {@link FileTypeParser.constructor}.
|
|
450
|
+
|
|
451
|
+
The detectors are called before the default detections in the provided order.
|
|
452
|
+
|
|
453
|
+
Custom detectors can be used to add new `FileTypeResults` or to modify return behavior of existing `FileTypeResult` detections.
|
|
454
|
+
|
|
455
|
+
If the detector returns `undefined`, there are 2 possible scenarios:
|
|
456
|
+
|
|
457
|
+
1. The detector has not read from the tokenizer, it will be proceeded with the next available detector.
|
|
458
|
+
2. The detector has read from the tokenizer (`tokenizer.position` has been increased).
|
|
459
|
+
In that case no further detectors will be executed and the final conclusion is that file-type returns undefined.
|
|
460
|
+
Note that this an exceptional scenario, as the detector takes the opportunity from any other detector to determine the file type.
|
|
461
|
+
|
|
462
|
+
Example detector array which can be extended and provided via the fileTypeOptions argument:
|
|
463
|
+
|
|
464
|
+
```
|
|
465
|
+
import {FileTypeParser} from 'file-type';
|
|
466
|
+
|
|
467
|
+
const customDetectors = [
|
|
468
|
+
async tokenizer => {
|
|
469
|
+
const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // 'UNICORN' as decimal string
|
|
470
|
+
|
|
471
|
+
const buffer = Buffer.alloc(7);
|
|
472
|
+
await tokenizer.peekBuffer(buffer, {length: unicornHeader.length, mayBeLess: true});
|
|
473
|
+
if (unicornHeader.every((value, index) => value === buffer[index])) {
|
|
474
|
+
return {ext: 'unicorn', mime: 'application/unicorn'};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return undefined;
|
|
478
|
+
},
|
|
479
|
+
];
|
|
480
|
+
|
|
481
|
+
const buffer = Buffer.from('UNICORN');
|
|
482
|
+
const parser = new FileTypeParser({customDetectors});
|
|
483
|
+
const fileType = await parser.fromBuffer(buffer);
|
|
484
|
+
console.log(fileType);
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
@param tokenizer - The [tokenizer](https://github.com/Borewit/strtok3#tokenizer) used to read the file content from.
|
|
488
|
+
@param fileType - The file type detected by the standard detections or a previous custom detection, or `undefined`` if no matching file type could be found.
|
|
489
|
+
@returns The detected file type, or `undefined` when there is no match.
|
|
490
|
+
*/
|
|
491
|
+
export type Detector = (tokenizer: ITokenizer, fileType?: FileTypeResult) => Promise<FileTypeResult | undefined>;
|
|
492
|
+
|
|
493
|
+
export type FileTypeOptions = {
|
|
494
|
+
customDetectors?: Iterable<Detector>;
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
export declare class TokenizerPositionError extends Error {
|
|
498
|
+
constructor(message?: string);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
export declare class FileTypeParser {
|
|
502
|
+
detectors: Iterable<Detector>;
|
|
503
|
+
|
|
504
|
+
constructor(options?: {customDetectors?: Iterable<Detector>});
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
Works the same way as {@link fileTypeFromBuffer}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
508
|
+
*/
|
|
509
|
+
fromBuffer(buffer: Uint8Array | ArrayBuffer): Promise<FileTypeResult | undefined>;
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
Works the same way as {@link fileTypeFromStream}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
513
|
+
*/
|
|
514
|
+
fromStream(stream: ReadableStream): Promise<FileTypeResult | undefined>;
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
Works the same way as {@link fileTypeFromTokenizer}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
518
|
+
*/
|
|
519
|
+
fromTokenizer(tokenizer: ITokenizer): Promise<FileTypeResult | undefined>;
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
Works the same way as {@link fileTypeFromBlob}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
523
|
+
*/
|
|
524
|
+
fromBlob(blob: Blob): Promise<FileTypeResult | undefined>;
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
Works the same way as {@link fileTypeStream}, additionally taking into account custom detectors (if any were provided to the constructor).
|
|
528
|
+
*/
|
|
529
|
+
toDetectionStream(readableStream: ReadableStream, options?: StreamOptions): Promise<FileTypeResult | undefined>;
|
|
530
|
+
}
|
package/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Buffer} from 'node:buffer';
|
|
2
2
|
import * as Token from 'token-types';
|
|
3
|
-
import * as strtok3 from 'strtok3/core';
|
|
3
|
+
import * as strtok3 from 'strtok3/core';
|
|
4
4
|
import {
|
|
5
5
|
stringToBytes,
|
|
6
6
|
tarHeaderChecksumMatches,
|
|
@@ -11,31 +11,15 @@ import {extensions, mimeTypes} from './supported.js';
|
|
|
11
11
|
const minimumBytes = 4100; // A fair amount of file-types are detectable within this range.
|
|
12
12
|
|
|
13
13
|
export async function fileTypeFromStream(stream) {
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
return await fileTypeFromTokenizer(tokenizer);
|
|
17
|
-
} finally {
|
|
18
|
-
await tokenizer.close();
|
|
19
|
-
}
|
|
14
|
+
return new FileTypeParser().fromStream(stream);
|
|
20
15
|
}
|
|
21
16
|
|
|
22
17
|
export async function fileTypeFromBuffer(input) {
|
|
23
|
-
|
|
24
|
-
throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
28
|
-
|
|
29
|
-
if (!(buffer?.length > 1)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return fileTypeFromTokenizer(strtok3.fromBuffer(buffer));
|
|
18
|
+
return new FileTypeParser().fromBuffer(input);
|
|
34
19
|
}
|
|
35
20
|
|
|
36
21
|
export async function fileTypeFromBlob(blob) {
|
|
37
|
-
|
|
38
|
-
return fileTypeFromBuffer(new Uint8Array(buffer));
|
|
22
|
+
return new FileTypeParser().fromBlob(blob);
|
|
39
23
|
}
|
|
40
24
|
|
|
41
25
|
function _check(buffer, headers, options) {
|
|
@@ -60,16 +44,98 @@ function _check(buffer, headers, options) {
|
|
|
60
44
|
}
|
|
61
45
|
|
|
62
46
|
export async function fileTypeFromTokenizer(tokenizer) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
47
|
+
return new FileTypeParser().fromTokenizer(tokenizer);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class FileTypeParser {
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.detectors = options?.customDetectors;
|
|
53
|
+
|
|
54
|
+
this.fromTokenizer = this.fromTokenizer.bind(this);
|
|
55
|
+
this.fromBuffer = this.fromBuffer.bind(this);
|
|
56
|
+
this.parse = this.parse.bind(this);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async fromTokenizer(tokenizer) {
|
|
60
|
+
const initialPosition = tokenizer.position;
|
|
61
|
+
|
|
62
|
+
for (const detector of this.detectors || []) {
|
|
63
|
+
const fileType = await detector(tokenizer);
|
|
64
|
+
if (fileType) {
|
|
65
|
+
return fileType;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (initialPosition !== tokenizer.position) {
|
|
69
|
+
return undefined; // Cannot proceed scanning of the tokenizer is at an arbitrary position
|
|
70
|
+
}
|
|
68
71
|
}
|
|
72
|
+
|
|
73
|
+
return this.parse(tokenizer);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async fromBuffer(input) {
|
|
77
|
+
if (!(input instanceof Uint8Array || input instanceof ArrayBuffer)) {
|
|
78
|
+
throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
82
|
+
|
|
83
|
+
if (!(buffer?.length > 1)) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return this.fromTokenizer(strtok3.fromBuffer(buffer));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async fromBlob(blob) {
|
|
91
|
+
const buffer = await blob.arrayBuffer();
|
|
92
|
+
return this.fromBuffer(new Uint8Array(buffer));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async fromStream(stream) {
|
|
96
|
+
const tokenizer = await strtok3.fromStream(stream);
|
|
97
|
+
try {
|
|
98
|
+
return await this.fromTokenizer(tokenizer);
|
|
99
|
+
} finally {
|
|
100
|
+
await tokenizer.close();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async toDetectionStream(readableStream, options = {}) {
|
|
105
|
+
const {default: stream} = await import('node:stream');
|
|
106
|
+
const {sampleSize = minimumBytes} = options;
|
|
107
|
+
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
readableStream.on('error', reject);
|
|
110
|
+
|
|
111
|
+
readableStream.once('readable', () => {
|
|
112
|
+
(async () => {
|
|
113
|
+
try {
|
|
114
|
+
// Set up output stream
|
|
115
|
+
const pass = new stream.PassThrough();
|
|
116
|
+
const outputStream = stream.pipeline ? stream.pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
|
|
117
|
+
|
|
118
|
+
// Read the input stream and detect the filetype
|
|
119
|
+
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? Buffer.alloc(0);
|
|
120
|
+
try {
|
|
121
|
+
pass.fileType = await this.fromBuffer(chunk);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error instanceof strtok3.EndOfStreamError) {
|
|
124
|
+
pass.fileType = undefined;
|
|
125
|
+
} else {
|
|
126
|
+
reject(error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
resolve(outputStream);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
reject(error);
|
|
133
|
+
}
|
|
134
|
+
})();
|
|
135
|
+
});
|
|
136
|
+
});
|
|
69
137
|
}
|
|
70
|
-
}
|
|
71
138
|
|
|
72
|
-
class FileTypeParser {
|
|
73
139
|
check(header, options) {
|
|
74
140
|
return _check(this.buffer, header, options);
|
|
75
141
|
}
|
|
@@ -211,7 +277,7 @@ class FileTypeParser {
|
|
|
211
277
|
}
|
|
212
278
|
|
|
213
279
|
await tokenizer.ignore(id3HeaderLength);
|
|
214
|
-
return
|
|
280
|
+
return this.fromTokenizer(tokenizer); // Skip ID3 header, recursion
|
|
215
281
|
}
|
|
216
282
|
|
|
217
283
|
// Musepack, SV7
|
|
@@ -728,7 +794,7 @@ class FileTypeParser {
|
|
|
728
794
|
const element = await readElement();
|
|
729
795
|
if (element.id === 0x42_82) {
|
|
730
796
|
const rawValue = await tokenizer.readToken(new Token.StringType(element.len, 'utf-8'));
|
|
731
|
-
return rawValue.
|
|
797
|
+
return rawValue.replaceAll(/\00.*$/g, ''); // Return DocType
|
|
732
798
|
}
|
|
733
799
|
|
|
734
800
|
await tokenizer.ignore(element.len); // ignore payload
|
|
@@ -769,7 +835,7 @@ class FileTypeParser {
|
|
|
769
835
|
if (this.check([0x57, 0x41, 0x56, 0x45], {offset: 8})) {
|
|
770
836
|
return {
|
|
771
837
|
ext: 'wav',
|
|
772
|
-
mime: 'audio/
|
|
838
|
+
mime: 'audio/wav',
|
|
773
839
|
};
|
|
774
840
|
}
|
|
775
841
|
|
|
@@ -1440,6 +1506,13 @@ class FileTypeParser {
|
|
|
1440
1506
|
};
|
|
1441
1507
|
}
|
|
1442
1508
|
|
|
1509
|
+
if (this.checkString('Kaydara FBX Binary \u0000')) {
|
|
1510
|
+
return {
|
|
1511
|
+
ext: 'fbx',
|
|
1512
|
+
mime: 'application/x.autodesk.fbx', // Invented by us
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1443
1516
|
if (
|
|
1444
1517
|
this.check([0x4C, 0x50], {offset: 34})
|
|
1445
1518
|
&& (
|
|
@@ -1609,39 +1682,8 @@ class FileTypeParser {
|
|
|
1609
1682
|
}
|
|
1610
1683
|
}
|
|
1611
1684
|
|
|
1612
|
-
export async function fileTypeStream(readableStream,
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
return new Promise((resolve, reject) => {
|
|
1616
|
-
readableStream.on('error', reject);
|
|
1617
|
-
|
|
1618
|
-
readableStream.once('readable', () => {
|
|
1619
|
-
(async () => {
|
|
1620
|
-
try {
|
|
1621
|
-
// Set up output stream
|
|
1622
|
-
const pass = new stream.PassThrough();
|
|
1623
|
-
const outputStream = stream.pipeline ? stream.pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
|
|
1624
|
-
|
|
1625
|
-
// Read the input stream and detect the filetype
|
|
1626
|
-
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? Buffer.alloc(0);
|
|
1627
|
-
try {
|
|
1628
|
-
const fileType = await fileTypeFromBuffer(chunk);
|
|
1629
|
-
pass.fileType = fileType;
|
|
1630
|
-
} catch (error) {
|
|
1631
|
-
if (error instanceof strtok3.EndOfStreamError) {
|
|
1632
|
-
pass.fileType = undefined;
|
|
1633
|
-
} else {
|
|
1634
|
-
reject(error);
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
|
|
1638
|
-
resolve(outputStream);
|
|
1639
|
-
} catch (error) {
|
|
1640
|
-
reject(error);
|
|
1641
|
-
}
|
|
1642
|
-
})();
|
|
1643
|
-
});
|
|
1644
|
-
});
|
|
1685
|
+
export async function fileTypeStream(readableStream, options = {}) {
|
|
1686
|
+
return new FileTypeParser().toDetectionStream(readableStream, options);
|
|
1645
1687
|
}
|
|
1646
1688
|
|
|
1647
1689
|
export const supportedExtensions = new Set(extensions);
|
package/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as strtok3 from 'strtok3';
|
|
2
|
-
import {
|
|
2
|
+
import {FileTypeParser} from './core.js';
|
|
3
3
|
|
|
4
|
-
export async function fileTypeFromFile(path) {
|
|
4
|
+
export async function fileTypeFromFile(path, fileTypeOptions) {
|
|
5
5
|
const tokenizer = await strtok3.fromFile(path);
|
|
6
6
|
try {
|
|
7
|
-
|
|
7
|
+
const parser = new FileTypeParser(fileTypeOptions);
|
|
8
|
+
return await parser.fromTokenizer(tokenizer);
|
|
8
9
|
} finally {
|
|
9
10
|
await tokenizer.close();
|
|
10
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "file-type",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "19.0.0",
|
|
4
4
|
"description": "Detect the file type of a Buffer/Uint8Array/ArrayBuffer",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "sindresorhus/file-type",
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
},
|
|
19
19
|
"./core": "./core.js"
|
|
20
20
|
},
|
|
21
|
+
"sideEffects": false,
|
|
21
22
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
23
|
+
"node": ">=18"
|
|
23
24
|
},
|
|
24
25
|
"scripts": {
|
|
25
26
|
"test": "xo && ava && tsd"
|
|
@@ -205,7 +206,8 @@
|
|
|
205
206
|
"cpio",
|
|
206
207
|
"ace",
|
|
207
208
|
"avro",
|
|
208
|
-
"icc"
|
|
209
|
+
"icc",
|
|
210
|
+
"fbx"
|
|
209
211
|
],
|
|
210
212
|
"dependencies": {
|
|
211
213
|
"readable-web-to-node-stream": "^3.0.2",
|
|
@@ -214,18 +216,21 @@
|
|
|
214
216
|
},
|
|
215
217
|
"devDependencies": {
|
|
216
218
|
"@tokenizer/token": "^0.3.0",
|
|
217
|
-
"@types/node": "^20.
|
|
218
|
-
"ava": "^
|
|
219
|
+
"@types/node": "^20.10.7",
|
|
220
|
+
"ava": "^6.0.1",
|
|
219
221
|
"commonmark": "^0.30.0",
|
|
220
222
|
"noop-stream": "^1.0.0",
|
|
221
|
-
"tsd": "^0.
|
|
222
|
-
"xo": "^0.
|
|
223
|
+
"tsd": "^0.30.3",
|
|
224
|
+
"xo": "^0.56.0"
|
|
223
225
|
},
|
|
224
226
|
"xo": {
|
|
225
227
|
"envs": [
|
|
226
228
|
"node",
|
|
227
229
|
"browser"
|
|
228
230
|
],
|
|
231
|
+
"ignores": [
|
|
232
|
+
"fixture"
|
|
233
|
+
],
|
|
229
234
|
"rules": {
|
|
230
235
|
"no-inner-declarations": "warn",
|
|
231
236
|
"no-await-in-loop": "warn",
|
package/readme.md
CHANGED
|
@@ -113,7 +113,7 @@ The file type is detected by checking the [magic number](https://en.wikipedia.or
|
|
|
113
113
|
|
|
114
114
|
If file access is available, it is recommended to use `fileTypeFromFile()` instead.
|
|
115
115
|
|
|
116
|
-
Returns a `Promise` for an object with the detected file type
|
|
116
|
+
Returns a `Promise` for an object with the detected file type:
|
|
117
117
|
|
|
118
118
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
119
119
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -124,7 +124,7 @@ Or `undefined` when there is no match.
|
|
|
124
124
|
|
|
125
125
|
Type: `Buffer | Uint8Array | ArrayBuffer`
|
|
126
126
|
|
|
127
|
-
A buffer representing file data. It works best if the buffer contains the entire file
|
|
127
|
+
A buffer representing file data. It works best if the buffer contains the entire file. It may work with a smaller portion as well.
|
|
128
128
|
|
|
129
129
|
### fileTypeFromFile(filePath)
|
|
130
130
|
|
|
@@ -132,7 +132,7 @@ Detect the file type of a file path.
|
|
|
132
132
|
|
|
133
133
|
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
134
134
|
|
|
135
|
-
Returns a `Promise` for an object with the detected file type
|
|
135
|
+
Returns a `Promise` for an object with the detected file type:
|
|
136
136
|
|
|
137
137
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
138
138
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -151,7 +151,7 @@ Detect the file type of a Node.js [readable stream](https://nodejs.org/api/strea
|
|
|
151
151
|
|
|
152
152
|
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
153
153
|
|
|
154
|
-
Returns a `Promise` for an object with the detected file type
|
|
154
|
+
Returns a `Promise` for an object with the detected file type:
|
|
155
155
|
|
|
156
156
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
157
157
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -170,7 +170,7 @@ Detect the file type of a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/
|
|
|
170
170
|
|
|
171
171
|
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
172
172
|
|
|
173
|
-
Returns a `Promise` for an object with the detected file type
|
|
173
|
+
Returns a `Promise` for an object with the detected file type:
|
|
174
174
|
|
|
175
175
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
176
176
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -181,14 +181,18 @@ Or `undefined` when there is no match.
|
|
|
181
181
|
import {fileTypeFromBlob} from 'file-type';
|
|
182
182
|
|
|
183
183
|
const blob = new Blob(['<?xml version="1.0" encoding="ISO-8859-1" ?>'], {
|
|
184
|
-
type: 'plain
|
|
184
|
+
type: 'text/plain',
|
|
185
185
|
endings: 'native'
|
|
186
186
|
});
|
|
187
187
|
|
|
188
188
|
console.log(await fileTypeFromBlob(blob));
|
|
189
|
-
//=> {ext: 'txt', mime: 'plain
|
|
189
|
+
//=> {ext: 'txt', mime: 'text/plain'}
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
+
#### blob
|
|
193
|
+
|
|
194
|
+
Type: [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
|
195
|
+
|
|
192
196
|
### fileTypeFromTokenizer(tokenizer)
|
|
193
197
|
|
|
194
198
|
Detect the file type from an `ITokenizer` source.
|
|
@@ -197,7 +201,7 @@ This method is used internally, but can also be used for a special "tokenizer" r
|
|
|
197
201
|
|
|
198
202
|
A tokenizer propagates the internal read functions, allowing alternative transport mechanisms, to access files, to be implemented and used.
|
|
199
203
|
|
|
200
|
-
Returns a `Promise` for an object with the detected file type
|
|
204
|
+
Returns a `Promise` for an object with the detected file type:
|
|
201
205
|
|
|
202
206
|
- `ext` - One of the [supported file types](#supported-file-types)
|
|
203
207
|
- `mime` - The [MIME type](https://en.wikipedia.org/wiki/Internet_media_type)
|
|
@@ -305,6 +309,49 @@ Returns a `Set<string>` of supported file extensions.
|
|
|
305
309
|
|
|
306
310
|
Returns a `Set<string>` of supported MIME types.
|
|
307
311
|
|
|
312
|
+
## Custom detectors
|
|
313
|
+
|
|
314
|
+
A custom detector is a function that allows specifying custom detection mechanisms.
|
|
315
|
+
|
|
316
|
+
An iterable of detectors can be provided via the `fileTypeOptions` argument for the `FileTypeParser` constructor.
|
|
317
|
+
|
|
318
|
+
The detectors are called before the default detections in the provided order.
|
|
319
|
+
|
|
320
|
+
Custom detectors can be used to add new `FileTypeResults` or to modify return behaviour of existing `FileTypeResult` detections.
|
|
321
|
+
|
|
322
|
+
If the detector returns `undefined`, there are 2 possible scenarios:
|
|
323
|
+
|
|
324
|
+
1. The detector has not read from the tokenizer, it will be proceeded with the next available detector.
|
|
325
|
+
2. The detector has read from the tokenizer (`tokenizer.position` has been increased).
|
|
326
|
+
In that case no further detectors will be executed and the final conclusion is that file-type returns undefined.
|
|
327
|
+
Note that this an exceptional scenario, as the detector takes the opportunity from any other detector to determine the file type.
|
|
328
|
+
|
|
329
|
+
Example detector array which can be extended and provided to each public method via the `fileTypeOptions` argument:
|
|
330
|
+
|
|
331
|
+
```js
|
|
332
|
+
import {FileTypeParser} from 'file-type';
|
|
333
|
+
|
|
334
|
+
const customDetectors = [
|
|
335
|
+
async tokenizer => {
|
|
336
|
+
const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // 'UNICORN' as decimal string
|
|
337
|
+
|
|
338
|
+
const buffer = Buffer.alloc(7);
|
|
339
|
+
await tokenizer.peekBuffer(buffer, {length: unicornHeader.length, mayBeLess: true});
|
|
340
|
+
|
|
341
|
+
if (unicornHeader.every((value, index) => value === buffer[index])) {
|
|
342
|
+
return {ext: 'unicorn', mime: 'application/unicorn'};
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return undefined;
|
|
346
|
+
},
|
|
347
|
+
];
|
|
348
|
+
|
|
349
|
+
const buffer = Buffer.from('UNICORN');
|
|
350
|
+
const parser = new FileTypeParser({customDetectors});
|
|
351
|
+
const fileType = await parser.fromBuffer(buffer);
|
|
352
|
+
console.log(fileType);
|
|
353
|
+
```
|
|
354
|
+
|
|
308
355
|
## Supported file types
|
|
309
356
|
|
|
310
357
|
- [`3g2`](https://en.wikipedia.org/wiki/3GP_and_3G2#3G2) - Multimedia container format defined by the 3GPP2 for 3G CDMA2000 multimedia services
|
|
@@ -335,7 +382,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
335
382
|
- [`bpg`](https://bellard.org/bpg/) - Better Portable Graphics file
|
|
336
383
|
- [`bz2`](https://en.wikipedia.org/wiki/Bzip2) - Archive file
|
|
337
384
|
- [`cab`](https://en.wikipedia.org/wiki/Cabinet_(file_format)) - Cabinet file
|
|
338
|
-
- [`cfb`](https://en.wikipedia.org/wiki/Compound_File_Binary_Format) -
|
|
385
|
+
- [`cfb`](https://en.wikipedia.org/wiki/Compound_File_Binary_Format) - Compound File Binary Format
|
|
339
386
|
- [`chm`](https://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help) - Microsoft Compiled HTML Help
|
|
340
387
|
- [`class`](https://en.wikipedia.org/wiki/Java_class_file) - Java class file
|
|
341
388
|
- [`cpio`](https://en.wikipedia.org/wiki/Cpio) - Cpio archive
|
|
@@ -347,7 +394,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
347
394
|
- [`deb`](https://en.wikipedia.org/wiki/Deb_(file_format)) - Debian package
|
|
348
395
|
- [`dmg`](https://en.wikipedia.org/wiki/Apple_Disk_Image) - Apple Disk Image
|
|
349
396
|
- [`dng`](https://en.wikipedia.org/wiki/Digital_Negative) - Adobe Digital Negative image file
|
|
350
|
-
- [`docx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Word
|
|
397
|
+
- [`docx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Word document
|
|
351
398
|
- [`dsf`](https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf) - Sony DSD Stream File (DSF)
|
|
352
399
|
- [`dwg`](https://en.wikipedia.org/wiki/.dwg) - Autodesk CAD file
|
|
353
400
|
- [`elf`](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) - Unix Executable and Linkable Format
|
|
@@ -359,6 +406,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
359
406
|
- [`f4b`](https://en.wikipedia.org/wiki/Flash_Video) - Audiobook and podcast ISO base media file format used by Adobe Flash Player
|
|
360
407
|
- [`f4p`](https://en.wikipedia.org/wiki/Flash_Video) - ISO base media file format protected by Adobe Access DRM used by Adobe Flash Player
|
|
361
408
|
- [`f4v`](https://en.wikipedia.org/wiki/Flash_Video) - ISO base media file format used by Adobe Flash Player
|
|
409
|
+
- [`fbx`](https://en.wikipedia.org/wiki/FBX) - Filmbox is a proprietary file format used to provide interoperability between digital content creation apps.
|
|
362
410
|
- [`flac`](https://en.wikipedia.org/wiki/FLAC) - Free Lossless Audio Codec
|
|
363
411
|
- [`flif`](https://en.wikipedia.org/wiki/Free_Lossless_Image_Format) - Free Lossless Image Format
|
|
364
412
|
- [`flv`](https://en.wikipedia.org/wiki/Flash_Video) - Flash video
|
|
@@ -382,7 +430,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
382
430
|
- [`jxr`](https://en.wikipedia.org/wiki/JPEG_XR) - Joint Photographic Experts Group extended range
|
|
383
431
|
- [`ktx`](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/) - OpenGL and OpenGL ES textures
|
|
384
432
|
- [`lnk`](https://en.wikipedia.org/wiki/Shortcut_%28computing%29#Microsoft_Windows) - Microsoft Windows file shortcut
|
|
385
|
-
- [`lz`](https://en.wikipedia.org/wiki/Lzip) -
|
|
433
|
+
- [`lz`](https://en.wikipedia.org/wiki/Lzip) - Archive file
|
|
386
434
|
- [`lzh`](https://en.wikipedia.org/wiki/LHA_(file_format)) - LZH archive
|
|
387
435
|
- [`m4a`](https://en.wikipedia.org/wiki/M4A) - Audio-only MPEG-4 files
|
|
388
436
|
- [`m4b`](https://en.wikipedia.org/wiki/M4B) - Audiobook and podcast MPEG-4 files, which also contain metadata including chapter markers, images, and hyperlinks
|
|
@@ -421,7 +469,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
421
469
|
- [`pdf`](https://en.wikipedia.org/wiki/Portable_Document_Format) - Portable Document Format
|
|
422
470
|
- [`pgp`](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) - Pretty Good Privacy
|
|
423
471
|
- [`png`](https://en.wikipedia.org/wiki/Portable_Network_Graphics) - Portable Network Graphics
|
|
424
|
-
- [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Powerpoint
|
|
472
|
+
- [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Powerpoint document
|
|
425
473
|
- [`ps`](https://en.wikipedia.org/wiki/Postscript) - Postscript
|
|
426
474
|
- [`psd`](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) - Adobe Photoshop document
|
|
427
475
|
- [`pst`](https://en.wikipedia.org/wiki/Personal_Storage_Table) - Personal Storage Table file
|
|
@@ -451,7 +499,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
451
499
|
- [`woff2`](https://en.wikipedia.org/wiki/Web_Open_Font_Format) - Web Open Font Format
|
|
452
500
|
- [`wv`](https://en.wikipedia.org/wiki/WavPack) - WavPack
|
|
453
501
|
- [`xcf`](https://en.wikipedia.org/wiki/XCF_(file_format)) - eXperimental Computing Facility
|
|
454
|
-
- [`xlsx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Excel
|
|
502
|
+
- [`xlsx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Excel document
|
|
455
503
|
- [`xm`](https://wiki.openmpt.org/Manual:_Module_formats#The_FastTracker_2_format_.28.xm.29) - Audio module format: FastTracker 2
|
|
456
504
|
- [`xml`](https://en.wikipedia.org/wiki/XML) - eXtensible Markup Language
|
|
457
505
|
- [`xpi`](https://en.wikipedia.org/wiki/XPInstall) - XPInstall file
|
|
@@ -459,7 +507,7 @@ Returns a `Set<string>` of supported MIME types.
|
|
|
459
507
|
- [`zip`](https://en.wikipedia.org/wiki/Zip_(file_format)) - Archive file
|
|
460
508
|
- [`zst`](https://en.wikipedia.org/wiki/Zstandard) - Archive file
|
|
461
509
|
|
|
462
|
-
*Pull requests are welcome for additional commonly used file types.*
|
|
510
|
+
*[Pull requests](.github/pull_request_template.md) are welcome for additional commonly used file types.*
|
|
463
511
|
|
|
464
512
|
The following file types will not be accepted:
|
|
465
513
|
- [MS-CFB: Microsoft Compound File Binary File Format based formats](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb/53989ce4-7b05-4f8d-829b-d08d6148375b), too old and difficult to parse:
|
|
@@ -470,16 +518,26 @@ The following file types will not be accepted:
|
|
|
470
518
|
- `.csv` - [Reason.](https://github.com/sindresorhus/file-type/issues/264#issuecomment-568439196)
|
|
471
519
|
- `.svg` - Detecting it requires a full-blown parser. Check out [`is-svg`](https://github.com/sindresorhus/is-svg) for something that mostly works.
|
|
472
520
|
|
|
521
|
+
#### tokenizer
|
|
522
|
+
|
|
523
|
+
Type: [`ITokenizer`](https://github.com/Borewit/strtok3#tokenizer)
|
|
524
|
+
|
|
525
|
+
Usable as source of the examined file.
|
|
526
|
+
|
|
527
|
+
#### fileType
|
|
528
|
+
|
|
529
|
+
Type: `FileTypeResult`
|
|
530
|
+
|
|
531
|
+
An object having an `ext` (extension) and `mime` (mime type) property.
|
|
532
|
+
|
|
533
|
+
Detected by the standard detections or a previous custom detection. Undefined if no matching fileTypeResult could be found.
|
|
534
|
+
|
|
473
535
|
## Related
|
|
474
536
|
|
|
475
537
|
- [file-type-cli](https://github.com/sindresorhus/file-type-cli) - CLI for this module
|
|
538
|
+
- [image-dimensions](https://github.com/sindresorhus/image-dimensions) - Get the dimensions of an image
|
|
476
539
|
|
|
477
540
|
## Maintainers
|
|
478
541
|
|
|
479
542
|
- [Sindre Sorhus](https://github.com/sindresorhus)
|
|
480
543
|
- [Borewit](https://github.com/Borewit)
|
|
481
|
-
|
|
482
|
-
**Former**
|
|
483
|
-
|
|
484
|
-
- [Mikael Finstad](https://github.com/mifi)
|
|
485
|
-
- [Ben Brook](https://github.com/bencmbrook)
|
package/supported.js
CHANGED
|
@@ -150,6 +150,7 @@ export const extensions = [
|
|
|
150
150
|
'ace',
|
|
151
151
|
'avro',
|
|
152
152
|
'icc',
|
|
153
|
+
'fbx',
|
|
153
154
|
];
|
|
154
155
|
|
|
155
156
|
export const mimeTypes = [
|
|
@@ -188,7 +189,7 @@ export const mimeTypes = [
|
|
|
188
189
|
'video/webm',
|
|
189
190
|
'video/quicktime',
|
|
190
191
|
'video/vnd.avi',
|
|
191
|
-
'audio/
|
|
192
|
+
'audio/wav',
|
|
192
193
|
'audio/qcelp',
|
|
193
194
|
'audio/x-ms-asf',
|
|
194
195
|
'video/x-ms-asf',
|
|
@@ -299,4 +300,5 @@ export const mimeTypes = [
|
|
|
299
300
|
'application/x-ace-compressed',
|
|
300
301
|
'application/avro',
|
|
301
302
|
'application/vnd.iccprofile',
|
|
303
|
+
'application/x.autodesk.fbx', // Invented by us
|
|
302
304
|
];
|