twreporter-react
Version:
React-Redux site for The Reporter Foundation in Taiwan
184 lines (150 loc) • 4.26 kB
JavaScript
/**
* Copyright (c) 2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import sane from 'sane';
import { resolve as resolvePath } from 'path';
import { spawn } from 'child_process';
process.env.PATH += ':./node_modules/.bin';
const is_windows = process.platform === 'win32'
// still creates the NUL file in the current working directory
const dev_null = is_windows ? 'NUL' : '/dev/null'
var cmd = resolvePath(__dirname);
var srcDir = resolvePath(cmd, './source');
function exec(command, options) {
return new Promise(function (resolve, reject) {
var child = spawn(command, options, {
cmd: cmd,
env: process.env,
stdio: 'inherit'
});
child.on('exit', function (code) {
if (code === 0) {
resolve(true);
} else {
reject(new Error('Error code: ' + code));
}
});
});
}
var watcher = sane(srcDir, { glob: ['**/*.*'] })
.on('ready', startWatch)
.on('add', changeFile)
.on('delete', deleteFile)
.on('change', changeFile);
process.on('SIGINT', function () {
watcher.close();
console.log(CLEARLINE + yellow(invert('stopped watching')));
process.exit();
});
var isChecking;
var needsCheck;
var toCheck = {};
var timeout;
function startWatch() {
process.stdout.write(CLEARSCREEN + green(invert('watching...')));
}
function changeFile(filepath, root, stat) {
if (!stat.isDirectory()) {
toCheck[filepath] = true;
debouncedCheck();
}
}
function deleteFile(filepath) {
delete toCheck[filepath];
debouncedCheck();
}
function debouncedCheck() {
needsCheck = true;
clearTimeout(timeout);
timeout = setTimeout(guardedCheck, 250);
}
function guardedCheck() {
if (isChecking || !needsCheck) {
return;
}
isChecking = true;
var filepaths = Object.keys(toCheck);
toCheck = {};
needsCheck = false;
checkFiles(filepaths).then(() => {
isChecking = false;
process.nextTick(guardedCheck);
});
}
function checkFiles(filepaths) {
console.log('\u001b[2J');
// return parseFiles(filepaths)
// .then(() => runTests(filepaths))
return runTests(filepaths)
.catch(() => false)
.then(success => {
process.stdout.write(
'\n' + (success ? '' : '\x07') + green(invert('watching...'))
);
});
}
// Checking steps
function executable(command) {
if (is_windows) {
return command + '.cmd'
}
return command
}
function parseFiles(filepaths) {
console.log('Checking Syntax');
return Promise.all(filepaths.map(filepath => {
if (isJS(filepath) && !isTest(filepath)) {
return exec(executable('babel'), [
'--optional', 'runtime',
'--out-file', dev_null,
srcPath(filepath)
]);
}
}));
}
function runTests(filepaths) {
console.log('\nRunning Tests');
return exec(executable('mocha'), [
'--reporter', 'spec',
'--bail',
'--require', 'scripts/mocha-bootload'
].concat(
allTests(filepaths) ? filepaths.map(srcPath) : ['test/**/*.js'] // 'src/**/__tests__/**/*.js'
)).catch(() => false);
}
// Filepath
function srcPath(filepath) {
return resolvePath(srcDir, filepath);
}
// Predicates
function isJS(filepath) {
return filepath.indexOf('.js') === filepath.length - 3;
}
function allTests(filepaths) {
return filepaths.length > 0 && filepaths.every(isTest);
}
function isTest(filepath) {
return isJS(filepath) && ~filepath.indexOf('__tests__/');
}
// Print helpers
var CLEARSCREEN = '\u001b[2J';
var CLEARLINE = '\r\x1B[K';
var CHECK = green('\u2713');
var X = red('\u2718');
function invert(str) {
return `\u001b[7m ${str} \u001b[27m`;
}
function red(str) {
return `\x1B[K\u001b[1m\u001b[31m${str}\u001b[39m\u001b[22m`;
}
function green(str) {
return `\x1B[K\u001b[1m\u001b[32m${str}\u001b[39m\u001b[22m`;
}
function yellow(str) {
return `\x1B[K\u001b[1m\u001b[33m${str}\u001b[39m\u001b[22m`;
}