feat(eslint-plugin): add no-raw-param-reads and no-href-arithmetic rules - #43
Merged
Merged
Conversation
Completes the bypass audit in both directions (design-20 LR1 + LR3):
- no-raw-param-reads: flags useSearchParams()/useParams() from
next/navigation and router.query from next/router's useRouter()
(variable, direct-call, and destructured forms), nudging the typed
hooks from @paramour-js/next/app and /pages. Escape hatch: an allow
option naming surfaces; per-site exemptions use disable comments.
- no-href-arithmetic: flags content appended after an href() result in
+ chains and template literals; prefix-only concatenation (origin +
href(route)) stays legal. The pure hash case is the plugin's first
autofix: href(route) + "#top" rewrites to href(route, { hash: "top" })
when the options provably carry no hash.
- Shared scope-resolution helpers extracted to src/utils/ and
no-raw-hrefs refactored onto them with no behavior change.
- no-raw-hrefs messages now say href(route, ...) - there is no
route.href() method to point at.
- Both new rules ship in configs.recommended at warn per design-15 LP7.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Merged
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First release from the design-20 rule roadmap (LR1 + LR3), completing the bypass audit in both directions:
no-raw-hrefsfinds every raw write paramour never sees; these add the raw reads and guard the integrity of whathref()builds.no-raw-param-reads(LR1, surfaces 1–2)useSearchParams()/useParams()imported fromnext/navigation(named/aliased/namespace forms,.jsspelling included), nudginguseSearch(route)/useRouteParams(route)from@paramour-js/next/app.router.queryon anext/routeruseRouter()router — variable, direct-call, and destructured forms (including renames and nested patterns) — nudging the@paramour-js/next/pageshooks.allow: ("routerQuery" | "useParams" | "useSearchParams")[]switches a surface off wholesale; one-off legitimate reads (e.g. untypedutm_*forwarding) use a targeted disable comment, blessed in the docs.next/navigation's router has no.query).no-href-arithmetic(LR3)href()result in+chains (flattened, reported once at the top) and template literals. Prefix-only concatenation —origin + href(route), the legitimate absolute-URL pattern — never fires.?suffix (which teaches thesearchoption, since the appended query needs a codec key — not autofixable per design-15 LP6).href(route) + "#top"→href(route, { hash: "top" }), applied only when the expression is exactly call-plus-literal and the options provably carry nohash(bail-outs for spreads, computed keys, non-object options, trailing commas, and comments the rewrite would delete)..href()method-form concern is moot — core has noroute.href()method;href()is standalone, which is what makes scope-resolved detection precise.Supporting changes
getImportBinding,resolveDef, generalizedgetImportedCallee/isImportedCall,getStaticPath,createRule/DOCS_URL) extracted tosrc/utils/;no-raw-hrefsrefactored onto them with zero behavior change (its 44 tests pass untouched).no-raw-hrefsmessage wording fixed: "the route's href()" →href(route, …).configs.recommendedatwarn(LP7); docs page gains two template-following sections (anchors match rule names for the RuleCreator URLs); README and package description updated; minor changeset added.Test plan
pnpm test packages/eslint-plugin— 110 tests (44 existing unchanged + 30 + 36 new, including autofix output assertions)pnpm lint,pnpm typecheck,pnpm format:checkpnpm build:packages+pnpm check:publish🤖 Generated with Claude Code