custom-elements-manifest
custom-elements-manifest copied to clipboard
missing attributes extending mixins
Checklist
- [x] Did you run the analyzer with the
--dev
flag to get more information? - [x] Did you create a minimal reproduction in the playground?
- used version 0.5.7 of the analyzer
Completing the items above will greatly improve triaging time of your issue.
Expected behavior I would expect attributes to be inherited.
Example code:
- class A extends HTMLElement
- class B extends A
- class C extends B
Only the attribute from class A is available.
I have created 3 files:
// a.js
/**
* @tagname my-mixin-a
*/
export class MyElementA extends getClass(HTMLElement) { }
export function getClass(superClass = HTMLElement) {
return class extends superClass {
static get observedAttributes() {
return ['a'];
}
set a(val) {
this._a = val;
}
get a() {
return this._a;
}
}
}
// b.js
import { MyElementA } from './a.js';
/**
* @tag my-mixin-ab
*/
export class MyElementAB extends getClass(MyElementA) { };
export function getClass(superClass = MyElementA) {
return class extends superClass {
static get observedAttributes() {
return ['b'];
}
set b(val) {
this._b = val;
}
get b() {
return this._b;
}
}
}
// c.js
import { MyElementAB } from './b.js';
/**
* @tagname my-mixin-abc
*/
export class MyElementABC extends getClass(MyElementAB) { };
export function getClass(superClass = MyElementAB) {
return class extends superClass {
static get observedAttributes() {
return ['c'];
}
set c(val) {
this._c = val;
}
get c() {
return this._c;
}
}
}
The result:
// custom-elements.json
{
"schemaVersion": "1.0.0",
"readme": "",
"modules": [
{
"kind": "javascript-module",
"path": "src/a.js",
"declarations": [
{
"kind": "class",
"description": "",
"name": "MyElementA",
"mixins": [
{
"name": "getClass",
"module": "src/a.js"
}
],
"superclass": {
"name": "HTMLElement"
},
"tagName": "my-mixin-a",
"customElement": true,
"attributes": [
{
"name": "a",
"inheritedFrom": {
"name": "getClass",
"module": "src/c.js"
}
}
],
"members": [
{
"kind": "field",
"name": "a",
"inheritedFrom": {
"name": "getClass",
"module": "src/c.js"
}
}
]
},
{
"kind": "mixin",
"description": "",
"name": "getClass",
"members": [
{
"kind": "field",
"name": "a"
}
],
"attributes": [
{
"name": "a"
}
],
"parameters": [
{
"name": "superClass",
"default": "HTMLElement"
}
]
}
],
"exports": [
{
"kind": "js",
"name": "MyElementA",
"declaration": {
"name": "MyElementA",
"module": "src/a.js"
}
},
{
"kind": "js",
"name": "getClass",
"declaration": {
"name": "getClass",
"module": "src/a.js"
}
}
]
},
{
"kind": "javascript-module",
"path": "src/b.js",
"declarations": [
{
"kind": "class",
"description": "",
"name": "MyElementAB",
"mixins": [
{
"name": "getClass",
"module": "src/b.js"
}
],
"superclass": {
"name": "MyElementA",
"module": "/src/a.js"
},
"tagName": "my-mixin-ab",
"customElement": true,
"attributes": [
{
"name": "a",
"inheritedFrom": {
"name": "MyElementA",
"module": "src/a.js"
}
}
],
"members": [
{
"kind": "field",
"name": "a",
"inheritedFrom": {
"name": "MyElementA",
"module": "src/a.js"
}
}
]
},
{
"kind": "mixin",
"description": "",
"name": "getClass",
"members": [
{
"kind": "field",
"name": "b"
}
],
"attributes": [
{
"name": "b"
}
],
"parameters": [
{
"name": "superClass",
"default": "MyElementA"
}
]
}
],
"exports": [
{
"kind": "js",
"name": "MyElementAB",
"declaration": {
"name": "MyElementAB",
"module": "src/b.js"
}
},
{
"kind": "js",
"name": "getClass",
"declaration": {
"name": "getClass",
"module": "src/b.js"
}
}
]
},
{
"kind": "javascript-module",
"path": "src/c.js",
"declarations": [
{
"kind": "class",
"description": "",
"name": "MyElementABC",
"mixins": [
{
"name": "getClass",
"module": "src/c.js"
}
],
"superclass": {
"name": "MyElementAB",
"module": "/src/b.js"
},
"tagName": "my-mixin-abc",
"customElement": true,
"attributes": [
{
"name": "a",
"inheritedFrom": {
"name": "MyElementA",
"module": "src/a.js"
}
}
],
"members": [
{
"kind": "field",
"name": "a",
"inheritedFrom": {
"name": "MyElementA",
"module": "src/a.js"
}
}
]
},
{
"kind": "mixin",
"description": "",
"name": "getClass",
"members": [
{
"kind": "field",
"name": "c"
}
],
"attributes": [
{
"name": "c"
}
],
"parameters": [
{
"name": "superClass",
"default": "MyElementAB"
}
]
}
],
"exports": [
{
"kind": "js",
"name": "MyElementABC",
"declaration": {
"name": "MyElementABC",
"module": "src/c.js"
}
},
{
"kind": "js",
"name": "getClass",
"declaration": {
"name": "getClass",
"module": "src/c.js"
}
}
]
}
]
}
Thanks for reporting this issue, I appreciate you taking the time to make a reproduction, could I ask you to try and make the reproduction even smaller?
@thepassle No problem, I appreciate the module.
I tried to make it as small as possible, the issue only happened using multiple files. I was not able to reproduce it in the playground.
Would a small repo help?
Would a small repo help?
Yes that would help, I know it's already pretty minimal, but please try to make the repro as minimal as you possibly can (the least amount of classes/mixins required, maybe only a property instead of properties/and attributes, etc). Sorry to be nitpicky, but bugs in the inheritance stuff get very confusing very quickly.
Ok no problem, does this help?
https://github.com/reno1979/custom-element-manifest-test
Yes that helps, thanks a lot.
Do you use multiple mixins that have the same name in a project? E.g.: in your repo, you declare getClass
every time in each file
@thepassle correct, a code template is user. So all files are the same.
Is this code open source by any chance? I'd be interested to see what it looks like
@thepassle no sorry I can not publish the code. I wish I could. It is just a vanilla web component library. I'm working on something very basic that works almost the same, it is a way for me to experiment. And that is a personal project, so when published I will let you know.
I understand. To clarify, I'm interested in seeing why you'd re-declare a mixin with the same name for every file, as opposed to giving the mixin its own module/making it shared somehow.
ahh that is because it is a work in progress. The mixin is only a wrapper, the actual class that is wrapped should be able to extend on a different given class.
For example:
// baseA.js
export class BaseClassA extends HTMLElement {..}
// baseB.js
export class BaseClassB extends HTMLElement {..}
// element.js
import { BaseClassA } from './baseA.js';
import { BaseClassB } from './baseB.js';
export function getClass(SuperClass){
return new class extends SuperClass {
static get observedAttributes() {
return [].concat(SuperClass.observedAttributes);
}
... etc
}
}
class ElementA extends getClass(BaseClassA){};
class ElementB extends getClass(BaseClassB){};
customElements.define('wc-a', ElementA);
customElements.define('wc-b', ElementB);
```
@thepassle
Is there a possible workaround I could do in our code base to make it work?
Bump.
I'm still having this issue today in recent versions/usage of CEM analyzer. Is there a plan of attack for adding properties that come from the inheritance chain added to the class declaration in the manifest?
I'm attempting to use the manifest.json file for automated documentation, and not having mixin properties be available makes my documentation inacccurate