babel-plugin-transform-modules-ui5 7.4.2 → 7.6.0
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
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
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
|
+
# [7.6.0](https://github.com/ui5-community/babel-plugin-transform-modules-ui5/compare/v7.5.0...v7.6.0) (2024-07-22)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* support sap.ui.require for [@sap](https://github.com/sap)UiRequire annotated modules ([#131](https://github.com/ui5-community/babel-plugin-transform-modules-ui5/issues/131)) ([23c4ac6](https://github.com/ui5-community/babel-plugin-transform-modules-ui5/commit/23c4ac67eef5a825692c528852ef62bbd621d13e))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [7.5.0](https://github.com/ui5-community/babel-plugin-transform-modules-ui5/compare/v7.4.2...v7.5.0) (2024-07-12)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* support ControllerExtensions extended with .override(...) ([#128](https://github.com/ui5-community/babel-plugin-transform-modules-ui5/issues/128)) ([f744d9d](https://github.com/ui5-community/babel-plugin-transform-modules-ui5/commit/f744d9db3dd82020712b47a18ce55ed51a13fe89))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
6
28
|
## [7.4.2](https://github.com/ui5-community/babel-plugin-transform-modules-ui5/compare/v7.4.1...v7.4.2) (2024-06-25)
|
|
7
29
|
|
|
8
30
|
|
|
@@ -121,6 +121,7 @@ function convertClassToUI5Extend(path, node, classInfo, extraStaticProps, import
|
|
|
121
121
|
const typeAnnotation = (_member$typeAnnotatio = member.typeAnnotation) === null || _member$typeAnnotatio === void 0 ? void 0 : _member$typeAnnotatio.typeAnnotation;
|
|
122
122
|
// double-check that it is a valid node for a controller extension
|
|
123
123
|
if (_core.types.isTSTypeReference(typeAnnotation) || _core.types.isTSQualifiedName(typeAnnotation)) {
|
|
124
|
+
var _memberPath$hub;
|
|
124
125
|
const typeName = getTypeName(typeAnnotation);
|
|
125
126
|
|
|
126
127
|
// 1. transform the property from being typed as instance and un-initialized to a property where the controller extension *class* is assigned as value
|
|
@@ -137,7 +138,7 @@ function convertClassToUI5Extend(path, node, classInfo, extraStaticProps, import
|
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
// 3. restore the import in case it was run already and removed the import
|
|
140
|
-
const neededImportDeclaration = (0, _imports.getImportDeclaration)(memberPath.hub.file.opts.filename, typeName);
|
|
141
|
+
const neededImportDeclaration = (0, _imports.getImportDeclaration)(memberPath === null || memberPath === void 0 || (_memberPath$hub = memberPath.hub) === null || _memberPath$hub === void 0 || (_memberPath$hub = _memberPath$hub.file) === null || _memberPath$hub === void 0 || (_memberPath$hub = _memberPath$hub.opts) === null || _memberPath$hub === void 0 ? void 0 : _memberPath$hub.filename, typeName);
|
|
141
142
|
if (!importDeclarationPaths.some(path => path.node === neededImportDeclaration)) {
|
|
142
143
|
// TODO: import might be there but with the specifier removed; we can clone, but then other specifiers are duplicate
|
|
143
144
|
// if import is no longer there, re-add it
|
|
@@ -150,6 +151,36 @@ function convertClassToUI5Extend(path, node, classInfo, extraStaticProps, import
|
|
|
150
151
|
}
|
|
151
152
|
if (!member.value) continue; // remove all other un-initialized static class props (typescript)
|
|
152
153
|
|
|
154
|
+
// Now handle the case where an extended controller extension - not just e.g. "Routing", but
|
|
155
|
+
// "Routing.override({...})" - is assigned to the class property. To make this work in TypeScript code
|
|
156
|
+
// (Routing.override({...}) returns a class, but the "routing" member property needs to be typed as an instance),
|
|
157
|
+
// we require the following notation, using a dummy function ControllerExtension.use() that does actually
|
|
158
|
+
// not exist at runtime, but does the required class-to-instance conversion from TypeScript perspective:
|
|
159
|
+
// routing: ControllerExtension.use(Routing.override({...}))
|
|
160
|
+
// In this case, the code in the "if" clause above was not executed, regardless of the presence of the
|
|
161
|
+
// @transformControllerExtension marker, because it is not a type assignment. In the resulting code, the
|
|
162
|
+
// "ControllerExtension.use(...)" part should be removed and the content of the brackets should be assigned
|
|
163
|
+
// directly to the member property.
|
|
164
|
+
if (_core.types.isCallExpression(member.value)) {
|
|
165
|
+
const callee = member.value.callee;
|
|
166
|
+
if (_core.types.isMemberExpression(callee) && _core.types.isIdentifier(callee.object) && _core.types.isIdentifier(callee.property) && callee.property.name === "use" // we are looking for "ControllerExtension.use(...)"
|
|
167
|
+
) {
|
|
168
|
+
var _memberPath$hub2, _callee$object, _importDeclaration$so;
|
|
169
|
+
const importDeclaration = (0, _imports.getImportDeclaration)(memberPath === null || memberPath === void 0 || (_memberPath$hub2 = memberPath.hub) === null || _memberPath$hub2 === void 0 || (_memberPath$hub2 = _memberPath$hub2.file) === null || _memberPath$hub2 === void 0 || (_memberPath$hub2 = _memberPath$hub2.opts) === null || _memberPath$hub2 === void 0 ? void 0 : _memberPath$hub2.filename, callee === null || callee === void 0 || (_callee$object = callee.object) === null || _callee$object === void 0 ? void 0 : _callee$object.name // usually, but not necessarily always: "ControllerExtension"...
|
|
170
|
+
);
|
|
171
|
+
// ...hence we rather look at the imported module name to be sure
|
|
172
|
+
if ((importDeclaration === null || importDeclaration === void 0 || (_importDeclaration$so = importDeclaration.source) === null || _importDeclaration$so === void 0 ? void 0 : _importDeclaration$so.value) === "sap/ui/core/mvc/ControllerExtension") {
|
|
173
|
+
if (!member.value.arguments || member.value.arguments.length !== 1) {
|
|
174
|
+
// exactly one argument must be there
|
|
175
|
+
throw memberPath.buildCodeFrameError(`ControllerExtension.use() must be called with exactly one argument but has ${member.value.arguments ? member.value.arguments.length : 0}`);
|
|
176
|
+
}
|
|
177
|
+
member.value = member.value.arguments[0];
|
|
178
|
+
extendProps.unshift(buildObjectProperty(member)); // add it to the properties of the extend() config object
|
|
179
|
+
continue; // prevent the member from also being added to the constructor
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
153
184
|
// Special handling for TypeScript limitation where metadata, renderer and overrides must be properties.
|
|
154
185
|
if (["metadata", "renderer", "overrides"].includes(memberName)) {
|
|
155
186
|
if (opts.overridesToOverride && member.key.name === "overrides") {
|
|
@@ -15,6 +15,9 @@ const saveImports = file => {
|
|
|
15
15
|
// can be called from visitor to access previously present declarations
|
|
16
16
|
exports.saveImports = saveImports;
|
|
17
17
|
function getImportDeclaration(filename, typeName) {
|
|
18
|
+
if (!filename || !typeName) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
18
21
|
const typeNameParts = typeName.split(".");
|
|
19
22
|
|
|
20
23
|
// find the declaration importing the typeName among the collected import declarations in this file
|
|
@@ -139,14 +139,19 @@ function wrap(visitor, programNode, opts) {
|
|
|
139
139
|
if (imports.some(imp => imp.interop)) {
|
|
140
140
|
body.unshift(th.buildDefaultImportInterop());
|
|
141
141
|
}
|
|
142
|
-
|
|
142
|
+
|
|
143
|
+
// should we use sap.ui.require instead of sap.ui.define?
|
|
144
|
+
let useSapUiRequire = hasUseSapUiRequire(visitor.parent.comments, body, true);
|
|
145
|
+
|
|
146
|
+
// generate the sap.ui.define or sap.ui.require
|
|
147
|
+
const defineOrRequire = generateDefineOrRequire(body, imports, exportGlobal || opts.exportAllGlobal, useSapUiRequire);
|
|
143
148
|
|
|
144
149
|
// add the "use strict" directive if not on program node
|
|
145
150
|
if (!opts.neverUseStrict && !hasUseStrict(programNode)) {
|
|
146
|
-
const
|
|
147
|
-
|
|
151
|
+
const defineOrRequireFnBody = defineOrRequire.expression.arguments[1].body;
|
|
152
|
+
defineOrRequireFnBody.directives = [_core.types.directive(_core.types.directiveLiteral("use strict")), ...(defineOrRequireFnBody.directives || [])];
|
|
148
153
|
}
|
|
149
|
-
programNode.body = [...preDefine,
|
|
154
|
+
programNode.body = [...preDefine, defineOrRequire];
|
|
150
155
|
|
|
151
156
|
// if a copyright comment is present we append it to the new program node
|
|
152
157
|
if (copyright && visitor.parent) {
|
|
@@ -157,11 +162,36 @@ function wrap(visitor, programNode, opts) {
|
|
|
157
162
|
function hasUseStrict(node) {
|
|
158
163
|
return (node.directives || []).some(directive => directive.value.value === "use strict");
|
|
159
164
|
}
|
|
160
|
-
function
|
|
165
|
+
function hasUseSapUiRequire(comments, body, remove) {
|
|
166
|
+
// detect the @sapUiRequire comment
|
|
167
|
+
return comments.some(comment => {
|
|
168
|
+
let found = false;
|
|
169
|
+
// check for existing comment block
|
|
170
|
+
if (comment.type === "CommentBlock") {
|
|
171
|
+
found = comment.value.trim() === "@sapUiRequire";
|
|
172
|
+
}
|
|
173
|
+
// remove the comment (if it is somewhere in the body)
|
|
174
|
+
if (found && remove) {
|
|
175
|
+
body === null || body === void 0 || body.forEach(node => {
|
|
176
|
+
(0, _core.traverse)(node, {
|
|
177
|
+
enter(path) {
|
|
178
|
+
["leadingComments", "trailingComments", "innerComments"].forEach(key => {
|
|
179
|
+
var _path$node$key;
|
|
180
|
+
path.node[key] = (_path$node$key = path.node[key]) === null || _path$node$key === void 0 ? void 0 : _path$node$key.filter(c => c !== comment);
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
noScope: true
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return found;
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
function generateDefineOrRequire(body, imports, exportGlobal, useRequire) {
|
|
161
191
|
const defineOpts = {
|
|
162
192
|
SOURCES: _core.types.arrayExpression(imports.map(i => _core.types.stringLiteral(i.src))),
|
|
163
193
|
PARAMS: imports.map(i => _core.types.identifier(i.tmpName)),
|
|
164
194
|
BODY: body
|
|
165
195
|
};
|
|
166
|
-
return exportGlobal ? th.buildDefineGlobal(defineOpts) : th.buildDefine(defineOpts);
|
|
196
|
+
return useRequire ? th.buildRequire(defineOpts) : exportGlobal ? th.buildDefineGlobal(defineOpts) : th.buildDefine(defineOpts);
|
|
167
197
|
}
|
package/dist/utils/templates.js
CHANGED
|
@@ -5,13 +5,18 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.buildInheritingFunction = exports.buildInheritingConstructor = exports.buildExtendAssign = exports.buildExportDefault = exports.buildDynamicImportHelper = exports.buildDefineGlobal = exports.buildDefine = exports.buildDefaultImportInterop = exports.buildDefaultImportDeconstructor = exports.buildDeclareExports = exports.buildConstDeclaration = exports.buildAssign = exports.buildAllExportHelper = exports.buildAllExport = void 0;
|
|
7
7
|
exports.buildNamedExport = buildNamedExport;
|
|
8
|
-
exports.exportsIdentifier = exports.buildTempExport = exports.buildReturnExports = exports.buildReturn = exports.buildNamedImportDestructor = void 0;
|
|
8
|
+
exports.exportsIdentifier = exports.buildTempExport = exports.buildReturnExports = exports.buildReturn = exports.buildRequire = exports.buildNamedImportDestructor = void 0;
|
|
9
9
|
var _core = require("@babel/core");
|
|
10
10
|
const exportName = "__exports";
|
|
11
11
|
const exportsIdentifier = exports.exportsIdentifier = _core.types.identifier(exportName);
|
|
12
12
|
const buildAssign = exports.buildAssign = (0, _core.template)(`
|
|
13
13
|
OBJECT.NAME = VALUE;
|
|
14
14
|
`);
|
|
15
|
+
const buildRequire = exports.buildRequire = (0, _core.template)(`
|
|
16
|
+
sap.ui.require(SOURCES, function (PARAMS) {
|
|
17
|
+
BODY;
|
|
18
|
+
});
|
|
19
|
+
`);
|
|
15
20
|
const buildDefine = exports.buildDefine = (0, _core.template)(`
|
|
16
21
|
sap.ui.define(SOURCES, function (PARAMS) {
|
|
17
22
|
BODY;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babel-plugin-transform-modules-ui5",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.6.0",
|
|
4
4
|
"description": "An unofficial babel plugin for SAP UI5.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
"lint": "eslint src",
|
|
19
19
|
"lint:fix": "npm run lint -- --fix",
|
|
20
20
|
"lint:staged": "lint-staged",
|
|
21
|
-
"test": "jest __test__ --coverage=no",
|
|
21
|
+
"test": "FORCE_COLOR=0 jest __test__ --coverage=no",
|
|
22
22
|
"test:watch": "npm test -- --watch",
|
|
23
|
-
"test:update-snapshot": "jest --updateSnapshot",
|
|
23
|
+
"test:update-snapshot": "FORCE_COLOR=0 jest --updateSnapshot",
|
|
24
24
|
"prepare": "npm test && npm run build",
|
|
25
25
|
"format": "prettier --write 'src/**/*.js'"
|
|
26
26
|
},
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"prettier": "^3.1.0",
|
|
95
95
|
"rimraf": "^5.0.5"
|
|
96
96
|
},
|
|
97
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "8db5f32610df08996a49b97529c8a8f3fabcc59c"
|
|
98
98
|
}
|