diff --git a/package.json b/package.json index 3f5070440d..094946a201 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "babylon": "6.15.0", "browserify": "^13.0.0", "bundle-collapser": "^1.1.1", + "chalk": "^1.1.3", "coffee-script": "^1.8.0", "core-js": "^2.2.1", "coveralls": "^2.11.6", @@ -94,7 +95,7 @@ "postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json", "test": "jest", "flow": "flow", - "prettier": "prettier --write --no-bracket-spacing --single-quote --jsx-bracket-same-line --trailing-comma all --print-width 80 \"src/**/!(third_party)/*.js\"" + "prettier": "node ./scripts/prettier/index.js write" }, "jest": { "modulePathIgnorePatterns": [ diff --git a/scripts/prettier/index.js b/scripts/prettier/index.js new file mode 100644 index 0000000000..7864e6edca --- /dev/null +++ b/scripts/prettier/index.js @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2014-present, 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. + */ +'use strict'; + +// Based on similar script in Jest +// https://github.com/facebook/jest/blob/master/scripts/prettier.js + +const chalk = require('chalk'); +const glob = require('glob'); +const path = require('path'); +const runCommand = require('./runCommand'); + +const shouldWrite = process.argv[2] === 'write'; +const isWindows = process.platform === 'win32'; +const prettier = isWindows ? 'prettier.cmd' : 'prettier'; +const prettierCmd = path.resolve(__dirname, '../../node_modules/.bin/' + prettier); +const defaultOptions = { + 'bracket-spacing': 'false', + 'single-quote': 'true', + 'jsx-bracket-same-line': 'true', + 'trailing-comma': 'all', + 'print-width': 80, +}; +const config = { + default: { + patterns: ['src/**/*.js'], + ignore: [ + '**/third_party/**', + '**/node_modules/**', + ], + }, +}; + +Object.keys(config).forEach(key => { + const patterns = config[key].patterns; + const options = config[key].options; + const ignore = config[key].ignore; + + const globPattern = patterns.length > 1 + ? `{${patterns.join(',')}}` + : `${patterns.join(',')}`; + const files = glob.sync(globPattern, {ignore}); + + const args = Object.keys(defaultOptions).map( + k => `--${k}=${(options && options[k]) || defaultOptions[k]}` + ); + args.push(`--${shouldWrite ? 'write' : 'l'} {${files.join(' ')}}`); + + try { + runCommand(prettierCmd, args.join(' '), path.resolve(__dirname, '../..')); + } catch (e) { + console.log(e); + if (!shouldWrite) { + console.log( + chalk.red( + ` This project uses prettier to format all JavaScript code.\n` + ) + + chalk.dim(` Please run `) + + chalk.reset('yarn prettier') + + chalk.dim(` and add changes to files listed above to your commit.`) + + `\n` + ); + } + } +}); diff --git a/scripts/prettier/runCommand.js b/scripts/prettier/runCommand.js new file mode 100644 index 0000000000..81e3b9a943 --- /dev/null +++ b/scripts/prettier/runCommand.js @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2014, 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. + */ +'use strict'; + +const chalk = require('chalk'); +const spawn = require('child_process').spawnSync; + +module.exports = function runCommand(cmd, args, cwd) { + if (!cwd) { + cwd = __dirname; + } + + const callArgs = args.split(' '); + console.log( + chalk.dim('$ cd ' + cwd) + + '\n' + + chalk.dim( + ' $ ' + + cmd + + ' ' + + (args.length > 1000 ? args.slice(0, 1000) + '...' : args) + ) + + '\n' + ); + const result = spawn(cmd, callArgs, { + cwd, + stdio: 'inherit', + }); + if (result.error || result.status !== 0) { + const message = 'Error running command.'; + const error = new Error(message); + error.stack = message; + throw error; + } +};