@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.
Files changed (58) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/components-package/nps.js +0 -1
  3. package/lib/cem/cem.js +1 -1
  4. package/lib/cem/patch/@custom-elements-manifest/analyzer/cli.js +128 -0
  5. package/lib/cem/patch/@custom-elements-manifest/analyzer/package.json +59 -0
  6. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/browser-entrypoint.js +23 -0
  7. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/create.js +117 -0
  8. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/arrow-function.js +26 -0
  9. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/class-jsdoc.js +157 -0
  10. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/classes.js +20 -0
  11. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createArrowFunction.js +17 -0
  12. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createAttribute.js +24 -0
  13. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClass.js +301 -0
  14. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClassField.js +26 -0
  15. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createFunctionLike.js +73 -0
  16. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createMixin.js +33 -0
  17. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createVariable.js +22 -0
  18. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/handlers.js +338 -0
  19. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/custom-elements-define-calls.js +90 -0
  20. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/exports.js +156 -0
  21. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/function-like.js +24 -0
  22. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/mixins.js +29 -0
  23. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/reexported-wrapped-mixin-exports.js +84 -0
  24. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/variables.js +34 -0
  25. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/collect-phase/collect-imports.js +101 -0
  26. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/catalyst.js +11 -0
  27. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/controller.js +34 -0
  28. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/catalyst.js +11 -0
  29. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/controller.js +34 -0
  30. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/attr.js +53 -0
  31. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/custom-element-decorator.js +36 -0
  32. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/fast/fast.js +7 -0
  33. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/lit.js +13 -0
  34. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/member-denylist.js +21 -0
  35. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/method-denylist.js +20 -0
  36. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/property-decorator.js +94 -0
  37. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/static-properties.js +121 -0
  38. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/utils.js +66 -0
  39. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/stencil/stencil.js +129 -0
  40. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/index.js +80 -0
  41. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/cleanup-classes.js +25 -0
  42. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/field-denylist.js +22 -0
  43. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/method-denylist.js +25 -0
  44. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/apply-inheritance.js +78 -0
  45. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/is-custom-element.js +34 -0
  46. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/link-class-to-tagname.js +27 -0
  47. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/remove-unexported-declarations.js +23 -0
  48. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/resolve-initializers.js +52 -0
  49. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/ast-helpers.js +186 -0
  50. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/cli-helpers.js +164 -0
  51. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/exports.js +44 -0
  52. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/find-external-manifests.js +67 -0
  53. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/imports.js +25 -0
  54. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/index.js +71 -0
  55. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/jsdoc.js +19 -0
  56. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/manifest-helpers.js +194 -0
  57. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/mixins.js +112 -0
  58. 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
+ }
@@ -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
+
@@ -0,0 +1,7 @@
1
+ import { attrDecoratorPlugin } from '../decorators/attr.js';
2
+ import { customElementDecoratorPlugin } from '../decorators/custom-element-decorator.js';
3
+
4
+ export const fastPlugin = () => [
5
+ attrDecoratorPlugin(),
6
+ customElementDecoratorPlugin()
7
+ ]
@@ -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
+ }