@ui5/webcomponents-tools 2.17.0-rc.4 → 2.17.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,35 @@
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](https://github.com/UI5/webcomponents/compare/v2.17.0-rc.5...v2.17.0) (2025-12-05)
7
+
8
+
9
+ ### Reverts
10
+
11
+ * Revert "feat(framework): scope theming css variables with component packages (#12491)" (#12775) ([3385623](https://github.com/UI5/webcomponents/commit/33856235e357a3d4d0b9391eab2a83a5b3010556)), closes [#12491](https://github.com/UI5/webcomponents/issues/12491) [#12775](https://github.com/UI5/webcomponents/issues/12775)
12
+ * Revert "chore: scope theming variables used in illustrations (#12687)" (#12770) ([c9288ff](https://github.com/UI5/webcomponents/commit/c9288ff0f655fdd03262b71ac788e5688c904add)), closes [#12687](https://github.com/UI5/webcomponents/issues/12687) [#12770](https://github.com/UI5/webcomponents/issues/12770)
13
+ * Revert "feat(framework): introduce loadBaseThemingCSSVariables configuration (#12699)" (#12767) ([db375d3](https://github.com/UI5/webcomponents/commit/db375d30b9f4a7e07961fabbdcefdcdc78a93f46)), closes [#12699](https://github.com/UI5/webcomponents/issues/12699) [#12767](https://github.com/UI5/webcomponents/issues/12767)
14
+
15
+
16
+
17
+
18
+
19
+ # [2.17.0-rc.5](https://github.com/UI5/webcomponents/compare/v2.17.0-rc.4...v2.17.0-rc.5) (2025-12-04)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * **tools:** dependencies usage ([#12716](https://github.com/UI5/webcomponents/issues/12716)) ([89bb0dd](https://github.com/UI5/webcomponents/commit/89bb0dd62322598bd1ea7ce984eaf0618546a6f2))
25
+
26
+
27
+ ### Features
28
+
29
+ * **framework:** introduce loadBaseThemingCSSVariables configuration ([#12699](https://github.com/UI5/webcomponents/issues/12699)) ([f01b2eb](https://github.com/UI5/webcomponents/commit/f01b2eb6256f2032bd802d0a60c4625b0d1af5fe))
30
+
31
+
32
+
33
+
34
+
6
35
  # [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
36
 
8
37
 
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;
@@ -1,6 +1,5 @@
1
1
  const fs = require("fs").promises;
2
2
  const path = require("path");
3
- const { scopeThemingVariables } = require("../css-processors/scope-variables.mjs");
4
3
 
5
4
  const generate = async (argv) => {
6
5
  if (argv.length < 7) {
@@ -92,7 +91,7 @@ const generate = async (argv) => {
92
91
  console.log(`Generating illustrations from ${srcPath} to ${destPath}`)
93
92
 
94
93
  const svgImportTemplate = svgContent => {
95
- return `export default \`${scopeThemingVariables(svgContent)}\`;`
94
+ return `export default \`${svgContent}\`;`
96
95
  };
97
96
  const svgToJs = async fileName => {
98
97
  const svg = await fs.readFile(path.join(srcPath, fileName), { encoding: "utf-8" });
@@ -4,7 +4,7 @@ import * as fs from "fs";
4
4
  import * as path from "path";
5
5
  import { writeFile, mkdir } from "fs/promises";
6
6
  import chokidar from "chokidar";
7
- import {scopeUi5Variables} from "./scope-variables.mjs";
7
+ import scopeVariables from "./scope-variables.mjs";
8
8
  import { writeFileIfChanged, getFileContent } from "./shared.mjs";
9
9
  import { pathToFileURL } from "url";
10
10
 
@@ -24,7 +24,7 @@ const generate = async (argv) => {
24
24
  build.onEnd(result => {
25
25
  result.outputFiles.forEach(async f => {
26
26
  // scoping
27
- let newText = scopeUi5Variables(f.text, packageJSON);
27
+ let newText = scopeVariables(f.text, packageJSON);
28
28
  newText = newText.replaceAll(/\\/g, "\\\\"); // Escape backslashes as they might appear in css rules
29
29
  await mkdir(path.dirname(f.path), { recursive: true });
30
30
  writeFile(f.path, newText);
@@ -6,45 +6,10 @@ import { writeFile, mkdir } from "fs/promises";
6
6
  import postcss from "postcss";
7
7
  import combineDuplicatedSelectors from "../postcss-combine-duplicated-selectors/index.js"
8
8
  import { writeFileIfChanged, getFileContent } from "./shared.mjs";
9
- import { scopeUi5Variables, scopeThemingVariables } from "./scope-variables.mjs";
9
+ import scopeVariables from "./scope-variables.mjs";
10
10
  import { pathToFileURL } from "url";
11
11
 
12
- async function processThemingPackageFile(f) {
13
- const selector = ':root';
14
- const newRule = postcss.rule({ selector });
15
- const result = await postcss().process(f.text);
16
-
17
- result.root.walkRules(selector, rule => {
18
- for (const decl of rule.nodes) {
19
- if (decl.type !== 'decl' ) {
20
- continue;
21
- } else if (decl.prop.startsWith('--sapFontUrl')) {
22
- continue;
23
- } else if (!decl.prop.startsWith('--sap')) {
24
- newRule.append(decl.clone());
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})` }));
30
- }
31
- }
32
- });
33
-
34
- return newRule.toString();
35
- };
36
-
37
- async function processComponentPackageFile(f, packageJSON) {
38
- let result = await postcss(combineDuplicatedSelectors).process(f.text);
39
-
40
- result = scopeUi5Variables(result.css, packageJSON, f.path);
41
-
42
- result = scopeThemingVariables(result);
43
-
44
- return result;
45
- }
46
-
47
- async function generate(argv) {
12
+ const generate = async (argv) => {
48
13
  const tsMode = process.env.UI5_TS === "true";
49
14
  const extension = tsMode ? ".css.ts" : ".css.js";
50
15
 
@@ -55,6 +20,29 @@ async function generate(argv) {
55
20
  ]);
56
21
  const restArgs = argv.slice(2);
57
22
 
23
+ const processThemingPackageFile = async (f) => {
24
+ const selector = ':root';
25
+ const result = await postcss().process(f.text);
26
+
27
+ const newRule = postcss.rule({ selector });
28
+
29
+ result.root.walkRules(selector, rule => {
30
+ rule.walkDecls(decl => {
31
+ if (!decl.prop.startsWith('--sapFontUrl')) {
32
+ newRule.append(decl.clone());
33
+ }
34
+ });
35
+ });
36
+
37
+ return newRule.toString();
38
+ };
39
+
40
+ const processComponentPackageFile = async (f) => {
41
+ const result = await postcss(combineDuplicatedSelectors).process(f.text);
42
+
43
+ return scopeVariables(result.css, packageJSON, f.path);
44
+ }
45
+
58
46
  let scopingPlugin = {
59
47
  name: 'scoping',
60
48
  setup(build) {
@@ -62,7 +50,7 @@ async function generate(argv) {
62
50
 
63
51
  build.onEnd(result => {
64
52
  result.outputFiles.forEach(async f => {
65
- let newText = f.path.includes("packages/theming") ? await processThemingPackageFile(f) : await processComponentPackageFile(f, packageJSON);
53
+ let newText = f.path.includes("packages/theming") ? await processThemingPackageFile(f) : await processComponentPackageFile(f);
66
54
 
67
55
  await mkdir(path.dirname(f.path), { recursive: true });
68
56
  writeFile(f.path, newText);
@@ -111,8 +99,4 @@ if (import.meta.url === fileUrl) {
111
99
 
112
100
  export default {
113
101
  _ui5mainFn: generate
114
- }
115
-
116
- export {
117
- processComponentPackageFile
118
102
  }
@@ -9,9 +9,9 @@ const require = createRequire(import.meta.url);
9
9
  * @returns
10
10
  */
11
11
  const getOverrideVersion = filePath => {
12
- if (!filePath) {
13
- return;
14
- }
12
+ if (!filePath) {
13
+ return;
14
+ }
15
15
 
16
16
  if (!filePath.includes(`overrides${path.sep}`)) {
17
17
  return; // The "overrides/" directory is the marker
@@ -36,22 +36,14 @@ const getOverrideVersion = filePath => {
36
36
  return overrideVersion;
37
37
  }
38
38
 
39
- const scopeUi5Variables = (cssText, packageJSON, inputFile) => {
40
- const escapeVersion = version => "v" + version?.replaceAll(/[^0-9A-Za-z\-_]/g, "-");
41
- const versionStr = escapeVersion(getOverrideVersion(inputFile) || packageJSON.version);
42
- const expr = /(--_?ui5)([^\,\:\)\s]+)/g;
43
- let newText = cssText.replaceAll(expr, `$1-${versionStr}$2`);
39
+ const scopeVariables = (cssText, packageJSON, inputFile) => {
40
+ const escapeVersion = version => "v" + version?.replaceAll(/[^0-9A-Za-z\-_]/g, "-");
41
+ const versionStr = escapeVersion(getOverrideVersion(inputFile) || packageJSON.version);
44
42
 
45
- return newText.replaceAll("--sap", `--ui5-sap`);
46
- }
43
+ const expr = /(--_?ui5)([^\,\:\)\s]+)/g;
47
44
 
48
- // Used with CSS text and SVG file content (illustrations)
49
- const scopeThemingVariables = (cssText) => {
50
- return cssText.replaceAll("--sap", `--ui5-sap`);
45
+ return cssText.replaceAll(expr, `$1-${versionStr}$2`);
51
46
  }
52
47
 
53
- export {
54
- scopeUi5Variables,
55
- scopeThemingVariables,
56
- };
48
+ export default scopeVariables;
57
49
 
@@ -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;
@@ -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",
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": "13048269dab7b8ff92e9964e7ce4b771005cf07b"
88
86
  }