Tooling:
- ESLint 9 flat config (eslint.config.mjs) with three scopes:
- browser vanilla JS for js/ (no modules, window globals)
- Node ESM for scripts/
- typescript-eslint for tests/ and *.ts
- Stylelint with a deliberately minimal "bug-only" ruleset
(block-no-empty, color-no-invalid-hex, function-no-unknown,
property-no-unknown, …) — no nags about compact handwritten CSS
- html-validate against index.html (DOCTYPE, accessible names,
non-redundant ARIA roles, valid landmark usage)
- TypeScript --noEmit strict on playwright.config.ts + tests/*.ts
npm scripts:
- lint — parallel run of lint:js, lint:css, lint:html (~3s)
- lint:js{,:fix}, lint:css{,:fix}, lint:html
- typecheck — tsc --noEmit
- check — lint + typecheck + test in parallel (CI entry point)
Fixes uncovered by the new checks:
- js/app.js: drop unused `activeTimers`, drop unused `t` lookup in
refreshTreeRow, switch `activeTags` let→const, replace empty
`catch(_)` blocks with parameter-less catch + intent comment
- js/data.js: drop unused index arg in renderExperience
- index.html: uppercase DOCTYPE, drop redundant role="banner" /
role="contentinfo" on <header>/<footer>, add aria-labels on icon-only
Stop / Reset buttons, add role="group" to the tag bar so its
aria-label is valid, add explicit type="button" everywhere
- tests/portfolio.spec.ts: landmark test now uses getByRole() rather
than the explicit [role="banner"] attribute selector
Housekeeping:
- .gitignore picks up .eslintcache / .stylelintcache / *.tsbuildinfo
- README documents the lint + check toolchain
Co-authored-by: Cursor <cursoragent@cursor.com>
38 lines
1.2 KiB
JSON
38 lines
1.2 KiB
JSON
{
|
|
"rules": {
|
|
"block-no-empty": true,
|
|
"no-empty-source": true,
|
|
"no-duplicate-at-import-rules": true,
|
|
"no-invalid-double-slash-comments": true,
|
|
"no-invalid-position-at-import-rule": true,
|
|
"no-irregular-whitespace": true,
|
|
"comment-no-empty": true,
|
|
"font-family-no-missing-generic-family-keyword": true,
|
|
"function-calc-no-unspaced-operator": true,
|
|
"function-linear-gradient-no-nonstandard-direction": true,
|
|
"function-no-unknown": true,
|
|
"keyframe-declaration-no-important": true,
|
|
"media-query-no-invalid": true,
|
|
"named-grid-areas-no-invalid": true,
|
|
"selector-anb-no-unmatchable": true,
|
|
"selector-pseudo-class-no-unknown": true,
|
|
"selector-pseudo-element-no-unknown": true,
|
|
"selector-type-no-unknown": true,
|
|
"string-no-newline": true,
|
|
"unit-no-unknown": true,
|
|
"color-no-invalid-hex": true,
|
|
"declaration-block-no-duplicate-properties": [
|
|
true,
|
|
{ "ignore": ["consecutive-duplicates-with-different-values"] }
|
|
],
|
|
"declaration-block-no-shorthand-property-overrides": true,
|
|
"property-no-unknown": true,
|
|
"at-rule-no-unknown": true
|
|
},
|
|
"ignoreFiles": [
|
|
"node_modules/**",
|
|
"playwright-report/**",
|
|
"test-results/**"
|
|
]
|
|
}
|