@ui5/webcomponents-tools 2.17.0-rc.4 → 2.17.0-rc.5

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,22 @@
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
+ # [2.17.0-rc.5](https://github.com/UI5/webcomponents/compare/v2.17.0-rc.4...v2.17.0-rc.5) (2025-12-04)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **tools:** dependencies usage ([#12716](https://github.com/UI5/webcomponents/issues/12716)) ([89bb0dd](https://github.com/UI5/webcomponents/commit/89bb0dd62322598bd1ea7ce984eaf0618546a6f2))
12
+
13
+
14
+ ### Features
15
+
16
+ * **framework:** introduce loadBaseThemingCSSVariables configuration ([#12699](https://github.com/UI5/webcomponents/issues/12699)) ([f01b2eb](https://github.com/UI5/webcomponents/commit/f01b2eb6256f2032bd802d0a60c4625b0d1af5fe))
17
+
18
+
19
+
20
+
21
+
6
22
  # [2.17.0-rc.4](https://github.com/UI5/webcomponents/compare/v2.17.0-rc.3...v2.17.0-rc.4) (2025-11-27)
7
23
 
8
24
 
package/bin/ui5nps.js CHANGED
@@ -165,7 +165,12 @@ class Parser {
165
165
  return new Promise(async (resolve, reject) => {
166
166
  if (command.trim().startsWith("ui5nps-script")) {
167
167
  const argv = parseArgsStringToArgv(command);
168
- const importedContent = require(argv[1]);
168
+ if (!path.isAbsolute(argv[1])) {
169
+ throw new Error(`Script path must be absolute: ${argv[1]}`);
170
+ }
171
+
172
+ const importPath = argv[1];
173
+ const importedContent = require(importPath);
169
174
  let _ui5mainFn;
170
175
 
171
176
  if (importedContent.__esModule) {
@@ -174,6 +179,10 @@ class Parser {
174
179
  _ui5mainFn = importedContent._ui5mainFn;
175
180
  }
176
181
 
182
+ if (!_ui5mainFn) {
183
+ return reject(new Error(`No valid _ui5mainFn function exported from ${importPath} tried to be executed with ui5nps-script. Either provide a valid _ui5mainFn function or use another way to execute the script (via node).`));
184
+ }
185
+
177
186
  console.log(` | Executing command ${commandName} as module.`);
178
187
  const result = _ui5mainFn(argv);
179
188
 
@@ -66,15 +66,6 @@ const getScripts = (options) => {
66
66
  viteConfig = `-c "${require.resolve("@ui5/webcomponents-tools/components-package/vite.config.js")}"`;
67
67
  }
68
68
 
69
- let eslintConfig;
70
- if (fs.existsSync(".eslintrc.js") || fs.existsSync(".eslintrc.cjs")) {
71
- // preferred way of custom configuration in root project folder
72
- eslintConfig = "";
73
- } else {
74
- // no custom configuration - use default from tools project
75
- eslintConfig = `--config "${require.resolve("@ui5/webcomponents-tools/components-package/eslint.js")}"`;
76
- }
77
-
78
69
  const scripts = {
79
70
  __ui5envs: {
80
71
  UI5_CEM_MODE: options.dev,
@@ -86,8 +77,8 @@ const getScripts = (options) => {
86
77
  "generated": `ui5nps-script "${LIB}/rimraf/rimraf.js src/generated`,
87
78
  "dist": `ui5nps-script "${LIB}/rimraf/rimraf.js dist`,
88
79
  },
89
- lint: `eslint . ${eslintConfig}`,
90
- lintfix: `eslint . ${eslintConfig} --fix`,
80
+ lint: `ui5nps-script "${LIB}eslint/eslint.js"`,
81
+ lintfix: `ui5nps-script "${LIB}eslint/eslint.js" --fix`,
91
82
  generate: {
92
83
  default: `ui5nps prepare.all`,
93
84
  all: `ui5nps-p build.templates build.i18n prepare.styleRelated copyProps build.illustrations`, // concurently
@@ -101,7 +92,7 @@ const getScripts = (options) => {
101
92
  },
102
93
  build: {
103
94
  default: "ui5nps prepare lint build.bundle", // build.bundle2
104
- templates: options.legacy ? `mkdirp src/generated/templates && node "${LIB}hbs2ui5/index.js" -d src/ -o src/generated/templates` : "",
95
+ templates: options.legacy ? `mkdir -p src/generated/templates && node "${LIB}hbs2ui5/index.js" -d src/ -o src/generated/templates` : "",
105
96
  styles: {
106
97
  default: `ui5nps-p build.styles.themes build.styles.components`, // concurently
107
98
  themes: `ui5nps-script "${LIB}css-processors/css-processor-themes.mjs"`,
@@ -123,7 +114,7 @@ const getScripts = (options) => {
123
114
  default: "ui5nps build.jsImports.illustrationsLoaders",
124
115
  illustrationsLoaders: createIllustrationsLoadersScript,
125
116
  },
126
- bundle: `vite build ${viteConfig} --mode testing --base ${websiteBaseUrl}`,
117
+ bundle: `ui5nps-script "${LIB}vite-bundler/vite-bundler.mjs" ${viteConfig} --mode testing --base ${websiteBaseUrl}`,
127
118
  bundle2: ``,
128
119
  illustrations: createIllustrationsJSImportsScript,
129
120
  },
@@ -147,8 +138,8 @@ const getScripts = (options) => {
147
138
  themes: 'ui5nps build.styles.themesWithWatch',
148
139
  components: `ui5nps build.styles.componentsWithWatch`,
149
140
  },
150
- templates: options.legacy ? 'chokidar "src/**/*.hbs" -i "src/generated" -c "ui5nps build.templates"' : "",
151
- i18n: 'chokidar "src/i18n/messagebundle.properties" -c "ui5nps build.i18n.defaultsjs"'
141
+ templates: options.legacy ? `ui5nps-script "${LIB}chokidar/chokidar.js" "src/**/*.hbs" "ui5nps build.templates"` : "",
142
+ i18n: `ui5nps-script "${LIB}chokidar/chokidar.js" "src/i18n/messagebundle.properties" "ui5nps build.i18n.defaultsjs"`
152
143
  },
153
144
  start: "ui5nps prepare watch.devServer",
154
145
  test: `ui5nps-script "${LIB}/test-runner/test-runner.js"`,
@@ -0,0 +1,28 @@
1
+ const chokidar = require('chokidar');
2
+ const { exec } = require("child_process");
3
+
4
+ const main = async (argv) => {
5
+ if (argv.length < 4) {
6
+ console.error("Please provide a file pattern to watch and a command to execute on changes.");
7
+ console.error("<file-pattern> <command>");
8
+ process.exit(1);
9
+ }
10
+
11
+ const filePattern = argv[2];
12
+ const command = argv.slice(3).join(' ');
13
+
14
+ const watcher = new chokidar.FSWatcher();
15
+
16
+ watcher.add(filePattern);
17
+ watcher.unwatch("src/generated");
18
+
19
+ watcher.on('change', async () => {
20
+ exec(command);
21
+ });
22
+ };
23
+
24
+ if (require.main === module) {
25
+ main(process.argv)
26
+ }
27
+
28
+ exports._ui5mainFn = main;
@@ -9,24 +9,28 @@ import { writeFileIfChanged, getFileContent } from "./shared.mjs";
9
9
  import { scopeUi5Variables, scopeThemingVariables } from "./scope-variables.mjs";
10
10
  import { pathToFileURL } from "url";
11
11
 
12
- async function processThemingPackageFile(f) {
12
+ async function processThemingPackageFile(f, scope = true) {
13
13
  const selector = ':root';
14
14
  const newRule = postcss.rule({ selector });
15
15
  const result = await postcss().process(f.text);
16
16
 
17
17
  result.root.walkRules(selector, rule => {
18
18
  for (const decl of rule.nodes) {
19
- if (decl.type !== 'decl' ) {
19
+ if (decl.type !== 'decl') {
20
20
  continue;
21
21
  } else if (decl.prop.startsWith('--sapFontUrl')) {
22
22
  continue;
23
23
  } else if (!decl.prop.startsWith('--sap')) {
24
24
  newRule.append(decl.clone());
25
25
  } else {
26
- const originalProp = decl.prop;
27
- const originalValue = decl.value;
28
-
29
- newRule.append(decl.clone({ prop: originalProp.replace("--sap", "--ui5-sap"), value: `var(${originalProp}, ${originalValue})` }));
26
+ if (scope) {
27
+ const originalProp = decl.prop;
28
+ const originalValue = decl.value;
29
+
30
+ newRule.append(decl.clone({ prop: originalProp.replace("--sap", "--ui5-sap"), value: `var(${originalProp}, ${originalValue})` }));
31
+ } else {
32
+ newRule.append(decl.clone());
33
+ }
30
34
  }
31
35
  }
32
36
  });
@@ -43,6 +47,24 @@ async function processComponentPackageFile(f, packageJSON) {
43
47
 
44
48
  return result;
45
49
  }
50
+ async function writeProcessedContent(basePath, content, packageJSON, extension) {
51
+ const cssPath = basePath;
52
+ const jsonPath = basePath.replace(/dist[\/\\]css/, "dist/generated/assets").replace(".css", ".css.json");
53
+ const jsPath = basePath.replace(/dist[\/\\]css/, "src/generated/").replace(".css", extension);
54
+
55
+ // Write CSS file
56
+ await mkdir(path.dirname(cssPath), { recursive: true });
57
+ await writeFile(cssPath, content);
58
+
59
+ // Write JSON file
60
+ await mkdir(path.dirname(jsonPath), { recursive: true });
61
+ await writeFileIfChanged(jsonPath, JSON.stringify(content));
62
+
63
+ // Write JS/TS file
64
+ const jsContent = getFileContent(packageJSON.name, `\`${content}\``);
65
+ await mkdir(path.dirname(jsPath), { recursive: true });
66
+ await writeFileIfChanged(jsPath, jsContent);
67
+ }
46
68
 
47
69
  async function generate(argv) {
48
70
  const tsMode = process.env.UI5_TS === "true";
@@ -55,27 +77,27 @@ async function generate(argv) {
55
77
  ]);
56
78
  const restArgs = argv.slice(2);
57
79
 
58
- let scopingPlugin = {
80
+ const scopingPlugin = {
59
81
  name: 'scoping',
60
82
  setup(build) {
61
83
  build.initialOptions.write = false;
62
84
 
63
85
  build.onEnd(result => {
64
86
  result.outputFiles.forEach(async f => {
65
- let newText = f.path.includes("packages/theming") ? await processThemingPackageFile(f) : await processComponentPackageFile(f, packageJSON);
66
-
67
- await mkdir(path.dirname(f.path), { recursive: true });
68
- writeFile(f.path, newText);
69
-
70
- // JSON
71
- const jsonPath = f.path.replace(/dist[\/\\]css/, "dist/generated/assets").replace(".css", ".css.json");
72
- await mkdir(path.dirname(jsonPath), { recursive: true });
73
- writeFileIfChanged(jsonPath, JSON.stringify(newText));
74
-
75
- // JS/TS
76
- const jsPath = f.path.replace(/dist[\/\\]css/, "src/generated/").replace(".css", extension);
77
- const jsContent = getFileContent(packageJSON.name, "\`" + newText + "\`");
78
- writeFileIfChanged(jsPath, jsContent);
87
+ if (f.path.includes("packages/theming")) {
88
+ const scopedText = await processThemingPackageFile(f);
89
+ const originalText = await processThemingPackageFile(f, false);
90
+
91
+ // Write scoped version
92
+ await writeProcessedContent(f.path, scopedText, packageJSON, extension);
93
+
94
+ // Write raw version
95
+ const originalPath = f.path.replace(/parameters-bundle.css$/, "parameters-bundle-raw.css");
96
+ await writeProcessedContent(originalPath, originalText, packageJSON, extension);
97
+ } else {
98
+ const processedText = await processComponentPackageFile(f, packageJSON);
99
+ await writeProcessedContent(f.path, processedText, packageJSON, extension);
100
+ }
79
101
  });
80
102
  })
81
103
  },
@@ -0,0 +1,44 @@
1
+ const fs = require("fs");
2
+ const { ESLint: ESLint7 } = require("eslint"); // isolated v7
3
+ const path = require("path");
4
+
5
+ const main = async argv => {
6
+ let eslintConfig;
7
+ if (fs.existsSync(".eslintrc.js") || fs.existsSync(".eslintrc.cjs")) {
8
+ // preferred way of custom configuration in root project folder
9
+ eslintConfig = null;
10
+ } else {
11
+ // no custom configuration - use default from tools project
12
+ eslintConfig = require.resolve("@ui5/webcomponents-tools/components-package/eslint.js")
13
+ };
14
+
15
+ const packageDir = path.dirname(require.resolve("@ui5/webcomponents-tools/package.json"));
16
+ const eslint = new ESLint7({
17
+ overrideConfigFile: eslintConfig,
18
+ fix: argv.includes("--fix"),
19
+ resolvePluginsRelativeTo: packageDir,
20
+ });
21
+ console.log("Running ESLint v7...");
22
+
23
+ // Lint files
24
+ const results = await eslint.lintFiles(["."]);
25
+
26
+ // Format results
27
+ const formatter = await eslint.loadFormatter("stylish");
28
+ const resultText = formatter.format(results);
29
+
30
+ // Output results
31
+ console.log(resultText);
32
+
33
+ // Exit with error code if there are errors
34
+ const hasErrors = results.some(result => result.errorCount > 0);
35
+ if (hasErrors) {
36
+ process.exit(1);
37
+ }
38
+ }
39
+
40
+ if (require.main === module) {
41
+ main(process.argv)
42
+ }
43
+
44
+ exports._ui5mainFn = main;
@@ -7,9 +7,10 @@ const ext = isTypeScript ? 'ts' : 'js';
7
7
 
8
8
  const generate = async (argv) => {
9
9
  const inputFolder = path.normalize(argv[2]);
10
- const outputFileDynamic = path.normalize(`${argv[3]}/Themes.${ext}`);
11
- const outputFileDynamicImportJSONAttr = path.normalize(`${argv[3]}/Themes-node.${ext}`);
12
- const outputFileFetchMetaResolve = path.normalize(`${argv[3]}/Themes-fetch.${ext}`);
10
+ const outputSuffix = argv[4] || "";
11
+ const outputFileDynamic = path.normalize(`${argv[3]}/Themes${outputSuffix}.${ext}`);
12
+ const outputFileDynamicImportJSONAttr = path.normalize(`${argv[3]}/Themes${outputSuffix}-node.${ext}`);
13
+ const outputFileFetchMetaResolve = path.normalize(`${argv[3]}/Themes${outputSuffix}-fetch.${ext}`);
13
14
 
14
15
  // All supported optional themes
15
16
  const allThemes = assets.themes.all;
@@ -24,9 +25,9 @@ const generate = async (argv) => {
24
25
  const packageName = JSON.parse(await fs.readFile("package.json")).name;
25
26
 
26
27
  const availableThemesArray = `[${themesOnFileSystem.map(theme => `"${theme}"`).join(", ")}]`;
27
- const dynamicImportLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle.css.json")).default;`).join("\n");
28
- const dynamicImportJSONAttrLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle.css.json", {with: { type: 'json'}})).default;`).join("\n");
29
- const fetchMetaResolveLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await fetch(new URL("../assets/themes/${theme}/parameters-bundle.css.json", import.meta.url))).json();`).join("\n");
28
+ const dynamicImportLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle${outputSuffix}.css.json")).default;`).join("\n");
29
+ const dynamicImportJSONAttrLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import(/* webpackChunkName: "${packageName.replace("@", "").replace("/", "-")}-${theme.replace("_", "-")}-parameters-bundle" */"../assets/themes/${theme}/parameters-bundle${outputSuffix}.css.json", {with: { type: 'json'}})).default;`).join("\n");
30
+ const fetchMetaResolveLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await fetch(new URL("../assets/themes/${theme}/parameters-bundle${outputSuffix}.css.json", import.meta.url))).json();`).join("\n");
30
31
 
31
32
  // dynamic imports file content
32
33
  const contentDynamic = function (lines) {
@@ -49,7 +50,7 @@ const loadAndCheck = async (themeName) => {
49
50
  };
50
51
 
51
52
  ${availableThemesArray}
52
- .forEach(themeName => registerThemePropertiesLoader(${packageName.split("").map(c => `"${c}"`).join(" + ")}, themeName, loadAndCheck));
53
+ .forEach(themeName => registerThemePropertiesLoader(${`${packageName + outputSuffix}`.split("").map(c => `"${c}"`).join(" + ")}, themeName, loadAndCheck));
53
54
  `;
54
55
  }
55
56
 
@@ -3,7 +3,7 @@ const { readFileSync } = require("fs");
3
3
  const path = require("path");
4
4
  const fs = require("fs");
5
5
 
6
- function testFn() {
6
+ function testFn(outArgv) {
7
7
  // search for dev-server port
8
8
  // start in current folder
9
9
  // traversing upwards in case of mono repo tests and dev-server running in root folder of repository
@@ -48,15 +48,15 @@ function testFn() {
48
48
 
49
49
  // add single spec parameter if passed
50
50
  let spec = "";
51
- if (process.argv.length === 3) {
52
- const specFile = process.argv[2];
51
+ if (outArgv.length === 3) {
52
+ const specFile = outArgv[2];
53
53
  spec = `--spec ${specFile}`;
54
54
  }
55
55
 
56
56
  // more parameters - pass them to wdio
57
57
  let restParams = "";
58
- if (process.argv.length > 3) {
59
- restParams = process.argv.slice(2).join(" ");
58
+ if (outArgv.length > 3) {
59
+ restParams = outArgv.slice(2).join(" ");
60
60
  }
61
61
 
62
62
  let wdioConfig = "";
@@ -67,7 +67,7 @@ function testFn() {
67
67
  }
68
68
 
69
69
  // run wdio with calculated parameters
70
- const cmd = `yarn cross-env WDIO_LOG_LEVEL=error wdio ${wdioConfig} ${spec} ${baseUrl} ${restParams}`;
70
+ const cmd = `npx cross-env WDIO_LOG_LEVEL=error wdio ${wdioConfig} ${spec} ${baseUrl} ${restParams}`;
71
71
  console.log(`executing: ${cmd}`);
72
72
  child_process.execSync(cmd, {stdio: 'inherit'});
73
73
  }
@@ -0,0 +1,35 @@
1
+ import { build } from 'vite';
2
+ import yargs from 'yargs';
3
+ import { hideBin } from 'yargs/helpers';
4
+ import { pathToFileURL } from "url";
5
+
6
+ async function start(outArgv) {
7
+ const argv = yargs(hideBin(outArgv))
8
+ .alias("c", "config")
9
+ .alias("mode", "mode")
10
+ .alias("base", "base")
11
+ .argv;
12
+
13
+ try {
14
+ await build({
15
+ configFile: argv.config || undefined,
16
+ mode: argv.mode || undefined,
17
+ base: argv.base || undefined,
18
+ logLevel: 'info',
19
+ });
20
+ } catch (e) {
21
+ console.error(e)
22
+ process.exit(1);
23
+ }
24
+ };
25
+
26
+ const filePath = process.argv[1];
27
+ const fileUrl = pathToFileURL(filePath).href;
28
+
29
+ if (import.meta.url === fileUrl) {
30
+ start(process.argv)
31
+ }
32
+
33
+ export default {
34
+ _ui5mainFn: start
35
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/webcomponents-tools",
3
- "version": "2.17.0-rc.4",
3
+ "version": "2.17.0-rc.5",
4
4
  "description": "UI5 Web Components: webcomponents.tools",
5
5
  "author": "SAP SE (https://www.sap.com)",
6
6
  "license": "Apache-2.0",
@@ -34,7 +34,6 @@
34
34
  "chai": "^4.3.4",
35
35
  "child_process": "^1.0.2",
36
36
  "chokidar": "^3.6.0",
37
- "chokidar-cli": "^3.0.0",
38
37
  "command-line-args": "^5.1.1",
39
38
  "comment-parser": "^1.4.0",
40
39
  "cross-env": "^7.0.3",
@@ -54,7 +53,6 @@
54
53
  "ignore": "^7.0.5",
55
54
  "is-port-reachable": "^3.1.0",
56
55
  "json-beautify": "^1.1.1",
57
- "mkdirp": "^1.0.4",
58
56
  "postcss": "^8.4.5",
59
57
  "postcss-cli": "^9.1.0",
60
58
  "postcss-selector-parser": "^6.0.10",
@@ -84,5 +82,5 @@
84
82
  "esbuild": "^0.25.0",
85
83
  "yargs": "^17.5.1"
86
84
  },
87
- "gitHead": "b7e93525288be73f17828a4aec16465097c1550b"
85
+ "gitHead": "affb457b35f4a92b8d6632de0042c8a9da7c244e"
88
86
  }