Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide suggestions and type checking for elements attributes #663

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

patricklx
Copy link
Contributor

@patricklx patricklx commented Jan 2, 2024

this would also make it possible to wrap WebComponents and have auto completions and type checking for those.
also allows any key. ideally we should only allow any key, if its prefixed with data-.

unfortunately <WebComponent myoptions="<cursor here>" /> does not provide completions.
But <WebComponent myoptions={{"<cursor here>"}} /> does

@patricklx
Copy link
Contributor Author

Screenshot 2024-01-03 at 12 45 12 Screenshot 2024-01-03 at 12 48 52

@@ -10,7 +10,7 @@ export type ResolveOrReturn<T> = T & (<U>(item: U) => () => U);
*/
export type ElementForTagName<Name extends string> = Name extends keyof HTMLElementTagNameMap
? Name extends keyof SVGElementTagNameMap
? HTMLElementTagNameMap[Name] & SVGElementTagNameMap[Name]
? HTMLElementTagNameMap[Name] | SVGElementTagNameMap[Name]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment also says that it should be an union This will return a union for elements that exist both in HTML and SVG.
But it was an intersection

@patricklx
Copy link
Contributor Author

hmmm, this needs a way to distinguish exactly between svg elements and html elements...
would need to add a parameter to emitElement when in svg context

@dfreeman
Copy link
Member

dfreeman commented Jan 3, 2024

Thanks for this, but I think this is conflating HTML attributes and DOM properties in a way that doesn't quite work.

The properties on an Element subtype aren't the same as the attributes it accepts. Some attributes and properties do align 1-to-1, like id, but many either don't directly align, like data-* attributes that correspond to dataset.* properties, or only exist on one side or the other, like aria-* attributes or the textContent property.

@patricklx
Copy link
Contributor Author

😞
then i give up. would have been nice to have this

@NullVoxPopuli
Copy link
Contributor

does TS provide no map/list of attributes?

@NullVoxPopuli
Copy link
Contributor

If we can't get a list of attributes,
surely it would be better to have some completion rather than the none-situation we have today.
We could filter out DOM properties that aren't single-words, so at least the single-word attribute / dom properties match up.
That's an improvement.

@patricklx
Copy link
Contributor Author

@dfreeman
Copy link
Member

dfreeman commented Jan 3, 2024

does TS provide no map/list of attributes?

We spent time looking into this earlier on in Glint's development—I think everyone involved agrees this would be nice to have! TS doesn't include anything like this in its standard library, though, and at least as of when we last checked we didn't find any third-party version either.

what about this? npmjs.com/package/html-element-attributes

At a types level, that just exposes Record<string, Array<string>>:
https://github.com/wooorm/html-element-attributes/blob/main/build.js#L88

We could filter out DOM properties that aren't single-words, so at least the single-word attribute / dom properties match up.

Is that a valid heuristic? I feel pretty strongly that wrong completions are worse than no completions.

@NullVoxPopuli
Copy link
Contributor

NullVoxPopuli commented Jan 3, 2024

I feel pretty strongly that wrong completions are worse than no completions.

yes, but a subset of incomplete, yet correct completions are better than no completions.

At a types level, that just exposes Record<string, Array>:

we could PR them to as const that whole structure (and sub structure) in index.js, which would make the type more specific.
I like this.

@dfreeman
Copy link
Member

dfreeman commented Jan 3, 2024

yes, but a subset of incomplete, yet correct completions are better than no completions.

Yes, which is exactly why I asked if your suggested heuristic of only doing single-word ones actually works 😜

@dfreeman
Copy link
Member

dfreeman commented Jan 3, 2024

In other words, my point is that this isn't just a casing issue. Driving off of Element properties would include, for instance, dataset as a suggestion, which isn't a valid HTML attribute. I don't think we have evidence that even just single-word names have any guarantee of aligning across the attribute/property line.

@patricklx
Copy link
Contributor Author

I think making a pr to https://www.npmjs.com/package/html-element-attributes to generate a d.ts would then make ut usable

@NullVoxPopuli
Copy link
Contributor

Let's see what the maintainer says: wooorm/html-element-attributes#9

I've worked with them before with remark/unified/codemirror stuff before, and iirc, they're pretty responsive.

@patricklx
Copy link
Contributor Author

Would also need https://github.com/wooorm/svg-element-attributes

@patricklx
Copy link
Contributor Author

patricklx commented Jan 4, 2024

well, I couldn't give up just yet :)
i build an own element.d.ts based on various packages from woorm.
its all interfaces, so it should be possible to augment them with custom definitions.

now i only get valid completions for element attributes. unfortunately it only works inside an AttrNode
so <a h$cursor$ ></a>

if we had a node for the tag name, we could probably default the location to attributes for the rest

return completions?.entries.map((completionEntry) => ({
label: completionEntry.name,
label: isInElementAttributes
? completionEntry.name.replace(/["']/g, '')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to remove " or ' from element attributes containing a -

@@ -42,7 +42,7 @@ export function templateToTypescript(
return mapTemplateContents(originalTemplate, { embeddingSyntax }, (ast, mapper) => {
let { emit, record, rangeForLine, rangeForNode } = mapper;
let scope = new ScopeStack([]);

let inSVG = false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it could be possible to have components inside svg, with this it would be possible to a glint-directive @glint-in-svg a the top of the template to specify that we are inside svg.

[P in keyof T]?: T[P] extends SVGAnimatedString ? string : T[P];
};

// TODO: improve this to allow other keys
Copy link
Contributor Author

@patricklx patricklx Jan 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anyone knowns how to achieve this?
basically would like to allow other keys that default to AttrValue.

Currently I do it with & Record<string, AttrValue> (line 157), but that sets all properties to AttrValue

# Conflicts:
#	packages/core/src/transform/template/template-to-typescript.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants