Skip to content

Instantly share code, notes, and snippets.

@btoo
Last active June 17, 2024 07:55

Revisions

  1. @btjk btjk revised this gist May 8, 2020. 1 changed file with 0 additions and 81 deletions.
    81 changes: 0 additions & 81 deletions lint.ts
    Original file line number Diff line number Diff line change
    @@ -1,81 +0,0 @@
    /**
    * performs linting (eslint) and formatting (prettier) on __staged files only__
    *
    * (probably as a pre-commit hook @see .huskyrc.js)
    */
    export default async () => {
    const { default: chalk } = await import('chalk');

    const { read, run } = await import('./utils');

    const stagedFiles = (await read('git diff --diff-filter=d --cached --name-only'))
    .split('\n')
    .filter(Boolean);

    if (stagedFiles.length) {
    console.log(chalk.blueBright('\nLinting staged files with ESLint before committing...'));

    /** eslint only works with js and ts for now */
    const stagedFilesForEslint = stagedFiles.filter((f) => f.match(/\.(js|jsx|ts|tsx|vue|json)$/));
    const stagedFilesForEslintStr = stagedFilesForEslint.join(' ');

    /**
    * a reusable function for formatting with Prettier.
    * this function should be called after either:
    * - linting succeeds or
    * - linting fails and then lint --fix is attempted
    */
    const formatStagedFilesWithPrettier = async () => {
    try {
    console.log(
    chalk.blueBright('\nFormatting staged files with Prettier before committing...\n')
    );
    const stagedFilesStr = stagedFiles.join(' ');
    await read(`npx prettier --list-different ${stagedFilesStr}`);
    // nothing to format
    } catch (resultOfCheckingToSeeIfAnythingNeedsToBeFormatted) {
    const filesThatNeedToBeFormatted = (resultOfCheckingToSeeIfAnythingNeedsToBeFormatted.stdout as string)
    .split('\n')
    .filter(Boolean);

    if (filesThatNeedToBeFormatted.length) {
    try {
    await read(`npx prettier --write ${filesThatNeedToBeFormatted.join(' ')}`);
    } finally {
    const { default: path } = await import('path');
    console.log(chalk.redBright.bold('The following files needed formatting:'));
    const cwd = process.cwd();
    filesThatNeedToBeFormatted.forEach((f) =>
    console.log(chalk.underline(path.join(cwd, f)))
    );
    console.log();
    process.exit(1);
    }
    }
    }
    };

    try {
    stagedFilesForEslint.length && (await run(`npx eslint ${stagedFilesForEslintStr}`));
    await formatStagedFilesWithPrettier();
    } catch (lintingErr) {
    // there are linting problems, so:
    // 1. try to fix the linting problems with eslint --fix
    // 2. try to format the code with prettier --write
    // 3. prevent the commit from happening

    console.log(chalk.blueBright('Attempting to `--fix` problems...'));

    try {
    stagedFilesForEslint.length && (await run(`npx eslint --fix ${stagedFilesForEslintStr}`));
    await formatStagedFilesWithPrettier();
    } finally {
    process.exit(1);
    }
    }
    } else {
    console.log(chalk.blueBright('\nThere are no files staged in git to lint/format\n'));
    }
    };

    export const LINT_MESSAGE = 'Lint and format staged files';
  2. @btjk btjk revised this gist May 8, 2020. 1 changed file with 81 additions and 0 deletions.
    81 changes: 81 additions & 0 deletions lint.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    /**
    * performs linting (eslint) and formatting (prettier) on __staged files only__
    *
    * (probably as a pre-commit hook @see .huskyrc.js)
    */
    export default async () => {
    const { default: chalk } = await import('chalk');

    const { read, run } = await import('./utils');

    const stagedFiles = (await read('git diff --diff-filter=d --cached --name-only'))
    .split('\n')
    .filter(Boolean);

    if (stagedFiles.length) {
    console.log(chalk.blueBright('\nLinting staged files with ESLint before committing...'));

    /** eslint only works with js and ts for now */
    const stagedFilesForEslint = stagedFiles.filter((f) => f.match(/\.(js|jsx|ts|tsx|vue|json)$/));
    const stagedFilesForEslintStr = stagedFilesForEslint.join(' ');

    /**
    * a reusable function for formatting with Prettier.
    * this function should be called after either:
    * - linting succeeds or
    * - linting fails and then lint --fix is attempted
    */
    const formatStagedFilesWithPrettier = async () => {
    try {
    console.log(
    chalk.blueBright('\nFormatting staged files with Prettier before committing...\n')
    );
    const stagedFilesStr = stagedFiles.join(' ');
    await read(`npx prettier --list-different ${stagedFilesStr}`);
    // nothing to format
    } catch (resultOfCheckingToSeeIfAnythingNeedsToBeFormatted) {
    const filesThatNeedToBeFormatted = (resultOfCheckingToSeeIfAnythingNeedsToBeFormatted.stdout as string)
    .split('\n')
    .filter(Boolean);

    if (filesThatNeedToBeFormatted.length) {
    try {
    await read(`npx prettier --write ${filesThatNeedToBeFormatted.join(' ')}`);
    } finally {
    const { default: path } = await import('path');
    console.log(chalk.redBright.bold('The following files needed formatting:'));
    const cwd = process.cwd();
    filesThatNeedToBeFormatted.forEach((f) =>
    console.log(chalk.underline(path.join(cwd, f)))
    );
    console.log();
    process.exit(1);
    }
    }
    }
    };

    try {
    stagedFilesForEslint.length && (await run(`npx eslint ${stagedFilesForEslintStr}`));
    await formatStagedFilesWithPrettier();
    } catch (lintingErr) {
    // there are linting problems, so:
    // 1. try to fix the linting problems with eslint --fix
    // 2. try to format the code with prettier --write
    // 3. prevent the commit from happening

    console.log(chalk.blueBright('Attempting to `--fix` problems...'));

    try {
    stagedFilesForEslint.length && (await run(`npx eslint --fix ${stagedFilesForEslintStr}`));
    await formatStagedFilesWithPrettier();
    } finally {
    process.exit(1);
    }
    }
    } else {
    console.log(chalk.blueBright('\nThere are no files staged in git to lint/format\n'));
    }
    };

    export const LINT_MESSAGE = 'Lint and format staged files';
  3. @btjk btjk revised this gist Mar 25, 2020. 1 changed file with 9 additions and 6 deletions.
    15 changes: 9 additions & 6 deletions .huskyrc.js
    Original file line number Diff line number Diff line change
    @@ -14,11 +14,14 @@ module.exports = {
    * if linting fails, prevent the commit from happening and fix the auto-fixable errors
    */
    'pre-commit': `
    stagedFiles = git diff --diff-filter=d --cached --name-only;
    {
    npx eslint $(stagedFiles)
    } || {
    npx eslint --fix $(stagedFiles) && exit 1
    }`,
    stagedFiles=$(git diff --diff-filter=d --cached --name-only);
    if [ -n "$stagedFiles" ]; then # at least one file is staged
    {
    npx eslint $stagedFiles
    } || {
    npx eslint --fix $stagedFiles && exit 1
    }
    fi
    `,
    },
    };
  4. @btjk btjk created this gist Mar 25, 2020.
    24 changes: 24 additions & 0 deletions .huskyrc.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    /**
    * @see {@tutorial https://github.com/typicode/husky}
    * _Requires Node >= 10 and Git >= 2.13.0._
    */
    module.exports = {
    hooks: {
    /**
    * @see {@tutorial https://stackoverflow.com/a/15656652/3942699}
    *
    * ___only works with files staged in git___
    * because doing on the entire repo is overkill atm
    *
    * if linting succeeds, proceed to committing the staged files.
    * if linting fails, prevent the commit from happening and fix the auto-fixable errors
    */
    'pre-commit': `
    stagedFiles = git diff --diff-filter=d --cached --name-only;
    {
    npx eslint $(stagedFiles)
    } || {
    npx eslint --fix $(stagedFiles) && exit 1
    }`,
    },
    };