Rules
ramonda-check runs 86 rules. Each has its own page: what it reports, why that
is a fault, and what to write instead. The page and the terminal say the same thing, because both
come from the rule.
Every one of them fails the run. There is no warning level: a warning that never fails
anything is read once and then not read at all. Where a rule is wrong about your code, the
answer is // ramonda-check-ignore <reason> on the line — which records the decision rather
than hiding it, and is printed back on every run. See
how to say "not here".
Looking for a rule by the trouble it explains rather than by its name? Something is wrong is indexed by what you can see, and Accessibility groups the thirty-five that are about it.
Every rule
props-written-by-the-receiver— a component or hook assigns to its ownprops— the write throws in every build, and the value belonged to whoever rendered the elementcompute-takes-no-arguments— a@computedeclares a parameter, and its cache is keyed by nothing so the argument is ignoredasync-render—render()isasync, so it returns a promise where the diff expects markupstate-written-while-rendering— a state write is reached fromrender()or a@compute— directly, through a helper it calls, or three files awaystate-mutated-in-place— a@statearray or object is changed in place —this.items.push(…),this.user.name = …— so the signal never firesdecorator-that-adds-nothing— two decorators on one member give it the same thing —@persistbeside@state, or one written twiceunkeyable-memoized-argument— a@memoizedis called with — or declared to take — something a cache key cannot hold: a key holds a string, a number or a booleanclock-read-while-rendering—Date.now(),new Date()orMath.random()is reached from a render, by any pathref-built-where-it-cannot-be-kept—createRef()is called from a render, a@compute, a@memoizedmember a render calls, or a hook's props callback — so it answers a new identity every pass, the child re-renders for arefthat only looks changed, and nothing can readcurrentcached-read-of-a-plain-field— a@computeor a hook's props callback reads an ordinary field that is written after the first render, so the cached value goes stalearrow-fields— a class field holds a function literal, so every instance builds a fresh one and props comparison can never matchbrowser-url— a component readswindow.locationin a project whose router already holds the answerdom-writes— a component writes the document —document.body.classList.add(…)and its family — whererender()could have said itduplicate-decorators— a single-use decorator is written twice:@catchError,@ShouldUpdateOnPropsChangeor@StablePropsunwatched-fields— a component reads a form field it does not watch, so it never re-renders when that field changeswatch-of-a-prop-that-is-not-there— a@watchPropselector names something the component's props type does not declare, so the method never runspersist-of-a-lossy-value— a@persistfield holds aMap, aSet, aDate, a function or a class instance, none of which JSON carriesunserializable-state— a@statefield holds aMap, aSet, aDate, a function or a class instance, and the project renders on a serverinterval-with-no-cleanup— a component starts a rawsetIntervalwhose id nothing ever clears, so it keeps firing after unmountlistener-added-by-hand— a component adds awindowordocumentlistener by hand, where@onWindowor@onDocumentwould do it — or, insideif (__DEV__)where a decorator cannot be used, adds one that nothing ever removeslate-request-read—requestContext()is read below anawait, after the request it names is gonehead-tags-collide— two tags in oneHeadresolve to the same identity, so only the second is writtenunguarded-async-lifecycle— anasynclifecycle awaits something with notryor.catchto handle a failurecontext-consumed-above-its-provider— a component consumes a context on a line above the Provider that publishes it, so the consumer reads an ancestor's valueclient-only-request-read— arequestContext()read is on a path that only runs in the browser, where the value it names is never availableone-provider-per-component— one component mounts two Providers of the same context, which core refuses at runtimeserver-env-in-shared-code—process.envis read from a member the browser also runs, whereprocessdoes not existfresh-object-in-hook-props— a hook — a context Provider above all — is handed an object or array built inside its props callback, where the callback also reads something reactive, so the value is rebuilt and every consumer of that key wakes with contents that did not changefresh-value-from-a-watch-selector— a@watchPropselector builds the value it returns — an object or an array — soObject.iscan never match it and the watcher fires on every props change with nothing changedunsplittable-import— a dynamic import's path is neither a literal nor a template a bundler can read, so no chunk is emitted for itunexposed-env-read—import.meta.envis read for a name@ramonda/builddoes not expose, so the value readsundefinedrow-reads-a-plain-field— alist()row callback puts a field nothing can track into the markup, so a reused row keeps the old valuedev-guard-as-an-expression— a__DEV__guard is written as&&or?:where anifwould do the same thinglens-path-through-a-gap— afocusOnwrite walks through a hop the types say may benullorundefined, which only the LAST hop createsduplicate-key-among-siblings— two children written side by side claim the same literalkeyrow-without-a-key— a row built bymapor bylist()has nokeyindex-as-key— a row'skeyis built from the.mapindex and nothing else, which is the identity the diff already hadclass-instead-of-classname— an element carriesclasswhere Ramonda readsclassNametag-needs-its-parent— a tag is written outside the parent it requires —<tr>with no table above it,<option>with no selectparent-with-a-foreign-child— a container whose children are fixed by the content model holds a tag that is not one of theminteractive-inside-interactive— an interactive element is nested inside another of the same kind: a link in a link, a button in a button, a form in a formunnamed-image— animg,area, imageinputor emptyobjecthas noalt,aria-label,aria-labelledbyortitleunknown-aria-attribute— anaria-*attribute is not a name the ARIA specification hasunknown-role— arolenames nothing, or names an abstract role that markup may not userole-missing-required-aria— an explicitroleis written without thearia-*its specification requiresrole-takes-no-name— anaria-labeloraria-labelledbyis written on a role the specification forbids namingregion-with-no-name—role="region"is written with noaria-label,aria-labelledbyortitle, so it is not a landmark at allfalse-on-a-boolean-attribute— a boolean attribute is written"false", which turns it ON because the parser reads only that it is theremisspelled-element-property— a name is written in the wrong case for element state that lives only in a property, so it is written as an attribute nothing readshalf-built-keyboard-path— an element with an interactiveroleand a pointer handler is missing thetabIndexor the key handler that would finish itelement-html-removed— a tag HTML has removed is written, so nothing defines what it meansoption-that-cannot-choose—selectedis written on an<option>inside a<Select>, which sets it fromvalueinsteadaria-value— anaria-*attribute carries a literal value its specification does not permitaria-with-no-subject— aroleor anaria-*sits on an element with no accessibility tree node to describeempty-heading-or-link— a heading or a link has nothing inside it to announceunnamed-frame— aniframehas notitlepositive-tabindex— atabIndexis above zero, which reorders the whole document rather than one elementaria-hidden-on-focusable—aria-hidden="true"is written on an element a keyboard can still focusaria-hidden-around-something-focusable—aria-hidden="true"wraps something a keyboard can still tab topresentation-role-on-focusable—role="presentation"is written on an element a keyboard can still focus, where the role is ignoredaria-state-with-no-role— anaria-*belonging to a role is written on an element that has no rolearia-state-the-role-does-not-have— anaria-*sits beside arolethat does not support it, so nothing exposes itaria-that-contradicts-the-tag— anaria-*is writtenfalsebeside the HTML attribute that says the oppositerole-that-fights-the-tag— arolesays the element behaves in a way the tag does not — a link as a button, or a button as a linklive-region-that-contradicts-its-role— anaria-livereplaces the politeness the element's role already carriesautocomplete-that-fills-nothing— anautocompletevalue names no autofill field, so the browser ignores it entirelylabel-that-names-nothing— a<label>has nohtmlForand no control inside it, so it labels nothingtable-with-no-headers— a<table>written out with data rows has no<th>anywhere in itlink-without-a-destination— an<a>has nohref, or one that goes nowhere — empty,#, orjavascript:fresh-object-in-props— a component is handed an object or array built during the render, so it is a new value every time and comparison can never match — lift it to a field or a@compute, or declare it on the child with@StablePropsfunction-built-in-the-markup— a function literal is written into a JSX attribute — in the attribute, on one side of a ternary or a??, or in a local one line up — so its identity is fresh every render, and the listener is removed and re-added or the child can never compare its prop equalobject-among-the-children— a plain object is written among an element's children, where the runtime drops it and the page renders without itfunction-used-as-a-tag— a plain function is written in tag position, where it names nothing the framework can construct — and the compiler only refuses the shapes that do not return exactly one elementclick-with-no-keyboard-path— a click handler sits on a non-interactive element with no key handler, notabIndex, noroleand nothing interactive inside itaccess-key— anaccessKeyis written, which overrides a shortcut the reader's own software may be usingattribute-that-does-nothing— one of six camelCase names —httpEquiv,acceptCharset,defaultValue,defaultChecked,innerHTML,textContent— reaches the DOM as itself, where no browser reads itmedia-with-no-captions— avideooraudioelement carries no<track>, so nothing on the page says what is in itduplicate-id— two elements in one render carry the same literalid, and both are always presentheading-skips-a-level— a heading is more than one level below the heading before it, both written in the same rendermore-than-one-main— one render has more than onemainlandmark, where HTML allows onelandmarks-that-cannot-be-told-apart— one render has two or more landmarks of the same kind and none of them is namedlazy-imports-that-collide— twolazyfunctions are written identically but name different modules — the module cache is keyed by the function's source, so one entry has to serve bothfragment-link-to-nowhere— anhref="#name"points at an id no element in the project carriesreference-to-an-id-that-is-not-there— anaria-labelledby,htmlForor other id reference names an id no element in the project carriescontrol-with-no-label— a form control has no label, noaria-label, noaria-labelledbyand notitle, so nothing says what it is fornamed-only-by-a-placeholder— a form control's only name is itsplaceholder, which disappears as soon as anybody types
Next
- Checking your app — how to run it, and what it proves that a running page cannot.
- Diagnostics — what the framework reports at runtime.