intl-list-format
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -1,4 +0,1 @@ | ||
# 1.0.0 (2019-01-15) | ||
## 1.0.1 (2019-02-07) |
1779
dist/index.js
(function () { | ||
'use strict'; | ||
'use strict'; | ||
var SUPPORTS_LIST_FORMAT = "ListFormat" in Intl; | ||
var SUPPORTS_LIST_FORMAT = "ListFormat" in Intl; | ||
/* tslint:disable:use-primitive-type no-construct no-any */ | ||
/** | ||
* The abstract operation ToObject converts argument to a value of type Object. | ||
* | ||
* https://tc39.github.io/ecma262/#sec-toobject | ||
* @param {T} argument | ||
* @returns{T extends boolean ? Boolean : T extends number ? Number : T extends string ? String : T extends symbol ? symbol : T} | ||
*/ | ||
function toObject(argument) { | ||
if (argument == null) { | ||
throw new TypeError("Argument " + argument + " cannot be converted to an Object"); | ||
} | ||
if (typeof argument === "boolean") { | ||
return new Boolean(argument); | ||
} | ||
if (typeof argument === "number") { | ||
return new Number(argument); | ||
} | ||
if (typeof argument === "string") { | ||
return new String(argument); | ||
} | ||
if (typeof argument === "symbol") { | ||
return new Object(argument); | ||
} | ||
return argument; | ||
} | ||
/** | ||
* Must represent the structurally valid (6.2.2) and canonicalized (6.2.3) BCP 47 language tag for the host environment's current locale. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-defaultlocale | ||
* @type {Locale?} | ||
*/ | ||
var _defaultLocale; | ||
/** | ||
* Sets the default locale | ||
* @param {Locale} locale | ||
*/ | ||
function setDefaultLocale(locale) { | ||
_defaultLocale = locale; | ||
} | ||
/** | ||
* The DefaultLocale abstract operation returns a String value representing the structurally valid (6.2.2) and canonicalized (6.2.3) BCP 47 language tag for the host environment's current locale. | ||
* https://tc39.github.io/ecma402/#sec-defaultlocale | ||
* @returns{Locale | undefined} | ||
*/ | ||
function getDefaultLocale() { | ||
return _defaultLocale; | ||
} | ||
/** | ||
* Retrieves the default locale if it is set, and throws otherwise | ||
* @returns{Locale} | ||
*/ | ||
function ensureDefaultLocale() { | ||
if (_defaultLocale == null) { | ||
throw new ReferenceError("Could not determine locale: No default locale has been configured"); | ||
} | ||
return _defaultLocale; | ||
} | ||
/** | ||
* A WeakMap between ListFormat instances and their internal slot members | ||
* @type {WeakMap<ListFormat, ListFormatInstanceInternals>} | ||
*/ | ||
var LIST_FORMAT_INSTANCE_INTERNAL_MAP = new WeakMap(); | ||
/** | ||
* Contains the internal static for ListFormat | ||
* @type {ListFormatStaticInternals} | ||
*/ | ||
var LIST_FORMAT_STATIC_INTERNALS = { | ||
/** | ||
* The value of the [[RelevantExtensionKeys]] internal slot is « ». | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-Intl.ListFormat-internal-slots | ||
*/ | ||
relevantExtensionKeys: [], | ||
/** | ||
* The value of the [[LocaleData]] internal slot is implementation defined within the constraints described in 9.1 | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-Intl.ListFormat-internal-slots | ||
*/ | ||
localeData: {}, | ||
/** | ||
* The value of the [[AvailableLocales]] internal slot is implementation defined within the constraints described in 9.1. | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-Intl.ListFormat-internal-slots | ||
*/ | ||
availableLocales: [] | ||
}; | ||
/** | ||
* Sets the value for a property in an internal slot for an instance of ListFormat | ||
* @param {ListFormat} instance | ||
* @param {T} property | ||
* @param {ListFormatInstanceInternals[T]} value | ||
*/ | ||
function setInternalSlot(instance, property, value) { | ||
var record = LIST_FORMAT_INSTANCE_INTERNAL_MAP.get(instance); | ||
if (record == null) { | ||
record = {}; | ||
LIST_FORMAT_INSTANCE_INTERNAL_MAP.set(instance, record); | ||
} | ||
// Update the property with the given value | ||
record[property] = value; | ||
} | ||
/** | ||
* Gets the value associated with the given property on the internal slots of the given instance of ListFormat | ||
* @param {ListFormat} instance | ||
* @param {T} property | ||
* @returns{ListFormatInstanceInternals[T]} | ||
*/ | ||
function getInternalSlot(instance, property) { | ||
var record = LIST_FORMAT_INSTANCE_INTERNAL_MAP.get(instance); | ||
if (record == null) { | ||
throw new ReferenceError("No internal slots has been allocated for the given instance of ListFormat"); | ||
} | ||
return record[property]; | ||
} | ||
/** | ||
* Returns true if the given property on the internal slots of the given instance of ListFormat exists | ||
* @param {ListFormat} instance | ||
* @param {T} property | ||
* @returns{ListFormatInstanceInternals[T]} | ||
*/ | ||
function hasInternalSlot(instance, property) { | ||
var record = LIST_FORMAT_INSTANCE_INTERNAL_MAP.get(instance); | ||
return record != null && property in record; | ||
} | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
this file except in compliance with the License. You may obtain a copy of the | ||
License at http://www.apache.org/licenses/LICENSE-2.0 | ||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
MERCHANTABLITY OR NON-INFRINGEMENT. | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
***************************************************************************** */ | ||
function __values(o) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | ||
if (m) return m.call(o); | ||
return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
} | ||
function __read(o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
} | ||
function __spread() { | ||
for (var ar = [], i = 0; i < arguments.length; i++) | ||
ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
} | ||
/** | ||
* A Regular Expression that matches Unicode extension sequences | ||
* @type {RegExp} | ||
*/ | ||
var UNICODE_EXTENSION_SEQUENCE_REGEXP = /-u(?:-[0-9a-z]{2,8})+/gi; | ||
/** | ||
* Removes all Unicode characters from the given string | ||
* @param {string} str | ||
* @returns{string} | ||
*/ | ||
function removeUnicodeExtensionSequences(str) { | ||
return str.replace(UNICODE_EXTENSION_SEQUENCE_REGEXP, ""); | ||
} | ||
/** | ||
* The BestAvailableLocale abstract operation compares the provided argument locale, | ||
* which must be a String value with a structurally valid and canonicalized BCP 47 language tag, | ||
* against the locales in availableLocales and returns either the longest non-empty prefix of locale | ||
* that is an element of availableLocales, or undefined if there is no such element. It uses the fallback | ||
* mechanism of RFC 4647, section 3.4. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-bestavailablelocale | ||
* @param {Locales} availableLocales | ||
* @param {Locale} locale | ||
* @returns{string} | ||
*/ | ||
function bestAvailableLocale(availableLocales, locale) { | ||
// Let candidate be locale. | ||
var candidate = locale; | ||
// Repeat | ||
while (true) { | ||
// If availableLocales contains an element equal to candidate, return candidate. | ||
if (availableLocales.includes(candidate)) { | ||
return candidate; | ||
} | ||
// Let pos be the character index of the last occurrence of "-" (U+002D) within candidate. | ||
var pos = candidate.lastIndexOf("-"); | ||
// If that character does not occur, return undefined. | ||
if (pos === -1) | ||
return undefined; | ||
// If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, decrease pos by 2. | ||
if (pos >= 2 && candidate.charAt(pos - 2) === "-") { | ||
pos -= 2; | ||
} | ||
// Let candidate be the substring of candidate from position 0, inclusive, to position pos, exclusive. | ||
candidate = candidate.slice(0, pos); | ||
} | ||
} | ||
/* tslint:disable:use-primitive-type no-construct no-any */ | ||
/** | ||
* The abstract operation ToObject converts argument to a value of type Object. | ||
* | ||
* https://tc39.github.io/ecma262/#sec-toobject | ||
* @param {T} argument | ||
* @returns{T extends boolean ? Boolean : T extends number ? Number : T extends string ? String : T extends symbol ? symbol : T} | ||
*/ | ||
function toObject(argument) { | ||
if (argument == null) { | ||
throw new TypeError("Argument " + argument + " cannot be converted to an Object"); | ||
} | ||
if (typeof argument === "boolean") { | ||
return new Boolean(argument); | ||
} | ||
if (typeof argument === "number") { | ||
return new Number(argument); | ||
} | ||
if (typeof argument === "string") { | ||
return new String(argument); | ||
} | ||
if (typeof argument === "symbol") { | ||
return new Object(argument); | ||
} | ||
return argument; | ||
} | ||
/** | ||
* The LookupSupportedLocales abstract operation returns the subset of the provided BCP 47 language priority list | ||
* requestedLocales for which availableLocales has a matching locale when using the BCP 47 Lookup algorithm. | ||
* Locales appear in the same order in the returned list as in requestedLocales. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-bestfitsupportedlocales | ||
* @param {Locales} availableLocales | ||
* @param {Locales} requestedLocales | ||
* @returns{Locales} | ||
*/ | ||
function lookupSupportedLocales(availableLocales, requestedLocales) { | ||
var e_1, _a; | ||
// Let subset be a new empty List. | ||
var subset = []; | ||
try { | ||
// For each element locale of requestedLocales in List order, do | ||
for (var requestedLocales_1 = __values(requestedLocales), requestedLocales_1_1 = requestedLocales_1.next(); !requestedLocales_1_1.done; requestedLocales_1_1 = requestedLocales_1.next()) { | ||
var locale = requestedLocales_1_1.value; | ||
// Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed. | ||
var noExtensionsLocale = removeUnicodeExtensionSequences(locale); | ||
// Let availableLocale be BestAvailableLocale(availableLocales, noExtensionsLocale). | ||
var availableLocale = bestAvailableLocale(availableLocales, noExtensionsLocale); | ||
// If availableLocale is not undefined, append locale to the end of subset. | ||
if (availableLocale !== undefined) { | ||
subset.push(locale); | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (requestedLocales_1_1 && !requestedLocales_1_1.done && (_a = requestedLocales_1["return"])) _a.call(requestedLocales_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
return subset; | ||
} | ||
/** | ||
* Must represent the structurally valid (6.2.2) and canonicalized (6.2.3) BCP 47 language tag for the host environment's current locale. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-defaultlocale | ||
* @type {Locale?} | ||
*/ | ||
var _defaultLocale; | ||
/** | ||
* Sets the default locale | ||
* @param {Locale} locale | ||
*/ | ||
function setDefaultLocale(locale) { | ||
_defaultLocale = locale; | ||
} | ||
/** | ||
* The DefaultLocale abstract operation returns a String value representing the structurally valid (6.2.2) and canonicalized (6.2.3) BCP 47 language tag for the host environment's current locale. | ||
* https://tc39.github.io/ecma402/#sec-defaultlocale | ||
* @returns{Locale | undefined} | ||
*/ | ||
function getDefaultLocale() { | ||
return _defaultLocale; | ||
} | ||
/** | ||
* Retrieves the default locale if it is set, and throws otherwise | ||
* @returns{Locale} | ||
*/ | ||
function ensureDefaultLocale() { | ||
if (_defaultLocale == null) { | ||
throw new ReferenceError("Could not determine locale: No default locale has been configured"); | ||
} | ||
return _defaultLocale; | ||
} | ||
/** | ||
* The BestFitSupportedLocales abstract operation returns the subset of the provided BCP 47 language priority list | ||
* requestedLocales for which availableLocales has a matching locale when using the Best Fit Matcher algorithm. | ||
* Locales appear in the same order in the returned list as in requestedLocales. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-bestfitsupportedlocales | ||
* @param {Locales} availableLocales | ||
* @param {Locales} requestedLocales | ||
* @returns{Locales} | ||
*/ | ||
function bestFitSupportedLocales(availableLocales, requestedLocales) { | ||
return lookupSupportedLocales(availableLocales, requestedLocales); | ||
} | ||
/** | ||
* The SupportedLocales abstract operation returns the subset of the provided BCP 47 language priority list | ||
* requestedLocales for which availableLocales has a matching locale. Two algorithms are available to match | ||
* the locales: the Lookup algorithm described in RFC 4647 section 3.4, and an implementation dependent | ||
* best-fit algorithm. Locales appear in the same order in the returned list as in requestedLocales. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-supportedlocales | ||
* @param {Locales} availableLocales | ||
* @param {Locales} requestedLocales | ||
* @param {SupportedLocalesOptions} [options] | ||
* @returns{Locales} | ||
*/ | ||
function supportedLocales(availableLocales, requestedLocales, options) { | ||
// If options is not undefined, then | ||
if (options !== undefined) { | ||
// Let options be ? ToObject(options). | ||
options = toObject(options); | ||
} | ||
// If options is not undefined, then Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). | ||
// Else, let matcher be "best fit". | ||
var matcher = options !== undefined && options.localeMatcher != null | ||
? options.localeMatcher | ||
: "best fit"; | ||
// If matcher is "best fit", then let supportedLocales be BestFitSupportedLocales(availableLocales, requestedLocales). | ||
// Else let supportedLocales be LookupSupportedLocales(availableLocales, requestedLocales). | ||
// Return CreateArrayFromList(supportedLocales). | ||
return matcher === "best fit" | ||
? bestFitSupportedLocales(availableLocales, requestedLocales) | ||
: lookupSupportedLocales(availableLocales, requestedLocales); | ||
} | ||
/** | ||
* The LookupMatcher abstract operation compares requestedLocales, which must be a List as returned by CanonicalizeLocaleList, | ||
* against the locales in availableLocales and determines the best available language to meet the request. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-lookupmatcher | ||
* @param {MatcherOptions} options | ||
* @returns{MatcherResult} | ||
*/ | ||
function lookupMatcher(_a) { | ||
var availableLocales = _a.availableLocales, requestedLocales = _a.requestedLocales; | ||
var e_1, _b; | ||
// Let result be a new Record. | ||
var result = {}; | ||
try { | ||
// For each element locale of requestedLocales in List order, do | ||
for (var requestedLocales_1 = __values(requestedLocales), requestedLocales_1_1 = requestedLocales_1.next(); !requestedLocales_1_1.done; requestedLocales_1_1 = requestedLocales_1.next()) { | ||
var locale = requestedLocales_1_1.value; | ||
// Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed. | ||
var noExtensionsLocale = removeUnicodeExtensionSequences(locale); | ||
// Let availableLocale be BestAvailableLocale(availableLocales, noExtensionsLocale). | ||
var availableLocale = bestAvailableLocale(availableLocales, noExtensionsLocale); | ||
// If availableLocale is not undefined, then | ||
if (availableLocale !== undefined) { | ||
// Set result.[[locale]] to availableLocale. | ||
result.locale = availableLocale; | ||
// If locale and noExtensionsLocale are not the same String value, then | ||
if (locale !== noExtensionsLocale) { | ||
// Let extension be the String value consisting of the first substring of local | ||
// that is a Unicode locale extension sequence. | ||
var extensionMatch = locale.match(UNICODE_EXTENSION_SEQUENCE_REGEXP); | ||
// Set result.[[extension]] to extension. | ||
result.extension = extensionMatch == null ? "" : extensionMatch[0]; | ||
} | ||
return result; | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (requestedLocales_1_1 && !requestedLocales_1_1.done && (_b = requestedLocales_1["return"])) _b.call(requestedLocales_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
// Let defLocale be DefaultLocale(). | ||
var defLocale = ensureDefaultLocale(); | ||
// Set result.[[locale]] to defLocale. | ||
result.locale = defLocale; | ||
// Return result. | ||
return result; | ||
} | ||
/** | ||
* The BestFitMatcher abstract operation compares requestedLocales, | ||
* which must be a List as returned by CanonicalizeLocaleList, | ||
* against the locales in availableLocales and determines the best available language to meet the request. | ||
* The algorithm is implementation dependent, but should produce results that a typical user of the requested | ||
* locales would perceive as at least as good as those produced by the LookupMatcher abstract operation. | ||
* ListFormatOptions specified through Unicode locale extension sequences must be ignored by the algorithm. | ||
* Information about such subsequences is returned separately. The abstract operation returns a record | ||
* with a [[locale]] field, whose value is the language tag of the selected locale, | ||
* which must be an element of availableLocales. | ||
* If the language tag of the request locale that led to the selected locale contained a Unicode locale extension sequence, | ||
* then the returned record also contains an [[extension]] field whose value is the first Unicode locale extension sequence | ||
* within the request locale language tag. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-bestfitmatcher | ||
* @param {MatcherOptions} options | ||
* @returns{MatcherResult} | ||
*/ | ||
function bestFitMatcher(options) { | ||
return lookupMatcher(options); | ||
} | ||
/** | ||
* A WeakMap between ListFormat instances and their internal slot members | ||
* @type {WeakMap<ListFormat, ListFormatInstanceInternals>} | ||
*/ | ||
var LIST_FORMAT_INSTANCE_INTERNAL_MAP = new WeakMap(); | ||
/** | ||
* Contains the internal static for ListFormat | ||
* @type {ListFormatStaticInternals} | ||
*/ | ||
var LIST_FORMAT_STATIC_INTERNALS = { | ||
/** | ||
* The value of the [[RelevantExtensionKeys]] internal slot is « ». | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-Intl.ListFormat-internal-slots | ||
*/ | ||
relevantExtensionKeys: [], | ||
/** | ||
* The value of the [[LocaleData]] internal slot is implementation defined within the constraints described in 9.1 | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-Intl.ListFormat-internal-slots | ||
*/ | ||
localeData: {}, | ||
/** | ||
* The value of the [[AvailableLocales]] internal slot is implementation defined within the constraints described in 9.1. | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-Intl.ListFormat-internal-slots | ||
*/ | ||
availableLocales: [] | ||
}; | ||
/** | ||
* Sets the value for a property in an internal slot for an instance of ListFormat | ||
* @param {ListFormat} instance | ||
* @param {T} property | ||
* @param {ListFormatInstanceInternals[T]} value | ||
*/ | ||
function setInternalSlot(instance, property, value) { | ||
var record = LIST_FORMAT_INSTANCE_INTERNAL_MAP.get(instance); | ||
if (record == null) { | ||
record = {}; | ||
LIST_FORMAT_INSTANCE_INTERNAL_MAP.set(instance, record); | ||
} | ||
// Update the property with the given value | ||
record[property] = value; | ||
} | ||
/** | ||
* Gets the value associated with the given property on the internal slots of the given instance of ListFormat | ||
* @param {ListFormat} instance | ||
* @param {T} property | ||
* @returns{ListFormatInstanceInternals[T]} | ||
*/ | ||
function getInternalSlot(instance, property) { | ||
var record = LIST_FORMAT_INSTANCE_INTERNAL_MAP.get(instance); | ||
if (record == null) { | ||
throw new ReferenceError("No internal slots has been allocated for the given instance of ListFormat"); | ||
} | ||
return record[property]; | ||
} | ||
/** | ||
* Returns true if the given property on the internal slots of the given instance of ListFormat exists | ||
* @param {ListFormat} instance | ||
* @param {T} property | ||
* @returns{ListFormatInstanceInternals[T]} | ||
*/ | ||
function hasInternalSlot(instance, property) { | ||
var record = LIST_FORMAT_INSTANCE_INTERNAL_MAP.get(instance); | ||
return record != null && property in record; | ||
} | ||
/** | ||
* The ResolveLocale abstract operation compares a BCP 47 language priority list | ||
* requestedLocales against the locales in availableLocales and determines the best available language to meet the request. | ||
* availableLocales, requestedLocales, and relevantExtensionKeys must be provided as List values, | ||
* options and localeData as Records. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-resolvelocale | ||
* @param {Locales} availableLocales | ||
* @param {Locales} requestedLocales | ||
* @param {ResolveLocaleOptions} options | ||
* @param {RelevantExtensionKey[]} _relevantExtensionKeys | ||
* @param {LocaleData} _localeData | ||
* @returns {ResolveLocaleResult} | ||
*/ | ||
function resolveLocale(availableLocales, requestedLocales, options, _relevantExtensionKeys, _localeData) { | ||
// Let matcher be options.[[localeMatcher]]. | ||
var matcher = options.localeMatcher; | ||
// If matcher is "lookup", then | ||
// (a) Let r be LookupMatcher(availableLocales, requestedLocales). | ||
// (b) Let r be BestFitMatcher(availableLocales, requestedLocales). | ||
var r = matcher === "lookup" | ||
? lookupMatcher({ availableLocales: availableLocales, requestedLocales: requestedLocales }) | ||
: bestFitMatcher({ availableLocales: availableLocales, requestedLocales: requestedLocales }); | ||
// Let foundLocale be r.[[locale]]. | ||
var foundLocale = r.locale; | ||
// Let result be a new Record. | ||
var result = {}; | ||
// Set result.[[dataLocale]] to foundLocale. | ||
result.dataLocale = foundLocale; | ||
// Let supportedExtension be "-u" | ||
var supportedExtension = "-u"; | ||
// For each element key of relevantExtensionKeys in List order, do | ||
// CORRECTION: According to the spec, there _are_ no relevant extension keys, so there's no point in walking through them | ||
// If the number of elements in supportedExtension is greater than 2, then | ||
if (supportedExtension.length > 2) { | ||
// Let privateIndex be Call(%StringProto_indexOf%, foundLocale, « "-x-" »). | ||
var privateIndex = String.prototype.indexOf.call(foundLocale, "-x-"); | ||
// If privateIndex = -1, then | ||
if (privateIndex === -1) { | ||
// Let foundLocale be the concatenation of foundLocale and supportedExtension. | ||
foundLocale = "" + foundLocale + supportedExtension; | ||
} | ||
// Else, | ||
else { | ||
// Let preExtension be the substring of foundLocale from position 0, inclusive, to position privateIndex, exclusive. | ||
var preExtension = foundLocale.slice(0, privateIndex); | ||
// Let postExtension be the substring of foundLocale from position privateIndex to the end of the string. | ||
var postExtension = foundLocale.slice(privateIndex); | ||
// Let foundLocale be the concatenation of preExtension, supportedExtension, and postExtension. | ||
foundLocale = "" + preExtension + supportedExtension + postExtension; | ||
} | ||
// Assert: IsStructurallyValidLanguageTag(foundLocale) is true. | ||
// Let foundLocale be CanonicalizeLanguageTag(foundLocale). | ||
// Intl.getCanonicalLocales will throw a TypeError if the locale isn't structurally valid | ||
foundLocale = Intl.getCanonicalLocales(foundLocale)[0]; | ||
} | ||
// Set result.[[locale]] to foundLocale. | ||
result.locale = foundLocale; | ||
// Return result. | ||
return result; | ||
} | ||
/** | ||
* Creates a String list from an iterable. | ||
* Algorithm: http://tc39.github.io/proposal-intl-list-format/#sec-createstringlistfromiterable | ||
* "This algorithm raises exceptions when it encounters values that are not Strings | ||
* because there is no obvious locale-aware coercion for arbitrary values." | ||
* @param {Iterable<string>} iterable | ||
* @return {string[]} | ||
*/ | ||
function stringListFromIterable(iterable) { | ||
// If iterable is undefined, then | ||
if (iterable === undefined) { | ||
// Return a new empty List. | ||
return []; | ||
} | ||
// Spread into an array | ||
var arr = __spread(iterable); | ||
// If any of the elements isn't a string, throw a TypeError | ||
if (arr.some(function (element) { return typeof element !== "string"; })) { | ||
throw new TypeError("All List items must be strings"); | ||
} | ||
return arr; | ||
} | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
this file except in compliance with the License. You may obtain a copy of the | ||
License at http://www.apache.org/licenses/LICENSE-2.0 | ||
/** | ||
* Returns true if the given item is a record | ||
* @param {T} item | ||
* @return {item is T} | ||
*/ | ||
function isRecord(item) { | ||
return Object.prototype.toString.call(item) === "[object Object]"; | ||
} | ||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
MERCHANTABLITY OR NON-INFRINGEMENT. | ||
/** | ||
* Returns true if the given item is a List | ||
* @param {T} item | ||
* @return {item is T} | ||
*/ | ||
function isList(item) { | ||
return Array.isArray(item) || isRecord(item); | ||
} | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
***************************************************************************** */ | ||
/** | ||
* The DeconstructPattern abstract operation is called with arguments pattern | ||
* (which must be a String) and placeables (which must be a Record), | ||
* and deconstructs the pattern string into a list of parts. | ||
* The placeables record is a record whose keys are placeables tokens used in the pattern string, | ||
* and values are parts records which will be used in the result List to represent the token part. | ||
* | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-deconstructpattern | ||
* @param {string} pattern | ||
* @param {Placeables} placeables | ||
* @return {ListPartition[]} | ||
*/ | ||
function deconstructPattern(pattern, placeables) { | ||
var e_1, _a; | ||
// Let result be a new empty List. | ||
var result = []; | ||
// Let beginIndex be ! Call(%StringProto_indexOf%, pattern, « "{", 0 »). | ||
var beginIndex = String.prototype.indexOf.call(pattern, "{", 0); | ||
// Let nextIndex be 0. | ||
var nextIndex = 0; | ||
// Let length be the number of code units in pattern. | ||
var length = pattern.length; | ||
// Repeat, while beginIndex is an integer index into pattern | ||
while (pattern[beginIndex] !== undefined) { | ||
// Let endIndex to ! Call(%StringProto_indexOf%, pattern, « "}", beginIndex »). | ||
var endIndex = String.prototype.indexOf.call(pattern, "}", beginIndex); | ||
// Assert: endIndex is greater than beginIndex. | ||
if (endIndex <= beginIndex) { | ||
throw new TypeError("Expected endIndex: " + endIndex + " to be greater than beginIndex: " + beginIndex); | ||
} | ||
// If beginIndex is greater than nextIndex, then | ||
if (beginIndex > nextIndex) { | ||
// Let literal be a substring of pattern from position nextIndex, inclusive, to position beginIndex, exclusive. | ||
var literal = pattern.slice(nextIndex, beginIndex); | ||
// Append a new Record { [[Type]]: "literal", [[Value]]: literal } as the last element of result | ||
result.push({ | ||
type: "literal", | ||
value: literal | ||
}); | ||
} | ||
// Let part be the substring of pattern from position beginIndex, exclusive, to position endIndex, exclusive. | ||
var part = pattern.slice(beginIndex + 1, endIndex); | ||
// Assert: placeables has a field [[<part>]]. | ||
if (placeables[Number(part)] == null) { | ||
throw new TypeError("Expected placeables to have a part for PropertyKey: " + part); | ||
} | ||
// Let subst be placeables.[[<part>]]. | ||
var subst = placeables[Number(part)]; | ||
// If Type(subst) is List, then | ||
if (isList(subst.value)) { | ||
try { | ||
// For each element s of subst in List order, do | ||
for (var _b = __values(subst.value), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var s = _c.value; | ||
// Append s as the last element of result. | ||
result.push(s); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
} | ||
// Else, | ||
else { | ||
// Append subst as the last element of result. | ||
result.push(subst); | ||
} | ||
// Set nextIndex to endIndex + 1. | ||
nextIndex = endIndex + 1; | ||
// Set beginIndex to ! Call(%StringProto_indexOf%, pattern, « "{", nextIndex »). | ||
beginIndex = String.prototype.indexOf.call(pattern, "{", nextIndex); | ||
} | ||
// If nextIndex is less than length, then | ||
if (nextIndex < length) { | ||
// Let literal be the substring of pattern from position nextIndex, inclusive, to position length, exclusive. | ||
var literal = pattern.slice(nextIndex, length); | ||
// Append a new Record { [[Type]]: "literal", [[Value]]: literal } as the last element of result. | ||
result.push({ | ||
type: "literal", | ||
value: literal | ||
}); | ||
} | ||
// Return result | ||
return result; | ||
} | ||
function __values(o) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | ||
if (m) return m.call(o); | ||
return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
} | ||
/** | ||
* The CreatePartsFromList abstract operation is called with arguments listFormat | ||
* (which must be an object initialized as a ListFormat) and list (which must be a List of String values), | ||
* and creates the corresponding list of parts according to the effective locale and the formatting options of listFormat. | ||
* Each part is a Record with two fields: [[Type]], which must be a string with values "element" or "literal", | ||
* and [[Value]] which must be a string or a number. | ||
* @param {ListFormat} listFormat | ||
* @param {string[]} list | ||
* @return {ListPartitions} | ||
*/ | ||
function createPartsFromList(listFormat, list) { | ||
var pattern; | ||
// Let size be the number of elements of list. | ||
var size = list.length; | ||
// If size is 0, then | ||
if (size === 0) { | ||
// Return a new empty List. | ||
return []; | ||
} | ||
// If size is 2, then | ||
if (size === 2) { | ||
// Let pattern be listFormat.[[TemplatePair]]. | ||
pattern = getInternalSlot(listFormat, "templatePair"); | ||
// Let first be a new Record { [[Type]]: "element", [[Value]]: list[0] }. | ||
var first = { | ||
type: "element", | ||
value: list[0] | ||
}; | ||
// Let second be a new Record { [[Type]]: "element", [[Value]]: list[1] }. | ||
var second = { | ||
type: "element", | ||
value: list[1] | ||
}; | ||
// Let placeables be a new Record { [[0]]: first, [[1]]: second }. | ||
var placeables = { | ||
0: first, | ||
1: second | ||
}; | ||
// Return DeconstructPattern(pattern, placeables). | ||
return deconstructPattern(pattern, placeables); | ||
} | ||
// Let last be a new Record { [[Type]]: "element", [[Value]]: list[size - 1] }. | ||
var last = { | ||
type: "element", | ||
value: list[size - 1] | ||
}; | ||
// Let parts be « last ». | ||
var parts = [last]; | ||
// Let i be size - 2. | ||
var i = size - 2; | ||
// Repeat, while i ≥ 0 | ||
while (i >= 0) { | ||
// If i is 0, then | ||
if (i === 0) { | ||
// Let pattern be listFormat.[[TemplateStart]]. | ||
pattern = getInternalSlot(listFormat, "templateStart"); | ||
} | ||
// Else, if i is less than size - 2, then | ||
else if (i < (size - 2)) { | ||
// Let pattern be listFormat.[[TemplateMiddle]]. | ||
pattern = getInternalSlot(listFormat, "templateMiddle"); | ||
} | ||
// Else, | ||
else { | ||
// Let pattern be listFormat.[[TemplateEnd]]. | ||
pattern = getInternalSlot(listFormat, "templateEnd"); | ||
} | ||
// Let head be a new Record { [[Type]]: "element", [[Value]]: list[i] }. | ||
var head = { | ||
type: "element", | ||
value: list[i] | ||
}; | ||
// Let tail be a new Record { [[Type]]: "element", [[Value]]: parts }. | ||
var tail = { | ||
type: "element", | ||
value: parts | ||
}; | ||
// Let placeables be a new Record { [[0]]: head, [[1]]: tail }. | ||
var placeables = { | ||
0: head, | ||
1: tail | ||
}; | ||
// Set parts to DeconstructPattern(pattern, placeables). | ||
parts = deconstructPattern(pattern, placeables); | ||
// Decrement i by 1. | ||
i--; | ||
} | ||
// Return parts. | ||
return parts; | ||
} | ||
function __read(o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
} | ||
/** | ||
* The FormatList abstract operation is called with arguments listFormat | ||
* (which must be an object initialized as a ListFormat) and list (which must be a List of String values) | ||
* | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-formatlist | ||
* @param {ListFormat} listFormat | ||
* @param {string[]} list | ||
* @returns {string} | ||
*/ | ||
function formatList(listFormat, list) { | ||
var e_1, _a; | ||
// Let parts be CreatePartsFromList(listFormat, list). | ||
var parts = createPartsFromList(listFormat, list); | ||
// Let result be an empty String. | ||
var result = ""; | ||
try { | ||
// For each part in parts, do | ||
for (var parts_1 = __values(parts), parts_1_1 = parts_1.next(); !parts_1_1.done; parts_1_1 = parts_1.next()) { | ||
var part = parts_1_1.value; | ||
// Set result to a String value produced by concatenating result and part.[[Value]]. | ||
result += part.value; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (parts_1_1 && !parts_1_1.done && (_a = parts_1["return"])) _a.call(parts_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
return result; | ||
} | ||
function __spread() { | ||
for (var ar = [], i = 0; i < arguments.length; i++) | ||
ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
} | ||
/** | ||
* The FormatListToParts abstract operation is called with arguments listFormat | ||
* (which must be an object initialized as a ListFormat) and list (which must be a List of String values) | ||
* | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-formatlisttoparts | ||
* @param {ListFormat} listFormat | ||
* @param {string[]} list | ||
* @returns {ListPartitions} | ||
*/ | ||
function formatListToParts(listFormat, list) { | ||
return createPartsFromList(listFormat, list); | ||
} | ||
/** | ||
* A Regular Expression that matches Unicode extension sequences | ||
* @type {RegExp} | ||
*/ | ||
var UNICODE_EXTENSION_SEQUENCE_REGEXP = /-u(?:-[0-9a-z]{2,8})+/gi; | ||
/** | ||
* Removes all Unicode characters from the given string | ||
* @param {string} str | ||
* @returns{string} | ||
*/ | ||
function removeUnicodeExtensionSequences(str) { | ||
return str.replace(UNICODE_EXTENSION_SEQUENCE_REGEXP, ""); | ||
} | ||
/** | ||
* The ListFormat constructor is the %ListFormat% intrinsic object and a standard built-in property of the Intl object. | ||
* Behaviour common to all service constructor properties of the Intl object is specified in 9.1. | ||
* | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-intl-listformat-constructor | ||
*/ | ||
var ListFormat = /** @class */ (function () { | ||
function ListFormat(locales, options) { | ||
var _newTarget = this.constructor; | ||
/** | ||
* The initial value of the @@toStringTag property is the string value "Intl.ListFormat". | ||
* @type {string} | ||
*/ | ||
this[Symbol.toStringTag] = "Intl.ListFormat"; | ||
// If NewTarget is undefined, throw a TypeError exception. | ||
if (_newTarget === undefined) { | ||
throw new TypeError("Constructor Intl.ListFormat requires 'new'"); | ||
} | ||
// Let requestedLocales be ? CanonicalizeLocaleList(locales). | ||
var requestedLocales = Intl.getCanonicalLocales(locales); | ||
// If options is undefined, then (a) Let options be ObjectCreate(null). | ||
// Else (b) Let options be ? ToObject(options). | ||
options = options === undefined | ||
? Object.create(null) | ||
: toObject(options); | ||
// Let opt be a new Record. | ||
var opt = {}; | ||
// Let type be GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction"). | ||
var type = options.type != null ? options.type : "conjunction"; | ||
// Set listFormat.[[Type]] to type. | ||
setInternalSlot(this, "type", type); | ||
// Let style be GetOption(options, "style", "string", « "long", "short", "narrow" », "long"). | ||
var style = options.style != null ? options.style : "long"; | ||
// Set listFormat.[[Style]] to style. | ||
setInternalSlot(this, "style", style); | ||
// Let localeData be %ListFormat%.[[LocaleData]]. | ||
var localeData = LIST_FORMAT_STATIC_INTERNALS.localeData; | ||
// Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). | ||
var matcher = options.localeMatcher != null ? options.localeMatcher : "best fit"; | ||
// Set opt.[[localeMatcher]] to matcher. | ||
opt.localeMatcher = matcher; | ||
// If style is "narrow" and type is not "unit", throw a RangeError exception. | ||
if (style === "narrow" && type !== "unit") { | ||
throw new RangeError("Style: 'narrow' requires type: 'unit'"); | ||
} | ||
// Let r be ResolveLocale(%ListFormat%.[[AvailableLocales]], requestedLocales, opt, %ListFormat%.[[RelevantExtensionKeys]], localeData). | ||
var r = resolveLocale(LIST_FORMAT_STATIC_INTERNALS.availableLocales, requestedLocales, opt, LIST_FORMAT_STATIC_INTERNALS.relevantExtensionKeys, localeData); | ||
// Let dataLocale be r.[[dataLocale]]. | ||
var dataLocale = r.dataLocale; | ||
// Let dataLocaleData be localeData.[[<dataLocale>]]. | ||
var dataLocaleData = localeData[dataLocale]; | ||
// Let dataLocaleTypes be dataLocaleData.[[<type>]]. | ||
var dataLocaleTypes = dataLocaleData.formats[type]; | ||
// Let templates be dataLocaleTypes.[[<style>]]. | ||
var templates = dataLocaleTypes[style]; | ||
// Set listFormat.[[TemplatePair]] to templates.[[Pair]]. | ||
setInternalSlot(this, "templatePair", templates.Pair); | ||
// Set listFormat.[[TemplateStart]] to templates.[[Start]]. | ||
setInternalSlot(this, "templateStart", templates.Start); | ||
// Set listFormat.[[TemplateMiddle]] to templates.[[Middle]]. | ||
setInternalSlot(this, "templateMiddle", templates.Middle); | ||
// Set listFormat.[[TemplateEnd]] to templates.[[End]]. | ||
setInternalSlot(this, "templateEnd", templates.End); | ||
// Set listFormat.[[Locale]] to r.[[locale]]. | ||
setInternalSlot(this, "locale", r.locale); | ||
// Intl.ListFormat instances have an [[InitializedListFormat]] internal slot. | ||
setInternalSlot(this, "initializedListFormat", this); | ||
} | ||
/** | ||
* Returns an array containing those of the provided locales that are supported without having to fall back to the runtime's default locale. | ||
* @param {Locale | Locales} locales | ||
* @param {SupportedLocalesOptions | undefined} options | ||
* @returns{Locales} | ||
*/ | ||
ListFormat.supportedLocalesOf = function (locales, options) { | ||
// Let availableLocales be %ListFormat%.[[AvailableLocales]]. | ||
var availableLocales = LIST_FORMAT_STATIC_INTERNALS.availableLocales; | ||
// Let requestedLocales be ? CanonicalizeLocaleList(locales). | ||
var requestedLocales = Intl.getCanonicalLocales(locales); | ||
return supportedLocales(availableLocales, requestedLocales, options); | ||
}; | ||
/** | ||
* Adds locale data to the internal slot. | ||
* This API exactly mimics that of the Intl polyfill (https://github.com/andyearnshaw/Intl.js) | ||
* @private | ||
* @internal | ||
* @param {InputLocaleDataEntry} data | ||
* @param {Locale} locale | ||
*/ | ||
ListFormat.__addLocaleData = function (_a) { | ||
var data = _a.data, locale = _a.locale; | ||
// Use the locale as the default one if none is configured | ||
var defaultLocale = getDefaultLocale(); | ||
if (defaultLocale == null) { | ||
setDefaultLocale(locale); | ||
} | ||
LIST_FORMAT_STATIC_INTERNALS.localeData[locale] = data; | ||
if (!LIST_FORMAT_STATIC_INTERNALS.availableLocales.includes(locale)) { | ||
LIST_FORMAT_STATIC_INTERNALS.availableLocales.push(locale); | ||
} | ||
}; | ||
/** | ||
* Formats the given list into a locale-sensitive string representation | ||
* @param {Iterable<string>} [list] | ||
* @returns{string} | ||
*/ | ||
ListFormat.prototype.format = function (list) { | ||
// Let lf be the this value. | ||
var lf = this; | ||
// If Type(lf) is not Object, throw a TypeError exception. | ||
if (!(lf instanceof Object)) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.format called on incompatible receiver " + this.toString()); | ||
} | ||
// If ListFormat does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. | ||
if (!hasInternalSlot(lf, "initializedListFormat")) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.format called on incompatible receiver " + this.toString()); | ||
} | ||
// Let stringList be ? StringListFromIterable(list). | ||
var stringList = stringListFromIterable(list); | ||
// Return FormatList(lf, stringList). | ||
return formatList(lf, stringList); | ||
}; | ||
/** | ||
* Formats the given list into locale-sensitive partitions | ||
* @param {Iterable<string>} [list] | ||
* @returns{ListPartitions} | ||
*/ | ||
ListFormat.prototype.formatToParts = function (list) { | ||
// Let lf be the this value. | ||
var lf = this; | ||
// If Type(lf) is not Object, throw a TypeError exception. | ||
if (!(lf instanceof Object)) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.formatToParts called on incompatible receiver " + this.toString()); | ||
} | ||
// If listFormat does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. | ||
if (!hasInternalSlot(lf, "initializedListFormat")) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.formatToParts called on incompatible receiver " + this.toString()); | ||
} | ||
// Let stringList be ? StringListFromIterable(list). | ||
var stringList = stringListFromIterable(list); | ||
// Return FormatListToParts(lf, stringList). | ||
return formatListToParts(lf, stringList); | ||
}; | ||
/** | ||
* This method provides access to the locale and options computed during initialization of the object. | ||
* @returns {ResolvedListFormatOptions} | ||
*/ | ||
ListFormat.prototype.resolvedOptions = function () { | ||
// Let lf be the this value. | ||
var lf = this; | ||
// If Type(lf) is not Object, throw a TypeError exception. | ||
if (!(lf instanceof Object)) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.resolvedOptions called on incompatible receiver " + this.toString()); | ||
} | ||
// If listFormat does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. | ||
if (!hasInternalSlot(lf, "initializedListFormat")) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.resolvedOptions called on incompatible receiver " + this.toString()); | ||
} | ||
var locale = getInternalSlot(this, "locale"); | ||
var style = getInternalSlot(this, "style"); | ||
var type = getInternalSlot(this, "type"); | ||
return { | ||
locale: locale, | ||
style: style, | ||
type: type | ||
}; | ||
}; | ||
return ListFormat; | ||
}()); | ||
/** | ||
* The BestAvailableLocale abstract operation compares the provided argument locale, | ||
* which must be a String value with a structurally valid and canonicalized BCP 47 language tag, | ||
* against the locales in availableLocales and returns either the longest non-empty prefix of locale | ||
* that is an element of availableLocales, or undefined if there is no such element. It uses the fallback | ||
* mechanism of RFC 4647, section 3.4. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-bestavailablelocale | ||
* @param {Locales} availableLocales | ||
* @param {Locale} locale | ||
* @returns{string} | ||
*/ | ||
function bestAvailableLocale(availableLocales, locale) { | ||
// Let candidate be locale. | ||
var candidate = locale; | ||
// Repeat | ||
while (true) { | ||
// If availableLocales contains an element equal to candidate, return candidate. | ||
if (availableLocales.includes(candidate)) { | ||
return candidate; | ||
} | ||
// Let pos be the character index of the last occurrence of "-" (U+002D) within candidate. | ||
var pos = candidate.lastIndexOf("-"); | ||
// If that character does not occur, return undefined. | ||
if (pos === -1) | ||
return undefined; | ||
// If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, decrease pos by 2. | ||
if (pos >= 2 && candidate.charAt(pos - 2) === "-") { | ||
pos -= 2; | ||
} | ||
// Let candidate be the substring of candidate from position 0, inclusive, to position pos, exclusive. | ||
candidate = candidate.slice(0, pos); | ||
} | ||
} | ||
/** | ||
* Patches Intl with Intl.ListFormat | ||
*/ | ||
function patch() { | ||
if (typeof Intl === "undefined") { | ||
throw new TypeError("Could not define Intl.ListFormat: Expected 'Intl' to exist. Remember to include polyfill for Intl.getCanonicalLocales before applying this polyfill"); | ||
} | ||
Intl.ListFormat = ListFormat; | ||
} | ||
/** | ||
* The LookupSupportedLocales abstract operation returns the subset of the provided BCP 47 language priority list | ||
* requestedLocales for which availableLocales has a matching locale when using the BCP 47 Lookup algorithm. | ||
* Locales appear in the same order in the returned list as in requestedLocales. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-bestfitsupportedlocales | ||
* @param {Locales} availableLocales | ||
* @param {Locales} requestedLocales | ||
* @returns{Locales} | ||
*/ | ||
function lookupSupportedLocales(availableLocales, requestedLocales) { | ||
var e_1, _a; | ||
// Let subset be a new empty List. | ||
var subset = []; | ||
try { | ||
// For each element locale of requestedLocales in List order, do | ||
for (var requestedLocales_1 = __values(requestedLocales), requestedLocales_1_1 = requestedLocales_1.next(); !requestedLocales_1_1.done; requestedLocales_1_1 = requestedLocales_1.next()) { | ||
var locale = requestedLocales_1_1.value; | ||
// Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed. | ||
var noExtensionsLocale = removeUnicodeExtensionSequences(locale); | ||
// Let availableLocale be BestAvailableLocale(availableLocales, noExtensionsLocale). | ||
var availableLocale = bestAvailableLocale(availableLocales, noExtensionsLocale); | ||
// If availableLocale is not undefined, append locale to the end of subset. | ||
if (availableLocale !== undefined) { | ||
subset.push(locale); | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (requestedLocales_1_1 && !requestedLocales_1_1.done && (_a = requestedLocales_1["return"])) _a.call(requestedLocales_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
return subset; | ||
} | ||
if (!SUPPORTS_LIST_FORMAT) { | ||
patch(); | ||
} | ||
/** | ||
* The BestFitSupportedLocales abstract operation returns the subset of the provided BCP 47 language priority list | ||
* requestedLocales for which availableLocales has a matching locale when using the Best Fit Matcher algorithm. | ||
* Locales appear in the same order in the returned list as in requestedLocales. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-bestfitsupportedlocales | ||
* @param {Locales} availableLocales | ||
* @param {Locales} requestedLocales | ||
* @returns{Locales} | ||
*/ | ||
function bestFitSupportedLocales(availableLocales, requestedLocales) { | ||
return lookupSupportedLocales(availableLocales, requestedLocales); | ||
} | ||
/** | ||
* The SupportedLocales abstract operation returns the subset of the provided BCP 47 language priority list | ||
* requestedLocales for which availableLocales has a matching locale. Two algorithms are available to match | ||
* the locales: the Lookup algorithm described in RFC 4647 section 3.4, and an implementation dependent | ||
* best-fit algorithm. Locales appear in the same order in the returned list as in requestedLocales. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-supportedlocales | ||
* @param {Locales} availableLocales | ||
* @param {Locales} requestedLocales | ||
* @param {SupportedLocalesOptions} [options] | ||
* @returns{Locales} | ||
*/ | ||
function supportedLocales(availableLocales, requestedLocales, options) { | ||
// If options is not undefined, then | ||
if (options !== undefined) { | ||
// Let options be ? ToObject(options). | ||
options = toObject(options); | ||
} | ||
// If options is not undefined, then Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). | ||
// Else, let matcher be "best fit". | ||
var matcher = options !== undefined && options.localeMatcher != null | ||
? options.localeMatcher | ||
: "best fit"; | ||
// If matcher is "best fit", then let supportedLocales be BestFitSupportedLocales(availableLocales, requestedLocales). | ||
// Else let supportedLocales be LookupSupportedLocales(availableLocales, requestedLocales). | ||
// Return CreateArrayFromList(supportedLocales). | ||
return matcher === "best fit" | ||
? bestFitSupportedLocales(availableLocales, requestedLocales) | ||
: lookupSupportedLocales(availableLocales, requestedLocales); | ||
} | ||
/** | ||
* The LookupMatcher abstract operation compares requestedLocales, which must be a List as returned by CanonicalizeLocaleList, | ||
* against the locales in availableLocales and determines the best available language to meet the request. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-lookupmatcher | ||
* @param {MatcherOptions} options | ||
* @returns{MatcherResult} | ||
*/ | ||
function lookupMatcher(_a) { | ||
var availableLocales = _a.availableLocales, requestedLocales = _a.requestedLocales; | ||
var e_1, _b; | ||
// Let result be a new Record. | ||
var result = {}; | ||
try { | ||
// For each element locale of requestedLocales in List order, do | ||
for (var requestedLocales_1 = __values(requestedLocales), requestedLocales_1_1 = requestedLocales_1.next(); !requestedLocales_1_1.done; requestedLocales_1_1 = requestedLocales_1.next()) { | ||
var locale = requestedLocales_1_1.value; | ||
// Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed. | ||
var noExtensionsLocale = removeUnicodeExtensionSequences(locale); | ||
// Let availableLocale be BestAvailableLocale(availableLocales, noExtensionsLocale). | ||
var availableLocale = bestAvailableLocale(availableLocales, noExtensionsLocale); | ||
// If availableLocale is not undefined, then | ||
if (availableLocale !== undefined) { | ||
// Set result.[[locale]] to availableLocale. | ||
result.locale = availableLocale; | ||
// If locale and noExtensionsLocale are not the same String value, then | ||
if (locale !== noExtensionsLocale) { | ||
// Let extension be the String value consisting of the first substring of local | ||
// that is a Unicode locale extension sequence. | ||
var extensionMatch = locale.match(UNICODE_EXTENSION_SEQUENCE_REGEXP); | ||
// Set result.[[extension]] to extension. | ||
result.extension = extensionMatch == null ? "" : extensionMatch[0]; | ||
} | ||
return result; | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (requestedLocales_1_1 && !requestedLocales_1_1.done && (_b = requestedLocales_1["return"])) _b.call(requestedLocales_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
// Let defLocale be DefaultLocale(). | ||
var defLocale = ensureDefaultLocale(); | ||
// Set result.[[locale]] to defLocale. | ||
result.locale = defLocale; | ||
// Return result. | ||
return result; | ||
} | ||
/** | ||
* The BestFitMatcher abstract operation compares requestedLocales, | ||
* which must be a List as returned by CanonicalizeLocaleList, | ||
* against the locales in availableLocales and determines the best available language to meet the request. | ||
* The algorithm is implementation dependent, but should produce results that a typical user of the requested | ||
* locales would perceive as at least as good as those produced by the LookupMatcher abstract operation. | ||
* ListFormatOptions specified through Unicode locale extension sequences must be ignored by the algorithm. | ||
* Information about such subsequences is returned separately. The abstract operation returns a record | ||
* with a [[locale]] field, whose value is the language tag of the selected locale, | ||
* which must be an element of availableLocales. | ||
* If the language tag of the request locale that led to the selected locale contained a Unicode locale extension sequence, | ||
* then the returned record also contains an [[extension]] field whose value is the first Unicode locale extension sequence | ||
* within the request locale language tag. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-bestfitmatcher | ||
* @param {MatcherOptions} options | ||
* @returns{MatcherResult} | ||
*/ | ||
function bestFitMatcher(options) { | ||
return lookupMatcher(options); | ||
} | ||
/** | ||
* The ResolveLocale abstract operation compares a BCP 47 language priority list | ||
* requestedLocales against the locales in availableLocales and determines the best available language to meet the request. | ||
* availableLocales, requestedLocales, and relevantExtensionKeys must be provided as List values, | ||
* options and localeData as Records. | ||
* | ||
* https://tc39.github.io/ecma402/#sec-resolvelocale | ||
* @param {Locales} availableLocales | ||
* @param {Locales} requestedLocales | ||
* @param {ResolveLocaleOptions} options | ||
* @param {RelevantExtensionKey[]} _relevantExtensionKeys | ||
* @param {LocaleData} _localeData | ||
* @returns {ResolveLocaleResult} | ||
*/ | ||
function resolveLocale(availableLocales, requestedLocales, options, _relevantExtensionKeys, _localeData) { | ||
// Let matcher be options.[[localeMatcher]]. | ||
var matcher = options.localeMatcher; | ||
// If matcher is "lookup", then | ||
// (a) Let r be LookupMatcher(availableLocales, requestedLocales). | ||
// (b) Let r be BestFitMatcher(availableLocales, requestedLocales). | ||
var r = matcher === "lookup" | ||
? lookupMatcher({ availableLocales: availableLocales, requestedLocales: requestedLocales }) | ||
: bestFitMatcher({ availableLocales: availableLocales, requestedLocales: requestedLocales }); | ||
// Let foundLocale be r.[[locale]]. | ||
var foundLocale = r.locale; | ||
// Let result be a new Record. | ||
var result = {}; | ||
// Set result.[[dataLocale]] to foundLocale. | ||
result.dataLocale = foundLocale; | ||
// Let supportedExtension be "-u" | ||
var supportedExtension = "-u"; | ||
// For each element key of relevantExtensionKeys in List order, do | ||
// CORRECTION: According to the spec, there _are_ no relevant extension keys, so there's no point in walking through them | ||
// If the number of elements in supportedExtension is greater than 2, then | ||
if (supportedExtension.length > 2) { | ||
// Let privateIndex be Call(%StringProto_indexOf%, foundLocale, « "-x-" »). | ||
var privateIndex = String.prototype.indexOf.call(foundLocale, "-x-"); | ||
// If privateIndex = -1, then | ||
if (privateIndex === -1) { | ||
// Let foundLocale be the concatenation of foundLocale and supportedExtension. | ||
foundLocale = "" + foundLocale + supportedExtension; | ||
} | ||
// Else, | ||
else { | ||
// Let preExtension be the substring of foundLocale from position 0, inclusive, to position privateIndex, exclusive. | ||
var preExtension = foundLocale.slice(0, privateIndex); | ||
// Let postExtension be the substring of foundLocale from position privateIndex to the end of the string. | ||
var postExtension = foundLocale.slice(privateIndex); | ||
// Let foundLocale be the concatenation of preExtension, supportedExtension, and postExtension. | ||
foundLocale = "" + preExtension + supportedExtension + postExtension; | ||
} | ||
// Assert: IsStructurallyValidLanguageTag(foundLocale) is true. | ||
// Let foundLocale be CanonicalizeLanguageTag(foundLocale). | ||
// Intl.getCanonicalLocales will throw a TypeError if the locale isn't structurally valid | ||
foundLocale = Intl.getCanonicalLocales(foundLocale)[0]; | ||
} | ||
// Set result.[[locale]] to foundLocale. | ||
result.locale = foundLocale; | ||
// Return result. | ||
return result; | ||
} | ||
/** | ||
* Creates a String list from an iterable. | ||
* Algorithm: http://tc39.github.io/proposal-intl-list-format/#sec-createstringlistfromiterable | ||
* "This algorithm raises exceptions when it encounters values that are not Strings | ||
* because there is no obvious locale-aware coercion for arbitrary values." | ||
* @param {Iterable<string>} iterable | ||
* @return {string[]} | ||
*/ | ||
function stringListFromIterable(iterable) { | ||
// If iterable is undefined, then | ||
if (iterable === undefined) { | ||
// Return a new empty List. | ||
return []; | ||
} | ||
// Spread into an array | ||
var arr = __spread(iterable); | ||
// If any of the elements isn't a string, throw a TypeError | ||
if (arr.some(function (element) { return typeof element !== "string"; })) { | ||
throw new TypeError("All List items must be strings"); | ||
} | ||
return arr; | ||
} | ||
/** | ||
* Returns true if the given item is a record | ||
* @param {T} item | ||
* @return {item is T} | ||
*/ | ||
function isRecord(item) { | ||
return Object.prototype.toString.call(item) === "[object Object]"; | ||
} | ||
/** | ||
* Returns true if the given item is a List | ||
* @param {T} item | ||
* @return {item is T} | ||
*/ | ||
function isList(item) { | ||
return Array.isArray(item) || isRecord(item); | ||
} | ||
/** | ||
* The DeconstructPattern abstract operation is called with arguments pattern | ||
* (which must be a String) and placeables (which must be a Record), | ||
* and deconstructs the pattern string into a list of parts. | ||
* The placeables record is a record whose keys are placeables tokens used in the pattern string, | ||
* and values are parts records which will be used in the result List to represent the token part. | ||
* | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-deconstructpattern | ||
* @param {string} pattern | ||
* @param {Placeables} placeables | ||
* @return {ListPartition[]} | ||
*/ | ||
function deconstructPattern(pattern, placeables) { | ||
var e_1, _a; | ||
// Let result be a new empty List. | ||
var result = []; | ||
// Let beginIndex be ! Call(%StringProto_indexOf%, pattern, « "{", 0 »). | ||
var beginIndex = String.prototype.indexOf.call(pattern, "{", 0); | ||
// Let nextIndex be 0. | ||
var nextIndex = 0; | ||
// Let length be the number of code units in pattern. | ||
var length = pattern.length; | ||
// Repeat, while beginIndex is an integer index into pattern | ||
while (pattern[beginIndex] !== undefined) { | ||
// Let endIndex to ! Call(%StringProto_indexOf%, pattern, « "}", beginIndex »). | ||
var endIndex = String.prototype.indexOf.call(pattern, "}", beginIndex); | ||
// Assert: endIndex is greater than beginIndex. | ||
if (endIndex <= beginIndex) { | ||
throw new TypeError("Expected endIndex: " + endIndex + " to be greater than beginIndex: " + beginIndex); | ||
} | ||
// If beginIndex is greater than nextIndex, then | ||
if (beginIndex > nextIndex) { | ||
// Let literal be a substring of pattern from position nextIndex, inclusive, to position beginIndex, exclusive. | ||
var literal = pattern.slice(nextIndex, beginIndex); | ||
// Append a new Record { [[Type]]: "literal", [[Value]]: literal } as the last element of result | ||
result.push({ | ||
type: "literal", | ||
value: literal | ||
}); | ||
} | ||
// Let part be the substring of pattern from position beginIndex, exclusive, to position endIndex, exclusive. | ||
var part = pattern.slice(beginIndex + 1, endIndex); | ||
// Assert: placeables has a field [[<part>]]. | ||
if (placeables[Number(part)] == null) { | ||
throw new TypeError("Expected placeables to have a part for PropertyKey: " + part); | ||
} | ||
// Let subst be placeables.[[<part>]]. | ||
var subst = placeables[Number(part)]; | ||
// If Type(subst) is List, then | ||
if (isList(subst.value)) { | ||
try { | ||
// For each element s of subst in List order, do | ||
for (var _b = __values(subst.value), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var s = _c.value; | ||
// Append s as the last element of result. | ||
result.push(s); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
} | ||
// Else, | ||
else { | ||
// Append subst as the last element of result. | ||
result.push(subst); | ||
} | ||
// Set nextIndex to endIndex + 1. | ||
nextIndex = endIndex + 1; | ||
// Set beginIndex to ! Call(%StringProto_indexOf%, pattern, « "{", nextIndex »). | ||
beginIndex = String.prototype.indexOf.call(pattern, "{", nextIndex); | ||
} | ||
// If nextIndex is less than length, then | ||
if (nextIndex < length) { | ||
// Let literal be the substring of pattern from position nextIndex, inclusive, to position length, exclusive. | ||
var literal = pattern.slice(nextIndex, length); | ||
// Append a new Record { [[Type]]: "literal", [[Value]]: literal } as the last element of result. | ||
result.push({ | ||
type: "literal", | ||
value: literal | ||
}); | ||
} | ||
// Return result | ||
return result; | ||
} | ||
/** | ||
* The CreatePartsFromList abstract operation is called with arguments listFormat | ||
* (which must be an object initialized as a ListFormat) and list (which must be a List of String values), | ||
* and creates the corresponding list of parts according to the effective locale and the formatting options of listFormat. | ||
* Each part is a Record with two fields: [[Type]], which must be a string with values "element" or "literal", | ||
* and [[Value]] which must be a string or a number. | ||
* @param {ListFormat} listFormat | ||
* @param {string[]} list | ||
* @return {ListPartitions} | ||
*/ | ||
function createPartsFromList(listFormat, list) { | ||
var pattern; | ||
// Let size be the number of elements of list. | ||
var size = list.length; | ||
// If size is 0, then | ||
if (size === 0) { | ||
// Return a new empty List. | ||
return []; | ||
} | ||
// If size is 2, then | ||
if (size === 2) { | ||
// Let pattern be listFormat.[[TemplatePair]]. | ||
pattern = getInternalSlot(listFormat, "templatePair"); | ||
// Let first be a new Record { [[Type]]: "element", [[Value]]: list[0] }. | ||
var first = { | ||
type: "element", | ||
value: list[0] | ||
}; | ||
// Let second be a new Record { [[Type]]: "element", [[Value]]: list[1] }. | ||
var second = { | ||
type: "element", | ||
value: list[1] | ||
}; | ||
// Let placeables be a new Record { [[0]]: first, [[1]]: second }. | ||
var placeables = { | ||
0: first, | ||
1: second | ||
}; | ||
// Return DeconstructPattern(pattern, placeables). | ||
return deconstructPattern(pattern, placeables); | ||
} | ||
// Let last be a new Record { [[Type]]: "element", [[Value]]: list[size - 1] }. | ||
var last = { | ||
type: "element", | ||
value: list[size - 1] | ||
}; | ||
// Let parts be « last ». | ||
var parts = [last]; | ||
// Let i be size - 2. | ||
var i = size - 2; | ||
// Repeat, while i ≥ 0 | ||
while (i >= 0) { | ||
// If i is 0, then | ||
if (i === 0) { | ||
// Let pattern be listFormat.[[TemplateStart]]. | ||
pattern = getInternalSlot(listFormat, "templateStart"); | ||
} | ||
// Else, if i is less than size - 2, then | ||
else if (i < size - 2) { | ||
// Let pattern be listFormat.[[TemplateMiddle]]. | ||
pattern = getInternalSlot(listFormat, "templateMiddle"); | ||
} | ||
// Else, | ||
else { | ||
// Let pattern be listFormat.[[TemplateEnd]]. | ||
pattern = getInternalSlot(listFormat, "templateEnd"); | ||
} | ||
// Let head be a new Record { [[Type]]: "element", [[Value]]: list[i] }. | ||
var head = { | ||
type: "element", | ||
value: list[i] | ||
}; | ||
// Let tail be a new Record { [[Type]]: "element", [[Value]]: parts }. | ||
var tail = { | ||
type: "element", | ||
value: parts | ||
}; | ||
// Let placeables be a new Record { [[0]]: head, [[1]]: tail }. | ||
var placeables = { | ||
0: head, | ||
1: tail | ||
}; | ||
// Set parts to DeconstructPattern(pattern, placeables). | ||
parts = deconstructPattern(pattern, placeables); | ||
// Decrement i by 1. | ||
i--; | ||
} | ||
// Return parts. | ||
return parts; | ||
} | ||
/** | ||
* The FormatList abstract operation is called with arguments listFormat | ||
* (which must be an object initialized as a ListFormat) and list (which must be a List of String values) | ||
* | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-formatlist | ||
* @param {ListFormat} listFormat | ||
* @param {string[]} list | ||
* @returns {string} | ||
*/ | ||
function formatList(listFormat, list) { | ||
var e_1, _a; | ||
// Let parts be CreatePartsFromList(listFormat, list). | ||
var parts = createPartsFromList(listFormat, list); | ||
// Let result be an empty String. | ||
var result = ""; | ||
try { | ||
// For each part in parts, do | ||
for (var parts_1 = __values(parts), parts_1_1 = parts_1.next(); !parts_1_1.done; parts_1_1 = parts_1.next()) { | ||
var part = parts_1_1.value; | ||
// Set result to a String value produced by concatenating result and part.[[Value]]. | ||
result += part.value; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (parts_1_1 && !parts_1_1.done && (_a = parts_1["return"])) _a.call(parts_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
return result; | ||
} | ||
/** | ||
* The FormatListToParts abstract operation is called with arguments listFormat | ||
* (which must be an object initialized as a ListFormat) and list (which must be a List of String values) | ||
* | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-formatlisttoparts | ||
* @param {ListFormat} listFormat | ||
* @param {string[]} list | ||
* @returns {ListPartitions} | ||
*/ | ||
function formatListToParts(listFormat, list) { | ||
return createPartsFromList(listFormat, list); | ||
} | ||
/** | ||
* The ListFormat constructor is the %ListFormat% intrinsic object and a standard built-in property of the Intl object. | ||
* Behaviour common to all service constructor properties of the Intl object is specified in 9.1. | ||
* | ||
* http://tc39.github.io/proposal-intl-list-format/#sec-intl-listformat-constructor | ||
*/ | ||
var ListFormat = /** @class */ (function () { | ||
function ListFormat(locales, options) { | ||
var _newTarget = this.constructor; | ||
/** | ||
* The initial value of the @@toStringTag property is the string value "Intl.ListFormat". | ||
* @type {string} | ||
*/ | ||
this[Symbol.toStringTag] = "Intl.ListFormat"; | ||
// If NewTarget is undefined, throw a TypeError exception. | ||
if (_newTarget === undefined) { | ||
throw new TypeError("Constructor Intl.ListFormat requires 'new'"); | ||
} | ||
// Let requestedLocales be ? CanonicalizeLocaleList(locales). | ||
var requestedLocales = Intl.getCanonicalLocales(locales); | ||
// If options is undefined, then (a) Let options be ObjectCreate(null). | ||
// Else (b) Let options be ? ToObject(options). | ||
options = | ||
options === undefined | ||
? Object.create(null) | ||
: toObject(options); | ||
// Let opt be a new Record. | ||
var opt = {}; | ||
// Let type be GetOption(options, "type", "string", « "conjunction", "disjunction", "unit" », "conjunction"). | ||
var type = options.type != null ? options.type : "conjunction"; | ||
// Set listFormat.[[Type]] to type. | ||
setInternalSlot(this, "type", type); | ||
// Let style be GetOption(options, "style", "string", « "long", "short", "narrow" », "long"). | ||
var style = options.style != null ? options.style : "long"; | ||
// Set listFormat.[[Style]] to style. | ||
setInternalSlot(this, "style", style); | ||
// Let localeData be %ListFormat%.[[LocaleData]]. | ||
var localeData = LIST_FORMAT_STATIC_INTERNALS.localeData; | ||
// Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit"). | ||
var matcher = options.localeMatcher != null ? options.localeMatcher : "best fit"; | ||
// Set opt.[[localeMatcher]] to matcher. | ||
opt.localeMatcher = matcher; | ||
// If style is "narrow" and type is not "unit", throw a RangeError exception. | ||
if (style === "narrow" && type !== "unit") { | ||
throw new RangeError("Style: 'narrow' requires type: 'unit'"); | ||
} | ||
// Let r be ResolveLocale(%ListFormat%.[[AvailableLocales]], requestedLocales, opt, %ListFormat%.[[RelevantExtensionKeys]], localeData). | ||
var r = resolveLocale(LIST_FORMAT_STATIC_INTERNALS.availableLocales, requestedLocales, opt, LIST_FORMAT_STATIC_INTERNALS.relevantExtensionKeys, localeData); | ||
// Let dataLocale be r.[[dataLocale]]. | ||
var dataLocale = r.dataLocale; | ||
// Let dataLocaleData be localeData.[[<dataLocale>]]. | ||
var dataLocaleData = localeData[dataLocale]; | ||
// Let dataLocaleTypes be dataLocaleData.[[<type>]]. | ||
var dataLocaleTypes = dataLocaleData.formats[type]; | ||
// Let templates be dataLocaleTypes.[[<style>]]. | ||
var templates = dataLocaleTypes[style]; | ||
// Set listFormat.[[TemplatePair]] to templates.[[Pair]]. | ||
setInternalSlot(this, "templatePair", templates.Pair); | ||
// Set listFormat.[[TemplateStart]] to templates.[[Start]]. | ||
setInternalSlot(this, "templateStart", templates.Start); | ||
// Set listFormat.[[TemplateMiddle]] to templates.[[Middle]]. | ||
setInternalSlot(this, "templateMiddle", templates.Middle); | ||
// Set listFormat.[[TemplateEnd]] to templates.[[End]]. | ||
setInternalSlot(this, "templateEnd", templates.End); | ||
// Set listFormat.[[Locale]] to r.[[locale]]. | ||
setInternalSlot(this, "locale", r.locale); | ||
// Intl.ListFormat instances have an [[InitializedListFormat]] internal slot. | ||
setInternalSlot(this, "initializedListFormat", this); | ||
} | ||
/** | ||
* Returns an array containing those of the provided locales that are supported without having to fall back to the runtime's default locale. | ||
* @param {Locale | Locales} locales | ||
* @param {SupportedLocalesOptions | undefined} options | ||
* @returns{Locales} | ||
*/ | ||
ListFormat.supportedLocalesOf = function (locales, options) { | ||
// Let availableLocales be %ListFormat%.[[AvailableLocales]]. | ||
var availableLocales = LIST_FORMAT_STATIC_INTERNALS.availableLocales; | ||
// Let requestedLocales be ? CanonicalizeLocaleList(locales). | ||
var requestedLocales = Intl.getCanonicalLocales(locales); | ||
return supportedLocales(availableLocales, requestedLocales, options); | ||
}; | ||
/** | ||
* Adds locale data to the internal slot. | ||
* This API exactly mimics that of the Intl polyfill (https://github.com/andyearnshaw/Intl.js) | ||
* @private | ||
* @internal | ||
* @param {InputLocaleDataEntry} data | ||
* @param {Locale} locale | ||
*/ | ||
ListFormat.__addLocaleData = function (_a) { | ||
var data = _a.data, locale = _a.locale; | ||
// Use the locale as the default one if none is configured | ||
var defaultLocale = getDefaultLocale(); | ||
if (defaultLocale == null) { | ||
setDefaultLocale(locale); | ||
} | ||
LIST_FORMAT_STATIC_INTERNALS.localeData[locale] = data; | ||
if (!LIST_FORMAT_STATIC_INTERNALS.availableLocales.includes(locale)) { | ||
LIST_FORMAT_STATIC_INTERNALS.availableLocales.push(locale); | ||
} | ||
}; | ||
/** | ||
* Formats the given list into a locale-sensitive string representation | ||
* @param {Iterable<string>} [list] | ||
* @returns{string} | ||
*/ | ||
ListFormat.prototype.format = function (list) { | ||
// Let lf be the this value. | ||
var lf = this; | ||
// If Type(lf) is not Object, throw a TypeError exception. | ||
if (!(lf instanceof Object)) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.format called on incompatible receiver " + this.toString()); | ||
} | ||
// If ListFormat does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. | ||
if (!hasInternalSlot(lf, "initializedListFormat")) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.format called on incompatible receiver " + this.toString()); | ||
} | ||
// Let stringList be ? StringListFromIterable(list). | ||
var stringList = stringListFromIterable(list); | ||
// Return FormatList(lf, stringList). | ||
return formatList(lf, stringList); | ||
}; | ||
/** | ||
* Formats the given list into locale-sensitive partitions | ||
* @param {Iterable<string>} [list] | ||
* @returns{ListPartitions} | ||
*/ | ||
ListFormat.prototype.formatToParts = function (list) { | ||
// Let lf be the this value. | ||
var lf = this; | ||
// If Type(lf) is not Object, throw a TypeError exception. | ||
if (!(lf instanceof Object)) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.formatToParts called on incompatible receiver " + this.toString()); | ||
} | ||
// If listFormat does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. | ||
if (!hasInternalSlot(lf, "initializedListFormat")) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.formatToParts called on incompatible receiver " + this.toString()); | ||
} | ||
// Let stringList be ? StringListFromIterable(list). | ||
var stringList = stringListFromIterable(list); | ||
// Return FormatListToParts(lf, stringList). | ||
return formatListToParts(lf, stringList); | ||
}; | ||
/** | ||
* This method provides access to the locale and options computed during initialization of the object. | ||
* @returns {ResolvedListFormatOptions} | ||
*/ | ||
ListFormat.prototype.resolvedOptions = function () { | ||
// Let lf be the this value. | ||
var lf = this; | ||
// If Type(lf) is not Object, throw a TypeError exception. | ||
if (!(lf instanceof Object)) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.resolvedOptions called on incompatible receiver " + this.toString()); | ||
} | ||
// If listFormat does not have an [[InitializedListFormat]] internal slot, throw a TypeError exception. | ||
if (!hasInternalSlot(lf, "initializedListFormat")) { | ||
throw new TypeError("Method Intl.ListFormat.prototype.resolvedOptions called on incompatible receiver " + this.toString()); | ||
} | ||
var locale = getInternalSlot(this, "locale"); | ||
var style = getInternalSlot(this, "style"); | ||
var type = getInternalSlot(this, "type"); | ||
return { | ||
locale: locale, | ||
style: style, | ||
type: type | ||
}; | ||
}; | ||
return ListFormat; | ||
}()); | ||
/** | ||
* Patches Intl with Intl.ListFormat | ||
*/ | ||
function patch() { | ||
if (typeof Intl === "undefined") { | ||
throw new TypeError("Could not define Intl.ListFormat: Expected 'Intl' to exist. Remember to include polyfill for Intl.getCanonicalLocales before applying this polyfill"); | ||
} | ||
Intl.ListFormat = ListFormat; | ||
} | ||
if (!SUPPORTS_LIST_FORMAT) { | ||
patch(); | ||
} | ||
}()); | ||
//# sourceMappingURL=index.js.map |
The MIT License (MIT) | ||
Copyright © 2019 Frederik Wessberg <frederikwessberg@hotmail.com> | ||
Copyright © 2019 [Frederik Wessberg](mailto:frederikwessberg@hotmail.com) ([@FredWessberg](https://twitter.com/FredWessberg)) ([Website](https://github.com/wessberg)) | ||
@@ -21,2 +21,2 @@ Permission is hereby granted, free of charge, to any person obtaining a copy | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE | ||
SOFTWARE |
{ | ||
"name": "intl-list-format", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "A fully spec-compliant polyfill for 'Intl.ListFormat'", | ||
@@ -13,24 +13,23 @@ "repository": { | ||
"scripts": { | ||
"generate:readme": "scaffold readme", | ||
"generate:license": "scaffold license", | ||
"generate:contributing": "scaffold contributing", | ||
"generate:coc": "scaffold coc", | ||
"generate:readme": "scaffold readme --yes", | ||
"generate:license": "scaffold license --yes", | ||
"generate:contributing": "scaffold contributing --yes", | ||
"generate:coc": "scaffold coc --yes", | ||
"generate:changelog": "standard-changelog --first-release", | ||
"generate:all": "npm run generate:license & npm run generate:contributing & npm run generate:coc & npm run generate:readme & npm run generate:changelog", | ||
"generate:all": "npm run generate:license & npm run generate:contributing & npm run generate:coc & npm run generate:readme && npm run generate:changelog", | ||
"clean:dist": "rm -rf dist", | ||
"clean:compiled": "rm -rf compiled", | ||
"clean": "npm run clean:dist && npm run clean:compiled", | ||
"update": "ncu -ua && npm update && npm install", | ||
"lint": "tsc --noEmit && tslint -c tslint.json --project tsconfig.json", | ||
"prerollup": "rm -r -f dist", | ||
"rollup": "rollup -c rollup.config.js", | ||
"prepare": "NODE_ENV=production npm run rollup", | ||
"prettier": "prettier --write '{src,test,documentation}/**/*.{js,ts,json,html,xml,css,md}'", | ||
"pretest": "npm run clean:compiled && tsc --module commonjs --target es2017 --sourceMap", | ||
"test": "NODE_ENV=TEST ava --fail-fast", | ||
"posttest": "npm run clean:compiled", | ||
"prebuild": "npm run clean:dist", | ||
"build": "npm run rollup", | ||
"build_data": "cd scripts/build-data && tsc && node compiled/scripts/build-data/build-data.js && rm -rf compiled", | ||
"publish:before": "NODE_ENV=production npm run lint && npm run build_data && npm run test && NODE_ENV=production npm run prepare && npm run generate:all && git add . && (git commit -am \"Bumped version\" && git push) || true", | ||
"publish:after": "git push && npm publish", | ||
"publish:patch": "npm run publish:before && npm version patch && npm run publish:after", | ||
"publish:minor": "npm run publish:before && npm version minor && npm run publish:after", | ||
"publish:major": "npm run publish:before && npm version major && npm run publish:after" | ||
"rollup": "rollup -c rollup.config.js", | ||
"preversion": "npm run lint && npm run build_data && NODE_ENV=production npm run build", | ||
"version": "npm run generate:all && git add .", | ||
"release": "np --no-cleanup --no-yarn" | ||
}, | ||
@@ -53,18 +52,22 @@ "files": [ | ||
], | ||
"author": { | ||
"name": "Frederik Wessberg", | ||
"email": "frederikwessberg@hotmail.com", | ||
"url": "https://github.com/wessberg" | ||
}, | ||
"contributors": [ | ||
{ | ||
"name": "Frederik Wessberg", | ||
"email": "frederikwessberg@hotmail.com", | ||
"url": "https://github.com/wessberg", | ||
"imageUrl": "https://avatars2.githubusercontent.com/u/20454213?s=460&v=4", | ||
"role": "Lead Developer", | ||
"twitter": "FredWessberg" | ||
} | ||
], | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@types/find-up": "^2.1.1", | ||
"@wessberg/rollup-plugin-ts": "1.1.17", | ||
"@wessberg/scaffold": "1.0.5", | ||
"@wessberg/ts-config": "^0.0.34", | ||
"ava": "^1.1.0", | ||
"@wessberg/rollup-plugin-ts": "1.1.28", | ||
"@wessberg/scaffold": "1.0.15", | ||
"@wessberg/ts-config": "^0.0.39", | ||
"ava": "^1.2.1", | ||
"cldr": "^4.13.0", | ||
"find-up": "^3.0.0", | ||
"npm-check-updates": "^2.15.0", | ||
"rollup": "^1.1.0", | ||
"rollup": "^1.1.2", | ||
"rollup-plugin-node-resolve": "^4.0.0", | ||
@@ -75,3 +78,7 @@ "standard-changelog": "^2.0.6", | ||
"tslint": "^5.12.1", | ||
"typescript": "^3.2.2" | ||
"typescript": "^3.3.3", | ||
"prettier": "^1.16.4", | ||
"pretty-quick": "^1.10.0", | ||
"husky": "^1.3.1", | ||
"np": "^4.0.2" | ||
}, | ||
@@ -86,16 +93,9 @@ "dependencies": {}, | ||
"engines": { | ||
"node": ">=9.0.0" | ||
"node": ">=4.0.0" | ||
}, | ||
"scaffold": { | ||
"patreonUserId": "11315442", | ||
"contributorMeta": { | ||
"Frederik Wessberg": { | ||
"imageUrl": "https://avatars2.githubusercontent.com/u/20454213?s=460&v=4", | ||
"role": "Maintainer", | ||
"twitterHandle": "FredWessberg", | ||
"isCocEnforcer": true | ||
} | ||
}, | ||
"backers": [] | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "pretty-quick --staged" | ||
} | ||
} | ||
} |
119
README.md
@@ -1,14 +0,30 @@ | ||
<a href="https://npmcharts.com/compare/intl-list-format?minimal=true"><img alt="Downloads per month" src="https://img.shields.io/npm/dm/intl-list-format.svg" height="20"></img></a> | ||
<a href="https://david-dm.org/intl-list-format"><img alt="Dependencies" src="https://img.shields.io/david/intl-list-format.svg" height="20"></img></a> | ||
<a href="https://www.npmjs.com/package/intl-list-format"><img alt="NPM Version" src="https://badge.fury.io/js/intl-list-format.svg" height="20"></img></a> | ||
<a href="https://github.com/wessberg/intl-list-format/graphs/contributors"><img alt="Contributors" src="https://img.shields.io/github/contributors/wessberg%2Fintl-list-format.svg" height="20"></img></a> | ||
<a href="https://opensource.org/licenses/MIT"><img alt="MIT License" src="https://img.shields.io/badge/License-MIT-yellow.svg" height="20"></img></a> | ||
<a href="https://www.patreon.com/bePatron?u=11315442"><img alt="Support on Patreon" src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" height="20"></img></a> | ||
<!-- SHADOW_SECTION_LOGO_START --> | ||
# `intl-list-format` | ||
<div><img alt="Logo" src="https://raw.githubusercontent.com/wessberg/intl-list-format/master/documentation/asset/logo.png" height="80" /></div> | ||
<!-- SHADOW_SECTION_LOGO_END --> | ||
<!-- SHADOW_SECTION_DESCRIPTION_SHORT_START --> | ||
> A fully spec-compliant polyfill for 'Intl.ListFormat' | ||
<!-- SHADOW_SECTION_DESCRIPTION_SHORT_END --> | ||
<!-- SHADOW_SECTION_BADGES_START --> | ||
<a href="https://npmcharts.com/compare/intl-list-format?minimal=true"><img alt="Downloads per month" src="https://img.shields.io/npm/dm/intl-list-format.svg" /></a> | ||
<a href="https://david-dm.org/wessberg/intl-list-format"><img alt="Dependencies" src="https://img.shields.io/david/wessberg%2Fintl-list-format.svg" /></a> | ||
<a href="https://github.com/wessberg/intl-list-format/graphs/contributors"><img alt="Contributors" src="https://img.shields.io/github/contributors/wessberg%2Fintl-list-format.svg" /></a> | ||
<a href="https://github.com/prettier/prettier"><img alt="code style: prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square" /></a> | ||
<a href="https://opensource.org/licenses/MIT"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" /></a> | ||
<a href="https://www.patreon.com/bePatron?u=11315442"><img alt="Support on Patreon" src="https://img.shields.io/badge/patreon-donate-green.svg" /></a> | ||
<!-- SHADOW_SECTION_BADGES_END --> | ||
<!-- SHADOW_SECTION_DESCRIPTION_LONG_START --> | ||
## Description | ||
<!-- SHADOW_SECTION_DESCRIPTION_LONG_END --> | ||
This is a 1:1 implementation of the [`Intl.ListFormat`](https://github.com/tc39/proposal-intl-list-format) draft spec proposal ECMA-402, or the ECMAScript® Internationalization API Specification. | ||
@@ -19,2 +35,10 @@ | ||
It builds upon another member of the `Intl` family: `Intl.getCanonicalLocales`, so this must be polyfilled. [See this section for an overview](#dependencies--browser-support). | ||
<!-- SHADOW_SECTION_FEATURES_START --> | ||
### Features | ||
<!-- SHADOW_SECTION_FEATURES_END --> | ||
Some highlights of this polyfill include: | ||
@@ -26,4 +50,37 @@ | ||
It builds upon another member of the `Intl` family: `Intl.getCanonicalLocales`, so this must be polyfilled. [See this section for an overview](#dependencies--browser-support). | ||
<!-- SHADOW_SECTION_FEATURE_IMAGE_START --> | ||
<!-- SHADOW_SECTION_FEATURE_IMAGE_END --> | ||
<!-- SHADOW_SECTION_TOC_START --> | ||
## Table of Contents | ||
- [Description](#description) | ||
- [Features](#features) | ||
- [Table of Contents](#table-of-contents) | ||
- [Install](#install) | ||
- [NPM](#npm) | ||
- [Yarn](#yarn) | ||
- [Applying the polyfill](#applying-the-polyfill) | ||
- [Loading locale data](#loading-locale-data) | ||
- [Usage](#usage) | ||
- [Intl.ListFormat.prototype.format](#intllistformatprototypeformat) | ||
- [Intl.ListFormat.prototype.formatToParts](#intllistformatprototypeformattoparts) | ||
- [Intl.ListFormat.prototype.resolvedOptions](#intllistformatprototyperesolvedoptions) | ||
- [Intl.ListFormat.supportedLocalesOf](#intllistformatsupportedlocalesof) | ||
- [Dependencies & Browser support](#dependencies--browser-support) | ||
- [Contributing](#contributing) | ||
- [Maintainers](#maintainers) | ||
- [Backers](#backers) | ||
- [Patreon](#patreon) | ||
- [FAQ](#faq) | ||
- [What is the default locale?](#what-is-the-default-locale) | ||
- [Are there any known quirks?](#are-there-any-known-quirks) | ||
- [License](#license) | ||
<!-- SHADOW_SECTION_TOC_END --> | ||
<!-- SHADOW_SECTION_INSTALL_START --> | ||
## Install | ||
@@ -43,2 +100,4 @@ | ||
<!-- SHADOW_SECTION_INSTALL_END --> | ||
## Applying the polyfill | ||
@@ -98,4 +157,8 @@ | ||
<!-- SHADOW_SECTION_USAGE_START --> | ||
## Usage | ||
<!-- SHADOW_SECTION_USAGE_END --> | ||
The following examples are taken [directly from the original proposal](https://github.com/tc39/proposal-intl-list-format) | ||
@@ -135,3 +198,3 @@ | ||
```typescript | ||
const lf = new Intl.ListFormat("en", {type: "unit", style: "narrow"}); | ||
const lf = new Intl.ListFormat("en", { type: "unit", style: "narrow" }); | ||
@@ -163,2 +226,4 @@ lf.resolvedOptions(); | ||
<!-- SHADOW_SECTION_CONTRIBUTING_START --> | ||
## Contributing | ||
@@ -168,8 +233,32 @@ | ||
<!-- SHADOW_SECTION_CONTRIBUTING_END --> | ||
<!-- SHADOW_SECTION_MAINTAINERS_START --> | ||
## Maintainers | ||
- <a href="https://github.com/wessberg"><img alt="Frederik Wessberg" src="https://avatars2.githubusercontent.com/u/20454213?s=460&v=4" height="11"></img></a> [Frederik Wessberg](https://github.com/wessberg): _Maintainer_ | ||
| <img alt="Frederik Wessberg" src="https://avatars2.githubusercontent.com/u/20454213?s=460&v=4" height="70" /> | | ||
| --------------------------------------------------------------------------------------------------------------------------------- | | ||
| [Frederik Wessberg](mailto:frederikwessberg@hotmail.com)<br>[@FredWessberg](https://twitter.com/FredWessberg)<br>_Lead Developer_ | | ||
## FAQ | ||
<!-- SHADOW_SECTION_MAINTAINERS_END --> | ||
<!-- SHADOW_SECTION_BACKERS_START --> | ||
## Backers | ||
### Patreon | ||
[Become a backer](https://www.patreon.com/bePatron?u=11315442) and get your name, avatar, and Twitter handle listed here. | ||
<a href="https://www.patreon.com/bePatron?u=11315442"><img alt="Backers on Patreon" src="https://patreon-badge.herokuapp.com/11315442.png" width="500" /></a> | ||
<!-- SHADOW_SECTION_BACKERS_END --> | ||
<!-- SHADOW_SECTION_FAQ_START --> | ||
### FAQ | ||
<!-- SHADOW_SECTION_FAQ_END --> | ||
### What is the default locale? | ||
@@ -183,8 +272,8 @@ | ||
## Backers 🏅 | ||
<!-- SHADOW_SECTION_LICENSE_START --> | ||
[Become a backer](https://www.patreon.com/bePatron?u=11315442) and get your name, logo, and link to your site listed here. | ||
## License | ||
## License 📄 | ||
MIT © [Frederik Wessberg](mailto:frederikwessberg@hotmail.com) ([@FredWessberg](https://twitter.com/FredWessberg)) ([Website](https://github.com/wessberg)) | ||
MIT © [Frederik Wessberg](https://github.com/wessberg) | ||
<!-- SHADOW_SECTION_LICENSE_END --> |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1997190
52910
272
18