"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
value: true
|
});
|
exports.default = void 0;
|
|
var _messageformatParser = require("messageformat-parser");
|
|
var _utils = require("./utils");
|
|
/** @private */
|
class Compiler {
|
/** Creates a new message compiler. Called internally from {@link MessageFormat#compile}.
|
*
|
* @private
|
* @param {MessageFormat} mf - A MessageFormat instance
|
* @property {object} locales - The locale identifiers that are used by the compiled functions
|
* @property {object} runtime - Names of the core runtime functions that are used by the compiled functions
|
* @property {object} formatters - The formatter functions that are used by the compiled functions
|
*/
|
constructor(mf) {
|
this.mf = mf;
|
this.lc = null;
|
this.locales = {};
|
this.runtime = {};
|
this.formatters = {};
|
}
|
/** Recursively compile a string or a tree of strings to JavaScript function sources
|
*
|
* If `src` is an object with a key that is also present in `plurals`, the key
|
* in question will be used as the locale identifier for its value. To disable
|
* the compile-time checks for plural & selectordinal keys while maintaining
|
* multi-locale support, use falsy values in `plurals`.
|
*
|
* @private
|
* @param {string|object} src - the source for which the JS code should be generated
|
* @param {string} lc - the default locale
|
* @param {object} plurals - a map of pluralization keys for all available locales
|
*/
|
|
|
compile(src, lc, plurals) {
|
if (typeof src != 'object') {
|
this.lc = lc;
|
const pc = plurals[lc] || {
|
cardinal: [],
|
ordinal: []
|
};
|
pc.strict = !!this.mf.options.strictNumberSign;
|
const r = (0, _messageformatParser.parse)(src, pc).map(token => this.token(token));
|
return `function(d) { return ${r.join(' + ') || '""'}; }`;
|
} else {
|
const result = {};
|
|
for (var key in src) {
|
// eslint-disable-next-line no-prototype-builtins
|
var lcKey = plurals.hasOwnProperty(key) ? key : lc;
|
result[key] = this.compile(src[key], lcKey, plurals);
|
}
|
|
return result;
|
}
|
}
|
/** @private */
|
|
|
cases(token, plural) {
|
let needOther = token.type === 'select' || !this.mf.hasCustomPluralFuncs;
|
const r = token.cases.map(({
|
key,
|
tokens
|
}) => {
|
if (key === 'other') needOther = false;
|
const s = tokens.map(tok => this.token(tok, plural));
|
return (0, _utils.propname)(key) + ': ' + (s.join(' + ') || '""');
|
});
|
if (needOther) throw new Error("No 'other' form found in " + JSON.stringify(token));
|
return `{ ${r.join(', ')} }`;
|
}
|
/** @private */
|
|
|
token(token, plural) {
|
if (typeof token == 'string') return JSON.stringify(token);
|
let fn;
|
let args = [(0, _utils.propname)(token.arg, 'd')];
|
|
switch (token.type) {
|
case 'argument':
|
return this.mf.options.biDiSupport ? (0, _utils.biDiMarkText)(args[0], this.lc) : args[0];
|
|
case 'select':
|
fn = 'select';
|
if (plural && this.mf.options.strictNumberSign) plural = null;
|
args.push(this.cases(token, plural));
|
this.runtime.select = true;
|
break;
|
|
case 'selectordinal':
|
fn = 'plural';
|
args.push(0, (0, _utils.funcname)(this.lc), this.cases(token, token), 1);
|
this.locales[this.lc] = true;
|
this.runtime.plural = true;
|
break;
|
|
case 'plural':
|
fn = 'plural';
|
args.push(token.offset || 0, (0, _utils.funcname)(this.lc), this.cases(token, token));
|
this.locales[this.lc] = true;
|
this.runtime.plural = true;
|
break;
|
|
case 'function':
|
if (!(token.key in this.mf.fmt) && token.key in this.mf.constructor.formatters) {
|
const fmt = this.mf.constructor.formatters[token.key];
|
this.mf.fmt[token.key] = fmt(this.mf);
|
}
|
|
if (!this.mf.fmt[token.key]) throw new Error(`Formatting function ${JSON.stringify(token.key)} not found!`);
|
args.push(JSON.stringify(this.lc));
|
|
if (token.param) {
|
if (plural && this.mf.options.strictNumberSign) plural = null;
|
const s = token.param.tokens.map(tok => this.token(tok, plural));
|
args.push('(' + (s.join(' + ') || '""') + ').trim()');
|
}
|
|
fn = (0, _utils.propname)(token.key, 'fmt');
|
this.formatters[token.key] = true;
|
break;
|
|
case 'octothorpe':
|
if (!plural) return '"#"';
|
fn = 'number';
|
args = [(0, _utils.propname)(plural.arg, 'd'), JSON.stringify(plural.arg)];
|
if (plural.offset) args.push(plural.offset);
|
this.runtime.number = true;
|
break;
|
}
|
|
if (!fn) throw new Error('Parser error for token ' + JSON.stringify(token));
|
return `${fn}(${args.join(', ')})`;
|
}
|
|
}
|
|
exports.default = Compiler;
|