@fgv/ts-bcp47 5.1.0-2 → 5.1.0-4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/bcp/overrides.json +21 -0
- package/dist/data/unsd/m49.json +3723 -0
- package/dist/index.browser.js +30 -0
- package/dist/index.js +28 -0
- package/dist/packlets/bcp47/bcp47Subtags/converters.js +32 -0
- package/dist/packlets/bcp47/bcp47Subtags/index.js +26 -0
- package/dist/packlets/bcp47/bcp47Subtags/model.js +23 -0
- package/dist/packlets/bcp47/bcp47Subtags/validate.js +48 -0
- package/dist/packlets/bcp47/common.js +53 -0
- package/dist/packlets/bcp47/helpers.js +96 -0
- package/dist/packlets/bcp47/index.js +32 -0
- package/dist/packlets/bcp47/languageRegistryData.js +202 -0
- package/dist/packlets/bcp47/languageTag.js +363 -0
- package/dist/packlets/bcp47/languageTagParser.js +275 -0
- package/dist/packlets/bcp47/match/chooser.js +88 -0
- package/dist/packlets/bcp47/match/common.js +49 -0
- package/dist/packlets/bcp47/match/index.js +26 -0
- package/dist/packlets/bcp47/match/similarity.js +205 -0
- package/dist/packlets/bcp47/normalization/baseNormalizer.js +89 -0
- package/dist/packlets/bcp47/normalization/canonicalNormalizer.js +86 -0
- package/dist/packlets/bcp47/normalization/common.js +77 -0
- package/dist/packlets/bcp47/normalization/index.js +27 -0
- package/dist/packlets/bcp47/normalization/normalizeTag.js +101 -0
- package/dist/packlets/bcp47/normalization/preferredTagNormalizer.js +177 -0
- package/dist/packlets/bcp47/overrides/converters.js +49 -0
- package/dist/packlets/bcp47/overrides/defaultRegistries.js +38 -0
- package/dist/packlets/bcp47/overrides/index.js +25 -0
- package/dist/packlets/bcp47/overrides/model.js +23 -0
- package/dist/packlets/bcp47/overrides/overridesRegistry.js +83 -0
- package/dist/packlets/bcp47/validation/baseValidator.js +86 -0
- package/dist/packlets/bcp47/validation/common.js +77 -0
- package/dist/packlets/bcp47/validation/index.js +29 -0
- package/dist/packlets/bcp47/validation/isCanonical.js +79 -0
- package/dist/packlets/bcp47/validation/isInPreferredForm.js +46 -0
- package/dist/packlets/bcp47/validation/isStrictlyValid.js +94 -0
- package/dist/packlets/bcp47/validation/isValid.js +92 -0
- package/dist/packlets/bcp47/validation/isWellFormed.js +75 -0
- package/dist/packlets/bcp47/validation/validateTag.js +153 -0
- package/dist/packlets/iana/common/converters.js +58 -0
- package/dist/packlets/iana/common/model.js +23 -0
- package/dist/packlets/iana/common/registeredItems.js +120 -0
- package/dist/packlets/iana/common/utils.js +30 -0
- package/dist/packlets/iana/common/validate.js +59 -0
- package/dist/packlets/iana/converters.js +25 -0
- package/dist/packlets/iana/defaultRegistries.js +38 -0
- package/dist/packlets/iana/iana-data-embedded.js +60 -0
- package/dist/packlets/iana/index.browser.js +34 -0
- package/dist/packlets/iana/index.js +34 -0
- package/dist/packlets/iana/jar/converters.js +25 -0
- package/dist/packlets/iana/jar/index.js +26 -0
- package/dist/packlets/iana/jar/jarConverters.js +60 -0
- package/dist/packlets/iana/jar/jarModel.js +23 -0
- package/dist/packlets/iana/jar/language-subtags/converters.js +25 -0
- package/dist/packlets/iana/jar/language-subtags/index.js +26 -0
- package/dist/packlets/iana/jar/language-subtags/model.js +25 -0
- package/dist/packlets/iana/jar/language-subtags/registry/converters.js +180 -0
- package/dist/packlets/iana/jar/language-subtags/registry/index.js +26 -0
- package/dist/packlets/iana/jar/language-subtags/registry/model.js +43 -0
- package/dist/packlets/iana/jar/language-subtags/tags/converters.js +101 -0
- package/dist/packlets/iana/jar/language-subtags/tags/index.js +27 -0
- package/dist/packlets/iana/jar/language-subtags/tags/model.js +23 -0
- package/dist/packlets/iana/jar/language-subtags/tags/tagValidation.js +66 -0
- package/dist/packlets/iana/jar/language-subtags/tags/validate.js +85 -0
- package/dist/packlets/iana/jar/model.js +25 -0
- package/dist/packlets/iana/language-subtags/common.js +23 -0
- package/dist/packlets/iana/language-subtags/converters.js +182 -0
- package/dist/packlets/iana/language-subtags/index.browser.js +30 -0
- package/dist/packlets/iana/language-subtags/index.js +29 -0
- package/dist/packlets/iana/language-subtags/jarConverters.js +288 -0
- package/dist/packlets/iana/language-subtags/model.js +23 -0
- package/dist/packlets/iana/language-subtags/scope.js +169 -0
- package/dist/packlets/iana/language-subtags/subtagRegistry.js +108 -0
- package/dist/packlets/iana/language-subtags/validate.js +23 -0
- package/dist/packlets/iana/language-tag-extensions/converters.js +59 -0
- package/dist/packlets/iana/language-tag-extensions/extensionsRegistry.js +64 -0
- package/dist/packlets/iana/language-tag-extensions/extensionsScope.js +50 -0
- package/dist/packlets/iana/language-tag-extensions/index.js +28 -0
- package/dist/packlets/iana/language-tag-extensions/jarConverters.js +143 -0
- package/dist/packlets/iana/language-tag-extensions/model.js +24 -0
- package/dist/packlets/iana/language-tag-extensions/validate.js +33 -0
- package/dist/packlets/iana/languageRegistries.js +80 -0
- package/dist/packlets/iana/languageRegistriesFileLoader.js +73 -0
- package/dist/packlets/iana/languageRegistriesLoader.js +113 -0
- package/dist/packlets/iana/model.js +25 -0
- package/dist/packlets/iana/validate.js +23 -0
- package/dist/packlets/unsd/areas.js +92 -0
- package/dist/packlets/unsd/common.js +23 -0
- package/dist/packlets/unsd/csv/converters.js +75 -0
- package/dist/packlets/unsd/csv/index.js +25 -0
- package/dist/packlets/unsd/csv/model.js +23 -0
- package/dist/packlets/unsd/defaultRegistries.js +38 -0
- package/dist/packlets/unsd/index.js +27 -0
- package/dist/packlets/unsd/regionCodes.js +115 -0
- package/dist/packlets/unsd/regions.js +71 -0
- package/dist/packlets/utils/index.js +24 -0
- package/dist/packlets/utils/jsonHelpers.js +25 -0
- package/dist/packlets/utils/public.js +24 -0
- package/dist/packlets/utils/validationHelpers.js +116 -0
- package/dist/test/unit/bcp47/commonTestCases.js +475 -0
- package/dist/test/unit/bcp47/languageTagHelpers.js +178 -0
- package/dist/test/unit/iana/testConstants.js +68 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/package.json +36 -31
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2022 Erik Fortune
|
|
3
|
+
*
|
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
* furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
* copies or substantial portions of the Software.
|
|
13
|
+
*
|
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
* SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
import { GenericLanguageTagTest, allCanonicalTestKeys, allNonCanonicalTestKeys, allNonPreferredCanonicalKeys, allPreferredKeys, allTestKeys, allValidatingKeys } from './languageTagHelpers';
|
|
23
|
+
const testCaseInit = [
|
|
24
|
+
{
|
|
25
|
+
description: 'valid canonical primary language',
|
|
26
|
+
from: 'en',
|
|
27
|
+
expected: [['en', allTestKeys]],
|
|
28
|
+
expectedDescription: [['English', allTestKeys]]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
description: 'valid non-canonical primary language',
|
|
32
|
+
from: 'EN',
|
|
33
|
+
expected: [
|
|
34
|
+
['EN', allNonCanonicalTestKeys],
|
|
35
|
+
['en', allCanonicalTestKeys]
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
description: 'valid but deprecated primary language',
|
|
40
|
+
from: 'in',
|
|
41
|
+
expected: [
|
|
42
|
+
['in', [...allNonCanonicalTestKeys, ...allNonPreferredCanonicalKeys]],
|
|
43
|
+
['id', allPreferredKeys]
|
|
44
|
+
],
|
|
45
|
+
expectedDescription: [['Indonesian', allTestKeys]]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
description: 'valid private primary language',
|
|
49
|
+
from: 'qpn',
|
|
50
|
+
expected: [['qpn', allTestKeys]],
|
|
51
|
+
expectedDescription: [['Private use', allTestKeys]]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
description: 'invalid primary language',
|
|
55
|
+
from: 'ENG-US',
|
|
56
|
+
expected: [
|
|
57
|
+
['ENG-US', ['default', 'wellFormed']],
|
|
58
|
+
['eng-US', ['wellFormedCanonical']],
|
|
59
|
+
[/invalid language/i, allValidatingKeys]
|
|
60
|
+
],
|
|
61
|
+
expectedDescription: [['ENG as spoken in United States', ['wellFormed']]]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
description: 'valid canonical extlang',
|
|
65
|
+
from: 'zh-cmn',
|
|
66
|
+
expected: [
|
|
67
|
+
['zh-cmn', [...allNonCanonicalTestKeys, ...allNonPreferredCanonicalKeys]],
|
|
68
|
+
['cmn', allPreferredKeys]
|
|
69
|
+
],
|
|
70
|
+
expectedDescription: [
|
|
71
|
+
['Chinese / Mandarin Chinese', ['wellFormed']],
|
|
72
|
+
['Mandarin Chinese', ['preferred']]
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
description: 'valid canonical extlang with additional tags',
|
|
77
|
+
from: 'zh-cmn-CN-x-private',
|
|
78
|
+
expected: [
|
|
79
|
+
['zh-cmn-CN-x-private', [...allNonCanonicalTestKeys, ...allNonPreferredCanonicalKeys]],
|
|
80
|
+
['cmn-CN-x-private', allPreferredKeys]
|
|
81
|
+
],
|
|
82
|
+
expectedDescription: [
|
|
83
|
+
['Chinese / Mandarin Chinese as spoken in China (-x "private")', ['wellFormed']],
|
|
84
|
+
['Mandarin Chinese as spoken in China (-x "private")', ['preferred']]
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
description: 'valid non-canonical extlang',
|
|
89
|
+
from: 'ZH-Cmn',
|
|
90
|
+
expected: [
|
|
91
|
+
['ZH-Cmn', allNonCanonicalTestKeys],
|
|
92
|
+
['zh-cmn', allCanonicalTestKeys],
|
|
93
|
+
['cmn', allPreferredKeys]
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
description: 'invalid extlang',
|
|
98
|
+
from: 'zh-Han',
|
|
99
|
+
expected: [
|
|
100
|
+
['zh-Han', ['default', 'wellFormed']],
|
|
101
|
+
['zh-han', ['wellFormedCanonical']],
|
|
102
|
+
[/invalid extlang/i, allValidatingKeys]
|
|
103
|
+
],
|
|
104
|
+
expectedDescription: [['Chinese / Han', ['wellFormed']]]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
description: 'valid extlang with invalid prefix',
|
|
108
|
+
from: 'en-cmn-us',
|
|
109
|
+
expected: [
|
|
110
|
+
['en-cmn-us', ['default', 'wellFormed', 'valid']],
|
|
111
|
+
['en-cmn-US', ['wellFormedCanonical', 'validCanonical', 'preferred']],
|
|
112
|
+
[/invalid prefix/i, ['strictlyValid', 'strictlyValidCanonical', 'strictlyValidPreferred']]
|
|
113
|
+
],
|
|
114
|
+
expectedDescription: [['English / Mandarin Chinese as spoken in United States', ['wellFormed']]]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
description: 'multiple extlang',
|
|
118
|
+
from: 'zh-cmn-yue',
|
|
119
|
+
expected: [
|
|
120
|
+
['zh-cmn-yue', ['default', 'wellFormed', 'wellFormedCanonical']],
|
|
121
|
+
[/multiple extlang/i, allValidatingKeys]
|
|
122
|
+
],
|
|
123
|
+
expectedDescription: [['Chinese / Mandarin Chinese / Yue Chinese', ['wellFormed']]]
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
description: 'valid non-canonical, non-suppressed script',
|
|
127
|
+
from: 'zh-LATN',
|
|
128
|
+
expected: [
|
|
129
|
+
['zh-LATN', allNonCanonicalTestKeys],
|
|
130
|
+
['zh-Latn', allCanonicalTestKeys]
|
|
131
|
+
],
|
|
132
|
+
expectedDescription: [['Chinese in Latin script', ['wellFormed', 'preferred']]]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
description: 'valid non-canonical, suppressed script',
|
|
136
|
+
from: 'en-LATN',
|
|
137
|
+
expected: [
|
|
138
|
+
['en-LATN', allNonCanonicalTestKeys],
|
|
139
|
+
['en-Latn', allNonPreferredCanonicalKeys],
|
|
140
|
+
['en', allPreferredKeys]
|
|
141
|
+
],
|
|
142
|
+
expectedDescription: [
|
|
143
|
+
['English in Latin script', ['wellFormed']],
|
|
144
|
+
['English', ['preferred']]
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
description: 'invalid script',
|
|
149
|
+
from: 'en-AaaA',
|
|
150
|
+
expected: [
|
|
151
|
+
['en-AaaA', ['default', 'wellFormed']],
|
|
152
|
+
['en-Aaaa', ['wellFormedCanonical']],
|
|
153
|
+
[/invalid script/i, allValidatingKeys]
|
|
154
|
+
],
|
|
155
|
+
expectedDescription: [['English in AaaA script', ['wellFormed']]]
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
description: 'valid non-canonical iso3166-2 region',
|
|
159
|
+
from: 'en-aq',
|
|
160
|
+
expected: [
|
|
161
|
+
['en-aq', allNonCanonicalTestKeys],
|
|
162
|
+
['en-AQ', allCanonicalTestKeys]
|
|
163
|
+
],
|
|
164
|
+
expectedDescription: [['English as spoken in Antarctica', ['wellFormed', 'preferred']]]
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
description: 'valid non-canonical UN M.49 region',
|
|
168
|
+
from: 'es-419',
|
|
169
|
+
expected: [['es-419', allTestKeys]],
|
|
170
|
+
expectedDescription: [['Spanish as spoken in Latin America and the Caribbean', allTestKeys]]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
description: 'invalid region',
|
|
174
|
+
from: 'en-AJ',
|
|
175
|
+
expected: [
|
|
176
|
+
['en-AJ', ['default', 'wellFormed', 'wellFormedCanonical']],
|
|
177
|
+
[/invalid region/i, allValidatingKeys]
|
|
178
|
+
],
|
|
179
|
+
expectedDescription: [['English as spoken in AJ', ['wellFormed']]]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
description: 'strictly valid non-canonical variant',
|
|
183
|
+
from: 'ca-Valencia',
|
|
184
|
+
expected: [
|
|
185
|
+
['ca-Valencia', allNonCanonicalTestKeys],
|
|
186
|
+
['ca-valencia', allCanonicalTestKeys]
|
|
187
|
+
],
|
|
188
|
+
expectedDescription: [['Catalan (Valencian)', ['wellFormed']]]
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
description: 'not strictly-valid non-canonical variant',
|
|
192
|
+
from: 'fr-Valencia',
|
|
193
|
+
expected: [
|
|
194
|
+
['fr-Valencia', ['default', 'wellFormed', 'valid']],
|
|
195
|
+
['fr-valencia', ['wellFormedCanonical', 'validCanonical', 'preferred']],
|
|
196
|
+
[/invalid prefix/i, ['strictlyValid', 'strictlyValidCanonical', 'strictlyValidPreferred']]
|
|
197
|
+
],
|
|
198
|
+
expectedDescription: [['French (Valencian)', ['wellFormed']]]
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
description: 'valid but deprecated region',
|
|
202
|
+
from: 'en-BU',
|
|
203
|
+
expected: [
|
|
204
|
+
['en-BU', [...allNonCanonicalTestKeys, ...allNonPreferredCanonicalKeys]],
|
|
205
|
+
['en-MM', allPreferredKeys]
|
|
206
|
+
],
|
|
207
|
+
expectedDescription: [
|
|
208
|
+
['English as spoken in Burma', ['wellFormed']],
|
|
209
|
+
['English as spoken in Myanmar', ['preferred']]
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
description: 'any prefix for variant with no registered prefix',
|
|
214
|
+
from: 'en-alalc97',
|
|
215
|
+
expected: [['en-alalc97', allTestKeys]],
|
|
216
|
+
expectedDescription: [['English (ALA-LC Romanization, 1997 edition)', ['wellFormed']]]
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
description: 'strictly valid with two variants',
|
|
220
|
+
from: 'SL-Rozaj-Lipaw',
|
|
221
|
+
expected: [
|
|
222
|
+
['SL-Rozaj-Lipaw', allNonCanonicalTestKeys],
|
|
223
|
+
['sl-rozaj-lipaw', allCanonicalTestKeys]
|
|
224
|
+
],
|
|
225
|
+
expectedDescription: [['Slovenian (Resian) (The Lipovaz dialect of Resian)', ['wellFormed']]]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
description: 'strictly valid with multiple variants',
|
|
229
|
+
from: 'SL-Rozaj-biske-1994',
|
|
230
|
+
expected: [
|
|
231
|
+
['SL-Rozaj-biske-1994', allNonCanonicalTestKeys],
|
|
232
|
+
['sl-rozaj-biske-1994', allCanonicalTestKeys]
|
|
233
|
+
],
|
|
234
|
+
expectedDescription: [
|
|
235
|
+
[
|
|
236
|
+
'Slovenian (Resian) (The San Giorgio dialect of Resian) (Standardized Resian orthography)',
|
|
237
|
+
['wellFormed']
|
|
238
|
+
]
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
description: 'not strictly valid with multiple variants',
|
|
243
|
+
from: 'SL-Rozaj-1996',
|
|
244
|
+
expected: [
|
|
245
|
+
['SL-Rozaj-1996', ['default', 'wellFormed', 'valid']],
|
|
246
|
+
['sl-rozaj-1996', ['wellFormedCanonical', 'validCanonical', 'preferred']],
|
|
247
|
+
[/invalid prefix/i, ['strictlyValid', 'strictlyValidCanonical', 'strictlyValidPreferred']]
|
|
248
|
+
],
|
|
249
|
+
expectedDescription: [['Slovenian (Resian) (German orthography of 1996)', ['wellFormed']]]
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
description: 'invalid variant',
|
|
253
|
+
from: 'ca-ES-xyzzy',
|
|
254
|
+
expected: [
|
|
255
|
+
['ca-ES-xyzzy', ['default', 'wellFormed', 'wellFormedCanonical']],
|
|
256
|
+
[/invalid variant/i, allValidatingKeys]
|
|
257
|
+
],
|
|
258
|
+
expectedDescription: [['Catalan as spoken in Spain (xyzzy)', ['wellFormed']]]
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
description: 'invalid duplicate variant',
|
|
262
|
+
from: 'ca-valencia-valencia',
|
|
263
|
+
expected: [
|
|
264
|
+
['ca-valencia-valencia', ['default', 'wellFormed', 'wellFormedCanonical']],
|
|
265
|
+
[/duplicate variant/i, allValidatingKeys]
|
|
266
|
+
],
|
|
267
|
+
expectedDescription: [['Catalan (Valencian) (Valencian)', ['wellFormed']]]
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
description: 'valid extensions',
|
|
271
|
+
from: 'en-us-u-en-US-t-MT',
|
|
272
|
+
expected: [
|
|
273
|
+
['en-us-u-en-US-t-MT', allNonCanonicalTestKeys],
|
|
274
|
+
['en-US-u-en-US-t-mt', allCanonicalTestKeys]
|
|
275
|
+
],
|
|
276
|
+
expectedDescription: [
|
|
277
|
+
[
|
|
278
|
+
'English as spoken in United States (Unicode Locale "en-US") (Specifying Transformed Content "MT")',
|
|
279
|
+
['wellFormed']
|
|
280
|
+
]
|
|
281
|
+
]
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
description: 'invalid extension',
|
|
285
|
+
from: 'es-us-a-extend',
|
|
286
|
+
expected: [
|
|
287
|
+
['es-us-a-extend', ['default', 'wellFormed']],
|
|
288
|
+
['es-US-a-extend', ['wellFormedCanonical']],
|
|
289
|
+
[/invalid.*extension/i, allValidatingKeys]
|
|
290
|
+
],
|
|
291
|
+
expectedDescription: [['Spanish as spoken in United States (-a "extend")', ['wellFormed']]]
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
description: 'duplicate extension',
|
|
295
|
+
from: 'es-us-u-US-u-GB',
|
|
296
|
+
expected: [
|
|
297
|
+
['es-us-u-US-u-GB', ['default', 'wellFormed']],
|
|
298
|
+
['es-US-u-us-u-gb', ['wellFormedCanonical']],
|
|
299
|
+
[/duplicate.*extension/i, allValidatingKeys]
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
description: 'valid private-use subtag',
|
|
304
|
+
from: 'en-x-Pig-Latin',
|
|
305
|
+
expected: [
|
|
306
|
+
['en-x-Pig-Latin', allNonCanonicalTestKeys],
|
|
307
|
+
['en-x-pig-latin', allCanonicalTestKeys]
|
|
308
|
+
],
|
|
309
|
+
expectedDescription: [
|
|
310
|
+
['English (-x "Pig-Latin")', ['wellFormed']],
|
|
311
|
+
['English (-x "pig-latin")', ['preferred']]
|
|
312
|
+
]
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
description: 'valid extension and private use subtag',
|
|
316
|
+
from: 'en-US-u-us-x-test',
|
|
317
|
+
expected: [['en-US-u-us-x-test', allTestKeys]],
|
|
318
|
+
expectedDescription: [
|
|
319
|
+
['English as spoken in United States (Unicode Locale "us") (-x "test")', ['wellFormed']]
|
|
320
|
+
]
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
description: 'valid grandfathered tag with no preferredValue',
|
|
324
|
+
from: 'i-Mingo',
|
|
325
|
+
expected: [
|
|
326
|
+
['i-Mingo', allNonCanonicalTestKeys],
|
|
327
|
+
['i-mingo', allCanonicalTestKeys]
|
|
328
|
+
],
|
|
329
|
+
expectedDescription: [
|
|
330
|
+
['i-Mingo (grandfathered)', ['wellFormed']],
|
|
331
|
+
['i-mingo (grandfathered)', ['preferred']]
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
description: 'valid grandfathered tag with preferredValue',
|
|
336
|
+
from: 'art-lojban',
|
|
337
|
+
expected: [
|
|
338
|
+
['art-lojban', [...allNonCanonicalTestKeys, ...allNonPreferredCanonicalKeys]],
|
|
339
|
+
['jbo', allPreferredKeys]
|
|
340
|
+
],
|
|
341
|
+
expectedDescription: [
|
|
342
|
+
['art-lojban (grandfathered)', ['wellFormed']],
|
|
343
|
+
['Lojban', ['preferred']]
|
|
344
|
+
]
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
description: 'valid grandfathered tag with complex preferred value',
|
|
348
|
+
from: 'en-gb-oed',
|
|
349
|
+
expected: [
|
|
350
|
+
['en-gb-oed', allNonCanonicalTestKeys],
|
|
351
|
+
['en-GB-oed', allNonPreferredCanonicalKeys],
|
|
352
|
+
['en-GB-oxendict', allPreferredKeys]
|
|
353
|
+
],
|
|
354
|
+
expectedDescription: [
|
|
355
|
+
['en-gb-oed (grandfathered)', ['wellFormed']],
|
|
356
|
+
['English as spoken in United Kingdom (Oxford English Dictionary spelling)', ['preferred']]
|
|
357
|
+
]
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
description: 'valid redundant tag with no preferredValue',
|
|
361
|
+
from: 'mn-Mong',
|
|
362
|
+
expected: [['mn-Mong', allTestKeys]],
|
|
363
|
+
expectedDescription: [['Mongolian in Mongolian script', allTestKeys]]
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
description: 'valid redundant tag with preferred value',
|
|
367
|
+
from: 'sgn-BR',
|
|
368
|
+
expected: [
|
|
369
|
+
['sgn-BR', [...allNonCanonicalTestKeys, ...allNonPreferredCanonicalKeys]],
|
|
370
|
+
['bzs', allPreferredKeys]
|
|
371
|
+
],
|
|
372
|
+
expectedDescription: [
|
|
373
|
+
['Sign languages as spoken in Brazil', ['wellFormed']],
|
|
374
|
+
['Brazilian Sign Language', ['preferred']]
|
|
375
|
+
]
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
description: 'invalid private tag',
|
|
379
|
+
from: 'x-thing-x-other-thing-x-last-thing',
|
|
380
|
+
expected: [[/malformed private-use/i, allTestKeys]]
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
description: 'completely private tag with multiple tags',
|
|
384
|
+
from: 'x-some-bunch-of-things',
|
|
385
|
+
expected: [
|
|
386
|
+
['x-some-bunch-of-things', allNonCanonicalTestKeys],
|
|
387
|
+
['x-some-bunch-OF-things', allCanonicalTestKeys]
|
|
388
|
+
],
|
|
389
|
+
expectedDescription: [
|
|
390
|
+
['(-x "some-bunch-of-things")', ['wellFormed']],
|
|
391
|
+
['(-x "some-bunch-OF-things")', ['preferred']]
|
|
392
|
+
]
|
|
393
|
+
}
|
|
394
|
+
];
|
|
395
|
+
const subtagsTestCaseInit = [
|
|
396
|
+
{
|
|
397
|
+
description: 'valid non-canonical tag with suppressed script',
|
|
398
|
+
from: {
|
|
399
|
+
primaryLanguage: 'en',
|
|
400
|
+
script: 'latn',
|
|
401
|
+
region: 'us',
|
|
402
|
+
privateUse: ['Non', 'Canon']
|
|
403
|
+
},
|
|
404
|
+
expected: [
|
|
405
|
+
['en-latn-us-x-Non-Canon', ['default', 'wellFormed', 'valid', 'strictlyValid']],
|
|
406
|
+
['en-Latn-US-x-non-canon', ['wellFormedCanonical', 'validCanonical', 'strictlyValidCanonical']],
|
|
407
|
+
['en-US-x-non-canon', ['preferred', 'strictlyValidPreferred']]
|
|
408
|
+
]
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
description: 'missing primary language',
|
|
412
|
+
from: {
|
|
413
|
+
extlangs: ['cmn', 'yue']
|
|
414
|
+
},
|
|
415
|
+
expected: [[/missing primary language/i, allTestKeys]]
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
// the grammar allows for up to three extlang tags but the specification reserves
|
|
419
|
+
// and forbids them, so two tags only fails for validating forms.
|
|
420
|
+
description: 'multiple extlang tags',
|
|
421
|
+
from: {
|
|
422
|
+
primaryLanguage: 'zh',
|
|
423
|
+
extlangs: ['cmn', 'yue']
|
|
424
|
+
},
|
|
425
|
+
expected: [
|
|
426
|
+
['zh-cmn-yue', ['default', 'wellFormed', 'wellFormedCanonical']],
|
|
427
|
+
[/multiple extlang/, allValidatingKeys]
|
|
428
|
+
]
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
// the grammar forbids > 3 extlang tags so this fails for all forms
|
|
432
|
+
description: 'too many extlang tags',
|
|
433
|
+
from: {
|
|
434
|
+
primaryLanguage: 'zh',
|
|
435
|
+
extlangs: ['cmn', 'yue', 'cdo', 'cjy']
|
|
436
|
+
},
|
|
437
|
+
expected: [[/too many extlang/, allTestKeys]]
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
description: 'invalid script tag',
|
|
441
|
+
from: {
|
|
442
|
+
primaryLanguage: 'en',
|
|
443
|
+
script: 'Xyzy'
|
|
444
|
+
},
|
|
445
|
+
expected: [
|
|
446
|
+
['en-Xyzy', ['default', 'preferred', 'wellFormed', 'wellFormedCanonical']],
|
|
447
|
+
[/invalid script/i, allValidatingKeys]
|
|
448
|
+
]
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
description: 'duplicate variant tags',
|
|
452
|
+
from: {
|
|
453
|
+
primaryLanguage: 'ca',
|
|
454
|
+
variants: ['valencia', 'Valencia']
|
|
455
|
+
},
|
|
456
|
+
expected: [
|
|
457
|
+
['ca-valencia-Valencia', ['default', 'wellFormed']],
|
|
458
|
+
['ca-valencia-valencia', ['wellFormedCanonical']],
|
|
459
|
+
[/duplicate variant/, allValidatingKeys]
|
|
460
|
+
]
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
description: 'invalid grandfathered tag',
|
|
464
|
+
from: { grandfathered: 'i-dothraki' },
|
|
465
|
+
expected: [
|
|
466
|
+
['i-dothraki', ['default', 'wellFormed', 'wellFormedCanonical']],
|
|
467
|
+
[/invalid grandfathered/i, [...allValidatingKeys]]
|
|
468
|
+
]
|
|
469
|
+
}
|
|
470
|
+
];
|
|
471
|
+
// eslint-disable-next-line @rushstack/typedef-var
|
|
472
|
+
export const tagTestCases = testCaseInit.map(GenericLanguageTagTest.mapInitToTestCases);
|
|
473
|
+
// eslint-disable-next-line @rushstack/typedef-var
|
|
474
|
+
export const subtagsTestCases = subtagsTestCaseInit.map(GenericLanguageTagTest.mapInitToTestCases);
|
|
475
|
+
//# sourceMappingURL=commonTestCases.js.map
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2022 Erik Fortune
|
|
3
|
+
*
|
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
* furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
* copies or substantial portions of the Software.
|
|
13
|
+
*
|
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
* SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
import '@fgv/ts-utils-jest';
|
|
23
|
+
export const allTestKeys = [
|
|
24
|
+
'default',
|
|
25
|
+
'wellFormed',
|
|
26
|
+
'wellFormedCanonical',
|
|
27
|
+
'valid',
|
|
28
|
+
'validCanonical',
|
|
29
|
+
'preferred',
|
|
30
|
+
'strictlyValid',
|
|
31
|
+
'strictlyValidCanonical',
|
|
32
|
+
'strictlyValidPreferred'
|
|
33
|
+
];
|
|
34
|
+
export const allNonCanonicalTestKeys = ['default', 'wellFormed', 'valid', 'strictlyValid'];
|
|
35
|
+
export const allCanonicalTestKeys = [
|
|
36
|
+
'wellFormedCanonical',
|
|
37
|
+
'validCanonical',
|
|
38
|
+
'preferred',
|
|
39
|
+
'strictlyValidCanonical',
|
|
40
|
+
'strictlyValidPreferred'
|
|
41
|
+
];
|
|
42
|
+
export const allNonPreferredCanonicalKeys = [
|
|
43
|
+
'wellFormedCanonical',
|
|
44
|
+
'validCanonical',
|
|
45
|
+
'strictlyValidCanonical'
|
|
46
|
+
];
|
|
47
|
+
export const allPreferredKeys = ['preferred', 'strictlyValidPreferred'];
|
|
48
|
+
export const allValidatingKeys = [
|
|
49
|
+
'valid',
|
|
50
|
+
'validCanonical',
|
|
51
|
+
'strictlyValid',
|
|
52
|
+
'strictlyValidCanonical',
|
|
53
|
+
'strictlyValidPreferred',
|
|
54
|
+
'preferred'
|
|
55
|
+
];
|
|
56
|
+
export class GenericLanguageTagTest {
|
|
57
|
+
constructor(init) {
|
|
58
|
+
this.description = init.description;
|
|
59
|
+
this.from = init.from;
|
|
60
|
+
this.expected = {};
|
|
61
|
+
for (const value of init.expected) {
|
|
62
|
+
for (const key of value[1]) {
|
|
63
|
+
this.expected[key] = value[0];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (init.expectedDescription) {
|
|
67
|
+
this.expectedDescription = {};
|
|
68
|
+
for (const value of init.expectedDescription) {
|
|
69
|
+
for (const key of value[1]) {
|
|
70
|
+
this.expectedDescription[key] = value[0];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
this.expectedDescription = undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
static mapInitToTestCases(init) {
|
|
79
|
+
return new GenericLanguageTagTest(init);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const optionsByKey = {
|
|
83
|
+
default: undefined,
|
|
84
|
+
wellFormed: { validity: 'well-formed', normalization: 'none' },
|
|
85
|
+
wellFormedCanonical: { validity: 'well-formed', normalization: 'canonical' },
|
|
86
|
+
valid: { validity: 'valid', normalization: 'none' },
|
|
87
|
+
validCanonical: { validity: 'valid', normalization: 'canonical' },
|
|
88
|
+
preferred: { validity: 'valid', normalization: 'preferred' },
|
|
89
|
+
strictlyValid: { validity: 'strictly-valid', normalization: 'none' },
|
|
90
|
+
strictlyValidCanonical: { validity: 'strictly-valid', normalization: 'canonical' },
|
|
91
|
+
strictlyValidPreferred: { validity: 'strictly-valid', normalization: 'preferred' }
|
|
92
|
+
};
|
|
93
|
+
export class TagTestCaseFactoryBase {
|
|
94
|
+
emitOne(gtc, which) {
|
|
95
|
+
const tc = this._construct(gtc, which);
|
|
96
|
+
return tc.expected ? [tc.description, tc] : undefined;
|
|
97
|
+
}
|
|
98
|
+
emit(which, all) {
|
|
99
|
+
if (Array.isArray(which)) {
|
|
100
|
+
return all.flatMap((gtc) => {
|
|
101
|
+
return which
|
|
102
|
+
.map((w) => this.emitOne(gtc, w))
|
|
103
|
+
.filter((tc) => tc !== undefined);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return (all
|
|
107
|
+
.map((gtc) => this.emitOne(gtc, which))
|
|
108
|
+
/* c8 ignore next 1 - defensive filter for test helper, array path covers same logic */
|
|
109
|
+
.filter((tc) => tc !== undefined));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export class GenericTagTestCaseFactory extends TagTestCaseFactoryBase {
|
|
113
|
+
constructor(construct) {
|
|
114
|
+
super();
|
|
115
|
+
this._construct = construct;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export class SimpleTagTestCaseBase {
|
|
119
|
+
constructor(gtc, which) {
|
|
120
|
+
var _a;
|
|
121
|
+
this.from = gtc.from;
|
|
122
|
+
this.options = optionsByKey[which];
|
|
123
|
+
const expected = gtc.expected[which];
|
|
124
|
+
this.expected = this._getExpectedValue(which, gtc, expected);
|
|
125
|
+
this.expectedDescription = (_a = gtc.expectedDescription) === null || _a === void 0 ? void 0 : _a[which];
|
|
126
|
+
const target = this._getTestTarget(which, gtc);
|
|
127
|
+
if (this.isSuccessTest) {
|
|
128
|
+
this.description = this._getSuccessTestDescription(target, gtc.from, gtc.description);
|
|
129
|
+
}
|
|
130
|
+
else if (this.isFailureTest) {
|
|
131
|
+
this.description = this._getFailureTestDescription(target, gtc.from, gtc.description);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
this.description = this._getIgnoredTestDescription(target, gtc.from, gtc.description);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
get isSuccessTest() {
|
|
138
|
+
return !this.isFailureTest && !this.isIgnoredTest;
|
|
139
|
+
}
|
|
140
|
+
get isFailureTest() {
|
|
141
|
+
return this.expected instanceof RegExp;
|
|
142
|
+
}
|
|
143
|
+
get isIgnoredTest() {
|
|
144
|
+
return this.expected === undefined;
|
|
145
|
+
}
|
|
146
|
+
_getExpectedValue(__which, __gtc, expected) {
|
|
147
|
+
return expected;
|
|
148
|
+
}
|
|
149
|
+
_getTestTarget(which, __gtc) {
|
|
150
|
+
return which;
|
|
151
|
+
}
|
|
152
|
+
_getSuccessTestDescription(testTarget, from, description) {
|
|
153
|
+
if (typeof from !== 'string') {
|
|
154
|
+
const fromDesc = JSON.stringify(from, undefined, 2);
|
|
155
|
+
return `${testTarget} succeeds for "${description}" with "${this.expected}" (${fromDesc})`;
|
|
156
|
+
}
|
|
157
|
+
return `${testTarget} succeeds for "${from}" with "${this.expected}" (${description})`;
|
|
158
|
+
}
|
|
159
|
+
_getFailureTestDescription(testTarget, from, description) {
|
|
160
|
+
if (typeof from === 'string') {
|
|
161
|
+
return `${testTarget} fails for "${from}" with "${this.expected}" (${description})`;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
const fromDesc = JSON.stringify(from, undefined, 2);
|
|
165
|
+
return `${testTarget} fails for "${description}" with "${this.expected}" (${fromDesc})`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
_getIgnoredTestDescription(testTarget, from, description) {
|
|
169
|
+
if (typeof from === 'string') {
|
|
170
|
+
return `${testTarget} "${from}" ignored due to expected value {${description}})`;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
const fromDesc = JSON.stringify(from, undefined, 2);
|
|
174
|
+
return `${testTarget} "${description}" ignored due to expected value {${fromDesc})`;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=languageTagHelpers.js.map
|