cem-tools
cem-tools copied to clipboard
[jet-brains-integration] Include source module and symbol in web-types
Thank you for making this awesome generator!
Web-Types allows for specifying source module and symbol. When these are set you can use Go To > Declaration (or more commonly Ctrl+Click) on the custom HTML element to jump directly to the source file. The info is already present in the CEM and just needs to be passed along.
(Tested with litelements)
The challenge I see with this is that the module path is usually inaccurate in the CEM since it references the source file and not the output. Since this source file is not usually included in the final package, this will be useless for most teams. I know there are tools out there to update this path, so I think this could be a valid feature, but I think we should avoid making it enabled by default. Instead, could we invert the property to something like inludeSource, so teams can opt into it if they have made the changes?
I wonder if it would be beneficial to provide an option for teams to supply their own source path in case they haven't updated the CEM with the new information.
We could allow the user to pass a function that provides the source object given a component and module.
By default this function returns (component, module) => ({ symbol: component.name, module: module.path })
We could do something similar to what we have done for the other tools where we pass the tag name and the class name and they can define a path:
sourceModule: (className, tagName) => `../dist/components/${tagName}/${className}.js`
We could do something similar to what we have done for the other tools where we pass the tag name and the class name and they can define a path:
sourceModule: (className, tagName) => `../dist/components/${tagName}/${className}.js`
This is not so nice, because the path can vary, if you put some components in sub directories,..
We could allow the user to pass a function that provides the source object given a component and module. By default this function returns
(component, module) => ({ symbol: component.name, module: module.path })
@Kouzukii Just to get it right. The return value is a object literal?
Because web-types.json accepts also {file,offset} for the source attribute.
/**
* Allows to specify the source of the entity. For Vue.js component this may be for instance a class.
*/
export type Source =
| {
/**
* Path to the file, relative to the web-types JSON.
*/
file: string;
/**
* Offset in the file under which the source symbol, like class name, is located.
*/
offset: number;
}
| {
/**
* Name of module, which exports the symbol. May be omitted, in which case it's assumed to be the name of the library.
*/
module?: string;
/**
* Name of the exported symbol.
*/
symbol: string;
}
https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json
"source": {
"description": "Allows to specify the source of the entity. For Vue.js component this may be for instance a class.",
"type": "object",
"oneOf": [
{
"type": "object",
"properties": {
"file": {
"description": "Path to the file, relative to the web-types JSON.",
"type": "string"
},
"offset": {
"description": "Offset in the file under which the source symbol, like class name, is located.",
"type": "integer"
}
},
"required": [
"file",
"offset"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"module": {
"description": "Name of module, which exports the symbol. May be omitted, in which case it's assumed to be the name of the library.",
"type": "string"
},
"symbol": {
"description": "Name of the exported symbol.",
"type": "string"
}
},
"required": [
"symbol"
],
"additionalProperties": false
}
]
}
@Kouzukii Just to get it right. The return value is a object literal?
Because web-types.json accepts also {file,offset} for the source attribute.
Yeah, I think allowing the user to pass the full object is the best way to go. I haven't tried file/offset, since module/symbol already worked in my usecase.
We could do something similar to what we have done for the other tools where we pass the tag name and the class name and they can define a path:
sourceModule: (className, tagName) => `../dist/components/${tagName}/${className}.js`This is not so nice, because the path can vary, if you put some components in sub directories,..
We have those too. That string returned by the function is completely configurable by the developer and can return whatever they would like:
sourceModule: (className, tagName) => {
switch(tagName) {
case 'tab':
case 'tabs':
case 'tab-panel':
return `../dist/components/tabs/${className}.js`;
case 'accordion':
case 'accordion-panel':
return `../dist/components/accordion/${className}.js`;
default:
return `../dist/components/${tagName}/${className}.js`;
}
}
We could allow the user to pass a function that provides the source object given a component and module. By default this function returns
(component, module) => ({ symbol: component.name, module: module.path })@Kouzukii Just to get it right. The return value is a object literal?
Because web-types.json accepts also {file,offset} for the source attribute.
Are you typically defining more than one custom element per module or file?
We could allow the user to pass a function that provides the source object given a component and module. By default this function returns
(component, module) => ({ symbol: component.name, module: module.path })@Kouzukii Just to get it right. The return value is a object literal? Because web-types.json accepts also {file,offset} for the source attribute.
Are you typically defining more than one custom element per module or file?
Usually not, but in our analyzer config we check for every declaration in the declarations block , just to be on the save side.
Source
IMHO: If you write a "rule" you don't have to touch the config file again.
In our company, the one who maintains the "build" stuff is not the dev.
@break-stuff
The {className, tagName} as arguments will work for me too, with that information I am able to load the cem file and filter out the needed data.
BTW: The return type should not be a simple string, i think it should be more like:
{symbol:string,module?:string} | {file:string, offset:number} | false .
The false should be used to decide to not set the sourceModule for an element at all (i.e. if it is deprecated or for other reasons).
I think all we need is the file path for the source module.
We already know the name, so that doesn't need to be provided.
From the projects I have worked on, I have yet to see a team put multiple components in the same file, so the offset property doesn't seem especially useful for web components.
I don't think the {symbol:string,module?:string} option really makes sense for web components either. Do you have a good scenario for this use-case?
@break-stuff I've added a sourceModuleTemplate option now to allow the user to customize the generated source module path (also fixed referenceTemplate since it wasn't being set) What do you think?
Hi. Any update on this PR ? I could use this feature :)
The challenge I see with this is that the module path is usually inaccurate in the CEM since it references the source file and not the output.
Could this be solved by the user by including the https://github.com/wc-toolkit/module-path-resolver in the plugins chain of the analyzer (I think the module-path-resolver didn't exist at the time of this PR)?