From f4c33f9baa697114375db2177fa549778ac8ce06 Mon Sep 17 00:00:00 2001 From: Denny Septian Panggabean Date: Sat, 22 Aug 2026 10:14:57 +0700 Subject: [PATCH] docs: add AGENTS.md as agent guidance source of truth Add AGENTS.md with full guide for AI coding agents (project overview, commands, repo layout, architecture, coding conventions, git/PR rules) and reduce CLAUDE.md to a thin pointer to it. Co-Authored-By: Claude --- AGENTS.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 5 ++++ 2 files changed, 74 insertions(+) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..87e7a2e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,69 @@ +# AGENTS.md + +Guide for AI coding agents (Claude Code and others) working in this repository. This is the source of truth — `CLAUDE.md` points here. + +## Project + +`@phpdevsr/js-validation` — lightweight, zero-dependency vanilla JavaScript form validation library inspired by `jquery-validation`. Ships as UMD + ES module, no runtime deps, Node >= 22. + +## Commands + +```bash +npm ci # install (lockfile-respecting) +npm run build # vite build (UMD + ESM, unminified) then minified build +npm test # vitest run — unit tests +npm run test:watch # vitest watch +npm run test:e2e # playwright (chromium + firefox + webkit), auto-serves on :5174 +npm run release # maintainer-only: bumps version + changelog (.github/scripts/release.sh) +``` + +CI uses Node 24 (`.github/workflows/ci.yml`), `.nvmrc` says 22, `package.json` engines says `>=22`. Use 22+ locally. + +## Repo layout + +- `src/core.js` — `VanillaValidator` class. The whole engine: rule registration (`addMethod`), locale messages (`addLocaleMessages`), rule resolution from `options.rules` + `data-rule-*` dataset, per-field `element()` validation, `validate()`, `showError`/`clearError`, submit + input event binding. +- `src/index.js` — full bundle entry: imports core, all rules, registers all locales, exports `jsValidation` default + `VanillaValidator` named. +- `src/core-entry.js` — core-only entry (no rules, no locales). For selective imports via `js-validation/core` + `js-validation/rules/*`. +- `src/rules/*.js` — one file per built-in rule. Each calls `VanillaValidator.addMethod(name, validateFn, message)`. +- `src/locales.js` — aggregates locale files from `src/locales/.js` (currently `en`, `es`). +- `test/js-validation.test.js` — vitest unit tests (jsdom-free; hand-rolled fake field/form objects). +- `test/selective-import.test.js` — verifies core-only entry works. +- `test/e2e//` — Playwright fixture (`fixture.html`) + spec per rule; `test/e2e/validation.spec.js` is the general one. +- `vite.config.js` (unminified), `vite.config.min.js` (terser-minified), `vite.config.e2e.js` (dev server for e2e, root `test/e2e`, aliases `/src` → `src`). +- `docs-site/` — separate Astro docs site (own `package.json`). +- `dist/` — build output, gitignored. + +## Architecture & conventions + +**Rule registration is global/static.** `VanillaValidator.methods` and `.locales` are static class properties. Rules register themselves as a side effect of import — `src/rules/email.js` just calls `addMethod` at module top level. Importing a rule file = registering that rule. This is why `core-entry.js` + selective rule imports work, and why test file load order matters (a rule imported by one test file is registered globally for all). + +**Adding a built-in rule** (see CONTRIBUTING.md): +1. Create `src/rules/myRule.js` — `import { VanillaValidator } from '../core.js'` then `addMethod(name, (value, param, field, validator) => bool, message)`. Message can be a string or `(param, field) => string`. +2. Import it in `src/index.js` (`import './rules/myRule.js'`). +3. Add a locale entry in each `src/locales/.js`. +4. Add tests in `test/js-validation.test.js` and an e2e fixture/spec in `test/e2e/`. + +**Adding a locale:** create `src/locales/.js` exporting a `{ ruleName: message }` object, then re-export it from `src/locales.js`. + +**Rule resolution per field** (`_rulesFor`): merges `data-rule-*` dataset attributes with `options.rules[fieldName]`. Dataset keys like `dataRuleEmail` → rule name `email` (first char after `rule` lowercased). A `data-rule-*` with empty value means `true`; `false`/`'false'` param skips the rule. `range` params are JSON-parsed arrays. + +**Message resolution** (`_messageFor`): `options.messages[field][rule]` → locale messages for `this.lang` (default `en`) → English fallback → rule's default message. Functions receive `(param, field)`. + +**Validation runs synchronously** in `element()`: iterates rules in insertion order, fails on first invalid rule, shows error, returns false. `validate()` runs `element()` over all non-disabled, named, non-submit fields. + +**Error display** toggles an `is-invalid` class on the field and inserts an error element (``, configurable via options) after the field, keyed by `data-jsv-error-for=""`. The unit tests use fake DOM objects with a manual `classList` Set, so no jsdom is needed. + +## Coding conventions + +- ESM throughout (`"type": "module"`). No build step for source — Vite only bundles `src/index.js` for dist. +- Vanilla JS, no TypeScript, no transpilation. Keep source readable as-is. +- Zero runtime dependencies — do not add any. Dev deps only (vite, vitest, playwright, terser). +- Match existing rule file style: single `addMethod` call, message as string or `(param) =>` fn. +- Prototype-pollution hardening: `addMethod`/`addLocaleMessages` reject `__proto__`/`constructor`/`prototype` keys. Preserve this guard when touching registration code. + +## Git & PRs + +- Branching: `develop` is the working branch (PRs target it); `main` is release-only. Current default for PRs is `develop`. +- PR titles must follow Conventional Commits: `feat|fix|chore|docs|perf|refactor|style|test|config|revert(scope)?!: summary` (enforced by `.github/prlint.json`). +- Dependabot keeps GitHub Actions and dev deps bumped — expect frequent `chore(deps)` commits. +- Don't commit `dist/`; it's built in CI and gitignored. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..00fc947 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +# CLAUDE.md + +This file is a thin pointer — `AGENTS.md` is the source of truth for agent guidance in this repo. + +See [AGENTS.md](AGENTS.md) for the full guide: project overview, commands, repo layout, architecture, coding conventions, and git/PR rules.