summaryrefslogtreecommitdiff
path: root/scripts/frontend/prettier.js
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/frontend/prettier.js')
-rw-r--r--scripts/frontend/prettier.js206
1 files changed, 98 insertions, 108 deletions
diff --git a/scripts/frontend/prettier.js b/scripts/frontend/prettier.js
index b66ba885701..ce86a9f4601 100644
--- a/scripts/frontend/prettier.js
+++ b/scripts/frontend/prettier.js
@@ -1,126 +1,116 @@
const glob = require('glob');
const prettier = require('prettier');
const fs = require('fs');
-const path = require('path');
-const prettierIgnore = require('ignore')();
+const { getStagedFiles } = require('./frontend_script_utils');
-const getStagedFiles = require('./frontend_script_utils').getStagedFiles;
+const matchExtensions = ['js', 'vue'];
+
+// This will improve glob performance by excluding certain directories.
+// The .prettierignore file will also be respected, but after the glob has executed.
+const globIgnore = ['**/node_modules/**', 'vendor/**', 'public/**'];
+
+const readFileAsync = (file, options) =>
+ new Promise((resolve, reject) => {
+ fs.readFile(file, options, function(err, data) {
+ if (err) reject(err);
+ else resolve(data);
+ });
+ });
+
+const writeFileAsync = (file, data, options) =>
+ new Promise((resolve, reject) => {
+ fs.writeFile(file, data, options, function(err) {
+ if (err) reject(err);
+ else resolve();
+ });
+ });
const mode = process.argv[2] || 'check';
const shouldSave = mode === 'save' || mode === 'save-all';
const allFiles = mode === 'check-all' || mode === 'save-all';
-let dirPath = process.argv[3] || '';
-if (dirPath && dirPath.charAt(dirPath.length - 1) !== '/') dirPath += '/';
-
-const config = {
- patterns: ['**/*.js', '**/*.vue', '**/*.scss'],
- /*
- * The ignore patterns below are just to reduce search time with glob, as it includes the
- * folders with the most ignored assets, the actual `.prettierignore` will be used later on
- */
- ignore: ['**/node_modules/**', '**/vendor/**', '**/public/**'],
- parsers: {
- js: 'babylon',
- vue: 'vue',
- scss: 'css',
- },
-};
+let globDir = process.argv[3] || '';
+if (globDir && globDir.charAt(globDir.length - 1) !== '/') globDir += '/';
-/*
- * Unfortunately the prettier API does not expose support for `.prettierignore` files, they however
- * use the ignore package, so we do the same. We simply cannot use the glob package, because
- * gitignore style is not compatible with globs ignore style.
- */
-prettierIgnore.add(
- fs
- .readFileSync(path.join(__dirname, '../../', '.prettierignore'))
- .toString()
- .trim()
- .split(/\r?\n/)
+console.log(
+ `Loading all ${allFiles ? '' : 'staged '}files ${globDir ? `within ${globDir} ` : ''}...`
);
-const availableExtensions = Object.keys(config.parsers);
-
-console.log(`Loading ${allFiles ? 'All' : 'Selected'} Files ...`);
+const globPatterns = matchExtensions.map(ext => `${globDir}**/*.${ext}`);
+const matchedFiles = allFiles
+ ? glob.sync(`{${globPatterns.join(',')}}`, { ignore: globIgnore })
+ : getStagedFiles(globPatterns);
+const matchedCount = matchedFiles.length;
-const stagedFiles =
- allFiles || dirPath ? null : getStagedFiles(availableExtensions.map(ext => `*.${ext}`));
-
-if (stagedFiles) {
- if (!stagedFiles.length || (stagedFiles.length === 1 && !stagedFiles[0])) {
- console.log('No matching staged files.');
- process.exit(1);
- }
- console.log(`Matching staged Files : ${stagedFiles.length}`);
+if (!matchedCount) {
+ console.log('No files found to process with prettier');
+ process.exit(0);
}
let didWarn = false;
-let didError = false;
-
-let files;
-if (allFiles) {
- const ignore = config.ignore;
- const patterns = config.patterns;
- const globPattern = patterns.length > 1 ? `{${patterns.join(',')}}` : `${patterns.join(',')}`;
- files = glob.sync(globPattern, { ignore }).filter(f => allFiles || stagedFiles.includes(f));
-} else if (dirPath) {
- const ignore = config.ignore;
- const patterns = config.patterns.map(item => {
- return dirPath + item;
- });
- const globPattern = patterns.length > 1 ? `{${patterns.join(',')}}` : `${patterns.join(',')}`;
- files = glob.sync(globPattern, { ignore });
-} else {
- files = stagedFiles.filter(f => availableExtensions.includes(f.split('.').pop()));
-}
-
-files = prettierIgnore.filter(files);
-
-if (!files.length) {
- console.log('No Files found to process with Prettier');
- process.exit(1);
-}
-
-console.log(`${shouldSave ? 'Updating' : 'Checking'} ${files.length} file(s)`);
-
-files.forEach(file => {
- try {
- prettier
- .resolveConfig(file)
- .then(options => {
- const fileExtension = file.split('.').pop();
- Object.assign(options, {
- parser: config.parsers[fileExtension],
+let passedCount = 0;
+let failedCount = 0;
+let ignoredCount = 0;
+
+console.log(`${shouldSave ? 'Updating' : 'Checking'} ${matchedCount} file(s)`);
+
+const fixCommand = `yarn prettier-${allFiles ? 'all' : 'staged'}-save`;
+const warningMessage = `
+===============================
+GitLab uses Prettier to format all JavaScript code.
+Please format each file listed below or run "${fixCommand}"
+===============================
+`;
+
+const checkFileWithOptions = (filePath, options) =>
+ readFileAsync(filePath, 'utf8').then(input => {
+ if (shouldSave) {
+ const output = prettier.format(input, options);
+ if (input === output) {
+ passedCount += 1;
+ } else {
+ return writeFileAsync(filePath, output, 'utf8').then(() => {
+ console.log(`Prettified : ${filePath}`);
+ failedCount += 1;
});
-
- const input = fs.readFileSync(file, 'utf8');
-
- if (shouldSave) {
- const output = prettier.format(input, options);
- if (output !== input) {
- fs.writeFileSync(file, output, 'utf8');
- console.log(`Prettified : ${file}`);
- }
- } else if (!prettier.check(input, options)) {
- if (!didWarn) {
- console.log(
- '\n===============================\nGitLab uses Prettier to format all JavaScript code.\nPlease format each file listed below or run "yarn prettier-staged-save"\n===============================\n'
- );
- didWarn = true;
- }
- console.log(`Prettify Manually : ${file}`);
+ }
+ } else {
+ if (prettier.check(input, options)) {
+ passedCount += 1;
+ } else {
+ if (!didWarn) {
+ console.log(warningMessage);
+ didWarn = true;
}
- })
- .catch(e => {
- console.log(`Error on loading the Config File: ${e.message}`);
- process.exit(1);
- });
- } catch (error) {
- didError = true;
- console.log(`\n\nError with ${file}: ${error.message}`);
- }
-});
+ console.log(`Prettify Manually : ${filePath}`);
+ failedCount += 1;
+ }
+ }
+ });
-if (didWarn || didError) {
- process.exit(1);
-}
+const checkFileWithPrettierConfig = filePath =>
+ prettier
+ .getFileInfo(filePath, { ignorePath: '.prettierignore' })
+ .then(({ ignored, inferredParser }) => {
+ if (ignored || !inferredParser) {
+ ignoredCount += 1;
+ return;
+ }
+ return prettier.resolveConfig(filePath).then(fileOptions => {
+ const options = { ...fileOptions, parser: inferredParser };
+ return checkFileWithOptions(filePath, options);
+ });
+ });
+
+Promise.all(matchedFiles.map(checkFileWithPrettierConfig))
+ .then(() => {
+ const failAction = shouldSave ? 'fixed' : 'failed';
+ console.log(
+ `\nSummary:\n ${matchedCount} files processed (${passedCount} passed, ${failedCount} ${failAction}, ${ignoredCount} ignored)\n`
+ );
+
+ if (didWarn) process.exit(1);
+ })
+ .catch(e => {
+ console.log(`\nAn error occured while processing files with prettier: ${e.message}\n`);
+ process.exit(1);
+ });