1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-12-04 15:24:23 +01:00
fab-manager/vendor/assets/components/messageformat/bin/messageformat.js
2016-03-23 18:39:41 +01:00

212 lines
6.7 KiB
JavaScript
Executable File

#!/usr/bin/env node
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"),
async = require('async'),
MessageFormat = require('../'),
_ = require('underscore'),
knownOpts = {
"locale" : String,
"inputdir" : Path,
"output" : Path,
"combine" : String,
"watch" : Boolean,
"namespace" : String,
"include" : String,
"stdout" : Boolean,
"verbose" : Boolean
},
description = {
"locale" : "locale 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"
},
defaults = {
"inputdir" : process.cwd(),
"output" : process.cwd(),
"combine" : undefined,
"watch" : false,
"namespace" : 'window.i18n',
"include" : '**/*.json',
"stdout" : false,
"verbose" : false
},
shortHands = {
"l" : "--locale",
"i" : "--inputdir",
"o" : "--output",
"c" : "--combine",
"w" : "--watch",
"ns" : "--namespace",
"I" : "--include",
"s" : "--stdout",
"v" : "--verbose"
},
options = nopt(knownOpts, shortHands, process.argv, 2),
argvRemain = options.argv.remain,
inputdir;
// 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);
}
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 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 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);
});
});
};
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();
});
});
}
});
});
});
}
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;
}