messageformat
Advanced tools
Comparing version 0.1.8 to 0.2.0
#!/usr/bin/env node | ||
var nopt = require("nopt") | ||
/** | ||
* Copyright 2014 | ||
* | ||
* 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 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
var | ||
nopt = require('nopt'), | ||
fs = require('fs'), | ||
vm = require('vm'), | ||
coffee = require('coffee-script'), /* only for watchr */ | ||
watch = require('watchr').watch, | ||
Path = require('path'), | ||
join = Path.join, | ||
glob = require("glob"), | ||
glob = require('glob'), | ||
async = require('async'), | ||
MessageFormat = require('../'), | ||
_ = require('underscore'), | ||
knownOpts = { | ||
@@ -18,3 +30,2 @@ "locale" : String, | ||
"output" : Path, | ||
"combine" : String, | ||
"watch" : Boolean, | ||
@@ -24,14 +35,14 @@ "namespace" : String, | ||
"stdout" : Boolean, | ||
"verbose" : Boolean | ||
"verbose" : Boolean, | ||
"help" : Boolean | ||
}, | ||
description = { | ||
"locale" : "locale to use [mandatory]", | ||
"locale" : "locale(s) to use [mandatory]", | ||
"inputdir" : "directory containing messageformat files to compile", | ||
"output" : "output where messageformat will be compiled", | ||
"combine" : "combines multiple input files to the provided namespace array element", | ||
"watch" : "watch `inputdir` for change", | ||
"namespace" : "object in the browser containing the templates", | ||
"include" : "Glob patterns for files to include in `inputdir`", | ||
"stdout" : "Print the result in stdout instead of writing in a file", | ||
"verbose" : "Print logs for debug" | ||
"namespace" : "global object in the output containing the templates", | ||
"include" : "glob patterns for files to include from `inputdir`", | ||
"stdout" : "print the result in stdout instead of writing in a file", | ||
"watch" : "watch `inputdir` for changes", | ||
"verbose" : "print logs for debug" | ||
}, | ||
@@ -41,8 +52,8 @@ defaults = { | ||
"output" : process.cwd(), | ||
"combine" : undefined, | ||
"watch" : false, | ||
"namespace" : 'window.i18n', | ||
"namespace" : 'i18n', | ||
"include" : '**/*.json', | ||
"stdout" : false, | ||
"verbose" : false | ||
"verbose" : false, | ||
"help" : false | ||
}, | ||
@@ -53,163 +64,110 @@ shortHands = { | ||
"o" : "--output", | ||
"c" : "--combine", | ||
"w" : "--watch", | ||
"ns" : "--namespace", | ||
"I" : "--include", | ||
"s" : "--stdout", | ||
"v" : "--verbose" | ||
"w" : "--watch", | ||
"v" : "--verbose", | ||
"?" : "--help" | ||
}, | ||
options = nopt(knownOpts, shortHands, process.argv, 2), | ||
argvRemain = options.argv.remain, | ||
inputdir; | ||
options = (function() { | ||
var o = nopt(knownOpts, shortHands, process.argv, 2); | ||
for (var key in defaults) { | ||
o[key] = o[key] || defaults[key]; | ||
} | ||
if (o.argv.remain) { | ||
if (o.argv.remain.length >= 1) o.inputdir = o.argv.remain[0]; | ||
if (o.argv.remain.length >= 2) o.output = o.argv.remain[1]; | ||
} | ||
if (!o.locale || o.help) { | ||
var usage = ['Usage: messageformat -l [locale] [OPTIONS] [INPUT_DIR] [OUTPUT_DIR]']; | ||
if (!o.help) { | ||
usage.push("Try 'messageformat --help' for more information."); | ||
console.error(usage.join('\n')); | ||
process.exit(-1); | ||
} | ||
usage.push('\nAvailable options:'); | ||
for (var key in shortHands) { | ||
var desc = description[shortHands[key].toString().substr(2)]; | ||
if (desc) usage.push(' -' + key + ',\t' + shortHands[key] + (shortHands[key].length < 8 ? ' ' : '') + '\t' + desc); | ||
} | ||
console.log(usage.join('\n')); | ||
process.exit(0); | ||
} | ||
if (fs.existsSync(o.output) && fs.statSync(o.output).isDirectory()) { | ||
o.output = Path.join(o.output, 'i18n.js'); | ||
} | ||
o.namespace = o.namespace.replace(/^window\./, '') | ||
return o; | ||
})(), | ||
_log = (options.verbose ? function(s) { console.log(s); } : function(){}); | ||
// defaults value | ||
_(defaults).forEach(function(value, key){ | ||
options[key] = options[key] || value; | ||
}) | ||
if(argvRemain && argvRemain.length >=1 ) options.inputdir = argvRemain[0]; | ||
if(argvRemain && argvRemain.length >=2 ) options.output = argvRemain[1]; | ||
if(!options.locale) { | ||
console.error('Usage: messageformat -l [locale] [INPUT_DIR] [OUTPUT_DIR]') | ||
console.error('') | ||
//console.error(nopt(knownOpts, shortHands, description, defaults)); | ||
process.exit(-1); | ||
function write(options, data) { | ||
data = data.join('\n'); | ||
if (options.stdout) { _log(''); return console.log(data); } | ||
fs.writeFile( options.output, data, 'utf8', function(err) { | ||
if (err) return console.error('--->\t' + err.message); | ||
_log(options.output + " written."); | ||
}); | ||
} | ||
var inputdir = options.inputdir; | ||
compile(); | ||
if(options.watch){ | ||
return watch(options.inputdir, _.debounce(compile, 100)); | ||
} | ||
function handleError( err, data ){ | ||
if(err){ | ||
err = err.message ? err.message : err; | ||
return console.error('--->\t'+ err); | ||
function parseFileSync(options, mf, file) { | ||
var path = Path.join(options.inputdir, file), | ||
lc0 = mf.lc, | ||
file_parts = file.split(/[.\/]+/), | ||
r = ''; | ||
if (!fs.statSync(path).isFile()) { | ||
_log('Skipping ' + file); | ||
return ''; | ||
} | ||
for (var i = file_parts.length - 1; i >= 0; --i) { | ||
if (file_parts[i] in MessageFormat.locale) { mf.lc = file_parts[i]; break; } | ||
} | ||
try { | ||
var text = fs.readFileSync(path, 'utf8'), | ||
nm = file.replace(/\.[^.]*$/, '').replace(/\\/g, '/'), | ||
gn = mf.globalName + '["' + nm + '"]'; | ||
_log('Building ' + gn + ' from `' + file + '` with locale "' + mf.lc + '"'); | ||
r = gn + '=' + mf.precompileObject(JSON.parse(text)); | ||
} catch (ex) { | ||
console.error('--->\tParse error in ' + path + ': ' + ex.message); | ||
} finally { | ||
mf.lc = lc0; | ||
} | ||
return r; | ||
} | ||
function compile(){ | ||
build(inputdir, options, function(err, data){ | ||
if( err ) return handleError( err ); | ||
write(data, function(err, output){ | ||
if( err ) return handleError( err ); | ||
if( options.verbose ) console.log(output + " written."); | ||
}) | ||
function build(options, callback) { | ||
var lc = options.locale.trim().split(/[ ,]+/), | ||
mf = new MessageFormat(lc[0], false, options.namespace), | ||
compiledMessageFormat = []; | ||
for (var i = 1; i < lc.length; ++i) MessageFormat.loadLocale(lc[i]); | ||
_log('Input dir: ' + options.inputdir); | ||
_log('Included locales: ' + lc.join(', ')); | ||
glob(options.include, {cwd: options.inputdir}, function(err, files) { | ||
if (!err) async.each(files, | ||
function(file, cb) { | ||
var pf = parseFileSync(options, mf, file); | ||
if (pf) compiledMessageFormat.push(pf); | ||
cb(); | ||
}, | ||
function() { | ||
var data = ['(function(G){G[\'' + mf.globalName + '\']=' + mf.functions()] | ||
.concat(compiledMessageFormat) | ||
.concat('})(this);\n'); | ||
return callback(options, data); | ||
} | ||
); | ||
}); | ||
} | ||
function write( data, callback ){ | ||
data = data.join('\n'); | ||
if(options.stdout) { | ||
return console.log(data); | ||
} | ||
var output = options.output; | ||
fs.stat(output, function(err, stat){ | ||
if(err){ | ||
// do nothing | ||
}else if(stat.isFile()){ | ||
// do nothing | ||
}else if(stat.isDirectory()){ | ||
// if `output` is a directory, create a new file called `i18n.js` in this directory. | ||
output = join(output, 'i18n.js'); | ||
}else{ | ||
return engines.handleError(ouput, 'is not a file nor a directory'); | ||
} | ||
fs.writeFile( output, data, 'utf8', function( err ){ | ||
if( typeof callback == "function" ) callback(err, output); | ||
}); | ||
}); | ||
}; | ||
build(options, write); | ||
function build(inputdir, options, callback){ | ||
// arrays of compiled templates | ||
var compiledMessageFormat = []; | ||
// read shared include file | ||
var inclFile = join(__dirname, '..', 'lib', 'messageformat.include.js'); | ||
if(options.verbose) console.log('Load include file: ' + inclFile); | ||
fs.readFile(inclFile, function(err, inclStr){ | ||
if(err) handleError(new Error('Could not read shared include file.' )); | ||
// read locale file | ||
var localeFile = join(__dirname, '..', 'locale', options.locale + '.js'); | ||
if(options.verbose) console.log('Load locale file: ' + localeFile); | ||
fs.readFile(localeFile, function(err, localeStr){ | ||
if(err) handleError(new Error('locale ' + options.locale + ' not supported.' )); | ||
var script = vm.createScript(localeStr); | ||
// needed for runInThisContext | ||
global.MessageFormat = MessageFormat; | ||
script.runInThisContext(); | ||
if( options.verbose ) { console.log('Read dir: ' + inputdir); } | ||
// list each file in inputdir folder and subfolders | ||
glob(options.include, {cwd: inputdir}, function(err, files){ | ||
files = files.map(function(file){ | ||
// normalize the file name | ||
return file.replace(inputdir, '').replace(/^\//, ''); | ||
}) | ||
async.forEach(files, readFile, function(err){ | ||
// errors are logged in readFile. No need to print them here. | ||
var fileData = [ | ||
'(function(){ ' + options.namespace + ' || (' + options.namespace + ' = {}) ', | ||
'var MessageFormat = { locale: {} };', | ||
localeStr.toString().trim(), | ||
inclStr.toString().trim(), | ||
].concat(compiledMessageFormat) | ||
.concat(['})();']); | ||
return callback(null, _.flatten(fileData)); | ||
}); | ||
// Read each file, compile them, and append the result in the `compiledI18n` array | ||
function readFile(file, cb){ | ||
var path = join(inputdir, file); | ||
fs.stat(path, function(err, stat){ | ||
if(err) { handleError(err); return cb(); } | ||
if(!stat.isFile()) { | ||
if( options.verbose ) { handleError('Skip ' + file); } | ||
return cb(); | ||
} | ||
fs.readFile(path, 'utf8', function(err, text){ | ||
if(err) { handleError(err); return cb() } | ||
var nm = join(file).split('.')[0].replace(/\\/g, '/'); // windows users should have the same key. | ||
if(options.combine !== undefined) { | ||
nm = options.combine; | ||
if( options.verbose ) console.log('Adding to ' + options.namespace + '["' + nm + '"]'); | ||
} | ||
else { | ||
if( options.verbose ) console.log('Building ' + options.namespace + '["' + nm + '"]'); | ||
} | ||
compiledMessageFormat.push(compiler( options, nm, JSON.parse(text) )); | ||
cb(); | ||
}); | ||
}); | ||
} | ||
}); | ||
}); | ||
if (options.watch) { | ||
_log('watching for changes in ' + options.inputdir + '...\n'); | ||
require('watchr').watch({ | ||
path: options.inputdir, | ||
ignorePaths: [ options.output ], | ||
listener: function(changeType, filePath) { if (/\.json$/.test(filePath)) build(options, write); } | ||
}); | ||
} | ||
function compiler(options, nm, obj){ | ||
var mf = new MessageFormat(options.locale), | ||
cmf = [options.namespace + '["' + nm + '"] = {']; | ||
_(obj).forEach(function(value, key){ | ||
var str = mf.precompile( mf.parse(value) ); | ||
cmf.push('"' + key + '":' + str + ','); | ||
}); | ||
cmf[cmf.length-1] = cmf[cmf.length-1].replace(/,$/, '}'); | ||
return cmf; | ||
} |
@@ -1,16 +0,13 @@ | ||
(function(){ window.i18n || (window.i18n = {}) | ||
var MessageFormat = { locale: {} }; | ||
MessageFormat.locale.en=function(n){return n===1?"one":"other"} | ||
var | ||
c=function(d){if(!d)throw new Error("MessageFormat: No data passed to function.")}, | ||
n=function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: `"+k+"` isnt a number.");return d[k]-(o||0)}, | ||
v=function(d,k){c(d);return d[k]}, | ||
p=function(d,k,o,l,p){c(d);return p[d[k]]||p[MessageFormat.locale[l](d[k]-o)]||p.other}, | ||
s=function(d,k,p){c(d);return p[d[k]]||p.other}; | ||
window.i18n["colors"] = { | ||
(function(G){G['i18n']={lc:{"en":function(n){return n===1?"one":"other"}}, | ||
c:function(d,k){if(!d)throw new Error("MessageFormat: Data required for '"+k+"'.")}, | ||
n:function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: '"+k+"' isn't a number.");return d[k]-(o||0)}, | ||
v:function(d,k){i18n.c(d,k);return d[k]}, | ||
p:function(d,k,o,l,p){i18n.c(d,k);return d[k] in p?p[d[k]]:(k=i18n.lc[l](d[k]-o),k in p?p[k]:p.other)}, | ||
s:function(d,k,p){i18n.c(d,k);return d[k] in p?p[d[k]]:p.other}} | ||
i18n["colors"] = { | ||
"red":function(d){return "red"}, | ||
"blue":function(d){return "blue"}, | ||
"green":function(d){return "green"}} | ||
window.i18n["sub/folder/plural"] = { | ||
"test":function(d){return "Your "+p(d,"NUM",0,"en",{"one":"message","other":"messages"})+" go here."}} | ||
})(); | ||
i18n["sub/folder/plural"] = { | ||
"test":function(d){return "Your "+i18n.p(d,"NUM",0,"en",{"one":"message","other":"messages"})+" go here."}} | ||
})(this); |
@@ -1,16 +0,13 @@ | ||
(function(){ window.i18n || (window.i18n = {}) | ||
var MessageFormat = { locale: {} }; | ||
MessageFormat.locale.fr=function(n){return n===0||n==1?"one":"other"} | ||
var | ||
c=function(d){if(!d)throw new Error("MessageFormat: No data passed to function.")}, | ||
n=function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: `"+k+"` isnt a number.");return d[k]-(o||0)}, | ||
v=function(d,k){c(d);return d[k]}, | ||
p=function(d,k,o,l,p){c(d);return p[d[k]]||p[MessageFormat.locale[l](d[k]-o)]||p.other}, | ||
s=function(d,k,p){c(d);return p[d[k]]||p.other}; | ||
window.i18n["colors"] = { | ||
(function(G){G['i18n']={lc:{"fr":function(n){return n===0||n==1?"one":"other"}}, | ||
c:function(d,k){if(!d)throw new Error("MessageFormat: Data required for '"+k+"'.")}, | ||
n:function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: '"+k+"' isn't a number.");return d[k]-(o||0)}, | ||
v:function(d,k){i18n.c(d,k);return d[k]}, | ||
p:function(d,k,o,l,p){i18n.c(d,k);return d[k] in p?p[d[k]]:(k=i18n.lc[l](d[k]-o),k in p?p[k]:p.other)}, | ||
s:function(d,k,p){i18n.c(d,k);return d[k] in p?p[d[k]]:p.other}} | ||
i18n["colors"] = { | ||
"red":function(d){return "rouge"}, | ||
"blue":function(d){return "bleu"}, | ||
"green":function(d){return "vert"}} | ||
window.i18n["sub/folder/plural"] = { | ||
"test":function(d){return p(d,"NUM",0,"fr",{"one":"Votre message se trouve","other":"Vos messages se trouvent"})+" ici."}} | ||
})(); | ||
i18n["sub/folder/plural"] = { | ||
"test":function(d){return i18n.p(d,"NUM",0,"fr",{"one":"Votre message se trouve","other":"Vos messages se trouvent"})+" ici."}} | ||
})(this); |
@@ -5,121 +5,72 @@ /** | ||
* ICU PluralFormat + SelectFormat for JavaScript | ||
* | ||
* Copyright 2014 | ||
* | ||
* 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 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* @author Alex Sexton - @SlexAxton | ||
* @version 0.1.7 | ||
* @license WTFPL | ||
* @contributor_license Dojo CLA | ||
*/ | ||
*/ | ||
(function ( root ) { | ||
// Create the contructor function | ||
function MessageFormat ( locale, pluralFunc ) { | ||
var fallbackLocale; | ||
if ( locale && pluralFunc ) { | ||
MessageFormat.locale[ locale ] = pluralFunc; | ||
function MessageFormat ( locale, pluralFunc, globalName ) { | ||
var lc = locale || 'en', lcFile; | ||
if ( pluralFunc ) { | ||
MessageFormat.locale[lc] = pluralFunc; | ||
} else { | ||
while ( lc && ! MessageFormat.locale.hasOwnProperty( lc ) ) { | ||
lc = lc.replace(/[-_]?[^-_]*$/, ''); | ||
} | ||
if ( ! lc ) { | ||
lc = locale.replace(/[-_].*$/, ''); | ||
MessageFormat.loadLocale(lc); | ||
} | ||
} | ||
// Defaults | ||
fallbackLocale = locale = locale || "en"; | ||
pluralFunc = pluralFunc || MessageFormat.locale[ fallbackLocale = MessageFormat.Utils.getFallbackLocale( locale ) ]; | ||
if ( ! pluralFunc ) { | ||
throw new Error( "Plural Function not found for locale: " + locale ); | ||
} | ||
// Own Properties | ||
this.pluralFunc = pluralFunc; | ||
this.locale = locale; | ||
this.fallbackLocale = fallbackLocale; | ||
this.lc = lc; // used in 'elementFormat' | ||
this.globalName = globalName || 'i18n'; | ||
} | ||
// methods in common with the generated MessageFormat | ||
// check d | ||
c=function(d){ | ||
if(!d){throw new Error("MessageFormat: No data passed to function.")} | ||
} | ||
// require number | ||
n=function(d,k,o){ | ||
if(isNaN(d[k])){throw new Error("MessageFormat: `"+k+"` isnt a number.")} | ||
return d[k] - (o || 0); | ||
} | ||
// value | ||
v=function(d,k){ | ||
c(d); | ||
return d[k]; | ||
} | ||
// plural | ||
p=function(d,k,o,l,p){ | ||
c(d); | ||
return d[k] in p ? p[d[k]] : (k = MessageFormat.locale[l](d[k]-o), k in p ? p[k] : p.other); | ||
} | ||
// select | ||
s=function(d,k,p){ | ||
c(d); | ||
return d[k] in p ? p[d[k]] : p.other; | ||
} | ||
if ( !('locale' in MessageFormat) ) MessageFormat.locale = {}; | ||
// Set up the locales object. Add in english by default | ||
MessageFormat.locale = { | ||
"en" : function ( n ) { | ||
if ( n === 1 ) { | ||
return "one"; | ||
MessageFormat.loadLocale = function ( lc ) { | ||
try { | ||
var lcFile = require('path').join(__dirname, 'locale', lc + '.js'), | ||
lcStr = ('' + require('fs').readFileSync(lcFile)).match(/{[^]*}/); | ||
if (!lcStr) throw "no function found in file '" + lcFile + "'"; | ||
MessageFormat.locale[lc] = 'function(n)' + lcStr; | ||
} catch (ex) { | ||
if ( lc == 'en' ) { | ||
MessageFormat.locale[lc] = 'function(n){return n===1?"one":"other"}'; | ||
} else { | ||
ex.message = 'Locale ' + lc + ' could not be loaded: ' + ex.message; | ||
throw ex; | ||
} | ||
return "other"; | ||
} | ||
}; | ||
// Build out our basic SafeString type | ||
// more or less stolen from Handlebars by @wycats | ||
MessageFormat.SafeString = function( string ) { | ||
this.string = string; | ||
}; | ||
MessageFormat.SafeString.prototype.toString = function () { | ||
return this.string.toString(); | ||
}; | ||
MessageFormat.Utils = { | ||
numSub : function ( string, d, key, offset ) { | ||
// make sure that it's not an escaped octothorpe | ||
var s = string.replace( /(^|[^\\])#/g, '$1"+n(' + d + ',' + key + (offset ? ',' + offset : '') + ')+"' ); | ||
return s.replace( /^""\+/, '' ).replace( /\+""$/, '' ); | ||
}, | ||
escapeExpression : function (string) { | ||
var escape = { | ||
"\n": "\\n", | ||
"\"": '\\"' | ||
}, | ||
badChars = /[\n"]/g, | ||
possible = /[\n"]/, | ||
escapeChar = function(chr) { | ||
return escape[chr] || "&"; | ||
}; | ||
// Don't escape SafeStrings, since they're already safe | ||
if ( string instanceof MessageFormat.SafeString ) { | ||
return string.toString(); | ||
MessageFormat.prototype.functions = function () { | ||
var l = []; | ||
for ( var lc in MessageFormat.locale ) { | ||
if ( MessageFormat.locale.hasOwnProperty(lc) ) { | ||
l.push(JSON.stringify(lc) + ':' + MessageFormat.locale[lc].toString().trim()); | ||
} | ||
else if ( string === null || string === false ) { | ||
return ""; | ||
} | ||
if ( ! possible.test( string ) ) { | ||
return string; | ||
} | ||
return string.replace( badChars, escapeChar ); | ||
}, | ||
getFallbackLocale: function( locale ) { | ||
var tagSeparator = locale.indexOf("-") >= 0 ? "-" : "_"; | ||
// Lets just be friends, fallback through the language tags | ||
while ( ! MessageFormat.locale.hasOwnProperty( locale ) ) { | ||
locale = locale.substring(0, locale.lastIndexOf( tagSeparator )); | ||
if (locale.length === 0) { | ||
return null; | ||
} | ||
} | ||
return locale; | ||
} | ||
return '{lc:{' + l.join(',') + '},\n' | ||
+ 'c:function(d,k){if(!d)throw new Error("MessageFormat: Data required for \'"+k+"\'.")},\n' | ||
+ 'n:function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: \'"+k+"\' isn\'t a number.");return d[k]-(o||0)},\n' | ||
+ 'v:function(d,k){' + this.globalName + '.c(d,k);return d[k]},\n' | ||
+ 'p:function(d,k,o,l,p){' + this.globalName + '.c(d,k);return d[k] in p?p[d[k]]:(k=' + this.globalName + '.lc[l](d[k]-o),k in p?p[k]:p.other)},\n' | ||
+ 's:function(d,k,p){' + this.globalName + '.c(d,k);return d[k] in p?p[d[k]]:p.other}}'; | ||
}; | ||
@@ -165,3 +116,3 @@ | ||
if ( ast.output ) { | ||
return 'v(d,"' + ast.argumentIndex + '")'; | ||
return self.globalName + '.v(d,"' + ast.argumentIndex + '")'; | ||
} | ||
@@ -175,8 +126,8 @@ else { | ||
if ( ast.key === 'select' ) { | ||
return 's(d,' + data.keys[data.pf_count] + ',' + interpMFP( ast.val, data ) + ')'; | ||
return self.globalName + '.s(d,' + data.keys[data.pf_count] + ',' + interpMFP( ast.val, data ) + ')'; | ||
} | ||
else if ( ast.key === 'plural' ) { | ||
data.offset[data.pf_count || 0] = ast.val.offset || 0; | ||
return 'p(d,' + data.keys[data.pf_count] + ',' + (data.offset[data.pf_count] || 0) | ||
+ ',"' + self.fallbackLocale + '",' + interpMFP( ast.val, data ) + ')'; | ||
return self.globalName + '.p(d,' + data.keys[data.pf_count] + ',' + (data.offset[data.pf_count] || 0) | ||
+ ',"' + self.lc + '",' + interpMFP( ast.val, data ) + ')'; | ||
} | ||
@@ -222,5 +173,7 @@ return ''; | ||
case 'string': | ||
tmp = '"' + MessageFormat.Utils.escapeExpression( ast.val ) + '"'; | ||
tmp = '"' + (ast.val || "").replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"'; | ||
if ( data.pf_count ) { | ||
tmp = MessageFormat.Utils.numSub( tmp, 'd', data.keys[data.pf_count-1], data.offset[data.pf_count-1]); | ||
var o = data.offset[data.pf_count-1]; | ||
tmp = tmp.replace(/(^|[^\\])#/g, '$1"+' + self.globalName + '.n(d,' + data.keys[data.pf_count-1] + (o ? ',' + o : '') + ')+"'); | ||
tmp = tmp.replace(/^""\+/, '').replace(/\+""$/, ''); | ||
} | ||
@@ -236,11 +189,17 @@ return tmp; | ||
MessageFormat.prototype.compile = function ( message ) { | ||
return (new Function( 'MessageFormat', | ||
'return ' + | ||
this.precompile( | ||
this.parse( message ) | ||
) | ||
))(MessageFormat); | ||
return (new Function( | ||
'this[\'' + this.globalName + '\']=' + this.functions() + ';' + | ||
'return ' + this.precompile( this.parse( message )) | ||
))(); | ||
}; | ||
MessageFormat.prototype.precompileObject = function ( messages ) { | ||
var tmp = []; | ||
for (var key in messages) { | ||
tmp.push(JSON.stringify(key) + ':' + this.precompile(this.parse(messages[key]))); | ||
} | ||
return '{\n' + tmp.join(',\n') + '}'; | ||
}; | ||
if (typeof exports !== 'undefined') { | ||
@@ -247,0 +206,0 @@ if (typeof module !== 'undefined' && module.exports) { |
@@ -1,1 +0,3 @@ | ||
MessageFormat.locale.is=function(n){return n===1?"one":"other"} | ||
MessageFormat.locale.is = function(n) { | ||
return ((n%10) === 1 && (n%100) !== 11) ? 'one' : 'other'; | ||
}; |
@@ -1,1 +0,1 @@ | ||
MessageFormat.locale.tr=function(n){return "other"} | ||
MessageFormat.locale.tr=function(n){return n===1?"one":"other"} |
2407
messageformat.js
@@ -5,279 +5,113 @@ /** | ||
* ICU PluralFormat + SelectFormat for JavaScript | ||
* | ||
* Copyright 2014 | ||
* | ||
* 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 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* @author Alex Sexton - @SlexAxton | ||
* @version 0.1.7 | ||
* @license WTFPL | ||
* @contributor_license Dojo CLA | ||
*/ | ||
*/ | ||
(function ( root ) { | ||
// Create the contructor function | ||
function MessageFormat ( locale, pluralFunc ) { | ||
var fallbackLocale; | ||
if ( locale && pluralFunc ) { | ||
MessageFormat.locale[ locale ] = pluralFunc; | ||
function MessageFormat ( locale, pluralFunc, globalName ) { | ||
var lc = locale || 'en', lcFile; | ||
if ( pluralFunc ) { | ||
MessageFormat.locale[lc] = pluralFunc; | ||
} else { | ||
while ( lc && ! MessageFormat.locale.hasOwnProperty( lc ) ) { | ||
lc = lc.replace(/[-_]?[^-_]*$/, ''); | ||
} | ||
if ( ! lc ) { | ||
lc = locale.replace(/[-_].*$/, ''); | ||
MessageFormat.loadLocale(lc); | ||
} | ||
} | ||
// Defaults | ||
fallbackLocale = locale = locale || "en"; | ||
pluralFunc = pluralFunc || MessageFormat.locale[ fallbackLocale = MessageFormat.Utils.getFallbackLocale( locale ) ]; | ||
if ( ! pluralFunc ) { | ||
throw new Error( "Plural Function not found for locale: " + locale ); | ||
} | ||
// Own Properties | ||
this.pluralFunc = pluralFunc; | ||
this.locale = locale; | ||
this.fallbackLocale = fallbackLocale; | ||
this.lc = lc; // used in 'elementFormat' | ||
this.globalName = globalName || 'i18n'; | ||
} | ||
// methods in common with the generated MessageFormat | ||
// check d | ||
c=function(d){ | ||
if(!d){throw new Error("MessageFormat: No data passed to function.")} | ||
} | ||
// require number | ||
n=function(d,k,o){ | ||
if(isNaN(d[k])){throw new Error("MessageFormat: `"+k+"` isnt a number.")} | ||
return d[k] - (o || 0); | ||
} | ||
// value | ||
v=function(d,k){ | ||
c(d); | ||
return d[k]; | ||
} | ||
// plural | ||
p=function(d,k,o,l,p){ | ||
c(d); | ||
return d[k] in p ? p[d[k]] : (k = MessageFormat.locale[l](d[k]-o), k in p ? p[k] : p.other); | ||
} | ||
// select | ||
s=function(d,k,p){ | ||
c(d); | ||
return d[k] in p ? p[d[k]] : p.other; | ||
} | ||
if ( !('locale' in MessageFormat) ) MessageFormat.locale = {}; | ||
// Set up the locales object. Add in english by default | ||
MessageFormat.locale = { | ||
"en" : function ( n ) { | ||
if ( n === 1 ) { | ||
return "one"; | ||
MessageFormat.loadLocale = function ( lc ) { | ||
try { | ||
var lcFile = require('path').join(__dirname, 'locale', lc + '.js'), | ||
lcStr = ('' + require('fs').readFileSync(lcFile)).match(/{[^]*}/); | ||
if (!lcStr) throw "no function found in file '" + lcFile + "'"; | ||
MessageFormat.locale[lc] = 'function(n)' + lcStr; | ||
} catch (ex) { | ||
if ( lc == 'en' ) { | ||
MessageFormat.locale[lc] = 'function(n){return n===1?"one":"other"}'; | ||
} else { | ||
ex.message = 'Locale ' + lc + ' could not be loaded: ' + ex.message; | ||
throw ex; | ||
} | ||
return "other"; | ||
} | ||
}; | ||
// Build out our basic SafeString type | ||
// more or less stolen from Handlebars by @wycats | ||
MessageFormat.SafeString = function( string ) { | ||
this.string = string; | ||
}; | ||
MessageFormat.SafeString.prototype.toString = function () { | ||
return this.string.toString(); | ||
}; | ||
MessageFormat.Utils = { | ||
numSub : function ( string, d, key, offset ) { | ||
// make sure that it's not an escaped octothorpe | ||
var s = string.replace( /(^|[^\\])#/g, '$1"+n(' + d + ',' + key + (offset ? ',' + offset : '') + ')+"' ); | ||
return s.replace( /^""\+/, '' ).replace( /\+""$/, '' ); | ||
}, | ||
escapeExpression : function (string) { | ||
var escape = { | ||
"\n": "\\n", | ||
"\"": '\\"' | ||
}, | ||
badChars = /[\n"]/g, | ||
possible = /[\n"]/, | ||
escapeChar = function(chr) { | ||
return escape[chr] || "&"; | ||
}; | ||
// Don't escape SafeStrings, since they're already safe | ||
if ( string instanceof MessageFormat.SafeString ) { | ||
return string.toString(); | ||
MessageFormat.prototype.functions = function () { | ||
var l = []; | ||
for ( var lc in MessageFormat.locale ) { | ||
if ( MessageFormat.locale.hasOwnProperty(lc) ) { | ||
l.push(JSON.stringify(lc) + ':' + MessageFormat.locale[lc].toString().trim()); | ||
} | ||
else if ( string === null || string === false ) { | ||
return ""; | ||
} | ||
if ( ! possible.test( string ) ) { | ||
return string; | ||
} | ||
return string.replace( badChars, escapeChar ); | ||
}, | ||
getFallbackLocale: function( locale ) { | ||
var tagSeparator = locale.indexOf("-") >= 0 ? "-" : "_"; | ||
// Lets just be friends, fallback through the language tags | ||
while ( ! MessageFormat.locale.hasOwnProperty( locale ) ) { | ||
locale = locale.substring(0, locale.lastIndexOf( tagSeparator )); | ||
if (locale.length === 0) { | ||
return null; | ||
} | ||
} | ||
return locale; | ||
} | ||
return '{lc:{' + l.join(',') + '},\n' | ||
+ 'c:function(d,k){if(!d)throw new Error("MessageFormat: Data required for \'"+k+"\'.")},\n' | ||
+ 'n:function(d,k,o){if(isNaN(d[k]))throw new Error("MessageFormat: \'"+k+"\' isn\'t a number.");return d[k]-(o||0)},\n' | ||
+ 'v:function(d,k){' + this.globalName + '.c(d,k);return d[k]},\n' | ||
+ 'p:function(d,k,o,l,p){' + this.globalName + '.c(d,k);return d[k] in p?p[d[k]]:(k=' + this.globalName + '.lc[l](d[k]-o),k in p?p[k]:p.other)},\n' | ||
+ 's:function(d,k,p){' + this.globalName + '.c(d,k);return d[k] in p?p[d[k]]:p.other}}'; | ||
}; | ||
// This is generated and pulled in for browsers. | ||
var mparser = (function(){ | ||
var mparser = (function() { | ||
/* | ||
* Generated by PEG.js 0.7.0. | ||
* Generated by PEG.js 0.8.0. | ||
* | ||
* http://pegjs.majda.cz/ | ||
*/ | ||
function quote(s) { | ||
/* | ||
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a | ||
* string literal except for the closing quote character, backslash, | ||
* carriage return, line separator, paragraph separator, and line feed. | ||
* Any character may appear in the form of an escape sequence. | ||
* | ||
* For portability, we also escape escape all control and non-ASCII | ||
* characters. Note that "\0" and "\v" escape sequences are not used | ||
* because JSHint does not like the first and IE the second. | ||
*/ | ||
return '"' + s | ||
.replace(/\\/g, '\\\\') // backslash | ||
.replace(/"/g, '\\"') // closing quote character | ||
.replace(/\x08/g, '\\b') // backspace | ||
.replace(/\t/g, '\\t') // horizontal tab | ||
.replace(/\n/g, '\\n') // line feed | ||
.replace(/\f/g, '\\f') // form feed | ||
.replace(/\r/g, '\\r') // carriage return | ||
.replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape) | ||
+ '"'; | ||
function peg$subclass(child, parent) { | ||
function ctor() { this.constructor = child; } | ||
ctor.prototype = parent.prototype; | ||
child.prototype = new ctor(); | ||
} | ||
var result = { | ||
/* | ||
* Parses the input with a generated parser. If the parsing is successfull, | ||
* returns a value explicitly or implicitly specified by the grammar from | ||
* which the parser was generated (see |PEG.buildParser|). If the parsing is | ||
* unsuccessful, throws |PEG.parser.SyntaxError| describing the error. | ||
*/ | ||
parse: function(input, startRule) { | ||
var parseFunctions = { | ||
"start": parse_start, | ||
"messageFormatPattern": parse_messageFormatPattern, | ||
"messageFormatPatternRight": parse_messageFormatPatternRight, | ||
"messageFormatElement": parse_messageFormatElement, | ||
"elementFormat": parse_elementFormat, | ||
"pluralStyle": parse_pluralStyle, | ||
"selectStyle": parse_selectStyle, | ||
"pluralFormatPattern": parse_pluralFormatPattern, | ||
"offsetPattern": parse_offsetPattern, | ||
"selectFormatPattern": parse_selectFormatPattern, | ||
"pluralForms": parse_pluralForms, | ||
"stringKey": parse_stringKey, | ||
"string": parse_string, | ||
"id": parse_id, | ||
"chars": parse_chars, | ||
"char": parse_char, | ||
"digits": parse_digits, | ||
"hexDigit": parse_hexDigit, | ||
"_": parse__, | ||
"whitespace": parse_whitespace | ||
}; | ||
if (startRule !== undefined) { | ||
if (parseFunctions[startRule] === undefined) { | ||
throw new Error("Invalid rule name: " + quote(startRule) + "."); | ||
} | ||
} else { | ||
startRule = "start"; | ||
} | ||
var pos = 0; | ||
var reportFailures = 0; | ||
var rightmostFailuresPos = 0; | ||
var rightmostFailuresExpected = []; | ||
function padLeft(input, padding, length) { | ||
var result = input; | ||
var padLength = length - input.length; | ||
for (var i = 0; i < padLength; i++) { | ||
result = padding + result; | ||
} | ||
return result; | ||
} | ||
function escape(ch) { | ||
var charCode = ch.charCodeAt(0); | ||
var escapeChar; | ||
var length; | ||
if (charCode <= 0xFF) { | ||
escapeChar = 'x'; | ||
length = 2; | ||
} else { | ||
escapeChar = 'u'; | ||
length = 4; | ||
} | ||
return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length); | ||
} | ||
function matchFailed(failure) { | ||
if (pos < rightmostFailuresPos) { | ||
return; | ||
} | ||
if (pos > rightmostFailuresPos) { | ||
rightmostFailuresPos = pos; | ||
rightmostFailuresExpected = []; | ||
} | ||
rightmostFailuresExpected.push(failure); | ||
} | ||
function parse_start() { | ||
var result0; | ||
var pos0; | ||
pos0 = pos; | ||
result0 = parse_messageFormatPattern(); | ||
if (result0 !== null) { | ||
result0 = (function(offset, messageFormatPattern) { return { type: "program", program: messageFormatPattern }; })(pos0, result0); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} | ||
function parse_messageFormatPattern() { | ||
var result0, result1, result2; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse_string(); | ||
if (result0 !== null) { | ||
result1 = []; | ||
result2 = parse_messageFormatPatternRight(); | ||
while (result2 !== null) { | ||
result1.push(result2); | ||
result2 = parse_messageFormatPatternRight(); | ||
} | ||
if (result1 !== null) { | ||
result0 = [result0, result1]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, s1, inner) { | ||
function SyntaxError(message, expected, found, offset, line, column) { | ||
this.message = message; | ||
this.expected = expected; | ||
this.found = found; | ||
this.offset = offset; | ||
this.line = line; | ||
this.column = column; | ||
this.name = "SyntaxError"; | ||
} | ||
peg$subclass(SyntaxError, Error); | ||
function parse(input) { | ||
var options = arguments.length > 1 ? arguments[1] : {}, | ||
peg$FAILED = {}, | ||
peg$startRuleFunctions = { start: peg$parsestart }, | ||
peg$startRuleFunction = peg$parsestart, | ||
peg$c0 = function(messageFormatPattern) { return { type: "program", program: messageFormatPattern }; }, | ||
peg$c1 = peg$FAILED, | ||
peg$c2 = [], | ||
peg$c3 = function(s1, inner) { | ||
var st = []; | ||
@@ -293,71 +127,8 @@ if ( s1 && s1.val ) { | ||
return { type: 'messageFormatPattern', statements: st }; | ||
})(pos0, result0[0], result0[1]); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} | ||
function parse_messageFormatPatternRight() { | ||
var result0, result1, result2, result3, result4, result5; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
pos1 = pos; | ||
if (input.charCodeAt(pos) === 123) { | ||
result0 = "{"; | ||
pos++; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"{\""); | ||
} | ||
} | ||
if (result0 !== null) { | ||
result1 = parse__(); | ||
if (result1 !== null) { | ||
result2 = parse_messageFormatElement(); | ||
if (result2 !== null) { | ||
result3 = parse__(); | ||
if (result3 !== null) { | ||
if (input.charCodeAt(pos) === 125) { | ||
result4 = "}"; | ||
pos++; | ||
} else { | ||
result4 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"}\""); | ||
} | ||
} | ||
if (result4 !== null) { | ||
result5 = parse_string(); | ||
if (result5 !== null) { | ||
result0 = [result0, result1, result2, result3, result4, result5]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, mfe, s1) { | ||
}, | ||
peg$c4 = "{", | ||
peg$c5 = { type: "literal", value: "{", description: "\"{\"" }, | ||
peg$c6 = "}", | ||
peg$c7 = { type: "literal", value: "}", description: "\"}\"" }, | ||
peg$c8 = function(mfe, s1) { | ||
var res = []; | ||
@@ -371,53 +142,7 @@ if ( mfe ) { | ||
return { type: "messageFormatPatternRight", statements : res }; | ||
})(pos0, result0[2], result0[5]); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} | ||
function parse_messageFormatElement() { | ||
var result0, result1, result2; | ||
var pos0, pos1, pos2; | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse_id(); | ||
if (result0 !== null) { | ||
pos2 = pos; | ||
if (input.charCodeAt(pos) === 44) { | ||
result1 = ","; | ||
pos++; | ||
} else { | ||
result1 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\",\""); | ||
} | ||
} | ||
if (result1 !== null) { | ||
result2 = parse_elementFormat(); | ||
if (result2 !== null) { | ||
result1 = [result1, result2]; | ||
} else { | ||
result1 = null; | ||
pos = pos2; | ||
} | ||
} else { | ||
result1 = null; | ||
pos = pos2; | ||
} | ||
result1 = result1 !== null ? result1 : ""; | ||
if (result1 !== null) { | ||
result0 = [result0, result1]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, argIdx, efmt) { | ||
}, | ||
peg$c9 = null, | ||
peg$c10 = ",", | ||
peg$c11 = { type: "literal", value: ",", description: "\",\"" }, | ||
peg$c12 = function(argIdx, efmt) { | ||
var res = { | ||
@@ -434,788 +159,1052 @@ type: "messageFormatElement", | ||
return res; | ||
})(pos0, result0[0], result0[1]); | ||
}, | ||
peg$c13 = "plural", | ||
peg$c14 = { type: "literal", value: "plural", description: "\"plural\"" }, | ||
peg$c15 = function(t, s) { | ||
return { | ||
type : "elementFormat", | ||
key : t, | ||
val : s.val | ||
}; | ||
}, | ||
peg$c16 = "select", | ||
peg$c17 = { type: "literal", value: "select", description: "\"select\"" }, | ||
peg$c18 = function(pfp) { | ||
return { type: "pluralStyle", val: pfp }; | ||
}, | ||
peg$c19 = function(sfp) { | ||
return { type: "selectStyle", val: sfp }; | ||
}, | ||
peg$c20 = function(op, pf) { | ||
var res = { | ||
type: "pluralFormatPattern", | ||
pluralForms: pf | ||
}; | ||
if ( op ) { | ||
res.offset = op; | ||
} | ||
else { | ||
res.offset = 0; | ||
} | ||
return res; | ||
}, | ||
peg$c21 = "offset", | ||
peg$c22 = { type: "literal", value: "offset", description: "\"offset\"" }, | ||
peg$c23 = ":", | ||
peg$c24 = { type: "literal", value: ":", description: "\":\"" }, | ||
peg$c25 = function(d) { | ||
return d; | ||
}, | ||
peg$c26 = function(pf) { | ||
return { | ||
type: "selectFormatPattern", | ||
pluralForms: pf | ||
}; | ||
}, | ||
peg$c27 = function(k, mfp) { | ||
return { | ||
type: "pluralForms", | ||
key: k, | ||
val: mfp | ||
}; | ||
}, | ||
peg$c28 = function(i) { | ||
return i; | ||
}, | ||
peg$c29 = "=", | ||
peg$c30 = { type: "literal", value: "=", description: "\"=\"" }, | ||
peg$c31 = function(ws, s) { | ||
var tmp = []; | ||
for( var i = 0; i < s.length; ++i ) { | ||
for( var j = 0; j < s[ i ].length; ++j ) { | ||
tmp.push(s[i][j]); | ||
} | ||
} | ||
return { | ||
type: "string", | ||
val: ws + tmp.join('') | ||
}; | ||
}, | ||
peg$c32 = /^[0-9a-zA-Z$_]/, | ||
peg$c33 = { type: "class", value: "[0-9a-zA-Z$_]", description: "[0-9a-zA-Z$_]" }, | ||
peg$c34 = /^[^ \t\n\r,.+={}]/, | ||
peg$c35 = { type: "class", value: "[^ \\t\\n\\r,.+={}]", description: "[^ \\t\\n\\r,.+={}]" }, | ||
peg$c36 = function(s1, s2) { | ||
return s1 + (s2 ? s2.join('') : ''); | ||
}, | ||
peg$c37 = function(chars) { return chars.join(''); }, | ||
peg$c38 = /^[^{}\\\0-\x1F \t\n\r]/, | ||
peg$c39 = { type: "class", value: "[^{}\\\\\\0-\\x1F \\t\\n\\r]", description: "[^{}\\\\\\0-\\x1F \\t\\n\\r]" }, | ||
peg$c40 = function(x) { | ||
return x; | ||
}, | ||
peg$c41 = "\\#", | ||
peg$c42 = { type: "literal", value: "\\#", description: "\"\\\\#\"" }, | ||
peg$c43 = function() { | ||
return "\\#"; | ||
}, | ||
peg$c44 = "\\{", | ||
peg$c45 = { type: "literal", value: "\\{", description: "\"\\\\{\"" }, | ||
peg$c46 = function() { | ||
return "\u007B"; | ||
}, | ||
peg$c47 = "\\}", | ||
peg$c48 = { type: "literal", value: "\\}", description: "\"\\\\}\"" }, | ||
peg$c49 = function() { | ||
return "\u007D"; | ||
}, | ||
peg$c50 = "\\u", | ||
peg$c51 = { type: "literal", value: "\\u", description: "\"\\\\u\"" }, | ||
peg$c52 = function(h1, h2, h3, h4) { | ||
return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); | ||
}, | ||
peg$c53 = /^[0-9]/, | ||
peg$c54 = { type: "class", value: "[0-9]", description: "[0-9]" }, | ||
peg$c55 = function(ds) { | ||
return parseInt((ds.join('')), 10); | ||
}, | ||
peg$c56 = /^[0-9a-fA-F]/, | ||
peg$c57 = { type: "class", value: "[0-9a-fA-F]", description: "[0-9a-fA-F]" }, | ||
peg$c58 = { type: "other", description: "whitespace" }, | ||
peg$c59 = function(w) { return w.join(''); }, | ||
peg$c60 = /^[ \t\n\r]/, | ||
peg$c61 = { type: "class", value: "[ \\t\\n\\r]", description: "[ \\t\\n\\r]" }, | ||
peg$currPos = 0, | ||
peg$reportedPos = 0, | ||
peg$cachedPos = 0, | ||
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, | ||
peg$maxFailPos = 0, | ||
peg$maxFailExpected = [], | ||
peg$silentFails = 0, | ||
peg$result; | ||
if ("startRule" in options) { | ||
if (!(options.startRule in peg$startRuleFunctions)) { | ||
throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); | ||
} | ||
peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; | ||
} | ||
function text() { | ||
return input.substring(peg$reportedPos, peg$currPos); | ||
} | ||
function offset() { | ||
return peg$reportedPos; | ||
} | ||
function line() { | ||
return peg$computePosDetails(peg$reportedPos).line; | ||
} | ||
function column() { | ||
return peg$computePosDetails(peg$reportedPos).column; | ||
} | ||
function expected(description) { | ||
throw peg$buildException( | ||
null, | ||
[{ type: "other", description: description }], | ||
peg$reportedPos | ||
); | ||
} | ||
function error(message) { | ||
throw peg$buildException(message, null, peg$reportedPos); | ||
} | ||
function peg$computePosDetails(pos) { | ||
function advance(details, startPos, endPos) { | ||
var p, ch; | ||
for (p = startPos; p < endPos; p++) { | ||
ch = input.charAt(p); | ||
if (ch === "\n") { | ||
if (!details.seenCR) { details.line++; } | ||
details.column = 1; | ||
details.seenCR = false; | ||
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { | ||
details.line++; | ||
details.column = 1; | ||
details.seenCR = true; | ||
} else { | ||
details.column++; | ||
details.seenCR = false; | ||
} | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
if (peg$cachedPos !== pos) { | ||
if (peg$cachedPos > pos) { | ||
peg$cachedPos = 0; | ||
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }; | ||
} | ||
return result0; | ||
advance(peg$cachedPosDetails, peg$cachedPos, pos); | ||
peg$cachedPos = pos; | ||
} | ||
function parse_elementFormat() { | ||
var result0, result1, result2, result3, result4, result5, result6; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse__(); | ||
if (result0 !== null) { | ||
if (input.substr(pos, 6) === "plural") { | ||
result1 = "plural"; | ||
pos += 6; | ||
return peg$cachedPosDetails; | ||
} | ||
function peg$fail(expected) { | ||
if (peg$currPos < peg$maxFailPos) { return; } | ||
if (peg$currPos > peg$maxFailPos) { | ||
peg$maxFailPos = peg$currPos; | ||
peg$maxFailExpected = []; | ||
} | ||
peg$maxFailExpected.push(expected); | ||
} | ||
function peg$buildException(message, expected, pos) { | ||
function cleanupExpected(expected) { | ||
var i = 1; | ||
expected.sort(function(a, b) { | ||
if (a.description < b.description) { | ||
return -1; | ||
} else if (a.description > b.description) { | ||
return 1; | ||
} else { | ||
result1 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"plural\""); | ||
} | ||
return 0; | ||
} | ||
if (result1 !== null) { | ||
result2 = parse__(); | ||
if (result2 !== null) { | ||
if (input.charCodeAt(pos) === 44) { | ||
result3 = ","; | ||
pos++; | ||
}); | ||
while (i < expected.length) { | ||
if (expected[i - 1] === expected[i]) { | ||
expected.splice(i, 1); | ||
} else { | ||
i++; | ||
} | ||
} | ||
} | ||
function buildMessage(expected, found) { | ||
function stringEscape(s) { | ||
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } | ||
return s | ||
.replace(/\\/g, '\\\\') | ||
.replace(/"/g, '\\"') | ||
.replace(/\x08/g, '\\b') | ||
.replace(/\t/g, '\\t') | ||
.replace(/\n/g, '\\n') | ||
.replace(/\f/g, '\\f') | ||
.replace(/\r/g, '\\r') | ||
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) | ||
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) | ||
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) | ||
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); | ||
} | ||
var expectedDescs = new Array(expected.length), | ||
expectedDesc, foundDesc, i; | ||
for (i = 0; i < expected.length; i++) { | ||
expectedDescs[i] = expected[i].description; | ||
} | ||
expectedDesc = expected.length > 1 | ||
? expectedDescs.slice(0, -1).join(", ") | ||
+ " or " | ||
+ expectedDescs[expected.length - 1] | ||
: expectedDescs[0]; | ||
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; | ||
return "Expected " + expectedDesc + " but " + foundDesc + " found."; | ||
} | ||
var posDetails = peg$computePosDetails(pos), | ||
found = pos < input.length ? input.charAt(pos) : null; | ||
if (expected !== null) { | ||
cleanupExpected(expected); | ||
} | ||
return new SyntaxError( | ||
message !== null ? message : buildMessage(expected, found), | ||
expected, | ||
found, | ||
pos, | ||
posDetails.line, | ||
posDetails.column | ||
); | ||
} | ||
function peg$parsestart() { | ||
var s0, s1; | ||
s0 = peg$currPos; | ||
s1 = peg$parsemessageFormatPattern(); | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c0(s1); | ||
} | ||
s0 = s1; | ||
return s0; | ||
} | ||
function peg$parsemessageFormatPattern() { | ||
var s0, s1, s2, s3; | ||
s0 = peg$currPos; | ||
s1 = peg$parsestring(); | ||
if (s1 !== peg$FAILED) { | ||
s2 = []; | ||
s3 = peg$parsemessageFormatPatternRight(); | ||
while (s3 !== peg$FAILED) { | ||
s2.push(s3); | ||
s3 = peg$parsemessageFormatPatternRight(); | ||
} | ||
if (s2 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c3(s1, s2); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
return s0; | ||
} | ||
function peg$parsemessageFormatPatternRight() { | ||
var s0, s1, s2, s3, s4, s5, s6; | ||
s0 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 123) { | ||
s1 = peg$c4; | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c5); } | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$parse_(); | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parsemessageFormatElement(); | ||
if (s3 !== peg$FAILED) { | ||
s4 = peg$parse_(); | ||
if (s4 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 125) { | ||
s5 = peg$c6; | ||
peg$currPos++; | ||
} else { | ||
result3 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\",\""); | ||
} | ||
s5 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c7); } | ||
} | ||
if (result3 !== null) { | ||
result4 = parse__(); | ||
if (result4 !== null) { | ||
result5 = parse_pluralStyle(); | ||
if (result5 !== null) { | ||
result6 = parse__(); | ||
if (result6 !== null) { | ||
result0 = [result0, result1, result2, result3, result4, result5, result6]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
if (s5 !== peg$FAILED) { | ||
s6 = peg$parsestring(); | ||
if (s6 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c8(s3, s6); | ||
s0 = s1; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, t, s) { | ||
return { | ||
type : "elementFormat", | ||
key : t, | ||
val : s.val | ||
}; | ||
})(pos0, result0[1], result0[5]); | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
return s0; | ||
} | ||
function peg$parsemessageFormatElement() { | ||
var s0, s1, s2, s3, s4; | ||
s0 = peg$currPos; | ||
s1 = peg$parseid(); | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 44) { | ||
s3 = peg$c10; | ||
peg$currPos++; | ||
} else { | ||
s3 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c11); } | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
if (s3 !== peg$FAILED) { | ||
s4 = peg$parseelementFormat(); | ||
if (s4 !== peg$FAILED) { | ||
s3 = [s3, s4]; | ||
s2 = s3; | ||
} else { | ||
peg$currPos = s2; | ||
s2 = peg$c1; | ||
} | ||
} else { | ||
peg$currPos = s2; | ||
s2 = peg$c1; | ||
} | ||
if (result0 === null) { | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse__(); | ||
if (result0 !== null) { | ||
if (input.substr(pos, 6) === "select") { | ||
result1 = "select"; | ||
pos += 6; | ||
if (s2 === peg$FAILED) { | ||
s2 = peg$c9; | ||
} | ||
if (s2 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c12(s1, s2); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
return s0; | ||
} | ||
function peg$parseelementFormat() { | ||
var s0, s1, s2, s3, s4, s5, s6, s7; | ||
s0 = peg$currPos; | ||
s1 = peg$parse_(); | ||
if (s1 !== peg$FAILED) { | ||
if (input.substr(peg$currPos, 6) === peg$c13) { | ||
s2 = peg$c13; | ||
peg$currPos += 6; | ||
} else { | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c14); } | ||
} | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parse_(); | ||
if (s3 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 44) { | ||
s4 = peg$c10; | ||
peg$currPos++; | ||
} else { | ||
result1 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"select\""); | ||
} | ||
s4 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c11); } | ||
} | ||
if (result1 !== null) { | ||
result2 = parse__(); | ||
if (result2 !== null) { | ||
if (input.charCodeAt(pos) === 44) { | ||
result3 = ","; | ||
pos++; | ||
} else { | ||
result3 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\",\""); | ||
} | ||
} | ||
if (result3 !== null) { | ||
result4 = parse__(); | ||
if (result4 !== null) { | ||
result5 = parse_selectStyle(); | ||
if (result5 !== null) { | ||
result6 = parse__(); | ||
if (result6 !== null) { | ||
result0 = [result0, result1, result2, result3, result4, result5, result6]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
if (s4 !== peg$FAILED) { | ||
s5 = peg$parse_(); | ||
if (s5 !== peg$FAILED) { | ||
s6 = peg$parsepluralStyle(); | ||
if (s6 !== peg$FAILED) { | ||
s7 = peg$parse_(); | ||
if (s7 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c15(s2, s6); | ||
s0 = s1; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, t, s) { | ||
return { | ||
type : "elementFormat", | ||
key : t, | ||
val : s.val | ||
}; | ||
})(pos0, result0[1], result0[5]); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
} | ||
return result0; | ||
} | ||
function parse_pluralStyle() { | ||
var result0; | ||
var pos0; | ||
pos0 = pos; | ||
result0 = parse_pluralFormatPattern(); | ||
if (result0 !== null) { | ||
result0 = (function(offset, pfp) { | ||
return { type: "pluralStyle", val: pfp }; | ||
})(pos0, result0); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} | ||
function parse_selectStyle() { | ||
var result0; | ||
var pos0; | ||
pos0 = pos; | ||
result0 = parse_selectFormatPattern(); | ||
if (result0 !== null) { | ||
result0 = (function(offset, sfp) { | ||
return { type: "selectStyle", val: sfp }; | ||
})(pos0, result0); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} | ||
function parse_pluralFormatPattern() { | ||
var result0, result1, result2; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse_offsetPattern(); | ||
result0 = result0 !== null ? result0 : ""; | ||
if (result0 !== null) { | ||
result1 = []; | ||
result2 = parse_pluralForms(); | ||
while (result2 !== null) { | ||
result1.push(result2); | ||
result2 = parse_pluralForms(); | ||
} | ||
if (result1 !== null) { | ||
result0 = [result0, result1]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, op, pf) { | ||
var res = { | ||
type: "pluralFormatPattern", | ||
pluralForms: pf | ||
}; | ||
if ( op ) { | ||
res.offset = op; | ||
} | ||
else { | ||
res.offset = 0; | ||
} | ||
return res; | ||
})(pos0, result0[0], result0[1]); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
function parse_offsetPattern() { | ||
var result0, result1, result2, result3, result4, result5, result6; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse__(); | ||
if (result0 !== null) { | ||
if (input.substr(pos, 6) === "offset") { | ||
result1 = "offset"; | ||
pos += 6; | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$currPos; | ||
s1 = peg$parse_(); | ||
if (s1 !== peg$FAILED) { | ||
if (input.substr(peg$currPos, 6) === peg$c16) { | ||
s2 = peg$c16; | ||
peg$currPos += 6; | ||
} else { | ||
result1 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"offset\""); | ||
} | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c17); } | ||
} | ||
if (result1 !== null) { | ||
result2 = parse__(); | ||
if (result2 !== null) { | ||
if (input.charCodeAt(pos) === 58) { | ||
result3 = ":"; | ||
pos++; | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parse_(); | ||
if (s3 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 44) { | ||
s4 = peg$c10; | ||
peg$currPos++; | ||
} else { | ||
result3 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\":\""); | ||
} | ||
s4 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c11); } | ||
} | ||
if (result3 !== null) { | ||
result4 = parse__(); | ||
if (result4 !== null) { | ||
result5 = parse_digits(); | ||
if (result5 !== null) { | ||
result6 = parse__(); | ||
if (result6 !== null) { | ||
result0 = [result0, result1, result2, result3, result4, result5, result6]; | ||
if (s4 !== peg$FAILED) { | ||
s5 = peg$parse_(); | ||
if (s5 !== peg$FAILED) { | ||
s6 = peg$parseselectStyle(); | ||
if (s6 !== peg$FAILED) { | ||
s7 = peg$parse_(); | ||
if (s7 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c15(s2, s6); | ||
s0 = s1; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, d) { | ||
return d; | ||
})(pos0, result0[5]); | ||
} | ||
return s0; | ||
} | ||
function peg$parsepluralStyle() { | ||
var s0, s1; | ||
s0 = peg$currPos; | ||
s1 = peg$parsepluralFormatPattern(); | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c18(s1); | ||
} | ||
s0 = s1; | ||
return s0; | ||
} | ||
function peg$parseselectStyle() { | ||
var s0, s1; | ||
s0 = peg$currPos; | ||
s1 = peg$parseselectFormatPattern(); | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c19(s1); | ||
} | ||
s0 = s1; | ||
return s0; | ||
} | ||
function peg$parsepluralFormatPattern() { | ||
var s0, s1, s2, s3; | ||
s0 = peg$currPos; | ||
s1 = peg$parseoffsetPattern(); | ||
if (s1 === peg$FAILED) { | ||
s1 = peg$c9; | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s2 = []; | ||
s3 = peg$parsepluralForms(); | ||
while (s3 !== peg$FAILED) { | ||
s2.push(s3); | ||
s3 = peg$parsepluralForms(); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
if (s2 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c20(s1, s2); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
return result0; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
function parse_selectFormatPattern() { | ||
var result0, result1; | ||
var pos0; | ||
pos0 = pos; | ||
result0 = []; | ||
result1 = parse_pluralForms(); | ||
while (result1 !== null) { | ||
result0.push(result1); | ||
result1 = parse_pluralForms(); | ||
return s0; | ||
} | ||
function peg$parseoffsetPattern() { | ||
var s0, s1, s2, s3, s4, s5, s6, s7; | ||
s0 = peg$currPos; | ||
s1 = peg$parse_(); | ||
if (s1 !== peg$FAILED) { | ||
if (input.substr(peg$currPos, 6) === peg$c21) { | ||
s2 = peg$c21; | ||
peg$currPos += 6; | ||
} else { | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c22); } | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, pf) { | ||
return { | ||
type: "selectFormatPattern", | ||
pluralForms: pf | ||
}; | ||
})(pos0, result0); | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parse_(); | ||
if (s3 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 58) { | ||
s4 = peg$c23; | ||
peg$currPos++; | ||
} else { | ||
s4 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c24); } | ||
} | ||
if (s4 !== peg$FAILED) { | ||
s5 = peg$parse_(); | ||
if (s5 !== peg$FAILED) { | ||
s6 = peg$parsedigits(); | ||
if (s6 !== peg$FAILED) { | ||
s7 = peg$parse_(); | ||
if (s7 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c25(s6); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
function parse_pluralForms() { | ||
var result0, result1, result2, result3, result4, result5, result6, result7; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse__(); | ||
if (result0 !== null) { | ||
result1 = parse_stringKey(); | ||
if (result1 !== null) { | ||
result2 = parse__(); | ||
if (result2 !== null) { | ||
if (input.charCodeAt(pos) === 123) { | ||
result3 = "{"; | ||
pos++; | ||
} else { | ||
result3 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"{\""); | ||
} | ||
} | ||
if (result3 !== null) { | ||
result4 = parse__(); | ||
if (result4 !== null) { | ||
result5 = parse_messageFormatPattern(); | ||
if (result5 !== null) { | ||
result6 = parse__(); | ||
if (result6 !== null) { | ||
if (input.charCodeAt(pos) === 125) { | ||
result7 = "}"; | ||
pos++; | ||
} else { | ||
result7 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"}\""); | ||
} | ||
} | ||
if (result7 !== null) { | ||
result0 = [result0, result1, result2, result3, result4, result5, result6, result7]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
return s0; | ||
} | ||
function peg$parseselectFormatPattern() { | ||
var s0, s1, s2; | ||
s0 = peg$currPos; | ||
s1 = []; | ||
s2 = peg$parsepluralForms(); | ||
while (s2 !== peg$FAILED) { | ||
s1.push(s2); | ||
s2 = peg$parsepluralForms(); | ||
} | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c26(s1); | ||
} | ||
s0 = s1; | ||
return s0; | ||
} | ||
function peg$parsepluralForms() { | ||
var s0, s1, s2, s3, s4, s5, s6, s7, s8; | ||
s0 = peg$currPos; | ||
s1 = peg$parse_(); | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$parsestringKey(); | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parse_(); | ||
if (s3 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 123) { | ||
s4 = peg$c4; | ||
peg$currPos++; | ||
} else { | ||
s4 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c5); } | ||
} | ||
if (s4 !== peg$FAILED) { | ||
s5 = peg$parse_(); | ||
if (s5 !== peg$FAILED) { | ||
s6 = peg$parsemessageFormatPattern(); | ||
if (s6 !== peg$FAILED) { | ||
s7 = peg$parse_(); | ||
if (s7 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 125) { | ||
s8 = peg$c6; | ||
peg$currPos++; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
s8 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c7); } | ||
} | ||
if (s8 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c27(s2, s6); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, k, mfp) { | ||
return { | ||
type: "pluralForms", | ||
key: k, | ||
val: mfp | ||
}; | ||
})(pos0, result0[1], result0[5]); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
function parse_stringKey() { | ||
var result0, result1; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
result0 = parse_id(); | ||
if (result0 !== null) { | ||
result0 = (function(offset, i) { | ||
return i; | ||
})(pos0, result0); | ||
return s0; | ||
} | ||
function peg$parsestringKey() { | ||
var s0, s1, s2; | ||
s0 = peg$currPos; | ||
s1 = peg$parseid(); | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c28(s1); | ||
} | ||
s0 = s1; | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 61) { | ||
s1 = peg$c29; | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c30); } | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
if (result0 === null) { | ||
pos0 = pos; | ||
pos1 = pos; | ||
if (input.charCodeAt(pos) === 61) { | ||
result0 = "="; | ||
pos++; | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$parsedigits(); | ||
if (s2 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c25(s2); | ||
s0 = s1; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"=\""); | ||
} | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result1 = parse_digits(); | ||
if (result1 !== null) { | ||
result0 = [result0, result1]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, d) { | ||
return d; | ||
})(pos0, result0[1]); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
return result0; | ||
} | ||
function parse_string() { | ||
var result0, result1, result2, result3, result4; | ||
var pos0, pos1, pos2; | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse__(); | ||
if (result0 !== null) { | ||
result1 = []; | ||
pos2 = pos; | ||
result2 = parse__(); | ||
if (result2 !== null) { | ||
result3 = parse_chars(); | ||
if (result3 !== null) { | ||
result4 = parse__(); | ||
if (result4 !== null) { | ||
result2 = [result2, result3, result4]; | ||
} else { | ||
result2 = null; | ||
pos = pos2; | ||
} | ||
return s0; | ||
} | ||
function peg$parsestring() { | ||
var s0, s1, s2, s3, s4, s5, s6; | ||
s0 = peg$currPos; | ||
s1 = peg$parse_(); | ||
if (s1 !== peg$FAILED) { | ||
s2 = []; | ||
s3 = peg$currPos; | ||
s4 = peg$parse_(); | ||
if (s4 !== peg$FAILED) { | ||
s5 = peg$parsechars(); | ||
if (s5 !== peg$FAILED) { | ||
s6 = peg$parse_(); | ||
if (s6 !== peg$FAILED) { | ||
s4 = [s4, s5, s6]; | ||
s3 = s4; | ||
} else { | ||
result2 = null; | ||
pos = pos2; | ||
peg$currPos = s3; | ||
s3 = peg$c1; | ||
} | ||
} else { | ||
result2 = null; | ||
pos = pos2; | ||
peg$currPos = s3; | ||
s3 = peg$c1; | ||
} | ||
while (result2 !== null) { | ||
result1.push(result2); | ||
pos2 = pos; | ||
result2 = parse__(); | ||
if (result2 !== null) { | ||
result3 = parse_chars(); | ||
if (result3 !== null) { | ||
result4 = parse__(); | ||
if (result4 !== null) { | ||
result2 = [result2, result3, result4]; | ||
} else { | ||
result2 = null; | ||
pos = pos2; | ||
} | ||
} else { | ||
peg$currPos = s3; | ||
s3 = peg$c1; | ||
} | ||
while (s3 !== peg$FAILED) { | ||
s2.push(s3); | ||
s3 = peg$currPos; | ||
s4 = peg$parse_(); | ||
if (s4 !== peg$FAILED) { | ||
s5 = peg$parsechars(); | ||
if (s5 !== peg$FAILED) { | ||
s6 = peg$parse_(); | ||
if (s6 !== peg$FAILED) { | ||
s4 = [s4, s5, s6]; | ||
s3 = s4; | ||
} else { | ||
result2 = null; | ||
pos = pos2; | ||
peg$currPos = s3; | ||
s3 = peg$c1; | ||
} | ||
} else { | ||
result2 = null; | ||
pos = pos2; | ||
peg$currPos = s3; | ||
s3 = peg$c1; | ||
} | ||
} | ||
if (result1 !== null) { | ||
result0 = [result0, result1]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s3; | ||
s3 = peg$c1; | ||
} | ||
} | ||
if (s2 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c31(s1, s2); | ||
s0 = s1; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, ws, s) { | ||
var tmp = []; | ||
for( var i = 0; i < s.length; ++i ) { | ||
for( var j = 0; j < s[ i ].length; ++j ) { | ||
tmp.push(s[i][j]); | ||
} | ||
} | ||
return { | ||
type: "string", | ||
val: ws + tmp.join('') | ||
}; | ||
})(pos0, result0[0], result0[1]); | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
return s0; | ||
} | ||
function peg$parseid() { | ||
var s0, s1, s2, s3, s4; | ||
s0 = peg$currPos; | ||
s1 = peg$parse_(); | ||
if (s1 !== peg$FAILED) { | ||
if (peg$c32.test(input.charAt(peg$currPos))) { | ||
s2 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c33); } | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} | ||
function parse_id() { | ||
var result0, result1, result2, result3; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
pos1 = pos; | ||
result0 = parse__(); | ||
if (result0 !== null) { | ||
if (/^[0-9a-zA-Z$_]/.test(input.charAt(pos))) { | ||
result1 = input.charAt(pos); | ||
pos++; | ||
if (s2 !== peg$FAILED) { | ||
s3 = []; | ||
if (peg$c34.test(input.charAt(peg$currPos))) { | ||
s4 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
result1 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("[0-9a-zA-Z$_]"); | ||
} | ||
s4 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c35); } | ||
} | ||
if (result1 !== null) { | ||
result2 = []; | ||
if (/^[^ \t\n\r,.+={}]/.test(input.charAt(pos))) { | ||
result3 = input.charAt(pos); | ||
pos++; | ||
while (s4 !== peg$FAILED) { | ||
s3.push(s4); | ||
if (peg$c34.test(input.charAt(peg$currPos))) { | ||
s4 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
result3 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("[^ \\t\\n\\r,.+={}]"); | ||
} | ||
s4 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c35); } | ||
} | ||
while (result3 !== null) { | ||
result2.push(result3); | ||
if (/^[^ \t\n\r,.+={}]/.test(input.charAt(pos))) { | ||
result3 = input.charAt(pos); | ||
pos++; | ||
} else { | ||
result3 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("[^ \\t\\n\\r,.+={}]"); | ||
} | ||
} | ||
} | ||
if (result2 !== null) { | ||
result3 = parse__(); | ||
if (result3 !== null) { | ||
result0 = [result0, result1, result2, result3]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
} | ||
if (s3 !== peg$FAILED) { | ||
s4 = peg$parse_(); | ||
if (s4 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c36(s2, s3); | ||
s0 = s1; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, s1, s2) { | ||
return s1 + (s2 ? s2.join('') : ''); | ||
})(pos0, result0[1], result0[2]); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
function parse_chars() { | ||
var result0, result1; | ||
var pos0; | ||
pos0 = pos; | ||
result1 = parse_char(); | ||
if (result1 !== null) { | ||
result0 = []; | ||
while (result1 !== null) { | ||
result0.push(result1); | ||
result1 = parse_char(); | ||
} | ||
} else { | ||
result0 = null; | ||
return s0; | ||
} | ||
function peg$parsechars() { | ||
var s0, s1, s2; | ||
s0 = peg$currPos; | ||
s1 = []; | ||
s2 = peg$parsechar(); | ||
if (s2 !== peg$FAILED) { | ||
while (s2 !== peg$FAILED) { | ||
s1.push(s2); | ||
s2 = peg$parsechar(); | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, chars) { return chars.join(''); })(pos0, result0); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
} else { | ||
s1 = peg$c1; | ||
} | ||
function parse_char() { | ||
var result0, result1, result2, result3, result4; | ||
var pos0, pos1; | ||
pos0 = pos; | ||
if (/^[^{}\\\0-\x1F \t\n\r]/.test(input.charAt(pos))) { | ||
result0 = input.charAt(pos); | ||
pos++; | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c37(s1); | ||
} | ||
s0 = s1; | ||
return s0; | ||
} | ||
function peg$parsechar() { | ||
var s0, s1, s2, s3, s4, s5; | ||
s0 = peg$currPos; | ||
if (peg$c38.test(input.charAt(peg$currPos))) { | ||
s1 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c39); } | ||
} | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c40(s1); | ||
} | ||
s0 = s1; | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$currPos; | ||
if (input.substr(peg$currPos, 2) === peg$c41) { | ||
s1 = peg$c41; | ||
peg$currPos += 2; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("[^{}\\\\\\0-\\x1F \\t\\n\\r]"); | ||
} | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c42); } | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, x) { | ||
return x; | ||
})(pos0, result0); | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c43(); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
if (result0 === null) { | ||
pos0 = pos; | ||
if (input.substr(pos, 2) === "\\#") { | ||
result0 = "\\#"; | ||
pos += 2; | ||
s0 = s1; | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$currPos; | ||
if (input.substr(peg$currPos, 2) === peg$c44) { | ||
s1 = peg$c44; | ||
peg$currPos += 2; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"\\\\#\""); | ||
} | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c45); } | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset) { | ||
return "\\#"; | ||
})(pos0); | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c46(); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
if (result0 === null) { | ||
pos0 = pos; | ||
if (input.substr(pos, 2) === "\\{") { | ||
result0 = "\\{"; | ||
pos += 2; | ||
s0 = s1; | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$currPos; | ||
if (input.substr(peg$currPos, 2) === peg$c47) { | ||
s1 = peg$c47; | ||
peg$currPos += 2; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"\\\\{\""); | ||
} | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c48); } | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset) { | ||
return "\u007B"; | ||
})(pos0); | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c49(); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
if (result0 === null) { | ||
pos0 = pos; | ||
if (input.substr(pos, 2) === "\\}") { | ||
result0 = "\\}"; | ||
pos += 2; | ||
s0 = s1; | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$currPos; | ||
if (input.substr(peg$currPos, 2) === peg$c50) { | ||
s1 = peg$c50; | ||
peg$currPos += 2; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"\\\\}\""); | ||
} | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c51); } | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset) { | ||
return "\u007D"; | ||
})(pos0); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
if (result0 === null) { | ||
pos0 = pos; | ||
pos1 = pos; | ||
if (input.substr(pos, 2) === "\\u") { | ||
result0 = "\\u"; | ||
pos += 2; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("\"\\\\u\""); | ||
} | ||
} | ||
if (result0 !== null) { | ||
result1 = parse_hexDigit(); | ||
if (result1 !== null) { | ||
result2 = parse_hexDigit(); | ||
if (result2 !== null) { | ||
result3 = parse_hexDigit(); | ||
if (result3 !== null) { | ||
result4 = parse_hexDigit(); | ||
if (result4 !== null) { | ||
result0 = [result0, result1, result2, result3, result4]; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$parsehexDigit(); | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parsehexDigit(); | ||
if (s3 !== peg$FAILED) { | ||
s4 = peg$parsehexDigit(); | ||
if (s4 !== peg$FAILED) { | ||
s5 = peg$parsehexDigit(); | ||
if (s5 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c52(s2, s3, s4, s5); | ||
s0 = s1; | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
} else { | ||
result0 = null; | ||
pos = pos1; | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, h1, h2, h3, h4) { | ||
return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); | ||
})(pos0, result0[1], result0[2], result0[3], result0[4]); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$c1; | ||
} | ||
@@ -1225,232 +1214,112 @@ } | ||
} | ||
return result0; | ||
} | ||
function parse_digits() { | ||
var result0, result1; | ||
var pos0; | ||
pos0 = pos; | ||
if (/^[0-9]/.test(input.charAt(pos))) { | ||
result1 = input.charAt(pos); | ||
pos++; | ||
} else { | ||
result1 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("[0-9]"); | ||
} | ||
} | ||
if (result1 !== null) { | ||
result0 = []; | ||
while (result1 !== null) { | ||
result0.push(result1); | ||
if (/^[0-9]/.test(input.charAt(pos))) { | ||
result1 = input.charAt(pos); | ||
pos++; | ||
} else { | ||
result1 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("[0-9]"); | ||
} | ||
} | ||
} | ||
} else { | ||
result0 = null; | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, ds) { | ||
return parseInt((ds.join('')), 10); | ||
})(pos0, result0); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
return result0; | ||
return s0; | ||
} | ||
function peg$parsedigits() { | ||
var s0, s1, s2; | ||
s0 = peg$currPos; | ||
s1 = []; | ||
if (peg$c53.test(input.charAt(peg$currPos))) { | ||
s2 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c54); } | ||
} | ||
function parse_hexDigit() { | ||
var result0; | ||
if (/^[0-9a-fA-F]/.test(input.charAt(pos))) { | ||
result0 = input.charAt(pos); | ||
pos++; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("[0-9a-fA-F]"); | ||
if (s2 !== peg$FAILED) { | ||
while (s2 !== peg$FAILED) { | ||
s1.push(s2); | ||
if (peg$c53.test(input.charAt(peg$currPos))) { | ||
s2 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c54); } | ||
} | ||
} | ||
return result0; | ||
} else { | ||
s1 = peg$c1; | ||
} | ||
function parse__() { | ||
var result0, result1; | ||
var pos0; | ||
reportFailures++; | ||
pos0 = pos; | ||
result0 = []; | ||
result1 = parse_whitespace(); | ||
while (result1 !== null) { | ||
result0.push(result1); | ||
result1 = parse_whitespace(); | ||
} | ||
if (result0 !== null) { | ||
result0 = (function(offset, w) { return w.join(''); })(pos0, result0); | ||
} | ||
if (result0 === null) { | ||
pos = pos0; | ||
} | ||
reportFailures--; | ||
if (reportFailures === 0 && result0 === null) { | ||
matchFailed("whitespace"); | ||
} | ||
return result0; | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c55(s1); | ||
} | ||
function parse_whitespace() { | ||
var result0; | ||
if (/^[ \t\n\r]/.test(input.charAt(pos))) { | ||
result0 = input.charAt(pos); | ||
pos++; | ||
} else { | ||
result0 = null; | ||
if (reportFailures === 0) { | ||
matchFailed("[ \\t\\n\\r]"); | ||
} | ||
} | ||
return result0; | ||
s0 = s1; | ||
return s0; | ||
} | ||
function peg$parsehexDigit() { | ||
var s0; | ||
if (peg$c56.test(input.charAt(peg$currPos))) { | ||
s0 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c57); } | ||
} | ||
function cleanupExpected(expected) { | ||
expected.sort(); | ||
var lastExpected = null; | ||
var cleanExpected = []; | ||
for (var i = 0; i < expected.length; i++) { | ||
if (expected[i] !== lastExpected) { | ||
cleanExpected.push(expected[i]); | ||
lastExpected = expected[i]; | ||
} | ||
} | ||
return cleanExpected; | ||
return s0; | ||
} | ||
function peg$parse_() { | ||
var s0, s1, s2; | ||
peg$silentFails++; | ||
s0 = peg$currPos; | ||
s1 = []; | ||
s2 = peg$parsewhitespace(); | ||
while (s2 !== peg$FAILED) { | ||
s1.push(s2); | ||
s2 = peg$parsewhitespace(); | ||
} | ||
function computeErrorPosition() { | ||
/* | ||
* The first idea was to use |String.split| to break the input up to the | ||
* error position along newlines and derive the line and column from | ||
* there. However IE's |split| implementation is so broken that it was | ||
* enough to prevent it. | ||
*/ | ||
var line = 1; | ||
var column = 1; | ||
var seenCR = false; | ||
for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) { | ||
var ch = input.charAt(i); | ||
if (ch === "\n") { | ||
if (!seenCR) { line++; } | ||
column = 1; | ||
seenCR = false; | ||
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { | ||
line++; | ||
column = 1; | ||
seenCR = true; | ||
} else { | ||
column++; | ||
seenCR = false; | ||
} | ||
} | ||
return { line: line, column: column }; | ||
if (s1 !== peg$FAILED) { | ||
peg$reportedPos = s0; | ||
s1 = peg$c59(s1); | ||
} | ||
var result = parseFunctions[startRule](); | ||
/* | ||
* The parser is now in one of the following three states: | ||
* | ||
* 1. The parser successfully parsed the whole input. | ||
* | ||
* - |result !== null| | ||
* - |pos === input.length| | ||
* - |rightmostFailuresExpected| may or may not contain something | ||
* | ||
* 2. The parser successfully parsed only a part of the input. | ||
* | ||
* - |result !== null| | ||
* - |pos < input.length| | ||
* - |rightmostFailuresExpected| may or may not contain something | ||
* | ||
* 3. The parser did not successfully parse any part of the input. | ||
* | ||
* - |result === null| | ||
* - |pos === 0| | ||
* - |rightmostFailuresExpected| contains at least one failure | ||
* | ||
* All code following this comment (including called functions) must | ||
* handle these states. | ||
*/ | ||
if (result === null || pos !== input.length) { | ||
var offset = Math.max(pos, rightmostFailuresPos); | ||
var found = offset < input.length ? input.charAt(offset) : null; | ||
var errorPosition = computeErrorPosition(); | ||
throw new this.SyntaxError( | ||
cleanupExpected(rightmostFailuresExpected), | ||
found, | ||
offset, | ||
errorPosition.line, | ||
errorPosition.column | ||
); | ||
s0 = s1; | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c58); } | ||
} | ||
return result; | ||
}, | ||
/* Returns the parser source code. */ | ||
toSource: function() { return this._source; } | ||
}; | ||
/* Thrown when a parser encounters a syntax error. */ | ||
result.SyntaxError = function(expected, found, offset, line, column) { | ||
function buildMessage(expected, found) { | ||
var expectedHumanized, foundHumanized; | ||
switch (expected.length) { | ||
case 0: | ||
expectedHumanized = "end of input"; | ||
break; | ||
case 1: | ||
expectedHumanized = expected[0]; | ||
break; | ||
default: | ||
expectedHumanized = expected.slice(0, expected.length - 1).join(", ") | ||
+ " or " | ||
+ expected[expected.length - 1]; | ||
return s0; | ||
} | ||
function peg$parsewhitespace() { | ||
var s0; | ||
if (peg$c60.test(input.charAt(peg$currPos))) { | ||
s0 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c61); } | ||
} | ||
foundHumanized = found ? quote(found) : "end of input"; | ||
return "Expected " + expectedHumanized + " but " + foundHumanized + " found."; | ||
return s0; | ||
} | ||
this.name = "SyntaxError"; | ||
this.expected = expected; | ||
this.found = found; | ||
this.message = buildMessage(expected, found); | ||
this.offset = offset; | ||
this.line = line; | ||
this.column = column; | ||
peg$result = peg$startRuleFunction(); | ||
if (peg$result !== peg$FAILED && peg$currPos === input.length) { | ||
return peg$result; | ||
} else { | ||
if (peg$result !== peg$FAILED && peg$currPos < input.length) { | ||
peg$fail({ type: "end", description: "end of input" }); | ||
} | ||
throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos); | ||
} | ||
} | ||
return { | ||
SyntaxError: SyntaxError, | ||
parse: parse | ||
}; | ||
result.SyntaxError.prototype = Error.prototype; | ||
return result; | ||
})(); | ||
@@ -1494,3 +1363,3 @@ | ||
if ( ast.output ) { | ||
return 'v(d,"' + ast.argumentIndex + '")'; | ||
return self.globalName + '.v(d,"' + ast.argumentIndex + '")'; | ||
} | ||
@@ -1504,8 +1373,8 @@ else { | ||
if ( ast.key === 'select' ) { | ||
return 's(d,' + data.keys[data.pf_count] + ',' + interpMFP( ast.val, data ) + ')'; | ||
return self.globalName + '.s(d,' + data.keys[data.pf_count] + ',' + interpMFP( ast.val, data ) + ')'; | ||
} | ||
else if ( ast.key === 'plural' ) { | ||
data.offset[data.pf_count || 0] = ast.val.offset || 0; | ||
return 'p(d,' + data.keys[data.pf_count] + ',' + (data.offset[data.pf_count] || 0) | ||
+ ',"' + self.fallbackLocale + '",' + interpMFP( ast.val, data ) + ')'; | ||
return self.globalName + '.p(d,' + data.keys[data.pf_count] + ',' + (data.offset[data.pf_count] || 0) | ||
+ ',"' + self.lc + '",' + interpMFP( ast.val, data ) + ')'; | ||
} | ||
@@ -1551,5 +1420,7 @@ return ''; | ||
case 'string': | ||
tmp = '"' + MessageFormat.Utils.escapeExpression( ast.val ) + '"'; | ||
tmp = '"' + (ast.val || "").replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"'; | ||
if ( data.pf_count ) { | ||
tmp = MessageFormat.Utils.numSub( tmp, 'd', data.keys[data.pf_count-1], data.offset[data.pf_count-1]); | ||
var o = data.offset[data.pf_count-1]; | ||
tmp = tmp.replace(/(^|[^\\])#/g, '$1"+' + self.globalName + '.n(d,' + data.keys[data.pf_count-1] + (o ? ',' + o : '') + ')+"'); | ||
tmp = tmp.replace(/^""\+/, '').replace(/\+""$/, ''); | ||
} | ||
@@ -1565,11 +1436,17 @@ return tmp; | ||
MessageFormat.prototype.compile = function ( message ) { | ||
return (new Function( 'MessageFormat', | ||
'return ' + | ||
this.precompile( | ||
this.parse( message ) | ||
) | ||
))(MessageFormat); | ||
return (new Function( | ||
'this[\'' + this.globalName + '\']=' + this.functions() + ';' + | ||
'return ' + this.precompile( this.parse( message )) | ||
))(); | ||
}; | ||
MessageFormat.prototype.precompileObject = function ( messages ) { | ||
var tmp = []; | ||
for (var key in messages) { | ||
tmp.push(JSON.stringify(key) + ':' + this.precompile(this.parse(messages[key]))); | ||
} | ||
return '{\n' + tmp.join(',\n') + '}'; | ||
}; | ||
if (typeof exports !== 'undefined') { | ||
@@ -1576,0 +1453,0 @@ if (typeof module !== 'undefined' && module.exports) { |
{ | ||
"name": "messageformat", | ||
"version": "0.1.8", | ||
"version": "0.2.0", | ||
"author": "Alex Sexton <alexsexton@gmail.com>", | ||
@@ -44,3 +44,3 @@ "description": "PluralFormat and SelectFormat Message and i18n Tool - A JavaScript Implemenation of the ICU standards.", | ||
}, | ||
"license": "To Use: WTFPL, To Contribute: Dojo CLA" | ||
"license": "To use or fork, Apache License, Version 2.0. To contribute back, Dojo CLA" | ||
} |
@@ -11,4 +11,8 @@ [![Build Status](https://secure.travis-ci.org/SlexAxton/messageformat.js.png)](http://travis-ci.org/SlexAxton/messageformat.js) | ||
MessageFormat in Java-land technically incorporates all other type formatting (and the older ChoiceFormat) directly into its messages, however, in the name of filesize, messageformat.js only strives to implement **SelectFormat** and **PluralFormat**. There are plans to pull in locale-aware **NumberFormat** parsing as a "plugin" to this library, but as of right now, it's best to pass things in preformatted (as suggested in the ICU docs). | ||
MessageFormat in Java-land technically incorporates all other type formatting (and the older ChoiceFormat) directly into its messages, however, in the name of filesize, messageformat.js only strives to implement **SelectFormat** and **PluralFormat**. | ||
There are plans to pull in locale-aware **NumberFormat** parsing as a "plugin" to this library, but as of right now, it's best to pass things in preformatted (as suggested in the ICU docs). | ||
We have also ported the Google Closure implementation of [NumberFormat](https://github.com/jedtoolkit/numberformat.js), but there is no direct integration of these two libraries. (They work well together!) | ||
## What problems does it solve? | ||
@@ -503,3 +507,3 @@ | ||
You may use this software under the WTFPL. | ||
You may use this software under the Apache License, version 2.0. | ||
@@ -506,0 +510,0 @@ You may contribute to this software under the Dojo CLA - <http://dojofoundation.org/about/cla> |
@@ -8,2 +8,1 @@ /*! | ||
MessageFormat = require('../messageformat'); | ||
require('../locale/cy'); |
@@ -10,6 +10,4 @@ /*global describe,it,expect,MessageFormat */ | ||
it("should have static helper functions/objects", function () { | ||
expect( MessageFormat.Utils ).to.be.an( 'object' ); | ||
it("should have static locale object", function () { | ||
expect( MessageFormat.locale ).to.be.an( 'object' ); | ||
expect( MessageFormat.SafeString ).to.be.a( 'function' ); | ||
}); | ||
@@ -22,2 +20,9 @@ | ||
if (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined') { | ||
it("should be a constructor", function () { | ||
var mf = new MessageFormat( 'es' ); | ||
expect( mf ).to.be.a( MessageFormat ); | ||
}); | ||
} | ||
it("should have instance functions", function () { | ||
@@ -32,9 +37,7 @@ var mf = new MessageFormat( 'en' ); | ||
var mf = new MessageFormat( 'en-x-test1-test2' ); | ||
expect(mf.fallbackLocale).to.be("en"); | ||
expect(mf.pluralFunc).to.be( MessageFormat.locale.en ); | ||
expect(mf.lc).to.be("en"); | ||
}); | ||
it("should fallback when a base pluralFunc exists (underscores)", function() { | ||
var mf = new MessageFormat( 'en_x_test1_test2' ); | ||
expect(mf.fallbackLocale).to.be("en"); | ||
expect(mf.pluralFunc).to.be( MessageFormat.locale.en ); | ||
expect(mf.lc).to.be("en"); | ||
}); | ||
@@ -47,3 +50,3 @@ | ||
it("should default to 'en' when no locale is passed into the constructor", function () { | ||
expect((new MessageFormat()).locale).to.be( 'en' ); | ||
expect((new MessageFormat()).lc).to.be( 'en' ); | ||
}); | ||
@@ -598,5 +601,5 @@ | ||
expect(mfunc({FRIENDS:0, ENEMIES: 0})).to.eql("I have 0 friends but 0 enemies."); | ||
expect(function(){ var x = mfunc({FRIENDS:0}); }).to.throwError(/MessageFormat\: \`ENEMIES\` isnt a number\./); | ||
expect(function(){ var x = mfunc({}); }).to.throwError(/MessageFormat\: \`.+\` isnt a number\./); | ||
expect(function(){ var x = mfunc({ENEMIES:0}); }).to.throwError(/MessageFormat\: \`FRIENDS\` isnt a number\./); | ||
expect(function(){ var x = mfunc({FRIENDS:0}); }).to.throwError(/MessageFormat\: \'ENEMIES\' isn\'t a number\./); | ||
expect(function(){ var x = mfunc({}); }).to.throwError(/MessageFormat\: \'.+\' isn\'t a number\./); | ||
expect(function(){ var x = mfunc({ENEMIES:0}); }).to.throwError(/MessageFormat\: \'FRIENDS\' isn\'t a number\./); | ||
}); | ||
@@ -704,3 +707,19 @@ }); | ||
}) ).to.eql('Al Sexton added themself and 2 other people to their group.'); | ||
}); | ||
it("can precompile a JSON object into executable Javascript source code", function () { | ||
var mf = new MessageFormat( 'en' ); | ||
var data = { 'key': 'I have {FRIENDS, plural, one{one friend} other{# friends}}.' }; | ||
var source = mf.precompileObject(data); | ||
expect(source).to.contain('"key"'); | ||
var mfunc = (new Function( | ||
'this[\'' + mf.globalName + '\']=' + mf.functions() + ';\n' + | ||
'var obj = ' + source + ';\n' + | ||
'return obj.key;' | ||
))(); | ||
expect(mfunc).to.be.a('function'); | ||
expect(mfunc({FRIENDS:1})).to.eql("I have one friend."); | ||
expect(mfunc({FRIENDS:2})).to.eql("I have 2 friends."); | ||
}); | ||
@@ -707,0 +726,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
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
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
0
526
240285
92
2896
3
3