@@ -132,9 +132,12 @@ const special_elements = {
132132 'invalid-customElement-shadow-attribute' : ( ) => '"shadow" must be either "open" or "none"' ,
133133 'unknown-svelte-option-attribute' : /** @param {string } name */ ( name ) =>
134134 `<svelte:options> unknown attribute '${ name } '` ,
135+ 'illegal-svelte-head-attribute' : ( ) => '<svelte:head> cannot have attributes nor directives' ,
135136 'invalid-svelte-fragment-attribute' : ( ) =>
136137 `<svelte:fragment> can only have a slot attribute and (optionally) a let: directive` ,
137138 'invalid-svelte-fragment-slot' : ( ) => `<svelte:fragment> slot attribute must have a static value` ,
139+ 'invalid-svelte-fragment-placement' : ( ) =>
140+ `<svelte:fragment> must be the direct child of a component` ,
138141 /** @param {string } name */
139142 'invalid-svelte-element-placement' : ( name ) =>
140143 `<${ name } > tags cannot be inside elements or blocks` ,
@@ -211,31 +214,75 @@ const elements = {
211214 * @param {string } node
212215 * @param {string } parent
213216 */
214- 'invalid-node-placement' : ( node , parent ) => `${ node } is invalid inside <${ parent } >`
217+ 'invalid-node-placement' : ( node , parent ) => `${ node } is invalid inside <${ parent } >` ,
218+ 'illegal-title-attribute' : ( ) => '<title> cannot have attributes nor directives' ,
219+ 'invalid-title-content' : ( ) => '<title> can only contain text and {tags}'
215220} ;
216221
217222/** @satisfies {Errors } */
218223const components = {
219- 'invalid-component-directive' : ( ) => `Directive is not valid on components`
224+ 'invalid-component-directive' : ( ) => `This type of directive is not valid on components`
220225} ;
221226
222227/** @satisfies {Errors } */
223228const attributes = {
224229 'empty-attribute-shorthand' : ( ) => `Attribute shorthand cannot be empty` ,
225230 'duplicate-attribute' : ( ) => `Attributes need to be unique` ,
226231 'invalid-event-attribute-value' : ( ) =>
227- `Event attribute must be a JavaScript expression, not a string`
232+ `Event attribute must be a JavaScript expression, not a string` ,
233+ /** @param {string } name */
234+ 'invalid-attribute-name' : ( name ) => `'${ name } ' is not a valid attribute name` ,
235+ /** @param {'no-each' | 'each-key' | 'child' } type */
236+ 'invalid-animation' : ( type ) =>
237+ type === 'no-each'
238+ ? `An element that uses the animate directive must be the immediate child of a keyed each block`
239+ : type === 'each-key'
240+ ? `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?`
241+ : `An element that uses the animate directive must be the sole child of a keyed each block` ,
242+ 'duplicate-animation' : ( ) => `An element can only have one 'animate' directive` ,
243+ /** @param {string[] | undefined } [modifiers] */
244+ 'invalid-event-modifier' : ( modifiers ) =>
245+ modifiers
246+ ? `Valid event modifiers are ${ modifiers . slice ( 0 , - 1 ) . join ( ', ' ) } or ${ modifiers . slice ( - 1 ) } `
247+ : `Event modifiers other than 'once' can only be used on DOM elements` ,
248+ /**
249+ * @param {string } modifier1
250+ * @param {string } modifier2
251+ */
252+ 'invalid-event-modifier-combination' : ( modifier1 , modifier2 ) =>
253+ `The '${ modifier1 } ' and '${ modifier2 } ' modifiers cannot be used together` ,
254+ /**
255+ * @param {string } directive1
256+ * @param {string } directive2
257+ */
258+ 'duplicate-transition' : ( directive1 , directive2 ) => {
259+ /** @param {string } _directive */
260+ function describe ( _directive ) {
261+ return _directive === 'transition' ? "a 'transition'" : `an '${ _directive } '` ;
262+ }
263+
264+ return directive1 === directive2
265+ ? `An element can only have one '${ directive1 } ' directive`
266+ : `An element cannot have both ${ describe ( directive1 ) } directive and ${ describe (
267+ directive2
268+ ) } directive`;
269+ } ,
270+ 'invalid-let-directive-placement' : ( ) => 'let directive at invalid position'
228271} ;
229272
230273/** @satisfies {Errors } */
231274const slots = {
232275 'invalid-slot-element-attribute' : ( ) => `<slot> can only receive attributes, not directives` ,
233276 'invalid-slot-attribute' : ( ) => `slot attribute must be a static value` ,
234- 'invalid-slot-name' : ( ) => `slot attribute must be a static value` ,
277+ /** @param {boolean } is_default */
278+ 'invalid-slot-name' : ( is_default ) =>
279+ is_default
280+ ? `default is a reserved word — it cannot be used as a slot name`
281+ : `slot attribute must be a static value` ,
235282 'invalid-slot-placement' : ( ) =>
236283 `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element` ,
237- 'duplicate-slot-name' : /** @param {string } name @param {string } component */ ( name , component ) =>
238- `Duplicate slot name '${ name } ' in <${ component } >` ,
284+ /** @param {string } name @param {string } component */
285+ 'duplicate-slot-name' : ( name , component ) => `Duplicate slot name '${ name } ' in <${ component } >` ,
239286 'invalid-default-slot-content' : ( ) =>
240287 `Found default slot content alongside an explicit slot="default"`
241288} ;
@@ -256,13 +303,20 @@ const bindings = {
256303 'invalid-type-attribute' : ( ) =>
257304 `'type' attribute must be a static text value if input uses two-way binding` ,
258305 'invalid-multiple-attribute' : ( ) =>
259- `'multiple' attribute must be static if select uses two-way binding`
306+ `'multiple' attribute must be static if select uses two-way binding` ,
307+ 'missing-contenteditable-attribute' : ( ) =>
308+ `'contenteditable' attribute is required for textContent, innerHTML and innerText two-way bindings` ,
309+ 'dynamic-contenteditable-attribute' : ( ) =>
310+ `'contenteditable' attribute cannot be dynamic if element uses two-way binding`
260311} ;
261312
262313/** @satisfies {Errors } */
263314const variables = {
264315 'illegal-global' : /** @param {string } name */ ( name ) =>
265- `${ name } is an illegal variable name. To reference a global variable called ${ name } , use globalThis.${ name } `
316+ `${ name } is an illegal variable name. To reference a global variable called ${ name } , use globalThis.${ name } ` ,
317+ /** @param {string } name */
318+ 'duplicate-declaration' : ( name ) => `'${ name } ' has already been declared` ,
319+ 'default-export' : ( ) => `A component cannot have a default export`
266320} ;
267321
268322/** @satisfies {Errors } */
@@ -279,6 +333,12 @@ const compiler_options = {
279333 'removed-compiler-option' : ( msg ) => `Invalid compiler option: ${ msg } `
280334} ;
281335
336+ /** @satisfies {Errors } */
337+ const const_tag = {
338+ 'invalid-const-placement' : ( ) =>
339+ `{@const} must be the immediate child of {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>`
340+ } ;
341+
282342/** @satisfies {Errors } */
283343const errors = {
284344 ...internal ,
@@ -293,7 +353,8 @@ const errors = {
293353 ...bindings ,
294354 ...variables ,
295355 ...compiler_options ,
296- ...legacy_reactivity
356+ ...legacy_reactivity ,
357+ ...const_tag
297358
298359 // missing_contenteditable_attribute: {
299360 // code: 'missing-contenteditable-attribute',
@@ -304,34 +365,11 @@ const errors = {
304365 // code: 'dynamic-contenteditable-attribute',
305366 // message: "'contenteditable' attribute cannot be dynamic if element uses two-way binding"
306367 // },
307- // invalid_event_modifier_combination: /**
308- // * @param {string } modifier1
309- // * @param {string } modifier2
310- // */ (modifier1, modifier2) => ({
311- // code: 'invalid-event-modifier',
312- // message: `The '${modifier1}' and '${modifier2}' modifiers cannot be used together`
313- // }),
314- // invalid_event_modifier_legacy: /** @param {string } modifier */ (modifier) => ({
315- // code: 'invalid-event-modifier',
316- // message: `The '${modifier}' modifier cannot be used in legacy mode`
317- // }),
318- // invalid_event_modifier: /** @param {string } valid */ (valid) => ({
319- // code: 'invalid-event-modifier',
320- // message: `Valid event modifiers are ${valid}`
321- // }),
322- // invalid_event_modifier_component: {
323- // code: 'invalid-event-modifier',
324- // message: "Event modifiers other than 'once' can only be used on DOM elements"
325- // },
326368 // textarea_duplicate_value: {
327369 // code: 'textarea-duplicate-value',
328370 // message:
329371 // 'A <textarea> can have either a value attribute or (equivalently) child content, but not both'
330372 // },
331- // illegal_attribute: /** @param {string } name */ (name) => ({
332- // code: 'illegal-attribute',
333- // message: `'${name}' is not a valid attribute name`
334- // }),
335373 // invalid_attribute_head: {
336374 // code: 'invalid-attribute',
337375 // message: '<svelte:head> should not have any attributes or directives'
@@ -340,10 +378,6 @@ const errors = {
340378 // code: 'invalid-action',
341379 // message: 'Actions can only be applied to DOM elements, not components'
342380 // },
343- // invalid_animation: {
344- // code: 'invalid-animation',
345- // message: 'Animations can only be applied to DOM elements, not components'
346- // },
347381 // invalid_class: {
348382 // code: 'invalid-class',
349383 // message: 'Classes can only be applied to DOM elements, not components'
@@ -364,22 +398,10 @@ const errors = {
364398 // code: 'dynamic-slot-name',
365399 // message: '<slot> name cannot be dynamic'
366400 // },
367- // invalid_slot_name: {
368- // code: 'invalid-slot-name',
369- // message: 'default is a reserved word — it cannot be used as a slot name'
370- // },
371401 // invalid_slot_attribute_value_missing: {
372402 // code: 'invalid-slot-attribute',
373403 // message: 'slot attribute value is missing'
374404 // },
375- // invalid_slotted_content_fragment: {
376- // code: 'invalid-slotted-content',
377- // message: '<svelte:fragment> must be a child of a component'
378- // },
379- // illegal_attribute_title: {
380- // code: 'illegal-attribute',
381- // message: '<title> cannot have attributes'
382- // },
383405 // illegal_structure_title: {
384406 // code: 'illegal-structure',
385407 // message: '<title> can only contain text and {tags}'
@@ -428,10 +450,6 @@ const errors = {
428450 // code: 'illegal-variable-declaration',
429451 // message: 'Cannot declare same variable name which is imported inside <script context="module">'
430452 // },
431- // css_invalid_global: {
432- // code: 'css-invalid-global',
433- // message: ':global(...) can be at the start or end of a selector sequence, but not in the middle'
434- // },
435453 // css_invalid_global_selector: {
436454 // code: 'css-invalid-global-selector',
437455 // message: ':global(...) must contain a single selector'
@@ -445,55 +463,15 @@ const errors = {
445463 // code: 'css-invalid-selector',
446464 // message: `Invalid selector "${selector}"`
447465 // }),
448- // duplicate_animation: {
449- // code: 'duplicate-animation',
450- // message: "An element can only have one 'animate' directive"
451- // },
452- // invalid_animation_immediate: {
453- // code: 'invalid-animation',
454- // message:
455- // 'An element that uses the animate directive must be the immediate child of a keyed each block'
456- // },
457- // invalid_animation_key: {
458- // code: 'invalid-animation',
459- // message:
460- // '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?'
461- // },
462- // invalid_animation_sole: {
463- // code: 'invalid-animation',
464- // message:
465- // 'An element that uses the animate directive must be the sole child of a keyed each block'
466- // },
467- // invalid_animation_dynamic_element: {
468- // code: 'invalid-animation',
469- // message: '<svelte:element> cannot have a animate directive'
470- // },
471466 // invalid_directive_value: {
472467 // code: 'invalid-directive-value',
473468 // message:
474469 // 'Can only bind to an identifier (e.g. `foo`) or a member expression (e.g. `foo.bar` or `foo[baz]`)'
475470 // },
476- // invalid_const_placement: {
477- // code: 'invalid-const-placement',
478- // message:
479- // '{@const } must be the immediate child of {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, <svelte:fragment> or <Component>'
480- // },
481- // invalid_const_declaration: /** @param {string } name */ (name) => ({
482- // code: 'invalid-const-declaration',
483- // message: `'${name}' has already been declared`
484- // }),
485- // invalid_const_update: /** @param {string } name */ (name) => ({
486- // code: 'invalid-const-update',
487- // message: `'${name}' is declared using {@const ...} and is read-only`
488- // }),
489471 // cyclical_const_tags: /** @param {string[] } cycle */ (cycle) => ({
490472 // code: 'cyclical-const-tags',
491473 // message: `Cyclical dependency detected: ${cycle.join(' → ')}`
492474 // }),
493- // invalid_component_style_directive: {
494- // code: 'invalid-component-style-directive',
495- // message: 'Style directives cannot be used on components'
496- // },
497475 // invalid_var_declaration: {
498476 // code: 'invalid_var_declaration',
499477 // message: '"var" scope should not extend outside the reactive block'
0 commit comments