@ui5/webcomponents-tools 2.15.0 → 2.16.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/components-package/nps.js +0 -1
- package/lib/cem/cem.js +1 -1
- package/lib/cem/patch/@custom-elements-manifest/analyzer/cli.js +128 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/package.json +59 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/browser-entrypoint.js +23 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/create.js +117 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/arrow-function.js +26 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/class-jsdoc.js +157 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/classes.js +20 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createArrowFunction.js +17 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createAttribute.js +24 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClass.js +301 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClassField.js +26 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createFunctionLike.js +73 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createMixin.js +33 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createVariable.js +22 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/handlers.js +338 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/custom-elements-define-calls.js +90 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/exports.js +156 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/function-like.js +24 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/mixins.js +29 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/reexported-wrapped-mixin-exports.js +84 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/variables.js +34 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/collect-phase/collect-imports.js +101 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/catalyst.js +11 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/controller.js +34 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/catalyst.js +11 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/controller.js +34 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/attr.js +53 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/custom-element-decorator.js +36 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/fast/fast.js +7 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/lit.js +13 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/member-denylist.js +21 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/method-denylist.js +20 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/property-decorator.js +94 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/static-properties.js +121 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/utils.js +66 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/stencil/stencil.js +129 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/index.js +80 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/cleanup-classes.js +25 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/field-denylist.js +22 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/method-denylist.js +25 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/apply-inheritance.js +78 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/is-custom-element.js +34 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/link-class-to-tagname.js +27 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/remove-unexported-declarations.js +23 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/resolve-initializers.js +52 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/ast-helpers.js +186 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/cli-helpers.js +164 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/exports.js +44 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/find-external-manifests.js +67 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/imports.js +25 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/index.js +71 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/jsdoc.js +19 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/manifest-helpers.js +194 -0
- package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/mixins.js +112 -0
- package/package.json +3 -3
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { isMixin } from '../../utils/mixins.js';
|
|
2
|
+
import { has } from '../../utils/index.js';
|
|
3
|
+
import { createClassDeclarationMixin } from './creators/handlers.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* REEXPORTED WRAPPED MIXIN EXPORTS
|
|
7
|
+
*
|
|
8
|
+
* Handle exported mixins
|
|
9
|
+
* @example ```
|
|
10
|
+
*
|
|
11
|
+
* function FooMixinImpl(klass) {
|
|
12
|
+
* class FooMixin extends klass {}
|
|
13
|
+
* return FooMixin;
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* export const FooMixin = dedupeMixin(FooMixinImpl);
|
|
17
|
+
*
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function reexportedWrappedMixinExportsPlugin() {
|
|
21
|
+
return {
|
|
22
|
+
name: 'CORE - REEXPORTED-WRAPPED-MIXINS',
|
|
23
|
+
analyzePhase({ts, node, moduleDoc, context}){
|
|
24
|
+
switch(node.kind) {
|
|
25
|
+
case ts.SyntaxKind.VariableStatement:
|
|
26
|
+
if(!isMixin(node)) {
|
|
27
|
+
node?.declarationList?.declarations?.forEach(declaration => {
|
|
28
|
+
|
|
29
|
+
const mixins = [];
|
|
30
|
+
if(ts.SyntaxKind.CallExpression === declaration?.initializer?.kind) {
|
|
31
|
+
/**
|
|
32
|
+
* If an exported variable has a callExpression, it might try to export a mixin
|
|
33
|
+
* We need to check if the current module contains any mixins
|
|
34
|
+
*/
|
|
35
|
+
const moduleMixinDeclarations = moduleDoc?.declarations?.filter(declaration => declaration.kind === 'mixin');
|
|
36
|
+
|
|
37
|
+
if(has(moduleMixinDeclarations)){
|
|
38
|
+
const mixinName = declaration?.initializer?.expression?.getText();
|
|
39
|
+
mixins.push(mixinName);
|
|
40
|
+
|
|
41
|
+
let node = declaration?.initializer?.arguments[0];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Handle nested Mixin calls
|
|
45
|
+
*/
|
|
46
|
+
while(node && ts.isCallExpression(node)) {
|
|
47
|
+
const mixinName = node.expression.getText();
|
|
48
|
+
mixins.push(mixinName);
|
|
49
|
+
|
|
50
|
+
node = node?.arguments[0]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* See if we can find the supposed Mixin in the modules declaration
|
|
55
|
+
* If we do, change the name of MixinImpl to the variableDeclaration thats actually being exported
|
|
56
|
+
*/
|
|
57
|
+
const foundMixin = moduleMixinDeclarations?.find(mixin => mixin.name === node?.getText());
|
|
58
|
+
if(foundMixin) {
|
|
59
|
+
foundMixin.name = declaration?.name?.getText()
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Next, we need to add any other mixins found along the way to the exported mixin's `mixins` array
|
|
63
|
+
*/
|
|
64
|
+
mixins?.forEach(mixin => {
|
|
65
|
+
const newMixin = createClassDeclarationMixin(mixin, moduleDoc, context);
|
|
66
|
+
foundMixin.mixins = [...(foundMixin?.mixins || []), newMixin];
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* At this point, there's now a variable declaration and a mixin declaration with the same name.
|
|
71
|
+
* We're only interested in the mixin, so we filter out the variable declaration
|
|
72
|
+
*/
|
|
73
|
+
moduleDoc.declarations = moduleDoc?.declarations?.filter(declaration => !(declaration.kind === 'variable' && declaration.name === foundMixin.name));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/variables.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createVariable } from './creators/createVariable.js';
|
|
2
|
+
import { isMixin } from '../../utils/mixins.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* variablePlugin
|
|
6
|
+
*
|
|
7
|
+
* handles variables
|
|
8
|
+
*/
|
|
9
|
+
export function variablePlugin() {
|
|
10
|
+
return {
|
|
11
|
+
name: 'CORE - VARIABLES',
|
|
12
|
+
analyzePhase({ts, node, moduleDoc}){
|
|
13
|
+
switch(node.kind) {
|
|
14
|
+
case ts.SyntaxKind.VariableStatement:
|
|
15
|
+
if(!isMixin(node)) {
|
|
16
|
+
node?.declarationList?.declarations?.forEach(declaration => {
|
|
17
|
+
/**
|
|
18
|
+
* It can be the case that a variable is already present in the declarations,
|
|
19
|
+
* for example if the variable is also an arrow function. So we need to make sure
|
|
20
|
+
* the declaration doesnt already exist before adding it to a modules declarations
|
|
21
|
+
*/
|
|
22
|
+
const alreadyExists = moduleDoc?.declarations?.some(_declaration => _declaration.name === declaration?.name?.getText());
|
|
23
|
+
|
|
24
|
+
if(!alreadyExists) {
|
|
25
|
+
const variable = createVariable(node, declaration);
|
|
26
|
+
moduleDoc.declarations.push(variable);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hasDefaultImport,
|
|
3
|
+
hasNamedImport,
|
|
4
|
+
hasAggregatingImport,
|
|
5
|
+
hasSideEffectImport,
|
|
6
|
+
} from '../../utils/imports.js';
|
|
7
|
+
import { isBareModuleSpecifier } from '../../utils/index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* COLLECT-IMPORTS
|
|
11
|
+
*
|
|
12
|
+
* Collects a modules imports so that declarations can later be resolved to their module/package.
|
|
13
|
+
*/
|
|
14
|
+
export function collectImportsPlugin() {
|
|
15
|
+
const files = {};
|
|
16
|
+
let currModuleImports;
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
name: 'CORE - IMPORTS',
|
|
20
|
+
collectPhase({ts, node}) {
|
|
21
|
+
if(node.kind === ts.SyntaxKind.SourceFile) {
|
|
22
|
+
/**
|
|
23
|
+
* Create an empty array for each module we visit
|
|
24
|
+
*/
|
|
25
|
+
files[node.fileName] = [];
|
|
26
|
+
currModuleImports = files[node.fileName];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @example import defaultExport from 'foo';
|
|
31
|
+
*/
|
|
32
|
+
if (hasDefaultImport(node)) {
|
|
33
|
+
const importTemplate = {
|
|
34
|
+
name: node.importClause.name.text,
|
|
35
|
+
kind: 'default',
|
|
36
|
+
importPath: node.moduleSpecifier.text,
|
|
37
|
+
isBareModuleSpecifier: isBareModuleSpecifier(node.moduleSpecifier.text),
|
|
38
|
+
isTypeOnly: !!node?.importClause?.isTypeOnly
|
|
39
|
+
};
|
|
40
|
+
currModuleImports.push(importTemplate);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @example import { export1, export2 } from 'foo';
|
|
45
|
+
* @example import { export1 as alias1 } from 'foo';
|
|
46
|
+
* @example import { export1, export2 as alias2 } from 'foo';
|
|
47
|
+
*/
|
|
48
|
+
if (hasNamedImport(node)) {
|
|
49
|
+
node.importClause.namedBindings.elements.forEach((element) => {
|
|
50
|
+
const importTemplate = {
|
|
51
|
+
name: element.name.text,
|
|
52
|
+
kind: 'named',
|
|
53
|
+
importPath: node.moduleSpecifier.text,
|
|
54
|
+
isBareModuleSpecifier: isBareModuleSpecifier(node.moduleSpecifier.text),
|
|
55
|
+
isTypeOnly: !!node?.importClause?.isTypeOnly
|
|
56
|
+
};
|
|
57
|
+
currModuleImports.push(importTemplate);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @example import * as name from './my-module.js';
|
|
63
|
+
*/
|
|
64
|
+
if (hasAggregatingImport(node)) {
|
|
65
|
+
const importTemplate = {
|
|
66
|
+
name: node.importClause.namedBindings.name.text,
|
|
67
|
+
kind: 'aggregate',
|
|
68
|
+
importPath: node.moduleSpecifier.text,
|
|
69
|
+
isBareModuleSpecifier: isBareModuleSpecifier(node.moduleSpecifier.text),
|
|
70
|
+
isTypeOnly: !!node?.importClause?.isTypeOnly
|
|
71
|
+
};
|
|
72
|
+
currModuleImports.push(importTemplate);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @example import './my-module.js';
|
|
77
|
+
*/
|
|
78
|
+
if(hasSideEffectImport(node)) {
|
|
79
|
+
const importTemplate = {
|
|
80
|
+
kind: 'side-effect',
|
|
81
|
+
importPath: node.moduleSpecifier.text,
|
|
82
|
+
isBareModuleSpecifier: isBareModuleSpecifier(node.moduleSpecifier.text),
|
|
83
|
+
isTypeOnly: false
|
|
84
|
+
};
|
|
85
|
+
currModuleImports.push(importTemplate);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
analyzePhase({ts, node, context}) {
|
|
89
|
+
if(node.kind === ts.SyntaxKind.SourceFile) {
|
|
90
|
+
|
|
91
|
+
/** Makes the imports available on the context object for a given module */
|
|
92
|
+
context.imports = files[node.fileName];
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
packageLinkPhase({context}) {
|
|
96
|
+
/** Reset */
|
|
97
|
+
context.imports = [];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { dasherize } from '@github/catalyst/lib/dasherize.js';
|
|
2
|
+
import { attrDecoratorPlugin } from '../decorators/attr.js';
|
|
3
|
+
import { controllerPlugin } from './controller.js';
|
|
4
|
+
|
|
5
|
+
export const catalystPlugin = () => [
|
|
6
|
+
attrDecoratorPlugin(attr => {
|
|
7
|
+
attr.name = `data-${dasherize(attr.name)}`;
|
|
8
|
+
return attr;
|
|
9
|
+
}),
|
|
10
|
+
controllerPlugin()
|
|
11
|
+
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { toKebabCase, resolveModuleOrPackageSpecifier, decorator } from '../../../utils/index.js'
|
|
2
|
+
|
|
3
|
+
export function controllerPlugin() {
|
|
4
|
+
return {
|
|
5
|
+
name: 'CORE - CONTROLLER',
|
|
6
|
+
analyzePhase({ts, node, moduleDoc, context}){
|
|
7
|
+
switch(node.kind) {
|
|
8
|
+
case ts.SyntaxKind.ClassDeclaration:
|
|
9
|
+
/**
|
|
10
|
+
* handle @controller
|
|
11
|
+
*/
|
|
12
|
+
const hasController = node?.modifiers?.find(decorator('controller'));
|
|
13
|
+
|
|
14
|
+
if(hasController) {
|
|
15
|
+
const className = node?.name?.getText();
|
|
16
|
+
|
|
17
|
+
const definitionDoc = {
|
|
18
|
+
kind: 'custom-element-definition',
|
|
19
|
+
name: toKebabCase(className).replace('-element', ''),
|
|
20
|
+
declaration: {
|
|
21
|
+
name: className,
|
|
22
|
+
...resolveModuleOrPackageSpecifier(moduleDoc, context, className)
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
moduleDoc.exports.push(definitionDoc);
|
|
28
|
+
}
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { dasherize } from '@github/catalyst/lib/dasherize.js';
|
|
2
|
+
import { attrDecoratorPlugin } from '../decorators/attr.js';
|
|
3
|
+
import { controllerPlugin } from './controller.js';
|
|
4
|
+
|
|
5
|
+
export const catalystPlugin2 = () => [
|
|
6
|
+
attrDecoratorPlugin(attr => {
|
|
7
|
+
attr.name = dasherize(attr.name);
|
|
8
|
+
return attr;
|
|
9
|
+
}),
|
|
10
|
+
controllerPlugin()
|
|
11
|
+
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { toKebabCase, resolveModuleOrPackageSpecifier, decorator } from '../../../utils/index.js'
|
|
2
|
+
|
|
3
|
+
export function controllerPlugin() {
|
|
4
|
+
return {
|
|
5
|
+
name: 'CORE - CONTROLLER',
|
|
6
|
+
analyzePhase({ts, node, moduleDoc, context}){
|
|
7
|
+
switch(node.kind) {
|
|
8
|
+
case ts.SyntaxKind.ClassDeclaration:
|
|
9
|
+
/**
|
|
10
|
+
* handle @controller
|
|
11
|
+
*/
|
|
12
|
+
const hasController = node?.modifiers?.find(decorator('controller'));
|
|
13
|
+
|
|
14
|
+
if(hasController) {
|
|
15
|
+
const className = node?.name?.getText();
|
|
16
|
+
|
|
17
|
+
const definitionDoc = {
|
|
18
|
+
kind: 'custom-element-definition',
|
|
19
|
+
name: toKebabCase(className).replace('-element', ''),
|
|
20
|
+
declaration: {
|
|
21
|
+
name: className,
|
|
22
|
+
...resolveModuleOrPackageSpecifier(moduleDoc, context, className)
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
moduleDoc.exports.push(definitionDoc);
|
|
28
|
+
}
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { decorator } from '../../../utils/index.js'
|
|
2
|
+
import { getOptionsObject } from '../../../utils/ast-helpers.js'
|
|
3
|
+
import { createAttributeFromField } from '../../analyse-phase/creators/createAttribute.js';
|
|
4
|
+
|
|
5
|
+
export function attrDecoratorPlugin(converter) {
|
|
6
|
+
return {
|
|
7
|
+
name: 'CORE - ATTR-DECORATOR',
|
|
8
|
+
analyzePhase({ts, node, moduleDoc}){
|
|
9
|
+
switch(node.kind) {
|
|
10
|
+
case ts.SyntaxKind.ClassDeclaration:
|
|
11
|
+
const className = node?.name?.getText();
|
|
12
|
+
const classDoc = moduleDoc?.declarations?.find(declaration => declaration.name === className);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* If a field has the @attr decorator, create an attr from the field in the classDoc
|
|
16
|
+
*/
|
|
17
|
+
node?.members?.forEach(member => {
|
|
18
|
+
const hasAttrDecorator = member?.modifiers?.find(decorator('attr'));
|
|
19
|
+
if(hasAttrDecorator) {
|
|
20
|
+
const correspondingField = classDoc?.members?.find(classMember => classMember.name === member.name.getText());
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* If a `field` was not found on the `currClass`, that's because it has a @internal jsdoc notation
|
|
24
|
+
*/
|
|
25
|
+
if(!correspondingField) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let attribute = createAttributeFromField(correspondingField);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* An @attr might have an options object, like: @attr({attribute: 'my-el'})
|
|
33
|
+
* to specify the attribute name, here we check if it does have such an object
|
|
34
|
+
* and add the name to the attribute
|
|
35
|
+
*/
|
|
36
|
+
const optionsObject = getOptionsObject(hasAttrDecorator);
|
|
37
|
+
if(optionsObject) {
|
|
38
|
+
const name = optionsObject?.properties?.find(prop => prop.name.getText() === 'attribute')?.initializer?.text;
|
|
39
|
+
attribute.name = name;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (converter) {
|
|
43
|
+
attribute = converter(attribute);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
classDoc.attributes = [...(classDoc.attributes || []), attribute];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getElementNameFromDecorator } from '../../../utils/ast-helpers.js';
|
|
2
|
+
import { has, decorator, resolveModuleOrPackageSpecifier } from '../../../utils/index.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CUSTOMELEMENT
|
|
6
|
+
*
|
|
7
|
+
* Handles the customElement decorator
|
|
8
|
+
* @example @customElement('my-el');
|
|
9
|
+
*/
|
|
10
|
+
export function customElementDecoratorPlugin() {
|
|
11
|
+
return {
|
|
12
|
+
name: 'CORE - CUSTOM-ELEMENT-DECORATOR',
|
|
13
|
+
analyzePhase({node, moduleDoc, context}){
|
|
14
|
+
if (has(node.modifiers)) {
|
|
15
|
+
const customElementDecorator = node.modifiers?.find(decorator('customElement'));
|
|
16
|
+
|
|
17
|
+
if(customElementDecorator) {
|
|
18
|
+
const className = node.name.text;
|
|
19
|
+
const tagName = getElementNameFromDecorator(customElementDecorator);
|
|
20
|
+
|
|
21
|
+
const definitionDoc = {
|
|
22
|
+
kind: 'custom-element-definition',
|
|
23
|
+
name: tagName,
|
|
24
|
+
declaration: {
|
|
25
|
+
name: className,
|
|
26
|
+
...resolveModuleOrPackageSpecifier(moduleDoc, context, className)
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
moduleDoc.exports = [...(moduleDoc.exports || []), definitionDoc];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/lit.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { customElementDecoratorPlugin } from '../decorators/custom-element-decorator.js';
|
|
2
|
+
import { methodDenyListPlugin } from './method-denylist.js';
|
|
3
|
+
import { memberDenyListPlugin } from './member-denylist.js';
|
|
4
|
+
import { propertyDecoratorPlugin } from './property-decorator.js';
|
|
5
|
+
import { staticPropertiesPlugin } from './static-properties.js';
|
|
6
|
+
|
|
7
|
+
export const litPlugin = () => [
|
|
8
|
+
customElementDecoratorPlugin(),
|
|
9
|
+
methodDenyListPlugin(),
|
|
10
|
+
memberDenyListPlugin(),
|
|
11
|
+
propertyDecoratorPlugin(),
|
|
12
|
+
staticPropertiesPlugin()
|
|
13
|
+
]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MEMBER-DENY-LIST
|
|
3
|
+
*
|
|
4
|
+
* Excludes members from the manifest
|
|
5
|
+
*/
|
|
6
|
+
export function memberDenyListPlugin() {
|
|
7
|
+
const MEMBER_DENY_LIST = ['properties', 'styles'];
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
name: 'CORE - LIT-MEMBER-DENYLIST',
|
|
11
|
+
moduleLinkPhase({moduleDoc}){
|
|
12
|
+
const classes = moduleDoc?.declarations?.filter(declaration => declaration.kind === 'class');
|
|
13
|
+
|
|
14
|
+
classes?.forEach(klass => {
|
|
15
|
+
if(!klass?.members) return;
|
|
16
|
+
klass.members = klass?.members?.filter(member => !MEMBER_DENY_LIST.includes(member.name));
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* METHOD-DENY-LIST
|
|
3
|
+
*
|
|
4
|
+
* Excludes methods from the manifest
|
|
5
|
+
*/
|
|
6
|
+
export function methodDenyListPlugin() {
|
|
7
|
+
const METHOD_DENY_LIST = ['requestUpdate', 'createRenderRoot', 'scheduleUpdate', 'performUpdate', 'shouldUpdate', 'update', 'render', 'firstUpdated', 'updated', 'willUpdate'];
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
name: 'CORE - LIT-METHOD-DENYLIST',
|
|
11
|
+
moduleLinkPhase({moduleDoc}){
|
|
12
|
+
const classesAndMixins = moduleDoc?.declarations?.filter(declaration => declaration.kind === 'class' || declaration.kind === 'mixin');
|
|
13
|
+
|
|
14
|
+
classesAndMixins?.forEach(klass => {
|
|
15
|
+
if(!klass?.members) return;
|
|
16
|
+
klass.members = klass?.members?.filter(member => !METHOD_DENY_LIST.includes(member.name));
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { decorator } from '../../../utils/index.js';
|
|
3
|
+
import { createAttributeFromField } from '../../analyse-phase/creators/createAttribute.js';
|
|
4
|
+
import { hasPropertyDecorator, isAlsoAttribute, getAttributeName, reflects } from './utils.js';
|
|
5
|
+
|
|
6
|
+
import { extractMixinNodes, isMixin } from '../../../utils/mixins.js';
|
|
7
|
+
import { handleName } from '../../analyse-phase/creators/createMixin.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* PROPERTY
|
|
11
|
+
*
|
|
12
|
+
* Handles the property decorator
|
|
13
|
+
* @example @property({});
|
|
14
|
+
*/
|
|
15
|
+
export function propertyDecoratorPlugin() {
|
|
16
|
+
return {
|
|
17
|
+
name: 'CORE - LIT-PROPERTY-DECORATOR',
|
|
18
|
+
analyzePhase({ts, node, moduleDoc}){
|
|
19
|
+
switch (node.kind) {
|
|
20
|
+
case ts.SyntaxKind.VariableStatement:
|
|
21
|
+
case ts.SyntaxKind.FunctionDeclaration:
|
|
22
|
+
if(isMixin(node)) {
|
|
23
|
+
const { mixinFunction, mixinClass } = extractMixinNodes(node);
|
|
24
|
+
const { name } = handleName({}, mixinFunction);
|
|
25
|
+
handlePropertyDecorator(mixinClass, moduleDoc, name);
|
|
26
|
+
}
|
|
27
|
+
break;
|
|
28
|
+
|
|
29
|
+
case ts.SyntaxKind.ClassDeclaration:
|
|
30
|
+
handlePropertyDecorator(node, moduleDoc);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
function handlePropertyDecorator(classNode, moduleDoc, mixinName = null) {
|
|
39
|
+
let className;
|
|
40
|
+
if(!mixinName) {
|
|
41
|
+
className = classNode?.name?.getText();
|
|
42
|
+
} else {
|
|
43
|
+
className = mixinName;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const currClass = moduleDoc?.declarations?.find(declaration => declaration.name === className);
|
|
47
|
+
/**
|
|
48
|
+
* Find members with @property decorator
|
|
49
|
+
*/
|
|
50
|
+
classNode?.members?.forEach(member => {
|
|
51
|
+
if (hasPropertyDecorator(member)) {
|
|
52
|
+
const propertyDecorator = member.modifiers.find(decorator('property'));
|
|
53
|
+
const propertyOptions = propertyDecorator?.expression?.arguments?.find(arg => ts.isObjectLiteralExpression(arg));
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* If property does _not_ have `attribute: false`, also create an attribute based on the field
|
|
57
|
+
*/
|
|
58
|
+
if (isAlsoAttribute(propertyOptions)) {
|
|
59
|
+
const field = currClass.members.find(classMember => classMember.name === member.name.getText());
|
|
60
|
+
/** If a `field` was not found on the `currClass`, that's because it has a @internal jsdoc notation */
|
|
61
|
+
if(!field) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const attribute = createAttributeFromField(field);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* If an attribute name is provided
|
|
68
|
+
* @example @property({attribute:'my-foo'})
|
|
69
|
+
*/
|
|
70
|
+
const attributeName = getAttributeName(propertyOptions);
|
|
71
|
+
if(attributeName) {
|
|
72
|
+
attribute.name = attributeName;
|
|
73
|
+
field.attribute = attributeName;
|
|
74
|
+
} else {
|
|
75
|
+
field.attribute = field.name;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if(reflects(propertyOptions)) {
|
|
80
|
+
field.attribute = attribute.name;
|
|
81
|
+
field.reflects = true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const existingAttribute = currClass?.attributes?.find(attr => attr.name === attribute.name);
|
|
85
|
+
|
|
86
|
+
if(!existingAttribute) {
|
|
87
|
+
currClass.attributes.push(attribute);
|
|
88
|
+
} else {
|
|
89
|
+
currClass.attributes = currClass?.attributes?.map(attr => attr.name === attribute.name ? ({...attr, ...attribute}) : attr);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|