svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Add component name to function or function prototype

Open webJose opened this issue 2 months ago • 5 comments

Describe the problem

When creating demos for component libraries, it would be handy if we could write generalized code that receives a component by arguments/properties and can extract the component name out of it.

Pardon me if this is already possible. I don't recall ever reading about this, if it exists today.

Describe the proposed solution

Have the Svelte compiler add the componentName property to the function or function's prototype. The name would come from... ? See options.

Simple Option

Use the file's name.

Not-So-Simple Option

Because the component is a default export, it really can be named anything. Furthermore, if it ever becomes possible to export components grouped in POJO objects (I opened an issue for this a long time ago), for documentation/demo purposes it could be a compound name like Card.Header.

Because of this, maybe the best option would be to add a per-component compiler option to set the desired name. If the option is not specified, then it would default to the simple option above.

Importance

nice to have

webJose avatar Oct 27 '25 08:10 webJose

This is a great proposal, I agree it would be very useful for component libraries.

I am very interested in working on this. If the maintainers approve the direction of this feature, could you(@webJose ) please assign this issue to me?

I'd be happy to start working on the implementation.

JuanHPassos avatar Oct 28 '25 22:10 JuanHPassos

This is trivial to do with a Vite plugin. It's probably not something that should live in Svelte.

The shape of component output is fairly stable. You can use a regex to find export default function MyComponent( and magic-string to append MyComponent.name = 'MyComponent' and whatever meta-data you desire for your demos while preserving source maps.

It should be a 5 minute job w/ ChatGPT to get a workable draft. Happy to help if you get stuck or have questions.

kwangure avatar Nov 06 '25 11:11 kwangure

Good point @kwangure , this is a working example using a vite plugin. Hope it helps :)

import path from 'node:path';

export default function svelteComponentName() {
	return {
		name: 'svelte-component-name',

		transform(code, id) {
			if (!id.endsWith('.svelte')) return;

			const filename = path.basename(id, '.svelte');

			const match = code.match(/export\s+default\s+function\s+([A-Za-z0-9_]+)\s*\(/);

			if (!match) return;

			const fnName = match[1];

			const inject = `\n${fnName}.componentName = "${filename}";\n`;

			return {
				code: code + inject,
				map: null
			};
		}
	};
}

aliberro39109 avatar Nov 07 '25 07:11 aliberro39109

While using Vite for this is nice, there's the matter of the TypeScript. Component<> should disclose the presence of componentName, which is not something achievable via Vite alone.

webJose avatar Nov 08 '25 19:11 webJose

This solvable with a regular TypeScript declaration, right?

Written by ChatGPT. Not validated but you get the idea:

// src/global.d.ts
declare module '*.svelte' {
  import { Component as Component2 } from 'svelte';

  export default class Component<
    Props = any,
    Events = any,
    Slots = any
  > extends Component2<Props, Events, Slots> {
    /** Custom property to identify the component */
    static componentName: string;
  }
}

If you're working on a library, add it to your main entry so that it's automatically included when users import anything.

EDIT: See https://www.typescriptlang.org/docs/handbook/declaration-merging.html

kwangure avatar Nov 13 '25 07:11 kwangure