@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,121 @@
1
+ import { createAttributeFromField } from '../../analyse-phase/creators/createAttribute.js';
2
+ import { getDefaultValuesFromConstructorVisitor } from '../../analyse-phase/creators/createClass.js';
3
+ import { handleJsDoc } from '../../analyse-phase/creators/handlers.js';
4
+ import {
5
+ isAlsoAttribute,
6
+ hasStaticKeyword,
7
+ getPropertiesObject,
8
+ getAttributeName,
9
+ reflects,
10
+ getType,
11
+ } from './utils.js';
12
+
13
+ import { extractMixinNodes, isMixin } from '../../../utils/mixins.js';
14
+ import { handleName } from '../../analyse-phase/creators/createMixin.js';
15
+
16
+ /**
17
+ * STATIC-PROPERTIES
18
+ *
19
+ * Handles `static get properties()` and `static properties`
20
+ */
21
+ export function staticPropertiesPlugin() {
22
+ return {
23
+ name: 'CORE - LIT-STATIC-PROPERTIES',
24
+ analyzePhase({ ts, node, moduleDoc, context }) {
25
+ switch (node.kind) {
26
+ case ts.SyntaxKind.VariableStatement:
27
+ case ts.SyntaxKind.FunctionDeclaration:
28
+ if (isMixin(node)) {
29
+ const { mixinFunction, mixinClass } = extractMixinNodes(node);
30
+ const { name } = handleName({}, mixinFunction);
31
+ handleStaticProperties(mixinClass, moduleDoc, context, name, ts);
32
+ }
33
+ break;
34
+
35
+ case ts.SyntaxKind.ClassDeclaration:
36
+ handleStaticProperties(node, moduleDoc, context, null, ts);
37
+ break;
38
+ }
39
+ },
40
+ };
41
+ }
42
+
43
+ function handleStaticProperties(classNode, moduleDoc, context, mixinName = null, ts) {
44
+ let className;
45
+ if (!mixinName) {
46
+ className = classNode?.name?.getText();
47
+ } else {
48
+ className = mixinName;
49
+ }
50
+ const currClass = moduleDoc?.declarations?.find(declaration => declaration.name === className);
51
+
52
+ classNode?.members?.forEach(member => {
53
+ if (hasStaticKeyword(member) && member.name.text === 'properties') {
54
+ const propertiesObject = getPropertiesObject(member);
55
+ propertiesObject?.properties?.forEach(property => {
56
+ if (property.kind !== ts.SyntaxKind.PropertyAssignment) return;
57
+
58
+ let classMember = {
59
+ kind: 'field',
60
+ name: property?.name?.getText() || '',
61
+ privacy: 'public',
62
+ };
63
+
64
+ const type = getType(property);
65
+ if (type) {
66
+ classMember.type = { text: type }
67
+ }
68
+
69
+ classMember = handleJsDoc(classMember, property);
70
+
71
+ const memberIndex = currClass?.members?.findIndex(field => field.name === classMember.name);
72
+ if (memberIndex >= 0) {
73
+ classMember = { ...classMember, ...currClass.members[memberIndex] };
74
+ }
75
+
76
+ if (isAlsoAttribute(property)) {
77
+ const attribute = createAttributeFromField(classMember);
78
+
79
+ /**
80
+ * If an attribute name is provided
81
+ * @example @property({attribute:'my-foo'})
82
+ */
83
+ const attributeName = getAttributeName(property);
84
+ if (attributeName) {
85
+ attribute.name = attributeName;
86
+ classMember.attribute = attributeName;
87
+ } else {
88
+ classMember.attribute = classMember.name;
89
+ }
90
+
91
+ if (reflects(property)) {
92
+ classMember.attribute = attribute.name;
93
+ classMember.reflects = true;
94
+ }
95
+
96
+ const attributeIndex = currClass?.attributes?.findIndex(
97
+ attr => attr.name === attribute.name,
98
+ );
99
+ if (attributeIndex >= 0) {
100
+ currClass.attributes[attributeIndex] = {
101
+ ...currClass.attributes[attributeIndex],
102
+ ...attribute,
103
+ };
104
+ } else {
105
+ currClass.attributes.push(attribute);
106
+ }
107
+ }
108
+
109
+ if (memberIndex >= 0) {
110
+ currClass.members[memberIndex] = classMember;
111
+ } else {
112
+ currClass.members.push(classMember);
113
+ }
114
+ });
115
+ return;
116
+ }
117
+ });
118
+
119
+ /** Get default values */
120
+ getDefaultValuesFromConstructorVisitor(classNode, currClass, context);
121
+ }
@@ -0,0 +1,66 @@
1
+ import ts from 'typescript';
2
+
3
+ export function isAlsoAttribute(node) {
4
+ let result = true;
5
+ (node?.initializer || node)?.properties?.forEach((property) => {
6
+ if (
7
+ property.name.text === 'attribute' &&
8
+ property.initializer.kind === ts.SyntaxKind.FalseKeyword
9
+ ) {
10
+ result = false;
11
+ }
12
+ });
13
+ return result;
14
+ }
15
+
16
+ export function reflects(node) {
17
+ let result = false;
18
+ (node?.initializer || node)?.properties?.forEach((property) => {
19
+ if (
20
+ property.name.text === 'reflect' &&
21
+ property.initializer.kind === ts.SyntaxKind.TrueKeyword
22
+ ) {
23
+ result = true;
24
+ }
25
+ });
26
+ return result;
27
+ }
28
+
29
+ export function getType(node) {
30
+ let result = false;
31
+ (node?.initializer || node)?.properties?.forEach((property) => {
32
+ if (property.name.text === 'type') {
33
+ result = property.initializer.text.toLowerCase();
34
+ }
35
+ });
36
+ return result;
37
+ }
38
+
39
+ export function getAttributeName(node) {
40
+ let result = false;
41
+ (node?.initializer || node)?.properties?.forEach((property) => {
42
+ if (
43
+ property.name.text === 'attribute' &&
44
+ property.initializer.kind === ts.SyntaxKind.StringLiteral
45
+ ) {
46
+ result = property.initializer.text;
47
+ }
48
+ });
49
+ return result;
50
+ }
51
+
52
+ export function hasPropertyDecorator(node) {
53
+ return node?.modifiers?.some((decorator) => {
54
+ return ts.isDecorator(decorator) && decorator?.expression?.expression?.getText() === 'property'
55
+ });
56
+ }
57
+
58
+ export const hasStaticKeyword = node => node?.modifiers?.some(mod => mod.kind === ts.SyntaxKind.StaticKeyword);
59
+
60
+ export function getPropertiesObject(node) {
61
+ if (ts.isGetAccessor(node)) {
62
+ return node.body?.statements?.find(ts.isReturnStatement)?.expression;
63
+ } else {
64
+ return node.initializer;
65
+ }
66
+ }
@@ -0,0 +1,129 @@
1
+ import { decorator, toKebabCase } from '../../../utils/index.js'
2
+
3
+ export function stencilPlugin() {
4
+ let events = [];
5
+
6
+ const METHOD_DENYLIST = ['componentWillLoad', 'componentDidLoad', 'componentShouldUpdate', 'componentWillRender', 'componentDidRender', 'componentWillUpdate', 'componentDidUpdate'];
7
+
8
+ return {
9
+ name: 'CORE - STENCIL',
10
+ // Runs for each module
11
+ analyzePhase({ts, node, moduleDoc}){
12
+ switch (node.kind) {
13
+ case ts.SyntaxKind.ClassDeclaration:
14
+ /**
15
+ * Add tagName to classDoc, extracted from `@Component({tag: 'foo-bar'})` decorator
16
+ * Add custom-element-definition to exports
17
+ */
18
+ const componentDecorator = node?.modifiers?.find(decorator('Component'))?.expression;
19
+
20
+ const tagName = componentDecorator?.arguments?.[0]?.properties?.find(prop => {
21
+ return prop?.name?.getText() === 'tag'
22
+ })?.initializer?.text;
23
+
24
+ const className = node?.name?.getText();
25
+ const currClass = moduleDoc?.declarations?.find(declaration => declaration.name === className);
26
+ if(tagName) {
27
+ currClass.tagName = tagName;
28
+ moduleDoc.exports.push({
29
+ kind: "custom-element-definition",
30
+ name: tagName,
31
+ declaration: {
32
+ name: className,
33
+ module: moduleDoc.path
34
+ }
35
+ });
36
+ }
37
+
38
+ /**
39
+ * Collect fields with `@Event()` decorator so we can process them in `moduleLinkPhase`
40
+ */
41
+ const eventFields = node?.members
42
+ ?.filter(member => member?.modifiers?.find(decorator('Event')))
43
+ ?.map(member => {
44
+ const eventDecorator = member?.modifiers?.find(decorator('Event'));
45
+ const eventName = eventDecorator?.expression?.arguments?.[0]?.properties?.find(prop => {
46
+ return prop?.name?.getText() === 'eventName'
47
+ })?.initializer?.text;
48
+
49
+ return { field: member?.name?.getText(), as: eventName || member?.name?.getText() }
50
+ });
51
+ events = [...(eventFields || [])];
52
+
53
+ /**
54
+ * Handle `@Prop` decorator, and store attributes to add to manifest later
55
+ * - if type is primitive -> create attr
56
+ * - if not `{ attribute: ''}` in decorator, just kebabcase the fieldname, otherwise use the value provided
57
+ * - if type is not primitive -> no attr
58
+ * - add fieldName to attr
59
+ */
60
+ node?.members
61
+ ?.filter(member => member?.modifiers?.find(decorator('Prop')))
62
+ ?.forEach(property => {
63
+ const fieldName = property?.name?.text;
64
+ const attrNameFromDecorator = property?.modifiers?.[0]?.expression?.arguments?.[0]?.properties?.find(prop => prop?.name?.getText() === 'attribute')?.initializer?.text;
65
+ const attrName = attrNameFromDecorator || toKebabCase(property?.name?.text);
66
+
67
+ const reflects = property?.modifiers?.[0]?.expression?.arguments?.[0]?.properties?.find(prop => prop?.name?.getText() === 'reflects')?.initializer?.getText?.() === 'true';
68
+ const member = currClass?.members?.find(mem => mem?.name === fieldName);
69
+ if(reflects) {
70
+ member.reflects = true;
71
+ member.attribute = attrName;
72
+ }
73
+
74
+ if(!currClass.attributes) currClass.attributes = [];
75
+ const hasType = !!property?.type?.getText?.();
76
+
77
+ currClass.attributes.push({
78
+ name: attrName,
79
+ fieldName,
80
+ ...(member?.default ? { default: member.default } : {}),
81
+ ...(member?.description ? { description: member.description } : {}),
82
+ ...(hasType ? {
83
+ type: { text: property?.type?.getText?.() }
84
+ } : {})
85
+ })
86
+ });
87
+
88
+ break;
89
+ }
90
+ },
91
+
92
+ // Runs for each module, after analyzing, all information about your module should now be available
93
+ moduleLinkPhase({moduleDoc}){
94
+ /**
95
+ * Remove lifecycle methods
96
+ */
97
+ const classes = moduleDoc?.declarations?.filter(declaration => declaration.kind === 'class');
98
+
99
+ classes?.forEach(klass => {
100
+ if(!klass?.members) return;
101
+ klass.members = klass?.members?.filter(member => {
102
+ return !METHOD_DENYLIST.includes(member.name)
103
+ });
104
+ });
105
+
106
+ /**
107
+ * Events
108
+ */
109
+ classes?.forEach(klass => {
110
+ if(!klass?.members) return;
111
+ const eventsAsFields = klass.members
112
+ ?.filter(member => events.some(event => event.field === member.name))
113
+ ?.map(member => {
114
+ delete member.privacy;
115
+ delete member.kind;
116
+ member.name = events.find(event => event.field === member.name).as;
117
+ return member;
118
+ }) || [];
119
+
120
+ /* Add events as eventDocs */
121
+ klass.events = [...(klass?.events || []), ...eventsAsFields]
122
+
123
+ /* Remove events as class fields */
124
+ klass.members = klass?.members?.filter(member => !events.some(event => event.field === member.name || event.as === member.name));
125
+ });
126
+
127
+ }
128
+ }
129
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * COLLECT
3
+ */
4
+ import { collectImportsPlugin } from './collect-phase/collect-imports.js';
5
+
6
+ /**
7
+ * ANALYSE
8
+ */
9
+ import { exportsPlugin } from './analyse-phase/exports.js';
10
+ import { customElementsDefineCallsPlugin } from './analyse-phase/custom-elements-define-calls.js';
11
+ import { functionLikePlugin } from './analyse-phase/function-like.js';
12
+ import { arrowFunctionPlugin } from './analyse-phase/arrow-function.js';
13
+ import { classPlugin } from './analyse-phase/classes.js';
14
+ import { mixinPlugin } from './analyse-phase/mixins.js';
15
+ import { variablePlugin } from './analyse-phase/variables.js';
16
+ import { classJsDocPlugin } from './analyse-phase/class-jsdoc.js';
17
+ import { reexportedWrappedMixinExportsPlugin } from './analyse-phase/reexported-wrapped-mixin-exports.js';
18
+
19
+ /**
20
+ * LINK
21
+ */
22
+ import { methodDenyListPlugin } from './link-phase/method-denylist.js';
23
+ import { fieldDenyListPlugin } from './link-phase/field-denylist.js';
24
+ import { cleanupClassesPlugin } from './link-phase/cleanup-classes.js';
25
+
26
+ /**
27
+ * POST-PROCESSING
28
+ */
29
+ import { removeUnexportedDeclarationsPlugin } from './post-processing/remove-unexported-declarations.js';
30
+ import { resolveInitializersPlugin } from './post-processing/resolve-initializers.js';
31
+ import { isCustomElementPlugin } from './post-processing/is-custom-element.js';
32
+ import { linkClassToTagnamePlugin } from './post-processing/link-class-to-tagname.js';
33
+ import { applyInheritancePlugin } from './post-processing/apply-inheritance.js';
34
+
35
+ /**
36
+ * FRAMEWORKS
37
+ */
38
+ import { stencilPlugin } from './framework-plugins/stencil/stencil.js';
39
+ import { catalystPlugin } from './framework-plugins/catalyst/catalyst.js';
40
+ import { catalystPlugin2 } from './framework-plugins/catalyst-major-2/catalyst.js';
41
+ import { fastPlugin } from './framework-plugins/fast/fast.js';
42
+ import { litPlugin } from './framework-plugins/lit/lit.js';
43
+
44
+ /**
45
+ * Establish the execution order of plugins
46
+ */
47
+ export const FEATURES = [
48
+ /** COLLECT */
49
+ collectImportsPlugin(),
50
+
51
+ /** ANALYSE */
52
+ exportsPlugin(),
53
+ customElementsDefineCallsPlugin(),
54
+ functionLikePlugin(),
55
+ arrowFunctionPlugin(),
56
+ classPlugin(),
57
+ mixinPlugin(),
58
+ variablePlugin(),
59
+ reexportedWrappedMixinExportsPlugin(),
60
+ classJsDocPlugin(),
61
+
62
+ /** LINK */
63
+ methodDenyListPlugin(),
64
+ fieldDenyListPlugin(),
65
+ cleanupClassesPlugin(),
66
+
67
+ /** POST-PROCESSING */
68
+ resolveInitializersPlugin(),
69
+ linkClassToTagnamePlugin(),
70
+ isCustomElementPlugin(),
71
+ applyInheritancePlugin(),
72
+ removeUnexportedDeclarationsPlugin(),
73
+
74
+ /** FRAMEWORKS */
75
+ // litPlugin()
76
+ // fastPlugin()
77
+ // stencilPlugin()
78
+ // catalystPlugin()
79
+ // catalystPlugin2()
80
+ ].flat();
@@ -0,0 +1,25 @@
1
+ import { has } from "../../utils/index.js"
2
+
3
+ /**
4
+ * CLEANUP-CLASSES
5
+ *
6
+ * Removes empty arrays from classes; e.g. if a class doesn't have any `members`,
7
+ * then we remove it from the class doc
8
+ */
9
+ export function cleanupClassesPlugin() {
10
+ return {
11
+ name: 'CORE - CLEANUP-CLASSES',
12
+ moduleLinkPhase({moduleDoc}){
13
+ const classes = moduleDoc?.declarations?.filter(declaration => declaration.kind === 'class' || declaration.kind === 'mixin');
14
+
15
+ classes?.forEach(klass => {
16
+ ['cssProperties', 'cssParts', 'slots', 'members', 'attributes', 'events', 'cssStates'].forEach(field => {
17
+ if(!has(klass[field])) {
18
+ delete klass[field];
19
+ }
20
+ });
21
+ });
22
+ },
23
+ }
24
+ }
25
+
@@ -0,0 +1,22 @@
1
+ /**
2
+ * FIELD-DENY-LIST
3
+ *
4
+ * Excludes fields from the manifest
5
+ */
6
+ export function fieldDenyListPlugin() {
7
+ const FIELD_DENY_LIST = [
8
+ 'observedAttributes',
9
+ ];
10
+
11
+ return {
12
+ name: 'CORE - FIELD-DENYLIST',
13
+ moduleLinkPhase({moduleDoc}){
14
+ const classes = moduleDoc?.declarations?.filter(declaration => declaration.kind === 'class' || declaration.kind === 'mixin');
15
+
16
+ classes?.forEach(klass => {
17
+ klass.members = klass?.members?.filter(member => !FIELD_DENY_LIST.includes(member.name));
18
+ });
19
+ },
20
+ }
21
+ }
22
+
@@ -0,0 +1,25 @@
1
+ /**
2
+ * METHOD-DENY-LIST
3
+ *
4
+ * Excludes methods from the manifest
5
+ */
6
+ export function methodDenyListPlugin() {
7
+ const METHOD_DENY_LIST = [
8
+ 'connectedCallback',
9
+ 'disconnectedCallback',
10
+ 'attributeChangedCallback',
11
+ 'adoptedCallback'
12
+ ];
13
+
14
+ return {
15
+ name: 'CORE - METHOD-DENYLIST',
16
+ moduleLinkPhase({moduleDoc}){
17
+ const classes = moduleDoc?.declarations?.filter(declaration => declaration.kind === 'class' || declaration.kind === 'mixin');
18
+
19
+ classes?.forEach(klass => {
20
+ klass.members = klass?.members?.filter(member => !METHOD_DENY_LIST.includes(member.name));
21
+ });
22
+ },
23
+ }
24
+ }
25
+
@@ -0,0 +1,78 @@
1
+ import { getAllDeclarationsOfKind, getModuleForClassLike, getModuleFromManifests, getInheritanceTree } from '../../utils/manifest-helpers.js';
2
+ import { resolveModuleOrPackageSpecifier } from '../../utils/index.js';
3
+
4
+ /**
5
+ * APPLY-INHERITANCE-PLUGIN
6
+ *
7
+ * Applies inheritance for all classes in the manifest
8
+ */
9
+ export function applyInheritancePlugin() {
10
+ return {
11
+ name: 'CORE - APPLY-INHERITANCE',
12
+ packageLinkPhase({customElementsManifest, context}){
13
+ const allManifests = [customElementsManifest, ...(context.thirdPartyCEMs || [])];
14
+ const classLikes = [];
15
+
16
+ allManifests.forEach((manifest) => {
17
+ const classes = getAllDeclarationsOfKind(manifest, 'class');
18
+ const mixins = getAllDeclarationsOfKind(manifest, 'mixin');
19
+ classLikes.push(...[...classes, ...mixins]);
20
+ });
21
+
22
+ classLikes.forEach((customElement) => {
23
+ const inheritanceChain = getInheritanceTree(allManifests, customElement.name);
24
+
25
+ inheritanceChain?.forEach(klass => {
26
+ // ignore the current class itself
27
+ if (klass?.name === customElement.name) {
28
+ return;
29
+ }
30
+
31
+ ['slots', 'cssParts', 'cssProperties', 'attributes', 'members', 'events', 'cssStates'].forEach(type => {
32
+ klass?.[type]?.forEach(currItem => {
33
+ const containingModulePath = getModuleForClassLike(allManifests, klass.name);
34
+ const containingModule = getModuleFromManifests(allManifests, containingModulePath);
35
+
36
+ const newItem = { ...currItem };
37
+
38
+ /**
39
+ * If an attr or member is already present in the base class, but we encounter it here,
40
+ * it means that the base has overridden that method from the super class
41
+ * So we either add the data to the overridden method, or we add it to the array as a new item
42
+ */
43
+ const existing = customElement?.[type]?.find(item => newItem.name === item.name);
44
+
45
+ if (existing) {
46
+
47
+ existing.inheritedFrom = {
48
+ name: klass.name,
49
+ ...resolveModuleOrPackageSpecifier(containingModule, context, klass.name)
50
+ }
51
+
52
+ customElement[type] = customElement?.[type]?.map(item => item.name === existing.name
53
+ ? {
54
+ ...newItem,
55
+ ...existing,
56
+ // Patch: Custom patch to not merge child parent privacy/type
57
+ // https://github.com/open-wc/custom-elements-manifest/pull/300
58
+ // ...{
59
+ // ...(newItem.type ? { type: newItem.type } : {}),
60
+ // ...(newItem.privacy ? { privacy: newItem.privacy } : {})
61
+ // }
62
+ }
63
+ : item);
64
+ } else {
65
+ newItem.inheritedFrom = {
66
+ name: klass.name,
67
+ ...resolveModuleOrPackageSpecifier(containingModule, context, klass.name)
68
+ }
69
+
70
+ customElement[type] = [...(customElement[type] || []), newItem];
71
+ };
72
+ });
73
+ });
74
+ });
75
+ });
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,34 @@
1
+ const BASECLASSES = [
2
+ 'htmlelement',
3
+ 'litelement',
4
+ 'fastelement'
5
+ ];
6
+
7
+ /**
8
+ * ISCUSTOMELEMENT
9
+ *
10
+ * Heuristic to see whether or not a class is a custom element
11
+ */
12
+ export function isCustomElementPlugin() {
13
+ return {
14
+ name: 'CORE - IS-CUSTOM-ELEMENT',
15
+ packageLinkPhase({customElementsManifest, context}) {
16
+ customElementsManifest?.modules?.forEach(_module => {
17
+ _module?.declarations?.forEach(declaration => {
18
+ if(declaration?.kind === 'class') {
19
+ /** If a class has a tagName, that means its been defined, and is a custom element */
20
+ if(declaration?.tagName) {
21
+ declaration.customElement = true;
22
+ }
23
+
24
+ /** If a class extends from any of these, its a custom element */
25
+ if(BASECLASSES.includes(declaration?.superclass?.name?.toLowerCase())) {
26
+ declaration.customElement = true;
27
+ }
28
+ }
29
+ });
30
+ });
31
+ }
32
+ }
33
+ }
34
+
@@ -0,0 +1,27 @@
1
+ import { getAllDeclarationsOfKind, getAllExportsOfKind } from '../../utils/manifest-helpers.js';
2
+
3
+ /**
4
+ * LINK-CLASS-TO-TAGNAME
5
+ *
6
+ * Links a custom element definition to its corresponding class
7
+ */
8
+ export function linkClassToTagnamePlugin() {
9
+ return {
10
+ name: 'CORE - LINK-CLASS-TO-TAGNAME',
11
+ packageLinkPhase({customElementsManifest, context}){
12
+ /* Get all class declarations and custom element definitions in the manifest */
13
+ const classes = getAllDeclarationsOfKind(customElementsManifest, 'class');
14
+ const definitions = getAllExportsOfKind(customElementsManifest, 'custom-element-definition');
15
+
16
+ /* Loop through all classes, and try to find their corresponding custom element definition */
17
+ classes?.forEach((klass) => {
18
+ const tagName = definitions?.find(def => def?.declaration?.name === klass?.name)?.name;
19
+
20
+ /* If there's a match, we can link the custom element definition to the class */
21
+ if (tagName && !klass.tagName) {
22
+ klass.tagName = tagName;
23
+ }
24
+ });
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,23 @@
1
+ import { has } from '../../utils/index.js';
2
+
3
+ /**
4
+ * REMOVE-UNEXPORTED-DECLARATIONS
5
+ *
6
+ * If a module has declarations that are _not_ exported, that means those declarations are considered 'private' to that module, and they shouldnt be present in the manifest, so we remove them.
7
+ */
8
+ export function removeUnexportedDeclarationsPlugin() {
9
+ return {
10
+ name: 'CORE - REMOVE-UNEXPORTED-DECLARATIONS',
11
+ packageLinkPhase({customElementsManifest}){
12
+ customElementsManifest?.modules?.forEach(mod => {
13
+ if(has(mod?.declarations)) {
14
+ mod.declarations = mod?.declarations?.filter(declaration => {
15
+ return mod?.exports?.some(_export => {
16
+ return declaration?.name === _export?.name || declaration?.name === _export?.declaration?.name;
17
+ });
18
+ });
19
+ }
20
+ });
21
+ },
22
+ }
23
+ }