uniapp+vue3+ts (normalized code configuration ESLint+Prettier+Husky)

Project standardized configuration

Install the plugin in the editor vscode:

1. ESLint

2. Prettier

ESLint Configuration

Install:

pnpm i eslint -D

initialization:

npx eslint --init

Modify the .eslintrc.cjs configuration file

// @see https://eslint.bootcss.com/docs/rules/
?
module.exports = {
    env: {
        browser: true,
        es2021: true,
        node: true,
    },
    globals: {},
    /* specify how to parse the grammar */
    parser: 'vue-eslint-parser',
    /** Grammar parsing configuration with priority lower than parse */
    parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module',
        parser: '@typescript-eslint/parser',
        jsxPragma: 'React',
        ecmaFeatures: {
            jsx: true,
        },
    },
    /* Inherit existing rules */
    extends: ['eslint:recommended', 'plugin:vue/vue3-essential', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
    plugins: ['vue', '@typescript-eslint'],
    overrides: [
        {
            files: ['*.ts', '*.tsx', '*.vue'],
            rules: {
                'no-undef': 0,
            },
        },
    ],
    /*
     * 'off' or 0 ==> turn off rule
     * 'warn' or 1 ==> Turn on the rule as a warning (does not affect code execution)
     * 'error' or 2 ==> rule as an error (the code cannot be executed, the interface reports an error)
     */
    rules: {
        // typeScript (https://typescript-eslint.io/rules)
        '@typescript-eslint/no-unused-vars': 2, // Prohibit defining unused variables
        '@typescript-eslint/prefer-ts-expect-error': 2, // disallow @ts-ignore
        '@typescript-eslint/no-explicit-any': 0, // disable any type
        '@typescript-eslint/no-non-null-assertion': 0,
        '@typescript-eslint/no-namespace': 0, // Disable custom TypeScript modules and namespaces.
        '@typescript-eslint/semi': 0,
        'no-prototype-builtins': 0, // can use obj.hasOwnProperty()
        '@typescript-eslint/no-var-requires': 0, // do not allow require in import
        '@typescript-eslint/no-empty-function': 2, // turn off empty method checking
        // eslint-plugin-vue (https://eslint.vuejs.org/rules/)
        'vue/multi-word-component-names': 0, // Require component names to always be "-" linked words
        'vue/script-setup-uses-vars': 2, // Prevent variables <template> used by <script setup> from being marked as unused
        'vue/no-mutating-props': 0, // Do not allow component props to change
        'vue/no-v-html': 0, // disable v-html
        'vue/no-setup-props-destructure': 0, // Disable props destructure to be passed to setup
        'vue/no-v-model-argument': 0, // Do not allow adding arguments to be used in v-model custom components
        'vue/component-definition-name-casing': [2, 'PascalCase'], // Enforce a specific case of the component definition name PascalCase | kebab-case
        'vue/attribute-hyphenation': [2, 'always', { ignore: [] }], // Enforce attribute naming style for custom components in templates
        'vue/no-dupe-keys': [2, { groups: [] }], // Do not allow duplicate field names
        'vue/no-dupe-v-else-if': 2, // Do not allow duplicate v-if conditions in / v-else-if chains
        'vue/no-duplicate-attributes': 2, // prohibit duplicate attributes
        'vue/no-ref-as-operand': 2, // use ref object must.value
        'vue/first-attribute-linebreak': [
            2,
            {
                singleline: 'ignore',
                multiline: 'below',
            },
        ], // Mandatory setting of the position of the first property
?
        '@typescript-eslint/no-this-alias': [
            'warn',
            {
                allowDestructuring: false, // Disallow `const { props, state } = this`; true by default
                allowedNames: ['_this'], // the alias of this can be _this
            },
        ],
        // eslint (https://eslint.bootcss.com/docs/rules/)
        'no-unexpected-multiline': 2, // Forbid empty multiline
        'no-await-in-loop': 2, // This rule disallows await in loop body
        'no-dupe-else-if': 2, // disallow duplicate conditions in if-else-if chains
        'no-const-assign': 2, // disallow reassignment of const variables
        'no-dupe-keys': 2, // disallow duplicate keys in object literals
        'no-multiple-empty-lines': ['warn', { max: 1 }], // multiple empty lines are not allowed
        'no-unused-vars': 2, // disallow unused variables
        'use-isnan': 2, // need to call isNaN() when checking for NaN
        'valid-typeof': 2, // force typeof expressions to be compared to valid strings
        'no-var': 2, // requires let or const instead of var
        'no-extra-semi': 2, // disallow unnecessary semicolons
        'no-multi-str': 2, // disallow multiline strings
        'no-unused-labels': 2, // disallow unused labels
        // Force a line break after opening array brackets and before closing array brackets
        'array-bracket-newline': [2, 'consistent'],
        eqeqeq: [2, 'smart'], // must use congruence
        'arrow-spacing': 2, // enforce consistent spacing before and after arrows in arrow functions
        // Force newlines between arguments to function calls
        'function-call-argument-newline': [2, 'consistent'],
        'no-undef': 2, // Disallow use of undeclared variables unless mentioned in /*global */ comments
        complexity: [2, 15],
        indent: [2, 4, { SwitchCase: 1 }],
        'valid-jsdoc': 0, //jsdoc rules
        'no-console': process.env.NODE_ENV === 'production' ? 2 : 0,
        'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
        'no-useless-escape': 0, // disallow unnecessary escape characters
        '@typescript-eslint/ban-types': 0, // Allow function to be declared
        'prettier/prettier': [
            2,
            {
                // Include parentheses around individual arrow function arguments always: (x) => x \ avoid: x => x
                arrowParens: 'always',
                // Whether the right angle bracket of the start tag follows the end of the last line of attributes, the default is false
                bracketSameLine: false,
                // Print spaces between parentheses in object literals
                bracketSpacing: true,
                // Whether to format the style of embedded code snippets in some files (auto|off; default auto)
                embeddedLanguageFormatting: 'auto',
                // Specify the whitespace sensitivity of the HTML file (css|strict|ignore; default css)
                htmlWhitespaceSensitivity: 'ignore',
                // Maximum number of characters in a line
                printWidth: 150,
                // exceed print width (always | never | preserve )
                proseWrap: 'preserve',
                // Whether to use quotes for object properties (as-needed | consistent | preserve;
                quoteProps: 'as-needed',
                // Specify the parser to use, no need to write @prettier at the beginning of the file
                requirePragma: false,
                // No need to automatically insert @prettier at the beginning of the file
                insertPragma: false,
                // no quotes at the end
                semi: false,
                // Use single quotes (true: single quotes; false: double quotes)
                singleQuote: true,
                // Number of spaces for indentation, default 2 spaces
                tabWidth: 4,
                // Print trailing commas when possible on multiple lines.
                trailingComma: 'es5',
                // use tabs instead of spaces for indentation
                useTabs: false,
                // Vue file script and style tag indentation
                vueIndentScriptAndStyle: false,
                // newline character ends with lf is optional value "<auto|lf|crlf|cr>"
                endOfLine: 'auto',
            },
        ],
    },
}
?

.eslintignore ignores the file (you can create it yourself without this file)

dist
node_modules

Run the script to add:

package.json adds two running scripts

"scripts": {
    "lint": "eslint src",
    "fix": "eslint src --fix",
}

Prettier

Install

pnpm install -D eslint-plugin-prettier prettier eslint-config-prettier

prettierrc.json to add rules (you can create it yourself without this file)

{
    "arrowParens": "always",
    "bracketSameLine": false,
    "bracketSpacing": true,
    "embeddedLanguageFormatting": "auto",
    "htmlWhitespaceSensitivity": "ignore",
    "insertPragma": false,
    "printWidth": 150,
    "proseWrap": "preserve",
    "quoteProps": "as-needed",
    "requirePragma": false,
    "semi": false,
    "singleQuote": true,
    "tabWidth": 4,
    "trailingComma": "es5",
    "useTabs": false,
    "vueIndentScriptAndStyle": false,
    "endOfLine": "auto"
}

prettierignore ignore file

/dist/*
/html/*
.local
/node_modules/**
**/*.svg
**/*.sh
/public/*

Husky

Install

pnpm install -D husky

run

npx husky-init

A .husky directory will be generated under the root directory, and there will be a pre-commit file under this directory. The commands in this file will be executed when we execute commit