@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/CHANGELOG.md +8 -0
- package/components-package/nps.js +4 -4
- package/lib/amd-to-es6/index.js +104 -0
- package/lib/cem/custom-elements-manifest.config.mjs +57 -21
- package/lib/cem/event.mjs +24 -3
- package/lib/cem/types-internal.d.ts +554 -785
- package/lib/cem/types.d.ts +520 -655
- package/lib/cem/utils.mjs +9 -10
- package/lib/cem/validate.js +15 -13
- package/lib/generate-custom-elements-manifest/index.js +51 -107
- package/package.json +2 -2
- package/lib/esm-abs-to-rel/index.js +0 -61
- package/lib/replace-global-core/index.js +0 -25
package/CHANGELOG.md
CHANGED
@@ -3,6 +3,14 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
5
5
|
|
6
|
+
# [1.22.0-rc.2](https://github.com/SAP/ui5-webcomponents/compare/v1.22.0-rc.1...v1.22.0-rc.2) (2024-01-25)
|
7
|
+
|
8
|
+
**Note:** Version bump only for package @ui5/webcomponents-tools
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
6
14
|
# [1.22.0-rc.1](https://github.com/SAP/ui5-webcomponents/compare/v1.22.0-rc.0...v1.22.0-rc.1) (2024-01-18)
|
7
15
|
|
8
16
|
|
@@ -135,13 +135,13 @@ const getScripts = (options) => {
|
|
135
135
|
bundle: `node ${LIB}/dev-server/dev-server.js ${viteConfig}`,
|
136
136
|
},
|
137
137
|
generateAPI: {
|
138
|
-
default: `nps ${ tsOption ? "generateAPI.generateCEM generateAPI.validateCEM" : "generateAPI.prepare generateAPI.preprocess generateAPI.jsdoc generateAPI.cleanup generateAPI.prepareManifest"}`,
|
139
|
-
generateCEM: `cem analyze --config
|
140
|
-
validateCEM: `node "${LIB}/cem/validate.js"`,
|
138
|
+
default: `nps ${ tsOption ? "generateAPI.generateCEM generateAPI.validateCEM" : "generateAPI.prepare generateAPI.preprocess generateAPI.jsdoc generateAPI.cleanup generateAPI.prepareManifest generateAPI.validateCEM"}`,
|
139
|
+
generateCEM: `cem analyze --config "${LIB}/cem/custom-elements-manifest.config.mjs" ${ options.dev ? "--dev" : "" }`,
|
140
|
+
validateCEM: `node "${LIB}/cem/validate.js" ${ options.dev ? "--dev" : "" }`,
|
141
141
|
prepare: `node "${LIB}/copy-and-watch/index.js" --silent "dist/**/*.js" jsdoc-dist/`,
|
142
142
|
prepareManifest: `node "${LIB}/generate-custom-elements-manifest/index.js" dist dist`,
|
143
143
|
preprocess: `node "${preprocessJSDocScript}" jsdoc-dist/ src`,
|
144
|
-
jsdoc: `jsdoc -c "${LIB}/jsdoc/
|
144
|
+
jsdoc: `jsdoc -c "${LIB}/jsdoc/config.json"`,
|
145
145
|
cleanup: "rimraf jsdoc-dist/"
|
146
146
|
},
|
147
147
|
};
|
@@ -0,0 +1,104 @@
|
|
1
|
+
const fs = require("fs").promises;
|
2
|
+
const path = require("path");
|
3
|
+
const basePath = process.argv[2];
|
4
|
+
const babelCore = require("@babel/core");
|
5
|
+
const babelParser = require("@babel/parser");
|
6
|
+
const babelGenerator = require("@babel/generator").default;
|
7
|
+
const replaceAsync = require('replace-in-file');
|
8
|
+
|
9
|
+
const convertSAPUIDefineToDefine = async (filePath) => {
|
10
|
+
return replaceAsync({
|
11
|
+
files: filePath,
|
12
|
+
processor: (input) => {
|
13
|
+
return input.replace("sap.ui.define", "define").replace(", /* bExport= */ false", "").replace(", /* bExport= */ true", "");
|
14
|
+
}
|
15
|
+
})
|
16
|
+
}
|
17
|
+
|
18
|
+
const convertAmdToEs6 = async (code) => {
|
19
|
+
code = code.replace(/sap\.ui\.require/g, "require");
|
20
|
+
|
21
|
+
return (await babelCore.transformAsync(code, {
|
22
|
+
plugins: [['babel-plugin-amd-to-esm', {}]]
|
23
|
+
})).code;
|
24
|
+
}
|
25
|
+
|
26
|
+
const convertAbsImportsToRelative = (filePath, code) => {
|
27
|
+
let changed = false;
|
28
|
+
// console.log("File processing started: ", srcPath);
|
29
|
+
|
30
|
+
if (code.includes("import(")) {
|
31
|
+
// esprima can't parse this, but it's from the project files
|
32
|
+
return;
|
33
|
+
}
|
34
|
+
|
35
|
+
const tree = babelParser.parse(code, { sourceType: "module" });
|
36
|
+
const importer = filePath.replace(basePath, "");
|
37
|
+
const importerDir = path.dirname(importer);
|
38
|
+
// console.log("Importer -> ", importer);
|
39
|
+
|
40
|
+
tree?.program?.body?.forEach(node => {
|
41
|
+
if (node.type === "ImportDeclaration") {
|
42
|
+
let importee = node.source.value;
|
43
|
+
// console.log(importee);
|
44
|
+
if (importee.startsWith(".")) {
|
45
|
+
// add .js extension if missing
|
46
|
+
if (!importee.endsWith(".js")) {
|
47
|
+
node.source.value += ".js"
|
48
|
+
changed = true;
|
49
|
+
}
|
50
|
+
return;
|
51
|
+
}
|
52
|
+
let importeeDir = path.dirname(importee);
|
53
|
+
let importeeFile = path.basename(importee);
|
54
|
+
let relativePath = path.relative(importerDir, importeeDir);
|
55
|
+
if (relativePath.length === 0) {
|
56
|
+
relativePath = "."
|
57
|
+
}
|
58
|
+
if (!relativePath.startsWith(".")) {
|
59
|
+
relativePath = "./" + relativePath;
|
60
|
+
}
|
61
|
+
|
62
|
+
relativePath = relativePath.replace(/\\/g, "/"); // the browser expects unix paths
|
63
|
+
let relativeImport = `${relativePath}/${importeeFile}.js`;
|
64
|
+
// console.log(importee + " --> " + relativeImport);
|
65
|
+
node.source.value = relativeImport;
|
66
|
+
changed = true;
|
67
|
+
}
|
68
|
+
});
|
69
|
+
|
70
|
+
return changed ? babelGenerator(tree).code : code;
|
71
|
+
}
|
72
|
+
|
73
|
+
const replaceGlobalCoreUsage = (filePath, code) => {
|
74
|
+
if (!filePath.includes("Configuration")) {
|
75
|
+
const replaced = code.replace(/sap\.ui\.getCore\(\)/g, `Core`);
|
76
|
+
return code !== replaced ? `import Core from 'sap/ui/core/Core';${replaced}` : code;
|
77
|
+
}
|
78
|
+
|
79
|
+
return code;
|
80
|
+
};
|
81
|
+
|
82
|
+
const transformAmdToES6Module = async (filePath) => {
|
83
|
+
await convertSAPUIDefineToDefine(filePath);
|
84
|
+
|
85
|
+
let code = (await fs.readFile(filePath)).toString();
|
86
|
+
|
87
|
+
code = await convertAmdToEs6(code);
|
88
|
+
|
89
|
+
code = replaceGlobalCoreUsage(filePath, code);
|
90
|
+
|
91
|
+
code = convertAbsImportsToRelative(filePath, code);
|
92
|
+
|
93
|
+
return fs.writeFile(filePath, code);
|
94
|
+
}
|
95
|
+
|
96
|
+
const transformAmdToES6Modules = async () => {
|
97
|
+
const { globby } = await import("globby");
|
98
|
+
const fileNames = await globby(basePath.replace(/\\/g, "/") + "**/*.js");
|
99
|
+
return Promise.all(fileNames.map(transformAmdToES6Module).filter(x => !!x));
|
100
|
+
};
|
101
|
+
|
102
|
+
transformAmdToES6Modules().then(() => {
|
103
|
+
console.log("Success: all amd modules are transformed to es6!");
|
104
|
+
});
|
@@ -21,6 +21,8 @@ import {
|
|
21
21
|
normalizeTagType
|
22
22
|
} from "./utils.mjs";
|
23
23
|
|
24
|
+
const packageJSON = JSON.parse(fs.readFileSync("./package.json"));
|
25
|
+
|
24
26
|
const extractClassNodeJSDoc = node => {
|
25
27
|
const fileContent = node.getFullText();
|
26
28
|
const allJSDocsRegExp = new RegExp(`\\/\\*\\*(.|\\n)+?\\s+\\*\\/`, "gm");
|
@@ -421,13 +423,18 @@ export default {
|
|
421
423
|
}
|
422
424
|
}
|
423
425
|
|
424
|
-
|
425
|
-
moduleDoc.exports = moduleDoc.exports.filter(e => !(e.kind === "custom-element-definition" && !moduleDoc.declarations?.find(d => d.name === e.name)?.tagName))
|
426
|
-
}
|
426
|
+
moduleDoc.path = moduleDoc.path?.replace(/^src/, "dist").replace(/\.ts$/, ".js");
|
427
427
|
|
428
|
-
moduleDoc.exports
|
428
|
+
moduleDoc.exports = moduleDoc.exports.
|
429
|
+
filter(e => !(e.kind === "custom-element-definition" && !moduleDoc.declarations?.find(d => d.name === e.name)?.tagName))
|
430
|
+
|
431
|
+
moduleDoc.exports.forEach(e => {
|
429
432
|
const classNode = moduleDoc.declarations.find(c => c.name === e.declaration.name);
|
430
433
|
|
434
|
+
if (e.declaration && e.declaration.module) {
|
435
|
+
e.declaration.module = e.declaration.module.replace(/^src/, "dist").replace(/\.ts$/, ".js");
|
436
|
+
}
|
437
|
+
|
431
438
|
if (classNode?.customElement && classNode.tagName && e.kind !== "custom-element-definition") {
|
432
439
|
moduleDoc.exports.push({
|
433
440
|
kind: "custom-element-definition",
|
@@ -439,24 +446,53 @@ export default {
|
|
439
446
|
})
|
440
447
|
}
|
441
448
|
})
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
449
|
+
|
450
|
+
const typeReferences = new Set();
|
451
|
+
const registerTypeReference = reference => typeReferences.add(JSON.stringify(reference))
|
452
|
+
|
453
|
+
moduleDoc.declarations.forEach(declaration => {
|
454
|
+
["events", "slots", "members"].forEach(memberType => {
|
455
|
+
declaration[memberType]?.forEach(member => {
|
456
|
+
if (member.type?.references) {
|
457
|
+
member.type.references.forEach(registerTypeReference)
|
458
|
+
} else if (member._ui5type?.references) {
|
459
|
+
member._ui5type.references.forEach(registerTypeReference)
|
460
|
+
} else if (member.kind === "method") {
|
461
|
+
member.return?.type?.references?.forEach(registerTypeReference)
|
462
|
+
|
463
|
+
member.parameters?.forEach(parameter => {
|
464
|
+
parameter.type?.references?.forEach(registerTypeReference)
|
465
|
+
})
|
466
|
+
}
|
467
|
+
})
|
468
|
+
})
|
469
|
+
});
|
470
|
+
|
471
|
+
typeReferences.forEach(reference => {
|
472
|
+
reference = JSON.parse(reference);
|
473
|
+
if (reference.package === packageJSON?.name && reference.module === moduleDoc.path) {
|
474
|
+
const hasExport = moduleDoc.exports.some(e => e.declaration?.name === reference.name && e.declaration?.module === reference.module)
|
475
|
+
|
476
|
+
if (!hasExport) {
|
477
|
+
const JSDocErrors = getJSDocErrors();
|
478
|
+
JSDocErrors.push(
|
479
|
+
`=== ERROR: Problem found with ${reference.name} type reference in ${moduleDoc.path?.replace(/^dist/, "src").replace(/\.js$/, ".ts")}: \n\t- ${reference.name} is used as type of public API, but it's not exported`)
|
480
|
+
}
|
481
|
+
}
|
459
482
|
})
|
483
|
+
|
484
|
+
moduleDoc.exports = moduleDoc.exports.
|
485
|
+
filter(e => moduleDoc.declarations.find(d => d.name === e.declaration.name && ["class", "function", "variable", "enum"].includes(d.kind)) || e.name === "default");
|
486
|
+
},
|
487
|
+
packageLinkPhase({ context }) {
|
488
|
+
if (context.dev) {
|
489
|
+
const JSDocErrors = getJSDocErrors();
|
490
|
+
if (JSDocErrors.length > 0) {
|
491
|
+
console.log(JSDocErrors.join("\n"));
|
492
|
+
console.log(`Invalid JSDoc. ${JSDocErrors.length} were found.`);
|
493
|
+
throw new Error(`Invalid JSDoc.`);
|
494
|
+
}
|
495
|
+
}
|
460
496
|
}
|
461
497
|
},
|
462
498
|
],
|
package/lib/cem/event.mjs
CHANGED
@@ -4,13 +4,15 @@ import {
|
|
4
4
|
getDeprecatedStatus,
|
5
5
|
getSinceStatus,
|
6
6
|
getType,
|
7
|
+
getTypeRefs,
|
7
8
|
validateJSDocComment,
|
8
9
|
hasTag,
|
9
10
|
findTag,
|
10
11
|
findAllTags,
|
11
12
|
getReference,
|
12
13
|
normalizeDescription,
|
13
|
-
normalizeTagType
|
14
|
+
normalizeTagType,
|
15
|
+
getJSDocErrors
|
14
16
|
} from "./utils.mjs";
|
15
17
|
|
16
18
|
const jsDocRegExp = /\/\*\*(.|\n)+?\s+\*\//;
|
@@ -54,8 +56,9 @@ const getParams = (ts, eventDetails, commentParams, classNode, moduleDoc) => {
|
|
54
56
|
};
|
55
57
|
|
56
58
|
function processEvent(ts, event, classNode, moduleDoc) {
|
59
|
+
const name = event?.expression?.arguments?.[0]?.text;
|
57
60
|
const result = {
|
58
|
-
name
|
61
|
+
name,
|
59
62
|
_ui5privacy: "private",
|
60
63
|
type: { text: "CustomEvent" }
|
61
64
|
};
|
@@ -68,7 +71,7 @@ function processEvent(ts, event, classNode, moduleDoc) {
|
|
68
71
|
|
69
72
|
const eventParsedComment = parse(comment, { spacing: 'preserve' })[0];
|
70
73
|
|
71
|
-
validateJSDocComment("event", eventParsedComment,
|
74
|
+
validateJSDocComment("event", eventParsedComment, name, moduleDoc);
|
72
75
|
|
73
76
|
const deprecatedTag = findTag(eventParsedComment, "deprecated");
|
74
77
|
const privacy = findTag(eventParsedComment, ["public", "private", "protected"])?.tag || "private";
|
@@ -79,11 +82,29 @@ function processEvent(ts, event, classNode, moduleDoc) {
|
|
79
82
|
const native = hasTag(eventParsedComment, "native");
|
80
83
|
const eventDetails = event?.expression?.arguments?.[1]?.properties?.find(prop => prop?.name?.text === "detail")?.initializer?.properties;
|
81
84
|
|
85
|
+
if (event?.expression?.arguments?.[1] && !event?.expression?.typeArguments) {
|
86
|
+
const JSDocErrors = getJSDocErrors();
|
87
|
+
|
88
|
+
JSDocErrors.push(
|
89
|
+
`=== ERROR: Problem found with ${name}'s description in ${moduleDoc.path}: \n\t- Event details have to be described with type via generics type passed to the decorator ( @event<TypeForDetails>("example-name", {details}) ) `
|
90
|
+
);
|
91
|
+
}
|
92
|
+
|
82
93
|
result.description = description;
|
83
94
|
result._ui5allowPreventDefault = allowPreventDefault;
|
84
95
|
|
85
96
|
if (native) {
|
86
97
|
result.type = { text: "Event" };
|
98
|
+
} else if (event?.expression?.typeArguments) {
|
99
|
+
const typesText = event?.expression?.typeArguments.map(type => type.typeName?.text).filter(Boolean).join(" | ");
|
100
|
+
const typeRefs = (getTypeRefs(ts, event.expression)
|
101
|
+
?.map(e => getReference(ts, e, event, moduleDoc.path)).filter(Boolean)) || [];
|
102
|
+
|
103
|
+
result.type = { text: `CustomEvent<${typesText}>` };
|
104
|
+
|
105
|
+
if (typeRefs.length) {
|
106
|
+
result.type.references = typeRefs;
|
107
|
+
}
|
87
108
|
}
|
88
109
|
|
89
110
|
if (privacy) {
|