diff --git a/packages/svelte/messages/compile-errors/slots.md b/packages/svelte/messages/compile-errors/slots.md index 17ad8c0636..51213c5b5d 100644 --- a/packages/svelte/messages/compile-errors/slots.md +++ b/packages/svelte/messages/compile-errors/slots.md @@ -1,15 +1,18 @@ ## invalid_slot_element_attribute - can only receive attributes and (optionally) let directives +`` can only receive attributes and (optionally) let directives ## invalid_slot_attribute slot attribute must be a static value +## invalid_slot_name_default + +`default` is a reserved word — it cannot be used as a slot name + ## invalid_slot_name -default is a reserved word — it cannot be used as a slot name` - : `slot attribute must be a static value +slot attribute must be a static value ## invalid_slot_placement @@ -25,4 +28,4 @@ Found default slot content alongside an explicit slot="default" ## conflicting_children_snippet -Cannot use explicit children snippet at the same time as implicit children content. Remove either the non-whitespace content or the children snippet block \ No newline at end of file +Cannot use explicit children snippet at the same time as implicit children content. Remove either the non-whitespace content or the children snippet block diff --git a/packages/svelte/src/compiler/errors-tmp.js b/packages/svelte/src/compiler/errors-tmp.js index 00f16c3be5..d8a3c3f0fc 100644 --- a/packages/svelte/src/compiler/errors-tmp.js +++ b/packages/svelte/src/compiler/errors-tmp.js @@ -20,76 +20,6 @@ const internal = { `Internal compiler error: ${message}. Please report this to https://github.com/sveltejs/svelte/issues` }; -/** @satisfies {Errors} */ -const attributes = { - 'empty-attribute-shorthand': () => `Attribute shorthand cannot be empty`, - 'duplicate-attribute': () => `Attributes need to be unique`, - 'invalid-event-attribute-value': () => - `Event attribute must be a JavaScript expression, not a string`, - /** @param {string} name */ - 'invalid-attribute-name': (name) => `'${name}' is not a valid attribute name`, - /** @param {'no-each' | 'each-key' | 'child'} type */ - 'invalid-animation': (type) => - type === 'no-each' - ? `An element that uses the animate directive must be the immediate child of a keyed each block` - : type === 'each-key' - ? `An element that uses the animate directive must be used inside a keyed each block. Did you forget to add a key to your each block?` - : `An element that uses the animate directive must be the sole child of a keyed each block`, - 'duplicate-animation': () => `An element can only have one 'animate' directive`, - /** @param {string[] | undefined} [modifiers] */ - 'invalid-event-modifier': (modifiers) => - modifiers - ? `Valid event modifiers are ${modifiers.slice(0, -1).join(', ')} or ${modifiers.slice(-1)}` - : `Event modifiers other than 'once' can only be used on DOM elements`, - /** - * @param {string} modifier1 - * @param {string} modifier2 - */ - 'invalid-event-modifier-combination': (modifier1, modifier2) => - `The '${modifier1}' and '${modifier2}' modifiers cannot be used together`, - /** - * @param {string} directive1 - * @param {string} directive2 - */ - 'duplicate-transition': (directive1, directive2) => { - /** @param {string} _directive */ - function describe(_directive) { - return _directive === 'transition' ? "a 'transition'" : `an '${_directive}'`; - } - - return directive1 === directive2 - ? `An element can only have one '${directive1}' directive` - : `An element cannot have both ${describe(directive1)} directive and ${describe( - directive2 - )} directive`; - }, - 'invalid-let-directive-placement': () => 'let directive at invalid position', - 'invalid-style-directive-modifier': () => - `Invalid 'style:' modifier. Valid modifiers are: 'important'`, - 'invalid-sequence-expression': () => - `Sequence expressions are not allowed as attribute/directive values in runes mode, unless wrapped in parentheses` -}; - -/** @satisfies {Errors} */ -const slots = { - 'invalid-slot-element-attribute': () => - ` can only receive attributes and (optionally) let directives`, - 'invalid-slot-attribute': () => `slot attribute must be a static value`, - /** @param {boolean} is_default */ - 'invalid-slot-name': (is_default) => - is_default - ? `default is a reserved word — it cannot be used as a slot name` - : `slot attribute must be a static value`, - 'invalid-slot-placement': () => - `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`, - /** @param {string} name @param {string} component */ - 'duplicate-slot-name': (name, component) => `Duplicate slot name '${name}' in <${component}>`, - 'invalid-default-slot-content': () => - `Found default slot content alongside an explicit slot="default"`, - 'conflicting-children-snippet': () => - `Cannot use explicit children snippet at the same time as implicit children content. Remove either the non-whitespace content or the children snippet block` -}; - /** @satisfies {Errors} */ const bindings = { 'invalid-binding-expression': () => `Can only bind to an Identifier or MemberExpression`, @@ -149,7 +79,6 @@ const const_tag = { /** @satisfies {Errors} */ const errors = { ...internal, - ...slots, ...bindings, ...variables, ...compiler_options, diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index eb66c3fc9c..27ea175e59 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -1052,7 +1052,7 @@ export function conflicting_property_name(node) { * @returns {never} */ export function invalid_slot_element_attribute(node) { - e(node, "invalid_slot_element_attribute", " can only receive attributes and (optionally) let directives"); + e(node, "invalid_slot_element_attribute", "`` can only receive attributes and (optionally) let directives"); } /** @@ -1064,13 +1064,22 @@ export function invalid_slot_attribute(node) { e(node, "invalid_slot_attribute", "slot attribute must be a static value"); } +/** + * @param {number | NodeLike} node + + * @returns {never} + */ +export function invalid_slot_name_default(node) { + e(node, "invalid_slot_name_default", "`default` is a reserved word — it cannot be used as a slot name"); +} + /** * @param {number | NodeLike} node * @returns {never} */ export function invalid_slot_name(node) { - e(node, "invalid_slot_name", "default is a reserved word — it cannot be used as a slot name`\n\t\t\t: `slot attribute must be a static value"); + e(node, "invalid_slot_name", "slot attribute must be a static value"); } /** diff --git a/packages/svelte/src/compiler/phases/2-analyze/validation.js b/packages/svelte/src/compiler/phases/2-analyze/validation.js index 2eaaf7b262..d71a727e47 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/validation.js +++ b/packages/svelte/src/compiler/phases/2-analyze/validation.js @@ -261,7 +261,7 @@ function validate_slot_attribute(context, attribute) { if (owner) { if (!is_text_attribute(attribute)) { - error(attribute, 'invalid-slot-attribute'); + e.invalid_slot_attribute(attribute); } if ( @@ -270,13 +270,13 @@ function validate_slot_attribute(context, attribute) { owner.type === 'SvelteSelf' ) { if (owner !== context.path.at(-2)) { - error(attribute, 'invalid-slot-placement'); + e.invalid_slot_placement(attribute); } const name = attribute.value[0].data; if (context.state.component_slots.has(name)) { - error(attribute, 'duplicate-slot-name', name, owner.name); + e.duplicate_slot_name(attribute, name, owner.name); } context.state.component_slots.add(name); @@ -293,12 +293,12 @@ function validate_slot_attribute(context, attribute) { } } - error(node, 'invalid-default-slot-content'); + e.invalid_default_slot_content(node); } } } } else { - error(attribute, 'invalid-slot-placement'); + e.invalid_slot_placement(attribute); } } @@ -668,7 +668,7 @@ const validation = { (node) => node.type !== 'SnippetBlock' && (node.type !== 'Text' || node.data.trim()) ) ) { - error(node, 'conflicting-children-snippet'); + e.conflicting_children_snippet(node); } } }, @@ -711,15 +711,15 @@ const validation = { if (attribute.type === 'Attribute') { if (attribute.name === 'name') { if (!is_text_attribute(attribute)) { - error(attribute, 'invalid-slot-name', false); + e.invalid_slot_name(attribute); } const slot_name = attribute.value[0].data; if (slot_name === 'default') { - error(attribute, 'invalid-slot-name', true); + e.invalid_slot_name_default(attribute); } } } else if (attribute.type !== 'SpreadAttribute' && attribute.type !== 'LetDirective') { - error(attribute, 'invalid-slot-element-attribute'); + e.invalid_slot_element_attribute(attribute); } } },