@ui5/webcomponents-tools 0.0.0-07d38e78e → 0.0.0-093de5dd1

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 (105) hide show
  1. package/CHANGELOG.md +1030 -0
  2. package/LICENSE.txt +201 -0
  3. package/README.md +7 -10
  4. package/assets-meta.js +1 -5
  5. package/bin/dev.js +3 -2
  6. package/bin/ui5nps.js +274 -0
  7. package/components-package/eslint.js +59 -31
  8. package/components-package/nps.js +98 -75
  9. package/components-package/vite.config.js +7 -11
  10. package/components-package/wdio.js +12 -5
  11. package/icons-collection/nps.js +30 -21
  12. package/lib/amd-to-es6/index.js +15 -10
  13. package/lib/cem/cem.js +12 -0
  14. package/lib/cem/custom-elements-manifest.config.mjs +90 -45
  15. package/lib/cem/event.mjs +69 -32
  16. package/lib/cem/merge.mjs +220 -0
  17. package/lib/cem/patch/@custom-elements-manifest/analyzer/cli.js +128 -0
  18. package/lib/cem/patch/@custom-elements-manifest/analyzer/package.json +59 -0
  19. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/browser-entrypoint.js +23 -0
  20. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/create.js +117 -0
  21. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/arrow-function.js +26 -0
  22. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/class-jsdoc.js +157 -0
  23. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/classes.js +20 -0
  24. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createArrowFunction.js +17 -0
  25. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createAttribute.js +24 -0
  26. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClass.js +301 -0
  27. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createClassField.js +26 -0
  28. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createFunctionLike.js +73 -0
  29. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createMixin.js +33 -0
  30. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/createVariable.js +22 -0
  31. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/creators/handlers.js +338 -0
  32. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/custom-elements-define-calls.js +90 -0
  33. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/exports.js +156 -0
  34. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/function-like.js +24 -0
  35. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/mixins.js +29 -0
  36. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/reexported-wrapped-mixin-exports.js +84 -0
  37. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/analyse-phase/variables.js +34 -0
  38. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/collect-phase/collect-imports.js +101 -0
  39. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/catalyst.js +11 -0
  40. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst/controller.js +34 -0
  41. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/catalyst.js +11 -0
  42. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/catalyst-major-2/controller.js +34 -0
  43. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/attr.js +53 -0
  44. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/decorators/custom-element-decorator.js +36 -0
  45. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/fast/fast.js +7 -0
  46. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/lit.js +13 -0
  47. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/member-denylist.js +21 -0
  48. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/method-denylist.js +20 -0
  49. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/property-decorator.js +94 -0
  50. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/static-properties.js +121 -0
  51. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/utils.js +66 -0
  52. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/framework-plugins/stencil/stencil.js +129 -0
  53. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/index.js +80 -0
  54. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/cleanup-classes.js +25 -0
  55. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/field-denylist.js +22 -0
  56. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/link-phase/method-denylist.js +25 -0
  57. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/apply-inheritance.js +78 -0
  58. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/is-custom-element.js +34 -0
  59. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/link-class-to-tagname.js +27 -0
  60. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/remove-unexported-declarations.js +23 -0
  61. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/features/post-processing/resolve-initializers.js +52 -0
  62. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/ast-helpers.js +186 -0
  63. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/cli-helpers.js +164 -0
  64. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/exports.js +44 -0
  65. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/find-external-manifests.js +67 -0
  66. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/imports.js +25 -0
  67. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/index.js +71 -0
  68. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/jsdoc.js +19 -0
  69. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/manifest-helpers.js +194 -0
  70. package/lib/cem/patch/@custom-elements-manifest/analyzer/src/utils/mixins.js +112 -0
  71. package/lib/cem/schema-internal.json +65 -0
  72. package/lib/cem/types-internal.d.ts +14 -2
  73. package/lib/cem/utils.mjs +69 -30
  74. package/lib/cem/validate.js +61 -55
  75. package/lib/chokidar/chokidar.js +28 -0
  76. package/lib/copy-and-watch/index.js +105 -97
  77. package/lib/copy-list/index.js +16 -10
  78. package/lib/create-icons/index.js +24 -19
  79. package/lib/create-illustrations/index.js +49 -27
  80. package/lib/create-new-component/{tsFileContentTemplate.js → Component.js} +12 -9
  81. package/lib/create-new-component/ComponentTemplate.js +12 -0
  82. package/lib/create-new-component/index.js +13 -12
  83. package/lib/css-processors/css-processor-components.mjs +74 -59
  84. package/lib/css-processors/css-processor-themes.mjs +85 -62
  85. package/lib/css-processors/shared.mjs +5 -35
  86. package/lib/dev-server/{dev-server.js → dev-server.mjs} +26 -14
  87. package/lib/dev-server/virtual-index-html-plugin.js +24 -20
  88. package/lib/eslint/eslint.js +44 -0
  89. package/lib/generate-js-imports/illustrations.js +53 -54
  90. package/lib/generate-json-imports/i18n.js +56 -36
  91. package/lib/generate-json-imports/themes.js +27 -14
  92. package/lib/hbs2ui5/RenderTemplates/LitRenderer.js +12 -7
  93. package/lib/hbs2ui5/index.js +3 -3
  94. package/lib/i18n/defaults.js +15 -9
  95. package/lib/i18n/toJSON.js +38 -12
  96. package/lib/icons-hash/icons-hash.mjs +149 -0
  97. package/lib/remove-dev-mode/remove-dev-mode.mjs +38 -24
  98. package/lib/rimraf/rimraf.js +31 -0
  99. package/lib/scoping/get-all-tags.js +9 -2
  100. package/lib/test-runner/test-runner.js +56 -48
  101. package/lib/vite-bundler/vite-bundler.mjs +35 -0
  102. package/package.json +22 -19
  103. package/tsconfig.json +18 -0
  104. package/lib/css-processors/css-processor-component-styles.mjs +0 -48
  105. package/lib/dev-server/ssr-dom-shim-loader.js +0 -26
@@ -0,0 +1,194 @@
1
+ /**
2
+ * UTILITIES RELATED TO GETTING INFORMATION OUT OF A MANIFEST OR DOC
3
+ */
4
+
5
+ import { has } from "./index.js";
6
+
7
+ /**
8
+ * @typedef {import('custom-elements-manifest/schema').Package} Package
9
+ */
10
+
11
+ function loopThroughDeclarations(manifest, predicate) {
12
+ manifest?.modules?.forEach(_module => {
13
+ _module?.declarations?.forEach(predicate);
14
+ });
15
+ }
16
+
17
+ function loopThroughExports(manifest, predicate) {
18
+ manifest?.modules?.forEach(_module => {
19
+ _module?.exports?.forEach(predicate);
20
+ });
21
+ }
22
+
23
+ /**
24
+ * Loops through all modules' exports, and returns the kind provided by the users
25
+ *
26
+ * @example getKind('class');
27
+ * @example getKind('custom-element-definition');
28
+ */
29
+ export function getAllExportsOfKind(manifest, kind) {
30
+ const result = [];
31
+ loopThroughExports(manifest, (_export) => {
32
+ if(_export.kind === kind) {
33
+ result.push(_export);
34
+ }
35
+ });
36
+ return result;
37
+ }
38
+
39
+
40
+ /**
41
+ * Loops through all modules' declarations, and returns the kind provided by the users
42
+ *
43
+ * @example getKind('class');
44
+ * @example getKind('custom-element-definition');
45
+ */
46
+ export function getAllDeclarationsOfKind(manifest, kind) {
47
+ const result = [];
48
+ loopThroughDeclarations(manifest, (declaration) => {
49
+ if(declaration.kind === kind) {
50
+ result.push(declaration);
51
+ }
52
+ });
53
+ return result;
54
+ }
55
+
56
+ /**
57
+ * Gets the inheritance tree from a manifest given a className
58
+ * Returns an array of a classes mixins/superclasses all the way up the chain
59
+ *
60
+ * @param {Package[]} manifests
61
+ * @param {string} className
62
+ */
63
+ export function getInheritanceTree(manifests, className) {
64
+ const tree = [];
65
+ const allClassLikes = new Map();
66
+ const _classes = [];
67
+ const _mixins = [];
68
+
69
+ manifests.forEach((cem) => {
70
+ _classes.push(...getAllDeclarationsOfKind(cem, 'class'));
71
+ _mixins.push(...getAllDeclarationsOfKind(cem, 'mixin'));
72
+ });
73
+
74
+ [..._mixins, ..._classes].forEach((klass) => {
75
+ allClassLikes.set(klass.name, klass);
76
+ });
77
+
78
+ let klass = allClassLikes.get(className)
79
+
80
+ if(klass) {
81
+ tree.push(klass)
82
+
83
+ klass?.mixins?.forEach(mixin => {
84
+ let foundMixin = _mixins.find(m => m.name === mixin.name);
85
+ if(foundMixin) {
86
+ tree.push(foundMixin);
87
+
88
+ while(has(foundMixin?.mixins)) {
89
+ foundMixin?.mixins?.forEach(mixin => {
90
+ foundMixin = _mixins.find(m => m.name === mixin.name);
91
+ if(foundMixin) {
92
+ tree.push(foundMixin);
93
+ }
94
+ });
95
+ }
96
+ }
97
+ });
98
+
99
+ while(allClassLikes.has(klass.superclass?.name)) {
100
+ const newKlass = allClassLikes.get(klass.superclass.name);
101
+ let allMixins = [];
102
+ if (klass?.mixins) {
103
+ allMixins = [...klass.mixins];
104
+ }
105
+ if (newKlass?.mixins) {
106
+ allMixins = [...allMixins, ...newKlass.mixins];
107
+ }
108
+
109
+ allMixins.forEach(mixin => {
110
+ let foundMixin = _mixins.find(m => m.name === mixin.name);
111
+ if(foundMixin) {
112
+ tree.push(foundMixin);
113
+
114
+ while(has(foundMixin?.mixins)) {
115
+ foundMixin?.mixins?.forEach(mixin => {
116
+ foundMixin = _mixins.find(m => m.name === mixin.name);
117
+ if(foundMixin) {
118
+ tree.push(foundMixin);
119
+ }
120
+ });
121
+ }
122
+ }
123
+ });
124
+
125
+ tree.push(newKlass);
126
+ klass = newKlass;
127
+ }
128
+ return tree;
129
+ }
130
+ return [];
131
+ }
132
+
133
+ /**
134
+ * @param {Package[]} manifests
135
+ * @param {string} modulePath
136
+ */
137
+ export function getModuleFromManifests(manifests, modulePath) {
138
+ let result = undefined;
139
+
140
+ manifests.forEach((cem) => {
141
+ cem?.modules?.forEach((_module) => {
142
+ if (_module.path === modulePath) {
143
+ result = _module;
144
+ }
145
+ });
146
+ });
147
+
148
+ return result;
149
+ }
150
+
151
+ /**
152
+ * @param {Package[]} manifests
153
+ * @param {string} className
154
+ */
155
+ export function getModuleForClassLike(manifests, className) {
156
+ let result = undefined;
157
+
158
+ manifests.forEach((cem) => {
159
+ cem?.modules?.forEach(_module => {
160
+ _module?.declarations?.forEach(declaration => {
161
+ if((declaration.kind === 'class' || declaration.kind === 'mixin') && declaration.name === className) {
162
+ result = _module.path;
163
+ }
164
+ });
165
+ });
166
+ });
167
+
168
+ return result;
169
+ }
170
+
171
+ /**
172
+ * Given a manifest module, a class name, and a class member name, gets the
173
+ * manifest doc for the module's class' member.
174
+ *
175
+ * @param {Partial<import('custom-elements-manifest/schema').Module>} moduleDoc Manifest module
176
+ * @param {string} className Class to get member of
177
+ * @param {string} memberName Class member to get
178
+ * @param {boolean} isStatic Is it a static member?
179
+ * @return {import('custom-elements-manifest/schema').ClassMember|void} the requested class member
180
+ */
181
+ export function getClassMemberDoc(moduleDoc, className, memberName, isStatic = false) {
182
+ /** @type {import('custom-elements-manifest/schema').ClassDeclaration} */
183
+ const classDoc = (moduleDoc.declarations.find(x => x.name === className));
184
+
185
+ if (!classDoc || !has(classDoc.members))
186
+ return;
187
+
188
+ const memberDoc = classDoc.members.find(x =>
189
+ x.name === memberName &&
190
+ (x.static ?? false) === isStatic
191
+ );
192
+
193
+ return memberDoc;
194
+ }
@@ -0,0 +1,112 @@
1
+ import ts from 'typescript';
2
+
3
+ import { getReturnValue } from '../utils/ast-helpers.js';
4
+
5
+ export const isMixin = node => !!extractMixinNodes(node);
6
+
7
+ export function extractMixinNodes(node) {
8
+ if (ts.isVariableStatement(node) || ts.isFunctionDeclaration(node)) {
9
+ if (ts.isVariableStatement(node)) {
10
+ /**
11
+ * @example const MyMixin = klass => class MyMixin extends klass {}
12
+ * @example export const MyMixin = klass => class MyMixin extends klass {}
13
+ */
14
+ const variableDeclaration = node.declarationList.declarations.find(declaration =>
15
+ ts.isVariableDeclaration(declaration),
16
+ );
17
+ if (variableDeclaration) {
18
+ const body = variableDeclaration?.initializer?.body;
19
+ if (body && ts.isClassExpression(body)) {
20
+ return {
21
+ mixinFunction: node,
22
+ mixinClass: body,
23
+ };
24
+ }
25
+
26
+ /**
27
+ * @example const MyMixin = klass => { return class MyMixin extends Klass{} }
28
+ */
29
+ if (body && ts.isBlock(body)) {
30
+ const returnStatement = body.statements.find(statement => ts.isReturnStatement(statement));
31
+
32
+ if (returnStatement && returnStatement?.expression?.kind && ts.isClassExpression(returnStatement.expression)) {
33
+ return {
34
+ mixinFunction: variableDeclaration.initializer,
35
+ mixinClass: returnStatement.expression
36
+ };
37
+ }
38
+ }
39
+
40
+ /**
41
+ * @example const MyMixin = klass => { class MyMixin extends klass {} return MyMixin;}
42
+ */
43
+ if (body && ts.isBlock(body)) {
44
+ const classDeclaration = body.statements.find(statement => ts.isClassDeclaration(statement));
45
+ const returnStatement = body.statements.find(statement => ts.isReturnStatement(statement));
46
+ /** Avoid undefined === undefined */
47
+ if(!(classDeclaration && returnStatement))
48
+ return;
49
+ const classDeclarationName = classDeclaration.name?.getText?.();
50
+ const returnValue = getReturnValue(returnStatement)
51
+ /**
52
+ * If the classDeclaration inside the function body has the same name as whats being
53
+ * returned from the function, consider it a mixin
54
+ */
55
+ if (classDeclarationName === returnValue) {
56
+ return {
57
+ mixinFunction: node,
58
+ mixinClass: classDeclaration
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+
65
+ /**
66
+ * @example function MyMixin(klass) { return class MyMixin extends Klass{} }
67
+ */
68
+ if (ts.isFunctionDeclaration(node)) {
69
+ if (node.body && ts.isBlock(node.body)) {
70
+
71
+ const returnStatement = node.body.statements.find(statement => ts.isReturnStatement(statement));
72
+
73
+ if (returnStatement?.expression && ts.isClassExpression(returnStatement.expression)) {
74
+ return {
75
+ mixinFunction: node,
76
+ mixinClass: returnStatement.expression
77
+ };
78
+ }
79
+ }
80
+ }
81
+
82
+ /**
83
+ * @example function MyMixin(klass) {class A extends klass {} return A;}
84
+ */
85
+ if (ts.isFunctionDeclaration(node)) {
86
+ if (node.body && ts.isBlock(node.body)) {
87
+ const classDeclaration = node.body.statements.find(statement => ts.isClassDeclaration(statement));
88
+ const returnStatement = node.body.statements.find(statement => ts.isReturnStatement(statement));
89
+
90
+ /** Avoid undefined === undefined */
91
+ if(!(classDeclaration && returnStatement))
92
+ return;
93
+
94
+ const classDeclarationName = classDeclaration.name?.getText?.();
95
+
96
+ const returnValue = getReturnValue(returnStatement)
97
+
98
+ /**
99
+ * If the classDeclaration inside the function body has the same name as whats being
100
+ * returned from the function, consider it a mixin
101
+ */
102
+ if (classDeclarationName === returnValue) {
103
+ return {
104
+ mixinFunction: node,
105
+ mixinClass: classDeclaration
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ return false;
112
+ }
@@ -46,6 +46,12 @@
46
46
  "ClassDeclaration": {
47
47
  "additionalProperties": false,
48
48
  "properties": {
49
+ "_ui5experimental": {
50
+ "type": [
51
+ "string",
52
+ "boolean"
53
+ ]
54
+ },
49
55
  "_ui5package": {
50
56
  "type": "string"
51
57
  },
@@ -123,6 +129,12 @@
123
129
  "EnumDeclaration": {
124
130
  "additionalProperties": false,
125
131
  "properties": {
132
+ "_ui5experimental": {
133
+ "type": [
134
+ "string",
135
+ "boolean"
136
+ ]
137
+ },
126
138
  "_ui5package": {
127
139
  "type": "string"
128
140
  },
@@ -187,6 +199,12 @@
187
199
  "InterfaceDeclaration": {
188
200
  "additionalProperties": false,
189
201
  "properties": {
202
+ "_ui5experimental": {
203
+ "type": [
204
+ "string",
205
+ "boolean"
206
+ ]
207
+ },
190
208
  "_ui5package": {
191
209
  "type": "string"
192
210
  },
@@ -389,6 +407,9 @@
389
407
  "CssCustomProperty": {
390
408
  "additionalProperties": false,
391
409
  "properties": {
410
+ "inheritedFrom": {
411
+ "$ref": "#/definitions/Reference"
412
+ },
392
413
  "default": {
393
414
  "type": "string"
394
415
  },
@@ -425,6 +446,9 @@
425
446
  "additionalProperties": false,
426
447
  "description": "The description of a CSS Part",
427
448
  "properties": {
449
+ "inheritedFrom": {
450
+ "$ref": "#/definitions/Reference"
451
+ },
428
452
  "deprecated": {
429
453
  "description": "Whether the CSS shadow part is deprecated.\nIf the value is a string, it's the reason for the deprecation.",
430
454
  "type": [
@@ -453,6 +477,12 @@
453
477
  "additionalProperties": false,
454
478
  "description": "A description of a custom element class.\n\nCustom elements are JavaScript classes, so this extends from\n`ClassDeclaration` and adds custom-element-specific features like\nattributes, events, and slots.\n\nNote that `tagName` in this interface is optional. Tag names are not\nneccessarily part of a custom element class, but belong to the definition\n(often called the \"registration\") or the `customElements.define()` call.\n\nBecause classes and tag names can only be registered once, there's a\none-to-one relationship between classes and tag names. For ease of use,\nwe allow the tag name here.\n\nSome packages define and register custom elements in separate modules. In\nthese cases one `Module` should contain the `CustomElement` without a\ntagName, and another `Module` should contain the\n`CustomElementExport`.",
455
479
  "properties": {
480
+ "_ui5experimental": {
481
+ "type": [
482
+ "string",
483
+ "boolean"
484
+ ]
485
+ },
456
486
  "_ui5package": {
457
487
  "type": "string"
458
488
  },
@@ -618,6 +648,12 @@
618
648
  "additionalProperties": false,
619
649
  "description": "A class mixin that also adds custom element related properties.",
620
650
  "properties": {
651
+ "_ui5experimental": {
652
+ "type": [
653
+ "string",
654
+ "boolean"
655
+ ]
656
+ },
621
657
  "_ui5package": {
622
658
  "type": "string"
623
659
  },
@@ -788,6 +824,14 @@
788
824
  "description": "Whether the parameter is optional. Undefined implies non-optional.",
789
825
  "type": "boolean"
790
826
  },
827
+ "_ui5Cancelable": {
828
+ "description": "Whether the event is cancelable or not.",
829
+ "type": "boolean"
830
+ },
831
+ "_ui5Bubbles": {
832
+ "description": "Whether the event bubbles or not.",
833
+ "type": "boolean"
834
+ },
791
835
  "_ui5since": {
792
836
  "description": "Marks when the field was introduced",
793
837
  "type": "string"
@@ -827,6 +871,12 @@
827
871
  "FunctionDeclaration": {
828
872
  "additionalProperties": false,
829
873
  "properties": {
874
+ "_ui5experimental": {
875
+ "type": [
876
+ "string",
877
+ "boolean"
878
+ ]
879
+ },
830
880
  "_ui5package": {
831
881
  "type": "string"
832
882
  },
@@ -1007,6 +1057,12 @@
1007
1057
  "additionalProperties": false,
1008
1058
  "description": "A description of a class mixin.\n\nMixins are functions which generate a new subclass of a given superclass.\nThis interfaces describes the class and custom element features that\nare added by the mixin. As such, it extends the CustomElement interface and\nClassLike interface.\n\nSince mixins are functions, it also extends the FunctionLike interface. This\nmeans a mixin is callable, and has parameters and a return type.\n\nThe return type is often hard or impossible to accurately describe in type\nsystems like TypeScript. It requires generics and an `extends` operator\nthat TypeScript lacks. Therefore it's recommended that the return type is\nleft empty. The most common form of a mixin function takes a single\nargument, so consumers of this interface should assume that the return type\nis the single argument subclassed by this declaration.\n\nA mixin should not have a superclass. If a mixins composes other mixins,\nthey should be listed in the `mixins` field.\n\nSee [this article]{@link https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/}\nfor more information on the classmixin pattern in JavaScript.",
1009
1059
  "properties": {
1060
+ "_ui5experimental": {
1061
+ "type": [
1062
+ "string",
1063
+ "boolean"
1064
+ ]
1065
+ },
1010
1066
  "_ui5package": {
1011
1067
  "type": "string"
1012
1068
  },
@@ -1172,6 +1228,9 @@
1172
1228
  "Slot": {
1173
1229
  "additionalProperties": false,
1174
1230
  "properties": {
1231
+ "inheritedFrom": {
1232
+ "$ref": "#/definitions/Reference"
1233
+ },
1175
1234
  "_ui5propertyName": {
1176
1235
  "type": "string"
1177
1236
  },
@@ -1275,6 +1334,12 @@
1275
1334
  "VariableDeclaration": {
1276
1335
  "additionalProperties": false,
1277
1336
  "properties": {
1337
+ "_ui5experimental": {
1338
+ "type": [
1339
+ "string",
1340
+ "boolean"
1341
+ ]
1342
+ },
1278
1343
  "_ui5package": {
1279
1344
  "type": "string"
1280
1345
  },
@@ -319,9 +319,20 @@ export interface Event {
319
319
  _ui5parameters?: Parameter[]
320
320
  _ui5privacy?: Privacy
321
321
  /**
322
- * Whether the parameter is optional. Undefined implies non-optional.
322
+ * Whether the event is preventable.
323
+ */
324
+ _ui5allowPreventDefault?: boolean;
325
+
326
+ /**
327
+ * Whether the event is cancelable.
323
328
  */
324
- _ui5allowPreventDefault?: boolean
329
+ _ui5Cancelable?: boolean;
330
+
331
+ /**
332
+ * Whether the event is bubbles.
333
+ */
334
+ _ui5Bubbles?: boolean;
335
+
325
336
  /**
326
337
  * Marks when the field was introduced
327
338
  */
@@ -484,6 +495,7 @@ export interface TypeReference extends Reference {
484
495
  * The common interface of classes and mixins.
485
496
  */
486
497
  export interface ClassLike {
498
+ _ui5experimental?: boolean | string
487
499
  _ui5implements?: Reference[]
488
500
  _ui5privacy?: Privacy
489
501
  /**
package/lib/cem/utils.mjs CHANGED
@@ -3,6 +3,8 @@ import path from "path";
3
3
 
4
4
  let documentationErrors = new Map();
5
5
 
6
+ const packageRegex = /^((@([a-z0-9._-]+)\/)?([a-z0-9._-]+))/;
7
+
6
8
  const getDeprecatedStatus = (jsdocComment) => {
7
9
  const deprecatedTag = findTag(jsdocComment, "deprecated");
8
10
  return deprecatedTag?.name
@@ -14,12 +16,23 @@ const getDeprecatedStatus = (jsdocComment) => {
14
16
  : undefined;
15
17
  };
16
18
 
19
+ const getExperimentalStatus = (jsdocComment) => {
20
+ const experimentalTag = findTag(jsdocComment, "experimental");
21
+ return experimentalTag?.name
22
+ ? experimentalTag.description
23
+ ? `${experimentalTag.name} ${experimentalTag.description}`
24
+ : experimentalTag.name
25
+ : experimentalTag
26
+ ? true
27
+ : undefined;
28
+ };
29
+
17
30
  const toKebabCase = str => {
18
31
  return str.replaceAll(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? "-" : "") + $.toLowerCase())
19
32
  }
20
33
 
21
34
  const normalizeDescription = (description) => {
22
- return typeof description === 'string' ? description.replaceAll(/^-\s+|^(\n)+|(\n)+$/g, ""): description;
35
+ return typeof description === 'string' ? description.replaceAll(/^-\s+|^(\n)+|(\n)+$/g, "") : description;
23
36
  }
24
37
 
25
38
  const getTypeRefs = (ts, node, member) => {
@@ -100,10 +113,22 @@ const findPackageName = (ts, sourceFile, typeName) => {
100
113
  if (currentModuleSpecifier?.text?.startsWith(".")) {
101
114
  return packageJSON?.name;
102
115
  } else {
103
- return Object.keys(packageJSON?.dependencies || {}).find(
104
- (dependency) =>
105
- currentModuleSpecifier?.text?.startsWith(`${dependency}/`)
106
- );
116
+ // my-package/test
117
+ // my-package
118
+ // @scope/my-package
119
+ // my.package
120
+ // _mypackage
121
+ // mypackage-
122
+ // scope/my-package/test
123
+ // @scope/my-package/test
124
+ const match = currentModuleSpecifier?.text.match(packageRegex);
125
+ let packageName;
126
+
127
+ if (match) {
128
+ packageName = match[1];
129
+ }
130
+
131
+ return packageName || undefined;
107
132
  }
108
133
  }
109
134
  };
@@ -145,23 +170,24 @@ const findImportPath = (ts, sourceFile, typeName, modulePath) => {
145
170
  ?.replace("src", "dist")?.replace(".ts", ".js") || undefined
146
171
  );
147
172
  } else {
148
- const packageName = Object.keys(packageJSON?.dependencies || {}).find(
149
- (dependency) =>
150
- currentModuleSpecifier?.text?.startsWith(dependency)
151
- );
152
- return currentModuleSpecifier?.text
153
- ?.replace(`${packageName}/`, "") || undefined;
173
+ let packageName = currentModuleSpecifier?.text?.replace(packageRegex, "") || undefined;
174
+
175
+ if (packageName?.startsWith("/")) {
176
+ packageName = packageName.replace("/", "");
177
+ }
178
+
179
+ return packageName;
154
180
  }
155
181
  }
156
182
  };
157
183
 
158
184
 
159
185
  const isClass = text => {
160
- return text.includes("@abstract") || text.includes("@class") || text.includes("@constructor");
186
+ return text.includes("@abstract") || text.includes("@class") || text.includes("@constructor");
161
187
  };
162
188
 
163
189
  const normalizeTagType = (type) => {
164
- return type?.trim();
190
+ return type?.trim();
165
191
  }
166
192
 
167
193
  const packageJSON = JSON.parse(fs.readFileSync("./package.json"));
@@ -211,13 +237,13 @@ const commonTags = ["public", "protected", "private", "since", "deprecated"];
211
237
  const allowedTags = {
212
238
  field: [...commonTags, "formEvents", "formProperty", "default"],
213
239
  slot: [...commonTags, "default"],
214
- event: [...commonTags, "param", "allowPreventDefault", "native"],
240
+ event: [...commonTags, "param", "native", "allowPreventDefault"],
215
241
  eventParam: [...commonTags],
216
242
  method: [...commonTags, "param", "returns", "override"],
217
- class: [...commonTags, "constructor", "class", "abstract", "implements", "extends", "slot", "csspart"],
218
- enum: [...commonTags],
219
- enumMember: [...commonTags],
220
- interface: [...commonTags],
243
+ class: [...commonTags, "constructor", "class", "abstract", "experimental", "implements", "extends", "slot", "csspart"],
244
+ enum: [...commonTags, "experimental",],
245
+ enumMember: [...commonTags, "experimental",],
246
+ interface: [...commonTags, "experimental",],
221
247
  };
222
248
  allowedTags.getter = [...allowedTags.field, "override"]
223
249
 
@@ -230,19 +256,29 @@ const tagMatchCallback = (tag, tagName) => {
230
256
  };
231
257
 
232
258
  const findDecorator = (node, decoratorName) => {
233
- return node?.decorators?.find(
259
+ return (node?.modifiers || node?.decorators)?.find(
234
260
  (decorator) =>
235
261
  decorator?.expression?.expression?.text === decoratorName
236
262
  );
237
263
  };
238
264
 
239
265
  const findAllDecorators = (node, decoratorName) => {
240
- return (
241
- node?.decorators?.filter(
242
- (decorator) =>
243
- decorator?.expression?.expression?.text === decoratorName
244
- ) || []
245
- );
266
+ if (typeof decoratorName === "string") {
267
+ return (node?.modifiers || node?.decorators)?.filter(decorator => decorator?.expression?.expression?.text === decoratorName) || [];
268
+ }
269
+
270
+ if (Array.isArray(decoratorName)) {
271
+ return (node?.modifiers || node?.decorators)?.filter(decorator => {
272
+ if (decorator?.expression?.expression?.text) {
273
+ return decoratorName.includes(decorator.expression.expression.text);
274
+ }
275
+
276
+ return false;
277
+ }
278
+ ) || [];
279
+ }
280
+
281
+ return [];
246
282
  };
247
283
 
248
284
  const hasTag = (jsDoc, tagName) => {
@@ -272,7 +308,7 @@ const findAllTags = (jsDoc, tagName) => {
272
308
  };
273
309
 
274
310
  const validateJSDocTag = (tag) => {
275
- const booleanTags = ["private", "protected", "public", "abstract", "allowPreventDefault", "native", "formProperty", "constructor", "override"];
311
+ const booleanTags = ["private", "protected", "public", "abstract", "native", "allowPreventDefault", "formProperty", "constructor", "override"];
276
312
  let tagName = tag.tag;
277
313
 
278
314
  if (booleanTags.includes(tag.tag)) {
@@ -284,6 +320,8 @@ const validateJSDocTag = (tag) => {
284
320
  return !tag.name && !tag.type && !tag.description;
285
321
  case "deprecated":
286
322
  return !tag.type;
323
+ case "experimental":
324
+ return !tag.type;
287
325
  case "extends":
288
326
  return !tag.type && tag.name && !tag.description;
289
327
  case "implements":
@@ -316,7 +354,7 @@ const validateJSDocComment = (fieldType, jsdocComment, node, moduleDoc) => {
316
354
  let isValid = false
317
355
 
318
356
  if (fieldType === "event" && tag?.tag === "param") {
319
- isValid = allowedTags[fieldType]?.includes(tag.tag) && validateJSDocTag({...tag, tag: "eventparam"});
357
+ isValid = allowedTags[fieldType]?.includes(tag.tag) && validateJSDocTag({ ...tag, tag: "eventparam" });
320
358
  } else {
321
359
  isValid = allowedTags[fieldType]?.includes(tag.tag) && validateJSDocTag(tag);
322
360
  }
@@ -345,26 +383,27 @@ const displayDocumentationErrors = () => {
345
383
  [...documentationErrors.keys()].forEach(modulePath => {
346
384
  const moduleErrors = documentationErrors.get(modulePath);
347
385
 
348
- console.log(`=== ERROR: ${moduleErrors.length > 1 ? `${moduleErrors.length} problems` : "Problem"} found in file: ${modulePath}:`)
386
+ console.log(`=== ERROR: ${moduleErrors.length > 1 ? `${moduleErrors.length} problems` : "Problem"} found in file: ${modulePath}:`)
349
387
  moduleErrors.forEach(moduleError => {
350
388
  errorsCount++;
351
389
  console.log(`\t- ${moduleError}`)
352
390
  })
353
391
  })
354
392
 
355
- if(errorsCount) {
393
+ if (errorsCount) {
356
394
  throw new Error(`Found ${errorsCount} errors in the description of the public API.`);
357
395
  }
358
396
  }
359
397
 
360
398
  const formatArrays = (typeText) => {
361
- return typeText?.replaceAll(/(\S+)\[\]/g, "Array<$1>")
399
+ return typeText?.replaceAll(/(\S+)\[\]/g, "Array<$1>")
362
400
  }
363
401
 
364
402
  export {
365
403
  getPrivacyStatus,
366
404
  getSinceStatus,
367
405
  getDeprecatedStatus,
406
+ getExperimentalStatus,
368
407
  getType,
369
408
  getReference,
370
409
  validateJSDocComment,