cerebro-converter
Version:
Cerebro plugin for converting units and currencies
770 lines (657 loc) • 19.6 kB
JavaScript
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 14);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = {
getRates: __webpack_require__(8),
buildExtract: __webpack_require__(7),
parseUnitName: __webpack_require__(10),
linearConverter: __webpack_require__(9)
};
/***/ }),
/* 1 */
/***/ (function(module, exports) {
/* eslint quote-props: 0 */
/**
* List of all supported currencies
* @type {Array}
*/
module.exports.CURRENCIES = ['aud', 'bgn', 'brl', 'cad', 'chf', 'cny', 'czk', 'dkk', 'eur', 'gbp', 'hkd', 'hrk', 'huf', 'idr', 'ils', 'inr', 'jpy', 'krw', 'mxn', 'myr', 'nok', 'nzd', 'php', 'pln', 'ron', 'rub', 'sek', 'sgd', 'thb', 'try', 'uah', 'usd', 'zar', 'btc', 'clp'];
/**
* Array of prioritized currencies
* @type {Array}
*/
module.exports.PRIORITY_CURRENCIES = ['rub', 'usd', 'eur'];
/**
* Hash of currencies by locale countries
* @type {Object}
*/
module.exports.CURRENCY_BY_COUNTRY = {
'AU': 'aud',
'BR': 'brl',
'US': 'usd',
'CA': 'cad',
'CH': 'chf',
'CL': 'clp',
'CN': 'cny',
'GB': 'gbp',
'HK': 'hkd',
'KR': 'krw',
'NZ': 'nzd',
'PH': 'php',
'RU': 'rub',
'SG': 'sgd',
'UA': 'uah',
'ZA': 'zar',
'AD': 'eur',
'AT': 'eur',
'AX': 'eur',
'BE': 'eur',
'BL': 'eur',
'CY': 'eur',
'DE': 'eur',
'EE': 'eur',
'ES': 'eur',
'FI': 'eur',
'FR': 'eur',
'GF': 'eur',
'GP': 'eur',
'GR': 'eur',
'IE': 'eur',
'IT': 'eur',
'LU': 'eur',
'MC': 'eur',
'ME': 'eur',
'MF': 'eur',
'MQ': 'eur',
'MT': 'eur',
'NL': 'eur',
'PM': 'eur',
'PT': 'eur',
'RE': 'eur',
'SI': 'eur',
'SK': 'eur',
'SM': 'eur',
'TF': 'eur',
'VA': 'eur',
'YT': 'eur',
'IL': 'ils',
'IN': 'inr'
/**
* Hash of currencies by locale language
* @type {Object}
*/
};module.exports.CURRENCY_BY_LANG = {
'bg': 'bgn',
'cs': 'czk',
'da': 'dkk',
'hr': 'hrk',
'hu': 'huf',
'id': 'idr',
'he': 'ils',
'hi': 'inr',
'ja': 'jpy',
'ms': 'myr',
'nb': 'nok',
'nn': 'nok',
'no': 'nok',
'ru': 'rub'
/**
* Object of synonims of currencies for better matching them in search queries
* @type {Object}
*/
};module.exports.SYNONIMS = {
'франк*': 'chf',
'franc*': 'chf',
'₣': 'chf',
'real*': 'brl',
'реал*': 'brl',
'kun*': 'hrk',
'кун*': 'hrk',
'форинт*': 'huf',
'forint*': 'huf',
'₹': 'inr',
'rs': 'inr',
'rupee*': 'inr',
'ringgit*': 'myr',
'ринггит*': 'myr',
'฿': 'thb',
'baht': 'thb',
'бат*': 'thb',
'bat*': 'thb',
'lir*': 'try',
'лир*': 'try',
'rand*': 'zar',
'рэнд*': 'zar',
'ренд*': 'zar',
'zlot*': 'pln',
'злот*': 'pln',
'₴': 'uah',
'грн': 'uah',
'грив*': 'uah',
'bucks': 'usd',
'$': 'usd',
'dollar*': 'usd',
'долл*': 'usd',
'€': 'eur',
'eur*': 'eur',
'евро': 'eur',
'£': 'gbp',
'фунт*': 'gbp',
'pound*': 'gbp',
'₽': 'rub',
'руб': 'rub',
'рубл*': 'rub',
'₪': 'ils',
'шекел*': 'ils',
'йен*': 'jpy',
'юан*': 'cny',
'yuan': 'cny',
'bitc*': 'btc',
'битко*': 'btc'
/**
* Hash of special display names for some currencies. Default name of currency displayed
* @type {Object}
*/
};module.exports.DISPLAY_NAMES = {
'usd': '$',
'eur': '€',
'gbp': '£',
'rub': '₽',
'uah': '₴',
'ils': '₪',
'chf': '₣',
'thb': '฿',
'inr': '₹'
};
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
const getUrl = __webpack_require__(12);
const getBaseCurrency = __webpack_require__(11);
const { SYNONIMS, DISPLAY_NAMES, PRIORITY_CURRENCIES } = __webpack_require__(1);
const { parseUnitName, buildExtract, linearConverter } = __webpack_require__(0);
// Hash of exchange rates
const rates = {};
// Date of fetching exchange rates
let ratesDate = null;
let baseCurrency = null;
/**
* Get cache expiration date
* @return {Date}
*/
function cacheExpirationDate() {
return new Date(Date.now() - 2 * 3600 * 1000);
}
/**
* Check that saved exchange rates are still valid
* @return {Boolean}
*/
function cacheValid() {
return ratesDate && ratesDate >= cacheExpirationDate();
}
/**
* Fetch & save rates from yahoo API
* @return {Promise} promise that resolves with rates JSON
*/
function getRates(config) {
baseCurrency = getBaseCurrency(config);
const url = getUrl();
if (cacheValid()) return Promise.resolve(rates);
return fetch(url).then(resp => resp.json()).then(response => {
// Save exchange rates date
ratesDate = new Date(); // mycurrency.net doesn't provide last refresh timestamp
// Convert response array with exchange rates to hash
Object.keys(response.rates).forEach(key => {
rates[key.toLowerCase()] = parseFloat(response.rates[key]);
});
});
}
/**
* Convert string to real currency
* @param {String} unit
* @return {String}
*/
function toUnit(unit) {
return parseUnitName(SYNONIMS, rates, unit);
}
/**
* Get target currency when it is not defined
* @param {string} currency
* @return {string}
*/
function defaultTarget(currency) {
if (baseCurrency !== currency) {
return baseCurrency;
}
return PRIORITY_CURRENCIES.find(cur => cur !== currency);
}
/**
* Prettified name of currency. It is currency sign if it is supported
* @param {String} currency
* @return {String}
*/
function displayName(currency) {
return DISPLAY_NAMES[currency] || currency;
}
function toUnitStruct(unit) {
return {
unit,
displayName: displayName(unit)
};
}
module.exports = {
getRates,
extract: buildExtract(toUnit, toUnitStruct, defaultTarget),
convert: linearConverter(rates)
};
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
const { SYNONIMS, UNITS } = __webpack_require__(13);
const { buildExtract, getRates, parseUnitName, linearConverter } = __webpack_require__(0);
const toUnit = parseUnitName.bind(null, SYNONIMS, UNITS);
function defaultTarget(unit) {
return unit === 'm' ? 'ft' : 'm';
}
function toUnitStruct(unit) {
return {
unit,
displayName: unit
};
}
module.exports = {
getRates,
extract: buildExtract(toUnit, toUnitStruct, defaultTarget),
convert: linearConverter(UNITS)
};
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
const { SYNONIMS, UNITS } = __webpack_require__(15);
const { buildExtract, getRates, parseUnitName, linearConverter } = __webpack_require__(0);
const toUnit = parseUnitName.bind(null, SYNONIMS, UNITS);
function defaultTarget(unit) {
return unit === 'kg' ? 'lb' : 'kg';
}
function toUnitStruct(unit) {
return {
unit,
displayName: unit
};
}
module.exports = {
getRates,
extract: buildExtract(toUnit, toUnitStruct, defaultTarget),
convert: linearConverter(UNITS)
};
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
const { SYNONIMS, UNITS, KELVIN } = __webpack_require__(16);
const { buildExtract, getRates, parseUnitName } = __webpack_require__(0);
const toUnit = parseUnitName.bind(null, SYNONIMS, UNITS);
function defaultTarget(unit) {
return unit === '°c' ? '°f' : '°c';
}
function toUnitStruct(unit) {
return {
unit,
displayName: unit.toUpperCase()
};
}
function convert(amount, from, to) {
let result = amount;
if (from.unit === '°f') {
result = 5 / 9 * (result - 32);
if (to.unit === 'k') {
result = result - KELVIN;
}
} else if (from.unit === '°c') {
if (to.unit === 'k') {
result = KELVIN + result;
}
if (to.unit === '°f') {
result = 9 / 5 * result + 32;
}
} else if (from.unit === 'k') {
if (to.unit === '°c') {
result = result + KELVIN;
}
if (to.unit === '°f') {
result = 9 / 5 * (result + KELVIN) + 32;
}
}
return Math.round(result * 100) / 100;
}
module.exports = {
getRates,
convert,
extract: buildExtract(toUnit, toUnitStruct, defaultTarget)
};
/***/ }),
/* 6 */
/***/ (function(module, exports) {
module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAGqklEQVR4Ae3ZA5RrSxaH8W/vqpOT1rWfbXNs27Zt4/XS2LZtz7Nt275GIzqn9nStvhp0+uWkc6fv6vxWKk5q1b+q9gnomsm6urqEAmrf6T9Agh0hYrsFkz4KUIE1Q4GBXsUpLVOIMlOWi8hVw8P+0rnvWreuowHUvtX/XOfsLRZ4kE9IkfaiHxoyBsoCnuIMLAczbg/w60Yevtr7pso9UxrA8Nf7lqTevuadPAeBLAMz2qICq4bHA0gcbfMKkkCecVeehXelb6r8nsmhTGLtF8u7pp7jfUmeEwfeaIAZ004WoFEDBzt5r7+ufqP/LW0HYN9fMNDXo7/wCYfENzemv8b4dnBJYl8a+UbvM9sKoF6rfChJ5UGNOtuVEEDAJypfGf5u3+JCAaz7Ynl3Vd6SN9guZTkkKTu5hr21UABpqi/0KbNCaKEcTzOWgai8ZOWnGWgpAAMZ83hCK71NvxDyHLyya9rfc0hLAaz91NxZwJ6WM7lQh8XH4J91GnrUIJbXmS4McB5xIgcyAc//YL3VARXtD8bkLGDpPGTx0TC6PN5mWhGiRS0FIIYaKM2EBmAQctg06/Ey3g51IsSDKMVt6aepyfoJuCYBFCCKzD8IXGl80HP2IpLyXGTREUi8XwTbcDvU1rYRgsC8AxGfggECIESYESGCDd0J1dWF+vG0ygLme/FP/hPSvyNb0x0fjb7gYjZpnPhSuOmX4HtonWGS4J/wKzQG3ETjtDfCtd8B31swgAIh1O+/FOm7L15Hy3Px8/YmVNeSrblx80xYZQ0qSnFGY/nlSGUdW8h/HXZtdEXhfnyh5Z9XCSe9CAOI13d9Bv6pfyDcfTr5P5+L+DKRioBLKUYQy7BTX0mgufF+ygUDKMipADZ+UiESAacgypTRTf10iKctMt7EEeHSzfdNLZmuAQDqsTXXMHrmB9ENN+PUsz3xtEs8OnQreuVnQB24dIYFEImDpJftkTLDdQPoBjDDef6HKpDk4AWC0REqkAcjq1cRZ3SKAFndWgugUgF8wKt0LAAhMGJzGNnrdbgkBTM6oVwusWG4Agw+8ADm9kB/WTu7AoA8DJAd8gZ8eQAs0Am9vb1k6ze0FkBkBoHOBRCZGdYYxZzrWADWALJRJtItgvyfmVlsYNax9w8hzOwAmuluATrCAJkBWyBkIAIIiLLlPgUCiGs7AFV94O9RYAt4irIcPehNMO8gwllvj7chryG7PQPd52Xk57wHRpeDKBOzpgGICOvXr6fRaDQdfDzW9/T0xOvbaAVYjpUXwaHvx/UvBXWEU1+P7PQE3GN+iKRzaNxzDnrVl8GXKUpEOO2007jzzjtxzvG/xHAe9KAHceyxx5Jl2TaqAeKgcj/1E19G6Ym/xO37CqRncfxTJA6e6hXfRuLv9D6lKWu+BeLMDQwMMG/evM0BmNnmcKI46Dj78blmtu22gGiCv+806n9/LulTfofu8kSi2uXfQM59F6oOUJoxmgcQ73/Ywx7G5MaD2PZFEMOXUkSUTeLtoA6wKTkK5HnedABRXB2quo2LYGgguzwZ97ifEZd97cY/4pcdi9v/NaCecNY7IDQAKRyAqnL66adz7733xkFOOPOHHXYYhx56aLze8grQwkWwZwn6qO9v3vN24vOoH/8S8tGVxJpg+74WsipEk2+DCVsscrVarVmLA2/yHgVWQFbTOiUaooBNVASXUzt/EIn/3p7/PtSXYPnp1E98ObJ3/FP01ziX0o44c7EGxG3QTKlUalYDYhttKYD15ZG1s+hbocK8iboW9bgbf4AZqPOAgO8lFsZw72moKoi2WwNihW/ng1AML7bbWtoCe72dWpZzKW7yI4G6BBA2Uz8eiGhLRXCiFkKYrDVd+pUxIyMjl7VcA6p5+J0FOsww61jbtDXOPf74429pOYAbb68cX61xaZKwvYqDj0Xyy4ODg6HlAB78RSpDFT6Y5WQqdEynZj/WjrGl/9u//vWvfy/8e8Di946ctL7Cx5yHjoRgnQmgXC4zNDR0+cqVK98WZ79wANGCd4x8avUGPmyQTeftYGaoKnHmh4eHz73rrrue9djHPnb5lPwztOBdI59cNWRPr9S5NPGQlCBxoNJeEwEFRKRwU1WSJNn0hWj9mjVrPnPFFVc8acztMDmhBd9+Pb3P2rfnqb2pPtsph6uw0MxKFKAE7suWsubBv8KV+sACrRARgAAMhRBuyfP8xLHB/3ps1m+kBUJBfx0LY9eFPfM1CSkFrWAhGw77Amk6q2iVDxvGvPjFL15Fy7q6urq6uv4FdBJwO7xN9tUAAAAASUVORK5CYII="
/***/ }),
/* 7 */
/***/ (function(module, exports) {
/**
* Build function, that extracts from and to units from regexp match
* @param {Function} toUnit convert string to real unit name
* @param {Function} toUnitStruct Function that converts unit name to structure:
* @param {Function} defaultTarget Function that returns default target unit
* ** unit
* ** displayName
* ** rate
* @return {Function} extract function that takes regexp match and return from and to structures
*/
module.exports = function (toUnit, toUnitStruct, defaultTarget) {
return function extract(match) {
const from = toUnit(match[2]);
const to = match[3] ? toUnit(match[3]) : defaultTarget(from);
if (!from || !to) {
return false;
}
return [toUnitStruct(from), toUnitStruct(to)];
};
};
/***/ }),
/* 8 */
/***/ (function(module, exports) {
/**
* Default getRates function just resolves Promise
* because we know convertion rates
*
* @return {Promise}
*/
module.exports = () => Promise.resolve();
/***/ }),
/* 9 */
/***/ (function(module, exports) {
/**
* Generate base linear converter from rates hash
* @param {Object} rates
* @return {Function} converter function
*/
module.exports = rates => (amount, from, to) => Math.round(amount / rates[from.unit] * rates[to.unit] * 100) / 100;
/***/ }),
/* 10 */
/***/ (function(module, exports) {
/**
* Convert user-provided string to real unit name
*
* @param {Object} synonims Hash with synonims
* @param {Object} units Hash with conversion rates
* @param {String} unit provided unit
* @return {String} real unit name
*/
module.exports = function parseUnitName(synonims, units, unit) {
let result = unit;
if (synonims[result]) {
result = synonims[result];
} else {
const synonim = Object.keys(synonims).filter(key => key.indexOf('*') !== -1).find(key => {
const regexp = new RegExp(key.replace(/\*/g, '.*'));
return result.match(regexp);
});
result = synonims[synonim] || result;
}
return units[result] ? result : null;
};
/***/ }),
/* 11 */
/***/ (function(module, exports, __webpack_require__) {
const { CURRENCY_BY_LANG, CURRENCY_BY_COUNTRY } = __webpack_require__(1);
/**
* Get base currency based on country and language
* @return {String}
*/
module.exports = config => CURRENCY_BY_COUNTRY[config.get('country')] || CURRENCY_BY_LANG[config.get('lang')] || 'usd';
/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {
// List of available currencies
const { CURRENCIES } = __webpack_require__(1);
// TODO: move API key to plugin settings
const API_KEY = '5d35ac86e868977c24bbae30b5f9d018';
/**
* Build url to get exchange rates
* @return {String} url
*/
module.exports = () => {
return `http://data.fixer.io/api/latest?access_key=${API_KEY}&format=1`;
};
/***/ }),
/* 13 */
/***/ (function(module, exports) {
/* eslint quote-props: 0 */
module.exports.SYNONIMS = {
'см': 'cm',
'centimeter*': 'cm',
'сантиметр*': 'cm',
'км': 'km',
'kilometer*': 'km',
'километр*': 'km',
'м': 'm',
'meter*': 'm',
'метр*': 'm',
'mile*': 'mile',
'миля*': 'mile',
'мили': 'mile',
'миль': 'mile',
'in*': 'in',
'"': 'in',
'дюйм*': 'in',
"'": 'ft',
'foot': 'ft',
'feet': 'ft',
'фут*': 'ft',
'yard*': 'yard',
'ярд*': 'yard'
};
module.exports.UNITS = {
'm': 1,
'cm': 100,
'in': 39.37,
'ft': 3.28,
'yard': 1.09,
'km': 0.001,
'mile': 0.00062
};
/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {
/* eslint no-eval: 0 */
const distance = __webpack_require__(3);
const mass = __webpack_require__(4);
const currency = __webpack_require__(2);
const temperature = __webpack_require__(5);
const icon = __webpack_require__(6);
// Array of all available converters
const CONVERTERS = [distance, mass, currency, temperature];
const numberRegexp = /[-+/*\d\s,\.\( )]+/;
const unitRegexp = /[\wa-я\$€£₣₹฿₴₽₪'"°℃]+/;
const mainRegexpString = [
// Start of line
'^',
// Number that we want to convert
`(${numberRegexp.source})`,
// Maybe space before source unit
'\\s?',
// Source unit name
`(${unitRegexp.source})`,
// Maybe spaces and any of word, like 'to' or 'in'
'\\s*(?:to|in|at|в)?\\s*',
// Maybe target unit (we can try to get default target unit by source unit)
`(${unitRegexp.source})?`,
// End of line
'$'].join('');
// Main regexp to match conversation strings
const REGEXP = new RegExp(mainRegexpString, 'i');
/**
* Get rates for all units
* @return {Promise} promise that resolves when all units are ready
*/
function eachConverter(config, fn) {
CONVERTERS.forEach(converter => {
converter.getRates(config).then(() => fn(converter));
});
}
/**
* Convert currency
*
* @param {String} options.term
* @param {Function} options.display
*/
const converterPlugin = ({ term, display, config }) => {
const match = term.toLowerCase().match(REGEXP);
if (match) {
let amount;
try {
amount = parseFloat(eval(match[1].toString().replace(/,/g, '.')));
} catch (err) {
// do nothing when amount parse failed
return;
}
eachConverter(config, converter => {
const pair = converter.extract(match);
if (!pair) {
return;
}
const [from, to] = pair;
const result = converter.convert(amount, from, to).toLocaleString();
display({
icon,
title: `${amount.toLocaleString()}${from.displayName} = ${result}${to.displayName}`,
term: `${term} = ${result}${to.displayName}`,
clipboard: result.toString()
});
});
}
};
module.exports = {
name: 'Convert',
fn: converterPlugin
};
/***/ }),
/* 15 */
/***/ (function(module, exports) {
/* eslint quote-props: 0 */
module.exports.SYNONIMS = {
'pound*': 'lb',
'фунт*': 'lb',
'ounce': 'oz',
'унци*': 'oz',
'kilogram*': 'kg',
'килогра*': 'kg',
'gram*': 'g',
'грам*': 'g',
'г': 'g',
'gr': 'g',
'гр': 'g',
'milligram*': 'mg',
'миллигр*': 'mg',
'карат*': 'ct',
'carat*': 'ct'
};
module.exports.UNITS = {
'kg': 1,
'g': 1000,
'mg': 1000000,
'lb': 2.2,
'oz': 35.27,
'ct': 5000
};
/***/ }),
/* 16 */
/***/ (function(module, exports) {
/* eslint quote-props: 0 */
module.exports.SYNONIMS = {
'°': '°c',
'℃': '°c',
'c': '°c',
'celsi*': '°c',
'цельси*': '°c',
'кельви*': 'k',
'kelvi*': 'k',
'fahrenheit*': '°f',
'фаренгейт*': '°f',
'f': '°f'
};
module.exports.UNITS = {
'°f': true,
'°c': true,
'k': true
};
module.exports.KELVIN = 273.15;
/***/ })
/******/ ]);