From a32511692fd5f6256db77ebe0682d843228f7190 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 22 Oct 2018 17:47:03 +0000 Subject: [PATCH] Fix/update prettier script --- .prettierignore | 4 + package.json | 3 +- scripts/frontend/frontend_script_utils.js | 3 +- scripts/frontend/prettier.js | 206 ++++++++++------------ yarn.lock | 5 - 5 files changed, 105 insertions(+), 116 deletions(-) diff --git a/.prettierignore b/.prettierignore index b674ccd50cf..dc9e572ab54 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,3 +3,7 @@ /public/ /vendor/ /tmp/ + +# ignore stylesheets for now as this clashes with our linter +*.css +*.scss diff --git a/package.json b/package.json index 8ec47bc2837..23747bbfbb2 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js", "karma-start": "BABEL_ENV=karma karma start config/karma.config.js", "postinstall": "node ./scripts/frontend/postinstall.js", - "prettier-staged": "node ./scripts/frontend/prettier.js", + "prettier-staged": "node ./scripts/frontend/prettier.js check", "prettier-staged-save": "node ./scripts/frontend/prettier.js save", "prettier-all": "node ./scripts/frontend/prettier.js check-all", "prettier-all-save": "node ./scripts/frontend/prettier.js save-all", @@ -126,7 +126,6 @@ "eslint-plugin-jasmine": "^2.10.1", "gettext-extractor": "^3.3.2", "gettext-extractor-vue": "^4.0.1", - "ignore": "^3.3.7", "istanbul": "^0.4.5", "jasmine-core": "^2.9.0", "jasmine-diff": "^0.1.3", diff --git a/scripts/frontend/frontend_script_utils.js b/scripts/frontend/frontend_script_utils.js index e42b912d359..e3d357b4a40 100644 --- a/scripts/frontend/frontend_script_utils.js +++ b/scripts/frontend/frontend_script_utils.js @@ -13,7 +13,8 @@ const execGitCmd = args => exec('git', args) .trim() .toString() - .split('\n'); + .split('\n') + .filter(Boolean); module.exports = { getStagedFiles: fileExtensionFilter => { 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); + }); diff --git a/yarn.lock b/yarn.lock index 292c7128d18..950407fb627 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4181,11 +4181,6 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.3.7: - version "3.3.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b" - integrity sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg== - ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" -- GitLab