Skip to content

[8/11] Add alpha/numeric checkers - #231

Merged
cinar merged 4 commits into
mainfrom
p1-08-alpha-numeric
Sep 5, 2026
Merged

[8/11] Add alpha/numeric checkers#231
cinar merged 4 commits into
mainfrom
p1-08-alpha-numeric

Conversation

@cinar

@cinar cinar commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Problem

alphanumeric and digits exist, but "letters only" and "a valid numeric string" (not just digits — allows a leading sign and a decimal point) are distinct, commonly-needed cases neither one covers.

Fix

Add alpha/numeric:

  • alpha.go mirrors alphanumeric.go/digits.go exactly, restricted to unicode.IsLetter.
  • numeric.go validates via strconv.ParseFloat rather than a hand-rolled character scan, so it correctly accepts signs, decimals, and scientific notation without reimplementing number-grammar parsing. An empty string is rejected (ParseFloat errors on it) — unlike the other loop-based string checkers here, which vacuously accept "". "" isn't a valid number, so this matches user expectation better than copying that side effect.
  • Both registered in maker.go. Left unmapped in schema_maker.go, matching the existing precedent that alphanumeric/digits/ascii/hex aren't schema-mapped either (they fall into x-checker) — no new judgment call needed about Unicode-regex portability in JSON Schema patterns.
  • NOT_ALPHA/NOT_NUMERIC messages added to all 23 locale files plus en-US.
  • Documented in the README's checker table.

Testing

  • alpha_test.go/numeric_test.go: valid/invalid (including empty-string and sign/decimal cases for numeric), non-string-field panic, struct-tag valid/invalid.
  • Full suite passes, 100% coverage maintained.
  • go vet, gosec, revive clean.

Fixes #205


Chain note: PR 8 of 11.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FLdVmP5daHiknrTW4Geh2i

cinar and others added 3 commits September 5, 2026 17:12
gte/lte cover inclusive bounds, but there was no strict-inequality
equivalent, a common gap for users coming from other validators.

- gt.go/lt.go mirror gte.go/lte.go exactly, including the CanInt/
  CanUint/CanFloat handling from #193 and the ErrNotNumeric-preserving
  contract on a non-numeric field.
- Registered in maker.go under "gt"/"lt".
- Added ExclusiveMinimum/ExclusiveMaximum to the Schema struct (no
  existing field covered them) and mapped gt/lt to them in
  schema_maker.go, matching JSON Schema's exclusiveMinimum/
  exclusiveMaximum keywords.
- NOT_GT/NOT_LT messages added to all 23 locale files plus en-US.
  Along the way, spotted that NOT_LTE's message is byte-identical to
  NOT_GTE's across every single locale file -- a pre-existing
  copy-paste bug (lte's error says "cannot be less than" when it
  should say "cannot be greater than"), unrelated to this change and
  left alone here; worth a small dedicated fix later.
- Documented in the README's checker table.

Fixes #203

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLdVmP5daHiknrTW4Geh2i
eq-field exists for comparing against a sibling struct field, but
there was no way to compare a field against a literal constant.

- IsEq/IsNe are generic (comparable), usable standalone for any type.
  The reflect-based checkers compare against the tag's string param
  via reflectString, so the tag form works for string-kind fields,
  matching how other single-purpose checkers in this package (email,
  hex, hash) already restrict themselves to strings.
- ne's error code is "EQ" (the value unexpectedly *is* equal, which is
  the failure condition for a "must not equal" check), separate from
  eq's "NOT_EQ", both carrying the compared-against value in the error
  data so failures are actionable ("Value must equal active." /
  "Value must not equal admin.").
- Added Const to the Schema struct (nothing existing covered it) and
  mapped eq to JSON Schema's const keyword. ne has no clean single-field
  JSON Schema translation without a Not *Schema field, which felt like
  too much structural surface for one checker, so it's left to record
  in XChecker like any other checker with no equivalent -- consistent
  with the project's existing "never silently drop" policy.
- NOT_EQ/EQ messages added to all 23 locale files plus en-US.
- Documented in the README's checker table.

Fixes #204

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLdVmP5daHiknrTW4Geh2i
alphanumeric and digits exist, but "letters only" and "a valid numeric
string" (not just digits -- allows a leading sign and a decimal point)
are distinct, commonly-needed cases neither one covers.

- alpha.go mirrors alphanumeric.go/digits.go exactly, restricted to
  unicode.IsLetter.
- numeric.go validates via strconv.ParseFloat rather than a hand-rolled
  character scan, so it correctly accepts signs, decimals, and
  scientific notation without reimplementing number-grammar parsing.
  An empty string is rejected (ParseFloat errors on it), unlike the
  other loop-based string checkers, which vacuously accept "" -- "" is
  not a valid number, and this matches user expectation better than
  copying that side effect.
- Both registered in maker.go. Left unmapped in schema_maker.go,
  matching the existing precedent that alphanumeric/digits/ascii/hex
  aren't schema-mapped either (they fall into XChecker).
- NOT_ALPHA/NOT_NUMERIC messages added to all 23 locale files plus
  en-US.
- Documented in the README's checker table.

Fixes #205

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLdVmP5daHiknrTW4Geh2i
Base automatically changed from p1-07-eq-ne to main September 5, 2026 17:23
@cinar
cinar enabled auto-merge (squash) September 5, 2026 17:24
@cinar
cinar merged commit 81c83d1 into main Sep 5, 2026
5 of 6 checks passed
@cinar
cinar deleted the p1-08-alpha-numeric branch September 5, 2026 17:25
cinar added a commit that referenced this pull request Sep 5, 2026
## Problem

`main` is currently red: the `build` CI job fails on `staticcheck`:

```
locales/fa_ir.go:11:25: string literal contains the Unicode format character U+200C, consider using the '‌' escape sequence instead (ST1018)
```

Introduced in #231 (`alpha`/`numeric` checkers) — the fa-IR translation
for `NOT_ALPHA` had a raw zero-width non-joiner character embedded
directly in the string literal instead of the escaped form every other
ZWNJ in this file already uses (see #178, which fixed this exact class
of issue previously).

## Fix

Replace the raw U+200C with the `\u200c` escape sequence, matching the
existing convention in the same file.

## Verification

Local `staticcheck` can't run in this environment (Go toolchain version
mismatch unrelated to this change), so verified with a Unicode-category
scan across every `.go` file in the repo for any `Cf` (format) character
— confirms this was the only occurrence.

- `go build`, `go vet`, `go test -race` (100% coverage), `gosec`,
`revive` all clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01FLdVmP5daHiknrTW4Geh2i

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add alpha/numeric string-content checkers

1 participant