Skip to content

Commit 416ab0b

Browse files
committed
Require Node.js 12 and move to ESM
Signed-off-by: Richie Bendall <[email protected]>
1 parent b8446ff commit 416ab0b

File tree

8 files changed

+101
-111
lines changed

8 files changed

+101
-111
lines changed

.editorconfig

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# editorconfig.org
2-
31
root = true
42

53
[*]
@@ -9,5 +7,6 @@ trim_trailing_whitespace = true
97
insert_final_newline = true
108
indent_style = tab
119

12-
[*.md]
13-
trim_trailing_whitespace = false
10+
[*.yml]
11+
indent_style = space
12+
indent_size = 2

LICENSE renamed to license

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2019 Richie Bendall
3+
Copyright (c) 2019 - 2021 Richie Bendall
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

package.json

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
"repository": "https://github.com/Richienb/fetch-charset-detection.git",
66
"author": "Richie Bendall <[email protected]>",
77
"license": "MIT",
8-
"main": "index.js",
8+
"type": "module",
9+
"exports": "./dist/index.js",
910
"files": [
10-
"index.js",
11-
"index.d.ts"
11+
"dist"
1212
],
1313
"engines": {
14-
"node": ">=10"
14+
"node": ">=12"
1515
},
1616
"scripts": {
1717
"build": "tsc",
@@ -29,44 +29,29 @@
2929
"node-fetch"
3030
],
3131
"dependencies": {
32-
"cheerio": "^1.0.0-rc.3",
32+
"cheerio": "^1.0.0-rc.10",
3333
"content-type": "^1.0.4",
34-
"iconv-lite": "^0.6.2"
34+
"iconv-lite": "^0.6.3"
3535
},
3636
"devDependencies": {
37-
"@richienb/tsconfig": "^0.1.1",
38-
"@types/cheerio": "^0.22.21",
39-
"@types/content-type": "^1.1.3",
40-
"@types/nice-try": "^2.0.0",
41-
"@typescript-eslint/eslint-plugin": "^4.1.1",
42-
"@typescript-eslint/parser": "^4.1.1",
43-
"ava": "^3.12.1",
44-
"eslint-config-richienb": "^0.4.2",
45-
"eslint-config-xo-typescript": "^0.32.0",
46-
"node-fetch": "^2.6.1",
47-
"ts-node": "^9.0.0",
48-
"xo": "^0.33.1"
49-
},
50-
"xo": {
51-
"extends": "richienb",
52-
"rules": {
53-
"node/no-missing-import": 0
54-
},
55-
"overrides": [
56-
{
57-
"files": "test.ts",
58-
"rules": {
59-
"@typescript-eslint/no-unsafe-call": 0
60-
}
61-
}
62-
]
37+
"@richienb/tsconfig": "^0.3.0",
38+
"@types/cheerio": "^0.22.30",
39+
"@types/content-type": "^1.1.5",
40+
"ava": "^3.15.0",
41+
"node-fetch": "3.0.0-beta.10",
42+
"ts-node": "^10.1.0",
43+
"typescript": "^4.3.5",
44+
"xo": "^0.43.0"
6345
},
6446
"ava": {
65-
"extensions": [
66-
"ts"
67-
],
68-
"require": [
69-
"ts-node/register"
47+
"extensions": {
48+
"ts": "module"
49+
},
50+
"nonSemVerExperiments": {
51+
"configurableModuleFormat": true
52+
},
53+
"nodeArguments": [
54+
"--loader=ts-node/esm"
7055
]
7156
}
7257
}

README.md renamed to readme.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ npm install fetch-charset-detection
1111
## Usage
1212

1313
```js
14-
const convertBody = require("fetch-charset-detection")
14+
import convertBody from 'fetch-charset-detection';
1515

16-
convertBody(content)
16+
convertBody(content);
1717
```
1818

1919
## API
@@ -22,7 +22,7 @@ convertBody(content)
2222

2323
#### content
2424

25-
Type: `Buffer`
25+
Type: [`Buffer`](https://nodejs.org/api/buffer.html#buffer_class_buffer)
2626

2727
The content to stringify.
2828

source/index.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
1-
import getCharset from "./utils/get-charset"
2-
import { decode } from "iconv-lite"
1+
import type {Buffer} from 'node:buffer';
2+
import iconv from 'iconv-lite';
3+
import getCharset from './utils/get-charset.js';
34

45
/**
56
Detect the encoding of a buffer and stringify it.
7+
68
@param content The content to stringify.
79
@param headers The HTTP headers provided with the content.
10+
11+
@example
12+
```
13+
import convertBody from 'fetch-charset-detection';
14+
15+
convertBody(content);
16+
```
817
*/
9-
function convertBody(content: Buffer, headers?: Headers): string {
18+
export default function convertBody(content: Buffer, headers?: Headers): string {
1019
// Turn raw buffers into a single utf-8 buffer
11-
return decode(
20+
return iconv.decode(
1221
content,
13-
getCharset(content, headers)
14-
)
22+
getCharset(content, headers),
23+
);
1524
}
16-
17-
export = convertBody

source/utils/get-charset.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,43 @@
1-
import { load } from "cheerio"
2-
import parseContentType from "./parse-content-type"
1+
import type {Buffer} from 'node:buffer';
2+
import {load} from 'cheerio';
3+
import parseContentType from './parse-content-type.js';
34

45
/**
56
Get the charset of `content`.
7+
68
@param content The content to stringify.
79
@param headers HTTP Headers provided with the request.
810
*/
9-
function getCharset(content: Buffer, headers?: Headers) {
11+
export default function getCharset(content: Buffer, headers?: Headers) {
1012
// See http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding
1113
// Resulting charset
12-
let charset: string
14+
let charset: string;
1315

1416
// Try to extract content-type header
15-
const contentType = headers?.get("content-type")
17+
const contentType = headers?.get('content-type');
1618
if (contentType) {
17-
charset = parseContentType(contentType)
19+
charset = parseContentType(contentType);
1820
}
1921

2022
// No charset in content type, peek at response body for at most 1024 bytes
21-
const data = content.slice(0, 1024).toString()
23+
const data = content.slice(0, 1024).toString();
2224

2325
// HTML5, HTML4 and XML
2426
if (!charset && data) {
25-
const $ = load(data)
27+
const $ = load(data);
2628

2729
charset = parseContentType(
28-
$("meta[charset]").attr("charset") || // HTML5
29-
$("meta[http-equiv][content]").attr("content") || // HTML4
30-
load(data.replace(/<\?(.*)\?>/im, "<$1>"), { xmlMode: true }).root().find("xml").attr("encoding") // XML
31-
)
30+
$('meta[charset]').attr('charset') // HTML5
31+
|| $('meta[http-equiv][content]').attr('content') // HTML4
32+
|| load(data.replace(/<\?(.*)\?>/im, '<$1>'), {xmlMode: true}).root().find('xml').attr('encoding'), // XML
33+
);
3234

3335
// Prevent decode issues when sites use incorrect encoding
3436
// ref: https://hsivonen.fi/encoding-menu/
35-
if (charset && ["gb2312", "gbk"].includes(charset.toLowerCase())) {
36-
charset = "gb18030"
37+
if (charset && ['gb2312', 'gbk'].includes(charset.toLowerCase())) {
38+
charset = 'gb18030';
3739
}
3840
}
3941

40-
return charset || "utf-8"
42+
return charset || 'utf-8';
4143
}
42-
43-
export = getCharset

source/utils/parse-content-type.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import { parse } from "content-type"
1+
import {parse} from 'content-type';
22

33
/**
44
Get the character set from a Content-Type header.
5+
56
@param contentType The Content-Type HTTP header.
67
*/
7-
function parseContentType(contentType: string) {
8+
export default function parseContentType(contentType: string) {
89
try {
9-
return parse(contentType).parameters.charset
10-
} catch (_) {
11-
return contentType
10+
return parse(contentType).parameters.charset;
11+
} catch {
12+
return contentType;
1213
}
1314
}
14-
15-
export = parseContentType

test.ts

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
1-
import test from "ava"
2-
import { Headers } from "node-fetch"
3-
import { encode } from "iconv-lite"
4-
import convertBody from "./source"
1+
import test from 'ava';
2+
import {Headers} from 'node-fetch';
3+
import iconv from 'iconv-lite';
4+
import convertBody from './source/index.js';
55

6-
test("should support encoding decode, xml dtd detect", t => {
7-
const text = "<?xml version=\"1.0\" encoding=\"EUC-JP\"?><title>日本語</title>"
8-
t.is(convertBody(encode(text, "EUC-JP"), new Headers({ "Content-Type": "text/xml" })), text)
9-
})
6+
test('should support encoding decode, xml dtd detect', t => {
7+
const text = '<?xml version="1.0" encoding="EUC-JP"?><title>日本語</title>';
8+
t.is(convertBody(iconv.encode(text, 'EUC-JP'), new Headers({'Content-Type': 'text/xml'})), text);
9+
});
1010

11-
test("should support encoding decode, content-type detect", t => {
12-
const text = "<div>日本語</div>"
13-
t.is(convertBody(encode(text, "Shift_JIS"), new Headers({ "Content-Type": "text/html; charset=Shift-JIS" })), text)
14-
})
11+
test('should support encoding decode, content-type detect', t => {
12+
const text = '<div>日本語</div>';
13+
t.is(convertBody(iconv.encode(text, 'Shift_JIS'), new Headers({'Content-Type': 'text/html; charset=Shift-JIS'})), text);
14+
});
1515

16-
test("should support encoding decode, html5 detect", t => {
17-
const text = "<meta charset=\"gbk\"><div>中文</div>"
18-
t.is(convertBody(encode(text, "gbk"), new Headers({ "Content-Type": "text/html" })), text)
19-
})
16+
test('should support encoding decode, html5 detect', t => {
17+
const text = '<meta charset="gbk"><div>中文</div>';
18+
t.is(convertBody(iconv.encode(text, 'gbk'), new Headers({'Content-Type': 'text/html'})), text);
19+
});
2020

21-
test("should support encoding decode, html4 detect", t => {
22-
const text = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\"><div>中文</div>"
23-
t.is(convertBody(encode(text, "gb2312"), new Headers({ "Content-Type": "text/html" })), text)
24-
})
21+
test('should support encoding decode, html4 detect', t => {
22+
const text = '<meta http-equiv="Content-Type" content="text/html; charset=gb2312"><div>中文</div>';
23+
t.is(convertBody(iconv.encode(text, 'gb2312'), new Headers({'Content-Type': 'text/html'})), text);
24+
});
2525

26-
test("should support uncommon content-type order, end with qs", t => {
27-
const text = "中文"
28-
t.is(convertBody(encode(text, "gbk"), new Headers({ "Content-Type": "text/plain; charset=gbk; qs=1" })), text)
29-
})
26+
test('should support uncommon content-type order, end with qs', t => {
27+
const text = '中文';
28+
t.is(convertBody(iconv.encode(text, 'gbk'), new Headers({'Content-Type': 'text/plain; charset=gbk; qs=1'})), text);
29+
});
3030

31-
test("should support chunked encoding, html4 detect", t => {
32-
const text = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\" /><div>日本語</div>"
33-
const padding = "a".repeat(10)
34-
t.is(convertBody(encode(padding + text, "Shift_JIS"), new Headers({ "Content-Type": "text/html", "Transfer-Encoding": "chunked" })), padding + text)
35-
})
31+
test('should support chunked encoding, html4 detect', t => {
32+
const text = '<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" /><div>日本語</div>';
33+
const padding = 'a'.repeat(10);
34+
t.is(convertBody(iconv.encode(padding + text, 'Shift_JIS'), new Headers({'Content-Type': 'text/html', 'Transfer-Encoding': 'chunked'})), padding + text);
35+
});
3636

37-
test("should only do encoding detection up to 1024 bytes", t => {
38-
const text = "中文"
39-
const padding = "a".repeat(1200)
40-
t.not(convertBody(encode(padding + text, "gbk"), new Headers({ "Content-Type": "text/html", "Transfer-Encoding": "chunked" })), text)
41-
})
37+
test('should only do encoding detection up to 1024 bytes', t => {
38+
const text = '中文';
39+
const padding = 'a'.repeat(1200);
40+
t.not(convertBody(iconv.encode(padding + text, 'gbk'), new Headers({'Content-Type': 'text/html', 'Transfer-Encoding': 'chunked'})), text);
41+
});

0 commit comments

Comments
 (0)