|
1 | | -function parseAcceptLanguageEntry(entry: string): { lang: string; q: number } { |
2 | | - const langWithQ = entry.split(";").map(u => u.trim()); |
3 | | - let q = 1.0; |
4 | | - if (langWithQ.length > 1) { |
5 | | - const qVal = langWithQ[1].split("=").map(u => u.trim()); |
6 | | - if (qVal.length === 2 && qVal[0].toLowerCase() === "q") { |
7 | | - const qn = Number(qVal[1]); |
8 | | - q = isNaN(qn) ? 0.0 : qn; |
9 | | - } |
10 | | - } |
11 | | - return { lang: langWithQ[0], q }; |
12 | | -} |
| 1 | +const entryRegexp = |
| 2 | + // locale ; q = qval |
| 3 | + /(?:^|,)([^,;]+)(?:;\s*[qQ]\s*=([^,;]+))?/g; |
13 | 4 |
|
14 | 5 | export function acceptedLanguages(acceptLanguageHeader = ""): string[] { |
15 | 6 | if (typeof acceptLanguageHeader !== "string") { |
16 | 7 | throw new TypeError("Argument must be a string"); |
17 | 8 | } |
18 | | - const tokens = acceptLanguageHeader |
19 | | - .split(",") |
20 | | - .map(t => t.trim()) |
21 | | - .filter(t => t !== ""); |
22 | | - const langsWithQ = Array.from(tokens.map(parseAcceptLanguageEntry).entries()); |
| 9 | + |
| 10 | + const langsWithQ: Array<{ lang: string; q: number; index: number }> = []; |
| 11 | + for (const token of acceptLanguageHeader.matchAll(entryRegexp)) { |
| 12 | + const q = token[2] ? parseFloat(token[2]) || 0 : 1; |
| 13 | + langsWithQ.push({ lang: token[1].trim(), q, index: token.index }); |
| 14 | + } |
| 15 | + |
23 | 16 | // order by q descending, keeping the header order for equal weights |
24 | | - langsWithQ.sort(([aidx, aval], [bidx, bval]) => |
25 | | - aval.q === bval.q ? aidx - bidx : bval.q - aval.q |
26 | | - ); |
27 | | - return langsWithQ.map(([, val]) => val.lang); |
| 17 | + langsWithQ.sort((a, b) => (a.q === b.q ? a.index - b.index : b.q - a.q)); |
| 18 | + |
| 19 | + return langsWithQ.map(val => val.lang); |
28 | 20 | } |
0 commit comments