Initial commit
This commit is contained in:
47
node_modules/bcp-47-match/index.d.ts
generated
vendored
Normal file
47
node_modules/bcp-47-match/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
export function basicFilter(
|
||||
tags: string | Tags,
|
||||
ranges: string | Ranges | undefined
|
||||
): Tags
|
||||
export function extendedFilter(
|
||||
tags: string | Tags,
|
||||
ranges: string | Ranges | undefined
|
||||
): Tags
|
||||
export function lookup(
|
||||
tags: string | Tags,
|
||||
ranges: string | Ranges | undefined
|
||||
): string | undefined
|
||||
/**
|
||||
* BCP-47 tag.
|
||||
*/
|
||||
export type Tag = string
|
||||
/**
|
||||
* List of BCP-47 tags.
|
||||
*/
|
||||
export type Tags = Array<Tag>
|
||||
/**
|
||||
* RFC 4647 range.
|
||||
*/
|
||||
export type Range = string
|
||||
/**
|
||||
* List of RFC 4647 range.
|
||||
*/
|
||||
export type Ranges = Array<Range>
|
||||
/**
|
||||
* An internal check.
|
||||
*/
|
||||
export type Check = (tag: Tag, range: Range) => boolean
|
||||
/**
|
||||
* Filter: yields all tags that match a range.
|
||||
*/
|
||||
export type Filter = FilterOrLookup<true>
|
||||
/**
|
||||
* Lookup: yields the best tag that matches a range.
|
||||
*/
|
||||
export type Lookup = FilterOrLookup<false>
|
||||
/**
|
||||
* A check.
|
||||
*/
|
||||
export type FilterOrLookup<IsFilter extends boolean> = (
|
||||
tags: Tag | Tags,
|
||||
ranges?: Range | Ranges | undefined
|
||||
) => IsFilter extends true ? Tags : Tag | undefined
|
234
node_modules/bcp-47-match/index.js
generated
vendored
Normal file
234
node_modules/bcp-47-match/index.js
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
/**
|
||||
* See <https://tools.ietf.org/html/rfc4647#section-3.1>
|
||||
* for more info on the algorithms.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {string} Tag
|
||||
* BCP-47 tag.
|
||||
* @typedef {Array<Tag>} Tags
|
||||
* List of BCP-47 tags.
|
||||
* @typedef {string} Range
|
||||
* RFC 4647 range.
|
||||
* @typedef {Array<Range>} Ranges
|
||||
* List of RFC 4647 range.
|
||||
*
|
||||
* @callback Check
|
||||
* An internal check.
|
||||
* @param {Tag} tag
|
||||
* BCP-47 tag.
|
||||
* @param {Range} range
|
||||
* RFC 4647 range.
|
||||
* @returns {boolean}
|
||||
* Whether the range matches the tag.
|
||||
*
|
||||
* @typedef {FilterOrLookup<true>} Filter
|
||||
* Filter: yields all tags that match a range.
|
||||
* @typedef {FilterOrLookup<false>} Lookup
|
||||
* Lookup: yields the best tag that matches a range.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {boolean} IsFilter
|
||||
* Whether to filter or perform a lookup.
|
||||
* @callback FilterOrLookup
|
||||
* A check.
|
||||
* @param {Tag|Tags} tags
|
||||
* One or more BCP-47 tags.
|
||||
* @param {Range|Ranges|undefined} [ranges='*']
|
||||
* One or more RFC 4647 ranges.
|
||||
* @returns {IsFilter extends true ? Tags : Tag|undefined}
|
||||
* Result.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Factory to perform a filter or a lookup.
|
||||
*
|
||||
* This factory creates a function that accepts a list of tags and a list of
|
||||
* ranges, and contains logic to exit early for lookups.
|
||||
* `check` just has to deal with one tag and one range.
|
||||
* This match function iterates over ranges, and for each range,
|
||||
* iterates over tags.
|
||||
* That way, earlier ranges matching any tag have precedence over later ranges.
|
||||
*
|
||||
* @template {boolean} IsFilter
|
||||
* @param {Check} check
|
||||
* A check.
|
||||
* @param {IsFilter} filter
|
||||
* Whether to filter or perform a lookup.
|
||||
* @returns {FilterOrLookup<IsFilter>}
|
||||
* Filter or lookup.
|
||||
*/
|
||||
function factory(check, filter) {
|
||||
/**
|
||||
* @param {Tag|Tags} tags
|
||||
* One or more BCP-47 tags.
|
||||
* @param {Range|Ranges|undefined} [ranges='*']
|
||||
* One or more RFC 4647 ranges.
|
||||
* @returns {IsFilter extends true ? Tags : Tag|undefined}
|
||||
* Result.
|
||||
*/
|
||||
return function (tags, ranges) {
|
||||
let left = cast(tags, 'tag')
|
||||
const right = cast(
|
||||
ranges === null || ranges === undefined ? '*' : ranges,
|
||||
'range'
|
||||
)
|
||||
/** @type {Tags} */
|
||||
const matches = []
|
||||
let rightIndex = -1
|
||||
|
||||
while (++rightIndex < right.length) {
|
||||
const range = right[rightIndex].toLowerCase()
|
||||
|
||||
// Ignore wildcards in lookup mode.
|
||||
if (!filter && range === '*') continue
|
||||
|
||||
let leftIndex = -1
|
||||
/** @type {Tags} */
|
||||
const next = []
|
||||
|
||||
while (++leftIndex < left.length) {
|
||||
if (check(left[leftIndex].toLowerCase(), range)) {
|
||||
// Exit if this is a lookup and we have a match.
|
||||
if (!filter) {
|
||||
return /** @type {IsFilter extends true ? Tags : Tag|undefined} */ (
|
||||
left[leftIndex]
|
||||
)
|
||||
}
|
||||
|
||||
matches.push(left[leftIndex])
|
||||
} else {
|
||||
next.push(left[leftIndex])
|
||||
}
|
||||
}
|
||||
|
||||
left = next
|
||||
}
|
||||
|
||||
// If this is a filter, return the list. If it’s a lookup, we didn’t find
|
||||
// a match, so return `undefined`.
|
||||
return /** @type {IsFilter extends true ? Tags : Tag|undefined} */ (
|
||||
filter ? matches : undefined
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic Filtering (Section 3.3.1) matches a language priority list consisting
|
||||
* of basic language ranges (Section 2.1) to sets of language tags.
|
||||
*
|
||||
* @param {Tag|Tags} tags
|
||||
* One or more BCP-47 tags.
|
||||
* @param {Range|Ranges|undefined} [ranges='*']
|
||||
* One or more RFC 4647 ranges.
|
||||
* @returns {Tags}
|
||||
* List of BCP-47 tags.
|
||||
*/
|
||||
export const basicFilter = factory(function (tag, range) {
|
||||
return range === '*' || tag === range || tag.includes(range + '-')
|
||||
}, true)
|
||||
|
||||
/**
|
||||
* Extended Filtering (Section 3.3.2) matches a language priority list
|
||||
* consisting of extended language ranges (Section 2.2) to sets of language
|
||||
* tags.
|
||||
*
|
||||
* @param {Tag|Tags} tags
|
||||
* One or more BCP-47 tags.
|
||||
* @param {Range|Ranges|undefined} [ranges='*']
|
||||
* One or more RFC 4647 ranges.
|
||||
* @returns {Tags}
|
||||
* List of BCP-47 tags.
|
||||
*/
|
||||
export const extendedFilter = factory(function (tag, range) {
|
||||
// 3.3.2.1
|
||||
const left = tag.split('-')
|
||||
const right = range.split('-')
|
||||
let leftIndex = 0
|
||||
let rightIndex = 0
|
||||
|
||||
// 3.3.2.2
|
||||
if (right[rightIndex] !== '*' && left[leftIndex] !== right[rightIndex]) {
|
||||
return false
|
||||
}
|
||||
|
||||
leftIndex++
|
||||
rightIndex++
|
||||
|
||||
// 3.3.2.3
|
||||
while (rightIndex < right.length) {
|
||||
// 3.3.2.3.A
|
||||
if (right[rightIndex] === '*') {
|
||||
rightIndex++
|
||||
continue
|
||||
}
|
||||
|
||||
// 3.3.2.3.B
|
||||
if (!left[leftIndex]) return false
|
||||
|
||||
// 3.3.2.3.C
|
||||
if (left[leftIndex] === right[rightIndex]) {
|
||||
leftIndex++
|
||||
rightIndex++
|
||||
continue
|
||||
}
|
||||
|
||||
// 3.3.2.3.D
|
||||
if (left[leftIndex].length === 1) return false
|
||||
|
||||
// 3.3.2.3.E
|
||||
leftIndex++
|
||||
}
|
||||
|
||||
// 3.3.2.4
|
||||
return true
|
||||
}, true)
|
||||
|
||||
/**
|
||||
* Lookup (Section 3.4) matches a language priority list consisting of basic
|
||||
* language ranges to sets of language tags to find the one exact language tag
|
||||
* that best matches the range.
|
||||
*
|
||||
* @param {Tag|Tags} tags
|
||||
* One or more BCP-47 tags.
|
||||
* @param {Range|Ranges|undefined} [ranges='*']
|
||||
* One or more RFC 4647 ranges.
|
||||
* @returns {Tag|undefined}
|
||||
* BCP-47 tag.
|
||||
*/
|
||||
export const lookup = factory(function (tag, range) {
|
||||
let right = range
|
||||
|
||||
/* eslint-disable-next-line no-constant-condition */
|
||||
while (true) {
|
||||
if (right === '*' || tag === right) return true
|
||||
|
||||
let index = right.lastIndexOf('-')
|
||||
|
||||
if (index < 0) return false
|
||||
|
||||
if (right.charAt(index - 2) === '-') index -= 2
|
||||
|
||||
right = right.slice(0, index)
|
||||
}
|
||||
}, false)
|
||||
|
||||
/**
|
||||
* Validate tags or ranges, and cast them to arrays.
|
||||
*
|
||||
* @param {string|Array<string>} values
|
||||
* @param {string} name
|
||||
* @returns {Array<string>}
|
||||
*/
|
||||
function cast(values, name) {
|
||||
const value = values && typeof values === 'string' ? [values] : values
|
||||
|
||||
if (!value || typeof value !== 'object' || !('length' in value)) {
|
||||
throw new Error(
|
||||
'Invalid ' + name + ' `' + value + '`, expected non-empty string'
|
||||
)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
22
node_modules/bcp-47-match/license
generated
vendored
Normal file
22
node_modules/bcp-47-match/license
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2018 Titus Wormer <tituswormer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
88
node_modules/bcp-47-match/package.json
generated
vendored
Normal file
88
node_modules/bcp-47-match/package.json
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "bcp-47-match",
|
||||
"version": "2.0.3",
|
||||
"description": "Match BCP 47 language tags with language ranges per RFC 4647",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"bcp",
|
||||
"47",
|
||||
"bcp47",
|
||||
"bcp-47",
|
||||
"language",
|
||||
"tag",
|
||||
"match",
|
||||
"matching",
|
||||
"check",
|
||||
"rfc",
|
||||
"4647"
|
||||
],
|
||||
"repository": "wooorm/bcp-47-match",
|
||||
"bugs": "https://github.com/wooorm/bcp-47-match/issues",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
},
|
||||
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
|
||||
"contributors": [
|
||||
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"files": [
|
||||
"index.d.ts",
|
||||
"index.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.0.0",
|
||||
"c8": "^7.0.0",
|
||||
"chalk": "^5.0.0",
|
||||
"prettier": "^2.0.0",
|
||||
"remark-cli": "^11.0.0",
|
||||
"remark-preset-wooorm": "^9.0.0",
|
||||
"type-coverage": "^2.0.0",
|
||||
"typescript": "^4.0.0",
|
||||
"xo": "^0.52.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prepack": "npm run build && npm run format",
|
||||
"build": "tsc --build --clean && tsc --build && type-coverage",
|
||||
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
|
||||
"test-api": "node --conditions development test.js",
|
||||
"test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api",
|
||||
"test": "npm run build && npm run format && npm run test-coverage"
|
||||
},
|
||||
"prettier": {
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"bracketSpacing": false,
|
||||
"semi": false,
|
||||
"trailingComma": "none"
|
||||
},
|
||||
"xo": {
|
||||
"prettier": true
|
||||
},
|
||||
"remarkConfig": {
|
||||
"plugins": [
|
||||
"preset-wooorm",
|
||||
[
|
||||
"gfm",
|
||||
{
|
||||
"tablePipeAlign": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"lint-table-pipe-alignment",
|
||||
false
|
||||
]
|
||||
]
|
||||
},
|
||||
"typeCoverage": {
|
||||
"atLeast": 100,
|
||||
"detail": true,
|
||||
"strict": true,
|
||||
"ignoreCatch": true
|
||||
}
|
||||
}
|
315
node_modules/bcp-47-match/readme.md
generated
vendored
Normal file
315
node_modules/bcp-47-match/readme.md
generated
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
<!--lint disable no-html-->
|
||||
|
||||
# bcp-47-match
|
||||
|
||||
[![Build][build-badge]][build]
|
||||
[![Coverage][coverage-badge]][coverage]
|
||||
[![Downloads][downloads-badge]][downloads]
|
||||
[![Size][size-badge]][size]
|
||||
|
||||
Match BCP 47 language tags with language ranges per RFC 4647.
|
||||
|
||||
## Contents
|
||||
|
||||
* [What is this?](#what-is-this)
|
||||
* [When should I use this?](#when-should-i-use-this)
|
||||
* [Install](#install)
|
||||
* [Use](#use)
|
||||
* [API](#api)
|
||||
* [`basicFilter(tags[, ranges='*'])`](#basicfiltertags-ranges)
|
||||
* [`extendedFilter(tags[, ranges='*'])`](#extendedfiltertags-ranges)
|
||||
* [`lookup(tags, ranges)`](#lookuptags-ranges)
|
||||
* [Types](#types)
|
||||
* [Compatibility](#compatibility)
|
||||
* [Security](#security)
|
||||
* [Related](#related)
|
||||
* [Contribute](#contribute)
|
||||
* [License](#license)
|
||||
|
||||
## What is this?
|
||||
|
||||
This package can match [BCP 47][spec] language tags with “language ranges” per
|
||||
[RFC 4647][match].
|
||||
This is done by the `:lang()` pseudo class in CSS, the `Accept-Language` HTTP
|
||||
header, and a few other places.
|
||||
|
||||
## When should I use this?
|
||||
|
||||
You can use this package if you want to choose a certain document based on
|
||||
language tags.
|
||||
|
||||
## Install
|
||||
|
||||
This package is [ESM only][esm].
|
||||
In Node.js (version 14.14+, 16.0+), install with [npm][]:
|
||||
|
||||
```sh
|
||||
npm install bcp-47-match
|
||||
```
|
||||
|
||||
In Deno with [`esm.sh`][esmsh]:
|
||||
|
||||
```js
|
||||
import * as bcp47Match from 'https://esm.sh/bcp-47-match@2'
|
||||
```
|
||||
|
||||
In browsers with [`esm.sh`][esmsh]:
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import * as bcp47Match from 'https://esm.sh/bcp-47-match@2?bundle'
|
||||
</script>
|
||||
```
|
||||
|
||||
## Use
|
||||
|
||||
```js
|
||||
import {basicFilter, extendedFilter, lookup} from 'bcp-47-match'
|
||||
|
||||
const tags = ['en-GB', 'de-CH', 'en', 'de']
|
||||
|
||||
console.log(basicFilter(tags, '*')) // => [ 'en-GB', 'de-CH', 'en', 'de' ]
|
||||
console.log(basicFilter(tags, 'en')) // => [ 'en-GB', 'en' ]
|
||||
console.log(basicFilter(tags, 'en-GB')) // => [ 'en-GB' ]
|
||||
console.log(basicFilter(tags, ['en-GB', 'en'])) // => [ 'en-GB', 'en' ]
|
||||
console.log(basicFilter(tags, 'jp')) // => []
|
||||
|
||||
console.log(extendedFilter(tags, '*')) // => [ 'en-GB', 'de-CH', 'en', 'de' ]
|
||||
console.log(extendedFilter(tags, 'en')) // => [ 'en-GB', 'en' ]
|
||||
console.log(extendedFilter(tags, 'en-GB')) // => [ 'en-GB' ]
|
||||
console.log(extendedFilter(tags, '*-GB')) // => [ 'en-GB' ]
|
||||
console.log(extendedFilter(tags, ['en-GB', 'en'])) // => [ 'en-GB', 'en' ]
|
||||
console.log(extendedFilter(tags, 'jp')) // => []
|
||||
|
||||
console.log(lookup(tags, 'en')) // => 'en'
|
||||
console.log(lookup(tags, 'en-GB')) // => 'en-GB'
|
||||
console.log(lookup(tags, ['en-GB', 'en'])) // => 'en-GB'
|
||||
console.log(lookup(tags, ['en', 'en-GB'])) // => 'en'
|
||||
console.log(lookup(tags, 'jp')) // => undefined
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
This package exports the identifier `basicFilter`, `extendedFilter`, and
|
||||
`lookup`.
|
||||
There is no default export.
|
||||
|
||||
### `basicFilter(tags[, ranges='*'])`
|
||||
|
||||
> 👉 **Note**: See
|
||||
> [Basic Filtering spec](https://tools.ietf.org/html/rfc4647#section-3.3.1)
|
||||
|
||||
Match language tags to a list of simple ranges.
|
||||
Searches for matches between the first range and all tags, and continues
|
||||
with further ranges.
|
||||
Returns a list of matching tags in the order they matched.
|
||||
|
||||
<details><summary>View matching table</summary>
|
||||
|
||||
| Basic Filter | `*` | `de` | `de-CH` | `de-DE` | `de-*-DE` | `*-CH` |
|
||||
| - | - | - | - | - | - | - |
|
||||
| `de` | ✔︎ | ✔︎ | | | | |
|
||||
| `de-CH` | ✔︎ | ✔︎ | ✔︎ | | | |
|
||||
| `de-CH-1996` | ✔︎ | ✔︎ | ✔︎ | | | |
|
||||
| `de-DE` | ✔︎ | ✔︎ | | ✔︎ | | |
|
||||
| `de-DE-1996` | ✔︎ | ✔︎ | | ✔︎ | | |
|
||||
| `de-DE-x-goethe` | ✔︎ | ✔︎ | | ✔︎ | | |
|
||||
| `de-Deva` | ✔︎ | ✔︎ | | | | |
|
||||
| `de-Deva-DE` | ✔︎ | ✔︎ | | | | |
|
||||
| `de-Latf-DE` | ✔︎ | ✔︎ | | | | |
|
||||
| `de-Latn-DE` | ✔︎ | ✔︎ | | | | |
|
||||
| `de-Latn-DE-1996` | ✔︎ | ✔︎ | | | | |
|
||||
| `de-x-DE` | ✔︎ | ✔︎ | | | | |
|
||||
| `en` | ✔︎ | | | | | |
|
||||
| `en-GB` | ✔︎ | | | | | |
|
||||
| `zh` | ✔︎ | | | | | |
|
||||
| `zh-Hans` | ✔︎ | | | | | |
|
||||
| `zh-Hant` | ✔︎ | | | | | |
|
||||
|
||||
</details>
|
||||
|
||||
###### Parameters
|
||||
|
||||
* `tags` (`string` or `Array<string>`)
|
||||
— list of BCP 47 tags
|
||||
* `ranges` (`string` or `Array<string>`, default: `'*'`)
|
||||
— list of RFC 4647
|
||||
[basic ranges][basic-range]
|
||||
(aka, matching `/^(\*|[a-z]{1,8}(-[a-z0-9]{1,8})*)$/i`)
|
||||
|
||||
###### Returns
|
||||
|
||||
Possibly empty list of matching tags in the order they matched
|
||||
(`Array<string>`).
|
||||
|
||||
### `extendedFilter(tags[, ranges='*'])`
|
||||
|
||||
> 👉 **Note**: See
|
||||
> [Extended Filtering spec](https://tools.ietf.org/html/rfc4647#section-3.3.2)
|
||||
|
||||
Match language tags to a list of extended ranges.
|
||||
Searches for matches between the first range and all tags, and continues
|
||||
with further ranges.
|
||||
|
||||
<details><summary>View matching table</summary>
|
||||
|
||||
| Extended Filter | `*` | `de` | `de-CH` | `de-DE` | `de-*-DE` | `*-CH` |
|
||||
| - | - | - | - | - | - | - |
|
||||
| `de` | ✔︎ | ✔︎ | | | | |
|
||||
| `de-CH` | ✔︎ | ✔︎ | ✔︎ | | | ✔︎ |
|
||||
| `de-CH-1996` | ✔︎ | ✔︎ | ✔︎ | | | ✔︎ |
|
||||
| `de-DE` | ✔︎ | ✔︎ | | ✔︎ | ✔︎ | |
|
||||
| `de-DE-1996` | ✔︎ | ✔︎ | | ✔︎ | ✔︎ | |
|
||||
| `de-DE-x-goethe` | ✔︎ | ✔︎ | | ✔︎ | ✔︎ | |
|
||||
| `de-Deva` | ✔︎ | ✔︎ | | | | |
|
||||
| `de-Deva-DE` | ✔︎ | ✔︎ | | ✔︎ | ✔︎ | |
|
||||
| `de-Latf-DE` | ✔︎ | ✔︎ | | ✔︎ | ✔︎ | |
|
||||
| `de-Latn-DE` | ✔︎ | ✔︎ | | ✔︎ | ✔︎ | |
|
||||
| `de-Latn-DE-1996` | ✔︎ | ✔︎ | | ✔︎ | ✔︎ | |
|
||||
| `de-x-DE` | ✔︎ | ✔︎ | | | | |
|
||||
| `en` | ✔︎ | | | | | |
|
||||
| `en-GB` | ✔︎ | | | | | |
|
||||
| `zh` | ✔︎ | | | | | |
|
||||
| `zh-Hans` | ✔︎ | | | | | |
|
||||
| `zh-Hant` | ✔︎ | | | | | |
|
||||
|
||||
</details>
|
||||
|
||||
###### Parameters
|
||||
|
||||
* `tags` (`string` or `Array<string>`)
|
||||
— list of BCP 47 tags
|
||||
* `ranges` (`string` or `Array<string>`, default: `'*'`)
|
||||
— list of RFC 4647 [extended ranges][extended-range]
|
||||
(aka, matching `/^(\*|[a-z]{1,8})(-(\*|[a-z0-9]{1,8}))*$/i`)
|
||||
|
||||
###### Returns
|
||||
|
||||
Possibly empty list of matching tags in the order they matched
|
||||
(`Array<string>`).
|
||||
|
||||
### `lookup(tags, ranges)`
|
||||
|
||||
> 👉 **Note**: See
|
||||
> [Lookup spec](https://tools.ietf.org/html/rfc4647#section-3.4)
|
||||
|
||||
Find the best language tag that matches a list of ranges.
|
||||
Searches for a match between the first range and all tags, and continues
|
||||
with further ranges.
|
||||
Returns the first match, if any.
|
||||
|
||||
<details><summary>View matching table</summary>
|
||||
|
||||
| Lookup | `*` | `de` | `de-CH` | `de-DE` | `de-*-DE` | `*-CH` |
|
||||
| - | - | - | - | - | - | - |
|
||||
| `de` | | ✔︎︎ | ✔︎︎ | ✔︎ | ✔︎ | ✔︎ |
|
||||
| `de-CH` | | | ✔︎ | | | ✔︎ |
|
||||
| `de-CH-1996` | | | | | | ✔︎ |
|
||||
| `de-DE` | | | | ✔︎ | | ✔︎ |
|
||||
| `de-DE-1996` | | | | | | ✔︎ |
|
||||
| `de-DE-x-goethe` | | | | | | ✔︎ |
|
||||
| `de-Deva` | | | | | | ✔︎ |
|
||||
| `de-Deva-DE` | | | | | | ✔︎ |
|
||||
| `de-Latf-DE` | | | | | | ✔︎ |
|
||||
| `de-Latn-DE` | | | | | | ✔︎ |
|
||||
| `de-Latn-DE-1996` | | | | | | ✔︎ |
|
||||
| `de-x-DE` | | | | | | ✔︎ |
|
||||
| `en` | | | | | | ✔︎ |
|
||||
| `en-GB` | | | | | | ✔︎ |
|
||||
| `zh` | | | | | | ✔︎ |
|
||||
| `zh-Hans` | | | | | | ✔︎ |
|
||||
| `zh-Hant` | | | | | | ✔︎ |
|
||||
|
||||
</details>
|
||||
|
||||
###### Parameters
|
||||
|
||||
* `tags` (`string` or `Array<string>`)
|
||||
— list of BCP 47 tags
|
||||
* `ranges` (`string` or `Array<string>`)
|
||||
— list of RFC 4647 basic ranges (but `*` is ignored)
|
||||
|
||||
###### Returns
|
||||
|
||||
First matching tag in `tags`, `undefined` otherwise (`string?`).
|
||||
|
||||
## Types
|
||||
|
||||
This package is fully typed with [TypeScript][].
|
||||
It exports no additional types.
|
||||
|
||||
## Compatibility
|
||||
|
||||
This package is at least compatible with all maintained versions of Node.js.
|
||||
As of now, that is Node.js 14.14+ and 16.0+.
|
||||
It also works in Deno and modern browsers.
|
||||
|
||||
## Security
|
||||
|
||||
This package is safe.
|
||||
|
||||
## Related
|
||||
|
||||
* [`wooorm/bcp-47`](https://github.com/wooorm/bcp-47)
|
||||
— parse and serialize BCP 47 language tags
|
||||
* [`wooorm/bcp-47-normalize`](https://github.com/wooorm/bcp-47-normalize)
|
||||
— normalize, canonicalize, and format BCP 47 tags
|
||||
* [`wooorm/iso-3166`](https://github.com/wooorm/iso-3166)
|
||||
— ISO 3166 codes
|
||||
* [`wooorm/iso-639-2`](https://github.com/wooorm/iso-639-2)
|
||||
— ISO 639-2 codes
|
||||
* [`wooorm/iso-639-3`](https://github.com/wooorm/iso-639-3)
|
||||
— ISO 639-3 codes
|
||||
* [`wooorm/iso-15924`](https://github.com/wooorm/iso-15924)
|
||||
— ISO 15924 codes
|
||||
* [`wooorm/un-m49`](https://github.com/wooorm/un-m49)
|
||||
— UN M49 codes
|
||||
|
||||
## Contribute
|
||||
|
||||
Yes please!
|
||||
See [How to Contribute to Open Source][contribute].
|
||||
|
||||
## License
|
||||
|
||||
[MIT][license] © [Titus Wormer][author]
|
||||
|
||||
<!-- Definitions -->
|
||||
|
||||
[build-badge]: https://github.com/wooorm/bcp-47-match/workflows/main/badge.svg
|
||||
|
||||
[build]: https://github.com/wooorm/bcp-47-match/actions
|
||||
|
||||
[coverage-badge]: https://img.shields.io/codecov/c/github/wooorm/bcp-47-match.svg
|
||||
|
||||
[coverage]: https://codecov.io/github/wooorm/bcp-47-match
|
||||
|
||||
[downloads-badge]: https://img.shields.io/npm/dm/bcp-47-match.svg
|
||||
|
||||
[downloads]: https://www.npmjs.com/package/bcp-47-match
|
||||
|
||||
[size-badge]: https://img.shields.io/bundlephobia/minzip/bcp-47-match.svg
|
||||
|
||||
[size]: https://bundlephobia.com/result?p=bcp-47-match
|
||||
|
||||
[npm]: https://docs.npmjs.com/cli/install
|
||||
|
||||
[esmsh]: https://esm.sh
|
||||
|
||||
[license]: license
|
||||
|
||||
[author]: https://wooorm.com
|
||||
|
||||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
|
||||
|
||||
[typescript]: https://www.typescriptlang.org
|
||||
|
||||
[contribute]: https://opensource.guide/how-to-contribute/
|
||||
|
||||
[spec]: https://tools.ietf.org/html/bcp47
|
||||
|
||||
[match]: https://tools.ietf.org/html/rfc4647
|
||||
|
||||
[basic-range]: https://tools.ietf.org/html/rfc4647#section-2.1
|
||||
|
||||
[extended-range]: https://tools.ietf.org/html/rfc4647#section-2.2
|
Reference in New Issue
Block a user