file-type 19.6.0 → 20.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/index.js CHANGED
@@ -5,9 +5,9 @@ Node.js specific entry point.
5
5
  import {ReadableStream as WebReadableStream} from 'node:stream/web';
6
6
  import {pipeline, PassThrough, Readable} from 'node:stream';
7
7
  import * as strtok3 from 'strtok3';
8
- import {FileTypeParser, reasonableDetectionSizeInBytes} from './core.js';
8
+ import {FileTypeParser as DefaultFileTypeParser, reasonableDetectionSizeInBytes} from './core.js';
9
9
 
10
- export class NodeFileTypeParser extends FileTypeParser {
10
+ export class FileTypeParser extends DefaultFileTypeParser {
11
11
  async fromStream(stream) {
12
12
  const tokenizer = await (stream instanceof WebReadableStream ? strtok3.fromWebStream(stream, this.tokenizerOptions) : strtok3.fromStream(stream, this.tokenizerOptions));
13
13
  try {
@@ -66,15 +66,21 @@ export class NodeFileTypeParser extends FileTypeParser {
66
66
  }
67
67
 
68
68
  export async function fileTypeFromFile(path, fileTypeOptions) {
69
- return (new NodeFileTypeParser(fileTypeOptions)).fromFile(path, fileTypeOptions);
69
+ return (new FileTypeParser(fileTypeOptions)).fromFile(path, fileTypeOptions);
70
70
  }
71
71
 
72
72
  export async function fileTypeFromStream(stream, fileTypeOptions) {
73
- return (new NodeFileTypeParser(fileTypeOptions)).fromStream(stream);
73
+ return (new FileTypeParser(fileTypeOptions)).fromStream(stream);
74
74
  }
75
75
 
76
76
  export async function fileTypeStream(readableStream, options = {}) {
77
- return new NodeFileTypeParser(options).toDetectionStream(readableStream, options);
77
+ return new FileTypeParser(options).toDetectionStream(readableStream, options);
78
78
  }
79
79
 
80
- export {fileTypeFromTokenizer, fileTypeFromBuffer, fileTypeFromBlob, FileTypeParser, supportedMimeTypes, supportedExtensions} from './core.js';
80
+ export {
81
+ fileTypeFromTokenizer,
82
+ fileTypeFromBuffer,
83
+ fileTypeFromBlob,
84
+ supportedMimeTypes,
85
+ supportedExtensions,
86
+ } from './core.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "file-type",
3
- "version": "19.6.0",
3
+ "version": "20.0.0",
4
4
  "description": "Detect the file type of a file, stream, or data",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/file-type",
@@ -217,22 +217,40 @@
217
217
  "fbx",
218
218
  "vsdx",
219
219
  "vtt",
220
- "apk"
220
+ "apk",
221
+ "drc",
222
+ "lz4",
223
+ "potx",
224
+ "xltx",
225
+ "dotx",
226
+ "xltm",
227
+ "ots",
228
+ "odg",
229
+ "otg",
230
+ "otp",
231
+ "ott",
232
+ "xlsm",
233
+ "docm",
234
+ "dotm",
235
+ "potm",
236
+ "pptm",
237
+ "jar"
221
238
  ],
222
239
  "dependencies": {
223
- "get-stream": "^9.0.1",
224
- "strtok3": "^9.0.1",
240
+ "@tokenizer/inflate": "^0.2.6",
241
+ "strtok3": "^10.0.1",
225
242
  "token-types": "^6.0.0",
226
- "uint8array-extras": "^1.3.0"
243
+ "uint8array-extras": "^1.4.0"
227
244
  },
228
245
  "devDependencies": {
229
246
  "@tokenizer/token": "^0.3.0",
230
- "@types/node": "^20.10.7",
247
+ "@types/node": "^22.10.5",
231
248
  "ava": "^6.0.1",
232
- "commonmark": "^0.30.0",
249
+ "commonmark": "^0.31.2",
250
+ "get-stream": "^9.0.1",
233
251
  "noop-stream": "^1.0.0",
234
- "tsd": "^0.30.3",
235
- "xo": "^0.56.0"
252
+ "tsd": "^0.31.2",
253
+ "xo": "^0.60.0"
236
254
  },
237
255
  "xo": {
238
256
  "envs": [
package/readme.md CHANGED
@@ -16,13 +16,13 @@ We accept contributions for commonly used modern file formats, not historical or
16
16
  npm install file-type
17
17
  ```
18
18
 
19
- **This package is an ESM package. Your project needs to be ESM too. [Read more](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).**
19
+ **This package is an ESM package. Your project needs to be ESM too. [Read more](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). For TypeScript + CommonJS, see [`load-esm`](https://github.com/Borewit/load-esm).**
20
20
 
21
21
  If you use it with Webpack, you need the latest Webpack version and ensure you configure it correctly for ESM.
22
22
 
23
23
  ## Usage
24
24
 
25
- #### Node.js
25
+ ### Node.js
26
26
 
27
27
  Determine file type from a file:
28
28
 
@@ -91,7 +91,7 @@ const write = fs.createWriteStream(`decrypted.${streamWithFileType.fileType.ext}
91
91
  streamWithFileType.pipe(write);
92
92
  ```
93
93
 
94
- #### Browser
94
+ ### Browser
95
95
 
96
96
  ```js
97
97
  import {fileTypeFromStream} from 'file-type';
@@ -178,10 +178,10 @@ A readable stream representing file data.
178
178
 
179
179
  Detect the file type of a [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob),
180
180
 
181
- [!TIP]
181
+ > [!TIP]
182
182
  > A [`File` object](https://developer.mozilla.org/docs/Web/API/File) is a `Blob` and can be passed in here.
183
183
 
184
- It will **stream** the underlying Blob, and required a [ReadableStreamBYOBReader](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader) which **require Node.js ≥ 20**.
184
+ It will **stream** the underlying Blob.
185
185
 
186
186
  The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the blob.
187
187
 
@@ -204,6 +204,21 @@ console.log(await fileTypeFromBlob(blob));
204
204
  //=> {ext: 'txt', mime: 'text/plain'}
205
205
  ```
206
206
 
207
+ > [!WARNING]
208
+ > This method depends on [ReadableStreamBYOBReader](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader) which **requires Node.js ≥ 20**
209
+ > and [may not be available in all modern browsers](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader#browser_compatibility).
210
+
211
+ To work around this limitation, you can use an alternative approach to read and process the `Blob` without relying on streaming:
212
+
213
+ ```js
214
+ import {fileTypeFromBuffer} from 'file-type';
215
+
216
+ async function readFromBlobWithoutStreaming(blob) {
217
+ const buffer = await blob.arrayBuffer();
218
+ return fileTypeFromBuffer(buffer);
219
+ }
220
+ ```
221
+
207
222
  #### blob
208
223
 
209
224
  Type: [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
@@ -325,46 +340,58 @@ Returns a `Set<string>` of supported MIME types.
325
340
 
326
341
  ## Custom detectors
327
342
 
328
- A custom detector is a function that allows specifying custom detection mechanisms.
343
+ A custom file type detector.
329
344
 
330
- An iterable of detectors can be provided via the `fileTypeOptions` argument for the `FileTypeParser` constructor.
331
- In Node.js, you should use `NodeFileTypeParser`, which extends `FileTypeParser` and provides access to Node.js specific functions.
345
+ Detectors can be added via the constructor options or by directly modifying `FileTypeParser#detectors`.
332
346
 
333
- The detectors are called before the default detections in the provided order.
347
+ Detectors provided through the constructor options are executed before the default detectors.
334
348
 
335
- Custom detectors can be used to add new `FileTypeResults` or to modify return behaviour of existing `FileTypeResult` detections.
349
+ Custom detectors allow for:
350
+ - Introducing new `FileTypeResult` entries.
351
+ - Modifying the detection behavior of existing `FileTypeResult` types.
336
352
 
337
- If the detector returns `undefined`, there are 2 possible scenarios:
353
+ ### Detector execution flow
338
354
 
339
- 1. The detector has not read from the tokenizer, it will be proceeded with the next available detector.
340
- 2. The detector has read from the tokenizer (`tokenizer.position` has been increased).
341
- In that case no further detectors will be executed and the final conclusion is that file-type returns undefined.
342
- Note that this an exceptional scenario, as the detector takes the opportunity from any other detector to determine the file type.
355
+ If a detector returns `undefined`, the following rules apply:
343
356
 
344
- Example detector array which can be extended and provided to each public method via the `fileTypeOptions` argument:
357
+ 1. **No Tokenizer Interaction**: If the detector does not modify the tokenizer's position, the next detector in the sequence is executed.
358
+ 2. **Tokenizer Interaction**: If the detector modifies the tokenizer's position (`tokenizer.position` is advanced), no further detectors are executed. In this case, the file type remains `undefined`, as subsequent detectors cannot evaluate the content. This is an exceptional scenario, as it prevents any other detectors from determining the file type.
359
+
360
+ ### Example usage
361
+
362
+ Below is an example of a custom detector array. This can be passed to the `FileTypeParser` via the `fileTypeOptions` argument.
345
363
 
346
364
  ```js
347
- import {FileTypeParser} from 'file-type'; // or `NodeFileTypeParser` in Node.js
365
+ import {FileTypeParser} from 'file-type';
348
366
 
349
- const customDetectors = [
350
- async tokenizer => {
351
- const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // 'UNICORN' as decimal string
367
+ const unicornDetector = {
368
+ id: 'unicorn', // May be used to recognize the detector in the detector list
369
+ async detect(tokenizer) {
370
+ const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // "UNICORN" in ASCII decimal
352
371
 
353
- const buffer = new Uint8Array(7);
372
+ const buffer = new Uint8Array(unicornHeader.length);
354
373
  await tokenizer.peekBuffer(buffer, {length: unicornHeader.length, mayBeLess: true});
355
-
356
374
  if (unicornHeader.every((value, index) => value === buffer[index])) {
357
375
  return {ext: 'unicorn', mime: 'application/unicorn'};
358
376
  }
359
377
 
360
378
  return undefined;
361
- },
362
- ];
379
+ }
380
+ }
363
381
 
364
- const buffer = new Uint8Array(new TextEncoder().encode('UNICORN'));
365
- const parser = new FileTypeParser({customDetectors}); // `NodeFileTypeParser({customDetectors})` in Node.js
382
+ const buffer = new Uint8Array([85, 78, 73, 67, 79, 82, 78]);
383
+ const parser = new FileTypeParser({customDetectors: [unicornDetector]});
366
384
  const fileType = await parser.fromBuffer(buffer);
367
- console.log(fileType);
385
+ console.log(fileType); // {ext: 'unicorn', mime: 'application/unicorn'}
386
+ ```
387
+
388
+ ```ts
389
+ /**
390
+ @param tokenizer - The [tokenizer](https://github.com/Borewit/strtok3#tokenizer) used to read file content.
391
+ @param fileType - The file type detected by standard or previous custom detectors, or `undefined` if no match is found.
392
+ @returns The detected file type, or `undefined` if no match is found.
393
+ */
394
+ export type Detector = (tokenizer: ITokenizer, fileType?: FileTypeResult) => Promise<FileTypeResult | undefined>;
368
395
  ```
369
396
 
370
397
  ## Abort signal
@@ -372,7 +399,7 @@ console.log(fileType);
372
399
  Some async operations can be aborted by passing an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) to the `FileTypeParser` constructor.
373
400
 
374
401
  ```js
375
- import {FileTypeParser} from 'file-type'; // or `NodeFileTypeParser` in Node.js
402
+ import {FileTypeParser} from 'file-type';
376
403
 
377
404
  const abortController = new AbortController()
378
405
 
@@ -426,7 +453,11 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
426
453
  - [`deb`](https://en.wikipedia.org/wiki/Deb_(file_format)) - Debian package
427
454
  - [`dmg`](https://en.wikipedia.org/wiki/Apple_Disk_Image) - Apple Disk Image
428
455
  - [`dng`](https://en.wikipedia.org/wiki/Digital_Negative) - Adobe Digital Negative image file
456
+ - [`docm`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft Word macro-enabled document
429
457
  - [`docx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Word document
458
+ - [`dotm`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft Word macro-enabled template
459
+ - [`dotx`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft Word template
460
+ - [`drc`](https://en.wikipedia.org/wiki/Zstandard) - Google's Draco 3D Data Compression
430
461
  - [`dsf`](https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf) - Sony DSD Stream File (DSF)
431
462
  - [`dwg`](https://en.wikipedia.org/wiki/.dwg) - Autodesk CAD file
432
463
  - [`elf`](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) - Unix Executable and Linkable Format
@@ -453,6 +484,7 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
453
484
  - [`indd`](https://en.wikipedia.org/wiki/Adobe_InDesign#File_format) - Adobe InDesign document
454
485
  - [`it`](https://wiki.openmpt.org/Manual:_Module_formats#The_Impulse_Tracker_format_.28.it.29) - Audio module format: Impulse Tracker
455
486
  - [`j2c`](https://en.wikipedia.org/wiki/JPEG_2000) - JPEG 2000
487
+ - [`jar`](https://en.wikipedia.org/wiki/JAR_(file_format)) - Java archive
456
488
  - [`jls`](https://en.wikipedia.org/wiki/Lossless_JPEG#JPEG-LS) - Lossless/near-lossless compression standard for continuous-tone images
457
489
  - [`jp2`](https://en.wikipedia.org/wiki/JPEG_2000) - JPEG 2000
458
490
  - [`jpg`](https://en.wikipedia.org/wiki/JPEG) - Joint Photographic Experts Group image
@@ -463,6 +495,7 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
463
495
  - [`ktx`](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/) - OpenGL and OpenGL ES textures
464
496
  - [`lnk`](https://en.wikipedia.org/wiki/Shortcut_%28computing%29#Microsoft_Windows) - Microsoft Windows file shortcut
465
497
  - [`lz`](https://en.wikipedia.org/wiki/Lzip) - Archive file
498
+ - [`lz4`](https://en.wikipedia.org/wiki/LZ4_(compression_algorithm)) - Compressed archive created by one of a variety of LZ4 compression utilities
466
499
  - [`lzh`](https://en.wikipedia.org/wiki/LHA_(file_format)) - LZH archive
467
500
  - [`m4a`](https://en.wikipedia.org/wiki/M4A) - Audio-only MPEG-4 files
468
501
  - [`m4b`](https://en.wikipedia.org/wiki/M4B) - Audiobook and podcast MPEG-4 files, which also contain metadata including chapter markers, images, and hyperlinks
@@ -485,6 +518,7 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
485
518
  - [`mxf`](https://en.wikipedia.org/wiki/Material_Exchange_Format) - Material Exchange Format
486
519
  - [`nef`](https://www.nikonusa.com/en/learn-and-explore/a/products-and-innovation/nikon-electronic-format-nef.html) - Nikon Electronic Format image file
487
520
  - [`nes`](https://fileinfo.com/extension/nes) - Nintendo NES ROM
521
+ - [`odg`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for drawing
488
522
  - [`odp`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for presentations
489
523
  - [`ods`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for spreadsheets
490
524
  - [`odt`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for word processing
@@ -496,12 +530,19 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
496
530
  - [`opus`](https://en.wikipedia.org/wiki/Opus_(audio_format)) - Audio file
497
531
  - [`orf`](https://en.wikipedia.org/wiki/ORF_format) - Olympus Raw image file
498
532
  - [`otf`](https://en.wikipedia.org/wiki/OpenType) - OpenType font
533
+ - [`otg`](https://en.wikipedia.org/wiki/OpenDocument_technical_specification#Templates) - OpenDocument template for drawing
534
+ - [`otp`](https://en.wikipedia.org/wiki/OpenDocument_technical_specification#Templates) - OpenDocument template for presentations
535
+ - [`ots`](https://en.wikipedia.org/wiki/OpenDocument_technical_specification#Templates) - OpenDocument template for spreadsheets
536
+ - [`ott`](https://en.wikipedia.org/wiki/OpenDocument_technical_specification#Templates) - OpenDocument template for word processing
499
537
  - [`parquet`](https://en.wikipedia.org/wiki/Apache_Parquet) - Apache Parquet
500
538
  - [`pcap`](https://wiki.wireshark.org/Development/LibpcapFileFormat) - Libpcap File Format
501
539
  - [`pdf`](https://en.wikipedia.org/wiki/Portable_Document_Format) - Portable Document Format
502
540
  - [`pgp`](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) - Pretty Good Privacy
503
541
  - [`png`](https://en.wikipedia.org/wiki/Portable_Network_Graphics) - Portable Network Graphics
504
- - [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Powerpoint document
542
+ - [`potm`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft PowerPoint macro-enabled template
543
+ - [`potx`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft PowerPoint template
544
+ - [`pptm`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft PowerPoint macro-enabled document
545
+ - [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft PowerPoint document
505
546
  - [`ps`](https://en.wikipedia.org/wiki/Postscript) - Postscript
506
547
  - [`psd`](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) - Adobe Photoshop document
507
548
  - [`pst`](https://en.wikipedia.org/wiki/Personal_Storage_Table) - Personal Storage Table file
@@ -533,7 +574,10 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
533
574
  - [`woff2`](https://en.wikipedia.org/wiki/Web_Open_Font_Format) - Web Open Font Format
534
575
  - [`wv`](https://en.wikipedia.org/wiki/WavPack) - WavPack
535
576
  - [`xcf`](https://en.wikipedia.org/wiki/XCF_(file_format)) - eXperimental Computing Facility
577
+ - [`xlsm`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft Excel macro-enabled document
536
578
  - [`xlsx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft Excel document
579
+ - [`xltm`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft Excel macro-enabled template
580
+ - [`xltx`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft Excel template
537
581
  - [`xm`](https://wiki.openmpt.org/Manual:_Module_formats#The_FastTracker_2_format_.28.xm.29) - Audio module format: FastTracker 2
538
582
  - [`xml`](https://en.wikipedia.org/wiki/XML) - eXtensible Markup Language
539
583
  - [`xpi`](https://en.wikipedia.org/wiki/XPInstall) - XPInstall file
package/supported.js CHANGED
@@ -154,6 +154,23 @@ export const extensions = [
154
154
  'vsdx',
155
155
  'vtt',
156
156
  'apk',
157
+ 'drc',
158
+ 'lz4',
159
+ 'potx',
160
+ 'xltx',
161
+ 'dotx',
162
+ 'xltm',
163
+ 'ott',
164
+ 'ots',
165
+ 'otp',
166
+ 'odg',
167
+ 'otg',
168
+ 'xlsm',
169
+ 'docm',
170
+ 'dotm',
171
+ 'potm',
172
+ 'pptm',
173
+ 'jar',
157
174
  ];
158
175
 
159
176
  export const mimeTypes = [
@@ -307,4 +324,21 @@ export const mimeTypes = [
307
324
  'application/x.autodesk.fbx', // Invented by us
308
325
  'application/vnd.visio',
309
326
  'application/vnd.android.package-archive',
327
+ 'application/vnd.google.draco', // Invented by us
328
+ 'application/x-lz4', // Invented by us
329
+ 'application/vnd.openxmlformats-officedocument.presentationml.template',
330
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
331
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
332
+ 'application/vnd.ms-excel.template.macroenabled.12',
333
+ 'application/vnd.oasis.opendocument.text-template',
334
+ 'application/vnd.oasis.opendocument.spreadsheet-template',
335
+ 'application/vnd.oasis.opendocument.presentation-template',
336
+ 'application/vnd.oasis.opendocument.graphics',
337
+ 'application/vnd.oasis.opendocument.graphics-template',
338
+ 'application/vnd.ms-excel.sheet.macroEnabled.12',
339
+ 'application/vnd.ms-word.document.macroEnabled.12',
340
+ 'application/vnd.ms-word.template.macroEnabled.12',
341
+ 'application/vnd.ms-powerpoint.template.macroEnabled.12',
342
+ 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
343
+ 'application/java-archive',
310
344
  ];