mirror of https://github.com/sveltejs/svelte
commit
f4598e5463
@ -0,0 +1,65 @@
|
||||
---
|
||||
title: What's new in Svelte: July 2021
|
||||
description: Keeping cool with fixes, TypeScript tooling and tonnes of new features
|
||||
author: Daniel Sandoval
|
||||
authorURL: https://desandoval.net
|
||||
---
|
||||
|
||||
As the northern hemisphere heats up, Svelte has stayed cool with lots of performance and bug fixes, better TypeScript support, and lots of new components & tools from around the ecosystem. Let's take a peek 👀
|
||||
|
||||
## New in SvelteKit
|
||||
- `adapter-node` now precompresses assets using gzip & brotli ([#1693](https://github.com/sveltejs/kit/pull/1693))
|
||||
- Support for TypeScript transpilation has been added to the `svelte-kit package` tooling ([#1633](https://github.com/sveltejs/kit/pull/1633))
|
||||
- Improved caching defaults in `adapter-node` ([#1416](https://github.com/sveltejs/kit/pull/1416))
|
||||
- Allow configuring Rollup output options ([#1572](https://github.com/sveltejs/kit/pull/1572))
|
||||
- Fixed usage of SSL with HMR ([#1517](https://github.com/sveltejs/kit/pull/1517))
|
||||
|
||||
|
||||
|
||||
## Features & bug fixes from around svelte/*
|
||||
- [Svelte 3.38.3](https://github.com/sveltejs/svelte/blob/master/CHANGELOG.md#3383) (released June 22) includes a bunch of performance and bug fixes - including hydration optimizations, `this` preservation in bubbled events, and more!
|
||||
- The latest language tools releases added support for prop renaming from outside of a component, PostCSS syntax grammar, and a `.d.ts` output target in `svelte2tsx` which can be used to create type definitions from Svelte files.
|
||||
- Also in language tools, some long-awaited experimental features for enhanced TypeScript support were added - including explicitly typing all possible component events or slots, and using generics. Have a look at [the RFC](https://github.com/sveltejs/rfcs/pull/38) for more details and leave feedback in [this issue](https://github.com/sveltejs/language-tools/issues/442) if you are using it.
|
||||
- `svelte-scroller` got some quality-of-life fixes in 2.0.7 - fixing an initial width bug and updating its `index` more conservatively
|
||||
|
||||
|
||||
## Coming soon to Svelte
|
||||
- Constants in markup ([RFC](https://github.com/sveltejs/rfcs/blob/master/text/0000-markup-constants.md)): Adds a new `{@const ...}` tag that defines a local constant ([PR](https://github.com/sveltejs/svelte/pull/6413))
|
||||
|
||||
---
|
||||
|
||||
## Community Showcase
|
||||
|
||||
**Apps & Sites**
|
||||
- [SvelteThemes](https://sveltethemes.dev/) is a curated list of Svelte themes and templates built using svelte, sveltekit, elderjs, routify etc.
|
||||
- [Beatbump](https://github.com/snuffyDev/Beatbump) is an alternative frontend for YouTube Music created using Svelte/SvelteKit.
|
||||
- [Sveltuir](https://github.com/webspaceadam/sveltuir) is an app help you memorize the guitar fretboard
|
||||
|
||||
|
||||
**Educational Content**
|
||||
- [Svelte Radio: A Jolly Good Svelte Summer](https://share.transistor.fm/s/60880542) is a conversation about what's new in Svelte and a celebration of Svelte Radio's 1-year anniversary
|
||||
- [Class properties in Svelte](https://navillus.dev/blog/svelte-class-props) is a refresher on the power of `class` for developers switching over to Svelte from React
|
||||
- [Sveltekit Tutorial for Beginners](https://www.youtube.com/playlist?list=PLm_Qt4aKpfKjf77S8UD79Ockhwp_699Ms) is a video playlist for learning SvelteKit by WebJeda
|
||||
- [How To Cache Dynamic Pages On Demand With A Service Worker In SvelteKit](https://jochemvogel.medium.com/how-to-cache-dynamic-pages-on-demand-with-a-service-worker-in-sveltekit-4b4a7652583d) walks through the power of service workers when used within SvelteKit for on-demand caching
|
||||
- [Vue vs Svelte: Comparing Framework Internals](https://www.vuemastery.com/blog/vue-vs-svelte-comparing-framework-internals/) dives deep into the differences between Vue and Svelte from the inside out
|
||||
- [Setting up a development environment for SvelteKit with Docker and Docker Compose](https://jenyus.web.app/blog/2021-05-30-setting-up-a-development-environment-for-sveltekit-with-docker-and-compose) walks through how to use Docker to create reusable development environments, no matter what kind of device you run your code on
|
||||
- Scalable Scripts released three videos this month documenting how to deploy dockerized Svelte Apps to [AWS](https://youtu.be/VOs2Od5jYOc), [Azure](https://youtu.be/gdg4ne_uDm8) and [Google Cloud](https://youtu.be/_-uBb61Tikw)
|
||||
- [Render Katex with Svelte from zero to hero](https://www.youtube.com/watch?v=euowJs9CblA) demonstrates how to implement Katex in a Svelte project
|
||||
- [Using Custom Elements in Svelte](https://css-tricks.com/using-custom-elements-in-svelte/) shows some of the quirks to look out for when using custom elements in a Svelte site
|
||||
|
||||
|
||||
**Libraries, Tools & Components**
|
||||
- [svelte-pipeline](https://github.com/novacbn/svelte-pipeline) provides custom Javascript contexts and the Svelte Compiler as Svelte Stores, for REPLs, Editors, etc.
|
||||
- [Sveltotron](https://github.com/Salemmous/sveltotron) is an Electron-based app made to inspect your Svelte app
|
||||
- [svelte-qr-reader-writer](https://github.com/pleasemarkdarkly/svelte-qr-reader-writer) is a Svelte component that helps read and write data from QR codes
|
||||
- [svelte-stack-router](https://www.npmjs.com/package/svelte-stack-router) Aims to make Svelte apps feel more native by routing with Stacks
|
||||
- [svelte-typed-context](https://www.npmjs.com/package/svelte-typed-context) provides an interface which, when provided to `getContext` or `setContext`, allows for stricter types
|
||||
- [svelte-modals](https://svelte-modals.mattjennings.io/) is a simple, flexible, zero-dependency modal manager for Svelte
|
||||
|
||||
|
||||
**Want to contribute a component? Interested in helping make Svelte's presence on the web better?** Submit a Component to the Svelte Society site by making [a PR to this file](https://github.com/svelte-society/sveltesociety-2021/blob/main/src/routes/components/components.json) or check out [the list of open issues](https://github.com/svelte-society/sveltesociety-2021/issues) if you'd like to contribute to the Svelte Society rewrite in SvelteKit.
|
||||
|
||||
|
||||
## See you next month!
|
||||
|
||||
Want more updates? Join us on [Reddit](https://www.reddit.com/r/sveltejs/) or [Discord](https://discord.com/invite/yy75DKs)!
|
||||
@ -0,0 +1,253 @@
|
||||
// All compiler errors should be listed and accessed from here
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export default {
|
||||
invalid_binding_elements: (element: string, binding: string) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' is not a valid binding on <${element}> elements`
|
||||
}),
|
||||
invalid_binding_element_with: (elements: string, binding: string) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' binding can only be used with ${elements}`
|
||||
}),
|
||||
invalid_binding_on: (binding: string, element: string, post?: string) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' is not a valid binding on ${element}` + (post || '')
|
||||
}),
|
||||
invalid_binding_foreign: (binding: string) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' is not a valid binding. Foreign elements only support bind:this`
|
||||
}),
|
||||
invalid_binding_no_checkbox: (binding: string, is_radio: boolean) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' binding can only be used with <input type="checkbox">` + (is_radio ? ' — for <input type="radio">, use \'group\' binding' : '')
|
||||
}),
|
||||
invalid_binding: (binding: string) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `'${binding}' is not a valid binding`
|
||||
}),
|
||||
invalid_binding_window: (parts: string[]) => ({
|
||||
code: 'invalid-binding',
|
||||
message: `Bindings on <svelte:window> must be to top-level properties, e.g. '${parts[parts.length - 1]}' rather than '${parts.join('.')}'`
|
||||
}),
|
||||
invalid_binding_let: {
|
||||
code: 'invalid-binding',
|
||||
message: 'Cannot bind to a variable declared with the let: directive'
|
||||
},
|
||||
invalid_binding_await: {
|
||||
code: 'invalid-binding',
|
||||
message: 'Cannot bind to a variable declared with {#await ... then} or {:catch} blocks'
|
||||
},
|
||||
invalid_binding_writibale: {
|
||||
code: 'invalid-binding',
|
||||
message: 'Cannot bind to a variable which is not writable'
|
||||
},
|
||||
binding_undeclared: (name: string) => ({
|
||||
code: 'binding-undeclared',
|
||||
message: `${name} is not declared`
|
||||
}),
|
||||
invalid_type: {
|
||||
code: 'invalid-type',
|
||||
message: '\'type\' attribute cannot be dynamic if input uses two-way binding'
|
||||
},
|
||||
missing_type: {
|
||||
code: 'missing-type',
|
||||
message: '\'type\' attribute must be specified'
|
||||
},
|
||||
dynamic_multiple_attribute: {
|
||||
code: 'dynamic-multiple-attribute',
|
||||
message: '\'multiple\' attribute cannot be dynamic if select uses two-way binding'
|
||||
},
|
||||
missing_contenteditable_attribute: {
|
||||
code: 'missing-contenteditable-attribute',
|
||||
message: '\'contenteditable\' attribute is required for textContent and innerHTML two-way bindings'
|
||||
},
|
||||
dynamic_contenteditable_attribute: {
|
||||
code: 'dynamic-contenteditable-attribute',
|
||||
message: '\'contenteditable\' attribute cannot be dynamic if element uses two-way binding'
|
||||
},
|
||||
invalid_event_modifier_combination: (modifier1: string, modifier2: string) => ({
|
||||
code: 'invalid-event-modifier',
|
||||
message: `The '${modifier1}' and '${modifier2}' modifiers cannot be used together`
|
||||
}),
|
||||
invalid_event_modifier_legacy: (modifier: string) => ({
|
||||
code: 'invalid-event-modifier',
|
||||
message: `The '${modifier}' modifier cannot be used in legacy mode`
|
||||
}),
|
||||
invalid_event_modifier: (valid: string) => ({
|
||||
code: 'invalid-event-modifier',
|
||||
message: `Valid event modifiers are ${valid}`
|
||||
}),
|
||||
invalid_event_modifier_component: {
|
||||
code: 'invalid-event-modifier',
|
||||
message: "Event modifiers other than 'once' can only be used on DOM elements"
|
||||
},
|
||||
textarea_duplicate_value: {
|
||||
code: 'textarea-duplicate-value',
|
||||
message: 'A <textarea> can have either a value attribute or (equivalently) child content, but not both'
|
||||
},
|
||||
illegal_attribute: (name: string) => ({
|
||||
code: 'illegal-attribute',
|
||||
message: `'${name}' is not a valid attribute name`
|
||||
}),
|
||||
invalid_slot_attribute: {
|
||||
code: 'invalid-slot-attribute',
|
||||
message: 'slot attribute cannot have a dynamic value'
|
||||
},
|
||||
duplicate_slot_attribute: (name: string) => ({
|
||||
code: 'duplicate-slot-attribute',
|
||||
message: `Duplicate '${name}' slot`
|
||||
}),
|
||||
invalid_slotted_content: {
|
||||
code: 'invalid-slotted-content',
|
||||
message: 'Element with a slot=\'...\' attribute must be a child of a component or a descendant of a custom element'
|
||||
},
|
||||
invalid_attribute_head: {
|
||||
code: 'invalid-attribute',
|
||||
message: '<svelte:head> should not have any attributes or directives'
|
||||
},
|
||||
invalid_action: {
|
||||
code: 'invalid-action',
|
||||
message: 'Actions can only be applied to DOM elements, not components'
|
||||
},
|
||||
invalid_class: {
|
||||
code: 'invalid-class',
|
||||
message: 'Classes can only be applied to DOM elements, not components'
|
||||
},
|
||||
invalid_transition: {
|
||||
code: 'invalid-transition',
|
||||
message: 'Transitions can only be applied to DOM elements, not components'
|
||||
},
|
||||
invalid_let: {
|
||||
code: 'invalid-let',
|
||||
message: 'let directive value must be an identifier or an object/array pattern'
|
||||
},
|
||||
invalid_slot_directive: {
|
||||
code: 'invalid-slot-directive',
|
||||
message: '<slot> cannot have directives'
|
||||
},
|
||||
dynamic_slot_name: {
|
||||
code: 'dynamic-slot-name',
|
||||
message: '<slot> name cannot be dynamic'
|
||||
},
|
||||
invalid_slot_name: {
|
||||
code: 'invalid-slot-name',
|
||||
message: 'default is a reserved word — it cannot be used as a slot name'
|
||||
},
|
||||
invalid_slot_attribute_value_missing: {
|
||||
code: 'invalid-slot-attribute',
|
||||
message: 'slot attribute value is missing'
|
||||
},
|
||||
invalid_slotted_content_fragment: {
|
||||
code: 'invalid-slotted-content',
|
||||
message: '<svelte:fragment> must be a child of a component'
|
||||
},
|
||||
illegal_attribute_title: {
|
||||
code: 'illegal-attribute',
|
||||
message: '<title> cannot have attributes'
|
||||
},
|
||||
illegal_structure_title: {
|
||||
code: 'illegal-structure',
|
||||
message: '<title> can only contain text and {tags}'
|
||||
},
|
||||
duplicate_transition: (directive: string, parent_directive: string) => {
|
||||
function describe(_directive: string) {
|
||||
return _directive === 'transition'
|
||||
? "a 'transition'"
|
||||
: `an '${_directive}'`;
|
||||
}
|
||||
const message = directive === parent_directive
|
||||
? `An element can only have one '${directive}' directive`
|
||||
: `An element cannot have both ${describe(parent_directive)} directive and ${describe(directive)} directive`;
|
||||
return {
|
||||
code: 'duplicate-transition',
|
||||
message
|
||||
};
|
||||
},
|
||||
contextual_store: {
|
||||
code: 'contextual-store',
|
||||
message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
|
||||
},
|
||||
default_export: {
|
||||
code: 'default-export',
|
||||
message: 'A component cannot have a default export'
|
||||
},
|
||||
not_implemented: {
|
||||
code: 'not-implemented',
|
||||
message: 'A component currently cannot have an export ... from'
|
||||
},
|
||||
illegal_declaration: {
|
||||
code: 'illegal-declaration',
|
||||
message: 'The $ prefix is reserved, and cannot be used for variable and import names'
|
||||
},
|
||||
illegal_subscription: {
|
||||
code: 'illegal-subscription',
|
||||
message: 'Cannot reference store value inside <script context="module">'
|
||||
},
|
||||
illegal_global: (name: string) => ({
|
||||
code: 'illegal-global',
|
||||
message: `${name} is an illegal variable name`
|
||||
}),
|
||||
destructured_prop: {
|
||||
code: 'destructured-prop',
|
||||
message: 'Cannot declare props in destructured declaration'
|
||||
},
|
||||
cyclical_reactive_declaration: (cycle: string[]) => ({
|
||||
code: 'cyclical-reactive-declaration',
|
||||
message: `Cyclical dependency detected: ${cycle.join(' → ')}`
|
||||
}),
|
||||
invalid_tag_property: {
|
||||
code: 'invalid-tag-property',
|
||||
message: "tag name must be two or more words joined by the '-' character"
|
||||
},
|
||||
invalid_tag_attribute: {
|
||||
code: 'invalid-tag-attribute',
|
||||
message: "'tag' must be a string literal"
|
||||
},
|
||||
invalid_namespace_property: (namespace: string, suggestion?: string) => ({
|
||||
code: 'invalid-namespace-property',
|
||||
message: `Invalid namespace '${namespace}'` + (suggestion ? ` (did you mean '${suggestion}'?)` : '')
|
||||
}),
|
||||
invalid_namespace_attribute: {
|
||||
code: 'invalid-namespace-attribute',
|
||||
message: "The 'namespace' attribute must be a string literal representing a valid namespace"
|
||||
},
|
||||
invalid_attribute_value: (name: string) => ({
|
||||
code: `invalid-${name}-value`,
|
||||
message: `${name} attribute must be true or false`
|
||||
}),
|
||||
invalid_options_attribute_unknown: {
|
||||
code: 'invalid-options-attribute',
|
||||
message: '<svelte:options> unknown attribute'
|
||||
},
|
||||
invalid_options_attribute: {
|
||||
code: 'invalid-options-attribute',
|
||||
message: "<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes"
|
||||
},
|
||||
css_invalid_global: {
|
||||
code: 'css-invalid-global',
|
||||
message: ':global(...) can be at the start or end of a selector sequence, but not in the middle'
|
||||
},
|
||||
css_invalid_global_selector: {
|
||||
code: 'css-invalid-global-selector',
|
||||
message: ':global(...) must contain a single selector'
|
||||
},
|
||||
duplicate_animation: {
|
||||
code: 'duplicate-animation',
|
||||
message: "An element can only have one 'animate' directive"
|
||||
},
|
||||
invalid_animation_immediate: {
|
||||
code: 'invalid-animation',
|
||||
message: 'An element that uses the animate directive must be the immediate child of a keyed each block'
|
||||
},
|
||||
invalid_animation_sole: {
|
||||
code: 'invalid-animation',
|
||||
message: 'An element that uses the animate directive must be the sole child of a keyed each block'
|
||||
},
|
||||
invalid_directive_value: {
|
||||
code: 'invalid-directive-value',
|
||||
message: 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,143 @@
|
||||
// All compiler warnings should be listed and accessed from here
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export default {
|
||||
custom_element_no_tag: {
|
||||
code: 'custom-element-no-tag',
|
||||
message: 'No custom element \'tag\' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>'
|
||||
},
|
||||
unused_export_let: (component: string, property: string) => ({
|
||||
code: 'unused-export-let',
|
||||
message: `${component} has unused export property '${property}'. If it is for external reference only, please consider using \`export const ${property}\``
|
||||
}),
|
||||
module_script_reactive_declaration: {
|
||||
code: 'module-script-reactive-declaration',
|
||||
message: '$: has no effect in a module script'
|
||||
},
|
||||
non_top_level_reactive_declaration: {
|
||||
code: 'non-top-level-reactive-declaration',
|
||||
message: '$: has no effect outside of the top-level'
|
||||
},
|
||||
module_script_variable_reactive_declaration: (name: string) => ({
|
||||
code: 'module-script-reactive-declaration',
|
||||
message: `"${name}" is declared in a module script and will not be reactive`
|
||||
}),
|
||||
missing_declaration: (name: string, has_script: boolean) => ({
|
||||
code: 'missing-declaration',
|
||||
message: `'${name}' is not defined` + (has_script ? '' : `. Consider adding a <script> block with 'export let ${name}' to declare a prop`)
|
||||
}),
|
||||
missing_custom_element_compile_options: {
|
||||
code: 'missing-custom-element-compile-options',
|
||||
message: "The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
|
||||
},
|
||||
css_unused_selector: (selector: string) => ({
|
||||
code: 'css-unused-selector',
|
||||
message: `Unused CSS selector "${selector}"`
|
||||
}),
|
||||
empty_block: {
|
||||
code: 'empty-block',
|
||||
message: 'Empty block'
|
||||
},
|
||||
reactive_component: (name: string) => ({
|
||||
code: 'reactive-component',
|
||||
message: `<${name}/> will not be reactive if ${name} changes. Use <svelte:component this={${name}}/> if you want this reactivity.`
|
||||
}),
|
||||
component_name_lowercase: (name: string) => ({
|
||||
code: 'component-name-lowercase',
|
||||
message: `<${name}> will be treated as an HTML element unless it begins with a capital letter`
|
||||
}),
|
||||
avoid_is: {
|
||||
code: 'avoid-is',
|
||||
message: 'The \'is\' attribute is not supported cross-browser and should be avoided'
|
||||
},
|
||||
invalid_html_attribute: (name: string, suggestion: string) => ({
|
||||
code: 'invalid-html-attribute',
|
||||
message: `'${name}' is not a valid HTML attribute. Did you mean '${suggestion}'?`
|
||||
}),
|
||||
a11y_aria_attributes: (name: string) => ({
|
||||
code: 'a11y-aria-attributes',
|
||||
message: `A11y: <${name}> should not have aria-* attributes`
|
||||
}),
|
||||
a11y_unknown_aria_attribute: (attribute: string, suggestion?: string) => ({
|
||||
code: 'a11y-unknown-aria-attribute',
|
||||
message: `A11y: Unknown aria attribute 'aria-${attribute}'` + (suggestion ? ` (did you mean '${suggestion}'?)` : '')
|
||||
}),
|
||||
a11y_hidden: (name: string) => ({
|
||||
code: 'a11y-hidden',
|
||||
message: `A11y: <${name}> element should not be hidden`
|
||||
}),
|
||||
a11y_misplaced_role: (name: string) => ({
|
||||
code: 'a11y-misplaced-role',
|
||||
message: `A11y: <${name}> should not have role attribute`
|
||||
}),
|
||||
a11y_unknown_role: (role: string | boolean, suggestion?: string) => ({
|
||||
code: 'a11y-unknown-role',
|
||||
message: `A11y: Unknown role '${role}'` + (suggestion ? ` (did you mean '${suggestion}'?)` : '')
|
||||
}),
|
||||
a11y_accesskey: {
|
||||
code: 'a11y-accesskey',
|
||||
message: 'A11y: Avoid using accesskey'
|
||||
},
|
||||
a11y_autofocus: {
|
||||
code: 'a11y-autofocus',
|
||||
message: 'A11y: Avoid using autofocus'
|
||||
},
|
||||
a11y_misplaced_scope: {
|
||||
code: 'a11y-misplaced-scope',
|
||||
message: 'A11y: The scope attribute should only be used with <th> elements'
|
||||
},
|
||||
a11y_positive_tabindex: {
|
||||
code: 'a11y-positive-tabindex',
|
||||
message: 'A11y: avoid tabindex values above zero'
|
||||
},
|
||||
a11y_invalid_attribute: (href_attribute: string, href_value: string) => ({
|
||||
code: 'a11y-invalid-attribute',
|
||||
message: `A11y: '${href_value}' is not a valid ${href_attribute} attribute`
|
||||
}),
|
||||
a11y_missing_attribute: (name: string, article: string, sequence: string) => ({
|
||||
code: 'a11y-missing-attribute',
|
||||
message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
|
||||
}),
|
||||
a11y_img_redundant_alt: {
|
||||
code: 'a11y-img-redundant-alt',
|
||||
message: 'A11y: Screenreaders already announce <img> elements as an image.'
|
||||
},
|
||||
a11y_label_has_associated_control: {
|
||||
code: 'a11y-label-has-associated-control',
|
||||
message: 'A11y: A form label must be associated with a control.'
|
||||
},
|
||||
a11y_media_has_caption: {
|
||||
code: 'a11y-media-has-caption',
|
||||
message: 'A11y: <video> elements must have a <track kind="captions">'
|
||||
},
|
||||
a11y_distracting_elements: (name: string) => ({
|
||||
code: 'a11y-distracting-elements',
|
||||
message: `A11y: Avoid <${name}> elements`
|
||||
}),
|
||||
a11y_structure_immediate: {
|
||||
code: 'a11y-structure',
|
||||
message: 'A11y: <figcaption> must be an immediate child of <figure>'
|
||||
},
|
||||
a11y_structure_first_or_last: {
|
||||
code: 'a11y-structure',
|
||||
message: 'A11y: <figcaption> must be first or last child of <figure>'
|
||||
},
|
||||
a11y_mouse_events_have_key_events: (event: string, accompanied_by: string) => ({
|
||||
code: 'a11y-mouse-events-have-key-events',
|
||||
message: `A11y: on:${event} must be accompanied by on:${accompanied_by}`
|
||||
}),
|
||||
a11y_missing_content: (name: string) => ({
|
||||
code: 'a11y-missing-content',
|
||||
message: `A11y: <${name}> element should have child content`
|
||||
}),
|
||||
redundant_event_modifier_for_touch: {
|
||||
code: 'redundant-event-modifier',
|
||||
message: 'Touch event handlers that don\'t use the \'event\' object are passive by default'
|
||||
},
|
||||
redundant_event_modifier_passive: {
|
||||
code: 'redundant-event-modifier',
|
||||
message: 'The passive modifier only works with wheel and touch events'
|
||||
}
|
||||
};
|
||||
@ -1,4 +1,4 @@
|
||||
<video><track kind="captions"/></video>
|
||||
<video></video>
|
||||
<video><track /></video>
|
||||
<audio muted></audio>
|
||||
<audio></audio>
|
||||
|
||||
Loading…
Reference in new issue