diff --git a/eslint.config.js b/eslint.config.js index 9ef7863..948a157 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,5 +1,6 @@ import tseslint from 'typescript-eslint' import prettier from 'eslint-config-prettier' +import checkFile from 'eslint-plugin-check-file' export default tseslint.config( {ignores: ['node_modules', 'dist', 'coverage', '.vitest']}, @@ -18,4 +19,11 @@ export default tseslint.config( ], }, }, + { + files: ['src/**/*.ts', 'tests/**/*.ts'], + plugins: {'check-file': checkFile}, + rules: { + 'check-file/filename-naming-convention': ['error', {'**/*.ts': 'KEBAB_CASE'}, {ignoreMiddleExtensions: true}], + }, + }, ) diff --git a/package-lock.json b/package-lock.json index 1cb1eb4..fafbeef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,11 +13,15 @@ "@types/node": "^25.9.0", "eslint": "^10.4.0", "eslint-config-prettier": "^10.1.8", + "eslint-plugin-check-file": "^3.3.1", "playwright": "^1.60.0", "prettier": "^3.8.3", "typescript": "^5.7.0", "typescript-eslint": "^8.59.4", "vitest": "^4.1.6" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@emnapi/core": { @@ -1035,6 +1039,19 @@ "node": "18 || 20 || >=22" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -1194,6 +1211,36 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-plugin-check-file": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-check-file/-/eslint-plugin-check-file-3.3.1.tgz", + "integrity": "sha512-b7fDkp8Y0T9vloTYSrkMnb5Cqpk1bc6+jDQdgKIhzdwb47NmLAvMFYo3SzHOPF8u4SEsOVhmrNSbo6Sp633syg==", + "dev": true, + "funding": [ + { + "type": "ko_fi", + "url": "https://ko-fi.com/huanluo" + }, + { + "type": "github", + "url": "https://github.com/sponsors/dukeluo" + } + ], + "license": "Apache-2.0", + "workspaces": [ + "examples/basic" + ], + "dependencies": { + "is-glob": "^4.0.3", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, "node_modules/eslint-scope": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", @@ -1362,6 +1409,19 @@ "node": ">=16.0.0" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1471,6 +1531,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1822,6 +1892,33 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/minimatch": { "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", @@ -2221,6 +2318,19 @@ "node": ">=14.0.0" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", diff --git a/package.json b/package.json index 833d464..d266fc2 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@types/node": "^25.9.0", "eslint": "^10.4.0", "eslint-config-prettier": "^10.1.8", + "eslint-plugin-check-file": "^3.3.1", "playwright": "^1.60.0", "prettier": "^3.8.3", "typescript": "^5.7.0", diff --git a/src/rules/index.ts b/src/rules/index.ts index 4ff3334..c54f518 100644 --- a/src/rules/index.ts +++ b/src/rules/index.ts @@ -1,9 +1,9 @@ import type {Rule} from '../types.js' import {filenameAltText} from './filename-alt-text.js' -import {vagueAltText} from './vagueAltText.js' -import {missingAltText} from './missingAltText.js' +import {vagueAltText} from './vague-alt-text.js' +import {missingAltText} from './missing-alt-text.js' import {placeholderAltText} from './placeholder-alt-text.js' -import {repeatedAltText} from './repeatedAltText.js' +import {repeatedAltText} from './repeated-alt-text.js' // Append-only registry. Add a rule by importing it here and pushing it onto the array. export const allRules: Rule[] = [filenameAltText, vagueAltText, missingAltText, placeholderAltText, repeatedAltText] diff --git a/src/rules/missingAltText.ts b/src/rules/missing-alt-text.ts similarity index 100% rename from src/rules/missingAltText.ts rename to src/rules/missing-alt-text.ts diff --git a/src/rules/placeholder-alt-text.ts b/src/rules/placeholder-alt-text.ts index cacd4b4..fe1310e 100644 --- a/src/rules/placeholder-alt-text.ts +++ b/src/rules/placeholder-alt-text.ts @@ -1,5 +1,5 @@ import type {Rule, RuleResult, RuleContext} from '../types.js' -import {normalizeAltText} from '../utils/normalizeAltText.js' +import {normalizeAltText} from '../utils/normalize-alt-text.js' // Known placeholder/boilerplate strings that signal the alt text was never written. const PLACEHOLDER_ALT_TEXT = new Set([ diff --git a/src/rules/repeatedAltText.ts b/src/rules/repeated-alt-text.ts similarity index 96% rename from src/rules/repeatedAltText.ts rename to src/rules/repeated-alt-text.ts index 553686f..492cddd 100644 --- a/src/rules/repeatedAltText.ts +++ b/src/rules/repeated-alt-text.ts @@ -1,5 +1,5 @@ import type {Rule, RuleResult} from '../types.js' -import {normalizeAltText} from '../utils/normalizeAltText.js' +import {normalizeAltText} from '../utils/normalize-alt-text.js' // Minimum number of consecutive images sharing the same alt before the run is flagged. const MIN_RUN_LENGTH = 2 diff --git a/src/rules/vagueAltText.ts b/src/rules/vague-alt-text.ts similarity index 97% rename from src/rules/vagueAltText.ts rename to src/rules/vague-alt-text.ts index a4a29d4..9b54db6 100644 --- a/src/rules/vagueAltText.ts +++ b/src/rules/vague-alt-text.ts @@ -1,5 +1,5 @@ import type {Rule, RuleResult} from '../types.js' -import {normalizeAltText} from '../utils/normalizeAltText.js' +import {normalizeAltText} from '../utils/normalize-alt-text.js' // Set of words that by themselves, are too vague to be useful alt text const VAGUE_WORDS = new Set([ diff --git a/src/utils/normalizeAltText.ts b/src/utils/normalize-alt-text.ts similarity index 100% rename from src/utils/normalizeAltText.ts rename to src/utils/normalize-alt-text.ts diff --git a/tests/missingAltText.test.ts b/tests/unit/missing-alt-text.test.ts similarity index 85% rename from tests/missingAltText.test.ts rename to tests/unit/missing-alt-text.test.ts index 6d38c9d..08f05c2 100644 --- a/tests/missingAltText.test.ts +++ b/tests/unit/missing-alt-text.test.ts @@ -1,7 +1,7 @@ import {describe, it, expect} from 'vitest' -import {missingAltText} from '../src/rules/missingAltText.js' -import type {RuleContext} from '../src/types.js' -import {evaluateAlts, makeImage} from './utils/helpers.js' +import {missingAltText} from '../../src/rules/missing-alt-text.js' +import type {RuleContext} from '../../src/types.js' +import {evaluateAlts, makeImage} from '../utils/helpers.js' describe('missing-alt-text', () => { it('flags an image with no alt attribute (alt === null)', () => { diff --git a/tests/repeatedAltText.test.ts b/tests/unit/repeated-alt-text.test.ts similarity index 97% rename from tests/repeatedAltText.test.ts rename to tests/unit/repeated-alt-text.test.ts index 7980ca4..89e0f43 100644 --- a/tests/repeatedAltText.test.ts +++ b/tests/unit/repeated-alt-text.test.ts @@ -1,6 +1,6 @@ import {describe, it, expect} from 'vitest' -import {repeatedAltText} from '../src/rules/repeatedAltText.js' -import {evaluateAlts} from './utils/helpers.js' +import {repeatedAltText} from '../../src/rules/repeated-alt-text.js' +import {evaluateAlts} from '../utils/helpers.js' describe('repeatedAltText', () => { describe('flags runs at or above the minimum length', () => { diff --git a/tests/vagueAltText.test.ts b/tests/unit/vague-alt-text.test.ts similarity index 96% rename from tests/vagueAltText.test.ts rename to tests/unit/vague-alt-text.test.ts index 8f41c95..53ca229 100644 --- a/tests/vagueAltText.test.ts +++ b/tests/unit/vague-alt-text.test.ts @@ -1,7 +1,7 @@ import {describe, it, expect} from 'vitest' -import {vagueAltText} from '../src/rules/vagueAltText.js' -import type {RuleContext} from '../src/types.js' -import {evaluateAlts, makeImage} from './utils/helpers.js' +import {vagueAltText} from '../../src/rules/vague-alt-text.js' +import type {RuleContext} from '../../src/types.js' +import {evaluateAlts, makeImage} from '../utils/helpers.js' describe('vagueAltText', () => { describe('flags vague single-word alt text', () => {