Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

i18n-number

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

i18n-number - npm Package Compare versions

Comparing version 3.0.1 to 4.0.0-pre.1

test/selenium-grid-wct.conf.js

2

bower.json
{
"name": "i18n-number",
"license": "https://github.com/t2ym/i18n-format/blob/master/LICENSE.md"
"license": "BSD-2-Clause"
}

@@ -20,3 +20,2 @@ /**

@group I18nBehavior
@element i18n-number

@@ -26,310 +25,24 @@ @hero hero.svg

*/
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { polyfill } from 'wc-putty/polyfill.js';
import { html, render } from 'lit-html/lit-html.js';
var intlLibraryScript;
var intlLibraryLoadingStatus = 'initializing';
var _setupIntlPolyfillCalled = false;
var formatCache = new Map();
const formatCache = new Map();
/**
* Set up Intl polyfill if required
*/
function _setupIntlPolyfill () {
// Polyfill Intl if required
var intlLibraryUrl = this.resolveUrl('../intl/dist/Intl.min.js', this.importMeta.url);
if (window.Intl) {
if (window.IntlPolyfill && window.Intl === window.IntlPolyfill) {
intlLibraryLoadingStatus = 'loaded';
}
else {
intlLibraryLoadingStatus = 'native';
}
export class I18nNumber extends polyfill(HTMLElement) {
static get importMeta() {
return import.meta;
}
else {
intlLibraryLoadingStatus = 'loading';
intlLibraryScript = document.createElement('script');
intlLibraryScript.setAttribute('src', intlLibraryUrl);
intlLibraryScript.setAttribute('id', 'intl-js-library');
intlLibraryScript.addEventListener('load', function intlLibraryLoaded (e) {
intlLibraryLoadingStatus = 'loaded';
e.target.removeEventListener('load', intlLibraryLoaded);
return false;
});
var s = document.querySelector('script') || document.body;
s.parentNode.insertBefore(intlLibraryScript, s);
static get is() {
return 'i18n-number';
}
}
/**
* Set up polyfill locale of Intl if required
*
* @param {String} locale Target locale to polyfill
* @param {Function} callback Callback function to handle locale load
* @return {Boolean} true if supported; false if callback will be called
*/
function _setupIntlPolyfillLocale (locale, callback) {
if (!window.IntlPolyfill) {
switch (intlLibraryLoadingStatus) {
case 'loading':
/* istanbul ignore else: intlLibraryScript is always set when the status is 'loading' */
if (intlLibraryScript) {
var libraryLoadedBindThis = function (e) {
_setupIntlPolyfillLocale.call(this, locale, callback);
e.target.removeEventListener('load', libraryLoadedBindThis);
}.bind(this);
intlLibraryScript.addEventListener('load', libraryLoadedBindThis);
return false;
}
else {
console.error('Intl.js is not being loaded');
}
/* istanbul ignore next: intlLibraryScript is always set when the status is 'loading' */
break;
// impossible cases
case 'initializing':
case 'loaded':
case 'native':
default:
/* istanbul ignore next: these cases are impossible */
break;
}
static get observedAttributes() {
return [ 'lang', 'options', 'offset' ];
}
else {
if (intlLibraryLoadingStatus !== 'native') {
var supported = Intl.NumberFormat.supportedLocalesOf(locale, { localeMatcher: 'lookup' });
var script;
var intlScript;
if (supported.length === 0) {
// load the locale
var fallbackLanguages = _enumerateFallbackLanguages(locale);
locale = fallbackLanguages.shift();
script = document.querySelector('script#intl-js-locale-' + locale);
if (!script) {
script = document.createElement('script');
script.setAttribute('id', 'intl-js-locale-' + locale);
script.setAttribute('src', this.resolveUrl('../intl/locale-data/jsonp/' + locale + '.js', this.importMeta.url));
var intlLocaleLoadedBindThis = function (e) {
if (e.target === script) {
e.target.removeEventListener('load', intlLocaleLoadedBindThis);
callback.call(this, locale);
}
return false;
}.bind(this);
var intlLocaleLoadErrorBindThis = function (e) {
if (e.target === script) {
e.target.removeEventListener('error', intlLocaleLoadErrorBindThis);
script.setAttribute('loaderror','');
locale = fallbackLanguages.shift();
if (!locale) {
locale = this.DEFAULT_LANG;
}
var fallbackSupport = Intl.NumberFormat.supportedLocalesOf(locale, { localeMatcher: 'lookup'});
if (fallbackSupport.length > 0) {
callback.call(this, locale);
}
else {
_setupIntlPolyfillLocale.call(this, locale, callback);
}
return false;
}
}.bind(this);
script.addEventListener('load', intlLocaleLoadedBindThis);
script.addEventListener('error', intlLocaleLoadErrorBindThis);
intlScript = document.querySelector('script#intl-js-library') || document.body;
intlScript.parentNode.insertBefore(script, intlScript.nextSibling);
}
else if (!script.hasAttribute('loaderror')) {
// already loading
var anotherIntlLocaleLoadedBindThis = function (e) {
if (e.target === script) {
callback.call(this, locale);
e.target.removeEventListener('load', anotherIntlLocaleLoadedBindThis);
return false;
}
}.bind(this);
var anotherIntlLocaleLoadErrorBindThis = function (e) {
if (e.target === script) {
e.target.removeEventListener('error', anotherIntlLocaleLoadErrorBindThis);
locale = fallbackLanguages.shift();
if (!locale) {
locale = this.DEFAULT_LANG;
}
var fallbackSupport = Intl.NumberFormat.supportedLocalesOf(locale, { localeMatcher: 'lookup'});
if (fallbackSupport.length > 0) {
callback.call(this, locale);
}
else {
_setupIntlPolyfillLocale.call(this, locale, callback);
}
return false;
}
}.bind(this);
script.addEventListener('load', anotherIntlLocaleLoadedBindThis);
script.addEventListener('error', anotherIntlLocaleLoadErrorBindThis);
}
else {
var enSupport = Intl.NumberFormat.supportedLocalesOf(this.DEFAULT_LANG, { localeMatcher: 'lookup'});
if (enSupport.length > 0) {
callback.call(this, this.DEFAULT_LANG);
}
else {
_setupIntlPolyfillLocale.call(this, this.DEFAULT_LANG, callback);
}
}
return false;
}
}
}
return true;
}
/**
* Enumerate fallback locales for the target locale.
*
* Subset implementation of BCP47 (https://tools.ietf.org/html/bcp47).
*
* ### Examples:
*
*| Target Locale | Fallback 1 | Fallback 2 | Fallback 3 |
*|:--------------|:-----------|:-----------|:-----------|
*| ru | N/A | N/A | N/A |
*| en-GB | en | N/A | N/A |
*| en-Latn-GB | en-GB | en-Latn | en |
*| fr-CA | fr | N/A | N/A |
*| zh-Hans-CN | zh-Hans | zh | N/A |
*| zh-CN | zh-Hans | zh | N/A |
*| zh-TW | zh-Hant | zh | N/A |
*
* #### Note:
*
* For zh language, the script Hans or Hant is supplied as its default script when a country/region code is supplied.
*
* @param {string} lang Target locale.
* @return {Array} List of fallback locales including the target locale at the index 0.
*/
function _enumerateFallbackLanguages (lang) {
var result = [];
var parts;
var match;
var isExtLangCode = 0;
var extLangCode;
var isScriptCode = 0;
var scriptCode;
var isCountryCode = 0;
var countryCode;
var n;
/* istanbul ignore if: lang is always a non-null string */
if (!lang || lang.length === 0) {
result.push('');
__render() {
return html`<span id="number">${this.formatted || ''}</span>`;
}
else {
parts = lang.split(/[-_]/);
// normalize ISO-639-1 language codes
if (parts.length > 0 &&
parts[0].match(/^[A-Za-z]{2,3}$/)) {
// language codes have to be lowercased
// e.g. JA -> ja, FR -> fr
// TODO: normalize 3-letter codes to 2-letter codes
parts[0] = parts[0].toLowerCase();
}
// normalize ISO-639-3 extension language codes
if (parts.length >= 2 &&
parts[1].match(/^[A-Za-z]{3}$/) &&
!parts[1].match(/^[Cc][Hh][SsTt]$/)) { // exclude CHS,CHT
// extension language codes have to be lowercased
// e.g. YUE -> yue
isExtLangCode = 1;
extLangCode = parts[1] = parts[1].toLowerCase();
}
// normalize ISO-15924 script codes
if (parts.length >= isExtLangCode + 2 &&
(match = parts[isExtLangCode + 1].match(/^([A-Za-z])([A-Za-z]{3})$/))) {
// script codes have to be capitalized only at the first character
// e.g. HANs -> Hans, lAtN -> Latn
isScriptCode = 1;
scriptCode = parts[isExtLangCode + 1] = match[1].toUpperCase() + match[2].toLowerCase();
}
// normalize ISO-3166-1 country/region codes
if (parts.length >= isExtLangCode + isScriptCode + 2 &&
(match = parts[isExtLangCode + isScriptCode + 1].match(/^[A-Za-z0-9]{2,3}$/))) {
// country/region codes have to be capitalized
// e.g. cn -> CN, jP -> JP
isCountryCode = 1;
countryCode = parts[isExtLangCode + isScriptCode + 1] = match[0].toUpperCase();
}
// extensions have to be in lowercases
// e.g. U-cA-Buddhist -> u-ca-buddhist, X-LiNux -> x-linux
if (parts.length >= isExtLangCode + isScriptCode + isCountryCode + 2) {
for (n = isExtLangCode + isScriptCode + isCountryCode + 1; n < parts.length; n++) {
parts[n] = parts[n].toLowerCase();
}
}
// enumerate fallback languages
while (parts.length > 0) {
// normalize delimiters as -
// e.g. ja_JP -> ja-JP
if (!parts[parts.length - 1].match(/^[xu]$/)) {
result.push(parts.join('-'));
}
if (isScriptCode &&
isCountryCode &&
parts.length == isExtLangCode + isScriptCode + 2) {
// script code can be omitted to default
// e.g. en-Latn-GB -> en-GB, zh-Hans-CN -> zh-CN
parts.splice(isExtLangCode + isScriptCode, 1);
result.push(parts.join('-'));
parts.splice(isExtLangCode + isScriptCode, 0, scriptCode);
}
if (isExtLangCode &&
isCountryCode &&
parts.length == isExtLangCode + isScriptCode + 2) {
// ext lang code can be omitted to default
// e.g. zh-yue-Hans-CN -> zh-Hans-CN
parts.splice(isExtLangCode, 1);
result.push(parts.join('-'));
parts.splice(isExtLangCode, 0, extLangCode);
}
if (isExtLangCode &&
isScriptCode &&
parts.length == isExtLangCode + isScriptCode + 1) {
// ext lang code can be omitted to default
// e.g. zh-yue-Hans -> zh-Hans
parts.splice(isExtLangCode, 1);
result.push(parts.join('-'));
parts.splice(isExtLangCode, 0, extLangCode);
}
if (!isScriptCode &&
!isExtLangCode &&
isCountryCode &&
parts.length == 2) {
// default script code can be added in certain cases with country codes
// e.g. zh-CN -> zh-Hans-CN, zh-TW -> zh-Hant-TW
switch (result[result.length - 1]) {
case 'zh-CN':
case 'zh-CHS':
result.push('zh-Hans');
break;
case 'zh-TW':
case 'zh-SG':
case 'zh-HK':
case 'zh-CHT':
result.push('zh-Hant');
break;
default:
break;
}
}
parts.pop();
}
}
return result;
}
Polymer({
importMeta: import.meta,
is: 'i18n-number',
_template: (t => { t.setAttribute('strip-whitespace', ''); return t; })(html`<span id="number"></span>`),
/**

@@ -341,4 +54,11 @@ * Fired whenever the formatted text is rendered.

properties: {
constructor() {
super();
this.attachShadow({ mode: 'open' });
/**
* Default locale constant 'en'
*/
this.DEFAULT_LANG = 'en';
/**
* The locale for the formatted number.

@@ -348,97 +68,85 @@ * The typical value is bound to `{{effectiveLang}}` when the containing element has

*/
_lang: {
type: String,
value: 'en',
observer: '_langChanged',
reflectToAttribute: false
},
this.lang = this.DEFAULT_LANG;
/**
* Options object for Intl.NumberFormat
* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat)
* Offset for number
*
* Note: number = rawNumber - offset
*/
options: {
type: Object,
observer: '_optionsChanged',
notify: true
},
this.offset = 0;
/**
* Raw string synchronized with textContent
*/
raw: {
type: String,
observer: '_rawChanged'
},
//this.raw = undefined;
/**
* Offset for number
*
* Note: number = rawNumber - offset
* Options object for Intl.NumberFormat
* (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat)
*/
offset: {
type: Number,
value: 0,
observer: '_offsetChanged'
},
//this.options = undefined;
/**
* Raw number parsed from raw
*/
rawNumber: {
type: Number,
notify: true
},
//this.rawNumber = undefined;
/**
* Number calculated from rawNumber and offset
*/
number: {
type: Number,
notify: true
},
//this.number = undefined;
/**
* Formatted string rendered for UI
*
* Note:
* - While Intl.js Polyfill locale module is being loaded, the value is set as `undefined` until load completion.
*/
formatted: {
type: String,
notify: true
//this.formatted = undefined;
this._setupObservers();
this.raw = this.textNode.data;
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case 'lang':
this._langChanged(newValue);
break;
case 'options':
try {
this.options = JSON.parse(newValue);
}
catch (ex) {
this.options = undefined;
}
break;
case 'offset':
this.offset = parseInt(newValue);
break;
/* istanbul ignore next */
default:
/* istanbul ignore next */
break;
}
},
}
observers: [
'_onOptionsPropertyChanged(options.*)'
],
get options() {
return this._options;
}
/**
* Default locale constant 'en'
*/
DEFAULT_LANG: 'en',
set options(value) {
this._optionsChanged(this._options = value);
}
/**
* Start loading Intl polyfill only once
*/
registered: function () {
if (!_setupIntlPolyfillCalled) {
_setupIntlPolyfillCalled = true;
_setupIntlPolyfill.call(this);
}
},
get raw() {
return this._raw;
}
ready: function () {
this._setupObservers();
this.raw = this.textNode.data;
if (!this.lang) {
// Polyfill non-functional default value for lang property in Safari 7
this.lang = this.DEFAULT_LANG;
}
},
set raw(value) {
this._rawChanged(this._raw = value);
}
attached: function () {
get offset() {
return this._offset;
}
set offset(value) {
this._offsetChanged(this._offset = value);
}
connectedCallback() {
this.raw = this.textNode.data;
},
this.invalidate();
}

@@ -448,8 +156,8 @@ /**

*/
_setupObservers: function () {
_setupObservers() {
let i = 0;
do {
this.textNode = dom(this).childNodes[i++];
this.textNode = this.childNodes[i++];
if (!this.textNode) {
this.textNode = dom(this).childNodes[0];
this.textNode = this.childNodes[0];
break;

@@ -460,24 +168,34 @@ }

if (!this.textNode) {
dom(this).appendChild(document.createTextNode(''));
this.textNode = dom(this).childNodes[0];
this.appendChild(document.createTextNode(''));
this.textNode = this.childNodes[0];
}
this.observer = new MutationObserver(this._textMutated.bind(this));
this.observer.observe(this.textNode, { characterData: true });
this.observer.observe(this, { attributes: true, attributeFilter: [ 'lang' ] });
this.nodeObserver = dom(this).observeNodes(function (info) {
let i = 0;
do {
if (info.addedNodes[i] &&
info.addedNodes[i].nodeType === info.addedNodes[i].TEXT_NODE) {
this.textNode = info.addedNodes[i];
this.raw = this.textNode.data;
//console.log('i18n-number: text node added with ' + this.raw);
this.observer.observe(this.textNode, { characterData: true });
this.nodeObserver = new MutationObserver(function (mutations) {
mutations.forEach(function(mutation) {
switch (mutation.type) {
case 'childList':
let i = 0;
do {
if (mutation.addedNodes[i] &&
mutation.addedNodes[i].nodeType === mutation.addedNodes[i].TEXT_NODE) {
this.textNode = mutation.addedNodes[i];
this.raw = this.textNode.data;
//console.log('i18n-number: text node added with ' + this.raw);
this.observer.observe(this.textNode, { characterData: true });
break;
}
i++;
}
while (i < mutation.addedNodes.length);
break;
/* istanbul ignore next */
default:
/* istanbul ignore next: mutation.type is characterData or attributes */
break;
}
i++;
}
while (i < info.addedNodes.length);
}, this);
}.bind(this));
},
this.nodeObserver.observe(this, { childList: true });
}

@@ -489,3 +207,3 @@ /**

*/
_textMutated: function (mutations) {
_textMutated(mutations) {
mutations.forEach(function(mutation) {

@@ -499,13 +217,9 @@ switch (mutation.type) {

break;
case 'attributes':
if (mutation.attributeName === 'lang') {
this._lang = this.lang;
}
break;
/* istanbul ignore next: mutation.type is characterData */
default:
/* istanbul ignore next: mutation.type is characterData or attributes */
/* istanbul ignore next: mutation.type is characterData */
break;
}
}, this);
},
}

@@ -517,3 +231,3 @@ /**

*/
_rawChanged: function (raw) {
_rawChanged(raw) {
if (this.textNode) {

@@ -526,3 +240,3 @@ if (raw !== this.textNode.data) {

}
},
}

@@ -534,3 +248,3 @@ /**

*/
_langChanged: function (lang) {
_langChanged(lang) {
if (!lang) {

@@ -544,3 +258,3 @@ this.lang = this.DEFAULT_LANG;

}
},
}

@@ -552,3 +266,3 @@ /**

*/
_optionsChanged: function (options) {
_optionsChanged(options) {
if (this.textNode) {

@@ -558,8 +272,16 @@ //console.log('i18n-number: _optionsChanged: options = ' + JSON.stringify(options));

}
},
}
/**
* Partially emulates notifyPath() in Polymer library
* Just calls _onOptionsPropertyChanged() to re-render
*/
notifyPath(path, value) {
this._onOptionsPropertyChanged();
}
/**
* Observer of `options` sub-properties to re-render the formatted number.
*/
_onOptionsPropertyChanged: function (/* changeRecord */) {
_onOptionsPropertyChanged(/* changeRecord */) {
if (this.textNode) {

@@ -569,3 +291,3 @@ //console.log('_onOptionsPropertyChanged: path = ' + changeRecord.path + ' value = ' + JSON.stringify(changeRecord.value));

}
},
}

@@ -577,3 +299,3 @@ /**

*/
_offsetChanged: function (offset) {
_offsetChanged(offset) {
if (this.textNode) {

@@ -583,3 +305,3 @@ //console.log('i18n-number: _offsetChanged: offset = ' + offset);

}
},
}

@@ -601,3 +323,3 @@ /**

return formatObject;
},
}

@@ -612,39 +334,13 @@ /**

*/
_formatNumber: function (lang, options, number) {
_formatNumber(lang, options, number) {
if (!lang) {
lang = this.DEFAULT_LANG;
}
switch (intlLibraryLoadingStatus) {
case 'loaded':
case 'loading':
default:
try {
if (_setupIntlPolyfillLocale.call(this, lang, function (locale) {
this.effectiveLang = locale;
this._render.call(this, locale, this.options, this.raw, this.offset);
}.bind(this))) {
return this._getNumberFormatObject(lang, options).format(number);
}
else {
// waiting for callback
return undefined;
}
}
catch (e) {
return number.toString();
}
/* istanbul ignore next: unreachable code due to returns in the same case */
break;
case 'native':
// native
try {
return this._getNumberFormatObject(lang, options).format(number);
}
catch (e) {
return number.toString();
}
/* istanbul ignore next: unreachable code due to returns in the same case */
break;
try {
return this._getNumberFormatObject(lang, options).format(number);
}
},
catch (e) {
return number.toString();
}
}

@@ -659,3 +355,3 @@ /**

*/
_render: function (lang, options, raw, offset) {
_render(lang, options, raw, offset) {
// TODO: rendering may be done redundantly on property initializations

@@ -677,8 +373,22 @@ raw = raw.trim();

}
this.$.number.textContent = this.formatted ? this.formatted : '';
this.invalidate();
//console.log('i18n-number: _render ' + this.formatted);
if (typeof this.formatted !== 'undefined') {
this.fire('rendered');
}
/**
* Renders shadowRoot with this.__render()
*/
invalidate() {
if (!this.needsRender) {
this.needsRender = true;
Promise.resolve().then(() => {
this.needsRender = false;
render(this.__render(), this.shadowRoot);
//console.log(`rendered "${this.formatted}"`);
if (typeof this.formatted !== 'undefined') {
this.dispatchEvent(new Event('rendered', { bubbles: true, cancelable: false, composed: true }));
}
});
}
},
}

@@ -701,5 +411,6 @@ /**

*/
render: function () {
render() {
this._render(this.lang, this.options, this.raw, this.offset);
}
});
}
customElements.define(I18nNumber.is, I18nNumber);
{
"description": "Wrapper element for Intl.NumberFormat",
"keywords": [
"polymer",
"lit-html",
"web-component",

@@ -18,3 +18,3 @@ "web-components",

"name": "i18n-number",
"version": "3.0.1",
"version": "4.0.0-pre.1",
"main": "i18n-number.js",

@@ -49,2 +49,3 @@ "directories": {

"lcov-result-merger": "^1.2.0",
"@polymer/polymer": "^3.0.0",
"wct-browser-legacy": "^1.0.0",

@@ -62,5 +63,5 @@ "wct-istanbul": "^0.14.3",

"dependencies": {
"@polymer/polymer": "^3.0.0",
"intl": "^1.2.0"
"lit-html": "^1.0.0",
"wc-putty": "^0.1.0"
}
}

@@ -7,3 +7,2 @@ {

"extraDependencies": [
"node_modules/intl/**",
"node_modules/@webcomponents/webcomponentsjs/**"

@@ -10,0 +9,0 @@ ],

@@ -43,3 +43,11 @@ /**

}
},
attached: function() {
this.$.num.setAttribute('lang', this.$.num.getAttribute('lang'));
this.$.num.setAttribute('lang', this.$.num.getAttribute('lang'));
this.$.num.setAttribute('attr', 'value');
this.$.num.setAttribute('options', '<');
this.$.num.constructor.importMeta;
}
});

@@ -40,3 +40,3 @@ {

"platform": "OS X 10.11",
"version": "9"
"version": "10"
}

@@ -43,0 +43,0 @@ ]

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc