diff --git a/packages/base/src/CustomElementsScopeUtils.ts b/packages/base/src/CustomElementsScopeUtils.ts index f000031f03ac..254fed3e1dae 100644 --- a/packages/base/src/CustomElementsScopeUtils.ts +++ b/packages/base/src/CustomElementsScopeUtils.ts @@ -118,10 +118,21 @@ const getEffectiveScopingSuffixForTag = (tag: string) => { /** * @public * Used for getting a scoped name for a CSS variable using the same transformation used in the build - * @name the name of the css variable as written in the code + * @param name the name of the css variable as written in the code + * @param withVersion whether to include the version in the scoped name * @returns a variable name with the current version inserted as available at runtime + * @deprecated As of version 2.19.0 this method is no longer required. Variables can now be defined at the component level + * and are automatically encapsulated within each component’s Shadow DOM. + * As a result, runtime scoping logic is no longer necessary. + * + * It is still needed for third-party packages that have not yet migrated to the + * component-level variable approach. */ -const getScopedVarName = (name: string) => { +const getScopedVarName = (name: string, withVersion: boolean = false) => { + if (!withVersion) { + return name; + } + const versionStr = `v${VersionInfo.version.replaceAll(".", "-")}`; const expr = /(--_?ui5)([^,:)\s]+)/g; return name.replaceAll(expr, `$1-${versionStr}$2`); diff --git a/packages/tools/lib/css-processors/css-processor-components.mjs b/packages/tools/lib/css-processors/css-processor-components.mjs index fa6b72a7e77a..5adb8c43fef7 100644 --- a/packages/tools/lib/css-processors/css-processor-components.mjs +++ b/packages/tools/lib/css-processors/css-processor-components.mjs @@ -14,7 +14,9 @@ const generate = async (argv) => { const tsMode = process.env.UI5_TS === "true"; const extension = tsMode ? ".css.ts" : ".css.js"; - const packageJSON = JSON.parse(fs.readFileSync("./package.json")) + const packageJSON = JSON.parse(fs.readFileSync("./package.json")); + const basePackageJSON = (await import("@ui5/webcomponents-base/package.json", { with: { type: "json" } })).default; + const inputFilesGlob = "src/themes/*.css"; const restArgs = argv.slice(2); @@ -31,7 +33,7 @@ const generate = async (argv) => { newText = f.text; } else { // scoping - newText = scopeVariables(f.text, packageJSON); + newText = scopeVariables(f.text, basePackageJSON); } newText = newText.replaceAll(/\\/g, "\\\\"); // Escape backslashes as they might appear in css rules diff --git a/packages/tools/lib/css-processors/css-processor-themes.mjs b/packages/tools/lib/css-processors/css-processor-themes.mjs index 5e7de4947584..60f508fe5836 100644 --- a/packages/tools/lib/css-processors/css-processor-themes.mjs +++ b/packages/tools/lib/css-processors/css-processor-themes.mjs @@ -15,7 +15,8 @@ const generate = async (argv) => { const tsMode = process.env.UI5_TS === "true"; const extension = tsMode ? ".css.ts" : ".css.js"; - const packageJSON = JSON.parse(fs.readFileSync("./package.json")) + const packageJSON = JSON.parse(fs.readFileSync("./package.json")); + const basePackageJSON = (await import("@ui5/webcomponents-base/package.json", { with: { type: "json" } })).default; const inputFiles = await globby([ "src/**/parameters-bundle.css", @@ -69,7 +70,7 @@ const generate = async (argv) => { combineDuplicatedSelectors, ]).process(f.text, { from: undefined }); - return { css: scopeVariables(combined.css, packageJSON, f.path) }; + return { css: scopeVariables(combined.css, basePackageJSON, f.path) }; } let scopingPlugin = { diff --git a/packages/tools/lib/css-processors/scope-variables.mjs b/packages/tools/lib/css-processors/scope-variables.mjs index 02b07a2489eb..ddbcdcb82250 100644 --- a/packages/tools/lib/css-processors/scope-variables.mjs +++ b/packages/tools/lib/css-processors/scope-variables.mjs @@ -38,6 +38,29 @@ const getOverrideVersion = filePath => { return overrideVersion; } +/** + * `packageJSON` should reference the `package.json` of the base package, + * as it serves as the starting point for every runtime and carries a unique version. + * The `getScopedVarName` function is also defined in the base package + * and is consumed by all other packages. + * + * Runtime (2.19.0) + * - base (2.19.0) + * - At least one of the following packages: ai / main / fiori / compat (2.19.0) + * - Custom package (x.x.x) + * + * It is not possible to have a runtime with the main package at version 2.19.0 + * and the base package at a different version (e.g., 2.18.0), + * because the main package depends on the base package. + * Such a mismatch would create a new runtime. + * + * Therefore, we can safely assume that the base package version + * matches the runtime version and can be reliably used for scoping. + * + * It is still needed for third-party packages that have not yet migrated to the + * component-level variable approach. + */ + const scopeVariables = (cssText, packageJSON, inputFile) => { const escapeVersion = version => "v" + version?.replaceAll(/[^0-9A-Za-z\-_]/g, "-"); const versionStr = escapeVersion(getOverrideVersion(inputFile) || packageJSON.version);