From 618723a6896df3f75c574d1081b5c653986ab600 Mon Sep 17 00:00:00 2001 From: RhenCloud Date: Fri, 19 Dec 2025 19:37:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20ESLint=20=E5=92=8C?= =?UTF-8?q?=20Prettier=20=E9=85=8D=E7=BD=AE=EF=BC=8C=E9=9B=86=E6=88=90?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=A0=BC=E5=BC=8F=E5=8C=96=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/lint-format.yml | 80 +++++++++++++ .prettierignore | 18 +++ .prettierrc | 12 ++ eslint.config.mjs | 21 +++- nuxt.config.ts | 185 ++++++++++++++++-------------- package.json | 66 ++++++----- 6 files changed, 261 insertions(+), 121 deletions(-) create mode 100644 .github/workflows/lint-format.yml create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.github/workflows/lint-format.yml b/.github/workflows/lint-format.yml new file mode 100644 index 0000000..e19760d --- /dev/null +++ b/.github/workflows/lint-format.yml @@ -0,0 +1,80 @@ +name: Lint and Format + +on: + push: + branches: ["**"] + pull_request: + branches: ["**"] + +jobs: + lint: + name: ESLint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "pnpm" + + - name: Enable corepack and install pnpm + run: | + corepack enable + corepack prepare pnpm@latest --activate + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run ESLint + run: pnpm lint + + - name: Run Prettier check + run: pnpm format:check + + format: + name: Auto-format (eslint --fix) + runs-on: ubuntu-latest + needs: lint + if: github.event_name == 'push' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + persist-credentials: true + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "pnpm" + + - name: Enable corepack and install pnpm + run: | + corepack enable + corepack prepare pnpm@latest --activate + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run Prettier --write + run: pnpm format + + - name: Run ESLint --fix + run: pnpm lint:fix + + - name: Commit & push fixes + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + if ! git diff --quiet; then + git add -A + git commit -m "chore: auto format by GitHub Actions" || echo "No changes to commit" + git push + else + echo "No formatting changes" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..70b0f5d --- /dev/null +++ b/.prettierignore @@ -0,0 +1,18 @@ +node_modules/ +.output/ +.nuxt/ +dist/ +build/ +public/build/ +.vscode/ +.pnp.* +coverage/ +*.log +*.lock +pnpm-lock.yaml +.env +.env.* +.DS_Store + +# ignore generated images +public/images/generated/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a5cc6de --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "trailingComma": "es5", + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf", + "htmlWhitespaceSensitivity": "css" +} diff --git a/eslint.config.mjs b/eslint.config.mjs index 934c3a1..fef86dd 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,6 +1,19 @@ // @ts-check -import withNuxt from './.nuxt/eslint.config.mjs' +import withNuxt from "./.nuxt/eslint.config.mjs"; +// import simpleImportSort from "eslint-plugin-simple-import-sort"; +import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; -export default withNuxt( - // Your custom configs here -) +export default withNuxt([eslintPluginPrettierRecommended], { + files: ["src/**/*.ts", "src/**/*.vue"], + ignores: [".nuxt/", "node_modules/"], + language: "vue", + + // plugins: { + // prettier: prettierPlugin, + // }, + // rules: { + // "prettier/prettier": "error", + // "simple-import-sort/imports": "error", + // "simple-import-sort/exports": "error", + // }, +}); diff --git a/nuxt.config.ts b/nuxt.config.ts index 2a2d14c..f728cb8 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -3,97 +3,108 @@ import siteConfig from "./app/config/siteConfig"; import tailwindcss from "@tailwindcss/vite"; export default defineNuxtConfig({ - compatibilityDate: "2025-12-12", - srcDir: "app/", - modules: ["@nuxt/image", "@nuxt/eslint"], + compatibilityDate: "2025-12-12", + srcDir: "app/", + modules: ["@nuxt/image", "@nuxt/eslint"], - // 禁用 Vue Router 的非关键警告 - vue: { - compilerOptions: { - isCustomElement: (tag) => tag.startsWith("ion-"), + // eslint: { + // config: { + // extends: ["plugin:nuxt/recommended", "prettier"], + // plugins: ["prettier"], + // rules: { + // "prettier/prettier": "error", + // }, + // stylistic: true + // }, + // }, + + // 禁用 Vue Router 的非关键警告 + vue: { + compilerOptions: { + isCustomElement: (tag) => tag.startsWith("ion-"), + }, + }, + + // Tailwind CSS 集成 + css: ["~/styles.global.css"], + + vite: { + plugins: [tailwindcss()], + }, + + routeRules: { + "/": { prerender: true }, + "/about": { isr: 3600 }, + "/sites": { prerender: true }, + "/projects": { prerender: true }, + "/friends": { prerender: true }, + }, + + app: { + head: { + title: siteConfig.siteMeta.title, + link: [ + { rel: "icon", href: siteConfig.siteMeta.icon }, + // Font Awesome CDN 预加载和优化 + { + rel: "preload", + as: "style", + href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css?font-display=swap", + crossorigin: "anonymous", }, - }, - - // Tailwind CSS 集成 - css: ["~/styles.global.css"], - - vite: { - plugins: [tailwindcss()], - }, - - routeRules: { - "/": { prerender: true }, - "/about": { isr: 3600 }, - "/sites": { prerender: true }, - "/projects": { prerender: true }, - "/friends": { prerender: true }, - }, - - app: { - head: { - title: siteConfig.siteMeta.title, - link: [ - { rel: "icon", href: siteConfig.siteMeta.icon }, - // Font Awesome CDN 预加载和优化 - { - rel: "preload", - as: "style", - href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css?font-display=swap", - crossorigin: "anonymous", - }, - { - rel: "preload", - as: "font", - href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-solid-900.woff2?font-display=swap", - type: "font/woff2", - crossorigin: "anonymous", - }, - { - rel: "preload", - as: "font", - href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-brands-400.woff2?font-display=swap", - type: "font/woff2", - crossorigin: "anonymous", - }, - ], + { + rel: "preload", + as: "font", + href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-solid-900.woff2?font-display=swap", + type: "font/woff2", + crossorigin: "anonymous", }, - }, - - nitro: { - prerender: { - crawlLinks: true, - // routes: ["/sitemap.xml", "/rss.xml"], + { + rel: "preload", + as: "font", + href: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-brands-400.woff2?font-display=swap", + type: "font/woff2", + crossorigin: "anonymous", }, - minify: true, + ], }, + }, - runtimeConfig: { - smtpHost: process.env.SMTP_HOST ?? "", - smtpPort: Number(process.env.SMTP_PORT ?? 465), - smtpUser: process.env.SMTP_USER ?? "", - smtpPass: process.env.SMTP_PASS ?? "", - senderEmail: process.env.SENDER_EMAIL ?? "", - adminEmail: process.env.ADMIN_EMAIL ?? "", - smtpSecure: process.env.SMTP_SECURE ? process.env.SMTP_SECURE === "true" : undefined, - wakatimeApiKey: process.env.WAKATIME_API_KEY ?? "", - wakatimeApiUrl: process.env.WAKATIME_API_URL ?? "https://wakatime.com/api/v1", - public: { - githubToken: process.env.NUXT_PUBLIC_GITHUB_TOKEN ?? "", - umamiApiKey: process.env.NUXT_PUBLIC_UMAMI_API_KEY ?? "", - // Twikoo 评论服务地址(在 Netlify 或部署环境中设置 NUXT_PUBLIC_TWIKOO_URL) - twikooUrl: process.env.NUXT_PUBLIC_TWIKOO_URL ?? "", - // Giscus 配置(在部署环境中设置 NUXT_PUBLIC_GISCUS_* 系列变量) - giscus: { - repo: process.env.NUXT_PUBLIC_GISCUS_REPO ?? "", - repoId: process.env.NUXT_PUBLIC_GISCUS_REPO_ID ?? "", - category: process.env.NUXT_PUBLIC_GISCUS_CATEGORY ?? "", - categoryId: process.env.NUXT_PUBLIC_GISCUS_CATEGORY_ID ?? "", - mapping: process.env.NUXT_PUBLIC_GISCUS_MAPPING ?? "pathname", - reactionsEnabled: process.env.NUXT_PUBLIC_GISCUS_REACTIONS_ENABLED ?? "1", - emitMetadata: process.env.NUXT_PUBLIC_GISCUS_EMIT_METADATA ?? "0", - inputPosition: process.env.NUXT_PUBLIC_GISCUS_INPUT_POSITION ?? "bottom", - theme: process.env.NUXT_PUBLIC_GISCUS_THEME ?? "light", - }, - }, + nitro: { + prerender: { + crawlLinks: true, + // routes: ["/sitemap.xml", "/rss.xml"], }, -}); \ No newline at end of file + minify: true, + }, + + runtimeConfig: { + smtpHost: process.env.SMTP_HOST ?? "", + smtpPort: Number(process.env.SMTP_PORT ?? 465), + smtpUser: process.env.SMTP_USER ?? "", + smtpPass: process.env.SMTP_PASS ?? "", + senderEmail: process.env.SENDER_EMAIL ?? "", + adminEmail: process.env.ADMIN_EMAIL ?? "", + smtpSecure: process.env.SMTP_SECURE ? process.env.SMTP_SECURE === "true" : undefined, + wakatimeApiKey: process.env.WAKATIME_API_KEY ?? "", + wakatimeApiUrl: process.env.WAKATIME_API_URL ?? "https://wakatime.com/api/v1", + public: { + githubToken: process.env.NUXT_PUBLIC_GITHUB_TOKEN ?? "", + umamiApiKey: process.env.NUXT_PUBLIC_UMAMI_API_KEY ?? "", + // Twikoo 评论服务地址(在 Netlify 或部署环境中设置 NUXT_PUBLIC_TWIKOO_URL) + twikooUrl: process.env.NUXT_PUBLIC_TWIKOO_URL ?? "", + // Giscus 配置(在部署环境中设置 NUXT_PUBLIC_GISCUS_* 系列变量) + giscus: { + repo: process.env.NUXT_PUBLIC_GISCUS_REPO ?? "", + repoId: process.env.NUXT_PUBLIC_GISCUS_REPO_ID ?? "", + category: process.env.NUXT_PUBLIC_GISCUS_CATEGORY ?? "", + categoryId: process.env.NUXT_PUBLIC_GISCUS_CATEGORY_ID ?? "", + mapping: process.env.NUXT_PUBLIC_GISCUS_MAPPING ?? "pathname", + reactionsEnabled: process.env.NUXT_PUBLIC_GISCUS_REACTIONS_ENABLED ?? "1", + emitMetadata: process.env.NUXT_PUBLIC_GISCUS_EMIT_METADATA ?? "0", + inputPosition: process.env.NUXT_PUBLIC_GISCUS_INPUT_POSITION ?? "bottom", + theme: process.env.NUXT_PUBLIC_GISCUS_THEME ?? "light", + }, + }, + }, +}); diff --git a/package.json b/package.json index f94ebc3..0510c6f 100644 --- a/package.json +++ b/package.json @@ -1,31 +1,37 @@ { - "name": "cloud-home", - "private": true, - "type": "module", - "scripts": { - "dev": "nuxt dev", - "build": "nuxt build", - "generate": "nuxt generate", - "preview": "nuxt preview", - "lint": "eslint .", - "lint:fix": "eslint . --fix" - }, - "dependencies": { - "@giscus/vue": "^3.1.1", - "@jaseeey/vue-umami-plugin": "^1.4.0", - "@nuxt/eslint": "1.12.1", - "@nuxt/image": "2.0.0", - "eslint": "^9.39.2", - "nodemailer": "^7.0.11", - "nuxt": "^4.2.2", - "vite-tsconfig-paths": "^6.0.1" - }, - "devDependencies": { - "@tailwindcss/vite": "^4.1.18", - "@types/node": "^24.10.1", - "@types/nodemailer": "^7.0.4", - "autoprefixer": "^10.4.22", - "tailwindcss": "^4.1.18", - "typescript": "^5.9.3" - } -} \ No newline at end of file + "name": "cloud-home", + "private": true, + "type": "module", + "scripts": { + "dev": "nuxt dev", + "build": "nuxt build", + "generate": "nuxt generate", + "preview": "nuxt preview", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "format": "prettier --write .", + "format:check": "prettier --check ." + }, + "dependencies": { + "@giscus/vue": "^3.1.1", + "@jaseeey/vue-umami-plugin": "^1.4.0", + "@nuxt/image": "2.0.0", + "nodemailer": "^7.0.11", + "nuxt": "^4.2.2", + "vite-tsconfig-paths": "^6.0.1" + }, + "devDependencies": { + "@nuxt/eslint": "1.12.1", + "@tailwindcss/vite": "^4.1.18", + "@types/node": "^24.10.1", + "@types/nodemailer": "^7.0.4", + "@typescript-eslint/parser": "^8.50.0", + "autoprefixer": "^10.4.22", + "eslint": "^9.39.2", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.4", + "prettier": "^3.7.4", + "tailwindcss": "^4.1.18", + "typescript": "^5.9.3" + } +}