くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

viteでの環境構築メモ | lint/自動チェック編

viteでの環境構築メモ(*´ω`*)

この記事のlint/自動チェック編(*´ω`*)

lint周り

eslint

$ pnpm add -D eslint eslint-plugin-vue 
$ pnpm add -D @rushstack/eslint-patch @vue/eslint-config-typescript
.eslintrc.cjs
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");

module.exports = {
  root: true,
  extends: [
    "plugin:vue/vue3-recommended",
    "eslint:recommended",
    "@vue/eslint-config-typescript",
  ],
  parser: "vue-eslint-parser",
  parserOptions: {
    parser: "@typescript-eslint/parser",
    ecmaVersion: "latest",
    sourceType: "module",
  },
  env: {
    browser: true,
    node: true,
    webextensions: true,
  },
};
settings.jsonの追加
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "eslint.validate": [
    "javascript",
    "typescript",
    "javascriptreact",
    "typescriptreact",
    "vue",
    "html",
    "json",
    "jsonc",
    "json5",
    "markdown"
  ],
  "editor.formatOnSave": true
}
package.jsonの追加
    "scripts": {
       ...
+     "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
    },

prettier

$ pn add -D prettier @vue/eslint-config-prettier

.prettierrc.jsonの追加

{}

.prettierignoreの追加

**/.git
**/dist
**/node_modules
**/pnpm-lock.yaml
**/.*ignore
**/.husky
**/coverage

.eslintrc.cjsの変更

  module.exports = {
  // ...
    extends: [
      "plugin:vue/vue3-recommended",
      "eslint:recommended",
      "@vue/eslint-config-typescript",
+     "@vue/eslint-config-prettier",
    ],
  };

.editorconfig

# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120

[*.md]
trim_trailing_whitespace = false

自動チェック周り

husky

$ pnpm add -D husky
$ pnpm prepare

lint-staged

$ pnpm add -D lint-staged
$ pnpm husky add .husky/pre-commit "pnpm lint-staged" 

.lintstagedrc.jsonの追加

{
  "*": ["eslint --no-ignore", "prettier --write"]
}

.eslintignoreの追加

$ cat .gitinore > .eslintignore
$ cat .prettierignore >> .eslintignore

comitlint

$ pnpm add -D @commitlint/config-conventional @commitlint/cli
$ pnpm add -D @commitlint/types
$ pnpm husky add .husky/commit-msg  'pnpm commitlint --edit ${1}'

commitlint.config.cjsの追加

// commitlint.config.cjs
/** @type {import("@commitlint/types").UserConfig} */
module.exports = {
  extends: ["@commitlint/config-conventional"],
  plugins: [
    {
      rules: {
        "issue-empty": (parsed) => {
          const { header } = parsed;
          const hasIssue = header.match(/(#\d+)/) != null;
          return hasIssue ? [true] : [false, "issue may not to empty"];
        },
      },
    },
  ],
  rules: {
    "issue-empty": [1, "never"],
  },
};
import type { UserConfig } from "@commitlint/types";

const config: UserConfig = {
  extends: ["@commitlint/config-conventional"],
  plugins: [
    {
      rules: {
        "issue-empty": (parsed) => {
          const { header } = parsed;
          const hasIssue = header.match(/(#\d+)/) != null;
          return hasIssue ? [true] : [false, "issue may not to empty"];
        },
      },
    },
  ],
  rules: {
    "issue-empty": [1, "never"],
  },
};

export default config;

git hooks

pre-commit

ファイル: .husky/pre-commit

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# protect spec branch
. "$(dirname -- "$0")/scripts/pre-commit-protect-branch.sh"

# check remain conflict
. "$(dirname -- "$0")/scripts/check-remain-conflict.sh"

# exec lint-stage
pnpm lint-staged

ファイル: .husky/scripts/pre-commit-protect-branch.sh

#!/usr/bin/env sh

###########################################################
# Protect branch
###########################################################
readonly PROTECTED_BRANCHES="(master|main|develop)"
readonly BRANCH_NAME=`git symbolic-ref HEAD | sed -e 's:^refs/heads/::'`
if [[ "${BRANCH_NAME}" =~ $PROTECTED_BRANCHES ]]; then
  echo "\\033[31m!!! NOT ALLOW COMMIT on "${BRANCH_NAME}" branch!!!\\033[m"
  exit 1
fi

ファイル: .husky/scripts/check-remain-conflict.sh

#!/usr/bin/env sh

###########################################################
# check remain conflict
###########################################################
echo "${BASH_SOURCE[0]}"
conflicts=`git diff --cached --name-only -G"<<<<<|=====|>>>>>" | grep -v "${BASH_SOURCE[0]}"`
FLAG=0
if [[ -n "$conflicts" ]]; then
    for FILE in $conflicts; do
        if [ ! -e $FILE ]; then
          echo "skip $FILE"
          continue
        fi
        echo "\\033[31m!!! REMAIN CONFLICT in $FILE!!!\\033[m"
        FLAG=1
    done;
fi

exit ${FLAG}

pre-push

$ pnpm husky add .husky/pre-push ""

ファイル: .husky/pre-push

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# protect branch and tag
. "$(dirname -- "$0")/scripts/pre-push-protect-branch.sh"

ファイル: .husky/scripts/pre-push-protect-branch.sh

#!/usr/bin/env sh

###########################################################
#  Protect branch/tag
###########################################################
readonly PROTECTED_BRANCHES="(master|main|develop)"
while read local_ref local_oid remote_ref remote_oid
do
  echo "local_ref=${local_ref} local_oid=${local_oid} remote_ref=${remote_ref} remote_oid=${remote_oid}"
  
  # protect tag
  TAG_NAME="${remote_ref/refs\/tags\//}"
  echo "TAG_NAME=${TAG_NAME}"
  if [[ "${remote_ref}" =~ ^refs/tags/.*$ ]]; then
    echo "\\033[31m!!! NOT ALLOW PUSH on '$TAG_NAME' tag!!!\\033[m"
    exit 1
  fi

  # protect branch
  BRANCH_NAME="${remote_ref/refs\/heads\//}"
  echo "BRANCH_NAME=${BRANCH_NAME}, remote_ref=${remote_ref}"
  if [[ "$BRANCH_NAME" =~ $PROTECTED_BRANCHES ]]; then
    echo "\\033[31m!!! NOT ALLOW PUSH on '$BRANCH_NAME' branch!!!\\033[m"
    exit 1
  fi
done