diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index d70c9e6c..00000000 --- a/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -dist/ -bin/ -*.md -*.html \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index ec3b45c5..00000000 --- a/.prettierrc +++ /dev/null @@ -1,6 +0,0 @@ -printWidth: 100 -tabWidth: 4 -useTabs: true -bracketSpacing: false -trailingComma: es5 -singleQuote: true diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..4043a395 --- /dev/null +++ b/biome.json @@ -0,0 +1,68 @@ +{ + "assist": { + "actions": { + "source": { + "organizeImports": "off" + } + } + }, + "formatter": { + "indentStyle": "tab", + "lineWidth": 100, + "bracketSpacing": false + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "trailingCommas": "es5", + "arrowParentheses": "asNeeded" + } + }, + "json": { + "formatter": {"indentStyle": "tab"} + }, + "linter": { + "enabled": true, + "includes": ["**", "!bench/**", "!test/manual/**"], + "rules": { + "correctness": { + "preset": "recommended" + }, + "suspicious": { + "preset": "recommended", + "noApproximativeNumericConstant": "off", + "noExplicitAny": "off" + }, + "style": { + "preset": "recommended", + "useTemplate": "off" + }, + "complexity": { + "preset": "recommended" + } + } + }, + "overrides": [ + { + "includes": ["test/**"], + "linter": { + "rules": { + "correctness": { + "noUnusedVariables": "off", + "noUnusedImports": "off", + "noUnusedFunctionParameters": "off" + }, + "suspicious": { + "noImplicitAnyLet": "off" + }, + "complexity": { + "useLiteralKeys": "off" + } + } + } + } + ], + "files": { + "includes": ["**", "!**/dist", "!**/bin", "!**/node_modules"] + } +} diff --git a/package.json b/package.json index efd55047..d9af7bc0 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,8 @@ "test-speed": "bash test/speed/run.sh", "rebase": "yarn is-git-clean && git fetch && git rebase origin/main", "load-options": "# rr -h | rr 'Options:(.+)Examples:' _ -ms | rr '\\n {26,}|\\n\\n *' ' ' | rr \"'\" '`' | rr '^ (-.+?), (--[^ ]+) *' '`€1` | **`€2`** ' | rr '(^---- . ----).+?(## Good to know)' '€1 + nl + pipe + nl + nl + €2' readme.md -jspT", - "test-format": "prettier . --list-different || (echo 'Please correct file formatting using `yarn format` and try again.' && exit 1)", - "format": "prettier . --write", + "test-format": "biome format || (echo 'Please correct file formatting using `yarn format` and try again.' && exit 1)", + "format": "biome format --write", "is-git-clean": "(git diff --quiet --exit-code --cached && git diff --quiet --exit-code) || (echo Please commit or stash changes && exit 1)", "release": "yarn version", "prerelease": "yarn is-git-clean && yarn test && yarn test-minify && yarn load-options", @@ -60,9 +60,9 @@ "sed" ], "devDependencies": { + "@biomejs/biome": "2.5.15", "@types/node": "24.19.1", "assert": "^2.0.0", - "prettier": "3.9.9", "yarn": "1.22.22" }, "resolutions": { diff --git a/src/alias.ts b/src/alias.ts index a362b791..e872b519 100644 --- a/src/alias.ts +++ b/src/alias.ts @@ -1,7 +1,7 @@ // The `€` and `§` aliases are for the shell, where `$` and `\` are hard to type, so the CLI uses them and not the engine. // Globs, file names and piped data never use them, as `€` and `§` can be part of the text. export function alias(config) { - const swap = (str) => { + const swap = str => { if (!str) { return str; } diff --git a/src/cli.ts b/src/cli.ts index 249d29b9..89de6bc8 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -96,7 +96,7 @@ const yargs = require('yargs') .alias('e', 'encoding') .describe('e', 'Encoding of files/piped data.') // Not .choices() as node takes the name of an encoding in any case, like `UTF8` - .check((argv) => Buffer.isEncoding(argv.encoding) || `Unknown encoding: ${argv.encoding}`) + .check(argv => Buffer.isEncoding(argv.encoding) || `Unknown encoding: ${argv.encoding}`) .string('x') .describe( @@ -461,7 +461,7 @@ const lineBreakEscapes = {'\n': '\\n', '\r': '\\r', '\u2028': '\\u2028', '\u2029 // Let javascript interpret escape sequences (like `\n` or `\x41`) by evaluating the replacement as the content of a single quoted string. // Anything that would end the string or break the source must be neutralised first: unescaped single quotes, real line breaks and a lone backslash at the end. function unescapeString(str = '') { - const source = str.replace(/\\(?:\r\n|[\s\S])?|['\n\r\u2028\u2029]/g, (match) => { + const source = str.replace(/\\(?:\r\n|[\s\S])?|['\n\r\u2028\u2029]/g, match => { if ('\\' === match) { return '\\\\'; } @@ -482,7 +482,7 @@ if (0 < needHelp) { const config: any = {}; // Use only camelCase full length version of settings so we make sure the core can be documented properly -Object.keys(yargs.argv).forEach((key) => { +Object.keys(yargs.argv).forEach(key => { if (1 < key.length && key.indexOf('-') < 0) { config[key] = yargs.argv[key]; } @@ -547,13 +547,13 @@ if (config.contentDelimiter) { // The exit code is only set, so the process ends by itself when all output is written const run = () => rexreplace.engine(config).then( - (status) => { + status => { printStatus(config, status); if (status.errors.length) { process.exitCode = 1; } }, - (e) => exitOnPanic(config, e) + e => exitOnPanic(config, e) ); // Like grep, stdin is only read when piped data is expected. An open pipe that nobody writes to would make the run wait forever. @@ -567,7 +567,7 @@ if (!pipeDataExpected || Boolean(process.stdin.isTTY)) { process.stdin.setEncoding(config.encoding); - process.stdin.on('data', (chunk) => { + process.stdin.on('data', chunk => { pipeData = (pipeData ?? '') + chunk; }); diff --git a/src/engine.ts b/src/engine.ts index 14fca745..e569f80b 100644 --- a/src/engine.ts +++ b/src/engine.ts @@ -99,8 +99,7 @@ async function run(config) { search: config.regex.source, flags: config.regex.flags, replacement: config.replacementJs || config.outputMatch ? null : config.replacement, - replacementSrc: - config.replacementJs && !config.outputMatch ? config.replacementOri : null, + replacementSrc: config.replacementJs && !config.outputMatch ? config.replacementOri : null, }; } @@ -135,7 +134,7 @@ async function run(config) { config.voidAsync = config.voidAsync || 1 === config.files.length || config.output || config.outputMatch; - const files = config.files.filter((filepath) => + const files = config.files.filter(filepath => fs.existsSync(filepath) ? true : error('File not found:', filepath) ); @@ -171,7 +170,7 @@ function openFile(file, config) { chat('Open async: ' + file); return fs.promises .readFile(file, config.encoding) - .then((data) => doReplacement(file, config, data), error); + .then(data => doReplacement(file, config, data), error); } } @@ -449,7 +448,7 @@ function dynamicReplacement(_file_rr, _config_rr, _data_rr) { _ = ' ', _nl = '\n'; - // prettier-ignore + // biome-ignore format: one variable on each line let _file = '❌', _file_rel = '❌', _dirpath = '❌', @@ -715,9 +714,7 @@ function dynamicReplacement(_file_rr, _config_rr, _data_rr) { function localTimeString(dateObj = new Date()) { return `${dateObj.getFullYear()}-${('0' + (dateObj.getMonth() + 1)).slice(-2)}-${( '0' + dateObj.getDate() - ).slice( - -2 - )} ${('0' + dateObj.getHours()).slice(-2)}:${('0' + dateObj.getMinutes()).slice(-2)}:${( + ).slice(-2)} ${('0' + dateObj.getHours()).slice(-2)}:${('0' + dateObj.getMinutes()).slice(-2)}:${( '0' + dateObj.getSeconds() ).slice(-2)}.${('00' + dateObj.getMilliseconds()).slice(-3)}`; } @@ -729,19 +726,19 @@ function getFilePaths(conf) { // With --absolute-path each file is known by its full path from here on. That is what --exclude-re sees, and the name that is printed. if (conf.absolutePath) { - files = files.map((file) => path.resolve(file)); + files = files.map(file => path.resolve(file)); } // --exclude-glob is always globs, also for the name of a file. They are used together, and the files they find are taken away. if (excludeGlob.length) { - const excluded = new Set(globs.sync(excludeGlob).map((file) => path.resolve(file))); - files = files.filter((file) => !excluded.has(path.resolve(file))); + const excluded = new Set(globs.sync(excludeGlob).map(file => path.resolve(file))); + files = files.filter(file => !excluded.has(path.resolve(file))); } excludeRe - .map((el) => getFinalRegex(getFinalPattern(el, conf), conf)) - .forEach((re) => { - files = files.filter((file) => !file.match(re)); + .map(el => getFinalRegex(getFinalPattern(el, conf), conf)) + .forEach(re => { + files = files.filter(file => !file.match(re)); }); return files.sort(); @@ -752,7 +749,7 @@ function getFilePaths(conf) { function findFiles(paths) { const files = []; const patterns = []; - paths.forEach((file) => { + paths.forEach(file => { if (fs.statSync(file, {throwIfNoEntry: false})?.isFile()) { files.push(file); } else { @@ -762,7 +759,7 @@ function findFiles(paths) { // A file given by its name and also found by a glob is only handled once const seen = new Set(); - return files.concat(patterns.length ? globs.sync(patterns) : []).filter((file) => { + return files.concat(patterns.length ? globs.sync(patterns) : []).filter(file => { const fullPath = path.resolve(file); if (seen.has(fullPath)) { return false; diff --git a/src/output.ts b/src/output.ts index 4e3bb648..985cd895 100644 --- a/src/output.ts +++ b/src/output.ts @@ -1,5 +1,5 @@ let font: any = {}; -font.red = font.green = font.gray = (str) => str; +font.red = font.green = font.gray = str => str; // check for node version supporting chalk - if so overwrite `font` //const font = import('chalk'); diff --git a/test/fuzzy/basics.test.js b/test/fuzzy/basics.test.js index dca96c54..1187c927 100644 --- a/test/fuzzy/basics.test.js +++ b/test/fuzzy/basics.test.js @@ -34,15 +34,14 @@ describe('basics', () => { const expected = (await rr(pattern, replacement, {pipedData: text})).out; fs.writeFileSync('my.file', text); - expect( - (await rr(pattern, replacement, {includeGlob: ['my.file'], output: true})).out - ).toBe(ended(expected)); + expect((await rr(pattern, replacement, {includeGlob: ['my.file'], output: true})).out).toBe( + ended(expected) + ); await rr(pattern, replacement, {includeGlob: ['my.file']}); - expect( - fs.readFileSync('my.file', 'utf8'), - JSON.stringify({pattern, replacement, text}) - ).toBe(expected); + expect(fs.readFileSync('my.file', 'utf8'), JSON.stringify({pattern, replacement, text})).toBe( + expected + ); } }); }); diff --git a/test/fuzzy/crossover.test.js b/test/fuzzy/crossover.test.js index 6ce16f1e..e87eca20 100644 --- a/test/fuzzy/crossover.test.js +++ b/test/fuzzy/crossover.test.js @@ -31,7 +31,7 @@ describe('crossover', () => { test('any combination of flags', async () => { const rnd = random(1); for (let i = 0; i < 300; i++) { - const config = Object.fromEntries(flags.map((flag) => [flag, 0 === rnd.int(3)])); + const config = Object.fromEntries(flags.map(flag => [flag, 0 === rnd.int(3)])); const pattern = rnd.pick(patterns); const text = rnd.text('abAB \næ.*+', 0, 30); const replacement = rnd.text('xy \n<>&', 0, 3); @@ -51,7 +51,7 @@ describe('crossover', () => { const matches = ended( ...(config.voidGlobal ? [text.match(regex)] : Array.from(text.matchAll(regex))) .filter(Boolean) - .map((match) => (1 < match.length ? match.slice(1).join('') : match[0])) + .map(match => (1 < match.length ? match.slice(1).join('') : match[0])) ); const given = config.replacementJs ? JSON.stringify(replacement) : replacement; @@ -70,18 +70,11 @@ describe('crossover', () => { // The name of the file is only printed if the file was changed const named = replaced !== text && !config.quiet && !config.quietTotal; expect(result.out, note).toBe( - config.outputMatch - ? matches - : config.output - ? ended(replaced) - : named - ? file + '\n' - : '' + config.outputMatch ? matches : config.output ? ended(replaced) : named ? file + '\n' : '' ); const expected = written ? replaced : text; - const files = - written && replaced !== text && config.keepBackup && !config.voidBackup ? 2 : 1; + const files = written && replaced !== text && config.keepBackup && !config.voidBackup ? 2 : 1; expect(fs.readFileSync(file, 'utf8'), note).toBe(expected); expect(fs.readdirSync(`run${i}`), note).toHaveLength(files); @@ -92,14 +85,9 @@ describe('crossover', () => { const rnd = random(2); for (let i = 0; i < 200; i++) { const config = Object.fromEntries( - [ - 'literal', - 'voidIgnoreCase', - 'voidGlobal', - 'dotAll', - 'voidMultiline', - 'unicode', - ].map((flag) => [flag, 0 === rnd.int(2)]) + ['literal', 'voidIgnoreCase', 'voidGlobal', 'dotAll', 'voidMultiline', 'unicode'].map( + flag => [flag, 0 === rnd.int(2)] + ) ); const pattern = rnd.pick(patterns); const text = rnd.text('abAB \r\næ中.*+', 0, 40); diff --git a/test/fuzzy/dot-all.test.js b/test/fuzzy/dot-all.test.js index 37352def..d8c15bb0 100644 --- a/test/fuzzy/dot-all.test.js +++ b/test/fuzzy/dot-all.test.js @@ -16,9 +16,7 @@ describe('--dot-all', () => { continue; } - expect((await rr(pattern, '_', {pipedData: text})).out, note).toBe( - text.replace(regex, '_') - ); + expect((await rr(pattern, '_', {pipedData: text})).out, note).toBe(text.replace(regex, '_')); expect((await rr(pattern, '_', {pipedData: text, dotAll: true})).out, note).toBe( text.replace(new RegExp(pattern, 'gims'), '_') ); diff --git a/test/fuzzy/encoding.test.js b/test/fuzzy/encoding.test.js index 488020e5..ad67345e 100644 --- a/test/fuzzy/encoding.test.js +++ b/test/fuzzy/encoding.test.js @@ -10,20 +10,18 @@ describe('--encoding', () => { const junk = () => Buffer.from( Array.from({length: rnd.int(40)}, () => rnd.int(255)).filter( - (byte) => !'qQzZ'.includes(String.fromCharCode(byte)) + byte => !'qQzZ'.includes(String.fromCharCode(byte)) ) ); const [before, after] = [junk(), junk()]; fs.writeFileSync('my.file', Buffer.concat([before, Buffer.from('qzq'), after])); await rr('qzq', 'ok', {includeGlob: ['my.file'], encoding: 'latin1'}); - expect(fs.readFileSync('my.file')).toEqual( - Buffer.concat([before, Buffer.from('ok'), after]) - ); + expect(fs.readFileSync('my.file')).toEqual(Buffer.concat([before, Buffer.from('ok'), after])); } }); - test.each(['utf8', 'utf16le'])('%s keeps any unicode text intact', async (encoding) => { + test.each(['utf8', 'utf16le'])('%s keeps any unicode text intact', async encoding => { const rnd = random(2); const alphabet = ['a', 'b', ' ', '\n', 'æ', 'ß', '中', '🦖', '👍🏽', 'é', '​', '€']; for (let i = 0; i < 200; i++) { diff --git a/test/fuzzy/exclude-glob.test.js b/test/fuzzy/exclude-glob.test.js index e8458fe9..1d637729 100644 --- a/test/fuzzy/exclude-glob.test.js +++ b/test/fuzzy/exclude-glob.test.js @@ -4,12 +4,12 @@ import {rr, random} from '../js/helper.js'; // Make `names` as files containing "foo" and return the ones changed by replacing "foo" const changed = async (names, config) => { - names.forEach((name) => { + names.forEach(name => { fs.mkdirSync(name.replace(/[^/]*$/, '') || '.', {recursive: true}); fs.writeFileSync(name, 'foo'); }); await rr('foo', 'x', config); - return names.filter((name) => 'x' === fs.readFileSync(name, 'utf8')); + return names.filter(name => 'x' === fs.readFileSync(name, 'utf8')); }; describe('--exclude-glob', () => { @@ -17,12 +17,7 @@ describe('--exclude-glob', () => { const rnd = random(1); for (let i = 0; i < 100; i++) { const names = Array.from( - new Set( - Array.from( - {length: 1 + rnd.int(7)}, - () => `run${i}/${rnd.text('abc', 1, 4)}.file` - ) - ) + new Set(Array.from({length: 1 + rnd.int(7)}, () => `run${i}/${rnd.text('abc', 1, 4)}.file`)) ); const [glob, regex] = rnd.pick([ ['a*', /\/a[^/]*$/], @@ -33,7 +28,7 @@ describe('--exclude-glob', () => { ['*c*', /\/[^/]*c[^/]*$/], ['{a,bb}.file', /\/(a|bb)\.file$/], ]); - const expected = names.filter((name) => !regex.test(name)).sort(); + const expected = names.filter(name => !regex.test(name)).sort(); const config = { includeGlob: [`run${i}/*`], excludeGlob: [`run${i}/${glob}`], diff --git a/test/fuzzy/exclude-re.test.js b/test/fuzzy/exclude-re.test.js index 05f74239..9b672320 100644 --- a/test/fuzzy/exclude-re.test.js +++ b/test/fuzzy/exclude-re.test.js @@ -4,12 +4,12 @@ import {rr, random} from '../js/helper.js'; // Make `names` as files containing "foo" and return the ones changed by replacing "foo" const changed = async (names, config) => { - names.forEach((name) => { + names.forEach(name => { fs.mkdirSync(name.replace(/[^/]*$/, '') || '.', {recursive: true}); fs.writeFileSync(name, 'foo'); }); await rr('foo', 'x', config); - return names.filter((name) => 'x' === fs.readFileSync(name, 'utf8')); + return names.filter(name => 'x' === fs.readFileSync(name, 'utf8')); }; describe('--exclude-re', () => { @@ -28,7 +28,7 @@ describe('--exclude-re', () => { const exclude = rnd.pick(['a', 'b$', '/c', 'a.*b', '^run\\d+/a', 'bb|cc', '\\.file$']); const voidIgnoreCase = !rnd.int(1); const regex = new RegExp(exclude, voidIgnoreCase ? '' : 'i'); - const expected = names.filter((name) => !regex.test(name)).sort(); + const expected = names.filter(name => !regex.test(name)).sort(); const config = { includeGlob: [`run${i}/*`], excludeRe: [exclude], diff --git a/test/fuzzy/keep-backup.test.js b/test/fuzzy/keep-backup.test.js index 520163c7..193190b2 100644 --- a/test/fuzzy/keep-backup.test.js +++ b/test/fuzzy/keep-backup.test.js @@ -2,7 +2,7 @@ import {describe, test, expect} from 'bun:test'; import fs from 'fs'; import {rr, random} from '../js/helper.js'; -const backups = (dir = '.') => fs.readdirSync(dir).filter((name) => name.endsWith('.backup')); +const backups = (dir = '.') => fs.readdirSync(dir).filter(name => name.endsWith('.backup')); describe('--keep-backup', () => { test('the backup is always the original and the file is always the result', async () => { @@ -19,7 +19,7 @@ describe('--keep-backup', () => { expect(fs.readFileSync(`run${i}/my.file`, 'utf8'), note).toBe(expected); expect(backups('run' + i), note).toHaveLength(expected === text ? 0 : 1); - backups('run' + i).forEach((name) => + backups('run' + i).forEach(name => expect(fs.readFileSync(`run${i}/${name}`, 'utf8'), note).toBe(text) ); } diff --git a/test/fuzzy/literal.test.js b/test/fuzzy/literal.test.js index 8bb7ba18..7741d527 100644 --- a/test/fuzzy/literal.test.js +++ b/test/fuzzy/literal.test.js @@ -9,9 +9,7 @@ describe('--literal', () => { for (let i = 0; i < 500; i++) { const pattern = rnd.text(alphabet, 1, 6); const replacement = rnd.text('xy\'"\\\n ', 0, 3); - const text = Array.from({length: rnd.int(5)}, () => rnd.text(alphabet, 0, 8)).join( - pattern - ); + const text = Array.from({length: rnd.int(5)}, () => rnd.text(alphabet, 0, 8)).join(pattern); const config = { pipedData: text, literal: true, @@ -32,9 +30,7 @@ describe('--literal', () => { for (let i = 0; i < 300; i++) { const pattern = rnd.text('.*+?()[]{}|^$\\', 1, 5); const text = rnd.text('abc \n', 0, 30); - expect((await rr(pattern, 'x', {pipedData: text, literal: true})).out, pattern).toBe( - text - ); + expect((await rr(pattern, 'x', {pipedData: text, literal: true})).out, pattern).toBe(text); } }); }); diff --git a/test/fuzzy/output-match.test.js b/test/fuzzy/output-match.test.js index 840f7812..100cc12a 100644 --- a/test/fuzzy/output-match.test.js +++ b/test/fuzzy/output-match.test.js @@ -11,7 +11,7 @@ describe('--output-match', () => { expect( (await rr(pattern, '_', {pipedData: text, outputMatch: true})).out, JSON.stringify({pattern, text}) - ).toBe(matches.map((match) => match + '\n').join('')); + ).toBe(matches.map(match => match + '\n').join('')); } }); @@ -24,7 +24,7 @@ describe('--output-match', () => { expect( (await rr(pattern, '_', {pipedData: text, outputMatch: true})).out, JSON.stringify({pattern, text}) - ).toBe(matches.map((match) => match.slice(1).join('') + '\n').join('')); + ).toBe(matches.map(match => match.slice(1).join('') + '\n').join('')); } }); }); diff --git a/test/fuzzy/output.test.js b/test/fuzzy/output.test.js index 5b239c05..0bc81e8d 100644 --- a/test/fuzzy/output.test.js +++ b/test/fuzzy/output.test.js @@ -1,7 +1,7 @@ import {describe, test, expect} from 'bun:test'; import {rr, random, ended} from '../js/helper.js'; -const read = (names) => Promise.all(names.map((name) => Bun.file(name).text())); +const read = names => Promise.all(names.map(name => Bun.file(name).text())); describe('--output', () => { test('sends exactly what would have been written to the files with the content delimiter after each', async () => { @@ -9,7 +9,7 @@ describe('--output', () => { for (let i = 0; i < 100; i++) { const names = ['a', 'b', 'c', 'd', 'e', 'f'] .slice(0, 1 + rnd.int(5)) - .map((name) => name + '.file'); + .map(name => name + '.file'); const texts = names.map(() => rnd.text('abAB01 \t\r\n\0\\\'"`$€§æ中🦖', 0, 200)); const pattern = rnd.pick(['a', 'b+', '^.', '\\s', 'ab', '$', '\\r?\\n']); // null is the default: a line break, unless the content already ends with one @@ -27,7 +27,7 @@ describe('--output', () => { expect(out, JSON.stringify({pattern, contentDelimiter, texts})).toBe( null === contentDelimiter ? ended(...(await read(names))) - : (await read(names)).map((text) => text + contentDelimiter).join('') + : (await read(names)).map(text => text + contentDelimiter).join('') ); } }); diff --git a/test/fuzzy/replacement-js.test.js b/test/fuzzy/replacement-js.test.js index 6bfdc1d2..3336891b 100644 --- a/test/fuzzy/replacement-js.test.js +++ b/test/fuzzy/replacement-js.test.js @@ -12,9 +12,7 @@ describe('--replacement-js', () => { for (let i = 0; i < 500; i++) { const text = rnd.text(alphabet, 1, 20); expect(await js('[^]+', '$0', text), JSON.stringify(text)).toBe(text); - expect(await js('([^]+)', '$1.length', text), JSON.stringify(text)).toBe( - String(text.length) - ); + expect(await js('([^]+)', '$1.length', text), JSON.stringify(text)).toBe(String(text.length)); } }); @@ -35,7 +33,7 @@ describe('--replacement-js', () => { const operator = rnd.pick(['+', '-', '*', '%', '/']); const operand = 1 + rnd.int(9); expect(await js('(\\d+)', `$1 ${operator} ${operand}`, numbers.join(' '))).toBe( - numbers.map((n) => eval(`"${n}" ${operator} ${operand}`)).join(' ') + numbers.map(n => eval(`"${n}" ${operator} ${operand}`)).join(' ') ); } }); diff --git a/test/fuzzy/unicode.test.js b/test/fuzzy/unicode.test.js index 0c72f639..321e757e 100644 --- a/test/fuzzy/unicode.test.js +++ b/test/fuzzy/unicode.test.js @@ -7,17 +7,7 @@ describe('--unicode', () => { test('gives the same as String.replace with and without the u flag', async () => { const rnd = random(1); for (let i = 0; i < 500; i++) { - const pattern = rnd.pick([ - '.', - '..', - '[^a]', - '\\S+', - 'a.', - '.b', - '[🦖🦕]', - '🦖+', - '\\W', - ]); + const pattern = rnd.pick(['.', '..', '[^a]', '\\S+', 'a.', '.b', '[🦖🦕]', '🦖+', '\\W']); const text = rnd.text(alphabet, 0, 15); const note = JSON.stringify({pattern, text}); diff --git a/test/fuzzy/void-async.test.js b/test/fuzzy/void-async.test.js index be6840b9..dc3061dc 100644 --- a/test/fuzzy/void-async.test.js +++ b/test/fuzzy/void-async.test.js @@ -9,11 +9,11 @@ describe('--void-async', () => { const names = ['a', 'b', 'c', 'd', 'e'].slice(0, 1 + rnd.int(4)); const texts = names.map(() => rnd.text('ab \næ🦖', 0, 20)); const pattern = rnd.pick(['a', 'b+', '\\s', 'ab']); - const expected = texts.map((text) => text.replace(new RegExp(pattern, 'gim'), '_')); - const result = (dir) => names.map((name) => fs.readFileSync(dir + name, 'utf8')); + const expected = texts.map(text => text.replace(new RegExp(pattern, 'gim'), '_')); + const result = dir => names.map(name => fs.readFileSync(dir + name, 'utf8')); const [sync, async] = [`sync${i}/`, `async${i}/`]; - [sync, async].forEach((dir) => { + [sync, async].forEach(dir => { fs.mkdirSync(dir, {recursive: true}); names.forEach((name, n) => fs.writeFileSync(dir + name, texts[n])); }); diff --git a/test/fuzzy/void-euro.test.js b/test/fuzzy/void-euro.test.js index 9022c530..4b468f20 100644 --- a/test/fuzzy/void-euro.test.js +++ b/test/fuzzy/void-euro.test.js @@ -9,17 +9,16 @@ describe('--void-euro', () => { const replacement = rnd.text(['$1', '$2', '$&', '$$', '-', 'x'], 0, 4); const text = rnd.text('ab \n', 0, 20); const expected = text.replace(new RegExp(pattern, 'gim'), replacement); - const euro = (str) => str.replace(/\$/g, '€'); + const euro = str => str.replace(/\$/g, '€'); const note = JSON.stringify({pattern, replacement, text}); expect((await rr(pattern, replacement, {pipedData: text})).out, note).toBe(expected); expect((await rr(euro(pattern), euro(replacement), {pipedData: text})).out, note).toBe( expected ); - expect( - (await rr(pattern, replacement, {pipedData: text, voidEuro: true})).out, - note - ).toBe(expected); + expect((await rr(pattern, replacement, {pipedData: text, voidEuro: true})).out, note).toBe( + expected + ); } }); diff --git a/test/fuzzy/void-ignore-case.test.js b/test/fuzzy/void-ignore-case.test.js index b995df9e..02429715 100644 --- a/test/fuzzy/void-ignore-case.test.js +++ b/test/fuzzy/void-ignore-case.test.js @@ -12,10 +12,9 @@ describe('--void-ignore-case', () => { expect((await rr(pattern, '_', {pipedData: text})).out, note).toBe( text.replace(new RegExp(pattern || '(?:)', 'gim'), '_') ); - expect( - (await rr(pattern, '_', {pipedData: text, voidIgnoreCase: true})).out, - note - ).toBe(text.replace(new RegExp(pattern || '(?:)', 'gm'), '_')); + expect((await rr(pattern, '_', {pipedData: text, voidIgnoreCase: true})).out, note).toBe( + text.replace(new RegExp(pattern || '(?:)', 'gm'), '_') + ); } }); }); diff --git a/test/fuzzy/void-section.test.js b/test/fuzzy/void-section.test.js index 9364c013..89c8d853 100644 --- a/test/fuzzy/void-section.test.js +++ b/test/fuzzy/void-section.test.js @@ -17,12 +17,8 @@ describe('--void-section', () => { } const section = pattern.replace(/\\/g, '§'); - expect((await rr(pattern, '_', {pipedData: text})).out, note).toBe( - text.replace(regex, '_') - ); - expect((await rr(section, '_', {pipedData: text})).out, note).toBe( - text.replace(regex, '_') - ); + expect((await rr(pattern, '_', {pipedData: text})).out, note).toBe(text.replace(regex, '_')); + expect((await rr(section, '_', {pipedData: text})).out, note).toBe(text.replace(regex, '_')); expect((await rr(pattern, '_', {pipedData: text, voidSection: true})).out, note).toBe( text.replace(regex, '_') ); diff --git a/test/js/basics.test.js b/test/js/basics.test.js index bcde49e4..e650ea6d 100644 --- a/test/js/basics.test.js +++ b/test/js/basics.test.js @@ -56,9 +56,9 @@ describe('replacement', () => { }); test('can refer to named groups', async () => { - expect( - (await rr('(?f)(?.*)', '$$', {pipedData: 'foobar'})).out - ).toBe('oobarf'); + expect((await rr('(?f)(?.*)', '$$', {pipedData: 'foobar'})).out).toBe( + 'oobarf' + ); }); test('can refer to the full match and what is around it', async () => { @@ -134,7 +134,7 @@ describe('files', () => { }); test('are handled in alphabetical order', async () => { - ['c', 'a', 'b'].forEach((name) => fs.writeFileSync(name + '.file', name)); + ['c', 'a', 'b'].forEach(name => fs.writeFileSync(name + '.file', name)); expect((await rr('$', '!', {includeGlob: ['c.file', '*.file'], output: true})).out).toBe( 'a!\nb!\nc!\n' ); @@ -157,7 +157,7 @@ describe('files', () => { }); test('can be pinpointed with braces and negation', async () => { - ['a', 'b', 'c'].forEach((name) => fs.writeFileSync(name + '.file', 'foobar')); + ['a', 'b', 'c'].forEach(name => fs.writeFileSync(name + '.file', 'foobar')); await rr('foo', '1', {includeGlob: ['{a,b}.file']}); await rr('bar', '2', {includeGlob: ['*.file', '!b.file']}); expect(fs.readFileSync('a.file', 'utf8')).toBe('12'); @@ -184,15 +184,12 @@ describe('files', () => { // The file names are read by src/cli.ts, so this runs the CLI itself test.each(['2024', '1e3', '0x10'])( 'can have a name that reads as a number, like %s (#733)', - async (name) => { + async name => { await Bun.write(name, 'foobar'); const cli = path.join(import.meta.dir, '../../src/cli.ts'); - const {stdout, stderr, exitCode} = Bun.spawnSync( - [process.execPath, cli, 'o', 'x', name], - { - stdin: 'ignore', - } - ); + const {stdout, stderr, exitCode} = Bun.spawnSync([process.execPath, cli, 'o', 'x', name], { + stdin: 'ignore', + }); expect({out: stdout.toString(), err: stderr.toString(), exit: exitCode}).toEqual({ out: name + '\n', err: '', diff --git a/test/js/crossover.test.js b/test/js/crossover.test.js index 46fda5af..86ee983d 100644 --- a/test/js/crossover.test.js +++ b/test/js/crossover.test.js @@ -13,10 +13,10 @@ describe('regex flags', () => { flags.filter((flag, n) => bits & (1 << n)) ); - test.each(combinations.map((on) => [on.join(' + ') || 'none', on]))( + test.each(combinations.map(on => [on.join(' + ') || 'none', on]))( '%s gives the same as String.replace', async (name, on) => { - const config = Object.fromEntries(on.map((flag) => [flag, true])); + const config = Object.fromEntries(on.map(flag => [flag, true])); const jsFlags = (config.voidGlobal ? '' : 'g') + (config.voidIgnoreCase ? '' : 'i') + @@ -56,7 +56,7 @@ describe('every pair of flags', () => { 'replacementJs', ]; - const pairs = flags.flatMap((first, n) => flags.slice(n).map((second) => [first, second])); + const pairs = flags.flatMap((first, n) => flags.slice(n).map(second => [first, second])); // Replace "o" with "1" in a file containing "foo". The 1 works as plain text, as javascript and when piped in. test.each(pairs)('%s + %s', async (first, second) => { @@ -99,9 +99,9 @@ describe('same result no matter how it is delivered', () => { test('--output', async () => { fs.writeFileSync('my.file', text); - expect( - (await rr('a.b', '[$&]', {includeGlob: ['my.file'], output: true, ...search})).out - ).toBe(expected); + expect((await rr('a.b', '[$&]', {includeGlob: ['my.file'], output: true, ...search})).out).toBe( + expected + ); }); test.each([ @@ -121,9 +121,9 @@ describe('same result no matter how it is delivered', () => { test('--replacement-pipe and --replacement-js', async () => { fs.writeFileSync('my.file', text); const config = {includeGlob: ['my.file'], output: true, ...search}; - expect( - (await rr('a.b', '_', {...config, replacementPipe: true, pipedData: '[$&]'})).out - ).toBe(expected); + expect((await rr('a.b', '_', {...config, replacementPipe: true, pipedData: '[$&]'})).out).toBe( + expected + ); expect((await rr('a.b', '"[" + $0 + "]"', {...config, replacementJs: true})).out).toBe( expected ); @@ -167,10 +167,8 @@ describe('many flags at once', () => { expect(fs.readFileSync('src/a.test.js', 'utf8')).toBe('VERSION'); expect(fs.readFileSync('src/deep/c.md', 'utf8')).toBe('VERSION'); expect(fs.readFileSync('dist/a.js', 'utf8')).toBe('VERSION'); - expect(fs.readdirSync('src').filter((name) => name.endsWith('.backup'))).toHaveLength(1); - expect(fs.readdirSync('src/deep').filter((name) => name.endsWith('.backup'))).toHaveLength( - 1 - ); + expect(fs.readdirSync('src').filter(name => name.endsWith('.backup'))).toHaveLength(1); + expect(fs.readdirSync('src/deep').filter(name => name.endsWith('.backup'))).toHaveLength(1); }); test('list the first match of each line across files', async () => { diff --git a/test/js/debug.test.js b/test/js/debug.test.js index 396d2296..cb3f2b0c 100644 --- a/test/js/debug.test.js +++ b/test/js/debug.test.js @@ -15,7 +15,7 @@ function runCli(...args) { describe('--debug', () => { test.each(['--debug', '-d'])( '%s prints only the status report, with what went into the engine and what it did', - (flag) => { + flag => { fs.writeFileSync('my.file', 'foobar'); const result = runCli('o', 'x', 'my.file', flag); expect(result.err).toBe(''); diff --git a/test/js/encoding.test.js b/test/js/encoding.test.js index ae651cfc..288f2a47 100644 --- a/test/js/encoding.test.js +++ b/test/js/encoding.test.js @@ -44,9 +44,7 @@ describe('--encoding', () => { encoding: 'latin1', voidIgnoreCase: true, }); - expect(fs.readFileSync('my.file')).toEqual( - Buffer.concat([bytes, Buffer.from('bar'), bytes]) - ); + expect(fs.readFileSync('my.file')).toEqual(Buffer.concat([bytes, Buffer.from('bar'), bytes])); }); // The error message, and not the stack trace from deep inside node, when an encoding is unknown (#690) @@ -85,7 +83,7 @@ describe('--encoding', () => { test('with --keep-backup the backup has the original bytes', async () => { fs.writeFileSync('my.file', latin1()); await rr('æ', 'ø', {includeGlob: ['my.file'], encoding: 'latin1', keepBackup: true}); - const backup = fs.readdirSync('.').find((name) => name.endsWith('.backup')); + const backup = fs.readdirSync('.').find(name => name.endsWith('.backup')); expect(fs.readFileSync(backup)).toEqual(latin1()); }); diff --git a/test/js/exclude-glob.test.js b/test/js/exclude-glob.test.js index c27eab29..699ba215 100644 --- a/test/js/exclude-glob.test.js +++ b/test/js/exclude-glob.test.js @@ -4,12 +4,12 @@ import {rr} from './helper.js'; // Make `names` as files containing "foo" and return the ones changed by replacing "foo" const changed = async (names, config) => { - names.forEach((name) => { + names.forEach(name => { fs.mkdirSync(name.replace(/[^/]*$/, '') || '.', {recursive: true}); fs.writeFileSync(name, 'foo'); }); await rr('foo', 'x', config); - return names.filter((name) => 'x' === fs.readFileSync(name, 'utf8')); + return names.filter(name => 'x' === fs.readFileSync(name, 'utf8')); }; describe('--exclude-glob', () => { @@ -25,22 +25,26 @@ describe('--exclude-glob', () => { test('can be given several times', async () => { const names = ['a.file', 'b.file', 'c.file']; - expect( - await changed(names, {includeGlob: ['*.file'], excludeGlob: ['a.*', 'b.*']}) - ).toEqual(['c.file']); + expect(await changed(names, {includeGlob: ['*.file'], excludeGlob: ['a.*', 'b.*']})).toEqual([ + 'c.file', + ]); }); test('understands braces and **', async () => { const names = ['a.file', 'b.file', 'c.file', 'sub/a.file', 'sub/deep/d.file']; - expect( - await changed(names, {includeGlob: ['**/*.file'], excludeGlob: ['{a,b}.file']}) - ).toEqual(['c.file', 'sub/a.file', 'sub/deep/d.file']); - expect(await changed(names, {includeGlob: ['**/*.file'], excludeGlob: ['sub/**']})).toEqual( - ['a.file', 'b.file', 'c.file'] + expect(await changed(names, {includeGlob: ['**/*.file'], excludeGlob: ['{a,b}.file']})).toEqual( + ['c.file', 'sub/a.file', 'sub/deep/d.file'] ); - expect( - await changed(names, {includeGlob: ['**/*.file'], excludeGlob: ['**/a.file']}) - ).toEqual(['b.file', 'c.file', 'sub/deep/d.file']); + expect(await changed(names, {includeGlob: ['**/*.file'], excludeGlob: ['sub/**']})).toEqual([ + 'a.file', + 'b.file', + 'c.file', + ]); + expect(await changed(names, {includeGlob: ['**/*.file'], excludeGlob: ['**/a.file']})).toEqual([ + 'b.file', + 'c.file', + 'sub/deep/d.file', + ]); }); test('reports when all files are left out', async () => { @@ -68,18 +72,15 @@ describe('--exclude-glob', () => { expect(await changed(names, config)).toEqual(['c.file']); }); - test.each(['output', 'outputMatch'])( - 'with --%s only the files left are sent', - async (flag) => { - fs.writeFileSync('a.file', 'foo'); - fs.writeFileSync('b.file', 'boo'); - const config = {includeGlob: ['*.file'], excludeGlob: ['a.*'], [flag]: true}; - expect((await rr('.oo', '$&', config)).out.trim()).toBe('boo'); - } - ); + test.each(['output', 'outputMatch'])('with --%s only the files left are sent', async flag => { + fs.writeFileSync('a.file', 'foo'); + fs.writeFileSync('b.file', 'boo'); + const config = {includeGlob: ['*.file'], excludeGlob: ['a.*'], [flag]: true}; + expect((await rr('.oo', '$&', config)).out.trim()).toBe('boo'); + }); test('with --verbose the count is the files left', async () => { - ['a', 'b', 'c'].forEach((name) => fs.writeFileSync(name + '.file', 'foo')); + ['a', 'b', 'c'].forEach(name => fs.writeFileSync(name + '.file', 'foo')); const config = {includeGlob: ['*.file'], excludeGlob: ['a.*'], verbose: true}; expect((await rr('o', 'x', config)).err).toContain('2 files found'); }); diff --git a/test/js/exclude-re.test.js b/test/js/exclude-re.test.js index b9f7e614..f6f4f148 100644 --- a/test/js/exclude-re.test.js +++ b/test/js/exclude-re.test.js @@ -4,12 +4,12 @@ import {rr} from './helper.js'; // Make `names` as files containing "foo" and return the ones changed by replacing "foo" const changed = async (names, config) => { - names.forEach((name) => { + names.forEach(name => { fs.mkdirSync(name.replace(/[^/]*$/, '') || '.', {recursive: true}); fs.writeFileSync(name, 'foo'); }); await rr('foo', 'x', config); - return names.filter((name) => 'x' === fs.readFileSync(name, 'utf8')); + return names.filter(name => 'x' === fs.readFileSync(name, 'utf8')); }; describe('--exclude-re', () => { @@ -25,9 +25,9 @@ describe('--exclude-re', () => { test('is a regex', async () => { const names = ['a1.file', 'a2.file', 'ab.file']; - expect( - await changed(names, {includeGlob: ['*.file'], excludeRe: ['a\\d\\.file$']}) - ).toEqual(['ab.file']); + expect(await changed(names, {includeGlob: ['*.file'], excludeRe: ['a\\d\\.file$']})).toEqual([ + 'ab.file', + ]); }); test('can be given several times', async () => { @@ -39,9 +39,10 @@ describe('--exclude-re', () => { test('sees the path of files in sub directories', async () => { const names = ['a.file', 'sub/a.file', 'sub/deep/a.file']; - expect( - await changed(names, {includeGlob: ['**/*.file'], excludeRe: ['^sub/[^/]+$']}) - ).toEqual(['a.file', 'sub/deep/a.file']); + expect(await changed(names, {includeGlob: ['**/*.file'], excludeRe: ['^sub/[^/]+$']})).toEqual([ + 'a.file', + 'sub/deep/a.file', + ]); }); test('reports when all files are left out', async () => { diff --git a/test/js/fix/683.test.js b/test/js/fix/683.test.js index 3888b738..66cc0cd1 100644 --- a/test/js/fix/683.test.js +++ b/test/js/fix/683.test.js @@ -6,9 +6,9 @@ import {rr} from '../helper.js'; // Make `names` as files containing "foo" and return the ones changed by replacing "foo" const changed = async (names, config) => { - names.forEach((name) => fs.writeFileSync(name, 'foo')); + names.forEach(name => fs.writeFileSync(name, 'foo')); await rr('foo', 'x', {includeGlob: ['*.file'], ...config}); - return names.filter((name) => 'x' === fs.readFileSync(name, 'utf8')); + return names.filter(name => 'x' === fs.readFileSync(name, 'utf8')); }; describe('#683 --exclude-re follows the regex flags of the main search', () => { @@ -20,20 +20,14 @@ describe('#683 --exclude-re follows the regex flags of the main search', () => { }); test('ignores case as default', async () => { - expect(await changed(['MY.file', 'your.file'], {excludeRe: ['^my']})).toEqual([ - 'your.file', - ]); - expect(await changed(['my.file', 'your.file'], {excludeRe: ['^MY']})).toEqual([ - 'your.file', - ]); + expect(await changed(['MY.file', 'your.file'], {excludeRe: ['^my']})).toEqual(['your.file']); + expect(await changed(['my.file', 'your.file'], {excludeRe: ['^MY']})).toEqual(['your.file']); }); test('--void-ignore-case makes the case matter', async () => { const names = ['MY.file', 'your.file']; expect(await changed(names, {excludeRe: ['^my'], voidIgnoreCase: true})).toEqual(names); - expect(await changed(names, {excludeRe: ['^MY'], voidIgnoreCase: true})).toEqual([ - 'your.file', - ]); + expect(await changed(names, {excludeRe: ['^MY'], voidIgnoreCase: true})).toEqual(['your.file']); }); test('--dot-all lets a dot match a line break in the path', async () => { diff --git a/test/js/fix/692.test.js b/test/js/fix/692.test.js index a14fad4c..5471e10c 100644 --- a/test/js/fix/692.test.js +++ b/test/js/fix/692.test.js @@ -16,14 +16,14 @@ function run(...args) { describe('#692 single argument', () => { const version = run('--version').out; - test.each(['-v', '-version', '--version'])('%s prints only the version', (arg) => { + test.each(['-v', '-version', '--version'])('%s prints only the version', arg => { const result = run(arg); expect(result.out).toBe(version); expect(result.out.trim()).toMatch(/^\S+$/); expect(result.exit).toBe(0); }); - test.each(['-h', '-help', '--help'])('%s prints the help with exit code 0', (arg) => { + test.each(['-h', '-help', '--help'])('%s prints the help with exit code 0', arg => { const result = run(arg); expect(result.out).toContain('Options:'); expect(result.err).toBe(''); @@ -33,7 +33,7 @@ describe('#692 single argument', () => { // -V is verbose and -H is halt: other flags, not a request for version or help test.each(['my-vile', '-V', 'o-ho', '-H', 'a-v', 'a-h', 'xversion', 'xhelp'])( '%s is a usage error: help on stderr, nothing on stdout, exit code 1', - (arg) => { + arg => { const result = run(arg); expect(result.out).toBe(''); expect(result.err).toContain('Options:'); diff --git a/test/js/fix/699.test.js b/test/js/fix/699.test.js index ffb318f6..e22d8946 100644 --- a/test/js/fix/699.test.js +++ b/test/js/fix/699.test.js @@ -7,9 +7,9 @@ import {rr} from '../helper.js'; // Make `names` as files containing "foo" and return the ones changed by replacing "foo" const changed = async (names, config) => { - names.forEach((name) => fs.writeFileSync(name, 'foo')); + names.forEach(name => fs.writeFileSync(name, 'foo')); await rr('foo', 'x', config); - return names.filter((name) => 'x' === fs.readFileSync(name, 'utf8')); + return names.filter(name => 'x' === fs.readFileSync(name, 'utf8')); }; const voided = {voidEuro: true, voidSection: true}; @@ -37,9 +37,10 @@ describe('#699 € and § are only aliases in the pattern, the replacement and - test('--void-euro and --void-section make no difference', async () => { const names = ['cost€.file', 'cost$.file', 'par§.file']; - expect( - await changed(names, {includeGlob: ['cost€.file', 'par§.file'], ...voided}) - ).toEqual(['cost€.file', 'par§.file']); + expect(await changed(names, {includeGlob: ['cost€.file', 'par§.file'], ...voided})).toEqual([ + 'cost€.file', + 'par§.file', + ]); }); }); @@ -47,28 +48,30 @@ describe('#699 € and § are only aliases in the pattern, the replacement and - const names = ['a[1].file', 'cost$.file', 'cost€.file', 'par§.file']; test('€ and § are plain chars', async () => { - expect( - await changed(names, {includeGlob: ['*.file'], excludeGlob: ['cost€.file']}) - ).toEqual(['a[1].file', 'cost$.file', 'par§.file']); - expect( - await changed(names, {includeGlob: ['*.file'], excludeGlob: ['par§.file']}) - ).toEqual(['a[1].file', 'cost$.file', 'cost€.file']); + expect(await changed(names, {includeGlob: ['*.file'], excludeGlob: ['cost€.file']})).toEqual([ + 'a[1].file', + 'cost$.file', + 'par§.file', + ]); + expect(await changed(names, {includeGlob: ['*.file'], excludeGlob: ['par§.file']})).toEqual([ + 'a[1].file', + 'cost$.file', + 'cost€.file', + ]); }); test('§ does not escape like a backslash does', async () => { expect( await changed(names, {includeGlob: ['*.file'], excludeGlob: ['a\\[1\\].file']}) ).toEqual(['cost$.file', 'cost€.file', 'par§.file']); - expect( - await changed(names, {includeGlob: ['*.file'], excludeGlob: ['a§[1§].file']}) - ).toEqual(names); + expect(await changed(names, {includeGlob: ['*.file'], excludeGlob: ['a§[1§].file']})).toEqual( + names + ); }); test('--void-euro and --void-section make no difference', async () => { const config = {includeGlob: ['*.file'], excludeGlob: ['cost€.file', 'par§.file']}; - expect(await changed(names, {...config, ...voided})).toEqual( - await changed(names, config) - ); + expect(await changed(names, {...config, ...voided})).toEqual(await changed(names, config)); }); }); @@ -99,9 +102,7 @@ describe('#699 € and § are only aliases in the pattern, the replacement and - test('the replacement', async () => { expect((await rr('(b)', '[€1§]', {pipedData: 'foobar'})).out).toBe('foo[b\\]ar'); - expect((await rr('(b)', '[€1§]', {pipedData: 'foobar', ...voided})).out).toBe( - 'foo[€1§]ar' - ); + expect((await rr('(b)', '[€1§]', {pipedData: 'foobar', ...voided})).out).toBe('foo[€1§]ar'); }); test('the replacement with --replacement-js', async () => { @@ -111,9 +112,9 @@ describe('#699 € and § are only aliases in the pattern, the replacement and - test('--exclude-re', async () => { const names = ['a1.file', 'ab.file', 'ab.files']; - expect(await changed(names, {includeGlob: ['a*'], excludeRe: ['§d', 'file€']})).toEqual( - ['ab.files'] - ); + expect(await changed(names, {includeGlob: ['a*'], excludeRe: ['§d', 'file€']})).toEqual([ + 'ab.files', + ]); expect( await changed(names, {includeGlob: ['a*'], excludeRe: ['§d', 'file€'], ...voided}) ).toEqual(names); diff --git a/test/js/fix/703.test.js b/test/js/fix/703.test.js index 169ea0b1..7e578071 100644 --- a/test/js/fix/703.test.js +++ b/test/js/fix/703.test.js @@ -39,7 +39,7 @@ describe('#703 the names of affected files', () => { expect(result.err).toContain('Nothing changed in: b.file'); }); - test.each(['quiet', 'quietTotal'])('are not printed with --%s', async (flag) => { + test.each(['quiet', 'quietTotal'])('are not printed with --%s', async flag => { expect(await run({[flag]: true})).toEqual({out: '', err: '', exit: null}); expect(await Bun.file('c.file').text()).toBe('fxx'); }); @@ -68,9 +68,7 @@ describe('#703 the names of affected files', () => { test('keeps a name with a line break in one piece', async () => { await Bun.write('my\n.file', 'foo'); - expect((await rr('o', 'x', {includeGlob: ['*.file'], null: true})).out).toBe( - 'my\n.file\0' - ); + expect((await rr('o', 'x', {includeGlob: ['*.file'], null: true})).out).toBe('my\n.file\0'); }); }); @@ -89,12 +87,8 @@ describe('#703 the names of affected files', () => { test('has the € and § aliases like the replacement', async () => { expect((await run({nameDelimiter: '€§'})).out).toBe('a.file$\\c.file$\\'); - expect((await run({nameDelimiter: '€§', voidEuro: true})).out).toBe( - 'a.file€\\c.file€\\' - ); - expect((await run({nameDelimiter: '€§', voidSection: true})).out).toBe( - 'a.file$§c.file$§' - ); + expect((await run({nameDelimiter: '€§', voidEuro: true})).out).toBe('a.file€\\c.file€\\'); + expect((await run({nameDelimiter: '€§', voidSection: true})).out).toBe('a.file$§c.file$§'); }); }); @@ -219,9 +213,7 @@ describe('#703 the names of affected files', () => { test('leaves piped data as it is by default', async () => { expect((await rr('o', 'x', {pipedData: 'foo'})).out).toBe('fxx'); - expect((await rr('o', 'x', {pipedData: 'foo', contentDelimiter: ', '})).out).toBe( - 'fxx' - ); + expect((await rr('o', 'x', {pipedData: 'foo', contentDelimiter: ', '})).out).toBe('fxx'); }); test('is put after the last match, from a file or a pipe', async () => { @@ -292,9 +284,7 @@ describe('#703 the names of affected files', () => { }); test('adds nothing when nothing is printed', async () => { - expect( - (await rr('nope', 'x', {pipedData: 'foo', outputMatch: true, nl: true})).out - ).toBe(''); + expect((await rr('nope', 'x', {pipedData: 'foo', outputMatch: true, nl: true})).out).toBe(''); await Bun.write('a.file', 'foo'); expect((await rr('nope', 'x', {includeGlob: ['a.file'], nl: true})).out).toBe(''); }); @@ -329,9 +319,7 @@ describe('#703 the names of affected files', () => { }); test('the most specific delimiter wins', async () => { - expect((await run({output: true, delimiter: ', ', null: true})).out).toBe( - 'fxx, bar, fxx, ' - ); + expect((await run({output: true, delimiter: ', ', null: true})).out).toBe('fxx, bar, fxx, '); expect( await run({ output: true, @@ -362,7 +350,7 @@ describe('#703 the names of affected files', () => { expect((await run({[flag]: true})).err).toBe((await run()).out); }); - test.each(['quiet', 'quietTotal'])('are not printed with --%s', async (quiet) => { + test.each(['quiet', 'quietTotal'])('are not printed with --%s', async quiet => { expect(await run({[flag]: true, [quiet]: true})).toEqual({out, err: '', exit: null}); }); @@ -389,9 +377,7 @@ describe('#703 the names of affected files', () => { const file = path.resolve('other', 'my.file'); await Bun.write(file, 'foo'); process.chdir('work'); - expect((await rr('o', 'x', {includeGlob: [file], absolutePath: true})).out).toBe( - file + '\n' - ); + expect((await rr('o', 'x', {includeGlob: [file], absolutePath: true})).out).toBe(file + '\n'); expect(await Bun.file(file).text()).toBe('fxx'); }); diff --git a/test/js/fix/705.test.js b/test/js/fix/705.test.js index 210057b7..5526b0ab 100644 --- a/test/js/fix/705.test.js +++ b/test/js/fix/705.test.js @@ -5,7 +5,7 @@ import fs from 'fs'; import {engine} from '../../../src/engine.ts'; import {rr} from '../helper.js'; -const content = (names) => names.map((name) => fs.readFileSync(name, 'utf8')); +const content = names => names.map(name => fs.readFileSync(name, 'utf8')); // The name of the backup is longer than a file system allows, so the file can not be renamed const tooLong = 'b'.repeat(240) + '.file'; @@ -32,7 +32,7 @@ describe('#705 the engine returns a promise that resolves when all files are don test('waits for every file', async () => { const names = Array.from({length: 20}, (_, n) => `my${n}.file`); - names.forEach((name) => fs.writeFileSync(name, 'foo')); + names.forEach(name => fs.writeFileSync(name, 'foo')); const result = await rr('o', 'x', {includeGlob: ['*.file'], voidAsync: false}); @@ -76,7 +76,7 @@ describe('#705 the engine returns a promise that resolves when all files are don describe('a file with an error', () => { test.each(flows)('does not stop the other files with %s', async (name, flags) => { - ['a.file', tooLong, 'c.file'].forEach((name) => fs.writeFileSync(name, 'foo')); + ['a.file', tooLong, 'c.file'].forEach(name => fs.writeFileSync(name, 'foo')); const result = await rr('o', 'x', {includeGlob: ['*.file'], ...flags}); diff --git a/test/js/fix/708.test.js b/test/js/fix/708.test.js index f2b4dd59..3fc6e88f 100644 --- a/test/js/fix/708.test.js +++ b/test/js/fix/708.test.js @@ -10,7 +10,7 @@ const workers = Math.max(16, os.availableParallelism() * 2); // Make `count` files with the content `foo` and give their names async function makeFiles(count) { const names = Array.from({length: count}, (_, i) => `file-${i}.txt`); - await Promise.all(names.map((name) => Bun.write(name, 'foo'))); + await Promise.all(names.map(name => Bun.write(name, 'foo'))); return names; } diff --git a/test/js/fix/718.test.js b/test/js/fix/718.test.js index 8d01c712..21697805 100644 --- a/test/js/fix/718.test.js +++ b/test/js/fix/718.test.js @@ -5,11 +5,11 @@ import fs from 'fs'; import path from 'path'; import {rr} from '../helper.js'; -const content = (name) => fs.readFileSync(name, 'utf8'); +const content = name => fs.readFileSync(name, 'utf8'); // Make each file with the content `foo` function makeFiles(...names) { - names.forEach((name) => { + names.forEach(name => { fs.mkdirSync(path.dirname(name), {recursive: true}); fs.writeFileSync(name, 'foo'); }); @@ -18,7 +18,7 @@ function makeFiles(...names) { describe('#718 a path that is a file is used as it is', () => { test.each(['my (1).file', '(draft).file', '{a,b}.file', '!important.file', 'a+(b).file'])( '%s is found', - async (name) => { + async name => { makeFiles(name); expect(await rr('o', 'x', {includeGlob: [name]})).toEqual({ out: name + '\n', @@ -47,9 +47,7 @@ describe('#718 a path that is a file is used as it is', () => { test('in a folder', async () => { makeFiles('pages/[id].file', 'pages/i.file'); - expect((await rr('o', 'x', {includeGlob: ['pages/[id].file']})).out).toBe( - 'pages/[id].file\n' - ); + expect((await rr('o', 'x', {includeGlob: ['pages/[id].file']})).out).toBe('pages/[id].file\n'); expect(content('pages/i.file')).toBe('foo'); }); }); @@ -152,9 +150,7 @@ describe('#718 with --exclude-re', () => { test('it sees the full path with --absolute-path', async () => { makeFiles('a.file'); - expect((await rr('o', 'x', {includeGlob: ['a.file'], excludeRe: ['^/']})).out).toBe( - 'a.file\n' - ); + expect((await rr('o', 'x', {includeGlob: ['a.file'], excludeRe: ['^/']})).out).toBe('a.file\n'); fs.writeFileSync('a.file', 'foo'); const config = {includeGlob: ['a.file'], excludeRe: ['^/'], absolutePath: true}; expect((await rr('o', 'x', config)).exit).toBe(1); diff --git a/test/js/fix/719.test.js b/test/js/fix/719.test.js index 96ad634d..17fc6f7e 100644 --- a/test/js/fix/719.test.js +++ b/test/js/fix/719.test.js @@ -18,7 +18,7 @@ describe('#719 a warning when piped data is not used', () => { expect(await Bun.file('my.file').text()).toBe('foo_ar'); }); - test.each(['quiet', 'quietTotal'])('is not shown with --%s', async (flag) => { + test.each(['quiet', 'quietTotal'])('is not shown with --%s', async flag => { expect(await piped({[flag]: true})).toEqual({out: '', err: '', exit: null}); }); @@ -45,7 +45,7 @@ describe('#719 a warning when piped data is not used', () => { expect(await Bun.file('my.file').text()).toBe('fooxar'); }); - test.each([null, '', '\n', '\r\n'])('is not given when %j is piped in', async (pipedData) => { + test.each([null, '', '\n', '\r\n'])('is not given when %j is piped in', async pipedData => { expect(await piped({pipedData})).toEqual({out: expectedOutput, err: '', exit: null}); }); diff --git a/test/js/fix/726.test.js b/test/js/fix/726.test.js index 57d0b47a..843e7147 100644 --- a/test/js/fix/726.test.js +++ b/test/js/fix/726.test.js @@ -55,7 +55,7 @@ describe('#726 a file given with an absolute path is changed', () => { await rr('o', 'x', {includeGlob: [file], keepBackup: true, ...flags}); const [backup, ...rest] = fs .readdirSync(path.dirname(file)) - .filter((name) => name !== 'my.file'); + .filter(name => name !== 'my.file'); expect(rest).toEqual([]); expect(backup).toMatch(/^my\.file\..+\.backup$/); expect(await Bun.file(path.join(path.dirname(file), backup)).text()).toBe('foobar'); diff --git a/test/js/fix/728.test.js b/test/js/fix/728.test.js index ef4c1e8c..ac4359e2 100644 --- a/test/js/fix/728.test.js +++ b/test/js/fix/728.test.js @@ -44,7 +44,7 @@ describe('#728 the exit code is 1 when a file gives an error', () => { } }); - test.each(['quiet', 'quietTotal'])('also with --%s', async (flag) => { + test.each(['quiet', 'quietTotal'])('also with --%s', async flag => { expect((await rr('o', 'x', {...oneUnreadable(), [flag]: true})).exit).toBe(1); }); }); diff --git a/test/js/fix/742.test.js b/test/js/fix/742.test.js index 855433ff..9e37236c 100644 --- a/test/js/fix/742.test.js +++ b/test/js/fix/742.test.js @@ -124,9 +124,7 @@ describe('#742 the engine part of the status', () => { expect(await rrStatus('o', 'x', {pipedData: 'foo', verbose: true})).not.toHaveProperty( 'engine' ); - expect(await rrStatus('o', 'x', {pipedData: 'foo', status: true})).not.toHaveProperty( - 'engine' - ); + expect(await rrStatus('o', 'x', {pipedData: 'foo', status: true})).not.toHaveProperty('engine'); const status = await rrStatus('o', 'x', { pipedData: 'foo', statusCompact: true, @@ -214,7 +212,7 @@ describe('#742 the CLI', () => { test.each(['--status-compact', '-S'])( '%s prints the status report on one line, with no line break in front', - (flag) => { + flag => { fs.writeFileSync('a.file', 'foo'); const result = runCli('o', 'x', 'a.file', flag, '--quiet-total'); expect(result.out).toBe( diff --git a/test/js/halt.test.js b/test/js/halt.test.js index 455faf34..42bd66c8 100644 --- a/test/js/halt.test.js +++ b/test/js/halt.test.js @@ -58,7 +58,7 @@ describe('--halt', () => { expect(result.out).toMatch(/-H,\s*--halt,\s*--bail/); }); - test.each(['--bail', '--halt', '-H'])('%s stops on the first error like --halt', (flag) => { + test.each(['--bail', '--halt', '-H'])('%s stops on the first error like --halt', flag => { const result = runCli('o', 'x', 'nope.file', flag); expect(result.err).toContain('0 files found'); expect(result.exit).toBe(1); @@ -73,7 +73,7 @@ describe('--halt', () => { }); describe('combined', () => { - test.each(['quiet', 'quietTotal'])('with --%s it still stops', async (flag) => { + test.each(['quiet', 'quietTotal'])('with --%s it still stops', async flag => { const result = await rr('o', 'x', { includeGlob: ['nope.file'], halt: true, diff --git a/test/js/helper.js b/test/js/helper.js index cec856e2..4dc9779a 100644 --- a/test/js/helper.js +++ b/test/js/helper.js @@ -37,14 +37,14 @@ async function run(pattern, replacement, config) { let status; const spies = [ - spyOn(process.stdout, 'write').mockImplementation((data) => { + spyOn(process.stdout, 'write').mockImplementation(data => { result.out += data; return true; }), spyOn(console, 'error').mockImplementation((...data) => { result.err += data.join(' ') + '\n'; }), - spyOn(process.stderr, 'write').mockImplementation((data) => { + spyOn(process.stderr, 'write').mockImplementation(data => { result.err += data; return true; }), @@ -81,7 +81,7 @@ async function run(pattern, replacement, config) { status = e.status; result.exit = 1; } finally { - spies.forEach((spy) => spy.mockRestore()); + spies.forEach(spy => spy.mockRestore()); } return {result, status}; @@ -89,7 +89,7 @@ async function run(pattern, replacement, config) { // What the content of the files gives by default: a line break after each item, unless it already ends with one export function ended(...items) { - return items.map((item) => (item.endsWith('\n') ? item : item + '\n')).join(''); + return items.map(item => (item.endsWith('\n') ? item : item + '\n')).join(''); } // Fuzz tests get new input on every run. Set RR_FUZZ_SEED to repeat a run. @@ -113,13 +113,11 @@ export function random(id) { }; const rnd = { - int: (max) => Math.floor(next() * (max + 1)), - pick: (list) => list[rnd.int(list.length - 1)], + int: max => Math.floor(next() * (max + 1)), + pick: list => list[rnd.int(list.length - 1)], // String of min to max elements from alphabet (a string or an array of strings) text: (alphabet, min, max) => - Array.from({length: min + rnd.int(max - min)}, () => - rnd.pick(Array.from(alphabet)) - ).join(''), + Array.from({length: min + rnd.int(max - min)}, () => rnd.pick(Array.from(alphabet))).join(''), }; return rnd; diff --git a/test/js/keep-backup.test.js b/test/js/keep-backup.test.js index 6d81eac1..ca071e0f 100644 --- a/test/js/keep-backup.test.js +++ b/test/js/keep-backup.test.js @@ -2,7 +2,7 @@ import {describe, test, expect} from 'bun:test'; import fs from 'fs'; import {rr} from './helper.js'; -const backups = (dir = '.') => fs.readdirSync(dir).filter((name) => name.endsWith('.backup')); +const backups = (dir = '.') => fs.readdirSync(dir).filter(name => name.endsWith('.backup')); describe('--keep-backup', () => { test('keeps the original content in a backup file next to the file', async () => { @@ -37,8 +37,8 @@ describe('--keep-backup', () => { fs.writeFileSync('b.file', 'bar'); fs.writeFileSync('sub/c.file', 'foo'); await rr('foo', 'x', {includeGlob: ['**/*.file'], keepBackup: true}); - expect(backups().map((name) => name.slice(0, 7))).toEqual(['a.file.']); - expect(backups('sub').map((name) => name.slice(0, 7))).toEqual(['c.file.']); + expect(backups().map(name => name.slice(0, 7))).toEqual(['a.file.']); + expect(backups('sub').map(name => name.slice(0, 7))).toEqual(['c.file.']); expect(fs.readFileSync('sub/' + backups('sub')[0], 'utf8')).toBe('foo'); }); @@ -57,14 +57,11 @@ describe('--keep-backup', () => { expect(fs.readFileSync(backups()[0], 'utf8')).toBe('foobar'); }); - test.each(['output', 'outputMatch'])( - 'with --%s there is nothing to back up', - async (flag) => { - fs.writeFileSync('my.file', 'foobar'); - await rr('o', 'x', {includeGlob: ['my.file'], keepBackup: true, [flag]: true}); - expect(fs.readdirSync('.')).toEqual(['my.file']); - } - ); + test.each(['output', 'outputMatch'])('with --%s there is nothing to back up', async flag => { + fs.writeFileSync('my.file', 'foobar'); + await rr('o', 'x', {includeGlob: ['my.file'], keepBackup: true, [flag]: true}); + expect(fs.readdirSync('.')).toEqual(['my.file']); + }); test('with --replacement-js', async () => { fs.writeFileSync('my.file', 'foobar'); @@ -81,7 +78,7 @@ describe('--keep-backup', () => { fs.writeFileSync('my.file', 'foobar'); await rr('o', 'x', {includeGlob: ['my.*'], keepBackup: true}); // The time in the name of the backup is in milliseconds - await new Promise((resolve) => setTimeout(resolve, 5)); + await new Promise(resolve => setTimeout(resolve, 5)); await rr('x', 'y', { includeGlob: ['my.*'], excludeGlob: ['*.backup'], @@ -90,7 +87,7 @@ describe('--keep-backup', () => { expect(fs.readFileSync('my.file', 'utf8')).toBe('fyybar'); expect( backups() - .map((name) => fs.readFileSync(name, 'utf8')) + .map(name => fs.readFileSync(name, 'utf8')) .sort() ).toEqual(['foobar', 'fxxbar']); }); diff --git a/test/js/literal.test.js b/test/js/literal.test.js index 9360b59b..99d0fb4c 100644 --- a/test/js/literal.test.js +++ b/test/js/literal.test.js @@ -12,7 +12,7 @@ describe('--literal', () => { expect((await rr('.', 'x', {pipedData: 'a.b'})).out).toBe('xxx'); }); - test.each(Array.from('-[]{}()*+?.,/\\^$|#'))('takes %s literally', async (char) => { + test.each(Array.from('-[]{}()*+?.,/\\^$|#'))('takes %s literally', async char => { const text = `a${char}b${char}${char}c`; expect((await rr(char, '_', {pipedData: text, literal: true})).out).toBe('a_b__c'); }); @@ -38,9 +38,7 @@ describe('--literal', () => { describe('combined', () => { test('is still case insensitive and global', async () => { - expect((await rr('a.', 'x', {pipedData: 'a. A. ab', literal: true})).out).toBe( - 'x x ab' - ); + expect((await rr('a.', 'x', {pipedData: 'a. A. ab', literal: true})).out).toBe('x x ab'); }); test('with --void-ignore-case and --void-global', async () => { @@ -56,12 +54,12 @@ describe('--literal', () => { test('€ and § are still aliases for $ and \\ unless voided', async () => { expect((await rr('€', 'x', {pipedData: '€ $', literal: true})).out).toBe('€ x'); expect((await rr('§', 'x', {pipedData: '§ \\', literal: true})).out).toBe('§ x'); - expect( - (await rr('€', 'x', {pipedData: '€ $', literal: true, voidEuro: true})).out - ).toBe('x $'); - expect( - (await rr('§', 'x', {pipedData: '§ \\', literal: true, voidSection: true})).out - ).toBe('x \\'); + expect((await rr('€', 'x', {pipedData: '€ $', literal: true, voidEuro: true})).out).toBe( + 'x $' + ); + expect((await rr('§', 'x', {pipedData: '§ \\', literal: true, voidSection: true})).out).toBe( + 'x \\' + ); }); test('with --output-match', async () => { @@ -85,7 +83,7 @@ describe('--literal', () => { test.each([...'-,# []{}()*+?./\\^$|'])( 'with --unicode finds a pattern with %j in it (#686)', - async (char) => { + async char => { const pattern = `a${char}b`; const config = {pipedData: pattern, literal: true, unicode: true}; expect(await rr(pattern, 'x', config)).toEqual({out: 'x', err: '', exit: null}); diff --git a/test/js/output-match.test.js b/test/js/output-match.test.js index a598017d..f605a8cf 100644 --- a/test/js/output-match.test.js +++ b/test/js/output-match.test.js @@ -4,18 +4,14 @@ import {rr} from './helper.js'; describe('--output-match', () => { test('prints each match on its own line', async () => { - expect((await rr('[fb].', '_', {pipedData: 'foobar', outputMatch: true})).out).toBe( - 'fo\nba\n' - ); + expect((await rr('[fb].', '_', {pipedData: 'foobar', outputMatch: true})).out).toBe('fo\nba\n'); }); test('prints only the groups (with nothing in between) if the pattern has groups', async () => { expect((await rr('([fb](.))', '_', {pipedData: 'foobar', outputMatch: true})).out).toBe( 'foo\nbaa\n' ); - expect((await rr('(f)o(o)', '_', {pipedData: 'foobar', outputMatch: true})).out).toBe( - 'fo\n' - ); + expect((await rr('(f)o(o)', '_', {pipedData: 'foobar', outputMatch: true})).out).toBe('fo\n'); }); test('prints nothing if there is no match', async () => { @@ -43,9 +39,9 @@ describe('--output-match', () => { test('prints matches from several files in alphabetical order', async () => { fs.writeFileSync('b.file', 'boo'); fs.writeFileSync('a.file', 'foo'); - expect( - (await rr('.o', '_', {includeGlob: ['b.file', 'a.file'], outputMatch: true})).out - ).toBe('fo\nbo\n'); + expect((await rr('.o', '_', {includeGlob: ['b.file', 'a.file'], outputMatch: true})).out).toBe( + 'fo\nbo\n' + ); }); test('prints a match that spans lines as it is', async () => { @@ -57,9 +53,7 @@ describe('--output-match', () => { }); test('prints nothing for a group that did not take part in the match (#684)', async () => { - expect((await rr('(f)|(b)', '_', {pipedData: 'foobar', outputMatch: true})).out).toBe( - 'f\nb\n' - ); + expect((await rr('(f)|(b)', '_', {pipedData: 'foobar', outputMatch: true})).out).toBe('f\nb\n'); }); test('prints named groups like any other group (#685)', async () => { @@ -97,9 +91,7 @@ describe('--output-match', () => { test('with --replacement-js the code is not run', async () => { const config = {pipedData: 'foobar', outputMatch: true, replacementJs: true}; - expect((await rr('[fb].', 'throw new Error("should not run")', config)).out).toBe( - 'fo\nba\n' - ); + expect((await rr('[fb].', 'throw new Error("should not run")', config)).out).toBe('fo\nba\n'); }); test('with --replacement-pipe the piped replacement is not used', async () => { diff --git a/test/js/output.test.js b/test/js/output.test.js index 4aef5514..d0cda2f1 100644 --- a/test/js/output.test.js +++ b/test/js/output.test.js @@ -85,7 +85,7 @@ describe('--output', () => { test.each([{voidAsync: true}, {voidBackup: true}, {voidAsync: true, voidBackup: true}])( 'with %o the file is still left alone', - async (config) => { + async config => { fs.writeFileSync('my.file', 'foobar'); const result = await rr('o', 'x', { includeGlob: ['my.file'], diff --git a/test/js/quiet-total.test.js b/test/js/quiet-total.test.js index 379be139..6a507356 100644 --- a/test/js/quiet-total.test.js +++ b/test/js/quiet-total.test.js @@ -13,9 +13,9 @@ describe('--quiet-total', () => { test('does not display errors', async () => { expect((await rr('(', 'x', {pipedData: 'foobar', quietTotal: true})).err).toBe(''); expect((await rr('o', 'x', {includeGlob: ['nope.file'], quietTotal: true})).err).toBe(''); - expect( - (await rr('o', 'x', {pipedData: 'foobar', engine: 'nope', quietTotal: true})).err - ).toBe(''); + expect((await rr('o', 'x', {pipedData: 'foobar', engine: 'nope', quietTotal: true})).err).toBe( + '' + ); }); test('is not the default', async () => { @@ -36,7 +36,7 @@ describe('--quiet-total', () => { expect(await rr('o', 'x', config)).toEqual({out: '', err: '', exit: null}); }); - test.each(['output', 'outputMatch'])('with --%s stdout is not affected', async (flag) => { + test.each(['output', 'outputMatch'])('with --%s stdout is not affected', async flag => { fs.writeFileSync('my.file', 'foobar'); const result = await rr('o', 'x', { includeGlob: ['my.file'], diff --git a/test/js/quiet.test.js b/test/js/quiet.test.js index 95539ae5..8b54ab53 100644 --- a/test/js/quiet.test.js +++ b/test/js/quiet.test.js @@ -42,7 +42,7 @@ describe('--quiet', () => { expect(result.err).toContain('Open sync: my.file'); }); - test.each(['output', 'outputMatch'])('with --%s stdout is not affected', async (flag) => { + test.each(['output', 'outputMatch'])('with --%s stdout is not affected', async flag => { fs.writeFileSync('my.file', 'foobar'); const result = await rr('o', 'x', { includeGlob: ['my.file'], diff --git a/test/js/replacement-js.test.js b/test/js/replacement-js.test.js index 2bead76f..ee819f0a 100644 --- a/test/js/replacement-js.test.js +++ b/test/js/replacement-js.test.js @@ -84,9 +84,9 @@ describe('--replacement-js', () => { }); test('can be more than nine groups', async () => { - expect( - await js('(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)', '$11 + $10 + $1', 'abcdefghijk') - ).toBe('kja'); + expect(await js('(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)', '$11 + $10 + $1', 'abcdefghijk')).toBe( + 'kja' + ); }); test('make the code run once per match', async () => { @@ -105,9 +105,9 @@ describe('--replacement-js', () => { describe('variables', () => { test('fs, path and globs are available', async () => { - expect( - await inFile('typeof fs.readFileSync + typeof path.join + typeof globs.sync') - ).toBe('functionfunctionfunction'); + expect(await inFile('typeof fs.readFileSync + typeof path.join + typeof globs.sync')).toBe( + 'functionfunctionfunction' + ); expect(await inFile('fs.readFileSync(file, "utf8").toUpperCase()')).toBe('FOOBAR'); expect(await inFile('globs.sync("*").join()')).toBe('my.file'); }); @@ -202,9 +202,7 @@ describe('--replacement-js', () => { expect(await inFile('time')).toMatch(timestamp); expect(await inFile('now === time')).toBe('true'); expect(await inFile('time_obj instanceof Date')).toBe('true'); - expect(Math.abs(Date.now() - Number(await inFile('time_obj.getTime()')))).toBeLessThan( - 60000 - ); + expect(Math.abs(Date.now() - Number(await inFile('time_obj.getTime()')))).toBeLessThan(60000); }); test('mtime and ctime tell about the last change of the file', async () => { @@ -250,15 +248,15 @@ describe('--replacement-js', () => { 'bytes', 'size', ]; - const code = `[${names.map((name) => `${name}_ === ${name} + " "`).join()}].join()`; + const code = `[${names.map(name => `${name}_ === ${name} + " "`).join()}].join()`; expect(await inFile(code)).toBe(names.map(() => 'true').join()); expect(await js('foobar', code, 'foobar')).toBe(names.map(() => 'true').join()); }); test('are the same when the code runs once per match', async () => { - expect( - await inFile('$0; [filename, name, ext, bytes, text, find, _, nl].join("|")') - ).toBe('my.file|my|.file|6|foobar|^[^]*$| |\n'); + expect(await inFile('$0; [filename, name, ext, bytes, text, find, _, nl].join("|")')).toBe( + 'my.file|my|.file|6|foobar|^[^]*$| |\n' + ); }); test('follow the file when several files are handled', async () => { diff --git a/test/js/replacement-pipe.test.js b/test/js/replacement-pipe.test.js index b440232d..b0b8ad7d 100644 --- a/test/js/replacement-pipe.test.js +++ b/test/js/replacement-pipe.test.js @@ -40,9 +40,7 @@ describe('--replacement-pipe', () => { test('lets the piped data refer to the match and its groups', async () => { fs.writeFileSync('my.file', 'foobar'); const config = {includeGlob: ['my.file'], replacementPipe: true, output: true}; - expect((await rr('(o)(b)', '_', {...config, pipedData: '$2$1[$&]'})).out).toBe( - 'fobo[ob]ar\n' - ); + expect((await rr('(o)(b)', '_', {...config, pipedData: '$2$1[$&]'})).out).toBe('fobo[ob]ar\n'); }); test('can be an empty string to remove what is matched', async () => { diff --git a/test/js/unicode.test.js b/test/js/unicode.test.js index a4b0474d..df24f638 100644 --- a/test/js/unicode.test.js +++ b/test/js/unicode.test.js @@ -18,12 +18,11 @@ describe('--unicode', () => { test('understands unicode property escapes', async () => { expect( - (await rr('\\p{Lu}', '_', {pipedData: 'aÆbÅc', unicode: true, voidIgnoreCase: true})) - .out + (await rr('\\p{Lu}', '_', {pipedData: 'aÆbÅc', unicode: true, voidIgnoreCase: true})).out ).toBe('a_b_c'); - expect( - (await rr('\\p{Script=Greek}+', '_', {pipedData: 'abc αβγ', unicode: true})).out - ).toBe('abc _'); + expect((await rr('\\p{Script=Greek}+', '_', {pipedData: 'abc αβγ', unicode: true})).out).toBe( + 'abc _' + ); }); test('counts an emoji as one char in quantifiers and classes', async () => { diff --git a/test/js/verbose.test.js b/test/js/verbose.test.js index 8bce918d..dcaf7ac3 100644 --- a/test/js/verbose.test.js +++ b/test/js/verbose.test.js @@ -29,7 +29,7 @@ describe('--verbose', () => { }); test('tells how many files were found', async () => { - ['a', 'b', 'c'].forEach((name) => fs.writeFileSync(name + '.file', 'foo')); + ['a', 'b', 'c'].forEach(name => fs.writeFileSync(name + '.file', 'foo')); expect((await rr('o', 'x', {includeGlob: ['*.file'], verbose: true})).err).toContain( '3 files found' ); diff --git a/test/js/void-async.test.js b/test/js/void-async.test.js index df3163f3..0542b42d 100644 --- a/test/js/void-async.test.js +++ b/test/js/void-async.test.js @@ -6,7 +6,7 @@ import {rr} from './helper.js'; describe('--void-async', () => { test('is done with a file before the next one is opened', async () => { - ['a', 'b'].forEach((name) => fs.writeFileSync(name + '.file', 'foo')); + ['a', 'b'].forEach(name => fs.writeFileSync(name + '.file', 'foo')); const config = {includeGlob: ['*.file'], voidAsync: true, verbose: true}; const result = await rr('o', 'x', config); expect(result.err.trim().split('\n')).toEqual([ @@ -22,7 +22,7 @@ describe('--void-async', () => { }); test('is not the default: all files are opened before the first one is done', async () => { - ['a', 'b'].forEach((name) => fs.writeFileSync(name + '.file', 'foo')); + ['a', 'b'].forEach(name => fs.writeFileSync(name + '.file', 'foo')); const config = {includeGlob: ['*.file'], voidAsync: false, verbose: true}; const result = await rr('o', 'x', config); const lines = result.err.split('\n'); @@ -34,14 +34,11 @@ describe('--void-async', () => { // Either file can be read first expect(lines[3]).toMatch(/^Work on content from: [ab]\.file$/); expect(result.out.split('\n').sort()).toEqual(['', 'a.file', 'b.file']); - expect(['a', 'b'].map((name) => fs.readFileSync(name + '.file', 'utf8'))).toEqual([ - 'fxx', - 'fxx', - ]); + expect(['a', 'b'].map(name => fs.readFileSync(name + '.file', 'utf8'))).toEqual(['fxx', 'fxx']); }); test('handles the files one by one in alphabetical order', async () => { - ['c', 'a', 'd', 'b'].forEach((name) => fs.writeFileSync(name + '.file', 'foo')); + ['c', 'a', 'd', 'b'].forEach(name => fs.writeFileSync(name + '.file', 'foo')); const result = await rr('o', 'x', {includeGlob: ['*.file'], voidAsync: true}); expect(result.out).toBe('a.file\nb.file\nc.file\nd.file\n'); }); @@ -81,21 +78,21 @@ describe('--void-async', () => { test.each(['output', 'outputMatch'])( 'is forced by --%s on several files to keep the order', - async (flag) => { - ['b', 'c', 'a'].forEach((name) => fs.writeFileSync(name + '.file', name + '\n')); + async flag => { + ['b', 'c', 'a'].forEach(name => fs.writeFileSync(name + '.file', name + '\n')); const config = {includeGlob: ['*.file'], voidAsync: false, [flag]: true}; expect((await rr('[abc]', '$&', config)).out).toBe('a\nb\nc\n'); } ); test('with --replacement-js and several files', async () => { - ['a', 'b', 'c'].forEach((name) => fs.writeFileSync(name + '.file', 'foo')); + ['a', 'b', 'c'].forEach(name => fs.writeFileSync(name + '.file', 'foo')); await rr('foo', 'name + name', { includeGlob: ['*.file'], voidAsync: true, replacementJs: true, }); - expect(['a', 'b', 'c'].map((name) => fs.readFileSync(name + '.file', 'utf8'))).toEqual([ + expect(['a', 'b', 'c'].map(name => fs.readFileSync(name + '.file', 'utf8'))).toEqual([ 'aa', 'bb', 'cc', diff --git a/test/js/void-backup.test.js b/test/js/void-backup.test.js index 0a0a846c..288677c2 100644 --- a/test/js/void-backup.test.js +++ b/test/js/void-backup.test.js @@ -20,9 +20,9 @@ describe('--void-backup', () => { }); test('handles several files', async () => { - ['a', 'b', 'c'].forEach((name) => fs.writeFileSync(name + '.file', 'foo' + name)); + ['a', 'b', 'c'].forEach(name => fs.writeFileSync(name + '.file', 'foo' + name)); await rr('foo', 'x', {includeGlob: ['*.file'], voidBackup: true}); - expect(['a', 'b', 'c'].map((name) => fs.readFileSync(name + '.file', 'utf8'))).toEqual([ + expect(['a', 'b', 'c'].map(name => fs.readFileSync(name + '.file', 'utf8'))).toEqual([ 'xa', 'xb', 'xc', @@ -30,7 +30,7 @@ describe('--void-backup', () => { }); describe('combined', () => { - test.each([true, false])('with --void-async set to %p', async (voidAsync) => { + test.each([true, false])('with --void-async set to %p', async voidAsync => { fs.writeFileSync('my.file', 'foobar'); await rr('o', 'x', {includeGlob: ['my.file'], voidBackup: true, voidAsync}); expect(fs.readFileSync('my.file', 'utf8')).toBe('fxxbar'); diff --git a/test/js/void-euro.test.js b/test/js/void-euro.test.js index 15730a64..7a74ecd3 100644 --- a/test/js/void-euro.test.js +++ b/test/js/void-euro.test.js @@ -15,9 +15,7 @@ describe('--void-euro', () => { test('makes € a plain char in the pattern', async () => { expect((await rr('.€', 'x', {pipedData: 'foobar', voidEuro: true})).out).toBe('foobar'); - expect((await rr('.€', 'x', {pipedData: 'price: 5€', voidEuro: true})).out).toBe( - 'price: x' - ); + expect((await rr('.€', 'x', {pipedData: 'price: 5€', voidEuro: true})).out).toBe('price: x'); }); test('makes € a plain char in the replacement', async () => { @@ -26,9 +24,7 @@ describe('--void-euro', () => { }); test('leaves $ working as usual', async () => { - expect((await rr('(.)$', '$1!', {pipedData: 'foobar', voidEuro: true})).out).toBe( - 'foobar!' - ); + expect((await rr('(.)$', '$1!', {pipedData: 'foobar', voidEuro: true})).out).toBe('foobar!'); }); test('never touches a € in the content', async () => { @@ -49,9 +45,9 @@ describe('--void-euro', () => { test('with --literal', async () => { expect((await rr('5€', 'x', {pipedData: '5€ 5$', literal: true})).out).toBe('5€ x'); - expect( - (await rr('5€', 'x', {pipedData: '5€ 5$', literal: true, voidEuro: true})).out - ).toBe('x 5$'); + expect((await rr('5€', 'x', {pipedData: '5€ 5$', literal: true, voidEuro: true})).out).toBe( + 'x 5$' + ); }); test('with --replacement-js the € is how to get to the groups', async () => { diff --git a/test/js/void-global.test.js b/test/js/void-global.test.js index a17c9882..96c59ca8 100644 --- a/test/js/void-global.test.js +++ b/test/js/void-global.test.js @@ -32,12 +32,8 @@ describe('--void-global', () => { }); test('with the default multiline only the first line is touched', async () => { - expect((await rr('^', '> ', {pipedData: 'a\nb\nc', voidGlobal: true})).out).toBe( - '> a\nb\nc' - ); - expect((await rr('$', '!', {pipedData: 'a\nb\nc', voidGlobal: true})).out).toBe( - 'a!\nb\nc' - ); + expect((await rr('^', '> ', {pipedData: 'a\nb\nc', voidGlobal: true})).out).toBe('> a\nb\nc'); + expect((await rr('$', '!', {pipedData: 'a\nb\nc', voidGlobal: true})).out).toBe('a!\nb\nc'); }); test('with --void-multiline $ is the end of the content', async () => { diff --git a/test/js/void-ignore-case.test.js b/test/js/void-ignore-case.test.js index 46e69cd9..d64a10ea 100644 --- a/test/js/void-ignore-case.test.js +++ b/test/js/void-ignore-case.test.js @@ -26,9 +26,7 @@ describe('--void-ignore-case', () => { test('applies to backreferences inside the pattern', async () => { expect((await rr('(a)\\1', '_', {pipedData: 'aA aa'})).out).toBe('_ _'); - expect((await rr('(a)\\1', '_', {pipedData: 'aA aa', voidIgnoreCase: true})).out).toBe( - 'aA _' - ); + expect((await rr('(a)\\1', '_', {pipedData: 'aA aa', voidIgnoreCase: true})).out).toBe('aA _'); }); describe('combined', () => { diff --git a/test/js/void-multiline.test.js b/test/js/void-multiline.test.js index bd89acbb..2778d7ba 100644 --- a/test/js/void-multiline.test.js +++ b/test/js/void-multiline.test.js @@ -18,9 +18,7 @@ describe('--void-multiline', () => { }); test('makes no difference for a single line', async () => { - expect((await rr('^f|r$', 'x', {pipedData: 'foobar', voidMultiline: true})).out).toBe( - 'xoobax' - ); + expect((await rr('^f|r$', 'x', {pipedData: 'foobar', voidMultiline: true})).out).toBe('xoobax'); }); test('does not see a final newline as the end of the content', async () => { diff --git a/test/js/void-section.test.js b/test/js/void-section.test.js index 7992dcbe..02c10999 100644 --- a/test/js/void-section.test.js +++ b/test/js/void-section.test.js @@ -58,12 +58,9 @@ describe('--void-section', () => { }); test('with --literal', async () => { - expect((await rr('a§b', 'x', {pipedData: 'a§b a\\b', literal: true})).out).toBe( - 'a§b x' - ); + expect((await rr('a§b', 'x', {pipedData: 'a§b a\\b', literal: true})).out).toBe('a§b x'); expect( - (await rr('a§b', 'x', {pipedData: 'a§b a\\b', literal: true, voidSection: true})) - .out + (await rr('a§b', 'x', {pipedData: 'a§b a\\b', literal: true, voidSection: true})).out ).toBe('x a\\b'); }); diff --git a/yarn.lock b/yarn.lock index 8f58935a..dce61abe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,60 @@ # yarn lockfile v1 +"@biomejs/biome@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-2.5.15.tgz#0a7d323f59b0d361e032ddcf7c4907d4f979eb22" + integrity sha512-WZTW4slm/pdkh92K6t/3aEN++44JD1PQ7squ7RCMLI1flHGl43DVOIGXvCjHiZgBMO1V4uYxoFNtqrIA4qGuIQ== + optionalDependencies: + "@biomejs/cli-darwin-arm64" "2.5.15" + "@biomejs/cli-darwin-x64" "2.5.15" + "@biomejs/cli-linux-arm64" "2.5.15" + "@biomejs/cli-linux-arm64-musl" "2.5.15" + "@biomejs/cli-linux-x64" "2.5.15" + "@biomejs/cli-linux-x64-musl" "2.5.15" + "@biomejs/cli-win32-arm64" "2.5.15" + "@biomejs/cli-win32-x64" "2.5.15" + +"@biomejs/cli-darwin-arm64@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.15.tgz#0d5e5c6a672617cb61101efafc638f993b7985a8" + integrity sha512-BZVzFhJ/mUvTLMYbc9x6el0o2Uv5zP7bACYyhFb6fSc1giroXm7PL0a5KqMJ9F+/BnkYRjagD/ROSDVOZ6eapg== + +"@biomejs/cli-darwin-x64@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.15.tgz#bb0a1b696e7270ca187c514573baf9a82ba0fec5" + integrity sha512-V5Kw63V+fVGNFhFrizDxMbGXAzZCh8kYzJpy3GI6gTapWDg7bZK9oYC9CbVgQSEdTnupz0U5Efz8Ev+5vdBBXw== + +"@biomejs/cli-linux-arm64-musl@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.15.tgz#63839d4c11081d53cffa0cecf388769734551d1b" + integrity sha512-tGzZUTcJCV7tj5Adh/Gn6nR4MycqA3iohq2LEcrarAgRBkU0h0OKd2UzCRkOsOYOuUGaUJb4YmqRqyy2feGGSw== + +"@biomejs/cli-linux-arm64@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.15.tgz#ea868026056577eeb43c7e7a1517627115655e20" + integrity sha512-XaG7P7eeSLYETD3K9grfB0mQmpLQZjygdbsxekWBJAg4am79fGAtRpfRyNnTvXB2fZFNnJZG3nXm7HBat0+VUw== + +"@biomejs/cli-linux-x64-musl@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.15.tgz#e969cebdfbdc7c69eef154e20a0672e0184dc6f1" + integrity sha512-IlxUcyxilVGPsE008x13pWdkTbU3nQpP2i9b5UrbOYj6goBkKsRX1XB7yJLcV+O1H9LBchIIm4adOaVLZBX0ZQ== + +"@biomejs/cli-linux-x64@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.15.tgz#4e5fb14b5ed66ff61e57510cbeef7dc5889d9959" + integrity sha512-xE4iEW/3LqlYj9GFgGrFsFSH51dEEpUbYWBfeOv0q87WkUDxK2o/HhreSb7qMJqck70RVM6Lg96hgedcAYcOkA== + +"@biomejs/cli-win32-arm64@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.15.tgz#a1c2c23500cce101ee9593623ed8af57794c3177" + integrity sha512-2kPKzhNlm8C+Ru3GcO0Me2ODkCBLrVOUNuyi84RJyWDVKAA4+Kjj3jMjL938lF6BRfvltC4vB2nPY9SvN51Ovg== + +"@biomejs/cli-win32-x64@2.5.15": + version "2.5.15" + resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.15.tgz#f652af401e7177466d0f20b1ba7f3998ee317401" + integrity sha512-yAzh4UqEImV6Hcy0zjUqNfJAsUhoD64FBQCdTG8Md/Z2wQeVP/ZmJ3XRYAs1g8J9fjTFyl2fCtc5FB5til47+g== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -402,11 +456,6 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== -prettier@3.9.9: - version "3.9.9" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.9.9.tgz#09b826918c91cd4cbc80e0cbd1d2a922ff04f233" - integrity sha512-Z/CJHIkdujO/OtN7nXUii0Rf3VT5SRuhjBA82Xvu2XhBUgX3nhP67T0LHceBdQLex7OOFGTox+Q5Yg8Jk2Qivg== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"