From 7a52ddeba2a68388b544f529d2d92104420f77b0 Mon Sep 17 00:00:00 2001 From: Shipwreckt Date: Fri, 31 Oct 2025 20:02:14 +0000 Subject: Changed from static to 11ty! --- node_modules/bcp-47/index.d.ts | 6 + node_modules/bcp-47/index.js | 9 + node_modules/bcp-47/lib/normal.d.ts | 2 + node_modules/bcp-47/lib/normal.js | 29 +++ node_modules/bcp-47/lib/parse.d.ts | 29 +++ node_modules/bcp-47/lib/parse.js | 310 +++++++++++++++++++++++++++++ node_modules/bcp-47/lib/regular.d.ts | 2 + node_modules/bcp-47/lib/regular.js | 12 ++ node_modules/bcp-47/lib/stringify.d.ts | 13 ++ node_modules/bcp-47/lib/stringify.js | 50 +++++ node_modules/bcp-47/license | 22 +++ node_modules/bcp-47/package.json | 85 ++++++++ node_modules/bcp-47/readme.md | 344 +++++++++++++++++++++++++++++++++ 13 files changed, 913 insertions(+) create mode 100644 node_modules/bcp-47/index.d.ts create mode 100644 node_modules/bcp-47/index.js create mode 100644 node_modules/bcp-47/lib/normal.d.ts create mode 100644 node_modules/bcp-47/lib/normal.js create mode 100644 node_modules/bcp-47/lib/parse.d.ts create mode 100644 node_modules/bcp-47/lib/parse.js create mode 100644 node_modules/bcp-47/lib/regular.d.ts create mode 100644 node_modules/bcp-47/lib/regular.js create mode 100644 node_modules/bcp-47/lib/stringify.d.ts create mode 100644 node_modules/bcp-47/lib/stringify.js create mode 100644 node_modules/bcp-47/license create mode 100644 node_modules/bcp-47/package.json create mode 100644 node_modules/bcp-47/readme.md (limited to 'node_modules/bcp-47') diff --git a/node_modules/bcp-47/index.d.ts b/node_modules/bcp-47/index.d.ts new file mode 100644 index 0000000..8b4a602 --- /dev/null +++ b/node_modules/bcp-47/index.d.ts @@ -0,0 +1,6 @@ +export {parse} from './lib/parse.js' +export {stringify} from './lib/stringify.js' +export type Schema = import('./lib/parse.js').Schema +export type Extension = import('./lib/parse.js').Extension +export type Warning = import('./lib/parse.js').Warning +export type Options = import('./lib/parse.js').Options diff --git a/node_modules/bcp-47/index.js b/node_modules/bcp-47/index.js new file mode 100644 index 0000000..a16162c --- /dev/null +++ b/node_modules/bcp-47/index.js @@ -0,0 +1,9 @@ +/** + * @typedef {import('./lib/parse.js').Schema} Schema + * @typedef {import('./lib/parse.js').Extension} Extension + * @typedef {import('./lib/parse.js').Warning} Warning + * @typedef {import('./lib/parse.js').Options} Options + */ + +export {parse} from './lib/parse.js' +export {stringify} from './lib/stringify.js' diff --git a/node_modules/bcp-47/lib/normal.d.ts b/node_modules/bcp-47/lib/normal.d.ts new file mode 100644 index 0000000..ca7cd82 --- /dev/null +++ b/node_modules/bcp-47/lib/normal.d.ts @@ -0,0 +1,2 @@ +/** @type {Record} */ +export const normal: Record diff --git a/node_modules/bcp-47/lib/normal.js b/node_modules/bcp-47/lib/normal.js new file mode 100644 index 0000000..20cca11 --- /dev/null +++ b/node_modules/bcp-47/lib/normal.js @@ -0,0 +1,29 @@ +/** @type {Record} */ +export const normal = { + 'en-gb-oed': 'en-GB-oxendict', + 'i-ami': 'ami', + 'i-bnn': 'bnn', + 'i-default': null, + 'i-enochian': null, + 'i-hak': 'hak', + 'i-klingon': 'tlh', + 'i-lux': 'lb', + 'i-mingo': null, + 'i-navajo': 'nv', + 'i-pwn': 'pwn', + 'i-tao': 'tao', + 'i-tay': 'tay', + 'i-tsu': 'tsu', + 'sgn-be-fr': 'sfb', + 'sgn-be-nl': 'vgt', + 'sgn-ch-de': 'sgg', + 'art-lojban': 'jbo', + 'cel-gaulish': null, + 'no-bok': 'nb', + 'no-nyn': 'nn', + 'zh-guoyu': 'cmn', + 'zh-hakka': 'hak', + 'zh-min': null, + 'zh-min-nan': 'nan', + 'zh-xiang': 'hsn' +} diff --git a/node_modules/bcp-47/lib/parse.d.ts b/node_modules/bcp-47/lib/parse.d.ts new file mode 100644 index 0000000..ef18cc1 --- /dev/null +++ b/node_modules/bcp-47/lib/parse.d.ts @@ -0,0 +1,29 @@ +/** + * Parse a BCP 47 language tag. + * + * @param {string} tag + * @param {Options} [options] + * @returns {Schema} + */ +export function parse(tag: string, options?: Options | undefined): Schema +export type Warning = (reason: string, code: number, offset: number) => void +export type Options = { + normalize?: boolean | undefined + forgiving?: boolean | undefined + warning?: Warning | undefined +} +export type Extension = { + singleton: string + extensions: Array +} +export type Schema = { + language: string | null | undefined + extendedLanguageSubtags: Array + script: string | null | undefined + region: string | null | undefined + variants: Array + extensions: Array + privateuse: Array + irregular: string | null | undefined + regular: string | null | undefined +} diff --git a/node_modules/bcp-47/lib/parse.js b/node_modules/bcp-47/lib/parse.js new file mode 100644 index 0000000..7251a71 --- /dev/null +++ b/node_modules/bcp-47/lib/parse.js @@ -0,0 +1,310 @@ +/** + * @callback Warning + * @param {string} reason + * @param {number} code + * @param {number} offset + * @returns {void} + * + * @typedef Options + * @property {boolean} [normalize=true] + * @property {boolean} [forgiving=false] + * @property {Warning} [warning] + * + * @typedef Extension + * @property {string} singleton + * @property {Array} extensions + * + * @typedef Schema + * @property {string|null|undefined} language + * @property {Array} extendedLanguageSubtags + * @property {string|null|undefined} script + * @property {string|null|undefined} region + * @property {Array} variants + * @property {Array} extensions + * @property {Array} privateuse + * @property {string|null|undefined} irregular + * @property {string|null|undefined} regular + */ + +import {isAlphanumerical} from 'is-alphanumerical' +import {isAlphabetical} from 'is-alphabetical' +import {isDecimal} from 'is-decimal' +import {regular} from './regular.js' +import {normal} from './normal.js' + +const own = {}.hasOwnProperty + +/** + * Parse a BCP 47 language tag. + * + * @param {string} tag + * @param {Options} [options] + * @returns {Schema} + */ +export function parse(tag, options = {}) { + const result = empty() + const source = String(tag) + const value = source.toLowerCase() + let index = 0 + + // Check input. + if (tag === null || tag === undefined) { + throw new Error('Expected string, got `' + tag + '`') + } + + // Let’s start. + // First: the edge cases. + if (own.call(normal, value)) { + const replacement = normal[value] + + if ( + (options.normalize === undefined || + options.normalize === null || + options.normalize) && + typeof replacement === 'string' + ) { + return parse(replacement) + } + + result[regular.includes(value) ? 'regular' : 'irregular'] = source + + return result + } + + // Now, to actually parse, eat what could be a language. + while (isAlphabetical(value.charCodeAt(index)) && index < 9) index++ + + // A language. + if (index > 1 /* Min 639. */ && index < 9 /* Max subtag. */) { + // 5 and up is a subtag. + // 4 is the size of reserved languages. + // 3 an ISO 639-2 or ISO 639-3. + // 2 is an ISO 639-1. + // + // + result.language = source.slice(0, index) + + if (index < 4 /* Max 639. */) { + let groups = 0 + + while ( + value.charCodeAt(index) === 45 /* `-` */ && + isAlphabetical(value.charCodeAt(index + 1)) && + isAlphabetical(value.charCodeAt(index + 2)) && + isAlphabetical(value.charCodeAt(index + 3)) && + !isAlphabetical(value.charCodeAt(index + 4)) + ) { + if (groups > 2 /* Max extended language subtag count. */) { + return fail( + index, + 3, + 'Too many extended language subtags, expected at most 3 subtags' + ) + } + + // Extended language subtag. + result.extendedLanguageSubtags.push(source.slice(index + 1, index + 4)) + index += 4 + groups++ + } + } + + // ISO 15924 script. + // + if ( + value.charCodeAt(index) === 45 /* `-` */ && + isAlphabetical(value.charCodeAt(index + 1)) && + isAlphabetical(value.charCodeAt(index + 2)) && + isAlphabetical(value.charCodeAt(index + 3)) && + isAlphabetical(value.charCodeAt(index + 4)) && + !isAlphabetical(value.charCodeAt(index + 5)) + ) { + result.script = source.slice(index + 1, index + 5) + index += 5 + } + + if (value.charCodeAt(index) === 45 /* `-` */) { + // ISO 3166-1 region. + // + if ( + isAlphabetical(value.charCodeAt(index + 1)) && + isAlphabetical(value.charCodeAt(index + 2)) && + !isAlphabetical(value.charCodeAt(index + 3)) + ) { + result.region = source.slice(index + 1, index + 3) + index += 3 + } + // UN M49 region. + // + else if ( + isDecimal(value.charCodeAt(index + 1)) && + isDecimal(value.charCodeAt(index + 2)) && + isDecimal(value.charCodeAt(index + 3)) && + !isDecimal(value.charCodeAt(index + 4)) + ) { + result.region = source.slice(index + 1, index + 4) + index += 4 + } + } + + while (value.charCodeAt(index) === 45 /* `-` */) { + const start = index + 1 + let offset = start + + while (isAlphanumerical(value.charCodeAt(offset))) { + if (offset - start > 7 /* Max variant. */) { + return fail( + offset, + 1, + 'Too long variant, expected at most 8 characters' + ) + } + + offset++ + } + + if ( + // Long variant. + offset - start > 4 /* Min alpha numeric variant. */ || + // Short variant. + (offset - start > 3 /* Min variant. */ && + isDecimal(value.charCodeAt(start))) + ) { + result.variants.push(source.slice(start, offset)) + index = offset + } + // Something else. + else { + break + } + } + + // Extensions. + while (value.charCodeAt(index) === 45 /* `-` */) { + // Exit if this isn’t an extension. + if ( + value.charCodeAt(index + 1) === 120 /* `x` */ || + !isAlphanumerical(value.charCodeAt(index + 1)) || + value.charCodeAt(index + 2) !== 45 /* `-` */ || + !isAlphanumerical(value.charCodeAt(index + 3)) + ) { + break + } + + let offset = index + 2 + let groups = 0 + + while ( + value.charCodeAt(offset) === 45 /* `-` */ && + isAlphanumerical(value.charCodeAt(offset + 1)) && + isAlphanumerical(value.charCodeAt(offset + 2)) + ) { + const start = offset + 1 + offset = start + 2 + groups++ + + while (isAlphanumerical(value.charCodeAt(offset))) { + if (offset - start > 7 /* Max extension. */) { + return fail( + offset, + 2, + 'Too long extension, expected at most 8 characters' + ) + } + + offset++ + } + } + + if (!groups) { + return fail( + offset, + 4, + 'Empty extension, extensions must have at least 2 characters of content' + ) + } + + result.extensions.push({ + singleton: source.charAt(index + 1), + extensions: source.slice(index + 3, offset).split('-') + }) + + index = offset + } + } + // Not a language. + else { + index = 0 + } + + // Private use. + if ( + (index === 0 && value.charCodeAt(index) === 120) /* `x` */ || + (value.charCodeAt(index) === 45 /* `-` */ && + value.charCodeAt(index + 1) === 120) /* `x` */ + ) { + index = index ? index + 2 : 1 + let offset = index + + while ( + value.charCodeAt(offset) === 45 /* `-` */ && + isAlphanumerical(value.charCodeAt(offset + 1)) + ) { + const start = index + 1 + offset = start + + while (isAlphanumerical(value.charCodeAt(offset))) { + if (offset - start > 7 /* Max private use. */) { + return fail( + offset, + 5, + 'Too long private-use area, expected at most 8 characters' + ) + } + + offset++ + } + + result.privateuse.push(source.slice(index + 1, offset)) + index = offset + } + } + + if (index !== source.length) { + return fail(index, 6, 'Found superfluous content after tag') + } + + return result + + /** + * Create an empty results object. + * + * @param {number} offset + * @param {number} code + * @param {string} reason + * @returns {Schema} + */ + function fail(offset, code, reason) { + if (options.warning) options.warning(reason, code, offset) + return options.forgiving ? result : empty() + } +} + +/** + * Create an empty results object. + * + * @returns {Schema} + */ +function empty() { + return { + language: null, + extendedLanguageSubtags: [], + script: null, + region: null, + variants: [], + extensions: [], + privateuse: [], + irregular: null, + regular: null + } +} diff --git a/node_modules/bcp-47/lib/regular.d.ts b/node_modules/bcp-47/lib/regular.d.ts new file mode 100644 index 0000000..1818fbd --- /dev/null +++ b/node_modules/bcp-47/lib/regular.d.ts @@ -0,0 +1,2 @@ +/** @type {Array} */ +export const regular: Array diff --git a/node_modules/bcp-47/lib/regular.js b/node_modules/bcp-47/lib/regular.js new file mode 100644 index 0000000..0aa5fab --- /dev/null +++ b/node_modules/bcp-47/lib/regular.js @@ -0,0 +1,12 @@ +/** @type {Array} */ +export const regular = [ + 'art-lojban', + 'cel-gaulish', + 'no-bok', + 'no-nyn', + 'zh-guoyu', + 'zh-hakka', + 'zh-min', + 'zh-min-nan', + 'zh-xiang' +] diff --git a/node_modules/bcp-47/lib/stringify.d.ts b/node_modules/bcp-47/lib/stringify.d.ts new file mode 100644 index 0000000..14942c4 --- /dev/null +++ b/node_modules/bcp-47/lib/stringify.d.ts @@ -0,0 +1,13 @@ +/** + * @typedef {Partial} Schema + * @typedef {Partial} Extension + */ +/** + * Compile a language schema to a BCP 47 language tag. + * + * @param {Schema} schema + * @returns {string} + */ +export function stringify(schema?: Schema): string +export type Schema = Partial +export type Extension = Partial diff --git a/node_modules/bcp-47/lib/stringify.js b/node_modules/bcp-47/lib/stringify.js new file mode 100644 index 0000000..e5b367a --- /dev/null +++ b/node_modules/bcp-47/lib/stringify.js @@ -0,0 +1,50 @@ +/** + * @typedef {Partial} Schema + * @typedef {Partial} Extension + */ + +/** + * Compile a language schema to a BCP 47 language tag. + * + * @param {Schema} schema + * @returns {string} + */ +export function stringify(schema = {}) { + /** @type {Array} */ + let result = [] + + if (schema.irregular) { + return schema.irregular + } + + if (schema.regular) { + return schema.regular + } + + if (schema.language) { + result = result.concat( + schema.language, + schema.extendedLanguageSubtags || [], + schema.script || [], + schema.region || [], + schema.variants || [] + ) + + const values = schema.extensions || [] + let index = -1 + + while (++index < values.length) { + const value = values[index] + + if (value.singleton && value.extensions && value.extensions.length > 0) { + result.push(value.singleton, ...value.extensions) + } + } + } + + if (schema.privateuse && schema.privateuse.length > 0) { + result.push('x', ...schema.privateuse) + } + + return result.join('-') +} diff --git a/node_modules/bcp-47/license b/node_modules/bcp-47/license new file mode 100644 index 0000000..8d8660d --- /dev/null +++ b/node_modules/bcp-47/license @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2016 Titus Wormer + +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. diff --git a/node_modules/bcp-47/package.json b/node_modules/bcp-47/package.json new file mode 100644 index 0000000..8a12183 --- /dev/null +++ b/node_modules/bcp-47/package.json @@ -0,0 +1,85 @@ +{ + "name": "bcp-47", + "version": "2.1.0", + "description": "Parse and stringify BCP 47 language tags", + "license": "MIT", + "keywords": [ + "bcp", + "47", + "bcp47", + "bcp-47", + "language", + "tag", + "parse" + ], + "repository": "wooorm/bcp-47", + "bugs": "https://github.com/wooorm/bcp-47/issues", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + }, + "author": "Titus Wormer (https://wooorm.com)", + "contributors": [ + "Titus Wormer (https://wooorm.com)" + ], + "sideEffects": false, + "type": "module", + "main": "index.js", + "types": "index.d.ts", + "files": [ + "index.d.ts", + "index.js", + "lib/" + ], + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "devDependencies": { + "@types/tape": "^4.0.0", + "c8": "^7.0.0", + "is-hidden": "^2.0.0", + "prettier": "^2.0.0", + "remark-cli": "^10.0.0", + "remark-preset-wooorm": "^9.0.0", + "rimraf": "^3.0.0", + "tape": "^5.0.0", + "type-coverage": "^2.0.0", + "typescript": "^4.0.0", + "xo": "^0.46.0" + }, + "scripts": { + "prepublishOnly": "npm run build && npm run format", + "build": "rimraf \"{lib,test}/**/*.d.ts\" \"*.d.ts\" && tsc && type-coverage", + "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", + "test-api": "node --conditions development test/index.js", + "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 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, + "rules": { + "complexity": "off" + } + }, + "remarkConfig": { + "plugins": [ + "preset-wooorm" + ] + }, + "typeCoverage": { + "atLeast": 100, + "detail": true, + "strict": true, + "ignoreCatch": true + } +} diff --git a/node_modules/bcp-47/readme.md b/node_modules/bcp-47/readme.md new file mode 100644 index 0000000..3e96ac6 --- /dev/null +++ b/node_modules/bcp-47/readme.md @@ -0,0 +1,344 @@ +# bcp-47 + +[![Build][build-badge]][build] +[![Coverage][coverage-badge]][coverage] +[![Downloads][downloads-badge]][downloads] +[![Size][size-badge]][size] + +Parse and stringify [BCP 47][spec] language tags. + +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`parse(tag[, options])`](#parsetag-options) + * [`stringify(schema)`](#stringifyschema) + * [`Schema`](#schema) + * [`function warning(reason, code, offset)`](#function-warningreason-code-offset) +* [Types](#types) +* [Compatibility](#compatibility) +* [Security](#security) +* [Related](#related) +* [Contribute](#contribute) +* [License](#license) + +## What is this? + +This is a package that can parse BCP 47 language tags to an object representing +them, and serialize those objects back into language tags. +It supports a forgiving mode to handle incorrect BCP 47 tags and can emit +warnings about problems in incorrect tags. + +## When should I use this? + +You can use this package if you need to access the data stored in BCP 47 +language tags. +You can also use this package if you want to check (lint) or manipulate tags. + +## Install + +This package is [ESM only][esm]. +In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]: + +```sh +npm install bcp-47 +``` + +In Deno with [Skypack][]: + +```js +import * as bcp47 from 'https://cdn.skypack.dev/bcp-47@2?dts' +``` + +In browsers with [Skypack][]: + +```html + +``` + +## Use + +```js +import {parse, stringify} from 'bcp-47' + +const schema = parse('hy-Latn-IT-arevela') + +console.log(schema) +console.log(stringify(schema)) +``` + +Yields: + +```js +{ language: 'hy', + extendedLanguageSubtags: [], + script: 'Latn', + region: 'IT', + variants: ['arevela'], + extensions: [], + privateuse: [], + irregular: null, + regular: null } +'hy-Latn-IT-arevela' +``` + +## API + +This package exports the following identifiers: `parse` and `stringify`. +There is no default export. + +### `parse(tag[, options])` + +Parse a BCP 47 tag into a language schema. +Note that the algorithm is case insensitive. + +###### `options.normalize` + +Whether to normalize legacy tags when possible (`boolean`, default: +`true`). +For example, `i-klingon` does not match the BCP 47 language algorithm but is +considered valid by BCP 47 nonetheless. +It is suggested to use `tlh` instead (the ISO 639-3 code for Klingon). +When `normalize` is `true`, passing `i-klingon` or other deprecated tags, is +handled as if their suggested valid tag was given instead. + +###### `options.forgiving` + +By default, when an error is encountered, an empty object is returned. +When in forgiving mode, all found values up to the point of the error +are included (`boolean`, default: `false`). +So, for example, where by default `en-GB-abcdefghi` an empty object is returned +(as the language variant is too long), in `forgiving` mode the `language` of +`schema` is populated with `en` and the `region` is populated with `GB`. + +###### `options.warning` + +When given, `warning` is called when an error is encountered +([`Function`][warning]). + +###### Returns + +Parsed BCP 47 language tag ([`Schema`][schema]). + +###### Throws + +When `tag` is `null` or `undefined`. + +### `stringify(schema)` + +Compile a [`schema`][schema] to a BCP 47 language tag. + +###### Returns + +BCP 47 language tag (`string`). + +### `Schema` + +A schema represents a language tag. +A schema is deemed empty when it has neither `language`, `irregular`, `regular`, +nor `privateuse` (where an empty `privateuse` array is handled as no +`privateuse` as well). + +###### `schema.language` + +Two or three character [ISO 639][iso-639] language code, four character reserved +language code, or 5 to 8 (inclusive) characters registered language subtag +(`string`). +For example, `en` (English) or `cmn` (Mandarin Chinese). + +###### `schema.extendedLanguageSubtags` + +Selected three-character [ISO 639][iso-639] codes(`Array`), such as +`yue` in `zh-yue-HK` (Chinese, Cantonese, as used in Hong Kong SAR). + +###### `schema.script` + +Four character [ISO 15924][iso-15924] script code (`string`), such as `Latn` in +`hy-Latn-IT-arevela` (Eastern Armenian written in Latin script, as used in +Italy). + +###### `schema.region` + +Two alphabetical character [ISO 3166-1][iso-3166-1] code or three digit +[UN M49][un-m49] code (`string`). +For example, `CN` in `cmn-Hans-CN` (Mandarin Chinese, Simplified script, as used +in China) or `419` in `es-419` (Spanish as used in Latin America and the +Caribbean). + +###### `schema.variants` + +5 to 8 (inclusive) character language variants (`Array`), such as +`rozaj` and `biske` in `sl-rozaj-biske` (San Giorgio dialect of Resian dialect +of Slovenian). + +###### `schema.extensions` + +List of extensions (`Array`), each an object containing a one character +`singleton`, and a list of `extensions` (`string`). +`singleton` cannot be `x` (case insensitive) and `extensions` must be between +two and eight (inclusive) characters. +For example, an extension would be `u-co-phonebk` in `de-DE-u-co-phonebk` +(German, as used in Germany, using German phonebook sort order), where `u` is +the `singleton` and `co` and `phonebk` are its extensions. + +###### `schema.privateuse` + +List of private-use subtags (`Array`), where each subtag must be between +one and eight (inclusive) characters. + +###### `schema.regular` + +One of the `regular` tags (`string`): tags that are seen as something different +by the algorithm. +Valid values are: + +* `art-lojban` +* `cel-gaulish` +* `no-bok` +* `no-nyn` +* `zh-guoyu` +* `zh-hakka` +* `zh-min` +* `zh-min-nan` +* `zh-xiang` + +###### `schema.irregular` + +One of the `irregular` tags (`string`): tags that are seen as invalid by the +algorithm). +Valid values are: + +* `en-GB-oed` +* `i-ami` +* `i-bnn` +* `i-default` +* `i-enochian` +* `i-hak` +* `i-klingon` +* `i-lux` +* `i-mingo` +* `i-navajo` +* `i-pwn` +* `i-tao` +* `i-tay` +* `i-tsu` +* `sgn-BE-FR` +* `sgn-BE-NL` +* `sgn-CH-DE` + +### `function warning(reason, code, offset)` + +Called when an error occurs. + +###### Parameters + +* `reason` (`string`) + — English reason for failure +* `code` (`number`) + — code for failure +* `offset` (`number`) + — index-based place where the error occurred in the tag + +###### Warnings + +| code | reason | +| :--- | :--------------------------------------------------------------------- | +| 1 | Too long variant, expected at most 8 characters | +| 2 | Too long extension, expected at most 8 characters | +| 3 | Too many extended language subtags, expected at most 3 subtags | +| 4 | Empty extension, extensions must have at least 2 characters of content | +| 5 | Too long private-use area, expected at most 8 characters | +| 6 | Found superfluous content after tag | + +## Types + +This package is fully typed with [TypeScript][]. +It exports additional `Schema`, `Extension`, `Warning`, and `Options` types that +model their respective interfaces. + +## Compatibility + +This package is at least compatible with all maintained versions of Node.js. +As of now, that is Node.js 12.20+, 14.14+, and 16.0+. +It also works in Deno and modern browsers. + +## Security + +This package is safe. + +## Related + +* [`wooorm/bcp-47-match`](https://github.com/wooorm/bcp-47-match) + — match BCP 47 language tags with language ranges per RFC 4647 +* [`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] + + + +[build-badge]: https://github.com/wooorm/bcp-47/workflows/main/badge.svg + +[build]: https://github.com/wooorm/bcp-47/actions + +[coverage-badge]: https://img.shields.io/codecov/c/github/wooorm/bcp-47.svg + +[coverage]: https://codecov.io/github/wooorm/bcp-47 + +[downloads-badge]: https://img.shields.io/npm/dm/bcp-47.svg + +[downloads]: https://www.npmjs.com/package/bcp-47 + +[size-badge]: https://img.shields.io/bundlephobia/minzip/bcp-47.svg + +[size]: https://bundlephobia.com/result?p=bcp-47 + +[npm]: https://docs.npmjs.com/cli/install + +[skypack]: https://www.skypack.dev + +[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/rfc/bcp/bcp47.html + +[warning]: #function-warningreason-code-offset + +[schema]: #schema + +[iso-639]: https://en.wikipedia.org/wiki/ISO_639 + +[iso-15924]: https://en.wikipedia.org/wiki/ISO_15924 + +[iso-3166-1]: https://en.wikipedia.org/wiki/ISO_3166-1 + +[un-m49]: https://en.wikipedia.org/wiki/UN_M.49 -- cgit v1.2.3