Guidance for AI coding agents in this repo. Human contributors: see the Contributing section of the README.
This is attr-accept: a single function, accept(file, acceptedFiles), that checks whether a file
matches an HTML <input type="file"> accept attribute value (MIME types and/or file extensions).
It is a tiny, published npm library written in TypeScript with no runtime dependencies; keep it that
way - the whole point is to stay small.
The toolchain is the Rust-based oxc stack: oxlint to lint,
oxfmt to format, tsdown (Rolldown + oxc) to build and emit
declarations, and Vitest to test; TypeScript (tsc --noEmit) type-checks and
size-limit budgets the bundle. There is no Babel, ESLint, Prettier, or Rollup; do not reintroduce
them.
- Clarify the design before implementing. For anything non-trivial, agree on the approach first.
- One unit of change per commit. Never mix unrelated changes. Present the change for review before committing.
- Every change ships with tests. Run local CI before calling it done, and do not claim it passes without running it.
- Verify against the code and the tools: read before you answer, run before you assert.
Local CI (must be green before review):
npm run type-check # tsc --noEmit
npm run lint # oxlint
npm run lint:type-aware # oxlint --type-aware
npm run format:check # oxfmt --check
npm run build # tsdown -> dist/
npm run test:cov # vitest with coverage
npm run size # size-limit bundle budgetThe prek git hooks (installed via npm install) auto-run oxfmt and oxlint on staged code and
validate the commit message, but they do not run type-check, the build, or the tests, and they do
not format Markdown. Run the commands above yourself, and run npm run format after editing
docs/Markdown or CI's format:check will fail on it.
- Concise and to the point. No fluff. Explain the non-obvious; do not narrate the obvious.
- ASCII only. No em-dash and no
--; write-. Use->not the arrow glyph,!=not the not-equal glyph, and so on. - Comments justify why, not what. Delete any comment that restates the code.
- Formatting is not a matter of taste: oxfmt owns it. Run
npm run formatrather than hand-formatting. House style (.oxfmtrc.json) is double quotes, two-space indent, semicolons, no trailing commas, no bracket spacing ({a, b}), arrow parens omitted when possible, and a 120-column print width.
- Conventional Commits; the type set is enforced by a
commit-msg hook and consumed by semantic-release. Write the subject in the present tense,
imperative voice:
fix: match extensions case-insensitively, notfixedorfixes. feat:/fix:/perf:cut a release;feat!:or aBREAKING CHANGE:footer cuts a major.chore:/ci:/docs:/test:/refactor:/style:/build:do not. Pick the type with that in mind.- Keep the body minimal, or omit it. A good subject plus the diff is usually enough; add a body only for what the code cannot show (why, a trade-off, a non-obvious consequence). Never restate the change or narrate the diff.
- Disclose AI with an
Assisted-by: Claude:claude-opus-4-8trailer. NeverCo-Authored-By, and never add a human'sSigned-off-by.
- Unit tests live beside the source as
src/*.spec.tsand run under Vitest in thenodeenvironment (the function is pure and does not touch the DOM). - Cover the matching rules directly: wildcard MIME types (
image/*), exact MIME types, extensions (.png), array vs comma-delimited input, and the "accept when there is nothing to match against" short-circuits. Table-driven cases keep this readable. - Coverage must not drop. New code ships with tests that hold or raise it. Measure with
npm run test:cov.
- Source is TypeScript (ESM); no JSX. The published API is exactly what
src/index.tsexports: the defaultacceptfunction and theFileWithTypetype. Keep the README usage examples in step with any public change. - Stay dependency-free and small. The
size-limitbudget inpackage.jsonfails the build if the bundle grows past its limit; treat that as a design constraint, not an obstacle to raise.
npm run buildbundlessrc/index.tswith tsdown intodist/(ESM.js, CJS.cjs, and the.d.tsemitted from source). Do not hand-edit anything indist/- it is generated.- What ships to npm is the
filesallowlist inpackage.json(distandsrc, minus specs); keep it accurate. - Releases are automated by semantic-release from the commit history; the repo version stays
0.0.0-developmentand is set at publish time. Never bump the version by hand. Runtime is Node>= 22(engines).
- GitHub Actions live in
.github/workflows(test.ymlruns lint/format/types, the test matrix, and the size check;release.ymlpublishes). Write the workflowname:, every job name, and every named step in Sentence case (match the existing files). - Dependabot groups patch/minor bumps and auto-merges patches on green CI (
.github/dependabot.yml,dependabot-auto-merge.yml). Auto-merge trusts CI, so any check that must gate a dependency bump has to run in CI. - Keep workflows minimal and scoped to one purpose; prefer the built-in
GITHUB_TOKENover a personal access token.