file-type 17.1.4 → 18.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 +4 -4
- package/core.js +36 -25
- package/package.json +11 -12
- package/readme.md +3 -3
- package/util.js +5 -5
package/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {Readable as ReadableStream} from 'node:stream';
|
|
2
|
-
import {ITokenizer} from 'strtok3
|
|
2
|
+
import {ITokenizer} from 'strtok3';
|
|
3
3
|
|
|
4
4
|
export type FileExtension =
|
|
5
5
|
| 'jpg'
|
|
@@ -364,7 +364,7 @@ export interface StreamOptions {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
/**
|
|
367
|
-
Returns a `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `
|
|
367
|
+
Returns a `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
368
368
|
|
|
369
369
|
This method can be handy to put in between a stream, but it comes with a price.
|
|
370
370
|
Internally `stream()` builds up a buffer of `sampleSize` bytes, used as a sample, to determine the file type.
|
|
@@ -375,7 +375,7 @@ A smaller sample size will result in lower probability of the best file type det
|
|
|
375
375
|
**Note:** Requires Node.js 14 or later.
|
|
376
376
|
|
|
377
377
|
@param readableStream - A [readable stream](https://nodejs.org/api/stream.html#stream_class_stream_readable) containing a file to examine.
|
|
378
|
-
@returns A `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `
|
|
378
|
+
@returns A `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
379
379
|
|
|
380
380
|
@example
|
|
381
381
|
```
|
|
@@ -387,7 +387,7 @@ const url = 'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg';
|
|
|
387
387
|
const stream1 = got.stream(url);
|
|
388
388
|
const stream2 = await fileTypeStream(stream1, {sampleSize: 1024});
|
|
389
389
|
|
|
390
|
-
if (stream2.fileType
|
|
390
|
+
if (stream2.fileType?.mime === 'image/jpeg') {
|
|
391
391
|
// stream2 can be used to stream the JPEG image (from the very beginning of the stream)
|
|
392
392
|
}
|
|
393
393
|
```
|
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'; // eslint-disable-line n/file-extension-in-import
|
|
4
4
|
import {
|
|
5
5
|
stringToBytes,
|
|
6
6
|
tarHeaderChecksumMatches,
|
|
@@ -26,7 +26,7 @@ export async function fileTypeFromBuffer(input) {
|
|
|
26
26
|
|
|
27
27
|
const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
28
28
|
|
|
29
|
-
if (!(buffer
|
|
29
|
+
if (!(buffer?.length > 1)) {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -146,6 +146,12 @@ class FileTypeParser {
|
|
|
146
146
|
|
|
147
147
|
// -- 3-byte signatures --
|
|
148
148
|
|
|
149
|
+
if (this.check([0xEF, 0xBB, 0xBF])) { // UTF-8-BOM
|
|
150
|
+
// Strip off UTF-8-BOM
|
|
151
|
+
this.tokenizer.ignore(3);
|
|
152
|
+
return this.parse(tokenizer);
|
|
153
|
+
}
|
|
154
|
+
|
|
149
155
|
if (this.check([0x47, 0x49, 0x46])) {
|
|
150
156
|
return {
|
|
151
157
|
ext: 'gif',
|
|
@@ -331,7 +337,8 @@ class FileTypeParser {
|
|
|
331
337
|
// - one entry indicating specific type of file.
|
|
332
338
|
// MS Office, OpenOffice and LibreOffice may put the parts in different order, so the check should not rely on it.
|
|
333
339
|
if (zipHeader.filename === 'mimetype' && zipHeader.compressedSize === zipHeader.uncompressedSize) {
|
|
334
|
-
|
|
340
|
+
let mimeType = await tokenizer.readToken(new Token.StringType(zipHeader.compressedSize, 'utf-8'));
|
|
341
|
+
mimeType = mimeType.trim();
|
|
335
342
|
|
|
336
343
|
switch (mimeType) {
|
|
337
344
|
case 'application/epub+zip':
|
|
@@ -1016,13 +1023,6 @@ class FileTypeParser {
|
|
|
1016
1023
|
};
|
|
1017
1024
|
}
|
|
1018
1025
|
|
|
1019
|
-
if (this.check([0xEF, 0xBB, 0xBF]) && this.checkString('<?xml', {offset: 3})) { // UTF-8-BOM
|
|
1020
|
-
return {
|
|
1021
|
-
ext: 'xml',
|
|
1022
|
-
mime: 'application/xml',
|
|
1023
|
-
};
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
1026
|
// -- 9-byte signatures --
|
|
1027
1027
|
|
|
1028
1028
|
if (this.check([0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00, 0x18])) {
|
|
@@ -1160,14 +1160,15 @@ class FileTypeParser {
|
|
|
1160
1160
|
};
|
|
1161
1161
|
}
|
|
1162
1162
|
|
|
1163
|
-
if (
|
|
1164
|
-
this.check([
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1163
|
+
if (this.check([0xFE, 0xFF])) { // UTF-16-BOM-LE
|
|
1164
|
+
if (this.check([0, 60, 0, 63, 0, 120, 0, 109, 0, 108], {offset: 2})) {
|
|
1165
|
+
return {
|
|
1166
|
+
ext: 'xml',
|
|
1167
|
+
mime: 'application/xml',
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
return undefined; // Some unknown text based format
|
|
1171
1172
|
}
|
|
1172
1173
|
|
|
1173
1174
|
// -- Unsafe signatures --
|
|
@@ -1361,11 +1362,22 @@ class FileTypeParser {
|
|
|
1361
1362
|
};
|
|
1362
1363
|
}
|
|
1363
1364
|
|
|
1364
|
-
if (this.check([0xFF, 0xFE
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1365
|
+
if (this.check([0xFF, 0xFE])) { // UTF-16-BOM-BE
|
|
1366
|
+
if (this.check([60, 0, 63, 0, 120, 0, 109, 0, 108, 0], {offset: 2})) {
|
|
1367
|
+
return {
|
|
1368
|
+
ext: 'xml',
|
|
1369
|
+
mime: 'application/xml',
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
if (this.check([0xFF, 0x0E, 0x53, 0x00, 0x6B, 0x00, 0x65, 0x00, 0x74, 0x00, 0x63, 0x00, 0x68, 0x00, 0x55, 0x00, 0x70, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6C, 0x00], {offset: 2})) {
|
|
1374
|
+
return {
|
|
1375
|
+
ext: 'skp',
|
|
1376
|
+
mime: 'application/vnd.sketchup.skp',
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
return undefined; // Some text based format
|
|
1369
1381
|
}
|
|
1370
1382
|
|
|
1371
1383
|
if (this.checkString('-----BEGIN PGP MESSAGE-----')) {
|
|
@@ -1488,7 +1500,6 @@ class FileTypeParser {
|
|
|
1488
1500
|
}
|
|
1489
1501
|
|
|
1490
1502
|
export async function fileTypeStream(readableStream, {sampleSize = minimumBytes} = {}) {
|
|
1491
|
-
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
|
1492
1503
|
const {default: stream} = await import('node:stream');
|
|
1493
1504
|
|
|
1494
1505
|
return new Promise((resolve, reject) => {
|
|
@@ -1502,7 +1513,7 @@ export async function fileTypeStream(readableStream, {sampleSize = minimumBytes}
|
|
|
1502
1513
|
const outputStream = stream.pipeline ? stream.pipeline(readableStream, pass, () => {}) : readableStream.pipe(pass);
|
|
1503
1514
|
|
|
1504
1515
|
// Read the input stream and detect the filetype
|
|
1505
|
-
const chunk = readableStream.read(sampleSize)
|
|
1516
|
+
const chunk = readableStream.read(sampleSize) ?? readableStream.read() ?? Buffer.alloc(0);
|
|
1506
1517
|
try {
|
|
1507
1518
|
const fileType = await fileTypeFromBuffer(chunk);
|
|
1508
1519
|
pass.fileType = fileType;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "file-type",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "18.0.0",
|
|
4
4
|
"description": "Detect the file type of a Buffer/Uint8Array/ArrayBuffer",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "sindresorhus/file-type",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"./core": "./core.js"
|
|
20
20
|
},
|
|
21
21
|
"engines": {
|
|
22
|
-
"node": "
|
|
22
|
+
"node": ">=14.16"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"test": "xo && ava && tsd"
|
|
@@ -197,18 +197,17 @@
|
|
|
197
197
|
],
|
|
198
198
|
"dependencies": {
|
|
199
199
|
"readable-web-to-node-stream": "^3.0.2",
|
|
200
|
-
"strtok3": "^7.0.0
|
|
201
|
-
"token-types": "^5.0.
|
|
200
|
+
"strtok3": "^7.0.0",
|
|
201
|
+
"token-types": "^5.0.1"
|
|
202
202
|
},
|
|
203
203
|
"devDependencies": {
|
|
204
204
|
"@tokenizer/token": "^0.3.0",
|
|
205
|
-
"@types/node": "^
|
|
206
|
-
"ava": "^3.
|
|
205
|
+
"@types/node": "^18.7.13",
|
|
206
|
+
"ava": "^4.3.1",
|
|
207
207
|
"commonmark": "^0.30.0",
|
|
208
208
|
"noop-stream": "^1.0.0",
|
|
209
|
-
"tsd": "^0.
|
|
210
|
-
"
|
|
211
|
-
"xo": "^0.46.4"
|
|
209
|
+
"tsd": "^0.22.0",
|
|
210
|
+
"xo": "^0.51.0"
|
|
212
211
|
},
|
|
213
212
|
"xo": {
|
|
214
213
|
"envs": [
|
|
@@ -219,11 +218,11 @@
|
|
|
219
218
|
"no-inner-declarations": "warn",
|
|
220
219
|
"no-await-in-loop": "warn",
|
|
221
220
|
"no-bitwise": "off",
|
|
222
|
-
"@typescript-eslint/no-unsafe-assignment": "off"
|
|
221
|
+
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
222
|
+
"unicorn/text-encoding-identifier-case": "off"
|
|
223
223
|
}
|
|
224
224
|
},
|
|
225
225
|
"ava": {
|
|
226
|
-
"serial": true
|
|
227
|
-
"verbose": true
|
|
226
|
+
"serial": true
|
|
228
227
|
}
|
|
229
228
|
}
|
package/readme.md
CHANGED
|
@@ -141,7 +141,7 @@ Detect the file type of a `Buffer`, `Uint8Array`, or `ArrayBuffer`.
|
|
|
141
141
|
|
|
142
142
|
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.
|
|
143
143
|
|
|
144
|
-
If file access is available, it is recommended to use `
|
|
144
|
+
If file access is available, it is recommended to use `fileTypeFromFile()` instead.
|
|
145
145
|
|
|
146
146
|
Returns a `Promise` for an object with the detected file type and MIME type:
|
|
147
147
|
|
|
@@ -282,7 +282,7 @@ A file source implementing the [tokenizer interface](https://github.com/Borewit/
|
|
|
282
282
|
|
|
283
283
|
### fileTypeStream(readableStream, options?)
|
|
284
284
|
|
|
285
|
-
Returns a `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `
|
|
285
|
+
Returns a `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
286
286
|
|
|
287
287
|
This method can be handy to put in between a stream, but it comes with a price.
|
|
288
288
|
Internally `stream()` builds up a buffer of `sampleSize` bytes, used as a sample, to determine the file type.
|
|
@@ -318,7 +318,7 @@ const url = 'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg';
|
|
|
318
318
|
const stream1 = got.stream(url);
|
|
319
319
|
const stream2 = await fileTypeStream(stream1, {sampleSize: 1024});
|
|
320
320
|
|
|
321
|
-
if (stream2.fileType
|
|
321
|
+
if (stream2.fileType?.mime === 'image/jpeg') {
|
|
322
322
|
// stream2 can be used to stream the JPEG image (from the very beginning of the stream)
|
|
323
323
|
}
|
|
324
324
|
```
|
package/util.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export function stringToBytes(string) {
|
|
2
|
-
return [...string].map(character => character.charCodeAt(0));
|
|
2
|
+
return [...string].map(character => character.charCodeAt(0)); // eslint-disable-line unicorn/prefer-code-point
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -17,12 +17,12 @@ export function tarHeaderChecksumMatches(buffer, offset = 0) {
|
|
|
17
17
|
|
|
18
18
|
let sum = 8 * 0x20; // Initialize signed bit sum
|
|
19
19
|
|
|
20
|
-
for (let
|
|
21
|
-
sum += buffer[
|
|
20
|
+
for (let index = offset; index < offset + 148; index++) {
|
|
21
|
+
sum += buffer[index];
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
for (let
|
|
25
|
-
sum += buffer[
|
|
24
|
+
for (let index = offset + 156; index < offset + 512; index++) {
|
|
25
|
+
sum += buffer[index];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
return readSum === sum;
|