Telegram Web, preconfigured for usage in I2P. http://web.telegram.i2p/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

366 lines
9.3 KiB

var readline = require('readline');
var fs = require('fs');
var util = require('util');
var path = require('path');
var glob = require('glob');
var helper = require('./helper');
var logger = require('./logger');
var constant = require('./constants');
var log = logger.create('init');
var JS_TPL_PATH = __dirname + '/../config.tpl.js';
var COFFEE_TPL_PATH = __dirname + '/../config.tpl.coffee';
var COLORS_ON = {
END: '\x1B[39m',
NYAN: '\x1B[36m',
GREEN: '\x1B[32m',
BOLD: '\x1B[1m',
bold: function(str) {
return this.BOLD + str + '\x1B[22m';
},
green: function(str) {
return this.GREEN + str + this.END;
}
};
// nasty global
var colors = COLORS_ON;
var COLORS_OFF = {
END: '',
NYAN: '',
GREEN: '',
BOLD: '',
bold: function(str) {
return str;
},
green: function(str) {
return str;
}
};
var validatePattern = function(value) {
if (!glob.sync(value).length) {
log.warn('There is no file matching this pattern.\n' + colors.NYAN);
}
};
var validateBrowser = function(name) {
var moduleName = 'karma-' + name.toLowerCase().replace('canary', '') + '-launcher';
try {
require(moduleName);
} catch (e) {
log.warn('Missing "%s" plugin.\n npm install %s --save-dev' + colors.NYAN, moduleName,
moduleName);
}
// TODO(vojta): check if the path resolves to a binary
};
var validateFramework = function(name) {
try {
require('karma-' + name);
} catch (e) {
log.warn('Missing "karma-%s" plugin.\n npm install karma-%s --save-dev' + colors.NYAN, name,
name);
}
};
var validateRequireJs = function(useRequire) {
if (useRequire) {
validateFramework('requirejs');
}
};
var questions = [{
id: 'framework',
question: 'Which testing framework do you want to use ?',
hint: 'Press tab to list possible options. Enter to move to the next question.',
options: ['jasmine', 'mocha', 'qunit', ''],
validate: validateFramework
}, {
id: 'requirejs',
question: 'Do you want to use Require.js ?',
hint: 'This will add Require.js plugin.\n' +
'Press tab to list possible options. Enter to move to the next question.',
options: ['no', 'yes'],
validate: validateRequireJs,
boolean: true
}, {
id: 'browsers',
question: 'Do you want to capture a browser automatically ?',
hint: 'Press tab to list possible options. Enter empty string to move to the next question.',
options: ['Chrome', 'ChromeCanary', 'Firefox', 'Safari', 'PhantomJS', 'Opera', 'IE', ''],
validate: validateBrowser,
multiple: true
}, {
id: 'files',
question: 'What is the location of your source and test files ?',
hint: 'You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".\n' +
'Enter empty string to move to the next question.',
multiple: true,
validate: validatePattern
}, {
id: 'exclude',
question: 'Should any of the files included by the previous patterns be excluded ?',
hint: 'You can use glob patterns, eg. "**/*.swp".\n' +
'Enter empty string to move to the next question.',
multiple: true,
validate: validatePattern
}, {
id: 'includedFiles',
question: 'Which files do you want to include with <script> tag ?',
hint: 'This should be a script that bootstraps your test by configuring Require.js and ' +
'kicking __karma__.start(), probably your test-main.js file.\n' +
'Enter empty string to move to the next question.',
multiple: true,
validate: validatePattern,
condition: function(answers) {return answers.requirejs;}
}, {
id: 'autoWatch',
question: 'Do you want Karma to watch all the files and run the tests on change ?',
hint: 'Press tab to list possible options.',
options: ['yes', 'no'],
boolean: true
}];
var StateMachine = function(rli) {
var currentQuestion;
var answers;
var currentOptions;
var currentOptionsPointer;
var pendingQuestionId;
var done;
this.onKeypress = function(key) {
if (!currentOptions || !key) {
return;
}
if (key.name === 'tab' || key.name === 'right' || key.name === 'down') {
this.suggestNextOption();
} else if (key.name === 'left' || key.name === 'up') {
currentOptionsPointer = currentOptionsPointer + currentOptions.length - 2;
this.suggestNextOption();
}
if (!key.ctrl && !key.meta && key.name !== 'enter' && key.name !== 'return') {
key.name = 'escape';
}
};
this.suggestNextOption = function() {
if (!currentOptions) {
return;
}
currentOptionsPointer = (currentOptionsPointer + 1) % currentOptions.length;
rli._deleteLineLeft();
rli._deleteLineRight();
rli.write(currentOptions[currentOptionsPointer]);
};
this.onLine = function(line) {
if (pendingQuestionId) {
line = line.trim();
if (currentOptions) {
currentOptionsPointer = currentOptions.indexOf(line);
if (currentOptionsPointer === -1) {
return;
}
}
if (line === '') {
line = null;
}
if (currentQuestion.boolean) {
line = (line === 'yes' || line === 'true' || line === 'on');
}
if (line !== null && currentQuestion.validate) {
currentQuestion.validate(line);
}
if (currentQuestion.multiple) {
answers[pendingQuestionId] = answers[pendingQuestionId] || [];
if (line !== null) {
answers[pendingQuestionId].push(line);
rli.prompt();
if (currentOptions) {
currentOptions.splice(currentOptionsPointer, 1);
currentOptionsPointer = -1;
}
} else {
this.nextQuestion();
}
} else {
answers[pendingQuestionId] = line;
this.nextQuestion();
}
}
};
this.nextQuestion = function() {
rli.write(colors.END);
currentQuestion = questions.shift();
while (currentQuestion && currentQuestion.condition && !currentQuestion.condition(answers)) {
currentQuestion = questions.shift();
}
if (currentQuestion) {
pendingQuestionId = null;
rli.write('\n' + colors.bold(currentQuestion.question) + '\n');
rli.write(currentQuestion.hint + colors.NYAN + '\n');
currentOptions = currentQuestion.options || null;
currentOptionsPointer = -1;
pendingQuestionId = currentQuestion.id;
rli.prompt();
this.suggestNextOption();
} else {
pendingQuestionId = null;
currentOptions = null;
// end
done(answers);
}
};
this.process = function(_questions, _done) {
questions = _questions;
answers = {};
done = _done;
this.nextQuestion();
};
};
var quote = function(value) {
return '\'' + value + '\'';
};
var quoteNonIncludedPattern = function(value) {
return util.format('{pattern: %s, included: false}', quote(value));
};
var formatFiles = function(files) {
return files.join(',\n ');
};
var getBasePath = function(configFilePath, cwd) {
var configParts = path.dirname(configFilePath).split(path.sep);
var cwdParts = cwd.split(path.sep);
var base = [];
while (configParts.length && configParts[0] === cwdParts[0]) {
configParts.shift();
cwdParts.shift();
}
while (configParts.length) {
var part = configParts.shift();
if (part === '..') {
base.unshift(cwdParts.pop());
} else if (part !== '.') {
base.unshift('..');
}
}
return base.join(path.sep);
};
var getReplacementsFromAnswers = function(answers, basePath) {
var files = answers.files.map(answers.includedFiles ? quoteNonIncludedPattern : quote);
if (answers.includedFiles) {
files = answers.includedFiles.map(quote).concat(files);
}
var frameworks = [];
if (answers.framework) {
frameworks.push(answers.framework);
}
if (answers.requirejs) {
frameworks.push('requirejs');
}
return {
DATE: new Date(),
BASE_PATH: basePath,
FRAMEWORKS: frameworks.map(quote).join(', '),
FILES: formatFiles(files),
EXCLUDE: answers.exclude ? formatFiles(answers.exclude.map(quote)) : '',
AUTO_WATCH: answers.autoWatch ? 'true' : 'false',
BROWSERS: answers.browsers.map(quote).join(', ')
};
};
var COFFEE_REGEXP = /\.coffee$/;
var isCoffeeFile = function(filename) {
return COFFEE_REGEXP.test(filename);
};
exports.init = function(config) {
var useColors = true;
var logLevel = constant.LOG_INFO;
if (helper.isDefined(config.colors)) {
colors = config.colors ? COLORS_ON : COLORS_OFF;
useColors = config.colors;
}
if (helper.isDefined(config.logLevel)) {
logLevel = config.logLevel;
}
logger.setup(logLevel, useColors);
// need to be registered before creating readlineInterface
process.stdin.on('keypress', function(s, key) {
sm.onKeypress(key);
});
var rli = readline.createInterface(process.stdin, process.stdout);
var sm = new StateMachine(rli, colors);
rli.on('line', sm.onLine.bind(sm));
sm.process(questions, function(answers) {
var cwd = process.cwd();
var configFile = config.configFile || 'karma.conf.js';
var templateFile = isCoffeeFile(configFile) ? COFFEE_TPL_PATH : JS_TPL_PATH;
var replacements = getReplacementsFromAnswers(answers, getBasePath(configFile, process.cwd()));
var content = fs.readFileSync(templateFile).toString().replace(/%(.*)%/g, function(a, key) {
return replacements[key];
});
var configFilePath = path.resolve(cwd, configFile);
fs.writeFileSync(configFilePath, content);
rli.write(colors.green('\nConfig file generated at "' + configFilePath + '".\n\n'));
rli.close();
});
};