@ui5/builder
Advanced tools
Comparing version
@@ -5,4 +5,13 @@ # Changelog | ||
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v2.5.1...HEAD). | ||
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v2.6.0...HEAD). | ||
<a name="v2.6.0"></a> | ||
## [v2.6.0] - 2021-01-14 | ||
### Features | ||
- Add 'generateThemeDesignerResources' task [`03241c0`](https://github.com/SAP/ui5-builder/commit/03241c0e2599cb0928cbbf34ddc678634b2d5a93) | ||
- Add 'libraryLessGenerator' processor ([#560](https://github.com/SAP/ui5-builder/issues/560)) [`a7e1e5c`](https://github.com/SAP/ui5-builder/commit/a7e1e5c0c4b63d9bab3f6645deff8e0f4187d305) | ||
- **manifestBundler:** Add support for sap.app/i18n/enhanceWith ([#564](https://github.com/SAP/ui5-builder/issues/564)) [`1b7a277`](https://github.com/SAP/ui5-builder/commit/1b7a277aeeba9a43b647a46ae4487878ca2d6219) | ||
- **manifestCreator:** enrich manifest with supportedLocales in i18n (for libraries) ([#547](https://github.com/SAP/ui5-builder/issues/547)) [`8102034`](https://github.com/SAP/ui5-builder/commit/810203477647c52948eb357ce9679373d32dd9b1) | ||
<a name="v2.5.1"></a> | ||
@@ -492,2 +501,3 @@ ## [v2.5.1] - 2020-12-18 | ||
[v2.6.0]: https://github.com/SAP/ui5-builder/compare/v2.5.1...v2.6.0 | ||
[v2.5.1]: https://github.com/SAP/ui5-builder/compare/v2.5.0...v2.5.1 | ||
@@ -494,0 +504,0 @@ [v2.5.0]: https://github.com/SAP/ui5-builder/compare/v2.4.5...v2.5.0 |
@@ -49,2 +49,6 @@ /** | ||
/** | ||
* @type {import('./lib/processors/libraryLessGenerator')} | ||
*/ | ||
libraryLessGenerator: "./lib/processors/libraryLessGenerator", | ||
/** | ||
* @type {import('./lib/processors/resourceCopier')} | ||
@@ -101,2 +105,6 @@ */ | ||
/** | ||
* @type {import('./lib/tasks/generateThemeDesignerResources')} | ||
*/ | ||
generateThemeDesignerResources: "./lib/tasks/generateThemeDesignerResources", | ||
/** | ||
* @type {import('./lib/tasks/bundlers/generateBundle')} | ||
@@ -103,0 +111,0 @@ */ |
@@ -63,2 +63,3 @@ const {promisify} = require("util"); | ||
selectedTasks.generateApiIndex = false; | ||
selectedTasks.generateThemeDesignerResources = false; | ||
@@ -65,0 +66,0 @@ // Disable generateResourcesJson due to performance. |
@@ -1,2 +0,2 @@ | ||
const path = require("path"); | ||
const posixPath = require("path").posix; | ||
const yazl = require("yazl"); | ||
@@ -26,3 +26,3 @@ const resourceFactory = require("@ui5/fs").resourceFactory; | ||
add(directory, resource) { | ||
const normalizedDirectory = path.normalize(directory); | ||
const normalizedDirectory = posixPath.normalize(directory); | ||
if (!this.propertyFiles.has(normalizedDirectory)) { | ||
@@ -42,3 +42,3 @@ this.propertyFiles.set(normalizedDirectory, [resource]); | ||
get(directory) { | ||
return this.propertyFiles.get(path.normalize(directory)) || []; | ||
return this.propertyFiles.get(posixPath.normalize(directory)) || []; | ||
} | ||
@@ -62,16 +62,54 @@ } | ||
module.exports = ({resources, options: {namespace, bundleName, propertiesExtension, descriptor}}) => { | ||
function getDescriptorI18nInfo(manifest) { | ||
function bundleNameToUrl(bundleName, appId) { | ||
if (!bundleName.startsWith(appId)) { | ||
return null; | ||
} | ||
const relativeBundleName = bundleName.substring(appId.length + 1); | ||
return relativeBundleName.replace(/\./g, "/") + propertiesExtension; | ||
} | ||
function addDescriptorI18nInfos(descriptorI18nInfos, manifest) { | ||
function addI18nInfo(i18nPath) { | ||
if (i18nPath.startsWith("ui5:")) { | ||
log.warn(`Using the ui5:// protocol for i18n bundles is currently not supported ('${i18nPath}' in ${manifest.path})`); | ||
return; | ||
} | ||
descriptorI18nInfos.set( | ||
posixPath.join(posixPath.dirname(manifest.path), posixPath.dirname(i18nPath)), | ||
posixPath.basename(i18nPath, propertiesExtension) | ||
); | ||
} | ||
const content = JSON.parse(manifest.content); | ||
let i18nFullPath = content["sap.app"]["i18n"]; | ||
const appI18n = content["sap.app"]["i18n"]; | ||
let bundleUrl; | ||
// i18n section in sap.app can be either a string or an object with bundleUrl | ||
if (typeof i18nFullPath === "object") { | ||
i18nFullPath = i18nFullPath.bundleUrl; | ||
if (typeof appI18n === "object") { | ||
if (appI18n.bundleUrl) { | ||
bundleUrl = appI18n.bundleUrl; | ||
} else if (appI18n.bundleName) { | ||
bundleUrl = bundleNameToUrl(appI18n.bundleName, content["sap.app"]["id"]); | ||
} | ||
} else if (typeof appI18n === "string") { | ||
bundleUrl = appI18n; | ||
} else { | ||
bundleUrl = "i18n/i18n.properties"; | ||
} | ||
if (!i18nFullPath) { | ||
i18nFullPath = "i18n/i18n.properties"; | ||
if (bundleUrl) { | ||
addI18nInfo(bundleUrl); | ||
} | ||
return { | ||
path: path.join(path.dirname(manifest.path), path.dirname(i18nFullPath)), | ||
rootName: path.basename(i18nFullPath, propertiesExtension) | ||
}; | ||
if (typeof appI18n === "object" && Array.isArray(appI18n.enhanceWith)) { | ||
appI18n.enhanceWith.forEach((enhanceWithEntry) => { | ||
let bundleUrl; | ||
if (enhanceWithEntry.bundleUrl) { | ||
bundleUrl = enhanceWithEntry.bundleUrl; | ||
} else if (enhanceWithEntry.bundleName) { | ||
bundleUrl = bundleNameToUrl(enhanceWithEntry.bundleName, content["sap.app"]["id"]); | ||
} | ||
if (bundleUrl) { | ||
addI18nInfo(bundleUrl); | ||
} | ||
}); | ||
} | ||
} | ||
@@ -81,3 +119,3 @@ | ||
resource.getBuffer().then((content) => { | ||
const basename = path.basename(resource.getPath()); | ||
const basename = posixPath.basename(resource.getPath()); | ||
return { | ||
@@ -97,7 +135,6 @@ name: basename, | ||
if (resource.isManifest) { | ||
const descriptorI18nInfo = getDescriptorI18nInfo(resource); | ||
descriptorI18nInfos.set(descriptorI18nInfo.path, descriptorI18nInfo.rootName); | ||
addDescriptorI18nInfos(descriptorI18nInfos, resource); | ||
archiveContent.set(resource.path, resource.content); | ||
} else { | ||
const directory = path.dirname(resource.path); | ||
const directory = posixPath.dirname(resource.path); | ||
i18nResourceList.add(directory, resource); | ||
@@ -108,5 +145,10 @@ } | ||
descriptorI18nInfos.forEach((rootName, directory) => { | ||
i18nResourceList.get(directory) | ||
.filter((resource) => resource.name.startsWith(rootName)) | ||
.forEach((resource) => archiveContent.set(resource.path, resource.content)); | ||
const i18nResources = i18nResourceList.get(directory) | ||
.filter((resource) => resource.name.startsWith(rootName)); | ||
if (i18nResources.length) { | ||
i18nResources.forEach((resource) => archiveContent.set(resource.path, resource.content)); | ||
} else { | ||
log.warn(`Could not find any resources for i18n bundle '${directory}'`); | ||
} | ||
}); | ||
@@ -113,0 +155,0 @@ |
@@ -24,2 +24,3 @@ "use strict"; | ||
const APP_DESCRIPTOR_V10 = new Version("1.9.0"); | ||
const APP_DESCRIPTOR_V22 = new Version("1.21.0"); | ||
@@ -118,2 +119,3 @@ // namespaces used in .library files | ||
reject(err); | ||
return; | ||
} | ||
@@ -128,2 +130,7 @@ resolve(new Library(xml.library)); | ||
class LibraryBundle { | ||
/** | ||
* | ||
* @param {string} prefix | ||
* @param {module:@ui5/fs.Resource[]} resources | ||
*/ | ||
constructor(prefix, resources) { | ||
@@ -133,5 +140,17 @@ this.prefix = prefix; | ||
} | ||
/** | ||
* | ||
* @param {string} name | ||
* @returns {module:@ui5/fs.Resource} | ||
*/ | ||
findResource(name) { | ||
return this.resources.find((res) => res.getPath() === this.prefix + name); | ||
} | ||
/** | ||
* | ||
* @param {RegExp} pattern | ||
* @returns {module:@ui5/fs.Resource[]} | ||
*/ | ||
getResources(pattern) { | ||
@@ -151,2 +170,9 @@ return this.resources.filter((res) => pattern == null || pattern.test(res.getPath())); | ||
const libraryJSInfo = await analyzeLibraryJS(libBundle.findResource("library.js")); | ||
const includeSupportedLocalesInformation = descriptorVersion.compare(APP_DESCRIPTOR_V22) >= 0; | ||
/** | ||
* cache for supported locales | ||
* | ||
* @see createI18nSection | ||
*/ | ||
const i18nToSupportedLocales = new Map(); | ||
@@ -330,3 +356,8 @@ const manifestAppData = library.getAppData("manifest", XMLNS_MANIFEST); | ||
} | ||
const i18nText = getChildTextContent(manifestAppData, "i18n"); | ||
let i18n; | ||
if (typeof i18nText === "string") { | ||
i18n = createI18nSection(i18nText, i18nToSupportedLocales); | ||
log.verbose(`sap.app/i18n taken from .library appData: '%s'`, i18nText); | ||
} | ||
const sapApp = { | ||
@@ -337,3 +368,3 @@ _version: sectionVersion(APP_DESCRIPTOR_V3_SECTION_SAP_APP), | ||
embeds: await findEmbeddedComponents(), | ||
i18n: getChildTextContent(manifestAppData, "i18n"), | ||
i18n, | ||
applicationVersion: { | ||
@@ -466,11 +497,8 @@ version: isValid(library.getVersion()) ? library.getVersion() : getProjectVersion() | ||
function i18n() { | ||
const i18nElement = findChild(libraryAppData, "i18n"); | ||
if ( i18nElement ) { | ||
const i18n = i18nElement._; | ||
let i18n = getChildTextContent(libraryAppData, "i18n"); | ||
if ( typeof i18n === "string") { | ||
if ( i18n === "false" ) { | ||
return false; | ||
} else if ( i18n === "true" ) { | ||
return "messagebundle.properties"; | ||
} else { | ||
return i18n; | ||
i18n = "messagebundle.properties"; | ||
} | ||
@@ -481,7 +509,9 @@ // log.verbose(" sap.ui5/library/i18n property taken from .library appData: '%s'", library.i18n); | ||
// log.verbose(" sap.ui5/library/i18n property determined from resources: '%s'", library.i18n); | ||
return "messagebundle.properties"; | ||
i18n = "messagebundle.properties"; | ||
} else { | ||
// i18n not defined and no messagebundle.properties | ||
return false; | ||
} | ||
} | ||
return createI18nSection(i18n, i18nToSupportedLocales); | ||
} | ||
@@ -537,2 +567,60 @@ | ||
/** | ||
* Creates an i18n section: | ||
* - either using bundleUrl and supportedLocales | ||
* - or the i18n String | ||
* | ||
* @param {string} i18n bundle url, e.g. "messagebundle.properties" | ||
* @param {Map<string, Set<string>>} i18nToSupportedLocales cache to determine the supportedLocales only once | ||
* @returns {{bundleUrl: string, supportedLocales: string[]}|null|string} json structure with bundleUrl and | ||
* supportedLocales or the i18n String if not a ".properties" file. | ||
* <code>null</code> if given i18n String is <code>null</code> | ||
*/ | ||
function createI18nSection(i18n, i18nToSupportedLocales) { | ||
if (i18n === undefined) { | ||
return undefined; | ||
} | ||
if (!i18n.endsWith(".properties")) { | ||
return i18n; | ||
} | ||
// if the supported locales information should not be included use i18n text | ||
if (!includeSupportedLocalesInformation) { | ||
return i18n; | ||
} | ||
let supportedLocales = i18nToSupportedLocales.get(i18n); | ||
if (!supportedLocales) { | ||
supportedLocales = new Set(); | ||
if (libBundle.findResource(i18n) != null) { | ||
supportedLocales.add(""); | ||
} | ||
const i18nPathPrefix = i18n.substring(0, i18n.length - ".properties".length) + "_"; | ||
// e.g. i18n/i18n_ | ||
libBundle.getResources().forEach((resource) => { | ||
const resPath = resource.getPath(); | ||
// e.g. sap/ui/mine/i18n/i18n_en.properties | ||
const indexOfI18nPathPrefix = resPath.lastIndexOf(i18nPathPrefix); | ||
if (resPath.endsWith(".properties") && indexOfI18nPathPrefix >= 0) { | ||
const i18nPath = resPath.substring(indexOfI18nPathPrefix + i18nPathPrefix.length, | ||
resPath.length - ".properties".length); | ||
if (!i18nPath.includes(".")) { | ||
supportedLocales.add(i18nPath.replace(/_/g, "-")); | ||
} | ||
} | ||
}); | ||
i18nToSupportedLocales.set(i18n, supportedLocales); | ||
} | ||
const supportedLocalesArray = Array.from(supportedLocales); | ||
supportedLocalesArray.sort(); | ||
return { | ||
bundleUrl: i18n, | ||
supportedLocales: supportedLocalesArray | ||
}; | ||
} | ||
function createSapFiori() { | ||
@@ -626,3 +714,3 @@ // collect registrationIds if present | ||
options = Object.assign({ | ||
descriptorVersion: APP_DESCRIPTOR_V10, | ||
descriptorVersion: APP_DESCRIPTOR_V22, | ||
include3rdParty: true, | ||
@@ -629,0 +717,0 @@ prettyPrint: true |
@@ -18,2 +18,3 @@ const taskInfos = { | ||
generateResourcesJson: {path: "./generateResourcesJson"}, | ||
generateThemeDesignerResources: {path: "./generateThemeDesignerResources"}, | ||
generateStandaloneAppBundle: {path: "./bundlers/generateStandaloneAppBundle"}, | ||
@@ -20,0 +21,0 @@ generateBundle: {path: "./bundlers/generateBundle"}, |
@@ -167,2 +167,14 @@ const AbstractBuilder = require("../AbstractBuilder"); | ||
this.addTask("generateThemeDesignerResources", async () => { | ||
return getTask("generateThemeDesignerResources").task({ | ||
workspace: resourceCollections.workspace, | ||
dependencies: resourceCollections.dependencies, | ||
options: { | ||
projectName: project.metadata.name, | ||
version: project.version, | ||
namespace: project.metadata.namespace | ||
} | ||
}); | ||
}); | ||
this.addTask("createDebugFiles", async () => { | ||
@@ -169,0 +181,0 @@ return getTask("createDebugFiles").task({ |
@@ -39,2 +39,13 @@ const AbstractBuilder = require("../AbstractBuilder"); | ||
this.addTask("generateThemeDesignerResources", async () => { | ||
return getTask("generateThemeDesignerResources").task({ | ||
workspace: resourceCollections.workspace, | ||
dependencies: resourceCollections.dependencies, | ||
options: { | ||
projectName: project.metadata.name, | ||
version: project.version | ||
} | ||
}); | ||
}); | ||
this.addTask("generateResourcesJson", () => { | ||
@@ -41,0 +52,0 @@ return getTask("generateResourcesJson").task({ |
{ | ||
"name": "@ui5/builder", | ||
"version": "2.5.1", | ||
"version": "2.6.0", | ||
"description": "UI5 Tooling - Builder", | ||
@@ -115,3 +115,3 @@ "author": { | ||
"estraverse": "5.1.0", | ||
"globby": "^11.0.1", | ||
"globby": "^11.0.2", | ||
"graceful-fs": "^4.2.4", | ||
@@ -131,3 +131,3 @@ "jsdoc": "^3.6.6", | ||
"devDependencies": { | ||
"ava": "^3.14.0", | ||
"ava": "^3.15.0", | ||
"chai": "^4.1.2", | ||
@@ -139,5 +139,5 @@ "chai-fs": "^2.0.0", | ||
"docdash": "^1.2.0", | ||
"eslint": "^7.15.0", | ||
"eslint": "^7.17.0", | ||
"eslint-config-google": "^0.14.0", | ||
"eslint-plugin-jsdoc": "^30.7.8", | ||
"eslint-plugin-jsdoc": "^30.7.13", | ||
"extract-zip": "^2.0.1", | ||
@@ -148,3 +148,3 @@ "mock-require": "^3.0.3", | ||
"recursive-readdir": "^2.1.1", | ||
"sinon": "^9.2.2", | ||
"sinon": "^9.2.3", | ||
"tap-nyan": "^1.1.0", | ||
@@ -151,0 +151,0 @@ "tap-xunit": "^2.4.1" |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
766917
2.37%104
1.96%20041
2.28%7
16.67%Updated