@@ -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