Launch Week Day 3: Introducing Organization Notifications in Socket.Learn More
Socket
Book a DemoSign in
Socket

rfc5646

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rfc5646 - npm Package Compare versions

Comparing version
2.0.0
to
3.0.0
+16
example.js
var LanguageTag = require('./src/main')
var tag = new LanguageTag('en-Latn-US')
console.log(tag.language)
console.log(tag.script)
console.log(tag.region)
console.log(tag.variant)
console.log(tag.minimal.toString())
console.log(tag == 'en-Latn-US') // eslint-disable-line eqeqeq
console.log(tag.matches('en-*'))
console.log(tag.minimal.suitableFor('en-US'))
console.log(tag.truncate().toString())
console.log(tag.truncate({script: false}).toString())
tag.forEach((subtag) => console.log(subtag.toString()))
/**
* @overview
* RFC 5646 Language Tags Implementation
* @author James M Snell (jasnell@gmail.com)
* @license Public Domain
* @description An implementation of the RFC 5646 Language Tag
* syntax that works in browser and server environments
* and does not require Language Tag registry knowledge.
* @example
* var tag = new LanguageTag('en-Latn-US');
* console.log(tag.language); // en
* console.log(tag.script); // Latn
* console.log(tag.region); // US
* console.log(tag.variant); // undefined
* console.log(tag.minimal; // en-US;
* console.log(tag == 'en-US'); // true
* console.log(tag.matches('en-*')); // true
* console.log(tag.minimal.suitableFor('en-US')); // true
* console.log(tag.truncate().toString()); //en-Latn-US
* console.log(tag.truncate({script:false}).toString()); // en-US
* var i = tag.iterator;
* var n
* while(!(n=i.next()).done) {
* console.log(n.value.toString());
* }
**/
'use strict'
const kInspect = typeof require === 'function'
? require('util').inspect.custom : 'inspect'
const Types = {}
Object.defineProperties(Types, {
Wildcard: { configurable: false, enumerable: true, value: undefined },
Other: { configurable: false, enumerable: true, value: 0x0 },
Language: { configurable: false, enumerable: true, value: 0x1 },
ExtLang: { configurable: false, enumerable: true, value: 0x2 },
Script: { configurable: false, enumerable: true, value: 0x4 },
Region: { configurable: false, enumerable: true, value: 0x8 },
Variant: { configurable: false, enumerable: true, value: 0x10 },
Singleton: { configurable: false, enumerable: true, value: 0x20 },
Extension: { configurable: false, enumerable: true, value: 0x40 },
PrivateUse: { configurable: false, enumerable: true, value: 0x80 },
Invalid: { configurable: false, enumerable: true, value: 0xFF }
})
const _wild = { r: /^\*$/i, v: Types.Wildcard }
const _pvt = { r: /^x$/i, v: Types.PrivateUse | Types.Singleton }
const _ext = { r: /^[a-wy-z]$/i, v: Types.Extension | Types.Singleton }
const _lang = { r: /^[a-z]{2,3}$/i, v: Types.Language }
const _extlang = { r: /^[a-z]{3}$/i, v: Types.ExtLang }
const _script = { r: /^[a-z]{4}$/i, v: Types.Script }
const _region = { r: /^[a-z]{2}|[0-9]{3}$/i, v: Types.Region }
const _variant = { r: /^[a-z0-9]{5,8}|[0-9][a-z0-9]{3}$/i, v: Types.Variant }
const _other = { r: /^[a-z0-9]{2,8}$/i, v: Types.Other }
const kInner = Symbol('inner')
function flag (a, b) {
return (a & b) === b
}
function countext (previous) {
let c = 1
let p = previous
while (p) {
if (p.type === Types.ExtLang) c++
else break
p = p.previous
}
return c
}
function extpvtchk (v, previous) {
if (previous) {
if (!flag(v, Types.Singleton) && flag(previous.type, Types.Extension)) { v |= Types.Extension } else if (!flag(v, Types.Singleton) && flag(previous.type, Types.PrivateUse)) { v |= Types.PrivateUse }
}
return v
}
function classify (token, previous) {
var ret
function _test (t) {
return t.r.test(token)
};
if (token.length === 0) { return Types.Invalid }
if (previous === undefined) {
ret = [_wild, _pvt, _lang].find(_test)
return ret ? ret.v : Types.Invalid
} else {
switch (previous.type) {
case Types.Language:
case Types.ExtLang:
ret = [_wild, _pvt, _ext, _extlang, _script, _region, _variant, _other]
.find(_test)
if (!ret) return Types.Invalid
return ret.v === Types.ExtLang
? (countext(previous) <= 3 ? ret.v : Types.Invalid)
: extpvtchk(ret.v, previous)
case Types.Script:
ret = [_wild, _pvt, _ext, _region, _variant, _other].find(_test)
return ret ? extpvtchk(ret.v, previous) : Types.Invalid
case Types.Region:
ret = [_wild, _pvt, _ext, _variant, _other].find(_test)
return ret ? extpvtchk(ret.v, previous) : Types.Invalid
default:
ret = [_wild, _pvt, _ext, _other].find(_test)
return ret ? extpvtchk(ret.v, previous) : Types.Invalid
}
}
}
class Subtag {
constructor (token, previous) {
token = token.toLowerCase()
if (previous !== undefined) {
if (previous[kInner] === undefined) { throw new TypeError('The "previous" argument must be a Subtag') }
previous[kInner].next = this
}
const type = classify(token, previous)
this[kInner] = {
token,
previous,
type,
wild: type === undefined,
singleton: (type & Types.Singleton) === Types.Singleton,
extension: (type & Types.Extension) === Types.Extension,
privateuse: (type & Types.PrivateUse) === Types.PrivateUse
}
}
get token () {
return this[kInner].token
}
get next () {
return this[kInner].next
}
get previous () {
return this[kInner].previous
}
get type () {
return this[kInner].type
}
get wild () {
return this[kInner].wild
}
get singleton () {
return this[kInner].singleton
}
get extension () {
return this[kInner].extension
}
get privateuse () {
return this[kInner].privateuse
}
[kInspect] () {
return this[kInner]
}
toString () {
const token = this[kInner].token
switch (this[kInner].type) {
case Types.Script:
return token[0].toUpperCase() + token.slice(1)
case Types.Region:
return token.toUpperCase()
default:
if (this[kInner].singleton) {
let ret = token
let next = this.next
while (next && !next[kInner].singleton) {
ret += `-${next[kInner].token}`
next = next[kInner].next
}
return ret
} else {
return token
}
}
}
valueOf () {
return this.toString()
}
}
class LanguageTag {
constructor (tag) {
let language
let region
let script
let variant
let invalid
let privateuse
let extensions
let first
let p
let wild = false
let length = 0
const tokens = String(tag).split(/[-_]/)
for (; length < tokens.length; length++) {
p = new Subtag(tokens[length], p)
switch (p.type) {
case Types.Language:
language = p.toString()
break
case Types.Region:
region = p.toString()
break
case Types.Script:
script = p.toString()
break
case Types.Variant:
variant = p.toString()
break
case Types.Invalid:
invalid = true
break
default:
if (p.singleton) {
if (p.privateuse && !privateuse) {
privateuse = p
} else if (p.extension) {
extensions = extensions || {}
extensions[p.token] = p
}
} else if (p.wild) {
wild = true
}
}
first = first || p
}
this[kInner] = {
language,
region,
script,
variant,
invalid,
privateuse,
extensions,
wild,
length,
first
}
}
get language () {
return this[kInner].language
}
get region () {
return this[kInner].region
}
get script () {
return this[kInner].script
}
get variant () {
return this[kInner].variant
}
get invalid () {
return this[kInner].invalid
}
get privateuse () {
return this[kInner].privateuse
}
get extensions () {
return this[kInner].extensions
}
get wild () {
return this[kInner].wild
}
get length () {
return this[kInner].length
}
get first () {
return this[kInner].first
}
[kInspect] () {
return this[kInner]
}
suitableFor (other) {
const inner = this[kInner]
if (inner.wild) return true
const _other = new LanguageTag(other)
const otherInner = _other[kInner]
if (inner.language !== otherInner.language) return false
if (inner.region && inner.region !== otherInner.region) return false
if (inner.script && inner.script !== otherInner.script) return false
if (inner.variant && inner.variant !== otherInner.variant) return false
return true
}
matches (other) {
const inner = this[kInner]
const wild = inner.wild
let a = wild ? this : other
const b = wild ? other : this
if (a === '*') a = '(?:[a-z0-9]{1,8})(?:-[a-z0-9]{1,8})*'
const pattern = a.toString().replace(/-\*/g, '(?:-[a-z0-9]{1,8})*')
const reg = new RegExp(`^${pattern}$`, 'i')
return reg.test(b.toString())
}
truncate (options) {
const tags = []
const inner = this[kInner]
let n = inner.first
if (n[kInner].privateuse) { return this } // don't truncate if tag is a privateuse
while (n !== undefined) {
let t = n
n = n.next
if (t.type < 0x10) {
if (options) {
if ((options.extlang === false && t.type === Types.ExtLang) ||
(options.script === false && t.type === Types.Script) ||
(options.variant === false && t.type === Types.Variant)) {
continue
}
}
tags.push(t.toString())
}
}
return new LanguageTag(tags.join('-'))
}
get minimal () {
return this.truncate({ extlang: false, script: false, variant: false })
}
valueOf () {
return this.toString()
}
toString () {
return Array.from(this).join('-')
}
* [Symbol.iterator] () {
let n = this.first
while (n !== undefined) {
yield n
n = n.next
}
}
forEach (callback) {
if (typeof callback !== 'function') { throw new TypeError('A callback function must be provided') }
for (const tag of this) { callback.call(this, tag) }
}
}
LanguageTag.Types = Types
module.exports = LanguageTag
+8
-12
{
"name": "rfc5646",
"version": "2.0.0",
"version": "3.0.0",
"description": "RFC 5646 Language Tags Implementation",
"license": "Public Domain",
"keywords": [
"rfc5646",
"languagetag"
],
"maintainers": [
"James M Snell <jasnell@us.ibm.com> (http://www.chmod777self.com)"
],
"keywords": [ "rfc5646", "languagetag" ],
"author": "James M Snell <jasnell@gmail.com>",
"scripts": {
"test": "mocha"
"test": "standard && mocha test -R tap"
},
"devDependencies": {
"async": "^1.4.0",
"mocha": "^2.2.5"
"async": "^2.5.0",
"mocha": "^4.0.1",
"standard": "^10.0.3"
},
"main": "./src/main.js",
"main": "main.js",
"repository": {

@@ -22,0 +18,0 @@ "type": "git",

+15
-10
# RFC 5646 Language Tag Implementation
Basic Language Tag handling. Does not attempt to do validation against
the registry. If you need a more complete implementation, look at
https://www.npmjs.com/package/language-tags by https://www.npmjs.com/~mcg
the registry.

@@ -12,2 +11,6 @@ License: Public Domain

```bash
yarn add rfc5646
```
```bash
npm install rfc5646

@@ -18,7 +21,9 @@ ```

```javascript
var LanguageTag = require('rfc5646');
```js
const LanguageTag = require('rfc5646');
var tag = LanguageTag('en-Latn-US');
// (The new keyword is required)
const tag = new LanguageTag('en-Latn-US');
// Immutable properties
console.log(tag.language); // en

@@ -31,2 +36,3 @@ console.log(tag.script); // Latn

console.log(tag.matches('en-*')); // true
console.log(tag.suitableFor('en-US')); // true
console.log(tag.minimal.suitableFor('en-US')); // true

@@ -36,7 +42,7 @@ console.log(tag.truncate().toString()); // en-Latn-US

tag.forEach(function(subtag) {
console.log(subtag.toString());
});
// ES6 Iteration...
tag.forEach((subtag) => console.log(subtag.toString()));
tag = LanguageTag('en-US-a-abc-b-xyz-x-123');
// Extensions and Private Use Tags
tag = new LanguageTag('en-US-a-abc-b-xyz-x-123');

@@ -46,3 +52,2 @@ console.log(tag.extensions.a.toString()); // a-abc

console.log(tag.privateuse.toString()); // x-123
```

Sorry, the diff of this file is not supported yet

##### Signed by https://keybase.io/jasnell
```
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - https://gpgtools.org
iQEcBAABCgAGBQJWJnVhAAoJEHNBsVwHCHesPmMIALeKhpZRjzrXUoFQlKw5n7Sy
k92HtUJzp+ZQuP+HiVhLsUzUbhk0O/vtAA7V3e4HJ9dU4Psea+9CKXh47p650mQF
1qOQ5Pid39UZ/zsit6fc4vYNM3vWwEbjHuGOUD5PVAfttPLhBH9w6G2s2zxwGXcx
hEOheYmNxpIYYHoXb2e4jx+i6YtW8U28J2yDB9lruowIooDYknQxCcIGRg4pJrEa
etYqtc3MD1N5xKxK1T7gh4jK0s5Rv0wc+6eX09wLwA4ooAbULxOOMCoCyQyN+q4S
uWH28hNeUAvI9aGau4Am04bcJzNvOdtuBB0QbHu3xPLIhPS0xXS4zZLctYz2rK8=
=55si
-----END PGP SIGNATURE-----
```
<!-- END SIGNATURES -->
### Begin signed statement
#### Expect
```
size exec file contents
./
15 .gitignore 44d20a8fa365553cb3fc77c3b81d228a44fe28b980b4a3907a6120d58af3253b
93 .jshintrc ac72baaccc327aca1aa7b22eb98d0eec7b15a69cfc2fe5a568c6f086ba8e2197
32 .npmignore 97df9979b36f6537fbdd6bacf86a9c534a0548be28fd3c038be3e33502b76d9a
620 example.js b1e1f7469e1fb5e8bb38d88a0c95ad89c4d02074dd5a0af8830e337dacb1f17f
513 package.json 7899444e5b69cb85941ecee2a1dc3afd52349def778c220cba428c9cc9e74f7a
1330 README.md 10addbae27687d65f7c6db6896875030ccb3397cc183359e459de1b9d4fb1638
src/
8772 main.js 0ae9ad6ef850da8296b8214fe0790ab99defbec73dd90bf8ef517b89c90b61ba
test/
10636 test.js 8a149f597584cdde54120f63dd3f8c5a32d0ee25d1c929acb2cd7e57327c15d8
```
#### Ignore
```
/SIGNED.md
```
#### Presets
```
git # ignore .git and anything as described by .gitignore files
dropbox # ignore .dropbox-cache and other Dropbox-related files
kb # ignore anything as described by .kbignore files
```
<!-- summarize version = 0.0.9 -->
### End signed statement
<hr>
#### Notes
With keybase you can sign any directory's contents, whether it's a git repo,
source code distribution, or a personal documents folder. It aims to replace the drudgery of:
1. comparing a zipped file to a detached statement
2. downloading a public key
3. confirming it is in fact the author's by reviewing public statements they've made, using it
All in one simple command:
```bash
keybase dir verify
```
There are lots of options, including assertions for automating your checks.
For more info, check out https://keybase.io/docs/command_line/code_signing
/**
* @overview
* RFC 5646 Language Tags Implementation
* @author James M Snell (jasnell@gmail.com)
* @license Public Domain
* @description An implementation of the RFC 5646 Language Tag
* syntax that works in browser and server environments
* and does not require Language Tag registry knowledge.
* @example
* var tag = new LanguageTag('en-Latn-US');
* console.log(tag.language); // en
* console.log(tag.script); // Latn
* console.log(tag.region); // US
* console.log(tag.variant); // undefined
* console.log(tag.minimal; // en-US;
* console.log(tag == 'en-US'); // true
* console.log(tag.matches('en-*')); // true
* console.log(tag.minimal.suitableFor('en-US')); // true
* console.log(tag.truncate().toString()); //en-Latn-US
* console.log(tag.truncate({script:false}).toString()); // en-US
* var i = tag.iterator;
* var n
* while(!(n=i.next()).done) {
* console.log(n.value.toString());
* }
**/
'use strict';
function def(obj, prop,value) {
Object.defineProperty(
obj, prop,{
enumerable: true,
value: value
});
}
/**
* @enum {number}
* @memberOf LanguageTag
* @description The Subtag Type
**/
const Types = {
/** Subtag is equal to '*' (value 0x0) **/
Wildcard: undefined,
Other : 0x0,
/** Language Subtag (value 0x1) **/
Language : 0x1,
/** Ext-Lang Subtag (value 0x2) **/
ExtLang : 0x2,
/** Script Subtag (value 0x4) **/
Script : 0x4,
/** Region Subtag (value 0x8) **/
Region : 0x8,
/** Variant Subtag (value 0x10) **/
Variant : 0x10,
/** Singleton Subtag (value 0x20) **/
Singleton: 0x20,
/** Extension Subtag (value 0x40) **/
Extension: 0x40,
/** Private Use Subtag (value 0x80) **/
PrivateUse: 0x80,
/** Invalid Subtag (value 0xFF) **/
Invalid: 0xFF
};
const _wild = {r:/^\*$/i,v:Types.Wildcard},
_pvt = {r:/^x$/i,v:Types.PrivateUse|Types.Singleton},
_ext = {r:/^[a-wy-z]$/i,v:Types.Extension|Types.Singleton},
_lang = {r:/^[a-z]{2,3}$/i,v:Types.Language},
_extlang = {r:/^[a-z]{3}$/i,v:Types.ExtLang},
_script = {r:/^[a-z]{4}$/i,v:Types.Script},
_region = {r:/^[a-z]{2}|[0-9]{3}$/i,v:Types.Region},
_variant = {r:/^[a-z0-9]{5,8}|[0-9][a-z0-9]{3}$/i,v:Types.Variant},
_other = {r:/^[a-z0-9]{2,8}$/i,v:Types.Other}
;
function flag(a,b) {
return (a&b)==b;
}
function countext(previous) {
var c = 1, p = previous;
while(p) {
if (p.type == Types.ExtLang) c++;
else break;
p = p.previous;
}
return c;
}
function extpvtchk(v,previous) {
if (previous) {
if (!flag(v,Types.Singleton) && flag(previous.type,Types.Extension))
v |= Types.Extension;
else if (!flag(v,Types.Singleton) && flag(previous.type,Types.PrivateUse))
v |= Types.PrivateUse;
}
return v;
}
function classify(token, previous) {
var ret;
var _test = function(t) {
return t.r.test(token);
};
if (token.length === 0)
return Types.Invalid;
if (!previous) {
ret = [_wild, _pvt, _lang].find(_test);
return ret ? ret.v : Types.Invalid;
} else {
switch(previous.type) {
case Types.Language:
case Types.ExtLang:
ret = [_wild,_pvt,_ext,_extlang,_script,_region,_variant,_other]
.find(_test);
if (!ret) return Types.Invalid;
return ret.v == Types.ExtLang ?
(countext(previous) <= 3 ? ret.v : Types.Invalid) :
extpvtchk(ret.v,previous);
case Types.Script:
ret = [_wild,_pvt,_ext,_region,_variant,_other].find(_test);
return ret ? extpvtchk(ret.v,previous): Types.Invalid;
case Types.Region:
ret = [_wild,_pvt,_ext,_variant,_other].find(_test);
return ret ? extpvtchk(ret.v,previous) : Types.Invalid;
default:
ret = [_wild,_pvt,_ext,_other].find(_test);
return ret ? extpvtchk(ret.v,previous) : Types.Invalid;
}
}
}
function Subtag(token, previous) {
if (!(this instanceof Subtag))
return new Subtag(token, previous);
def(this,'token',token.toLowerCase());
if (previous) {
def(previous,'next',this);
def(this,'previous',previous);
}
def(this,'type',classify(token,previous));
def(this,'wild',this.type === undefined);
def(this,'singleton',flag(this.type,Types.Singleton));
def(this,'extension',flag(this.type,Types.Extension));
def(this,'privateUse',flag(this.type,Types.PrivateUse));
}
Subtag.prototype = {
toString: function() {
switch(this.type) {
case Types.Script:
return this.token[0].toUpperCase() + this.token.substr(1);
case Types.Region:
return this.token.toUpperCase();
default:
if (this.singleton) {
var ret = this.token;
var next = this.next;
while(next && !next.singleton) {
ret += '-' + next.token;
next = next.next;
}
return ret;
} else {
return this.token;
}
}
},
valueOf: function() {
return this.toString();
}
};
function LanguageTag(_tag) {
if (!(this instanceof LanguageTag))
return new LanguageTag(_tag.toString());
else if (_tag instanceof LanguageTag)
return _tag;
// check for grandfathered here...
var f, p;
var splits = _tag.split(/[-_]/);
var exts;
var wild = false;
for (var n = 0, l = splits.length; n < l; n++) {
p = new Subtag(splits[n], p);
switch(p.type) {
case Types.Language:
def(this,'language',p.toString());
break;
case Types.Region:
def(this,'region',p.toString());
break;
case Types.Script:
def(this,'script',p.toString());
break;
case Types.Variant:
def(this,'variant',p.toString());
break;
case Types.Invalid:
def(this,'invalid',true);
break;
default:
if (p.singleton) {
if (p.privateUse) {
if (!this.privateuse)
def(this,'privateuse',p);
} else if (p.extension) {
if (!exts) exts = {};
exts[p.token] = p;
}
} else if (p.wild) {
this.wild = true;
}
}
f = f||p;
}
if (exts) def(this,'extensions',exts);
def(this,'wild', wild);
def(this,'length',splits.length);
def(this,'first',f);
}
LanguageTag.prototype = {
suitableFor : function(other) {
if (this.wild) return true;
var _othertag = new LanguageTag(other);
if (this.language !== _othertag.language) return false;
if (this.region && this.region !== _othertag.region) return false;
if (this.script && this.script !== _othertag.script) return false;
if (this.variant && this.variant !== _othertag.variant) return false;
return true;
},
valueOf : function() {
return this.toString();
},
toString : function() {
var tags = [], n = this.first;
this.forEach(function(tag) {
tags.push(tag.toString());
});
return tags.join('-');
},
matches : function(other) {
var wild = this.wild;
var a = wild?this:other;
var b = wild?other:this;
if (a === '*') a = '(?:[a-z0-9]{1,8})(?:-[a-z0-9]{1,8})*';
var pattern = a.toString().replace(/-\*/g,'(?:-[a-z0-9]{1,8})*');
var reg = new RegExp('^'+pattern+'$', 'i');
return reg.test(b.toString());
},
truncate : function(options) {
var tags = [], n = this.first;
if (n.privateUse) return this; // don't truncate if tag is a private use
while(n) {
var t = n;
n = n.next;
if (t.type < 0x10) {
if (options) {
if ((options.extlang === false && t.type === Types.ExtLang) ||
(options.script === false && t.type === Types.Script) ||
(options.variant === false && t.type === Types.Variant)) {
continue;
}
}
tags.push(t.toString());
}
}
return new LanguageTag(tags.join('-'));
},
get minimal() {
return this.truncate({extlang:false,script:false,variant:false});
},
get iterator() {
var current = this.first;
var ret = {
next: function() {
if (this.done) return {done:true};
var ret = current;
if (current.singleton) {
do {
current = current.next;
} while(current && !current.singleton);
} else {
current = current.next;
}
return {done:false,value:ret};
},
get done() {
return current === undefined;
}
};
return ret;
},
forEach : function(callback) {
if (typeof callback !== 'function')
throw new Error('A callback function must be provided');
var i = this.iterator;
while(!i.done) {
callback(i.next().value);
}
}
};
LanguageTag.Types = Types;
module.exports = LanguageTag;
'use strict';
// source: http://www.langtag.net/test-suites.html
const valid = ['fr',
'fr-Latn',
'fr-fra',
'fr-Latn-FR',
'fr-Latn-419',
'fr-FR',
'ax-TZ',
'fr-shadok',
'fr-y-myext-myext2',
'fra-Latn',
'fra',
'fra-FX',
'i-klingon',
'I-kLINgon',
'no-bok',
'fr-Lat',
'mn-Cyrl-MN',
'mN-cYrL-Mn',
'fr-Latn-CA',
'en-US',
'fr-Latn-CA',
'i-enochian',
'x-fr-CH',
'sr-Latn-CS',
'es-419',
'sl-nedis',
'de-CH-1996',
'de-Latg-1996',
'sl-IT-nedis',
'en-a-bbb-x-a-ccc',
'de-a-value',
'en-Latn-GB-boont-r-extended-sequence-x-private',
'en-x-US',
'az-Arab-x-AZE-derbend',
'es-Latn-CO-x-private',
'en-US-boont',
'ab-x-abc-x-abc',
'ab-x-abc-a-a',
'i-default',
'i-klingon',
'abcd-Latn',
'AaBbCcDd-x-y-any-x',
'en',
'de-AT',
'es-419',
'de-CH-1901',
'sr-Cyrl',
'sr-Cyrl-CS',
'sl-Latn-IT-rozaj',
'en-US-x-twain',
'zh-cmn',
'zh-cmn-Hant',
'zh-cmn-Hant-HK',
'zh-gan',
'zh-yue-Hant-HK',
'xr-lxs-qut',
'xr-lqt-qu',
'xr-p-lze',
'fr',
'fr-Latn',
'fr-fra',
'fr-Latn-FR',
'fr-Latn-419',
'fr-FR',
'fr-y-myext-myext2',
'apa-Latn',
'apa',
'apa-CA',
'i-klingon',
'no-bok',
'fr-Lat',
'mn-Cyrl-MN',
'mN-cYrL-Mn',
'fr-Latn-CA',
'en-US',
'fr-Latn-CA',
'i-enochian',
'x-fr-CH',
'sr-Latn-CS',
'es-419',
'sl-nedis',
'de-CH-1996',
'de-Latg-1996',
'sl-IT-nedis',
'en-a-bbb-x-a-ccc',
'de-a-value',
'en-x-US',
'az-Arab-x-AZE-derbend',
'es-Latn-CO-x-private',
'ab-x-abc-x-abc',
'ab-x-abc-a-a',
'i-default',
'i-klingon',
'en',
'de-AT',
'es-419',
'de-CH-1901',
'sr-Cyrl',
'sr-Cyrl-CS',
'sl-Latn-IT-rozaj',
'en-US-x-twain',
'zh-cmn',
'zh-cmn-Hant',
'zh-cmn-Hant-HK',
'zh-gan',
'zh-yue-Hant-HK',
'en-Latn-GB-boont-r-extended-sequence-x-private',
'en-US-boont'
];
const invalid = [
'f',
'f-Latn',
'fr-Latn-F',
'a-value',
'en-a-bbb-a-ccc',
'tlh-a-b-foo',
'i-notexist',
'abcdefghi-012345678',
'ab-abc-abc-abc-abc',
'ab-abcd-abc',
'ab-ab-abc',
'ab-123-abc',
'a-Hant-ZH',
'a1-Hant-ZH',
'ab-abcde-abc',
'ab-1abc-abc',
'ab-ab-abcd',
'ab-123-abcd',
'ab-abcde-abcd',
'ab-1abc-abcd',
'ab-a-b',
'ab-a-x',
'ab--ab',
'ab-abc-',
'-ab-abc',
'ab-c-abc-r-toto-c-abc',
'abcd-efg',
'aabbccddE',
'ax-TZ',
'fra-Latn',
'fra',
'fra-FX',
'abcd-Latn',
'AaBbCcDd-x-y-any-x',
'zh-Latm-CN',
'de-DE-1902',
'fr-shadok'
];
const wellformed = [
'en-GB-oed',
'zh-cmn-Hans',
'no-bok',
'#zh-Hans-HK-SCOUSE-a-foobar-b-x-a-en@collation=phonebook;calendar=islamic',
'#i-default@abc=def',
'#x-foobar@abc=def',
'#zh-Hans-HK-SCOUSE-a-foobar-x-a-en@collation=phonebook;calendar=islamic',
'#zh@collation=phonebook',
'#zh@collation=phonebook;calendar=islamic',
'#zh-Hans-HK-SCOUSE-a-foobar-b-en-x-a-en@collation=phonebook;calendar=islamic',
'AaBbCcDd',
'AaBbCcDd-x-y-any-x',
'abcd-Latn',
'ab-x-abc-a-a',
'ab-x-abc-a-a',
'ab-x-abc-x-abc',
'ax-TZ',
'az-Arab-x-AZE-derbend',
'de-a-value',
'de-CH-1996',
'de-Latg-1996',
'en',
'en-a-bbb-x-a-ccc',
'en-gb-oed',
'en-Latn',
'en-Latn-001',
'en-Latn-GB-boont-r-extended-sequence-x-private',
'en-Latn-US',
'en-Latn-US-lojban-gaulish',
'en-Latn-US-lojban-gaulish-a-12345678-ABCD-b-ABCDEFGH',
'en-Latn-US-lojban-gaulish-a-12345678-ABCD-b-ABCDEFGH-x-a-b-c-12345678',
'en-US',
'en-US',
'en-US-boont',
'en-x-US',
'es-419',
'es-Latn-CO-x-private',
'fr ',
'fra',
'fra-FX',
'fra-Latn',
'fr-FR',
'fr-Latn',
'fr-Latn-419',
'fr-Latn-CA',
'fr-Latn-CA',
'fr-Latn-FR',
'fr-shadok',
'fr-y-myext-myext2',
'i-default',
'i-default',
'i-enochian',
'i-klingon',
'i-klingon',
'mn-Cyrl-MN',
'mN-cYrL-Mn',
'no-bok',
'sl-IT-nedis',
'sl-nedis',
'sr-Latn-CS',
'x-12345678-a',
'x-fr-CH',
'i-notexist',
'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',
'art-lojban',
'cel-gaulish',
'en-boont',
'en-scouse',
'no-bok',
'no-nyn',
'zh-cmn',
'zh-cmn-Hans',
'zh-cmn-Hant',
'zh-gan',
'zh-guoyu',
'zh-hakka',
'zh-min',
'zh-min-nan',
'zh-wuu',
'zh-xiang',
'zh-yue',
'ab-a-abc-a-abc',
'en-a-bbb-a-ccc',
'ab-c-abc-r-toto-c-abc',
'zszLDm-sCVS-es-x-gn762vG-83-S-mlL',
'IIJdFI-cfZv',
'kbAxSgJ-685',
'tbutP',
'hDL-595',
'dUf-iUjq-0hJ4P-5YkF-WD8fk',
'FZAABA-FH',
'xZ-lh-4QfM5z9J-1eG4-x-K-R6VPr2z',
'Fyi',
'SeI-DbaG',
'ch-xwFn',
'OeC-GPVI',
'JLzvUSi',
'Fxh-hLAs',
'pKHzCP-sgaO-554',
'eytqeW-hfgH-uQ',
'ydn-zeOP-PR',
'uoWmBM-yHCf-JE',
'xwYem',
'zie',
'Re-wjSv-Ey-i-XE-E-JjWTEB8-f-DLSH-NVzLH-AtnFGWoH-SIDE',
'Ri-063-c-u6v-ZfhkToTB-C-IFfmv-XT-j-rdyYFMhK-h-pY-D5-Oh6FqBhL-hcXt-v-WdpNx71-K-c74m4-eBTT7-JdH7Q1Z',
'ji',
'IM-487',
'EPZ-zwcB',
'GauwEcwo',
'kDEP',
'FwDYt-TNvo',
'ottqP-KLES-x-9-i9',
'fcflR-grQQ',
'TvFwdu-kYhs',
'WE-336',
'MgxQa-ywEp-8lcW-7bvT-h-dP1Md-0h7-0Z3ir-K-Srkm-kA-7LXM-Z-whb2MiO-2mNsvbLm-W3O-4r-U-KceIxHdI-gvMVgUBV-2uRUni-J0-7C8yTK2',
'Hyr-B-evMtVoB1-mtsVZf-vQMV-gM-I-rr-kvLzg-f-lAUK-Qb36Ne-Z-7eFzOD-mv6kKf-l-miZ7U3-k-XDGtNQG',
'ybrlCpzy',
'PTow-w-cAQ51-8Xd6E-cumicgt-WpkZv3NY-q-ORYPRy-v-A4jL4A-iNEqQZZ-sjKn-W-N1F-pzyc-xP5eWz-LmsCiCcZ',
'ih-DlPR-PE',
'Krf-362',
'WzaD',
'EPaOnB-gHHn',
'XYta',
'NZ-RgOO-tR',
'at-FE',
'Tpc-693',
'YFp',
'gRQrQULo',
'pVomZ-585',
'laSu-ZcAq-338',
'gCW',
'PydSwHRI-TYfF',
'zKmWDD',
'X-bCrL5RL',
'HK',
'YMKGcLY',
'GDJ-nHYa-bw-X-ke-rohH5GfS-LdJKsGVe',
'tfOxdau-yjge-489-a-oB-I8Csb-1ESaK1v-VFNz-N-FT-ZQyn-On2-I-hu-vaW3-jIQb-vg0U-hUl-h-dO6KuJqB-U-tde2L-P3gHUY-vnl5c-RyO-H-gK1-zDPu-VF1oeh8W-kGzzvBbW-yuAJZ',
'LwDux',
'Zl-072',
'Ri-Ar',
'vocMSwo-cJnr-288',
'kUWq-gWfQ-794',
'YyzqKL-273',
'Xrw-ZHwH-841-9foT-ESSZF-6OqO-0knk-991U-9p3m-b-JhiV-0Kq7Y-h-cxphLb-cDlXUBOQ-X-4Ti-jty94yPp',
'en-GB-oed',
'LEuZl-so',
'HyvBvFi-cCAl-X-irMQA-Pzt-H',
'uDbsrAA-304',
'wTS',
'IWXS',
'XvDqNkSn-jRDR',
'gX-Ycbb-iLphEks-AQ1aJ5',
'FbSBz-VLcR-VL',
'JYoVQOP-Iytp',
'gDSoDGD-lq-v-7aFec-ag-k-Z4-0kgNxXC-7h',
'Bjvoayy-029',
'qSDJd',
'qpbQov',
'fYIll-516',
'GfgLyfWE-EHtB',
'Wc-ZMtk',
'cgh-VEYK',
'WRZs-AaFd-yQ',
'eSb-CpsZ-788',
'YVwFU',
'JSsHiQhr-MpjT-381',
'LuhtJIQi-JKYt',
'vVTvS-RHcP',
'SY',
'fSf-EgvQfI-ktWoG-8X5z-63PW',
'NOKcy',
'OjJb-550',
'KB',
'qzKBv-zDKk-589',
'Jr',
'Acw-GPXf-088',
'WAFSbos',
'HkgnmerM-x-e5-zf-VdDjcpz-1V6',
'UAfYflJU-uXDc-YV',
'x-CHsHx-VDcOUAur-FqagDTx-H-V0e74R',
'uZIAZ-Xmbh-pd',
'en-enx',
'en-enx-eny-enz-latn-us',
'fr-fra',
'fr-Lat',
//ILL-FORMED
'-a',
'a-',
'a1-Hant-ZH',
'aabbccddE',
'a--b',
'ab-123-abc',
'ab-123-abc',
'ab-123-abcd',
'ab-123-abcd',
'ab-1abc-abc',
'ab-1abc-abc',
'ab-1abc-abcd',
'ab-1abc-abcd',
'ab--ab',
'ab--ab',
'ab-a-b',
'ab-a-b',
'ab-ab-abc',
'ab-ab-abc',
'ab-ab-abcd',
'ab-ab-abcd',
'-ab-abc',
'-ab-abc',
'ab-abc-',
'ab-abc-',
'ab-abc-abc-abc-abc',
'ab-abc-abc-abc-abc',
'ab-abcd-abc',
'ab-abcd-abc',
'ab-abcde-abc',
'ab-abcde-abc',
'ab-abcde-abcd',
'ab-abcde-abcd',
'ab-a-x',
'ab-a-x',
'abcd-efg',
'abcdefghi-012345678',
'abcdefghi-012345678',
'a-foo',
'a-Hant-ZH',
'a-value',
'a-x',
'b-fish',
'en-enx-eny-enz-enw',
'en-UK-oed',
'en-US-Latn',
'f',
'f-Latn',
'fr-Latn-F',
'overlongone',
'tlh-a-b-foo',
'EdY-z_H791Xx6_m_kj',
'qWt85_8S0-L_rbBDq0gl_m_O_zsAx_nRS',
'VzyL2',
'T_VFJq-L-0JWuH_u2_VW-hK-kbE',
'u-t',
'Q-f_ZVJXyc-doj_k-i',
'JWB7gNa_K-5GB-25t_W-s-ZbGVwDu1-H3E',
'b-2T-Qob_L-C9v_2CZxK86',
'fQTpX_0_4Vg_L3L_g7VtALh2',
'S-Z-E_J',
'f6wsq-02_i-F',
'9_GcUPq_G',
'QjsIy_9-0-7_Dv2yPV09_D-JXWXM',
'D_se-f-k',
'ON47Wv1_2_W',
'f-z-R_s-ha',
'N3APeiw_195_Bx2-mM-pf-Z-Ip5lXWa-5r',
'IRjxU-E_6kS_D_b1b_H',
'NB-3-5-AyW_FQ-9hB-TrRJg3JV_3C',
'yF-3a_V_FoJQAHeL_Z-Mc-u',
'n_w_bbunOG_1-s-tJMT5je',
'Q-AEWE_X',
'57b1O_k_R6MU_sb',
'hK_65J_i-o_SI-Y',
'wB4B7u_5I2_I_NZPI',
'J24Nb_q_d-zE',
'v6-dHjJmvPS_IEb-x_A-O-i',
'8_8_dl-ZgBr84u-P-E',
'nIn-xD7EVhe_C',
'5_N-6P_x7Of_Lo_6_YX_R',
'0_46Oo0sZ-YNwiU8Wr_d-M-pg1OriV',
'laiY-5',
'K-8Mdd-j_ila0sSpo_aO8_J',
'wNATtSL-Cp4_gPa_fD41_9z',
'H_FGz5V8_n6rrcoz0_1O6d-kH-7-N',
'wDOrnHU-odqJ_vWl',
'gP_qO-I-jH',
'h',
'dJ0hX-o_csBykEhU-F',
'L-Vf7_BV_eRJ5goSF_Kp',
'y-oF-chnavU-H',
'9FkG-8Q-8_v',
'W_l_NDQqI-O_SFSAOVq',
'kDG3fzXw',
't-nsSp-7-t-mUK2',
'Yw-F',
'1-S_3_l',
'u-v_brn-Y',
'4_ft_3ZPZC5lA_D',
'n_dR-QodsqJnh_e',
'Hwvt-bSwZwj_KL-hxg0m-3_hUG',
'mQHzvcV-UL-o2O_1KhUJQo_G2_uryk3-a',
'b-UTn33HF',
'r-Ep-jY-aFM_N_H',
'K-k-krEZ0gwD_k_ua-9dm3Oy-s_v',
'XS_oS-p',
'EIx_h-zf5',
'p_z-0_i-omQCo3B',
'1_q0N_jo_9',
'0Ai-6-S',
'L-LZEp_HtW',
'Zj-A4JD_2A5Aj7_b-m3',
'x',
'p-qPuXQpp_d-jeKifB-c-7_G-X',
'X94cvJ_A',
'F2D25R_qk_W-w_Okf_kx',
'rc-f',
'D',
'gD_WrDfxmF-wu-E-U4t',
'Z_BN9O4_D9-D_0E_KnCwZF-84b-19',
'T-8_g-u-0_E',
'lXTtys9j_X_A_m-vtNiNMw_X_b-C6Nr',
'V_Ps-4Y-S',
'X5wGEA',
'mIbHFf_ALu4_Jo1Z1',
'ET-TacYx_c',
'Z-Lm5cAP_ri88-d_q_fi8-x',
'rTi2ah-4j_j_4AlxTs6m_8-g9zqncIf-N5',
'FBaLB85_u-0NxhAy-ZU_9c',
'x_j_l-5_aV95_s_tY_jp4',
'PL768_D-m7jNWjfD-Nl_7qvb_bs_8_Vg',
'9-yOc-gbh',
'6DYxZ_SL-S_Ye',
'ZCa-U-muib-6-d-f_oEh_O',
'Qt-S-o8340F_f_aGax-c-jbV0gfK_p',
'WE_SzOI_OGuoBDk-gDp',
'cs-Y_9',
'm1_uj',
'Y-ob_PT',
'li-B',
'f-2-7-9m_f8den_J_T_d',
'p-Os0dua-H_o-u',
'L',
'rby-w'
];
const LanguageTag = require('../');
const async = require('async');
const assert = require('assert');
function testParse(tag) {
return function() {
it(tag, function(done) {
try {
var t = new LanguageTag(tag);
if (!t.invalid) {
// if it's valid, it has to at least have a language or privateuse
assert(t.language || t.privateuse);
}
done();
} catch (err) {
done(err);
}
});
};
}
describe('Liberal Parsing Tests', function() {
// everything should parse, even invalid tags,
// that doesn't make the tags valid tho
async.parallel(
valid.map(testParse),
function() {});
async.parallel(
invalid.map(testParse),
function() {});
async.parallel(
wellformed.map(testParse),
function() {});
});
describe('Minimal Valid Example', function() {
it('All asserts should pass', function() {
var tag = new LanguageTag('en-Latn-US');
assert.equal(tag.language,'en');
assert.equal(tag.script,'Latn');
assert.equal(tag.region,'US');
assert.equal(tag.variant,undefined);
assert.equal(tag.minimal,'en-US');
assert(tag.matches('en-*'));
assert(tag.minimal.suitableFor('en-US'));
assert.equal(tag.truncate().toString(),'en-Latn-US');
assert.equal(tag.truncate({script:false}).toString(), 'en-US');
});
});