warn on quoted single-expression-attributes

pull/12479/head
Simon Holthausen 2 years ago
parent 9813526ba4
commit 5fc47f93d4

@ -14,6 +14,10 @@
> '%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

@ -541,7 +541,7 @@ function read_attribute(parser) {
}
};
return create_attribute(name, start, parser.index, [expression]);
return create_attribute(name, start, parser.index, expression);
}
}

@ -34,8 +34,23 @@ import { Scope, get_rune } from '../scope.js';
import { merge } from '../visitors.js';
import { a11y_validators } from './a11y.js';
/** @param {import('#compiler').Attribute} attribute */
function validate_attribute(attribute) {
/**
* @param {import('#compiler').Attribute} attribute
* @param {import('#compiler').ElementLike} parent
*/
function validate_attribute(attribute, parent) {
if (
Array.isArray(attribute.value) &&
attribute.value.length === 1 &&
attribute.value[0].type === 'ExpressionTag' &&
(parent.type === 'Component' ||
parent.type === 'SvelteComponent' ||
parent.type === 'SvelteSelf' ||
(parent.type === 'RegularElement' && is_custom_element_node(parent)))
) {
w.attribute_quoted(attribute);
}
if (attribute.value === true || !Array.isArray(attribute.value) || attribute.value.length === 1) {
return;
}
@ -72,7 +87,7 @@ function validate_component(node, context) {
if (attribute.type === 'Attribute') {
if (context.state.analysis.runes) {
validate_attribute(attribute);
validate_attribute(attribute, node);
if (is_expression_attribute(attribute)) {
const expression = get_attribute_expression(attribute);
@ -125,7 +140,7 @@ function validate_element(node, context) {
const is_expression = is_expression_attribute(attribute);
if (context.state.analysis.runes) {
validate_attribute(attribute);
validate_attribute(attribute, node);
if (is_expression) {
const expression = get_attribute_expression(attribute);

@ -108,6 +108,7 @@ export const codes = [
"attribute_global_event_reference",
"attribute_illegal_colon",
"attribute_invalid_property_name",
"attribute_quoted",
"bind_invalid_each_rest",
"block_empty",
"component_name_lowercase",
@ -686,6 +687,14 @@ export function attribute_invalid_property_name(node, wrong, right) {
w(node, "attribute_invalid_property_name", `'${wrong}' is not a valid HTML attribute. Did you mean '${right}'?`);
}
/**
* 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.
* @param {null | NodeLike} node
*/
export function attribute_quoted(node) {
w(node, "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.");
}
/**
* The rest operator (...) will create a new object and binding '%name%' with the original object will not work
* @param {null | NodeLike} node

@ -0,0 +1,21 @@
<svelte:options runes />
<!-- don't warn on these -->
<!-- prettier-ignore -->
<p class="{foo}"></p>
<!-- prettier-ignore -->
<svelte:element this={foo} class="{foo}"></svelte:element>
<!-- warn on these -->
<!-- prettier-ignore -->
<Component class="{foo}" />
<!-- prettier-ignore -->
<svelte:component this={foo} class="{foo}" />
<!-- prettier-ignore -->
{#if foo}
<svelte:self class="{foo}" />
{/if}
<!-- prettier-ignore -->
<custom-element class="{foo}"></custom-element>

@ -0,0 +1,50 @@
[
{
"code": "attribute_quoted",
"message": "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.",
"start": {
"column": 11,
"line": 13
},
"end": {
"column": 24,
"line": 13
}
},
{
"code": "attribute_quoted",
"message": "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.",
"start": {
"column": 29,
"line": 15
},
"end": {
"column": 42,
"line": 15
}
},
{
"code": "attribute_quoted",
"message": "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.",
"start": {
"column": 14,
"line": 18
},
"end": {
"column": 27,
"line": 18
}
},
{
"code": "attribute_quoted",
"message": "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.",
"start": {
"column": 16,
"line": 21
},
"end": {
"column": 29,
"line": 21
}
}
]

@ -1153,6 +1153,16 @@ declare module 'svelte/compiler' {
outro: boolean;
}
/** A `style:` directive */
interface LegacyStyleDirective extends BaseNode_1 {
type: 'StyleDirective';
/** The 'x' in `style:x` */
name: string;
/** The 'y' in `style:x={y}` */
value: true | Array<ExpressionTag | Text>;
modifiers: Array<'important'>;
}
interface LegacyWindow extends BaseElement_1 {
type: 'Window';
}
@ -1171,7 +1181,7 @@ declare module 'svelte/compiler' {
| LegacyClass
| LegacyLet
| LegacyEventHandler
| StyleDirective
| LegacyStyleDirective
| LegacyTransition
| LegacyAction;
@ -1634,7 +1644,7 @@ declare module 'svelte/compiler' {
/** The 'x' in `style:x` */
name: string;
/** The 'y' in `style:x={y}` */
value: true | Array<ExpressionTag | Text>;
value: true | ExpressionTag | Array<ExpressionTag | Text>;
modifiers: Array<'important'>;
metadata: {
dynamic: boolean;
@ -1855,7 +1865,7 @@ declare module 'svelte/compiler' {
interface Attribute extends BaseNode {
type: 'Attribute';
name: string;
value: true | Array<Text | ExpressionTag>;
value: true | ExpressionTag | Array<Text | ExpressionTag>;
metadata: {
dynamic: boolean;
/** May be set if this is an event attribute */

Loading…
Cancel
Save