UNPKG

make-plural

Version:

Translates Unicode CLDR pluralization rules to executable JavaScript

272 lines (243 loc) 12.2 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.MakePlural = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 'use strict'; var _toArray = function (arr) { return Array.isArray(arr) ? arr : Array.from(arr); }; var _toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); Object.defineProperty(exports, '__esModule', { value: true }); /** * make-plural.js -- https://github.com/eemeli/make-plural.js/ * Copyright (c) 2014-2015 by Eemeli Aro <eemeli@gmail.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * The software is provided "as is" and the author disclaims all warranties * with regard to this software including all implied warranties of * merchantability and fitness. In no event shall the author be liable for * any special, direct, indirect, or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether in an * action of contract, negligence or other tortious action, arising out of * or in connection with the use or performance of this software. */ var Parser = (function () { function Parser() { _classCallCheck(this, Parser); } _createClass(Parser, [{ key: 'parse', value: function parse(cond) { var _this = this; if (cond === 'i = 0 or n = 1') { return 'n >= 0 && n <= 1'; }if (cond === 'i = 0,1') { return 'n >= 0 && n < 2'; }if (cond === 'i = 1 and v = 0') { this.v0 = 1; return 'n == 1 && v0'; } return cond.replace(/([tv]) (!?)= 0/g, function (m, sym, noteq) { var sn = sym + '0'; _this[sn] = 1; return noteq ? '!' + sn : sn; }).replace(/\b[fintv]\b/g, function (m) { _this[m] = 1; return m; }).replace(/([fin]) % (10+)/g, function (m, sym, num) { var sn = sym + num; _this[sn] = 1; return sn; }).replace(/n10+ = 0/g, 't0 && $&').replace(/(\w+ (!?)= )([0-9.]+,[0-9.,]+)/g, function (m, se, noteq, x) { if (m === 'n = 0,1') return '(n == 0 || n == 1)'; if (noteq) return se + x.split(',').join(' && ' + se); return '(' + se + x.split(',').join(' || ' + se) + ')'; }).replace(/(\w+) (!?)= ([0-9]+)\.\.([0-9]+)/g, function (m, sym, noteq, x0, x1) { if (Number(x0) + 1 === Number(x1)) { if (noteq) return '' + sym + ' != ' + x0 + ' && ' + sym + ' != ' + x1; return '(' + sym + ' == ' + x0 + ' || ' + sym + ' == ' + x1 + ')'; } if (noteq) return '(' + sym + ' < ' + x0 + ' || ' + sym + ' > ' + x1 + ')'; if (sym === 'n') { _this.t0 = 1;return '(t0 && n >= ' + x0 + ' && n <= ' + x1 + ')'; } return '(' + sym + ' >= ' + x0 + ' && ' + sym + ' <= ' + x1 + ')'; }).replace(/ and /g, ' && ').replace(/ or /g, ' || ').replace(/ = /g, ' == '); } }, { key: 'vars', value: (function (_vars) { function vars() { return _vars.apply(this, arguments); } vars.toString = function () { return _vars.toString(); }; return vars; })(function () { var vars = []; if (this.i) vars.push('i = s[0]'); if (this.f || this.v) vars.push('f = s[1] || \'\''); if (this.t) vars.push('t = (s[1] || \'\').replace(/0+$/, \'\')'); if (this.v) vars.push('v = f.length'); if (this.v0) vars.push('v0 = !s[1]'); if (this.t0 || this.n10 || this.n100) vars.push('t0 = Number(s[0]) == n'); for (var k in this) { if (/^.10+$/.test(k)) { var k0 = k[0] === 'n' ? 't0 && s[0]' : k[0]; vars.push('' + k + ' = ' + k0 + '.slice(-' + k.substr(2).length + ')'); } }if (!vars.length) return ''; return 'var ' + ['s = String(n).split(\'.\')'].concat(vars).join(', '); }) }]); return Parser; })(); var Tests = (function () { function Tests(obj) { _classCallCheck(this, Tests); this.obj = obj; this.ordinal = {}; this.cardinal = {}; } _createClass(Tests, [{ key: 'add', value: function add(type, cat, examples) { this[type][cat] = examples.join(' ').replace(/^[ ,]+|[ ,…]+$/g, '').replace(/(0\.[0-9])~(1\.[1-9])/g, '$1 1.0 $2').split(/[ ,~…]+/); } }, { key: 'testCond', value: function testCond(n, type, expResult, fn) { try { var r = (fn || this.obj.fn)(n, type === 'ordinal'); } catch (e) { r = e.toString(); } if (r !== expResult) { throw new Error('Locale ' + JSON.stringify(this.obj.lc) + type + ' rule self-test failed for v = ' + JSON.stringify(n) + ' (was ' + JSON.stringify(r) + ', expected ' + JSON.stringify(expResult) + ')'); } return true; } }, { key: 'testCat', value: function testCat(type, cat, fn) { var _this2 = this; this[type][cat].forEach(function (n) { _this2.testCond(n, type, cat, fn); if (!/\.0+$/.test(n)) _this2.testCond(Number(n), type, cat, fn); }); return true; } }, { key: 'testAll', value: function testAll() { for (var cat in this.cardinal) { this.testCat('cardinal', cat); }for (var cat in this.ordinal) { this.testCat('ordinal', cat); }return true; } }]); return Tests; })(); var MakePlural = (function () { function MakePlural(lc) { var _ref = arguments[1] === undefined ? MakePlural : arguments[1]; var cardinals = _ref.cardinals; var ordinals = _ref.ordinals; _classCallCheck(this, MakePlural); if (!cardinals && !ordinals) throw new Error('At least one type of plural is required'); this.lc = lc; this.categories = { cardinal: [], ordinal: [] }; this.parser = new Parser(); this.tests = new Tests(this); this.fn = this.buildFunction(cardinals, ordinals); this.fn._obj = this; this.fn.categories = this.categories; this.fn.test = (function () { return this.tests.testAll() && this.fn; }).bind(this); this.fn.toString = this.fnToString.bind(this); return this.fn; } _createClass(MakePlural, [{ key: 'compile', value: function compile(type, req) { var cases = []; var rules = MakePlural.rules[type][this.lc]; if (!rules) { if (req) throw new Error('Locale "' + this.lc + '" ' + type + ' rules not found'); this.categories[type] = ['other']; return '\'other\''; } for (var r in rules) { var _rules$r$trim$split = rules[r].trim().split(/\s*@\w*/); var _rules$r$trim$split2 = _toArray(_rules$r$trim$split); var cond = _rules$r$trim$split2[0]; var examples = _rules$r$trim$split2.slice(1); var cat = r.replace('pluralRule-count-', ''); if (cond) cases.push([this.parser.parse(cond), cat]); this.tests.add(type, cat, examples); } this.categories[type] = cases.map(function (c) { return c[1]; }).concat('other'); if (cases.length === 1) { return '(' + cases[0][0] + ') ? \'' + cases[0][1] + '\' : \'other\''; } else { return [].concat(_toConsumableArray(cases.map(function (c) { return '(' + c[0] + ') ? \'' + c[1] + '\''; })), ['\'other\'']).join('\n : '); } } }, { key: 'buildFunction', value: function buildFunction(cardinals, ordinals) { var _this3 = this; var compile = function compile(c) { return c ? (c[1] ? 'return ' : 'if (ord) return ') + _this3.compile.apply(_this3, _toConsumableArray(c)) : ''; }, fold = { vars: function vars(str) { return (' ' + str + ';').replace(/(.{1,78})(,|$) ?/g, '$1$2\n '); }, cond: function cond(str) { return (' ' + str + ';').replace(/(.{1,78}) (\|\| |$) ?/gm, '$1\n $2'); } }, cond = [ordinals && ['ordinal', !cardinals], cardinals && ['cardinal', true]].map(compile).map(fold.cond), body = [fold.vars(this.parser.vars())].concat(_toConsumableArray(cond)).join('\n').replace(/\s+$/gm, '').replace(/^[\s;]*[\r\n]+/gm, ''), args = ordinals && cardinals ? 'n, ord' : 'n'; return new Function(args, body); } }, { key: 'fnToString', value: function fnToString(name) { return Function.prototype.toString.call(this.fn).replace(/^function( \w+)?/, name ? 'function ' + name : 'function').replace('\n/**/', ''); } }], [{ key: 'load', value: function load() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } args.forEach(function (cldr) { var data = cldr && cldr.supplemental || null; if (!data) throw new Error('Data does not appear to be CLDR data'); MakePlural.rules = { cardinal: data['plurals-type-cardinal'] || MakePlural.rules.cardinal, ordinal: data['plurals-type-ordinal'] || MakePlural.rules.ordinal }; }); return MakePlural; } }]); return MakePlural; })(); exports['default'] = MakePlural; MakePlural.cardinals = true; MakePlural.ordinals = false; MakePlural.rules = { cardinal: {}, ordinal: {} }; module.exports = exports['default']; },{}]},{},[1])(1) });