@ui5/webcomponents-tools 1.22.0-rc.1 → 1.22.0-rc.2

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/lib/cem/utils.mjs CHANGED
@@ -18,7 +18,7 @@ const normalizeDescription = (description) => {
18
18
  return typeof description === 'string' ? description.replaceAll(/^-\s+|^(\n)+|(\n)+$/g, ""): description;
19
19
  }
20
20
 
21
- const getTypeRefs = (ts, classNodeMember, member) => {
21
+ const getTypeRefs = (ts, node, member) => {
22
22
  const extractTypeRefs = (type) => {
23
23
  if (type?.kind === ts.SyntaxKind.TypeReference) {
24
24
  return type.typeArguments?.length
@@ -29,7 +29,7 @@ const getTypeRefs = (ts, classNodeMember, member) => {
29
29
  .map((type) => extractTypeRefs(type))
30
30
  .flat(1);
31
31
  } else if (type?.kind === ts.SyntaxKind.TemplateLiteralType) {
32
- if (member.type) {
32
+ if (member?.type) {
33
33
  member.type.text = member.type.text.replaceAll?.(/`|\${|}/g, "");
34
34
  }
35
35
 
@@ -39,7 +39,7 @@ const getTypeRefs = (ts, classNodeMember, member) => {
39
39
  }
40
40
  };
41
41
 
42
- let typeRefs = extractTypeRefs(classNodeMember.type);
42
+ let typeRefs = extractTypeRefs(node.type) || node?.typeArguments?.map(n => extractTypeRefs(n)).flat(2);
43
43
 
44
44
  if (typeRefs) {
45
45
  typeRefs = typeRefs.filter((e) => !!e);
@@ -62,7 +62,7 @@ const getPrivacyStatus = (jsdocComment) => {
62
62
  return privacyTag?.tag || "private";
63
63
  };
64
64
 
65
- const findPackageName = (ts, sourceFile, typeName, packageJSON) => {
65
+ const findPackageName = (ts, sourceFile, typeName) => {
66
66
  const localStatements = [
67
67
  ts.SyntaxKind.EnumDeclaration,
68
68
  ts.SyntaxKind.InterfaceDeclaration,
@@ -102,7 +102,7 @@ const findPackageName = (ts, sourceFile, typeName, packageJSON) => {
102
102
  }
103
103
  };
104
104
 
105
- const findImportPath = (ts, sourceFile, typeName, packageJSON, modulePath) => {
105
+ const findImportPath = (ts, sourceFile, typeName, modulePath) => {
106
106
  const localStatements = [
107
107
  ts.SyntaxKind.EnumDeclaration,
108
108
  ts.SyntaxKind.InterfaceDeclaration,
@@ -158,6 +158,8 @@ const normalizeTagType = (type) => {
158
158
  return type?.trim();
159
159
  }
160
160
 
161
+ const packageJSON = JSON.parse(fs.readFileSync("./package.json"));
162
+
161
163
  const getReference = (ts, type, classNode, modulePath) => {
162
164
  let sourceFile = classNode.parent;
163
165
 
@@ -165,22 +167,19 @@ const getReference = (ts, type, classNode, modulePath) => {
165
167
  sourceFile = sourceFile.parent;
166
168
  }
167
169
 
168
- const packageJSON = JSON.parse(fs.readFileSync("./package.json"));
169
-
170
170
  const typeName =
171
171
  typeof type === "string"
172
172
  ? normalizeTagType(type)
173
173
  : type.class?.expression?.text ||
174
174
  type.typeExpression?.type?.getText() ||
175
175
  type.typeExpression?.type?.elementType?.typeName?.text;
176
- const packageName = findPackageName(ts, sourceFile, typeName, packageJSON);
176
+ const packageName = findPackageName(ts, sourceFile, typeName);
177
177
  const importPath = findImportPath(
178
178
  ts,
179
179
  sourceFile,
180
180
  typeName,
181
- packageJSON,
182
181
  modulePath
183
- );
182
+ )?.replace(`${packageName}/`, "");
184
183
 
185
184
  return packageName && {
186
185
  name: typeName,
@@ -1,6 +1,10 @@
1
1
  const fs = require('fs');
2
2
  const Ajv = require('ajv');
3
3
  const path = require('path');
4
+ const yargs = require('yargs/yargs')
5
+ const { hideBin } = require('yargs/helpers')
6
+ const argv = yargs(hideBin(process.argv))
7
+ .argv;
4
8
 
5
9
  // Load your JSON schema
6
10
  const extenalSchema = require('./schema.json');
@@ -36,28 +40,26 @@ const clearProps = (data) => {
36
40
  return data;
37
41
  }
38
42
 
39
- const inputDataExternal = clearProps(JSON.parse(JSON.stringify(inputDataInternal)));
40
-
41
43
  const ajv = new Ajv({ allowUnionTypes: true, allError: true })
42
-
43
44
  let validate = ajv.compile(internalSchema)
44
45
 
45
46
  // Validate the JSON data against the schema
46
- if (validate(inputDataInternal)) {
47
- console.log('Validation internal custom-elements successful');
48
- } else {
49
- console.error('Validation of internal custom-elements failed');
50
- // console.error('Validation of internal custom-elements failed:', validate.errors);
47
+ if (argv.dev) {
48
+ if (validate(inputDataInternal)) {
49
+ console.log('Internal custom element manifest is validated successfully');
50
+ } else {
51
+ throw new Error(`Validation of internal custom elements manifest failed: ${validate.errors}`);
52
+ }
51
53
  }
52
54
 
55
+ const inputDataExternal = clearProps(JSON.parse(JSON.stringify(inputDataInternal)));
53
56
  validate = ajv.compile(extenalSchema)
54
57
 
55
58
  // Validate the JSON data against the schema
56
59
  if (validate(inputDataExternal)) {
57
- console.log('Validation external custom-elements successful');
60
+ console.log('Custom element manifest is validated successfully');
58
61
  fs.writeFileSync(inputFilePath, JSON.stringify(inputDataExternal, null, 2), 'utf8');
59
62
  fs.writeFileSync(inputFilePath.replace("custom-elements", "custom-elements-internal"), JSON.stringify(inputDataInternal, null, 2), 'utf8');
60
- } else {
61
- console.error('Validation of external custom-elements failed:');
62
- // console.error('Validation of external custom-elements failed:', ajv.errorsText(validate.errors));
63
- }
63
+ } else if (argv.dev) {
64
+ throw new Error(`Validation of public custom elements manifest failed: ${validate.errors}`);
65
+ }
@@ -5,61 +5,40 @@ const path = require("path");
5
5
  const inputDir = process.argv[2];
6
6
  const outputDir = process.argv[3];
7
7
 
8
- const camelToKebabMap = new Map();
9
- const apiIndex = new Map();
10
- const forbiddenAttributeTypes = ["object", "array"];
11
-
12
- const camelToKebabCase = string => {
13
- if (!camelToKebabMap.has(string)) {
14
- const result = string.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
15
- camelToKebabMap.set(string, result);
16
- }
17
- return camelToKebabMap.get(string);
18
- };
8
+ const moduleDeclarations = new Map();
19
9
 
20
10
  const generateJavaScriptExport = entity => {
21
11
  return {
22
- declaration: generateRefenrece(entity.name),
23
- deprecated: !!entity.deprecated,
12
+ declaration: {
13
+ name: entity.basename,
14
+ module: `dist/${entity.resource}`,
15
+ },
24
16
  kind: "js",
25
17
  name: "default",
26
18
  };
27
19
  };
28
20
 
29
21
  const generateCustomElementExport = entity => {
22
+ if (!entity.tagname) return;
23
+
30
24
  return {
31
25
  declaration: {
32
26
  name: entity.basename,
33
- module: `${entity.module}.js`,
27
+ module: `dist/${entity.resource}`,
34
28
  },
35
- deprecated: !!entity.deprecated,
36
29
  kind: "custom-element-definition",
37
- name: entity.tagname,
38
- };
39
- };
40
-
41
- const generateJavaScriptModule = entity => {
42
- return {
43
- kind: "javascript-module",
44
- path: `${entity.basename}.js`,
45
- declarations: [
46
- generateCustomElementDeclaration(entity),
47
- ],
48
- exports: [
49
- generateJavaScriptExport(entity),
50
- generateCustomElementExport(entity),
51
- ],
30
+ name: entity.basename,
52
31
  };
53
32
  };
54
33
 
55
34
  const generateSingleClassField = classField => {
56
35
  let generatedClassField = {
57
- deprecated: !!classField.deprecated,
58
36
  kind: "field",
59
37
  name: classField.name,
60
- privacy: classField.visibility,
61
- static: !!classField.static,
62
38
  type: generateType(classField.type),
39
+ privacy: classField.visibility,
40
+ deprecated: !!classField.deprecated || undefined,
41
+ static: !!classField.static || undefined,
63
42
  };
64
43
 
65
44
  if (classField.defaultValue) {
@@ -75,7 +54,7 @@ const generateSingleClassField = classField => {
75
54
 
76
55
  const generateSingleParameter = parameter => {
77
56
  let generatedParameter = {
78
- deprecated: !!parameter.deprecated,
57
+ deprecated: !!parameter.deprecated || undefined,
79
58
  name: parameter.name,
80
59
  type: generateType(parameter.type),
81
60
  };
@@ -86,6 +65,7 @@ const generateSingleParameter = parameter => {
86
65
 
87
66
  if (parameter.optional) {
88
67
  generatedParameter.optional = parameter.optional;
68
+ generatedParameter.default = parameter.defaultValue;
89
69
  }
90
70
 
91
71
  return generatedParameter;
@@ -101,7 +81,7 @@ const generateParameters = (parameters) => {
101
81
 
102
82
  const generateSingleClassMethod = classMethod => {
103
83
  let generatedClassMethod = {
104
- deprecated: !!classMethod.deprecated,
84
+ deprecated: !!classMethod.deprecated || undefined,
105
85
  kind: "method",
106
86
  name: classMethod.name,
107
87
  privacy: classMethod.visibility,
@@ -122,7 +102,7 @@ const generateSingleClassMethod = classMethod => {
122
102
  };
123
103
 
124
104
  if (classMethod.returnValue.description) {
125
- generatedClassMethod.return.description = classMethod.returnValue.type;
105
+ generatedClassMethod.return.description = classMethod.returnValue.description;
126
106
  }
127
107
  }
128
108
 
@@ -150,47 +130,16 @@ const generateMembers = (classFields, classMethods) => {
150
130
  };
151
131
 
152
132
  const generateType = type => {
153
- const dataType = apiIndex.get(type);
154
-
155
133
  return {
156
- text: dataType && dataType.name.includes(".types.") ?
157
- filterPublicApi(dataType.properties)
158
- .map(prop => `"${prop.name}"`)
159
- .join(" | ") : type,
160
- };
161
- };
162
-
163
- const generateSingleAttribute = attribute => {
164
- let generatedAttribute = {
165
- default: attribute.defaultValue,
166
- deprecated: !!attribute.deprecated,
167
- fieldName: attribute.name,
168
- name: camelToKebabCase(attribute.name),
169
- type: generateType(attribute.type),
134
+ text: type,
170
135
  };
171
-
172
- if (attribute.description) {
173
- generatedAttribute.description = attribute.description;
174
- }
175
-
176
- return generatedAttribute;
177
- };
178
-
179
- const generateAttributes = attributes => {
180
- attributes = attributes.reduce((newAttributesArray, attribute) => {
181
- newAttributesArray.push(generateSingleAttribute(attribute));
182
-
183
- return newAttributesArray;
184
- }, []);
185
-
186
- return attributes;
187
136
  };
188
137
 
189
138
  const generateSingleEvent = event => {
190
139
  let generatedEvent = {
191
- deprecated: !!event.deprecated,
140
+ deprecated: !!event.deprecated || undefined,
192
141
  name: event.name,
193
- type: event.native === "true" ? "NativeEvent" : "CustomEvent",
142
+ type: generateType(event.native === "true" ? "NativeEvent" : "CustomEvent")
194
143
  };
195
144
 
196
145
  if (event.description) {
@@ -212,7 +161,7 @@ const generateEvents = events => {
212
161
 
213
162
  const generateSingleSlot = slot => {
214
163
  return {
215
- deprecated: !!slot.deprecated,
164
+ deprecated: !!slot.deprecated || undefined,
216
165
  description: slot.description,
217
166
  name: slot.name,
218
167
  };
@@ -230,9 +179,9 @@ const generateSlots = slots => {
230
179
 
231
180
  const generateCustomElementDeclaration = entity => {
232
181
  let generatedCustomElementDeclaration = {
233
- deprecated: !!entity.deprecated,
182
+ deprecated: !!entity.deprecated || undefined,
234
183
  customElement: true,
235
- kind: entity.basename,
184
+ kind: entity.kind,
236
185
  name: entity.basename,
237
186
  tagName: entity.tagname,
238
187
  };
@@ -241,9 +190,6 @@ const generateCustomElementDeclaration = entity => {
241
190
  const events = filterPublicApi(entity.events);
242
191
  const classFields = filterPublicApi(entity.properties);
243
192
  const classMethods = filterPublicApi(entity.methods);
244
- const attributes = classFields.filter(property => {
245
- return property.noattribute !== "true" && property.readonly !== "true" && !forbiddenAttributeTypes.includes(property.type.toLowerCase());
246
- });
247
193
 
248
194
  if (slots.length) {
249
195
  generatedCustomElementDeclaration.slots = generateSlots(slots);
@@ -253,10 +199,6 @@ const generateCustomElementDeclaration = entity => {
253
199
  generatedCustomElementDeclaration.events = generateEvents(events);
254
200
  }
255
201
 
256
- if (attributes.length) {
257
- generatedCustomElementDeclaration.attributes = generateAttributes(attributes);
258
- }
259
-
260
202
  if (entity.description) {
261
203
  generatedCustomElementDeclaration.description = entity.description;
262
204
  }
@@ -273,31 +215,8 @@ const generateCustomElementDeclaration = entity => {
273
215
  };
274
216
 
275
217
  const generateRefenrece = (entityName) => {
276
- let packageName;
277
- let basename;
278
-
279
- if (!entityName) {
280
- throw new Error("JSDoc error: entity not found in api.json.");
281
- }
282
-
283
- if (entityName.includes(".")) {
284
- basename = entityName.split(".").pop();
285
- } else {
286
- basename = entityName
287
- }
288
-
289
- if (entityName.includes("sap.ui.webc.main")) {
290
- packageName = "@ui5/webcomponents";
291
- } else if (entityName.includes("sap.ui.webc.fiori")) {
292
- packageName = "@ui5/webcomponents-fiori";
293
- } else if (entityName.includes("sap.ui.webc.base")) {
294
- packageName = "@ui5/webcomponents-base";
295
- }
296
-
297
218
  return {
298
- module: `${basename}.js`,
299
- name: `${basename}`,
300
- package: packageName,
219
+ name: entityName,
301
220
  };
302
221
  };
303
222
 
@@ -313,12 +232,37 @@ const generate = async () => {
313
232
  modules: [],
314
233
  };
315
234
 
316
- file.symbols.forEach(entity => {
317
- if (entity.tagname || entity.kind === "class") {
318
- customElementsManifest.modules.push(generateJavaScriptModule(entity));
235
+ filterPublicApi(file.symbols).forEach(entity => {
236
+ let declaration = moduleDeclarations.get(entity.resource);
237
+
238
+ if (!declaration) {
239
+ moduleDeclarations.set(entity.resource, {
240
+ declarations: [],
241
+ exports: [],
242
+ });
243
+ declaration = moduleDeclarations.get(entity.resource);
244
+ }
245
+
246
+ if (entity.kind === "class" && entity.tagname) {
247
+ declaration.declarations.push(generateCustomElementDeclaration(entity));
248
+ declaration.exports.push(generateJavaScriptExport(entity));
249
+ declaration.exports.push(generateCustomElementExport(entity));
250
+ } else if (entity.kind === "class" && entity.static) {
251
+ declaration.exports.push(generateJavaScriptExport(entity));
319
252
  }
320
253
  });
321
254
 
255
+ [...moduleDeclarations.keys()].forEach(key => {
256
+ let declaration = moduleDeclarations.get(key);
257
+
258
+ customElementsManifest.modules.push({
259
+ kind: "javascript-module",
260
+ path: `dist/${key}`,
261
+ declarations: declaration.declarations,
262
+ exports: declaration.exports
263
+ })
264
+ })
265
+
322
266
  await fs.writeFile(path.join(outputDir, "custom-elements.json"), JSON.stringify(customElementsManifest));
323
267
  };
324
268
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/webcomponents-tools",
3
- "version": "1.22.0-rc.1",
3
+ "version": "1.22.0-rc.2",
4
4
  "description": "UI5 Web Components: webcomponents.tools",
5
5
  "author": "SAP SE (https://www.sap.com)",
6
6
  "license": "Apache-2.0",
@@ -79,5 +79,5 @@
79
79
  "esbuild": "^0.19.9",
80
80
  "yargs": "^17.5.1"
81
81
  },
82
- "gitHead": "1a4ba450e7d222535ddaf4f1d3b0ff91b020bb2a"
82
+ "gitHead": "7075f9a181e13ac1be2a319b2de876ace16dd564"
83
83
  }
@@ -1,61 +0,0 @@
1
- const esprima = require("esprima");
2
- const escodegen = require("escodegen");
3
-
4
- const fs = require("fs").promises;
5
- const path = require("path");
6
- const basePath = process.argv[2];
7
-
8
- const convertImports = async (srcPath) => {
9
- let changed = false;
10
- let code = (await fs.readFile(srcPath)).toString();
11
- if (code.includes("import(")) {
12
- // esprima can't parse this, but it's from the project files
13
- return;
14
- }
15
- const tree = esprima.parseModule(code);
16
- const importer = srcPath.replace(basePath, "");
17
- const importerDir = path.dirname(importer);
18
- // console.log("-> ", importer);
19
- tree.body.forEach(node => {
20
- if (node.type === "ImportDeclaration") {
21
- let importee = node.source.value;
22
- if (importee.startsWith(".")) {
23
- // add .js extension if missing
24
- if (!importee.endsWith(".js")) {
25
- node.source.value += ".js"
26
- changed = true;
27
- }
28
- return;
29
- }
30
- let importeeDir = path.dirname(importee);
31
- let importeeFile = path.basename(importee);
32
- let relativePath = path.relative(importerDir, importeeDir);
33
- if (relativePath.length === 0) {
34
- relativePath = "."
35
- }
36
- if (!relativePath.startsWith(".")) {
37
- relativePath = "./" + relativePath;
38
- }
39
-
40
- relativePath = relativePath.replace(/\\/g, "/"); // the browser expects unix paths
41
- let relativeImport = `${relativePath}/${importeeFile}.js`;
42
- // console.log(importee + " --> " + relativeImport);
43
- node.source.value = relativeImport;
44
- changed = true;
45
- }
46
- });
47
-
48
- if (changed) {
49
- return fs.writeFile(srcPath, escodegen.generate(tree));
50
- }
51
- }
52
-
53
- const generate = async () => {
54
- const { globby } = await import("globby");
55
- const fileNames = await globby(basePath.replace(/\\/g, "/") + "**/*.js");
56
- return Promise.all(fileNames.map(convertImports).filter(x => !!x));
57
- };
58
-
59
- generate().then(() => {
60
- console.log("Success: Converted absolute imports to relative for files in:", basePath);
61
- });
@@ -1,25 +0,0 @@
1
- const fs = require("fs").promises;
2
-
3
- const basePath = process.argv[2];
4
-
5
- const replaceGlobalCoreUsage = async (srcPath) => {
6
-
7
- const original = (await fs.readFile(srcPath)).toString();
8
- let replaced = original.replace(/sap\.ui\.getCore\(\)/g, `Core`);
9
-
10
- if (original !== replaced) {
11
- replaced = `import Core from 'sap/ui/core/Core';
12
- ${replaced}`;
13
- return fs.writeFile(srcPath, replaced);
14
- }
15
- };
16
-
17
- const generate = async () => {
18
- const { globby } = await import("globby");
19
- const fileNames = await globby(basePath.replace(/\\/g, "/") + "**/*.js");
20
- return Promise.all(fileNames.map(replaceGlobalCoreUsage).filter(x => !!x));
21
- };
22
-
23
- generate().then(() => {
24
- console.log("Success: Replaced global core usage in:", basePath);
25
- });