docs: generate pages for compiler/runtime warnings/errors (#13557)

* docs: generate pages for compiler/runtime warnings/errors

Ideally each warning has accompanying details so that it doesn't look so empty on the final site, but that can happen separately

* fix

* sort alphabetically, code ticks for headings

* only uppercase first word

* regenerate

* generate codes using [!NOTE], remove any backticks and escape `<` characters

* some prose preceeding the list of compiler warnings

* bring over prose from Svelte 4 a11y warnings

* fix

* lint

* remove backticks from headers, now that they are getting rendered

* Revert "remove backticks from headers, now that they are getting rendered"

This reverts commit c295281848.

* back to normal headers/code blocks

* fix

* separate authored from generated stuff

* newlines

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
annotate-notes
Simon H 3 months ago committed by GitHub
parent 1c8d1ca124
commit 4578d4f25a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,129 @@
### bind_invalid_checkbox_value
```
Using `bind:value` together with a checkbox input is not allowed. Use `bind:checked` instead
```
### bind_invalid_export
```
Component %component% has an export named `%key%` that a consumer component is trying to access using `bind:%key%`, which is disallowed. Instead, use `bind:this` (e.g. `<%name% bind:this={component} />`) and then access the property on the bound component instance (e.g. `component.%key%`)
```
### bind_not_bindable
```
A component is attempting to bind to a non-bindable property `%key%` belonging to %component% (i.e. `<%name% bind:%key%={...}>`). To mark a property as bindable: `let { %key% = $bindable() } = $props()`
```
### component_api_changed
```
%parent% called `%method%` on an instance of %component%, which is no longer valid in Svelte 5. See https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes for more information
```
### component_api_invalid_new
```
Attempted to instantiate %component% with `new %name%`, which is no longer valid in Svelte 5. If this component is not under your control, set the `compatibility.componentApi` compiler option to `4` to keep it working. See https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes for more information
```
### derived_references_self
```
A derived value cannot reference itself recursively
```
### each_key_duplicate
```
Keyed each block has duplicate key at indexes %a% and %b%
```
```
Keyed each block has duplicate key `%value%` at indexes %a% and %b%
```
### effect_in_teardown
```
`%rune%` cannot be used inside an effect cleanup function
```
### effect_in_unowned_derived
```
Effect cannot be created inside a `$derived` value that was not itself created inside an effect
```
### effect_orphan
```
`%rune%` can only be used inside an effect (e.g. during component initialisation)
```
### effect_update_depth_exceeded
```
Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops
```
### hydration_failed
```
Failed to hydrate the application
```
### invalid_snippet
```
Could not `{@render}` snippet due to the expression being `null` or `undefined`. Consider using optional chaining `{@render snippet?.()}`
```
### lifecycle_legacy_only
```
`%name%(...)` cannot be used in runes mode
```
### props_invalid_value
```
Cannot do `bind:%key%={undefined}` when `%key%` has a fallback value
```
### props_rest_readonly
```
Rest element properties of `$props()` such as `%property%` are readonly
```
### rune_outside_svelte
```
The `%rune%` rune is only available inside `.svelte` and `.svelte.js/ts` files
```
### state_descriptors_fixed
```
Property descriptors defined on `$state` objects must contain `value` and always be `enumerable`, `configurable` and `writable`.
```
### state_prototype_fixed
```
Cannot set prototype of `$state` object
```
### state_unsafe_local_read
```
Reading state that was created inside the same derived is forbidden. Consider using `untrack` to read locally created state
```
### state_unsafe_mutation
```
Updating state inside a derived is forbidden. If the value should not be reactive, declare it without `$state`
```

@ -0,0 +1,98 @@
### binding_property_non_reactive
```
`%binding%` is binding to a non-reactive property
```
```
`%binding%` (%location%) is binding to a non-reactive property
```
### console_log_state
```
Your `console.%method%` contained `$state` proxies. Consider using `$inspect(...)` or `$state.snapshot(...)` instead
```
When logging a [proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy), browser devtools will log the proxy itself rather than the value it represents. In the case of Svelte, the 'target' of a `$state` proxy might not resemble its current value, which can be confusing.
The easiest way to log a value as it changes over time is to use the [`$inspect`](https://svelte-5-preview.vercel.app/docs/runes#$inspect) rune. Alternatively, to log things on a one-off basis (for example, inside an event handler) you can use [`$state.snapshot`](https://svelte-5-preview.vercel.app/docs/runes#$state-snapshot) to take a snapshot of the current value.
### event_handler_invalid
```
%handler% should be a function. Did you mean to %suggestion%?
```
### hydration_attribute_changed
```
The `%attribute%` attribute on `%html%` changed its value between server and client renders. The client value, `%value%`, will be ignored in favour of the server value
```
### hydration_html_changed
```
The value of an `{@html ...}` block changed between server and client renders. The client value will be ignored in favour of the server value
```
```
The value of an `{@html ...}` block %location% changed between server and client renders. The client value will be ignored in favour of the server value
```
### hydration_mismatch
```
Hydration failed because the initial UI does not match what was rendered on the server
```
```
Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near %location%
```
### invalid_raw_snippet_render
```
The `render` function passed to `createRawSnippet` should return HTML for a single element
```
### lifecycle_double_unmount
```
Tried to unmount a component that was not mounted
```
### ownership_invalid_binding
```
%parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
```
### ownership_invalid_mutation
```
Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
```
```
%component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
```
### state_proxy_equality_mismatch
```
Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results
```
`$state(...)` creates a [proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) of the value it is passed. The proxy and the value have different identities, meaning equality checks will always return `false`:
```svelte
<script>
let value = { foo: 'bar' };
let proxy = $state(value);
value === proxy; // always false
</script>
```
To resolve this, ensure you're comparing values where both values were created with `$state(...)`, or neither were. Note that `$state.raw(...)` will _not_ create a state proxy.

@ -0,0 +1,945 @@
### animation_duplicate
```
An element can only have one 'animate' directive
```
### animation_invalid_placement
```
An element that uses the `animate:` directive must be the only child of a keyed `{#each ...}` block
```
### animation_missing_key
```
An element that uses the `animate:` directive must be the only child of a keyed `{#each ...}` block. Did you forget to add a key to your each block?
```
### attribute_contenteditable_dynamic
```
'contenteditable' attribute cannot be dynamic if element uses two-way binding
```
### attribute_contenteditable_missing
```
'contenteditable' attribute is required for textContent, innerHTML and innerText two-way bindings
```
### attribute_duplicate
```
Attributes need to be unique
```
### attribute_empty_shorthand
```
Attribute shorthand cannot be empty
```
### attribute_invalid_event_handler
```
Event attribute must be a JavaScript expression, not a string
```
### attribute_invalid_multiple
```
'multiple' attribute must be static if select uses two-way binding
```
### attribute_invalid_name
```
'%name%' is not a valid attribute name
```
### attribute_invalid_sequence_expression
```
Sequence expressions are not allowed as attribute/directive values in runes mode, unless wrapped in parentheses
```
### attribute_invalid_type
```
'type' attribute must be a static text value if input uses two-way binding
```
### attribute_unquoted_sequence
```
Attribute values containing `{...}` must be enclosed in quote marks, unless the value only contains the expression
```
### bind_invalid_expression
```
Can only bind to an Identifier or MemberExpression
```
### bind_invalid_name
```
`bind:%name%` is not a valid binding
```
```
`bind:%name%` is not a valid binding. %explanation%
```
### bind_invalid_target
```
`bind:%name%` can only be used with %elements%
```
### bind_invalid_value
```
Can only bind to state or props
```
### bindable_invalid_location
```
`$bindable()` can only be used inside a `$props()` declaration
```
### block_duplicate_clause
```
%name% cannot appear more than once within a block
```
### block_invalid_continuation_placement
```
{:...} block is invalid at this position (did you forget to close the preceeding element or block?)
```
### block_invalid_elseif
```
'elseif' should be 'else if'
```
### block_invalid_placement
```
{#%name% ...} block cannot be %location%
```
### block_unclosed
```
Block was left open
```
### block_unexpected_character
```
Expected a `%character%` character immediately following the opening bracket
```
### block_unexpected_close
```
Unexpected block closing tag
```
### component_invalid_directive
```
This type of directive is not valid on components
```
### const_tag_cycle
```
Cyclical dependency detected: %cycle%
```
### const_tag_invalid_expression
```
{@const ...} must consist of a single variable declaration
```
### const_tag_invalid_placement
```
`{@const}` must be the immediate child of `{#snippet}`, `{#if}`, `{:else if}`, `{:else}`, `{#each}`, `{:then}`, `{:catch}`, `<svelte:fragment>` or `<Component>`
```
### constant_assignment
```
Cannot assign to %thing%
```
### constant_binding
```
Cannot bind to %thing%
```
### css_empty_declaration
```
Declaration cannot be empty
```
### css_expected_identifier
```
Expected a valid CSS identifier
```
### css_global_block_invalid_combinator
```
A `:global` selector cannot follow a `%name%` combinator
```
### css_global_block_invalid_declaration
```
A top-level `:global {...}` block can only contain rules, not declarations
```
### css_global_block_invalid_list
```
A `:global` selector cannot be part of a selector list with more than one item
```
### css_global_block_invalid_modifier
```
A `:global` selector cannot modify an existing selector
```
### css_global_block_invalid_modifier_start
```
A `:global` selector can only be modified if it is a descendant of other selectors
```
### css_global_invalid_placement
```
`:global(...)` can be at the start or end of a selector sequence, but not in the middle
```
### css_global_invalid_selector
```
`:global(...)` must contain exactly one selector
```
### css_global_invalid_selector_list
```
`:global(...)` must not contain type or universal selectors when used in a compound selector
```
### css_nesting_selector_invalid_placement
```
Nesting selectors can only be used inside a rule or as the first selector inside a lone `:global(...)`
```
### css_selector_invalid
```
Invalid selector
```
### css_type_selector_invalid_placement
```
`:global(...)` must not be followed by a type selector
```
### debug_tag_invalid_arguments
```
{@debug ...} arguments must be identifiers, not arbitrary expressions
```
### declaration_duplicate
```
`%name%` has already been declared
```
### declaration_duplicate_module_import
```
Cannot declare a variable with the same name as an import inside `<script module>`
```
### derived_invalid_export
```
Cannot export derived state from a module. To expose the current derived value, export a function returning its value
```
### directive_invalid_value
```
Directive value must be a JavaScript expression enclosed in curly braces
```
### directive_missing_name
```
`%type%` name cannot be empty
```
### dollar_binding_invalid
```
The $ name is reserved, and cannot be used for variables and imports
```
### dollar_prefix_invalid
```
The $ prefix is reserved, and cannot be used for variables and imports
```
### each_item_invalid_assignment
```
Cannot reassign or bind to each block argument in runes mode. Use the array and index variables instead (e.g. `array[i] = value` instead of `entry = value`)
```
### effect_invalid_placement
```
`$effect()` can only be used as an expression statement
```
### element_invalid_closing_tag
```
`</%name%>` attempted to close an element that was not open
```
### element_invalid_closing_tag_autoclosed
```
`</%name%>` attempted to close element that was already automatically closed by `<%reason%>` (cannot nest `<%reason%>` inside `<%name%>`)
```
### element_unclosed
```
`<%name%>` was left open
```
### event_handler_invalid_component_modifier
```
Event modifiers other than 'once' can only be used on DOM elements
```
### event_handler_invalid_modifier
```
Valid event modifiers are %list%
```
### event_handler_invalid_modifier_combination
```
The '%modifier1%' and '%modifier2%' modifiers cannot be used together
```
### expected_attribute_value
```
Expected attribute value
```
### expected_block_type
```
Expected 'if', 'each', 'await', 'key' or 'snippet'
```
### expected_identifier
```
Expected an identifier
```
### expected_pattern
```
Expected identifier or destructure pattern
```
### expected_token
```
Expected token %token%
```
### expected_whitespace
```
Expected whitespace
```
### global_reference_invalid
```
`%name%` is an illegal variable name. To reference a global variable called `%name%`, use `globalThis.%name%`
```
### host_invalid_placement
```
`$host()` can only be used inside custom element component instances
```
### import_svelte_internal_forbidden
```
Imports of `svelte/internal/*` are forbidden. It contains private runtime code which is subject to change without notice. If you're importing from `svelte/internal/*` to work around a limitation of Svelte, please open an issue at https://github.com/sveltejs/svelte and explain your use case
```
### invalid_arguments_usage
```
The arguments keyword cannot be used within the template or at the top level of a component
```
### js_parse_error
```
%message%
```
### legacy_export_invalid
```
Cannot use `export let` in runes mode — use `$props()` instead
```
### legacy_props_invalid
```
Cannot use `$$props` in runes mode
```
### legacy_reactive_statement_invalid
```
`$:` is not allowed in runes mode, use `$derived` or `$effect` instead
```
### legacy_rest_props_invalid
```
Cannot use `$$restProps` in runes mode
```
### let_directive_invalid_placement
```
`let:` directive at invalid position
```
### mixed_event_handler_syntaxes
```
Mixing old (on:%name%) and new syntaxes for event handling is not allowed. Use only the on%name% syntax
```
### module_illegal_default_export
```
A component cannot have a default export
```
### node_invalid_placement
```
%thing% is invalid inside `<%parent%>`
```
HTML restricts where certain elements can appear. In case of a violation the browser will 'repair' the HTML in a way that breaks Svelte's assumptions about the structure of your components. Some examples:
- `<p>hello <div>world</div></p>` will result in `<p>hello </p><div>world</div><p></p>` for example (the `<div>` autoclosed the `<p>` because `<p>` cannot contain block-level elements)
- `<option><div>option a</div></option>` will result in `<option>option a</option>` (the `<div>` is removed)
- `<table><tr><td>cell</td></tr></table>` will result in `<table><tbody><tr><td>cell</td></tr></tbody></table>` (a `<tbody>` is auto-inserted)
### options_invalid_value
```
Invalid compiler option: %details%
```
### options_removed
```
Invalid compiler option: %details%
```
### options_unrecognised
```
Unrecognised compiler option %keypath%
```
### props_duplicate
```
Cannot use `$props()` more than once
```
### props_illegal_name
```
Declaring or accessing a prop starting with `$$` is illegal (they are reserved for Svelte internals)
```
### props_invalid_identifier
```
`$props()` can only be used with an object destructuring pattern
```
### props_invalid_pattern
```
`$props()` assignment must not contain nested properties or computed keys
```
### props_invalid_placement
```
`$props()` can only be used at the top level of components as a variable declaration initializer
```
### reactive_declaration_cycle
```
Cyclical dependency detected: %cycle%
```
### render_tag_invalid_call_expression
```
Calling a snippet function using apply, bind or call is not allowed
```
### render_tag_invalid_expression
```
`{@render ...}` tags can only contain call expressions
```
### render_tag_invalid_spread_argument
```
cannot use spread arguments in `{@render ...}` tags
```
### rune_invalid_arguments
```
`%rune%` cannot be called with arguments
```
### rune_invalid_arguments_length
```
`%rune%` must be called with %args%
```
### rune_invalid_computed_property
```
Cannot access a computed property of a rune
```
### rune_invalid_name
```
`%name%` is not a valid rune
```
### rune_invalid_usage
```
Cannot use `%rune%` rune in non-runes mode
```
### rune_missing_parentheses
```
Cannot use rune without parentheses
```
### rune_removed
```
The `%name%` rune has been removed
```
### rune_renamed
```
`%name%` is now `%replacement%`
```
### runes_mode_invalid_import
```
%name% cannot be used in runes mode
```
### script_duplicate
```
A component can have a single top-level `<script>` element and/or a single top-level `<script module>` element
```
### script_invalid_attribute_value
```
If the `%name%` attribute is supplied, it must be a boolean attribute
```
### script_invalid_context
```
If the context attribute is supplied, its value must be "module"
```
### script_reserved_attribute
```
The `%name%` attribute is reserved and cannot be used
```
### slot_attribute_duplicate
```
Duplicate slot name '%name%' in <%component%>
```
### slot_attribute_invalid
```
slot attribute must be a static value
```
### slot_attribute_invalid_placement
```
Element with a slot='...' attribute must be a child of a component or a descendant of a custom element
```
### slot_default_duplicate
```
Found default slot content alongside an explicit slot="default"
```
### slot_element_invalid_attribute
```
`<slot>` can only receive attributes and (optionally) let directives
```
### slot_element_invalid_name
```
slot attribute must be a static value
```
### slot_element_invalid_name_default
```
`default` is a reserved word — it cannot be used as a slot name
```
### slot_snippet_conflict
```
Cannot use `<slot>` syntax and `{@render ...}` tags in the same component. Migrate towards `{@render ...}` tags completely
```
### snippet_conflict
```
Cannot use explicit children snippet at the same time as implicit children content. Remove either the non-whitespace content or the children snippet block
```
### snippet_invalid_rest_parameter
```
Snippets do not support rest parameters; use an array instead
```
### snippet_parameter_assignment
```
Cannot reassign or bind to snippet parameter
```
### snippet_shadowing_prop
```
This snippet is shadowing the prop `%prop%` with the same name
```
### state_invalid_export
```
Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties
```
### state_invalid_placement
```
`%rune%(...)` can only be used as a variable declaration initializer or a class field
```
### store_invalid_scoped_subscription
```
Cannot subscribe to stores that are not declared at the top level of the component
```
### store_invalid_subscription
```
Cannot reference store value inside `<script module>`
```
### store_invalid_subscription_module
```
Cannot reference store value outside a `.svelte` file
```
Using a `$` prefix to refer to the value of a store is only possible inside `.svelte` files, where Svelte can automatically create subscriptions when a component is mounted and unsubscribe when the component is unmounted. Consider migrating to runes instead.
### style_directive_invalid_modifier
```
`style:` directive can only use the `important` modifier
```
### style_duplicate
```
A component can have a single top-level `<style>` element
```
### svelte_body_illegal_attribute
```
`<svelte:body>` does not support non-event attributes or spread attributes
```
### svelte_component_invalid_this
```
Invalid component definition — must be an `{expression}`
```
### svelte_component_missing_this
```
`<svelte:component>` must have a 'this' attribute
```
### svelte_element_missing_this
```
`<svelte:element>` must have a 'this' attribute with a value
```
### svelte_fragment_invalid_attribute
```
`<svelte:fragment>` can only have a slot attribute and (optionally) a let: directive
```
### svelte_fragment_invalid_placement
```
`<svelte:fragment>` must be the direct child of a component
```
### svelte_head_illegal_attribute
```
`<svelte:head>` cannot have attributes nor directives
```
### svelte_meta_duplicate
```
A component can only have one `<%name%>` element
```
### svelte_meta_invalid_content
```
<%name%> cannot have children
```
### svelte_meta_invalid_placement
```
`<%name%>` tags cannot be inside elements or blocks
```
### svelte_meta_invalid_tag
```
Valid `<svelte:...>` tag names are %list%
```
### svelte_options_deprecated_tag
```
"tag" option is deprecated — use "customElement" instead
```
### svelte_options_invalid_attribute
```
`<svelte:options>` can only receive static attributes
```
### svelte_options_invalid_attribute_value
```
Value must be %list%, if specified
```
### svelte_options_invalid_customelement
```
"customElement" must be a string literal defining a valid custom element name or an object of the form { tag?: string; shadow?: "open" | "none"; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
```
### svelte_options_invalid_customelement_props
```
"props" must be a statically analyzable object literal of the form "{ [key: string]: { attribute?: string; reflect?: boolean; type?: "String" | "Boolean" | "Number" | "Array" | "Object" }"
```
### svelte_options_invalid_customelement_shadow
```
"shadow" must be either "open" or "none"
```
### svelte_options_invalid_tagname
```
Tag name must be lowercase and hyphenated
```
See https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name for more information on valid tag names
### svelte_options_reserved_tagname
```
Tag name is reserved
```
See https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name for more information on valid tag names
### svelte_options_unknown_attribute
```
`<svelte:options>` unknown attribute '%name%'
```
### svelte_self_invalid_placement
```
`<svelte:self>` components can only exist inside `{#if}` blocks, `{#each}` blocks, `{#snippet}` blocks or slots passed to components
```
### tag_invalid_name
```
Expected a valid element or component name. Components must have a valid variable name or dot notation expression
```
### tag_invalid_placement
```
{@%name% ...} tag cannot be %location%
```
### textarea_invalid_content
```
A `<textarea>` can have either a value attribute or (equivalently) child content, but not both
```
### title_illegal_attribute
```
`<title>` cannot have attributes nor directives
```
### title_invalid_content
```
`<title>` can only contain text and {tags}
```
### transition_conflict
```
Cannot use `%type%:` alongside existing `%existing%:` directive
```
### transition_duplicate
```
Cannot use multiple `%type%:` directives on a single element
```
### typescript_invalid_feature
```
TypeScript language features like %feature% are not natively supported, and their use is generally discouraged. Outside of `<script>` tags, these features are not supported. For use within `<script>` tags, you will need to use a preprocessor to convert it to JavaScript before it gets passed to the Svelte compiler. If you are using `vitePreprocess`, make sure to specifically enable preprocessing script tags (`vitePreprocess({ script: true })`)
```
### unexpected_eof
```
Unexpected end of input
```
### unexpected_reserved_word
```
'%word%' is a reserved word in JavaScript and cannot be used here
```
### void_element_invalid_content
```
Void elements cannot have children or closing tags
```

@ -0,0 +1,817 @@
### a11y_accesskey
```
Avoid using accesskey
```
Enforce no `accesskey` on element. Access keys are HTML attributes that allow web developers to assign keyboard shortcuts to elements. Inconsistencies between keyboard shortcuts and keyboard commands used by screen reader and keyboard-only users create accessibility complications. To avoid complications, access keys should not be used.
<!-- prettier-ignore -->
```svelte
<!-- A11y: Avoid using accesskey -->
<div accesskey="z"></div>
```
### a11y_aria_activedescendant_has_tabindex
```
An element with an aria-activedescendant attribute should have a tabindex value
```
An element with `aria-activedescendant` must be tabbable, so it must either have an inherent `tabindex` or declare `tabindex` as an attribute.
```svelte
<!-- A11y: Elements with attribute aria-activedescendant should have tabindex value -->
<div aria-activedescendant="some-id"></div>
```
### a11y_aria_attributes
```
`<%name%>` should not have aria-* attributes
```
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `aria-*` props.
```svelte
<!-- A11y: <meta> should not have aria-* attributes -->
<meta aria-hidden="false" />
```
### a11y_autocomplete_valid
```
'%value%' is an invalid value for 'autocomplete' on `<input type="%type%">`
```
### a11y_autofocus
```
Avoid using autofocus
```
Enforce that `autofocus` is not used on elements. Autofocusing elements can cause usability issues for sighted and non-sighted users alike.
```svelte
<!-- A11y: Avoid using autofocus -->
<input autofocus />
```
### a11y_click_events_have_key_events
```
Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as `<button type="button">` or `<a>` might be more appropriate. See https://svelte.dev/docs/accessibility-warnings#a11y-click-events-have-key-events for more details
```
Enforce that visible, non-interactive elements with an `onclick` event are accompanied by a keyboard event handler.
Users should first consider whether an interactive element might be more appropriate such as a `<button type="button">` element for actions or `<a>` element for navigations. These elements are more semantically meaningful and will have built-in key handling. E.g. `Space` and `Enter` will trigger a `<button>` and `Enter` will trigger an `<a>` element.
If a non-interactive element is required then `onclick` should be accompanied by an `onkeyup` or `onkeydown` handler that enables the user to perform equivalent actions via the keyboard. In order for the user to be able to trigger a key press, the element will also need to be focusable by adding a [`tabindex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex). While an `onkeypress` handler will also silence this warning, it should be noted that the `keypress` event is deprecated.
```svelte
<!-- A11y: visible, non-interactive elements with an onclick event must be accompanied by a keyboard event handler. -->
<div onclick={() => {}}></div>
```
Coding for the keyboard is important for users with physical disabilities who cannot use a mouse, AT compatibility, and screenreader users.
### a11y_consider_explicit_label
```
Buttons and links should either contain text or have an `aria-label` or `aria-labelledby` attribute
```
### a11y_distracting_elements
```
Avoid `<%name%>` elements
```
Enforces that no distracting elements are used. Elements that can be visually distracting can cause accessibility issues with visually impaired users. Such elements are most likely deprecated, and should be avoided.
The following elements are visually distracting: `<marquee>` and `<blink>`.
```svelte
<!-- A11y: Avoid <marquee> elements -->
<marquee></marquee>
```
### a11y_figcaption_index
```
`<figcaption>` must be first or last child of `<figure>`
```
### a11y_figcaption_parent
```
`<figcaption>` must be an immediate child of `<figure>`
```
Enforce that certain DOM elements have the correct structure.
```svelte
<!-- A11y: <figcaption> must be an immediate child of <figure> -->
<div>
<figcaption>Image caption</figcaption>
</div>
```
### a11y_hidden
```
`<%name%>` element should not be hidden
```
Certain DOM elements are useful for screen reader navigation and should not be hidden.
<!-- prettier-ignore -->
```svelte
<!-- A11y: <h2> element should not be hidden -->
<h2 aria-hidden="true">invisible header</h2>
```
### a11y_img_redundant_alt
```
Screenreaders already announce `<img>` elements as an image
```
Enforce img alt attribute does not contain the word image, picture, or photo. Screen readers already announce `img` elements as an image. There is no need to use words such as _image_, _photo_, and/or _picture_.
```svelte
<img src="foo" alt="Foo eating a sandwich." />
<!-- aria-hidden, won't be announced by screen reader -->
<img src="bar" aria-hidden="true" alt="Picture of me taking a photo of an image" />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="foo" alt="Photo of foo being weird." />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="bar" alt="Image of me at a bar!" />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="foo" alt="Picture of baz fixing a bug." />
```
### a11y_incorrect_aria_attribute_type
```
The value of '%attribute%' must be a %type%
```
Enforce that only the correct type of value is used for aria attributes. For example, `aria-hidden`
should only receive a boolean.
```svelte
<!-- A11y: The value of 'aria-hidden' must be exactly one of true or false -->
<div aria-hidden="yes"></div>
```
### a11y_incorrect_aria_attribute_type_boolean
```
The value of '%attribute%' must be either 'true' or 'false'. It cannot be empty
```
### a11y_incorrect_aria_attribute_type_id
```
The value of '%attribute%' must be a string that represents a DOM element ID
```
### a11y_incorrect_aria_attribute_type_idlist
```
The value of '%attribute%' must be a space-separated list of strings that represent DOM element IDs
```
### a11y_incorrect_aria_attribute_type_integer
```
The value of '%attribute%' must be an integer
```
### a11y_incorrect_aria_attribute_type_token
```
The value of '%attribute%' must be exactly one of %values%
```
### a11y_incorrect_aria_attribute_type_tokenlist
```
The value of '%attribute%' must be a space-separated list of one or more of %values%
```
### a11y_incorrect_aria_attribute_type_tristate
```
The value of '%attribute%' must be exactly one of true, false, or mixed
```
### a11y_interactive_supports_focus
```
Elements with the '%role%' interactive role must have a tabindex value
```
Enforce that elements with an interactive role and interactive handlers (mouse or key press) must be focusable or tabbable.
```svelte
<!-- A11y: Elements with the 'button' interactive role must have a tabindex value. -->
<div role="button" onkeypress={() => {}} />
```
### a11y_invalid_attribute
```
'%href_value%' is not a valid %href_attribute% attribute
```
Enforce that attributes important for accessibility have a valid value. For example, `href` should not be empty, `'#'`, or `javascript:`.
```svelte
<!-- A11y: '' is not a valid href attribute -->
<a href="">invalid</a>
```
### a11y_label_has_associated_control
```
A form label must be associated with a control
```
Enforce that a label tag has a text label and an associated control.
There are two supported ways to associate a label with a control:
- Wrapping a control in a label tag.
- Adding `for` to a label and assigning it the ID of an input on the page.
```svelte
<label for="id">B</label>
<label>C <input type="text" /></label>
<!-- A11y: A form label must be associated with a control. -->
<label>A</label>
```
### a11y_media_has_caption
```
`<video>` elements must have a `<track kind="captions">`
```
Providing captions for media is essential for deaf users to follow along. Captions should be a transcription or translation of the dialogue, sound effects, relevant musical cues, and other relevant audio information. Not only is this important for accessibility, but can also be useful for all users in the case that the media is unavailable (similar to `alt` text on an image when an image is unable to load).
The captions should contain all important and relevant information to understand the corresponding media. This may mean that the captions are not a 1:1 mapping of the dialogue in the media content. However, captions are not necessary for video components with the `muted` attribute.
```svelte
<video><track kind="captions" /></video>
<audio muted></audio>
<!-- A11y: Media elements must have a <track kind=\"captions\"> -->
<video></video>
<!-- A11y: Media elements must have a <track kind=\"captions\"> -->
<video><track /></video>
```
### a11y_misplaced_role
```
`<%name%>` should not have role attribute
```
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `role` props.
```svelte
<!-- A11y: <meta> should not have role attribute -->
<meta role="tooltip" />
```
### a11y_misplaced_scope
```
The scope attribute should only be used with `<th>` elements
```
The scope attribute should only be used on `<th>` elements.
<!-- prettier-ignore -->
```svelte
<!-- A11y: The scope attribute should only be used with <th> elements -->
<div scope="row" />
```
### a11y_missing_attribute
```
`<%name%>` element should have %article% %sequence% attribute
```
Enforce that attributes required for accessibility are present on an element. This includes the following checks:
- `<a>` should have an href (unless it's a [fragment-defining tag](https://github.com/sveltejs/svelte/issues/4697))
- `<area>` should have alt, aria-label, or aria-labelledby
- `<html>` should have lang
- `<iframe>` should have title
- `<img>` should have alt
- `<object>` should have title, aria-label, or aria-labelledby
- `<input type="image">` should have alt, aria-label, or aria-labelledby
```svelte
<!-- A11y: <input type=\"image\"> element should have an alt, aria-label or aria-labelledby attribute -->
<input type="image" />
<!-- A11y: <html> element should have a lang attribute -->
<html></html>
<!-- A11y: <a> element should have an href attribute -->
<a>text</a>
```
### a11y_missing_content
```
`<%name%>` element should contain text
```
Enforce that heading elements (`h1`, `h2`, etc.) and anchors have content and that the content is accessible to screen readers
```svelte
<!-- A11y: <a> element should have child content -->
<a href="/foo"></a>
<!-- A11y: <h1> element should have child content -->
<h1></h1>
```
### a11y_mouse_events_have_key_events
```
'%event%' event must be accompanied by '%accompanied_by%' event
```
Enforce that `onmouseover` and `onmouseout` are accompanied by `onfocus` and `onblur`, respectively. This helps to ensure that any functionality triggered by these mouse events is also accessible to keyboard users.
```svelte
<!-- A11y: onmouseover must be accompanied by onfocus -->
<div onmouseover={handleMouseover} />
<!-- A11y: onmouseout must be accompanied by onblur -->
<div onmouseout={handleMouseout} />
```
### a11y_no_abstract_role
```
Abstract role '%role%' is forbidden
```
### a11y_no_interactive_element_to_noninteractive_role
```
`<%element%>` cannot have role '%role%'
```
[WAI-ARIA](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) roles should not be used to convert an interactive element to a non-interactive element. Non-interactive ARIA roles include `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`.
```svelte
<!-- A11y: <textarea> cannot have role 'listitem' -->
<textarea role="listitem"></textarea>
```
### a11y_no_noninteractive_element_interactions
```
Non-interactive element `<%element%>` should not be assigned mouse or keyboard event listeners
```
A non-interactive element does not support event handlers (mouse and key handlers). Non-interactive elements include `<main>`, `<area>`, `<h1>` (,`<h2>`, etc), `<p>`, `<img>`, `<li>`, `<ul>` and `<ol>`. Non-interactive [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) include `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`.
```sv
<!-- `A11y: Non-interactive element <li> should not be assigned mouse or keyboard event listeners.` -->
<li onclick={() => {}}></li>
<!-- `A11y: Non-interactive element <div> should not be assigned mouse or keyboard event listeners.` -->
<div role="listitem" onclick={() => {}}></div>
```
### a11y_no_noninteractive_element_to_interactive_role
```
Non-interactive element `<%element%>` cannot have interactive role '%role%'
```
[WAI-ARIA](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) roles should not be used to convert a non-interactive element to an interactive element. Interactive ARIA roles include `button`, `link`, `checkbox`, `menuitem`, `menuitemcheckbox`, `menuitemradio`, `option`, `radio`, `searchbox`, `switch` and `textbox`.
```svelte
<!-- A11y: Non-interactive element <h3> cannot have interactive role 'searchbox' -->
<h3 role="searchbox">Button</h3>
```
### a11y_no_noninteractive_tabindex
```
noninteractive element cannot have nonnegative tabIndex value
```
Tab key navigation should be limited to elements on the page that can be interacted with.
<!-- prettier-ignore -->
```svelte
<!-- A11y: noninteractive element cannot have nonnegative tabIndex value -->
<div tabindex="0"></div>
```
### a11y_no_redundant_roles
```
Redundant role '%role%'
```
Some HTML elements have default ARIA roles. Giving these elements an ARIA role that is already set by the browser [has no effect](https://www.w3.org/TR/using-aria/#aria-does-nothing) and is redundant.
```svelte
<!-- A11y: Redundant role 'button' -->
<button role="button">...</button>
<!-- A11y: Redundant role 'img' -->
<img role="img" src="foo.jpg" />
```
### a11y_no_static_element_interactions
```
`<%element%>` with a %handler% handler must have an ARIA role
```
Elements like `<div>` with interactive handlers like `click` must have an ARIA role.
<!-- prettier-ignore -->
```svelte
<!-- A11y: <div> with click handler must have an ARIA role -->
<div onclick={() => ''}></div>
```
### a11y_positive_tabindex
```
Avoid tabindex values above zero
```
Avoid positive `tabindex` property values. This will move elements out of the expected tab order, creating a confusing experience for keyboard users.
<!-- prettier-ignore -->
```svelte
<!-- A11y: avoid tabindex values above zero -->
<div tabindex="1"></div>
```
### a11y_role_has_required_aria_props
```
Elements with the ARIA role "%role%" must have the following attributes defined: %props%
```
Elements with ARIA roles must have all required attributes for that role.
```svelte
<!-- A11y: A11y: Elements with the ARIA role "checkbox" must have the following attributes defined: "aria-checked" -->
<span role="checkbox" aria-labelledby="foo" tabindex="0"></span>
```
### a11y_role_supports_aria_props
```
The attribute '%attribute%' is not supported by the role '%role%'
```
Elements with explicit or implicit roles defined contain only `aria-*` properties supported by that role.
```svelte
<!-- A11y: The attribute 'aria-multiline' is not supported by the role 'link'. -->
<div role="link" aria-multiline></div>
<!-- A11y: The attribute 'aria-required' is not supported by the role 'listitem'. This role is implicit on the element <li>. -->
<li aria-required></li>
```
### a11y_role_supports_aria_props_implicit
```
The attribute '%attribute%' is not supported by the role '%role%'. This role is implicit on the element `<%name%>`
```
Elements with explicit or implicit roles defined contain only `aria-*` properties supported by that role.
```svelte
<!-- A11y: The attribute 'aria-multiline' is not supported by the role 'link'. -->
<div role="link" aria-multiline></div>
<!-- A11y: The attribute 'aria-required' is not supported by the role 'listitem'. This role is implicit on the element <li>. -->
<li aria-required></li>
```
### a11y_unknown_aria_attribute
```
Unknown aria attribute 'aria-%attribute%'
```
```
Unknown aria attribute 'aria-%attribute%'. Did you mean '%suggestion%'?
```
Enforce that only known ARIA attributes are used. This is based on the [WAI-ARIA States and Properties spec](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties).
```svelte
<!-- A11y: Unknown aria attribute 'aria-labeledby' (did you mean 'labelledby'?) -->
<input type="image" aria-labeledby="foo" />
```
### a11y_unknown_role
```
Unknown role '%role%'
```
```
Unknown role '%role%'. Did you mean '%suggestion%'?
```
Elements with ARIA roles must use a valid, non-abstract ARIA role. A reference to role definitions can be found at [WAI-ARIA](https://www.w3.org/TR/wai-aria/#role_definitions) site.
<!-- prettier-ignore -->
```svelte
<!-- A11y: Unknown role 'toooltip' (did you mean 'tooltip'?) -->
<div role="toooltip"></div>
```
### attribute_avoid_is
```
The "is" attribute is not supported cross-browser and should be avoided
```
### attribute_global_event_reference
```
You are referencing `globalThis.%name%`. Did you forget to declare a variable with that name?
```
### attribute_illegal_colon
```
Attributes should not contain ':' characters to prevent ambiguity with Svelte directives
```
### attribute_invalid_property_name
```
'%wrong%' is not a valid HTML attribute. Did you mean '%right%'?
```
### attribute_quoted
```
Quoted attributes on components and custom elements will be stringified in a future version of Svelte. If this isn't what you want, remove the quotes
```
### bind_invalid_each_rest
```
The rest operator (...) will create a new object and binding '%name%' with the original object will not work
```
### block_empty
```
Empty block
```
### component_name_lowercase
```
`<%name%>` will be treated as an HTML element unless it begins with a capital letter
```
### css_unused_selector
```
Unused CSS selector "%name%"
```
### element_invalid_self_closing_tag
```
Self-closing HTML tags for non-void elements are ambiguous — use `<%name% ...></%name%>` rather than `<%name% ... />`
```
### event_directive_deprecated
```
Using `on:%name%` to listen to the %name% event is deprecated. Use the event attribute `on%name%` instead
```
### export_let_unused
```
Component has unused export property '%name%'. If it is for external reference only, please consider using `export const %name%`
```
### legacy_code
```
`%code%` is no longer valid — please use `%suggestion%` instead
```
### legacy_component_creation
```
Svelte 5 components are no longer classes. Instantiate them using `mount` or `hydrate` (imported from 'svelte') instead.
```
### node_invalid_placement_ssr
```
%thing% is invalid inside `<%parent%>`. When rendering this component on the server, the resulting HTML will be modified by the browser, likely resulting in a `hydration_mismatch` warning
```
HTML restricts where certain elements can appear. In case of a violation the browser will 'repair' the HTML in a way that breaks Svelte's assumptions about the structure of your components. Some examples:
- `<p>hello <div>world</div></p>` will result in `<p>hello </p><div>world</div><p></p>` for example (the `<div>` autoclosed the `<p>` because `<p>` cannot contain block-level elements)
- `<option><div>option a</div></option>` will result in `<option>option a</option>` (the `<div>` is removed)
- `<table><tr><td>cell</td></tr></table>` will result in `<table><tbody><tr><td>cell</td></tr></tbody></table>` (a `<tbody>` is auto-inserted)
This code will work when the component is rendered on the client (which is why this is a warning rather than an error), but if you use server rendering it will cause hydration to fail.
### non_reactive_update
```
`%name%` is updated, but is not declared with `$state(...)`. Changing its value will not correctly trigger updates
```
### options_deprecated_accessors
```
The `accessors` option has been deprecated. It will have no effect in runes mode
```
### options_deprecated_immutable
```
The `immutable` option has been deprecated. It will have no effect in runes mode
```
### options_missing_custom_element
```
The `customElement` option is used when generating a custom element. Did you forget the `customElement: true` compile option?
```
### options_removed_enable_sourcemap
```
The `enableSourcemap` option has been removed. Source maps are always generated now, and tooling can choose to ignore them
```
### options_removed_hydratable
```
The `hydratable` option has been removed. Svelte components are always hydratable now
```
### options_removed_loop_guard_timeout
```
The `loopGuardTimeout` option has been removed
```
### options_renamed_ssr_dom
```
`generate: "dom"` and `generate: "ssr"` options have been renamed to "client" and "server" respectively
```
### perf_avoid_inline_class
```
Avoid 'new class' — instead, declare the class at the top level scope
```
### perf_avoid_nested_class
```
Avoid declaring classes below the top level scope
```
### reactive_declaration_invalid_placement
```
Reactive declarations only exist at the top level of the instance script
```
### reactive_declaration_module_script_dependency
```
Reassignments of module-level declarations will not cause reactive statements to update
```
### reactive_declaration_non_reactive_property
```
Properties of objects and arrays are not reactive unless in runes mode. Changes to this property will not cause the reactive statement to update
```
### script_context_deprecated
```
`context="module"` is deprecated, use the `module` attribute instead
```
### script_unknown_attribute
```
Unrecognized attribute — should be one of `generics`, `lang` or `module`. If this exists for a preprocessor, ensure that the preprocessor removes it
```
### slot_element_deprecated
```
Using `<slot>` to render parent content is deprecated. Use `{@render ...}` tags instead
```
### state_referenced_locally
```
State referenced in its own scope will never update. Did you mean to reference it inside a closure?
```
### store_rune_conflict
```
It looks like you're using the `$%name%` rune, but there is a local binding called `%name%`. Referencing a local variable with a `$` prefix will create a store subscription. Please rename `%name%` to avoid the ambiguity
```
### svelte_component_deprecated
```
`<svelte:component>` is deprecated in runes mode — components are dynamic by default
```
In previous versions of Svelte, the component constructor was fixed when the component was rendered. In other words, if you wanted `<X>` to re-render when `X` changed, you would either have to use `<svelte:component this={X}>` or put the component inside a `{#key X}...{/key}` block.
In Svelte 5 this is no longer true — if `X` changes, `<X>` re-renders.
In some cases `<object.property>` syntax can be used as a replacement; a lowercased variable with property access is recognized as a component in Svelte 5.
For complex component resolution logic, an intermediary, capitalized variable may be necessary. E.g. in places where `@const` can be used:
```diff
{#each items as item}
- <svelte:component this={item.condition ? Y : Z} />
+ {@const Component = item.condition ? Y : Z}
+ <Component />
{/each}
```
A derived value may be used in other contexts:
```diff
<script>
...
let condition = $state(false);
+ const Component = $derived(condition ? Y : Z);
</script>
- <svelte:component this={condition ? Y : Z} />
+ <Component />
```
### svelte_element_invalid_this
```
`this` should be an `{expression}`. Using a string attribute value will cause an error in future versions of Svelte
```
### svelte_self_deprecated
```
`<svelte:self>` is deprecated — use self-imports (e.g. `import %name% from './%basename%'`) instead
```
### unknown_code
```
`%code%` is not a recognised code
```
```
`%code%` is not a recognised code (did you mean `%suggestion%`?)
```

@ -0,0 +1,5 @@
### lifecycle_function_unavailable
```
`%name%(...)` is not available on the server
```

@ -0,0 +1,23 @@
### invalid_default_snippet
```
Cannot use `{@render children(...)}` if the parent component uses `let:` directives. Consider using a named snippet instead
```
### lifecycle_outside_component
```
`%name%(...)` can only be used during component initialisation
```
### store_invalid_shape
```
`%name%` is not a store with a `subscribe` method
```
### svelte_element_invalid_this_value
```
The `this` prop on `<svelte:element>` must be a string, if defined
```

@ -0,0 +1,17 @@
### dynamic_void_element_content
```
`<svelte:element this="%tag%">` is a void element — it cannot have content
```
### state_snapshot_uncloneable
```
Value cannot be cloned with `$state.snapshot` — the original value was returned
```
```
The following properties cannot be cloned with `$state.snapshot` — the return value contains the originals:
%properties%
```

@ -0,0 +1,5 @@
---
title: 'Compiler errors'
---
@include .generated/compile-errors.md

@ -0,0 +1,21 @@
---
title: 'Compiler warnings'
---
Svelte warns you at compile time if it catches potential mistakes, such as writing inaccessible markup.
Some warnings may be incorrect in your concrete use case. You can disable such false positives by placing a `<!-- svelte-ignore <code> -->` comment above the line that causes the warning. Example:
```svelte
<!-- svelte-ignore a11y_autofocus -->
<input autofocus />
```
You can list multiple rules in a single comment (separated by commas), and add an explanatory note (in parentheses) alongside them:
```svelte
<!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_static_element_interactions (because of reasons) -->
<div onclick>...</div>
```
@include .generated/compile-warnings.md

@ -0,0 +1,15 @@
---
title: 'Runtime errors'
---
## Client errors
@include .generated/client-errors.md
## Server errors
@include .generated/server-errors.md
## Shared errors
@include .generated/shared-errors.md

@ -0,0 +1,11 @@
---
title: 'Runtime warnings'
---
## Client errors
@include .generated/client-errors.md
## Shared errors
@include .generated/shared-errors.md

@ -2,14 +2,36 @@
> Avoid using accesskey > Avoid using accesskey
Enforce no `accesskey` on element. Access keys are HTML attributes that allow web developers to assign keyboard shortcuts to elements. Inconsistencies between keyboard shortcuts and keyboard commands used by screen reader and keyboard-only users create accessibility complications. To avoid complications, access keys should not be used.
<!-- prettier-ignore -->
```svelte
<!-- A11y: Avoid using accesskey -->
<div accesskey="z"></div>
```
## a11y_aria_activedescendant_has_tabindex ## a11y_aria_activedescendant_has_tabindex
> An element with an aria-activedescendant attribute should have a tabindex value > An element with an aria-activedescendant attribute should have a tabindex value
An element with `aria-activedescendant` must be tabbable, so it must either have an inherent `tabindex` or declare `tabindex` as an attribute.
```svelte
<!-- A11y: Elements with attribute aria-activedescendant should have tabindex value -->
<div aria-activedescendant="some-id"></div>
```
## a11y_aria_attributes ## a11y_aria_attributes
> `<%name%>` should not have aria-* attributes > `<%name%>` should not have aria-* attributes
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `aria-*` props.
```svelte
<!-- A11y: <meta> should not have aria-* attributes -->
<meta aria-hidden="false" />
```
## a11y_autocomplete_valid ## a11y_autocomplete_valid
> '%value%' is an invalid value for 'autocomplete' on `<input type="%type%">` > '%value%' is an invalid value for 'autocomplete' on `<input type="%type%">`
@ -18,10 +40,30 @@
> Avoid using autofocus > Avoid using autofocus
Enforce that `autofocus` is not used on elements. Autofocusing elements can cause usability issues for sighted and non-sighted users alike.
```svelte
<!-- A11y: Avoid using autofocus -->
<input autofocus />
```
## a11y_click_events_have_key_events ## a11y_click_events_have_key_events
> Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as `<button type="button">` or `<a>` might be more appropriate. See https://svelte.dev/docs/accessibility-warnings#a11y-click-events-have-key-events for more details > Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as `<button type="button">` or `<a>` might be more appropriate. See https://svelte.dev/docs/accessibility-warnings#a11y-click-events-have-key-events for more details
Enforce that visible, non-interactive elements with an `onclick` event are accompanied by a keyboard event handler.
Users should first consider whether an interactive element might be more appropriate such as a `<button type="button">` element for actions or `<a>` element for navigations. These elements are more semantically meaningful and will have built-in key handling. E.g. `Space` and `Enter` will trigger a `<button>` and `Enter` will trigger an `<a>` element.
If a non-interactive element is required then `onclick` should be accompanied by an `onkeyup` or `onkeydown` handler that enables the user to perform equivalent actions via the keyboard. In order for the user to be able to trigger a key press, the element will also need to be focusable by adding a [`tabindex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex). While an `onkeypress` handler will also silence this warning, it should be noted that the `keypress` event is deprecated.
```svelte
<!-- A11y: visible, non-interactive elements with an onclick event must be accompanied by a keyboard event handler. -->
<div onclick={() => {}}></div>
```
Coding for the keyboard is important for users with physical disabilities who cannot use a mouse, AT compatibility, and screenreader users.
## a11y_consider_explicit_label ## a11y_consider_explicit_label
> Buttons and links should either contain text or have an `aria-label` or `aria-labelledby` attribute > Buttons and links should either contain text or have an `aria-label` or `aria-labelledby` attribute
@ -30,6 +72,15 @@
> Avoid `<%name%>` elements > Avoid `<%name%>` elements
Enforces that no distracting elements are used. Elements that can be visually distracting can cause accessibility issues with visually impaired users. Such elements are most likely deprecated, and should be avoided.
The following elements are visually distracting: `<marquee>` and `<blink>`.
```svelte
<!-- A11y: Avoid <marquee> elements -->
<marquee></marquee>
```
## a11y_figcaption_index ## a11y_figcaption_index
> `<figcaption>` must be first or last child of `<figure>` > `<figcaption>` must be first or last child of `<figure>`
@ -38,18 +89,61 @@
> `<figcaption>` must be an immediate child of `<figure>` > `<figcaption>` must be an immediate child of `<figure>`
Enforce that certain DOM elements have the correct structure.
```svelte
<!-- A11y: <figcaption> must be an immediate child of <figure> -->
<div>
<figcaption>Image caption</figcaption>
</div>
```
## a11y_hidden ## a11y_hidden
> `<%name%>` element should not be hidden > `<%name%>` element should not be hidden
Certain DOM elements are useful for screen reader navigation and should not be hidden.
<!-- prettier-ignore -->
```svelte
<!-- A11y: <h2> element should not be hidden -->
<h2 aria-hidden="true">invisible header</h2>
```
## a11y_img_redundant_alt ## a11y_img_redundant_alt
> Screenreaders already announce `<img>` elements as an image > Screenreaders already announce `<img>` elements as an image
Enforce img alt attribute does not contain the word image, picture, or photo. Screen readers already announce `img` elements as an image. There is no need to use words such as _image_, _photo_, and/or _picture_.
```svelte
<img src="foo" alt="Foo eating a sandwich." />
<!-- aria-hidden, won't be announced by screen reader -->
<img src="bar" aria-hidden="true" alt="Picture of me taking a photo of an image" />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="foo" alt="Photo of foo being weird." />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="bar" alt="Image of me at a bar!" />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="foo" alt="Picture of baz fixing a bug." />
```
## a11y_incorrect_aria_attribute_type ## a11y_incorrect_aria_attribute_type
> The value of '%attribute%' must be a %type% > The value of '%attribute%' must be a %type%
Enforce that only the correct type of value is used for aria attributes. For example, `aria-hidden`
should only receive a boolean.
```svelte
<!-- A11y: The value of 'aria-hidden' must be exactly one of true or false -->
<div aria-hidden="yes"></div>
```
## a11y_incorrect_aria_attribute_type_boolean ## a11y_incorrect_aria_attribute_type_boolean
> The value of '%attribute%' must be either 'true' or 'false'. It cannot be empty > The value of '%attribute%' must be either 'true' or 'false'. It cannot be empty
@ -82,38 +176,140 @@
> Elements with the '%role%' interactive role must have a tabindex value > Elements with the '%role%' interactive role must have a tabindex value
Enforce that elements with an interactive role and interactive handlers (mouse or key press) must be focusable or tabbable.
```svelte
<!-- A11y: Elements with the 'button' interactive role must have a tabindex value. -->
<div role="button" onkeypress={() => {}} />
```
## a11y_invalid_attribute ## a11y_invalid_attribute
> '%href_value%' is not a valid %href_attribute% attribute > '%href_value%' is not a valid %href_attribute% attribute
Enforce that attributes important for accessibility have a valid value. For example, `href` should not be empty, `'#'`, or `javascript:`.
```svelte
<!-- A11y: '' is not a valid href attribute -->
<a href="">invalid</a>
```
## a11y_label_has_associated_control ## a11y_label_has_associated_control
> A form label must be associated with a control > A form label must be associated with a control
Enforce that a label tag has a text label and an associated control.
There are two supported ways to associate a label with a control:
- Wrapping a control in a label tag.
- Adding `for` to a label and assigning it the ID of an input on the page.
```svelte
<label for="id">B</label>
<label>C <input type="text" /></label>
<!-- A11y: A form label must be associated with a control. -->
<label>A</label>
```
## a11y_media_has_caption ## a11y_media_has_caption
> `<video>` elements must have a `<track kind="captions">` > `<video>` elements must have a `<track kind="captions">`
Providing captions for media is essential for deaf users to follow along. Captions should be a transcription or translation of the dialogue, sound effects, relevant musical cues, and other relevant audio information. Not only is this important for accessibility, but can also be useful for all users in the case that the media is unavailable (similar to `alt` text on an image when an image is unable to load).
The captions should contain all important and relevant information to understand the corresponding media. This may mean that the captions are not a 1:1 mapping of the dialogue in the media content. However, captions are not necessary for video components with the `muted` attribute.
```svelte
<video><track kind="captions" /></video>
<audio muted></audio>
<!-- A11y: Media elements must have a <track kind=\"captions\"> -->
<video></video>
<!-- A11y: Media elements must have a <track kind=\"captions\"> -->
<video><track /></video>
```
## a11y_misplaced_role ## a11y_misplaced_role
> `<%name%>` should not have role attribute > `<%name%>` should not have role attribute
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `role` props.
```svelte
<!-- A11y: <meta> should not have role attribute -->
<meta role="tooltip" />
```
## a11y_misplaced_scope ## a11y_misplaced_scope
> The scope attribute should only be used with `<th>` elements > The scope attribute should only be used with `<th>` elements
The scope attribute should only be used on `<th>` elements.
<!-- prettier-ignore -->
```svelte
<!-- A11y: The scope attribute should only be used with <th> elements -->
<div scope="row" />
```
## a11y_missing_attribute ## a11y_missing_attribute
> `<%name%>` element should have %article% %sequence% attribute > `<%name%>` element should have %article% %sequence% attribute
Enforce that attributes required for accessibility are present on an element. This includes the following checks:
- `<a>` should have an href (unless it's a [fragment-defining tag](https://github.com/sveltejs/svelte/issues/4697))
- `<area>` should have alt, aria-label, or aria-labelledby
- `<html>` should have lang
- `<iframe>` should have title
- `<img>` should have alt
- `<object>` should have title, aria-label, or aria-labelledby
- `<input type="image">` should have alt, aria-label, or aria-labelledby
```svelte
<!-- A11y: <input type=\"image\"> element should have an alt, aria-label or aria-labelledby attribute -->
<input type="image" />
<!-- A11y: <html> element should have a lang attribute -->
<html></html>
<!-- A11y: <a> element should have an href attribute -->
<a>text</a>
```
## a11y_missing_content ## a11y_missing_content
> `<%name%>` element should contain text > `<%name%>` element should contain text
Enforce that heading elements (`h1`, `h2`, etc.) and anchors have content and that the content is accessible to screen readers
```svelte
<!-- A11y: <a> element should have child content -->
<a href="/foo"></a>
<!-- A11y: <h1> element should have child content -->
<h1></h1>
```
## a11y_mouse_events_have_key_events ## a11y_mouse_events_have_key_events
> '%event%' event must be accompanied by '%accompanied_by%' event > '%event%' event must be accompanied by '%accompanied_by%' event
Enforce that `onmouseover` and `onmouseout` are accompanied by `onfocus` and `onblur`, respectively. This helps to ensure that any functionality triggered by these mouse events is also accessible to keyboard users.
```svelte
<!-- A11y: onmouseover must be accompanied by onfocus -->
<div onmouseover={handleMouseover} />
<!-- A11y: onmouseout must be accompanied by onblur -->
<div onmouseout={handleMouseout} />
```
## a11y_no_abstract_role ## a11y_no_abstract_role
> Abstract role '%role%' is forbidden > Abstract role '%role%' is forbidden
@ -122,50 +318,150 @@
> `<%element%>` cannot have role '%role%' > `<%element%>` cannot have role '%role%'
[WAI-ARIA](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) roles should not be used to convert an interactive element to a non-interactive element. Non-interactive ARIA roles include `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`.
```svelte
<!-- A11y: <textarea> cannot have role 'listitem' -->
<textarea role="listitem"></textarea>
```
## a11y_no_noninteractive_element_interactions ## a11y_no_noninteractive_element_interactions
> Non-interactive element `<%element%>` should not be assigned mouse or keyboard event listeners > Non-interactive element `<%element%>` should not be assigned mouse or keyboard event listeners
A non-interactive element does not support event handlers (mouse and key handlers). Non-interactive elements include `<main>`, `<area>`, `<h1>` (,`<h2>`, etc), `<p>`, `<img>`, `<li>`, `<ul>` and `<ol>`. Non-interactive [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) include `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`.
```sv
<!-- `A11y: Non-interactive element <li> should not be assigned mouse or keyboard event listeners.` -->
<li onclick={() => {}}></li>
<!-- `A11y: Non-interactive element <div> should not be assigned mouse or keyboard event listeners.` -->
<div role="listitem" onclick={() => {}}></div>
```
## a11y_no_noninteractive_element_to_interactive_role ## a11y_no_noninteractive_element_to_interactive_role
> Non-interactive element `<%element%>` cannot have interactive role '%role%' > Non-interactive element `<%element%>` cannot have interactive role '%role%'
[WAI-ARIA](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) roles should not be used to convert a non-interactive element to an interactive element. Interactive ARIA roles include `button`, `link`, `checkbox`, `menuitem`, `menuitemcheckbox`, `menuitemradio`, `option`, `radio`, `searchbox`, `switch` and `textbox`.
```svelte
<!-- A11y: Non-interactive element <h3> cannot have interactive role 'searchbox' -->
<h3 role="searchbox">Button</h3>
```
## a11y_no_noninteractive_tabindex ## a11y_no_noninteractive_tabindex
> noninteractive element cannot have nonnegative tabIndex value > noninteractive element cannot have nonnegative tabIndex value
Tab key navigation should be limited to elements on the page that can be interacted with.
<!-- prettier-ignore -->
```svelte
<!-- A11y: noninteractive element cannot have nonnegative tabIndex value -->
<div tabindex="0"></div>
```
## a11y_no_redundant_roles ## a11y_no_redundant_roles
> Redundant role '%role%' > Redundant role '%role%'
Some HTML elements have default ARIA roles. Giving these elements an ARIA role that is already set by the browser [has no effect](https://www.w3.org/TR/using-aria/#aria-does-nothing) and is redundant.
```svelte
<!-- A11y: Redundant role 'button' -->
<button role="button">...</button>
<!-- A11y: Redundant role 'img' -->
<img role="img" src="foo.jpg" />
```
## a11y_no_static_element_interactions ## a11y_no_static_element_interactions
> `<%element%>` with a %handler% handler must have an ARIA role > `<%element%>` with a %handler% handler must have an ARIA role
Elements like `<div>` with interactive handlers like `click` must have an ARIA role.
<!-- prettier-ignore -->
```svelte
<!-- A11y: <div> with click handler must have an ARIA role -->
<div onclick={() => ''}></div>
```
## a11y_positive_tabindex ## a11y_positive_tabindex
> Avoid tabindex values above zero > Avoid tabindex values above zero
Avoid positive `tabindex` property values. This will move elements out of the expected tab order, creating a confusing experience for keyboard users.
<!-- prettier-ignore -->
```svelte
<!-- A11y: avoid tabindex values above zero -->
<div tabindex="1"></div>
```
## a11y_role_has_required_aria_props ## a11y_role_has_required_aria_props
> Elements with the ARIA role "%role%" must have the following attributes defined: %props% > Elements with the ARIA role "%role%" must have the following attributes defined: %props%
Elements with ARIA roles must have all required attributes for that role.
```svelte
<!-- A11y: A11y: Elements with the ARIA role "checkbox" must have the following attributes defined: "aria-checked" -->
<span role="checkbox" aria-labelledby="foo" tabindex="0"></span>
```
## a11y_role_supports_aria_props ## a11y_role_supports_aria_props
> The attribute '%attribute%' is not supported by the role '%role%' > The attribute '%attribute%' is not supported by the role '%role%'
Elements with explicit or implicit roles defined contain only `aria-*` properties supported by that role.
```svelte
<!-- A11y: The attribute 'aria-multiline' is not supported by the role 'link'. -->
<div role="link" aria-multiline></div>
<!-- A11y: The attribute 'aria-required' is not supported by the role 'listitem'. This role is implicit on the element <li>. -->
<li aria-required></li>
```
## a11y_role_supports_aria_props_implicit ## a11y_role_supports_aria_props_implicit
> The attribute '%attribute%' is not supported by the role '%role%'. This role is implicit on the element `<%name%>` > The attribute '%attribute%' is not supported by the role '%role%'. This role is implicit on the element `<%name%>`
Elements with explicit or implicit roles defined contain only `aria-*` properties supported by that role.
```svelte
<!-- A11y: The attribute 'aria-multiline' is not supported by the role 'link'. -->
<div role="link" aria-multiline></div>
<!-- A11y: The attribute 'aria-required' is not supported by the role 'listitem'. This role is implicit on the element <li>. -->
<li aria-required></li>
```
## a11y_unknown_aria_attribute ## a11y_unknown_aria_attribute
> Unknown aria attribute 'aria-%attribute%' > Unknown aria attribute 'aria-%attribute%'
> Unknown aria attribute 'aria-%attribute%'. Did you mean '%suggestion%'? > Unknown aria attribute 'aria-%attribute%'. Did you mean '%suggestion%'?
Enforce that only known ARIA attributes are used. This is based on the [WAI-ARIA States and Properties spec](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties).
```svelte
<!-- A11y: Unknown aria attribute 'aria-labeledby' (did you mean 'labelledby'?) -->
<input type="image" aria-labeledby="foo" />
```
## a11y_unknown_role ## a11y_unknown_role
> Unknown role '%role%' > Unknown role '%role%'
> Unknown role '%role%'. Did you mean '%suggestion%'? > Unknown role '%role%'. Did you mean '%suggestion%'?
Elements with ARIA roles must use a valid, non-abstract ARIA role. A reference to role definitions can be found at [WAI-ARIA](https://www.w3.org/TR/wai-aria/#role_definitions) site.
<!-- prettier-ignore -->
```svelte
<!-- A11y: Unknown role 'toooltip' (did you mean 'tooltip'?) -->
<div role="toooltip"></div>
```

@ -8,6 +8,10 @@ import * as esrap from 'esrap';
const messages = {}; const messages = {};
const seen = new Set(); const seen = new Set();
const DIR = '../../documentation/docs/98-reference/.generated';
fs.rmSync(DIR, { force: true, recursive: true });
fs.mkdirSync(DIR);
for (const category of fs.readdirSync('messages')) { for (const category of fs.readdirSync('messages')) {
if (category.startsWith('.')) continue; if (category.startsWith('.')) continue;
@ -32,9 +36,10 @@ for (const category of fs.readdirSync('messages')) {
sorted.push({ code, _ }); sorted.push({ code, _ });
const sections = text.trim().split('\n\n'); const sections = text.trim().split('\n\n');
let details = null; const details = [];
while (!sections[sections.length - 1].startsWith('> ')) { while (!sections[sections.length - 1].startsWith('> ')) {
details = /** @type {string} */ (sections.pop()); details.unshift(/** @type {string} */ (sections.pop()));
} }
if (sections.length === 0) { if (sections.length === 0) {
@ -44,7 +49,7 @@ for (const category of fs.readdirSync('messages')) {
seen.add(code); seen.add(code);
messages[category][code] = { messages[category][code] = {
messages: sections.map((section) => section.replace(/^> /gm, '').replace(/^>\n/gm, '\n')), messages: sections.map((section) => section.replace(/^> /gm, '').replace(/^>\n/gm, '\n')),
details details: details.join('\n\n')
}; };
} }
@ -54,6 +59,22 @@ for (const category of fs.readdirSync('messages')) {
sorted.map((x) => x._.trim()).join('\n\n') + '\n' sorted.map((x) => x._.trim()).join('\n\n') + '\n'
); );
} }
fs.writeFileSync(
`${DIR}/${category}.md`,
Object.entries(messages[category])
.map(([code, { messages, details }]) => {
const chunks = [`### ${code}`, ...messages.map((message) => '```\n' + message + '\n```')];
if (details) {
chunks.push(details);
}
return chunks.join('\n\n');
})
.sort()
.join('\n\n') + '\n'
);
} }
/** /**

Loading…
Cancel
Save