Skip to content

Commit 0735a75

Browse files
committed
Finish up support for Accept
1 parent 9726d85 commit 0735a75

7 files changed

+310
-118
lines changed

packages/headers/CHANGELOG.md

+35-7
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,50 @@ let ms = new Date().getTime();
7272
let headers = new SuperHeaders({ lastModified: ms });
7373
```
7474

75-
- Adds support for
75+
- Added `AcceptLanguage.prototype.accepts(language)`, `AcceptLanguage.prototype.getQuality(language)`,
76+
`AcceptLanguage.prototype.getPreferred(languages)`
7677

77-
- `headers.accept`
78-
- `headers.connection`
79-
- `headers.host`
80-
- `headers.referer`
78+
```ts
79+
import { AcceptLanguage } from '@mjackson/headers';
80+
81+
let header = new AcceptLanguage({ 'en-US': 1, en: 0.9 });
82+
83+
header.accepts('en-US'); // true
84+
header.accepts('en-GB'); // true
85+
header.accepts('en'); // true
86+
header.accepts('fr'); // false
87+
88+
header.getQuality('en-US'); // 1
89+
header.getQuality('en-GB'); // 0.9
90+
91+
header.getPreferred(['en-GB', 'en-US']); // 'en-US'
92+
```
8193

82-
- Adds low-level `Accept` API
94+
- Added `Accept` support
8395

8496
```ts
8597
import { Accept } from '@mjackson/headers';
8698

8799
let header = new Accept({ 'text/html': 1, 'text/*': 0.9 });
88-
header.get('text/html'); // 1
100+
101+
header.accepts('text/html'); // true
102+
header.accepts('text/plain'); // true
103+
header.accepts('text/*'); // true
104+
header.accepts('image/jpeg'); // false
105+
106+
header.getQuality('text/html'); // 1
107+
header.getQuality('text/plain'); // 0.9
108+
109+
header.getPreferred(['text/html', 'text/plain']); // 'text/html'
89110
```
90111

112+
- Added property support (getters and setters) for
113+
114+
- `headers.accept`
115+
- `headers.connection`
116+
- `headers.host`
117+
- `headers.referer`
118+
91119
## v0.8.0 (2024-11-14)
92120

93121
- Added CommonJS build

packages/headers/README.md

+36-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ HTTP headers contain a wealth of information:
77
- Who is sending this request?
88
- What's in the payload and how is it encoded?
99
- What is the filename of this file upload?
10-
- and much, much more!
10+
- and much more!
1111

1212
The [built-in JavaScript `Headers` interface](https://developer.mozilla.org/en-US/docs/Web/API/Headers) accepts and gives you strings for everything, which you're probably used to parsing and stringifying manually as needed. This library aims to give you a more fluent interface for all of this information. Similar to how the DOM gives you programmatic access to HTML documents, `headers` gives you access to HTTP headers.
1313

@@ -30,6 +30,12 @@ headers.accept = 'text/html,text/*;q=0.9';
3030
console.log(headers.accept.mediaTypes); // [ 'text/html', 'text/*' ]
3131
console.log(Object.fromEntries(headers.accept.entries())); // { 'text/html': 1, 'text/*': 0.9 }
3232

33+
headers.accept.accepts('text/html'); // true
34+
headers.accept.accepts('text/plain'); // true
35+
headers.accept.accepts('image/jpeg'); // false
36+
37+
headers.accept.getPreferred(['text/plain', 'text/html']); // 'text/html'
38+
3339
headers.accept.set('text/plain', 0.9);
3440
headers.accept.set('text/*', 0.8);
3541

@@ -38,8 +44,14 @@ console.log(headers.get('Accept')); // "text/html,text/plain;q=0.9,text/*;q=0.8"
3844
// Accept-Language
3945
headers.acceptLanguage = 'en-US,en;q=0.9';
4046

41-
console.log(headers.acceptLanguage.languages); // [ 'en-US', 'en' ]
42-
console.log(Object.fromEntries(headers.acceptLanguage.entries())); // { 'en-US': 1, en: 0.9 }
47+
console.log(headers.acceptLanguage.languages); // [ 'en-us', 'en' ]
48+
console.log(Object.fromEntries(headers.acceptLanguage.entries())); // { 'en-us': 1, en: 0.9 }
49+
50+
headers.acceptLanguage.accepts('en'); // true
51+
headers.acceptLanguage.accepts('ja'); // false
52+
53+
headers.acceptLanguage.getPreferred(['en-US', 'en-GB']); // 'en-US'
54+
headers.acceptLanguage.getPreferred(['en', 'fr']); // 'en'
4355

4456
// Content-Type
4557
headers.contentType = 'application/json; charset=utf-8';
@@ -192,10 +204,16 @@ If you need support for a header that isn't listed here, please [send a PR](http
192204

193205
```ts
194206
let header = new Accept('text/html;text/*;q=0.9');
195-
header.get('text/html'); // 1
196-
header.set('text/html', 0.8);
197-
header.delete('text/html');
198-
header.has('text/*'); // true
207+
208+
header.has('text/html'); // true
209+
header.has('text/plain'); // false
210+
211+
header.accepts('text/html'); // true
212+
header.accepts('text/plain'); // true
213+
header.accepts('text/*'); // true
214+
header.accepts('image/jpeg'); // false
215+
216+
header.getPreferred(['text/html', 'text/plain']); // 'text/html'
199217

200218
// Iterate over media type/quality pairs
201219
for (let [mediaType, quality] of header) {
@@ -211,10 +229,17 @@ let header = new Accept(['text/html', ['text/*', 0.9]]);
211229

212230
```ts
213231
let header = new AcceptLanguage('en-US,en;q=0.9');
214-
header.get('en-US'); // 1
215-
header.set('en-US', 0.8);
216-
header.delete('en-US');
217-
header.has('en'); // true
232+
233+
header.has('en-US'); // true
234+
header.has('en-GB'); // false
235+
236+
header.accepts('en-US'); // true
237+
header.accepts('en-GB'); // true
238+
header.accepts('en'); // true
239+
header.accepts('fr'); // true
240+
241+
header.getPreferred(['en-US', 'en-GB']); // 'en-US'
242+
header.getPreferred(['en', 'fr']); // 'en'
218243

219244
// Iterate over language/quality pairs
220245
for (let [language, quality] of header) {

packages/headers/src/lib/accept-language.test.ts

+54-38
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,64 @@ describe('Accept-Language', () => {
1111

1212
it('initializes with a string', () => {
1313
let header = new AcceptLanguage('en-US,en;q=0.9');
14-
assert.equal(header.get('en-US'), 1);
15-
assert.equal(header.get('en'), 0.9);
14+
assert.equal(header.size, 2);
1615
});
1716

1817
it('initializes with an array', () => {
1918
let header = new AcceptLanguage(['en-US', ['en', 0.9]]);
20-
assert.equal(header.get('en-US'), 1);
21-
assert.equal(header.get('en'), 0.9);
19+
assert.equal(header.size, 2);
2220
});
2321

2422
it('initializes with an object', () => {
2523
let header = new AcceptLanguage({ 'en-US': 1, en: 0.9 });
26-
assert.equal(header.get('en-US'), 1);
27-
assert.equal(header.get('en'), 0.9);
24+
assert.equal(header.size, 2);
2825
});
2926

3027
it('initializes with another AcceptLanguage', () => {
3128
let header = new AcceptLanguage(new AcceptLanguage('en-US,en;q=0.9'));
32-
assert.equal(header.get('en-US'), 1);
33-
assert.equal(header.get('en'), 0.9);
29+
assert.equal(header.size, 2);
3430
});
3531

3632
it('handles whitespace in initial value', () => {
3733
let header = new AcceptLanguage(' en-US , en;q= 0.9 ');
38-
assert.equal(header.get('en-US'), 1);
39-
assert.equal(header.get('en'), 0.9);
34+
assert.equal(header.size, 2);
35+
});
36+
37+
it('gets all languages', () => {
38+
let header = new AcceptLanguage('en-US,en;q=0.9');
39+
assert.deepEqual(header.languages, ['en-us', 'en']);
40+
});
41+
42+
it('gets all qualities', () => {
43+
let header = new AcceptLanguage('en-US,en;q=0.9');
44+
assert.deepEqual(header.qualities, [1, 0.9]);
45+
});
46+
47+
it('checks if a language is acceptable', () => {
48+
let header = new AcceptLanguage('en-US,en;q=0.9,fr;q=0.8');
49+
assert.equal(header.accepts('en-US'), true);
50+
assert.equal(header.accepts('en'), true);
51+
assert.equal(header.accepts('en-GB'), true);
52+
assert.equal(header.accepts('fr'), true);
53+
assert.equal(header.accepts('fi'), false);
54+
});
55+
56+
it('gets the correct quality values', () => {
57+
let header = new AcceptLanguage('en-US,en;q=0.9,fr;q=0.8');
58+
assert.equal(header.getQuality('en-US'), 1);
59+
assert.equal(header.getQuality('*'), 1);
60+
assert.equal(header.getQuality('en'), 1);
61+
assert.equal(header.getQuality('en-GB'), 0.9);
62+
assert.equal(header.getQuality('fr'), 0.8);
63+
assert.equal(header.getQuality('fi'), 0);
64+
});
65+
66+
it('gets the preferred language', () => {
67+
let header = new AcceptLanguage('en-US,en;q=0.9');
68+
assert.equal(header.getPreferred(['en-GB', 'en-US']), 'en-US');
69+
assert.equal(header.getPreferred(['en-GB', 'en']), 'en');
70+
assert.equal(header.getPreferred(['fr', 'en-GB']), 'en-GB');
71+
assert.equal(header.getPreferred(['fi', 'ja']), null);
4072
});
4173

4274
it('sets and gets languages', () => {
@@ -46,16 +78,10 @@ describe('Accept-Language', () => {
4678
});
4779

4880
it('deletes languages', () => {
49-
let header = new AcceptLanguage('en-US');
50-
assert.equal(header.delete('en-US'), true);
51-
assert.equal(header.delete('en'), false);
52-
assert.equal(header.get('en-US'), undefined);
53-
});
54-
55-
it('checks if language exists', () => {
5681
let header = new AcceptLanguage('en-US');
5782
assert.equal(header.has('en-US'), true);
58-
assert.equal(header.has('fs'), false);
83+
header.delete('en-US');
84+
assert.equal(header.has('en-US'), false);
5985
});
6086

6187
it('clears all languages', () => {
@@ -64,21 +90,11 @@ describe('Accept-Language', () => {
6490
assert.equal(header.size, 0);
6591
});
6692

67-
it('gets all languages', () => {
68-
let header = new AcceptLanguage('en-US,en;q=0.9');
69-
assert.deepEqual(header.languages, ['en-US', 'en']);
70-
});
71-
72-
it('gets all qualities', () => {
73-
let header = new AcceptLanguage('en-US,en;q=0.9');
74-
assert.deepEqual(header.qualities, [1, 0.9]);
75-
});
76-
7793
it('iterates over entries', () => {
7894
let header = new AcceptLanguage('en-US,en;q=0.9');
7995
let entries = Array.from(header.entries());
8096
assert.deepEqual(entries, [
81-
['en-US', 1],
97+
['en-us', 1],
8298
['en', 0.9],
8399
]);
84100
});
@@ -87,7 +103,7 @@ describe('Accept-Language', () => {
87103
let header = new AcceptLanguage('en-US,en;q=0.9');
88104
let entries = Array.from(header);
89105
assert.deepEqual(entries, [
90-
['en-US', 1],
106+
['en-us', 1],
91107
['en', 0.9],
92108
]);
93109
});
@@ -99,7 +115,7 @@ describe('Accept-Language', () => {
99115
result.push([language, quality]);
100116
});
101117
assert.deepEqual(result, [
102-
['en-US', 1],
118+
['en-us', 1],
103119
['en', 0.9],
104120
]);
105121
});
@@ -111,7 +127,7 @@ describe('Accept-Language', () => {
111127

112128
it('converts to string correctly', () => {
113129
let header = new AcceptLanguage('en-US,en;q=0.9');
114-
assert.equal(header.toString(), 'en-US,en;q=0.9');
130+
assert.equal(header.toString(), 'en-us,en;q=0.9');
115131
});
116132

117133
it('handles setting empty quality values', () => {
@@ -134,17 +150,17 @@ describe('Accept-Language', () => {
134150

135151
it('sorts initial value', () => {
136152
let header = new AcceptLanguage('en;q=0.9,en-US');
137-
assert.equal(header.toString(), 'en-US,en;q=0.9');
138-
assert.deepEqual(header.languages, ['en-US', 'en']);
153+
assert.equal(header.toString(), 'en-us,en;q=0.9');
154+
assert.deepEqual(header.languages, ['en-us', 'en']);
139155
});
140156

141157
it('sorts updated value', () => {
142158
let header = new AcceptLanguage('en-US,en;q=0.9');
143159
header.set('fi');
144-
assert.equal(header.toString(), 'en-US,fi,en;q=0.9');
145-
assert.deepEqual(header.languages, ['en-US', 'fi', 'en']);
160+
assert.equal(header.toString(), 'en-us,fi,en;q=0.9');
161+
assert.deepEqual(header.languages, ['en-us', 'fi', 'en']);
146162
header.set('en-US', 0.8);
147-
assert.equal(header.toString(), 'fi,en;q=0.9,en-US;q=0.8');
148-
assert.deepEqual(header.languages, ['fi', 'en', 'en-US']);
163+
assert.equal(header.toString(), 'fi,en;q=0.9,en-us;q=0.8');
164+
assert.deepEqual(header.languages, ['fi', 'en', 'en-us']);
149165
});
150166
});

0 commit comments

Comments
 (0)