diff --git a/.eslintignore b/.eslintignore index fd69918e46d529..23f0c7da923cc4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -28,3 +28,10 @@ .next build node_modules +.nyc_output + +# These come from crowdin. +# If we would commit changes crowdin would immediately try to revert. +# If we want to format these files we'd need to do it in crowdin +docs/**/*-pt.md +docs/**/*-zh.md diff --git a/package.json b/package.json index 03ae93db735b18..9a10cf6eec8ef5 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "lint:ci": "eslint . --report-unused-disable-directives --ext .js,.ts,.tsx --max-warnings 0", "stylelint": "stylelint --reportInvalidScopeDisables --reportNeedlessDisables docs/**/*.{js,ts,tsx}", "markdownlint": "markdownlint-cli2 \"**/*.md\"", - "prettier": "node ./scripts/prettier.mjs", - "prettier:all": "node ./scripts/prettier.mjs write", + "prettier": "pretty-quick --ignore-path .eslintignore", + "prettier:all": "prettier --write . --ignore-path .eslintignore", "size:snapshot": "node --max-old-space-size=4096 ./scripts/sizeSnapshot/create", "size:why": "yarn size:snapshot --analyze", "start": "yarn && yarn docs:dev", @@ -164,6 +164,7 @@ "piscina": "^3.2.0", "playwright": "^1.27.1", "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "process": "^0.11.10", "prop-types": "^15.8.1", "raw-loader": "4.0.2", diff --git a/scripts/jsonlint.mjs b/scripts/jsonlint.mjs index 59db2e1c889750..1be4900d731af9 100644 --- a/scripts/jsonlint.mjs +++ b/scripts/jsonlint.mjs @@ -14,7 +14,7 @@ async function run() { const eslintignoreContent = await fse.readFile(path.join(workspaceRoot, '.eslintignore'), { encoding: 'utf8', }); - const eslintignore = eslintignoreContent.split(/\r?\n/).slice(0, -1); + const eslintignore = eslintignoreContent.split(/\r?\n/).filter(Boolean); const filenames = await glob('**/*.json', { cwd: workspaceRoot, diff --git a/scripts/listChangedFiles.mjs b/scripts/listChangedFiles.mjs deleted file mode 100644 index d1621870e230ba..00000000000000 --- a/scripts/listChangedFiles.mjs +++ /dev/null @@ -1,29 +0,0 @@ -// Based on similar script in React -// https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/scripts/shared/listChangedFiles.js - -import util from 'util'; -import childProcess from 'child_process'; - -const execFile = util.promisify(childProcess.execFile); - -async function execGitCmd(args) { - const gitResults = await execFile('git', args, { - // 128 MB instead of the default 1MB to prevent "maxbuffer exceeded" on large diffs e.g. when updating icons - maxBuffer: 128 * 1024 * 1024, - }); - const stdout = gitResults.stdout.trim(); - if (stdout === '') { - return []; - } - return stdout.split('\n'); -} - -async function listChangedFiles({ branch }) { - const comparedBranch = process.env.CIRCLECI ? `origin/${branch}` : branch; - const mergeBase = await execGitCmd(['rev-parse', comparedBranch]); - const gitDiff = await execGitCmd(['diff', '--name-only', mergeBase]); - const gitLs = await execGitCmd(['ls-files', '--others', '--exclude-standard']); - return new Set([...gitDiff, ...gitLs]); -} - -export default listChangedFiles; diff --git a/scripts/listChangedFiles.test.mjs b/scripts/listChangedFiles.test.mjs deleted file mode 100644 index 4d12d04b854f82..00000000000000 --- a/scripts/listChangedFiles.test.mjs +++ /dev/null @@ -1,41 +0,0 @@ -import fs from 'fs'; -import rimraf from 'rimraf'; -import { promisify } from 'util'; -import { expect } from 'chai'; -import listChangedFiles from './listChangedFiles.mjs'; - -const writeFileAsync = promisify(fs.writeFile); -const rimrafAsync = promisify(rimraf); - -describe('listChangedFiles', function listChangedFilesSuite() { - // This test oftentimes times out after 4s but it's unclear why considering `listChangedFiles` is used in CI tasks that only take <1s. - this.timeout(10000); - const noop = () => {}; - // eslint-disable-next-line no-console - const time = process.env.CI ? console.time : noop; - // eslint-disable-next-line no-console - const timeLog = process.env.CI ? console.timeLog : noop; - // eslint-disable-next-line no-console - const timeEnd = process.env.CI ? console.timeEnd : noop; - it('should detect changes', async () => { - time('should detect changes'); - // #default-branch-switch - const changesBeforeAdd = await listChangedFiles({ branch: 'master' }); - timeLog('should detect changes'); - const testFile = 'someTestFile.yml'; - try { - await writeFileAsync(testFile, 'console.log("hello");'); - timeLog('should detect changes'); - // #default-branch-switch - const changesAfterAdd = await listChangedFiles({ branch: 'master' }); - timeLog('should detect changes'); - expect(changesBeforeAdd).not.to.contain(testFile); - expect(changesAfterAdd).to.contain(testFile); - expect(changesAfterAdd.size - changesBeforeAdd.size).to.equal(1); - timeLog('should detect changes'); - } finally { - await rimrafAsync(testFile); - timeEnd('should detect changes'); - } - }); -}); diff --git a/scripts/prettier.mjs b/scripts/prettier.mjs deleted file mode 100644 index f8276f96ae8641..00000000000000 --- a/scripts/prettier.mjs +++ /dev/null @@ -1,153 +0,0 @@ -/* eslint-disable no-console */ -// Based on similar script in React -// https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/scripts/prettier/index.js - -// supported modes = check, check-changed, write, write-changed - -import glob from 'globby'; -import prettier from 'prettier'; -import fs from 'fs'; -import path from 'path'; -import yargs from 'yargs'; -import { LANGUAGES } from 'docs/src/modules/constants.js'; -import listChangedFiles from './listChangedFiles.mjs'; -import { getWorkspaceRoot } from './utils.mjs'; - -const workspaceRoot = getWorkspaceRoot(); - -function isTranslatedDocument(filename) { - // markdown files from crowdin end with a 2 letter locale - return new RegExp(String.raw`-(${LANGUAGES.join('|')})\.md$`).test(filename); -} - -function runPrettier(options) { - const { changedFiles, shouldWrite } = options; - - let didWarn = false; - let didError = false; - - const warnedFiles = []; - const ignoredFiles = fs - .readFileSync(path.join(workspaceRoot, '.eslintignore'), 'utf-8') - .split(/\r*\n/) - .filter((line) => { - return ( - // ignore comments - !line.startsWith('#') && - // skip empty lines - line.length > 0 - ); - }) - .map((line) => { - if (line.startsWith('/')) { - // "/" marks the cwd of the ignore file. - // Since we declare the dirname of the gitignore the cwd we can prepend "." as a shortcut. - return `.${line}`; - } - return line; - }); - - const files = glob - .sync('**/*.{js,jsx,md,tsx,ts,cjs,mjs,json,html,css,prisma,yml}', { - cwd: workspaceRoot, - gitignore: true, - ignore: [ - // these are auto-generated - 'docs/pages/api-docs/**/*.md', - ...ignoredFiles, - ], - dot: true, - }) - .filter( - (f) => - (!changedFiles || changedFiles.has(f)) && - // These come from crowdin. - // If we would commit changes crowdin would immediately try to revert. - // If we want to format these files we'd need to do it in crowdin - !isTranslatedDocument(f), - ); - - if (!files.length) { - return; - } - - const prettierConfigPath = path.join(workspaceRoot, 'prettier.config.js'); - - files.forEach((file) => { - const prettierOptions = prettier.resolveConfig.sync(file, { - config: prettierConfigPath, - }); - - try { - const input = fs.readFileSync(file, 'utf8'); - if (shouldWrite) { - console.log(`Formatting ${file}`); - const output = prettier.format(input, { ...prettierOptions, filepath: file }); - if (output !== input) { - fs.writeFileSync(file, output, 'utf8'); - } - } else { - console.log(`Checking ${file}`); - if (!prettier.check(input, { ...prettierOptions, filepath: file })) { - warnedFiles.push(file); - didWarn = true; - } - } - } catch (error) { - didError = true; - console.log(`\n\n${error.message}`); - console.log(file); - } - }); - - if (didWarn) { - console.log( - '\n\nThis project uses prettier to format all JavaScript code.\n' + - `Please run '${!changedFiles ? 'yarn prettier:all' : 'yarn prettier'}'` + - ' and commit the changes to the files listed below:\n\n', - ); - console.log(warnedFiles.join('\n')); - } - - if (didWarn || didError) { - throw new Error('Triggered at least one error or warning'); - } -} - -async function run(argv) { - const { mode, branch } = argv; - const shouldWrite = mode === 'write' || mode === 'write-changed'; - const onlyChanged = mode === 'check-changed' || mode === 'write-changed'; - - let changedFiles; - if (onlyChanged) { - changedFiles = await listChangedFiles({ branch }); - } - - runPrettier({ changedFiles, shouldWrite, branch }); -} - -yargs(process.argv.slice(2)) - .command({ - command: '$0 [mode]', - description: 'formats codebase', - builder: (command) => { - return command - .positional('mode', { - description: '"write" | "check-changed" | "write-changed"', - type: 'string', - default: 'write-changed', - }) - .option('branch', { - // #default-branch-switch - default: 'master', - describe: 'The branch to diff against', - type: 'string', - }); - }, - handler: run, - }) - .help() - .strict(true) - .version(false) - .parse(); diff --git a/yarn.lock b/yarn.lock index 066186aee46a71..8949e4f8b7adbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5492,6 +5492,14 @@ chalk@^2.0.0, chalk@^2.3.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -7727,6 +7735,21 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -8397,7 +8420,7 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" -get-stream@^5.1.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -9034,6 +9057,11 @@ https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: agent-base "6" debug "4" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -9087,7 +9115,7 @@ ignore-walk@^5.0.1: dependencies: minimatch "^5.0.1" -ignore@^5.0.4, ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.0.4, ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -11347,6 +11375,11 @@ moo@^0.5.0: resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4" integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w== +mri@^1.1.5: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + mrmime@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" @@ -11367,6 +11400,17 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multimatch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" + integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== + dependencies: + "@types/minimatch" "^3.0.3" + array-differ "^3.0.0" + array-union "^2.1.0" + arrify "^2.0.1" + minimatch "^3.0.4" + multimatch@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-5.0.0.tgz#932b800963cea7a31a033328fa1e0c3a1874dbe6" @@ -11766,7 +11810,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^4.0.1: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -12770,6 +12814,18 @@ pretty-format@^27.0.2: ansi-styles "^5.0.0" react-is "^17.0.1" +pretty-quick@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.3.tgz#15281108c0ddf446675157ca40240099157b638e" + integrity sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA== + dependencies: + chalk "^3.0.0" + execa "^4.0.0" + find-up "^4.1.0" + ignore "^5.1.4" + mri "^1.1.5" + multimatch "^4.0.0" + prettyjson@^1.2.1: version "1.2.5" resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.5.tgz#ef3cfffcc70505c032abc59785884b4027031835"