编辑
2026-07-07
AI
00

目录

hooks
实践

hooks

中文名为钩子,实际常用于代码某些执行阶段触发某些逻辑,如结尾触发检测或测试,使得代码编译正常。

安全防线、质量守卫、审计日志,全部由 Hooks 在“幕后”自动完成

cursor中hooks配置:https://cursor.com/cn/docs/hooks

实践

针对vue3代码:高频用于eslint 运行没问题后再给到执行,可以有效降低AI带来的语法等问题。

文件位置:.cursor/hooks/local-lint-check.mjs

js
#!/usr/bin/env node /** * Cursor stop hook: lint changed src files with the same ESLint rules as `npm run local` * (vite-plugin-eslint in config/vite.config.dev.ts). */ import { spawnSync } from 'node:child_process' import { readFileSync } from 'node:fs' const MAX_OUTPUT_CHARS = 8000 const LINTABLE_FILE = /\.(vue|ts|tsx|js|jsx)$/i function readHookInput() { try { const raw = readFileSync(0, 'utf8') return raw ? JSON.parse(raw) : {} } catch { return {} } } function runGit(args) { const result = spawnSync('git', args, { cwd: process.cwd(), encoding: 'utf8', shell: process.platform === 'win32', }) return (result.stdout || '').split(/\r?\n/).filter(Boolean) } function getChangedLintableFiles() { const files = new Set() for (const file of runGit(['diff', '--name-only', 'HEAD', '--', 'src/'])) { if (LINTABLE_FILE.test(file)) files.add(file) } for (const file of runGit(['diff', '--cached', '--name-only', 'HEAD', '--', 'src/'])) { if (LINTABLE_FILE.test(file)) files.add(file) } for (const file of runGit(['ls-files', '--others', '--exclude-standard', 'src/'])) { if (LINTABLE_FILE.test(file)) files.add(file) } return [...files] } function runEslint(files) { const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx' const result = spawnSync( npx, ['eslint', ...files, '--max-warnings', '0', '--format', 'stylish'], { cwd: process.cwd(), encoding: 'utf8', shell: process.platform === 'win32', env: process.env, } ) const output = [result.stdout, result.stderr].filter(Boolean).join('\n').trim() return { ok: result.status === 0, output, exitCode: result.status ?? 1, } } function emit(result) { process.stdout.write(`${JSON.stringify(result)}\n`) } const input = readHookInput() if (input.status === 'aborted') { emit({}) process.exit(0) } const changedFiles = getChangedLintableFiles() if (changedFiles.length === 0) { emit({}) process.exit(0) } const { ok, output, exitCode } = runEslint(changedFiles) if (ok) { emit({}) process.exit(0) } const truncated = output.length > MAX_OUTPUT_CHARS ? `${output.slice(0, MAX_OUTPUT_CHARS)}\n...(输出已截断)` : output const fileList = changedFiles.map((f) => `- ${f}`).join('\n') emit({ followup_message: `本地 Lint 检查未通过(规则与 npm run local 开发服一致)。请修复以下问题: 检查文件: ${fileList} \`\`\` ${truncated || `eslint 退出码 ${exitCode}`} \`\`\` 可本地复现:npx eslint ${changedFiles.join(' ')}`, }) process.exit(0)

代码每次跑完,都会自动触发eslint check 使得:

js
已修复 Prettier 格式问题:将「复用HEX」表单项和 a-option 的多行属性合并为单行。npx eslint 现已通过(exit code 0)。
js
已修复 detail.vue 中的 2Prettier 格式问题: 第 117 行:将 a-button 的多行属性合并为单行 第 726 行:将三元表达式合并为单行 对上述两个文件的 ESLint 检查已通过。
js
已修复:将 fetchReuseHexCandidates 及其依赖的 isPersonalUploadedHex、sortReuseHexOptions 提前到 resetImportState 之前定义,消除 no-use-before-define 报错。 上述 3 个文件的 ESLint 检查均已通过。

本文作者:lixf6

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!